Aye aye mate, I've got the answer.
In your data, TrialStartTimestamp is the instant the first state of your trial begins, on the state machine clock.
The launch manager resets the state machine clock to 0 just before running the protocol (BpodSystem.resetSessionClock(), on line 713 of NewLaunchManager.m). Next, the launch manager runs your protocol .m file, which takes some time to run setup before the first call to RunStateMachine (or TrialManager.startTrial if using TrialManager) - so after the clock reset, a variable amount of time passes before the first state begins.
If you want a MATLAB timestamp as close as possible to state machine time 0, you can reset the clock again in your protocol just before your main loop with:
matlabStartTime = now;
BpodSystem.SerialPort.write('*', 'uint8'); % Reset bpod session clock
Confirmed = obj.SerialPort.read(1,'uint8');
if Confirmed ~= 1
error('Error: confirm not returned after resetting session clock.')
end
Unfortunately, since Windows, OSX and Ubuntu are non-Realtime operating systems, the actual time the '*' command gets written to Bpod via USB will vary, and on a busy PC latency can be 10s of milliseconds. The best policy is to synchronize clocks of separate acquisition systems using TTL pulses.
If you need to use MATLAB's clocks for timing, I'd also look into use of now() vs. PsychToolbox GetSecs: http://psychtoolbox.org/docs/GetSecs.
I hope this helps!
-Josh