# Odometry message for ackerman car

Hello , I have an Ackerman car which I want to calculate its velocity using wheel encoders to feed it as odometry message to robot localization. I'm confused what should be the proper calculations for odometry message velocity for an Ackerman car. I assigned the child_frame_id of the message to the base footprint of the car , so the velocity is with respect to the base_footprint of the car (which is in the middle between the rear wheels).

I used 3 models and not sure which is the right one ??

1st model:

(Calculate right rear and left rear wheels velocities and get the steering angle of the car from another sensor)

speed= (vR + vL)/ 2.0
vx = speed * math.cos(wheelAngle)
vy = speed * math.sin(wheelAngle)
odomMsg.twist.twist.linear.x = vx
odomMsg.twist.twist.linear.y = vy
odomMsg.child_frame_id = 'base_footprint'


2nd model:

(Calculate right rear and left rear wheels velocities and measure the distance between the 2 rear wheels)

LenghtBetweenTwoWheels=1.01
speed= (vR + vL)/ 2.0
v_th=(vR - vL)/ LenghtBetweenTwoWheels
vx = speed
vy = 0.0
odomMsg.twist.twist.linear.x = vx
odomMsg.twist.twist.linear.y = vy
odomMsg.twist.twist.angular.z = v_th
odomMsg.child_frame_id = 'base_footprint'


3rd model:

(Calculate right rear and left rear wheels velocities and get the steering angle of the car from another sensor)

wheelBase=1.68
speed= (vR + vL)/ 2.0
v_th=speed*tan(wheelAngle)/ wheelBase
vx = speed
vy = 0.0
odomMsg.twist.twist.linear.x = vx
odomMsg.twist.twist.linear.y = vy
odomMsg.twist.twist.angular.z = v_th
odomMsg.child_frame_id = 'base_footprint'


Any help ? Thank you

EDIT1:

a- My wheel encoders only ticks 52 each turn (The wheel diameter = 0.436m) so The difference between vR & vL wouldn't be very expressive, So I was hoping the third model is correct.

b- I tried the 3 equations: Used 3 sets of robot_localization nodes with same setup :

Setup:

ekf_local_node :

• world_frame: odom
• imu0: /imu
• odom0:/wheel_odom(i)
• output:/odometry/filtered1 "not used"

ekf_global_node :

• world_frame: map
• imu0: /imu
• odom0:/wheel_odom(i)
• output:/odom(i)

The only difference of the 3 set of nodes is that odom0 is /wheel_odom1 or /wheel_odom2 or /wheel_odom3 . Each of these topics calculate twist message according to one equation of last three models .

I turned 360 deg with the car ( used my max wheel angle ) and logged the results of the three ekf_nodes (odom)

The result was as shown in the pic:

yellow line : is the real turn ( using a 1 cm RTK gps with imu orientation)

red line : is the odom output from the first model equation (vx , vy)

green line : is the odom output from the second model equation (vx , vth) (vth=(vR - vL)/ LenghtBetweenTwoWheels)

blue line : is the odom output from the third model equation (vx , vth) (v_th=speed*tan(wheelAngle)/ wheelBase) -There is no difference between the second and third model result . Also , I tried to put vth = zero . And the same result happens. -All three equation doesn ...

edit retag close merge delete

Please post your full EKF config, as well as a sample message from every sensor input.

By the way, if it didn't use theta velocity, you wouldn't see a circle. What makes you think it's ignoring it?

Sorry, downloading bags and going through them is going to take more time than I have right now. Can you please paste your full EKF config and sample input messages inside the question itself? Use the code formatting.

Sort by » oldest newest most voted I'm looking at your config file, and I have a few comments:

1. Are you trying to run all of these at the same time? That's going to cause all sorts of trouble in rviz, because they are all publishing the same transform. If you want to do an apples-to-apples comparison, I suggest you rostopic echo /some_filtered_topic -p > output.txt, and then plot the output using MATLAB or Octave.
2. I'll tell you what I tell a lot of people: start simple. Forget the GPS for a moment, and forget testing all the models at once. Start with one simple EKF config that just fuses IMU and wheel encoder velocities from one of your models. Get that working well, and then plot the data. Then try with a different model, and plot that on top of it.
3. You have two_d_mode turn on, but you are fusing roll and pitch in your IMU. It won't hurt anything, but it also won't actually do anything.
4. Your first data sources are not fusing yaw velocity at all. I assume that's intentional.
5. For wheel encoder data, you should always fuse the 0 value for y velocity (just set Y velocity to true). Give it a tiny covariance value, too. Your robot is not omnidirectional, so fusing a 0 value for Y enforces a kinematic constraint that stops the robot from moving sideways.
more

Thank you Yes I run all nodes at the same time. , I'll do that and see the result. There are different possible ways to do this, but your second model is the simplest and is correct. If you think about it, the fixed wheels of an akerman chassis move the same way as a turtle bot, the only difference is that their idividual speeds are not controlled only their average speed. The ratio between there speeds is set by the steering angle.

However if you can measure their actual speed using encoders then you can determine the steering angle as if it was a turtle.

Hope this helps.

more