Enabling odometry, creating /odom messege, connecting with SLAM – Tutorial



Read this before you begin:

This is a second post on how to enable your robot with SLAM. If you haven’t seen the first one, i highly suggest reading it first here.

Added code works on RobertROS robot, that’s why you will probably have to change it according to your system. (The location of necessary changes will all be exposed)


WHY Odometry:


Although Hector SLAM ROS package does not require odometry to make a map, it certainly helps with:

  • reducing false jumps
  • reducing lagging of robot localization
  • overall quality of mapping

and it is routinely used with all robots that require accurate navigation for functioning.

Details: LINK


HOW Odometry:

Odometry is basically interpreting the location of your robot from wheel encoders. Because wheels usually slip on the ground, this interpretation of location is accumulatively wrong in long term. But that is OK, because Hector SLAM (and later amcl) only uses it as a short term location correction, and that is why it is very good to have it!

Example made with:

Raspberry (can be any computer, but then configuration is a bit different)

Arduino Mega (as motor driver and speed calculator)

Monster motor shield

2x Encoders (i used theese)

In order to use Odometry with in ROS, you will need to specify the odometry info in a topic called /odom, and it’s transform from /odom to /base_footprint. (See explanation of tf on ROS official site for more info)

This is how /odom messege looks like: LINK

To put it all together you will need to calculate how much your robot has moved based on time, speed and radius of your wheels.

In this example Arduino Mega is calculating wheel speeds and publishing them on /ard_odom thru rosserial on Raspberry Pi. So make shure you install it by:

sudo apt-get install ros-<DISTRO>-rosserial

where you replace <DISTRO> with your ROS version.

On Arduino:

The whole code can be found HERE, but following are the relevant code chunks for arduino:

For reading encoders with interrupts, the encoder library can be found HERE.


Initializing node and registering the publisher for speeds. You can change /ard_odom to anything you want.


In loop we get the full velocities form encoder ticks(converted to meters by TicksToMeters()) and differential of time. The speeds are saved to be published in void loop().

Note that velocities are used in the same function for closed loop control of the robot – ignore that for now.


Then in void loop(), speeds are published as Twist msg (x=Left wheel, y=Right wheel). First couple of times odom publishing is not active, because speeds are not calculated yet.


And that is all that that arduino code says about odom. All the surrounding code is for arduino to read cmd_vel, motor control, closed loop -> all very important for a robot but topic for another tutorial

On Rasperry Pi:

Now here are the relevant pieces of code on RPI:

This code reads /ard_odom and converts velocities to a usefull /odom messege that can be used in amcl, SLAM,… Although I can’t publish the full code, I will expose only the relevant chunks:

First subscribe to /ard_odom with Twist as recieving messege type.


Now specify all the details of tf. You can change topic names according to your config, but these are standard for ROS and I suggest keeping them.


Save speeds as SVL and SVR for right and left wheel and call function that generates odom.


And this is actually the whole procedure of making an odom msg and it’s transform.


Now just publish /odom and send transform somewhere in the loop like:


And if you did everything right, you should have yourself a legit odom setup. Congratz!

Share on FacebookShare on LinkedInTweet about this on TwitterEmail this to someone

You may also like...

11 Responses

  1. Etienne says:

    I followed your tutorials, (except the names my frames are not the same, I followed the hector_slam tutorial which uses base_footprint and nav, where you use base_frame and odom).
    My odometry seems to be working, however I see no difference in hector_slam. After a few minutes, the pose produced by hector mapping jumps.
    Could you finally add your odometry and see a difference ?
    From what I’ve understood, hector mapping is not using odometry, except maybe attitude (roll, pitch), but maybe I’ve missed something.

  2. Etienne says:

    oops, you are using base_footprint too.

    • Janez says:

      Hey! No, after adding odom to Hector SLAM, mapping still “jumps”, but it does so considerably less. After I make a map with slam, I use amcl package to navigate on it. There odometry works wery well!
      Hector SLAM never worked flawlessly, but it improves with adding odom, better LIDAR and a little customization of launch file.

      Hope this helps!

  3. Johannes says:


    I am using ros for a school project,
    I can drive a wheelchair open loop via an arduino using the /cmd_vel topic.

    and with some help of your arduino sketch i can read the wheel speeds via some encoders.
    now i need to transform those wheelspeeds to odom data.
    your piece of code to transform it to odom isnt compleet is it?

    would you mind sending me some pieces of your code to get my system working.

    With kind regards Johannes,

    • Janez says:

      The thing is, my code for transforming the speeds to odom has some custom libraries and arhitecture, that are not relevant here and would complicate things. You actually have all needed things above in the tutorial, you just have to customize it according to your robot. Please contact me on my mail if you have further problems with this 🙂

  4. ZEROUALI says:

    Can you show me how you connect motors with shiel motor please?

  5. sarthak says:

    Can you please tell me how do you define SVL and SVR? . Is it a twist message too?

  6. sarthak says:

    Can you please me tell what odomturnmultiplier is?

    • Janez says:

      OdomMultiplier is a global variable with which you can fine-adjust odom calculations of theta (dth). It’s usual values are 0.95 – 1.05

Leave a Reply

Your email address will not be published. Required fields are marked *