Event logging with RTKLIB and the u-blox M8T receiver

Event logging is a nice feature that has been available in the Emlid version of RTKLIB for a long time.  In the latest version of the demo5 code (b29e), I have ported this feature from their open-source code repository.  Their version is specifically for the u-blox M8T receiver but I have extended it to support the Swiftnav receiver as well.  I mentioned this feature in my previous post and had a couple requests for more information, hence this post.

Both the u-blox and Swiftnav receivers have hardware/firmware to capture the precise time an external pin changes state and send out a binary message with this information.  The RTKLIB event logging code decodes these messages and logs the events to the rinex file.  The events in the rinex file are then used in post-processing to generate a position log containing an interpolated position for each timing event. The most popular use for this feature is probably to record camera shutter times but it can also be used for other purposes such as marking survey locations in the data stream.

Here is an example of a drone flight from a data set containing events that I downloaded from the Emlid forum.  On the left is the ground track of the standard position solution plotted with RTKPLOT.  It includes one point for every rover observation epoch.  On the right is a plot of the event positions from the new event position file.  In this case there is one point for every event which gives precise locations for each camera image.  This is very useful information when processing the images.


Here are the positions of the two plotted on top of each other, green dots are the rover observation epochs from the position file and the blue dots are the events from the event position file.  As you can see from the plot, the event positions are interpolated from the observation epochs.



There is information in the Emlid and Swiftnav documentation on how to connect an external trigger to their hardware so I won’t cover that here.

Instead, I will go through an example using an M8T receiver from CSGShop.  I will also use this example to try and validate this feature since there has been some discussion on the Emlid forum about potential issues that as far as I can tell have not been completely resolved on the forum.

The CSGShop M8T receiver comes in several variations.  To use event logging you will need to choose a board that provides access to the external interrupt pins.  You can use either EXINT0 or EXINT1.  For this experiment I also use the TIMEPULSE pin to provide triggers for the event logging.  Here is an image of the receiver and the interface pins.


The goal of this experiment is to generate events for which I know their precise timing so I can use them to validate the RTKLIB event logging results.  To do this, I configured the M8T TIMEPULSE output for a period of two seconds and a falling edge that occurs at 0.2 seconds, all in GPST time.  I then connected the TIMEPULSE output pin to the EXTINT1 input pin so that each state change of the output pulse will be recorded as an event.  Although the M8T will record both rising edges and falling edges, RTKLIB is setup to record only the falling edges.

To configure the timing pulse, I used the u-blox u-center app to setup the UBX-CFG-TP5 command as shown below.


I then enabled the UBX-TIM-TM2 messages which the receiver uses to output the event information.  Next, I opened the table view in u-center and configured it to log GPS time, and the rise and fall times for EXTINT1.  This information is extracted from GPRMC and TIM-TM2 messages.  As you can see the falling edges of the pulse are occurring at exactly 0.2 seconds on the even seconds in GPS time so it looks like we have correctly configured the output pulse


Now that I have external events occurring at precisely known times, I can use these to test the RTKLIB code.   The u-blox example command files that I include with the demo5 executables already are setup to enable the UBX-TIM-TM2 messages, so there is no need to make any changes there.

The next step is to collect some base and rover data using the modified receiver as rover.  I did that, and then converted the raw .ubx files to rinex using the new demo5 version of RTKCONV.  The events appear with a time stamp followed by a 5 in the next field to indicate an external event as shown below.  The zero in the last field indicates it is a valid time mark.


The observation epochs are occurring every second, so notice that the event is being logged out of sequence with a one sample delay.  I did not see this with the Emlid data set example described above.  However, I do see the same delay  if I use the Emlid code to convert the binary file instead of my code.  I don’t know if the Emlid hardware has somehow been configured to avoid this sequencing issue or whether it can occur on the Emlid hardware as well.  I’ll get back to this in a minute.

Next I ran RTKPOST to calculate a position solution.  With the new code changes, a *.events.pos file is generated in addition to the *.pos file.  It is the same format as the *.pos file but contains the event positions instead of the observation epoch positions.  Note, that it will be generated for absolute solutions (XYZ,LLH) LLH but not for relative (ENU) solutions.

I first did this with the Emlid code and got the following result when plotting both the position file and event position file.


The events are occurring at the correct times, but note that unlike the previous example, the positions are not being correctly interpolated between the two closest observation epochs.  In fact, if you look carefully you will see they are being extrapolated from the two previous observation epochs.  This is most obvious in the N-S axis points and is occurring because the events are being logged out of sequence.

