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
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
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
lm393_speed_sensor.py 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 lm393_speed_sensor.py TODO
The rotational speed $\omega$ values will be converted to tangential velocity values using the radius $r$ of the wheels.
ROS Node for LM393 Speed Sensor
To design this node we will send out measurements periodically over a topic of type
The code for this node is in
After writing the node we need to build the packages in the workspace with
fjp@ubuntu:~/git/2wd-robot/ros$ catkin build TODO
As the final note of the build output suggests, we have to
setup.bash files in the
fjp@ubuntu:~/git/2wd-robot/ros$ source devel/setup.bash
To make the
speed_sensor node executable we have to modify the
fjp@ubuntu:~/git/2wd-robot/ros/src/grove_ultrasonic_ranger/src$ sudo chmod a+x speed_sensor.py
Then we can test the node using
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 speed_sensor.py
This lets the node publish range messages which we can capture in another terminal window using
First we use
rostopic list to find the name of the topic we are interested in:
fjp@ubuntu:~/git/2wd-robot/ros$ rostopic list TODO
We named our topic
/odom which we can use with the
rostopic echo command to see the published messages: