LORD-MicroStrain / microstrain_inertial

ROS driver for all of MicroStrain's current G and C series products. To learn more visit
https://www.microstrain.com/inertial
97 stars 72 forks source link

Raspberry Pi 4 Integration #28

Closed kbhakt closed 3 years ago

kbhakt commented 3 years ago

Hello,

I have some questions in regards to how to best integrate this IMU with a Raspberry Pi 4:

Q1: With the ROS library, I see there is a topic for reading the raw data using the ros_mscl library called /gx5/imu/data. Is there one for getting the euler angles after the kalman filter has been applied?

Q2: If I want to use 2 sensors on the raspberry pi, what is the best way to read from both sensors from one script -- can you give some guidance on how to achieve this?

Q3: I am planning on trying to read the sensor outputs at 250 Hz -- should I use the C++ version or the python version? What is easier to have multiple sensors as in Question 2?

Q4: I see there are many different files under the /src/ folder -- is there documentation to understand what each of those files do and are used for?

Please let me know if I need to elaborate more on any of these questions.

nathanmillermicrostrain commented 3 years ago

Hi kbhakt,

Hopefully this is helpful:

Q1) The orientation is found in the standard /gx5/nav/odom message. Note: it is a quaternion and will need to be converted to Euler angles, if that is what you require.

Q2) Assuming you are using the ros driver, you would have separate launch files with something like "gx5" and "gx5_2" for the argument listed as

Q3) Are you using the ros driver? If so, you would subscribe to the correct topic.

Q4) The driver is provided as-is and does not contain any additional documentation. You can find data communications protocols for all our devices at www.microstrain.com

kbhakt commented 3 years ago

Thank you for the quick response.

Q1) Great! How/What steps do I need to do to convert them to Euler angles?

Q2) Great!

Q3) I notice that there is two examples, one for C++ and one for Python. Are both scripts equivalent in terms of reading sensors? i.e is the C++ version preferred since inherently the coding language is better suited for real-time applications?

Q4) Ok!

nathanmillermicrostrain commented 3 years ago

Q1) To convert to Euler angles from a quaternion, you would want to use features of the tf2 package found here: http://wiki.ros.org/tf2

Q3) It is up to you, but you are correct that c++ is much better suited to real-time programming. Due to all the variables involved, only you can answer if your system can accept the potential latencies imposed by the Python interpreter. For what it is worth -> when real-time performance is required, we always choose c++.

kbhakt commented 3 years ago

Do you all have an example script of how to convert /gx5/nav/odom message to an Euler angle output using the TF2 package. I am having some difficulties of getting them integrated. Any advice or tips would be appreciated.

kbhakt commented 3 years ago

Just wanted to follow up on the above question? Any help would be appreciated.

nathanmillermicrostrain commented 3 years ago

Hello, you can use the documents here to solve this issue: http://docs.ros.org/en/kinetic/api/tf2/html/classtf2_1_1Quaternion.html http://docs.ros.org/en/kinetic/api/tf2/html/classtf2_1_1Matrix3x3.html

You would:

1) Set the quaternion object using the information in the odom message using the constructor: Quaternion ( const tf2Scalar &x, const tf2Scalar &y, const tf2Scalar &z, const tf2Scalar &w)

2) Use the Matrix3x3 function "void setRotation (const Quaternion &q)" to assign the quaternion to the matrix 3) Use the Matrix3x3 function "getEulerYPR (tf2Scalar &yaw, tf2Scalar &pitch, tf2Scalar &roll, unsigned int solution_number=1)" to get the euler angles.

kbhakt commented 3 years ago

Thank you this was helpful! I was wondering which axes yaw, pitch, roll refer to?

I saw this while looking through the API:

Definition at line 50 of file Quaternion.h. What is the default set? Is F2_EULER_DEFAULT_ZYX set to True? I cannot seem to find where this is defined.

yaw | Angle around Y unless TF2_EULER_DEFAULT_ZYX defined then Z pitch | Angle around X unless TF2_EULER_DEFAULT_ZYX defined then Y roll | Angle around Z unless TF2_EULER_DEFAULT_ZYX defined then X

Also, want to double check that the units are in radians correct, and if I wanted them in degrees I would just need to do a simple conversion.

Lastly, If I orient the sensor differently and tare the IMU -- this will reset the axes correct? I am wanting to mount the sensor on the shank of a leg, but want to avoid singularities in the Euler angle calculations if possible. Any advice on how I should proceed?

Thanks!

kbhakt commented 3 years ago

