Ground Speed and Course from GPS

Looking through the GPS example and ublox.cpp file, I don’t see any options to output ground speed and course direction. Is there an easy way to obtain these from the GPS or will they have to be determined manually?

@larssoltmann It can be obtained from NAV-VELNED message of UBX protocol, to decode it add new message to the parser.

Thanks Igor, I was able to get the NAV-VELNED message added and working. Now that it’s functioning, I would like to increase the update rate of the GPS. I see that it’s currently set at 1Hz, but would like to change it to 4Hz. Looking at the data sheet its not obvious which register controls the update rate. There are ‘update rate’ parameters in the CFG-RATE, CFG-PM2, and CFG-TP. Any idea which one of these I would use to set the update rate?


You can now change update rate by sending CFG-RATE message. I suggest that you code it same way as Ublox::enableNAV_POSLLH() and other configurational methods.

Seem to be having a bit of trouble changing the rate. Based on the description of the CFG-RATE settings I am sending this

unsigned char gps_rate[] = {0xb5, 0x62, 0x06, 0x08, 0x06, 0x00, 0x0A, 0x0F, 0x01, 0x00, 0x01, 0x00, 0x2F, 0x41};

0xb5 0x62 are the standard headers
0x06 0x08 are the ID’s
0x06 0x00 is the size of the payload (6 bytes)
0x0A 0x0F is the measurement rate (250ms, 4Hz)
0x01 0x00 is the navigation rate in cycles (which can not be changed from 1 so I’m assuming it doesn’t really matter what value I send it for this parameter)
0x01 0x00 is the time reference set to use GPS time (same as default)
0x2F 0x41 are the checksum A and B (when I calculated it out by hand I got 47 for A and 321 for B and had to mask B with 0xFF and to 0x41)

I can’t see what about this message is wrong, but the messages in the gps example still update at 1Hz. I did notice that when the enableNAV_POSLLH() and enableNAV_STATUS() messages are sent the byte associated with the message rate (CFG-MSG) is set to 0x01. Does this mean the message rate is set to 1Hz? Would I have to change this to match the 4Hz update rate I set in CFG-RATE?

1 Like

Just realized that I entered the update rate value incorrectly. For some reason I decided to breakup 250 into two bytes. I made the change and recalculated the checksum but am still getting a 1Hz update.

unsigned char gps_rate[] = {0xb5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xFA, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x96};

… and also forgot to enable the message. GPS now updates at 4Hz.

What did you actually do to update to 4 hz? Would love to find out as well

Scott, here is the function I used to set the GPS update rate to 4Hz.

int Ublox::setRATE()
    unsigned char gps_rate[] = {0xb5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xFA, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x96}; //4Hz
  //unsigned char gps_rate[] = {0xb5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xC8, 0x00, 0x01, 0x00, 0x01, 0x00, 0xDE, 0x6A}; //5Hz
    int gps_rate_length = (sizeof(gps_rate)/sizeof(*gps_rate));
    unsigned char from_gps_data_nav[gps_rate_length];

    return SPIdev::transfer(spi_device_name.c_str(), gps_rate, from_gps_data_nav, gps_rate_length, 5000000);

Just call this function during the GPS initialization.

1 Like

Hi, can you share the HEX code that you used to enable VELNED using the c++ code provided by Emlid? i am having problems enabling it. Thanks

It’s been a while since this code has been tested, but here is what I last used.

int Ublox::enableNAV_VELNED()
    unsigned char gps_nav_velned[] = {0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0x01, 0x12, 0x01, 0x1E, 0x67};
    int gps_nav_velned_length = (sizeof(gps_nav_velned)/sizeof(*gps_nav_velned));
    unsigned char from_gps_data_nav[gps_nav_velned_length];

    return SPIdev::transfer(spi_device_name.c_str(), gps_nav_velned, from_gps_data_nav, gps_nav_velned_length, 5000000);

Thank you. Unfortunately it doesn’t seem to work for me.

Hi can I ask you 2 questions:

  1. are you using 0x010C as id for NAV_VELNED ?
  2. Do you know why the HEX code from U-centre is different from the one used in your example, for the same messages? It is longer. The same think happens also with the NAV_POSLLH and NAV_STATUS messages provided by Emlid.

Thank you!

  1. Looks like I’m using ID “0x01 0x12”. Here is an excerpt from the M8 receiver description manual that I was using at the time. I did a quick check of the latest protocol description manual and it appears the message ID and format are still the same.

  1. I haven’t used u-center in probably 7 years so that one I can’t answer.

Thank you for your answer. In the method decode_single_message what id are you using for NAV_VELNED? for example for NAV_POSLLH is 0x0102 (because that message has id 2). NAV_VELNED has id 12 and for this reason i am using 0x010C inside decode_single_message() in order to decode that message.
My problem is related with the messages decoding. It seems that the method to enable that message is ok, but when i’m trying to decode the messages i’m receiving empty vectors.

The ID I’m using is 0x12. The receiver specifications guide lists all position, time, speed, etc messages as belonging to the class 0x01 and the VELNED message has the ID 0x12 within that class. So if I receive a message with 0x01 as the third byte and 0x12 as the fourth byte, then it must be a VELNED message.

int Ublox::decodeMessage(unsigned char data_array[100]){
	switch(data_array[3]) {
                case 0x12:
                        gps_N=(float)(((data_array[13]) << 24) | ((data_array[12]) << 16) | ((data_array[11]) << 8) | (data_array[10]))*0.0328084;  // cm/s to ft/s
                        gps_E=(float)(((data_array[17]) << 24) | ((data_array[16]) << 16) | ((data_array[15]) << 8) | (data_array[14]))*0.0328084;  // cm/s to ft/s
                        gps_D=(float)(((data_array[21]) << 24) | ((data_array[20]) << 16) | ((data_array[19]) << 8) | (data_array[18]))*0.0328084;  // cm/s to ft/s
                        gps_3D=(float)(((data_array[25]) << 24) | ((data_array[24]) << 16) | ((data_array[23]) << 8) | (data_array[22]))*0.0328084;  // cm/s to ft/s
                        gps_2D=(float)(((data_array[29]) << 24) | ((data_array[28]) << 16) | ((data_array[27]) << 8) | (data_array[26]))*0.0328084;  // cm/s to ft/s
                        gps_crs=(float)(((data_array[33]) << 24) | ((data_array[32]) << 16) | ((data_array[31]) << 8) | (data_array[30]))/ (float)100000;  //deg

Thank you for your help. I’ve change the code to parse only the id like your last example and now it works!
The receiving failure was related to the fact that i’m using ROS and the gps can’t keep up with the frequency. I need to understand how to enable only GPS and not other types like GLONASS, in order to increase the measurement rate.