---
# System prepended metadata

title: Ublox f9k IMU topic Issue
tags: [Ublox F9K Related]

---

contributed by <`cwcoscar`> From NCKU MECLAB
Date : 2023/04/12

[Reference code](https://github.com/ethanec/ublox)

## topic: esfmeas
- The following picture shows the message on `/ublox_f9k/esfmeas`
- The most important thing is to decode **data[]**

![](https://i.imgur.com/0oAyTlu.png)
- The following pisture is from EsfMEAS.msg
- It describes what information is in the data
- `DATA_FIELD_MASK = 16777215` in binary is `111111111111111111111111` (24digits). 
- Ones represent the bits which are measurement.
- `DATA_TYPE_MASK = 1056964608` in binary is `111111000000000000000000000000` (30 digits).
- Ones represent the bits which are data type.
- the number from these bits can refer to one type according to the description in the picture.

![](https://i.imgur.com/3FhtKOi.png)

- For example: `234881757` in binary is `001110000000000000001011011101` (30 digits)
- last 6 bits is `001110`, in decimal is `14`.
- It refer to `DATA_TYPE_GYRO_ANG_RATE_X = 14`
- first 24 bits is `0000000000000001011011101`, in decimal is `+733 [deg/s *2^-12 signed]`, which means `733/4096 [deg/s]`
- If the sign bit is `0`, it's positive and vise versa.
- The 24th bit is the sign bit.

### Frequency
- From the picture of `/ublox_f9k/esfmeas`, it shows the update time interval of accelerometer and gyroscope are both 0.05 second.
- Time tag is `[sec *10^-3]`

## Topic: imu_meas
- The following code is from node.cpp at line 1386.
- The origin version will publish the message at very high rate and it's because the publish function is write in the for loop.
- After moving it outside the publish function, the message is published at approximately 100 Hz.
- Only gyro and acc data are published seperately.
- The time interval of one kind is about 0.02 sec.
- The time interval of two kind is very small.
```cpp=0
void AdrUdrProduct::callbackEsfMEAS(const ublox_msgs::EsfMEAS &m) {
  if (enabled["esf_meas"]) {
    static ros::Publisher imu_pub = 
	nh->advertise<sensor_msgs::Imu>("imu_meas", kROSQueueSize);
    static ros::Publisher time_ref_pub =
	nh->advertise<sensor_msgs::TimeReference>("interrupt_time", kROSQueueSize);
    
    imu_.header.stamp = ros::Time::now();
    imu_.header.frame_id = frame_id;
    
    static const float rad_per_sec = pow(2, -12) * M_PI / 180.0F;
    static const float m_per_sec_sq = pow(2, -10);
    static const float deg_c = 1e-2;
     
    std::vector<uint32_t> imu_data = m.data;
    for (int i=0; i < imu_data.size(); i++){
      unsigned int data_type = imu_data[i] >> 24; //grab the last six bits of data
      int32_t data_value = static_cast<int32_t>(imu_data[i] << 8); //shift to extend sign from 24 to 32 bit integer
      data_value >>= 8;

      imu_.orientation_covariance[0] = -1;
      imu_.linear_acceleration_covariance[0] = -1;
      imu_.angular_velocity_covariance[0] = -1;

      if (data_type == 14) {
          imu_.angular_velocity.x = data_value * rad_per_sec;
      } else if (data_type == 16) {
          imu_.linear_acceleration.x = data_value * m_per_sec_sq;
      } else if (data_type == 13) {
          imu_.angular_velocity.y = data_value * rad_per_sec;
      } else if (data_type == 17) {
          imu_.linear_acceleration.y = data_value * m_per_sec_sq;
      } else if (data_type == 5) {
          imu_.angular_velocity.z = data_value * rad_per_sec;
      } else if (data_type == 18) {
          imu_.linear_acceleration.z = data_value * m_per_sec_sq;
      } else if (data_type == 12) {
        //ROS_INFO("Temperature in celsius: %f", data_value * deg_c); 
      } else {
        // ROS_INFO("data_type: %u", data_type);
        // ROS_INFO("data_value: %u", data_value);
      }

      t_ref_.header.stamp = ros::Time::now(); // create a new timestamp
      t_ref_.header.frame_id = frame_id;
   
      time_ref_pub.publish(t_ref_);
      // cwc
      // imu_pub.publish(imu_);
    }
    // cwc
    /* 
    If publish function is in the for loop, there will be several message at the same time stamp with several idenical data
    After observing the "data[]" in this topic, there are 3 condition.
    1st: one data in the array, and it's wheel tick
    2nd: three data in the array, they are gyro data (time intervel is 0.05 sec)
    3rd: four data in the array, they are acc data and temperature data (time intervel is 0.05 sec)
    Only 2nd and 3rd message are what we are concerned.
    Thus only if the array length is over 1, the message will be published.
    The publishing rate of this topic will be approximately at 100 Hz.
    */
    if (imu_data.size() > 1){
      imu_pub.publish(imu_);
    }
    // cwc
  }
  
  updater->force_update();
}
```