Ok so I tested the sensor with SensorConnect and found that the software as well as the output from the tf2 package using the functions above match.

Roll is rotation about x-axis Pitch is rotation about y-axis Yaw is rotation about z-axis

Now my only question is in respect to taring the sensor so that I don't run into singularity issues. Any advice on that problem would be appreciated.

kbhakt commented 3 years ago

One more follow up is in respect to the kalman filter. The topic /gx5/imu/data is raw data correct? When I use SensorConnect, it uses the kalman filter to output "best" euler angles. How do I ensure that the kalman filter is being used when I compute the euler angles via the tf2 package? Am I missing some link or misunderstanding how the kalman filter is being used?

Thanks.

nathanmillermicrostrain commented 3 years ago

Hello, hopefully, these answers are helpful:

  1. Singularities occur when pitch is at a +-90 degree angle. Try to avoid that condition and you are good to go. Also, quaternions and direction cosine matrices are available to avoid this issue. If you were to base your algorithms on using one of these and not the Euler angles, you wouldn't have to worry about singularities.

  2. The /gx5/imu/data contains the scaled IMU data values for acceleration and angular rate. The data contained in the /gx5/nav topic is always from the kalman filter.

kbhakt commented 3 years ago

Thank you for the response.

  1. When I connect the sensor to the SensorConnect software, I see that there is an offset in the yaw direction, not the pitch direction when I set the sensor on the table. When it is on the table, the x-axis points to the left, y-axis is up, and the z-axis is coming out of the table. Is this just due to the default setting of the IMU? For example if I were to tare the sensor then would the offset would just occur in another direction/channel? Also, I agree with your comments in terms of using something that doesn't have singularities would be ideal.

  2. Thank you for the clarification. I have a follow up question in respect to the /gx5/nav/odom topic. Below in the screenshot is showing the plotting of the odom topic vs. the computed euler angles using the tf2 package. Any insight as to why the tf2 package shows the singularity for one of the channels and not in in the odom package? My initial guess is that these are computed differently. I would just like to know how the /gx5/nav/odom is calculated to make sure my other method is implemented correctly.

Screenshot from 2021-02-22 14-50-16

  1. All of above was run using my laptop and ROS Noetic. I am wanting to get this working on a rpi4 ad ROS melodic and am having compilation issues. This is error I get during compilation (in terminal: catkin build ros_mscl):

Screenshot from 2021-02-22 14-59-53

I made sure I had Boost 1.68 installed on the pi in accordance to the mscl library being dependent on this version. The only difference between my setups is download the dependencies here: https://github.com/LORD-MicroStrain/MSCL#downloads. For the laptop I downloaded Debian C++ x64 and for the pi Debian C++ armhf (Raspbian). Note ALTAIR is just my workspace for compiling different packages for my robotic device.

