ROS packages for ROS Melodic related to odometry running on a Raspberry Pi 4 B for an autonomous 2WD Robot.

The following section describes the theory of robotic motion and odometry, which is part of the book Elements of Robotics. Here the relevant part for the speed sensors, attached to the robot wheels, is outlined. After going through the theory, we will look at the packages used for ROS. These will be self written ones and the differential drive ROS packages, which is already available.

Robotic Motion and Odometry

This section reviews the basic concepts of distance, time, velocity and acceleration. The physics of motion is can be described using calculus, but a computer cannot deal with continuous functions; instead, discrete approximations must be used.

Odometry, the fundamental algorithm for computing robotic motion. An approximation of the location of a robot can be obtained by repeatedly computing the distance moved and the change direction from the velocity of the wheels in a short period of time. Unfortunately, odometry is subject to serious errors. It is important to understand that errors in direction are much more significant than errors in distance.

In the simplest implementation, the speed of the wheels of a robot is assumed to be proportional to the power applied by the motors. To improve the accuracy of odometry wheel encoders can be used, which measure the actual number of revolutions of the wheels.

Distance, Velocity and Time

In general, if a robot moves at a constant applied to the motors it causes the wheels to rotate, which in turn causes the robot velocity $v$ for a period of time $t$, the distance $s$ it moves is $s = vt$. When power is to move at some velocity. However, we cannot specify that a certain power causes a certain velocity

  • No two electrical or mechanical components are ever precisely identical.
  • The environment affects the velocity of a robot because of different friction of the surface
  • External forces can affect the velocity of a robot. It needs more power to sustain a specific velocity when moving uphill and less power when moving downhill, because the force of gravity decreases and increases the velocity.

Velocity is speed in a direction. A robot can be moving 10cm/s forwards or backwards; in both cases, the speed is the same but the velocity is different.

Acceleration as Change in Velocity

ROS Packages

LM393 Speed Sensor - Odometry

To measure how far the robot has driven, we use the LM393 speed sensor from Joy-IT as odometry sensor. First, we will create a ROS package with catkin create pkg PKG_NAME [--catkin-deps [DEP [DEP ...]]]:

fjp@ubuntu:~/git/2wd-robot/ros/src$ catkin create pkg lm393_speed_sensor --catkin-deps rospy roscpp nav_msgs
Creating package "lm393_speed_sensor" in "/home/fjp/git/2wd-robot/ros/src"...
Created file lm393_speed_sensor/CMakeLists.txt
Created file lm393_speed_sensor/package.xml
Created folder lm393_speed_sensor/include/lm393_speed_sensor
Created folder lm393_speed_sensor/src
Successfully created package files in /home/fjp/git/2wd-robot/ros/src/lm393_speed_sensor.

The package depends on the two ROS client libraries rospy and roscpp. The current implementation uses python and the RPi.GPIO library for interrupts. To achieve more percise results, C++ should be used instead. To signalise the current pose of the robot in the odometry frame, the nav_msgs/Range message is used.


To get the speed sensors working, we connect the signal pins to (physical) GPIO 15 and (physical) GPIO 16 of the Raspberry Pi 4 B and power them with 3.3V. The ground pins are connected to ground of the Pi.

LM393 Speed Sensor Library

To use the LM393 speed sensor as a ROS node the sensor functionality is wraped in a class. This provides an easy to extend interface for the speed sensor (API) The code consists of a class LM393SpeedSensor which has two interrupt service routines (ISR) methods. Using the RPi.GPIO interrupt capabilities, these ISR methods are used as callback functions when the sensor measures a falling edge. This is the case when the rotary disk spins and the optocoupler measures a high to low signal due to the spinning disk.

The sensor API is implemented in the python module. Executing the module will result in the following output when the motors are spinning freely with full speed and using some force to slow them down. We see that the rotational speed $\omega$, measured in RPM (revolutions per minute) changes.

fjp@ubuntu:~/git/2wd-robot/ros/src/lm393_speed_sensor/src$ sudo python

The rotational speed $\omega$ values will be converted to tangential velocity values using the radius $r$ of the wheels.

\[v = \omega \cdot r = 2 \pi n \cdot r\]

ROS Node for LM393 Speed Sensor

ROS provides the Odometry Message in the nav_msgs header. This message type can be used to write a wrapper that will act as a ROS node for the LM393 speed sensor.

To design this node we will send out measurements periodically over a topic of type nav_msgs/Odometry. The code for this node is in

After writing the node we need to build the packages in the workspace with catkin build.

fjp@ubuntu:~/git/2wd-robot/ros$ catkin build

As the final note of the build output suggests, we have to source the setup.bash files in the devel space.

fjp@ubuntu:~/git/2wd-robot/ros$ source devel/setup.bash

To make the speed_sensor node executable we have to modify the file:

fjp@ubuntu:~/git/2wd-robot/ros/src/grove_ultrasonic_ranger/src$ sudo chmod a+x

Then we can test the node using rosrun:

fjp@ubuntu:~/git/2wd-robot/ros$ sudo su
[sudo] password for fjp:
root@ubuntu:/home/fjp/git/2wd-robot/ros# source devel/setup.bash 
root@ubuntu:/home/fjp/git/2wd-robot/ros# rosrun lm393_speed_sensor 

This lets the node publish range messages which we can capture in another terminal window using rostopic. First we use rostopic list to find the name of the topic we are interested in:

fjp@ubuntu:~/git/2wd-robot/ros$ rostopic list

We named our topic /odom which we can use with the rostopic echo command to see the published messages:

Leave a comment