To fix this, I modified the interpolation code to use the nearest observation epochs even when the event logging was delayed by one sample.  Here is the result using the latest demo5 b30 code.


Looking at the time stamps from the position log and the event position log, shown below, you can see that the observation epochs are occurring on the integer seconds and the events are occurring 0.2 seconds later on the even seconds, all in GPST time, just as we set them up to occur and verified with u-center.


So I don’t fully understand why the time stamps are appearing out of sequence with the CSGShop M8T data and not in the Emlid M8T data.  It may be that Emlid has configured the hardware somehow so this can not happen.  If this is true, then there should be no issue using the Emlid RTKLIB code with Emlid data but be careful using it with data from other hardware.  If anybody has any additional insight into this discrepancy please leave a comment.

I should also mention that all these code changes are in the core code so are present in both the command line apps as well as the GUI apps.  The most recent demo5 executables (b29e) do not contain the fix for interpolating delayed events and will function the same as the Emlid code.  The Github respository does have this fix.  The fix will also be in the demo5 b30 executables which I hope to release soon.


15 thoughts on “Event logging with RTKLIB and the u-blox M8T receiver”

  1. Hello!

    Any chance of getting the data you used for these tests?
    I can’t find it on the Emlid forum, and I really want to try this out.

    Also, thanks for working on RTKLIB, it is really useful! 🙂


  2. Thank you Paul
    I mean can I use time-based integration
    So.. we need a preview time Mark event logger
    And Camera time that already setup same as GPS time


    1. Hi Catur,
      If you want to manually tag locations, you can do this by connecting a normally open switch between EXTINT0 and GND. EXTINT0 has an internal pull-up resistor. Whenever you push the switch, a TIM-TM2 message will be logged in the data (provided you have enabled TIM-TM2 messages first). It will log both the falling edge (when you push the switch) and the rising edge (when you release the switch). Tim’s code will extract the time of the rising edge.
      This will work with my RAWX_Logger code for the Adalogger too as the code enables TIM-TM2 messages.
      You might want to connect a small capacitor across the switch contacts to help de-bounce the signal. 10nF should be perfect.
      Best wishes,


      1. Dear Paul
        Please more detail about implementing the event mark or push on switch with your RAWX_logger Code
        I mean should we add some line in your coding?


        1. Hi Catur,
          Please try connecting a push switch between EXTINT0 and GND on the CSG Shop board, collect some data while occasionally pressing the switch, and then use RTKLIB to analyse the results. You do not need to add anything to the RAWX_Logger code, the TIM-TM2 messages are already enabled.
          (You will learn much more if you try things for yourself before you ask for help.)
          Best wishes,


  3. Hi Tim,
    In the M8 protocol specification it mentions that the delay figures given in CFG-TP5 are applied to the time results for TIM-TM2. Perhaps the delay values are different for the Emild configuration vs CSGShop?
    Best wishes,


  4. Hi, I appreciate your great efforts and smart observations. I like your work.
    I played with demo code 5 b29e and I have a few observations.
    When processed with demoCode,some of the events are missing in the event.pos file.
    Emlid RTK lib also has this problem of missing events, but more number of missing events with democode.

    One more observation of missing events in EmlidRTKlib is , events are missed when time gap between event and observation data is less then 5ms, I guess its some time resolution error.


    1. Hi Flint. Events are limited by the M8T hardware (and RTKLIB code) to one event per observation epoch. If you are sampling at 5 Hz, then the time gap between events should be at least 200 ms. This should be the same for the Emlid code and the demo5 code. If you are seeing differences between the two codes, I would be interested in seeing an example if you don’t mind emailing the data to me.


      1. Hi Flint. Your rinex file was from a ComNav receiver and included a set of event observations for each event. RTKLIB is not setup to handle these. I modified the code to discard these extra event observations and interpolate as is done for the events in the RTKLIB generated rinex files. I’ve checked the modified code into the demo5 repository. It will not discard the extra observations if they are within the timing tolerance (DTTOL) of RTKLIB, so for best results, set DTTOL to a very low value (e.g. 0.001). This is defined in rtklib.h and you will need to rebuild the code after modifying this.


          1. Hi Flint. The ideal solution would be to use the event observations to generate the event position instead of interpolating from the adjacent epochs but RTKLIB is expecting evenly spaced samples and is not set up to handle the intra-epoch observations. Discarding the event observations is the best I could do with a simple solution.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.