I have also ensured that I have the tf2 package (https://github.com/ros/geometry2/tree/melodic-devel) compiled before trying the ros_mscl package.

Do you have advice on how to fix this compilation issue on the raspberry pi? Any help would be appreciated! Thanks!

nathanmillermicrostrain commented 3 years ago

To answer 1, I would need to know what type of sensor you have. If it is a -10 or -15, yaw will always drift as you don't have a way to correct it. If it is a -25, the magnetometer is used to correct for heading error and will point to magnetic north. If it is a -45, a combination of sensors will affect heading, but primarily the magnetometer, if enabled.

On 2, maybe the TF2 package is calculating the Euler angles in a different order (are you having to rearrange terms?) Not sure.

On 3, I don't know... looks like something to do with TF2, I would check google and your build environment. There's too many variables outside of our driver that could affect it.

Good luck!

kbhakt commented 3 years ago
  1. It is a GX5-25 IMU. So since this follows the magnetometer, is taring the sensor to the frame of the robotic device to go to avoid the singularity.

  2. This is code I use to call the functions from the tf2 package. The roll and pitch values match in the plots so it doesn't seem like the channels are swapped. tf2::Quaternion q(imu->orientation.x, imu->orientation.y, imu->orientation.z, imu->orientation.w); tf2::Matrix3x3 matrix(q); tf2Scalar yaw, pitch, roll; matrix.getEulerYPR(yaw, pitch, roll, 1);

  3. So I am just trying to compile the ros_mscl package to run microstrain.launch, so I'm not sure why this error is occurring on the pi. The package is the same as when I put it on the laptop. Nevertheless, I will continue debugging it.

nathanmillermicrostrain commented 3 years ago
  1. If you tare the orientation when your robot is in the correct frame, you should get what you want as the initial heading (which is referenced to magnetic north) will be captured and subtracted. Note, this is true for the other angles as well, so you will want to make sure it is in the correct initial orientation for all angles.

  2. From http://docs.ros.org/en/jade/api/tf2/html/classtf2_1_1Matrix3x3.html#a540e704538593ee8d4abf7336dde028e, looks like they might be using YXZ euler angles, whereas our device outputs ZYX euler angles, which would be the difference. (Note, there are 12 or so possible combinations)

  3. Sorry about that... with all the platforms people build on it can be difficult to know exactly why something is not building

kbhakt commented 3 years ago

Just a follow up on this. I was able to get my platform to compile with the necessary ROS packages.

I wanted to ask about the two data rates you can pass as arguments to the microstrain.launch file.

I noticed that there is an imu_data_rate and a filtered_rate. The defaults were set at 100 Hz and 10 Hz respectively. Two questions on the filtered rate:

  1. Is there a reason that this was not set to the same rate as the imu_data_rate?
  2. Is orientation the only thing being filtered when looking at topics or are there other quantities being filtered. Are they all using a kalman filter? Can you point me to some documentation where I can read more about each ros topic that is being outputted?

Thanks in advance!

nathanmillermicrostrain commented 3 years ago

Hi kbhakt,

Good to hear you got it compiling!

Here's the answers to your questions:

Is there a reason that this was not set to the same rate as the imu_data_rate?

A lot of applications do not need the filtered data at a high rate, so it is better to get it at a lower rate to reduce processing overhead. It is perfectly fine to up the rate if you require it.

Is orientation the only thing being filtered when looking at topics or are there other quantities being filtered. Are they all using a kalman filter? Can you point me to some documentation where I can read more about each ros topic that is being outputted?

The angular rate in the "nav/odom" message is generated using the KF... specifically, it is the measured angular rate (as found in the "imu/data" message with the KF estimated bias removed.) There is an additional topic for filtered IMU quantities in "nav/filtered_imu/data" which has the bias removed for both angular rate and acceleration. We do not have specific documentation for the mapping of the quantities for the ROS driver specifically, but I will point you to our standard documentation located here: https://www.microstrain.com/sites/default/files/3dm-gx5-25_dcp_manual_8500-0065_reference_document.pdf

kbhakt commented 3 years ago

Hello,

I am looking to better understand some of the terminology used in the above messages.

Questions:

  1. What/where does bias come into for angular rate and acceleration. Whenever you start the device, do we need to account for this every time the device (gx5-25) is power cycled?

  2. Could your provide a more detailed list of what each of the following topics output and differences between these (see attached screenshot).

Foot Raw Quaternion vs Filtered Quaternion vs Odom Pose

My understanding is that the first topic in the list is the raw output from the imu. or what is scaled imu data? The second topic is the data with the biased removed (?, see question 1). The third is the output after it has been passed through the kalman filter. Is this correct? Ideally I want to be subscribing to the topic that is the most accurate and repeatable.

Thank you in advance!

nathanmillermicrostrain commented 3 years ago

Hello kbhakt,

Answers are inserted below:

What/where does bias come into for angular rate and acceleration. Whenever you start the device, do we need to account for this every time the device (gx5-25) is power cycled?

You should not see a big bias in the accelerometers, the gyros are where biases tend to vary more significantly from power on to power on. The on-board kalman filter estimates the gyro bias in runtime, but it can take several seconds up to about a minute for it to settle on a representative value.

Could your provide a more detailed list of what each of the following topics output and differences between these (see attached screenshot).

/gx5/imu/data/orientation

This orientation is calculated using a simple complementary filter. It is provided as a backup to the kalman filter just in case something causes the filter to diverge. It is susceptible to linear acceleration, so it is not as accurate as the kalman filter, but it's behavior is well understood (no divergence.) I wouldn't use this as your primary source of orientation information, more of a backup.

/gx5/nav/filtered_imu/orientation /gx5/nav/odom/pose/orientation

Both of these come from the kalman filter. The filter is removing the estimated gyro bias and is much less susceptible to linear acceleration. This is the orientation I would recommend that you use. If you were doing something where a divergence in the filter would cause damage to your system, I would recommend cross-checking this orientation against the one from the /gx5/imu/data/orientation as a sanity check. For instance, some people use our devices on drones and it is always good to have an independent calculation to cross-check against. If this is not a concern to you, you can simply use this value as-is.

Hope that helps!

kbhakt commented 3 years ago

Thank you, these answers make things much clearer.

Some of follow up questions:

  1. You said that the bias can range from several seconds to a minute, is this were the status flag in the available topics is a good indicator of whether the system is ready or not?

  2. Could you explain a little bit more on the two filters. Does the complementary filter use all 9 DOF's to calculate the orientation or just the accel and gyro? Similar question for the kalman filter? Perhaps this information is proprietary, but I am just curious about the math behind this orientation calculation. Any references would be appreciated.

  3. For my application, I have users moving in 180 deg turns and 360 turns often. I plan to use quaternions to avoid the singularity issue experienced in the orientation calculation (if using Euler angles). Do you recommend re-taring the system for every trial to make sure the data is consistent, or is there an easy way to quantify the number of revolutions experienced with the IMU?

Thanks!

kbhakt commented 3 years ago

Just wanted to follow up with the above request.

Also, I wanted to get some insight into how magnetic disturbances could affect the output of the IMU. I am potentially having the IMU close to a motor. Since this a dynamic magnetic distortion, would the soft and hard magnetic calibrations help at all in this case? Furthermore, would an orientation be able to be measured accurately if this is the case -- whether it's just the complimentary filter or kalman filter? Could you provide some advice on how to accommodate for this issue?

Thanks!

nathanmillermicrostrain commented 3 years ago

Hi kbhakt,

Answers inserted below:

Also, I wanted to get some insight into how magnetic disturbances could affect the output of the IMU. I am potentially having the IMU close to a motor.

I would advise to keep the IMU as far away from motors, or other dynamic disturbances, as possible.

Since this a dynamic magnetic distortion, would the soft and hard magnetic calibrations help at all in this case?

No, the calibrations will not help for dynamic disturbances.

Furthermore, would an orientation be able to be measured accurately if this is the case -- whether it's just the complimentary filter or kalman filter?

Neither will be able to compensate fully for this issue. The kalman filter has adaptive features to reject transient magnetic disturbances, but the key word is "transient." If you put it by a motor that is operating a decent percentage of the time, that is no longer a transient situation. The filter will reject the magnetometer measurements, effectively acting like it doesn't have a magnetometer and, thus, the heading will drift at the rate of the gyro bias.

Could you provide some advice on how to accommodate for this issue?

I would suggest taking into account the sensitive nature of the magnetometer in your system design. Try to isolate the mag from as much external interference as you can. Also, it is good to do a hard/soft iron calibration on your platform to calibrate the things you can calibrate for. For the things you can't calibrate, the only thing you can do is move the IMU sufficiently far from the offending sources. Luckily, magnetic fields have an inverse-square effect, so it can drop off relatively quickly. Unfortunately, it is not hard to generate a field that completely saturates the Earth's field even at reasonable distances.

kbhakt commented 3 years ago

Ok thank you for the response. I will look more into the soft and hard calibration for our platform.

Would you be able to explain in some more detail with the request above: https://github.com/LORD-MicroStrain/ROS-MSCL/issues/28#issuecomment-824829023

Thanks!

nathanmillermicrostrain commented 3 years ago

Hi kbhakt,

I must have missed this one, here you go....

You said that the bias can range from several seconds to a minute, is this were the status flag in the available topics is a good indicator of whether the system is ready or not?

The system will be ready from the start... the biases effect on the orientation should be under a degree or so prior to the estimates settling. This is standard for this type of sensor and there really isn't feedback as it is hard to know when you should consider the biases settled in real-time.

Could you explain a little bit more on the two filters. Does the complementary filter use all 9 DOF's to calculate the orientation or just the accel and gyro? Similar question for the kalman filter? Perhaps this information is proprietary, but I am just curious about the math behind this orientation calculation. Any references would be appreciated.

Both are full 9DOF filters and use the accels, gyros, and mag. There are a lot of references on the web if you search for complementary orientation filter and/or orientation kalman filter.

For my application, I have users moving in 180 deg turns and 360 turns often. I plan to use quaternions to avoid the singularity issue experienced in the orientation calculation (if using Euler angles). Do you recommend re-taring the system for every trial to make sure the data is consistent, or is there an easy way to quantify the number of revolutions experienced with the IMU?

You shouldn't have to tare the system for each run, but it is really up to how you want to use the sensor; just know that it is uncommon to do that. As far as the number of revolutions, that would be on your code to keep track of as that isn't an available output of the device.

kbhakt commented 3 years ago

No worries. Thanks for the response!