Encoder-Free Odometry Using Stepper Motors

Many ground-based robots employ motor shaft encoders to help provide a reasonable estimate of the robot movement along the surface of the ground.

This technique enables robot odometry via feedback from the motor shaft. But what if we could do away with that and adopt a simpler approach? Could similar results be achieved whilst lowering costs and simplifying the system? The answer to that question is a resounding yes, and the solution is to use stepper motors.

Conventional DC Motor and Encoder-Based Systems

Conventional methods for wheeled-robot odometry employ shaft rotation feedback encoders that measure that actual rotation of the wheels on the robot. Typically using hall-effect or optical sensors, data is acquired as a series of pulses from the encoders, the frequency of which increases as the wheel turns faster. Owing to the nature of many electrical motor systems, it’s otherwise not possible to accurately predict how much a wheel will turn, given a certain electro-motive force. Thus shaft encoders are a mandatory feature on most ground-based robots that require odometry.

A typical DC motor with shaft encoder

Wheel encoders typically use 3-4 wires per encoder (plus the motor connections), along with the use of a software-based Proportional Integral Derivative (PID) controller to convert that into a usable odometry.

On a two-wheel drive robot, that then necessitates up to twelve connections for the data and power lines, and the creation of two PID filters. That’s a lot of resources just to be able to know what your wheels are doing!

Using Stepper Motors

Stepper motors are in common use today in many applications, with one of the most notable examples being that of 3D printers. A 3D printer requires highly accurate positioning abilities and the ability to hold the motor in any given position. That’s a nice feature of stepper motors for 3D printing, but they can also be used to drive robot wheels. Robots that utilize stepper motors for locomotion produce highly predictable and accurate motion, and can also be put to “Sleep” when any given wheel is stationary, thus saving power.

A typical stepper motor

Notable is the fact that stepper motors turn in discrete steps (thus the name!). That is to say, that under the control of a dedicated circuit known as a stepper controller, the motor shaft can be positioned anywhere around the 360 degree rotation, and typically with 1.8 degree step size.

Inferring the Motor Rotation

By providing a continuous pulse train to the stepper controller, the on-robot computer can cause the stepper to produce a continuous rotation, the speed of which is proportional to the frequency of the pulse train. A low frequency pulse train causes the wheel to turn slowly, whilst a high frequency pulse train causes the wheel to turn faster. In a properly designed system, there will be no missed steps, meaning that each pulse will result in a single step of the motor, and so the host computer can infer exactly what the speed of rotation of the wheel is, essentially by counting the pulses it is sending to the motor controller.

The stepper motor controller

Most modern host computers (including the Raspberry Pi) have dedicated hardware that can produce the necessary pulse trains to the stepper motor controllers. This hardware is know as Pulse Width Modulation (PWM), and is commonly used to create the necessary signals. As such, this requires very little intervention by the host computer. Furthermore, once setup, speed control and odometry are achieved with no additional resources. Thus encoder-free odometry using stepper motors is both simple and easy to implement, both at the hardware level (no need for encoder wiring) and at the software level (no need for PID controller).

Examining the Code

Underside of controller showing connections

On the Mini-Turty host computer, using a timer callback, we periodically update the speed of the motor according to what is instructed by the robot teleop / velocity commands.

For our differential drive robot, we use stepper motors driven by stepper controllers, which are directly controlled by the Raspberry Pi host computer. To understand how we derive the odometry, consider the following code snippet:

void MiniTurtyBase::timerCallback(const ros::TimerEvent)
{
  double vx;
  double vth;
  
  updateMotorControl(DIFFDRIVE_MOTOR_LEFT);
  updateMotorControl(DIFFDRIVE_MOTOR_RIGHT);

  vx = (motors[DIFFDRIVE_MOTOR_RIGHT].currentSpeed + 
        motors[DIFFDRIVE_MOTOR_LEFT].currentSpeed) / 2;
  vth = (motors[DIFFDRIVE_MOTOR_RIGHT].currentSpeed - 
         motors[DIFFDRIVE_MOTOR_LEFT].currentSpeed) * 8;

  publishOdom(vx, vth);
}

The above timer callback function is attached to a ROS timer, and hence is called periodically. On each invocation, the callback updates the motor control with the new motor speeds for the left and right motors. It then calculates the velocity ‘vx’, which is the speed that the robot is moving in the forward (or backward) direction. It also calculates the velocity ‘vth’, which is the speed at which the robot is rotating about the z-axis (aka turning!). These two velocities are derived from the current speed that the motors are rotating at, which in turn is derived from the speed that was set. Thus we achieve a quasi-feedback from the motors that is purely software-based. These calculated linear and rotational velocities are then passed to the function ‘publishOdom()’, whose purpose is to send the odometry information back to ROS.

At this point, the astute reader might be wondering: why not just use the speed that was set by the incoming velocity command and publish that? Well the answer to that is we need to take into account the fact that stepper motors do not instantaneously change speed. For most velocity alterations, it is necessary to “slew” the rate of the motor. Slewing, in this context, is the process of gradually changing from one speed to another. Thus a motor that is going from say 20 RPM to 100 RPM might make that change as a series of steps, going from 20, to 30, to 40, and so on up to 100. So in order to provide accurate odometry information, it’s important that the actual speed of the motor is used, rather than any target speed that we may be currently slewing toward.

The full code for the Mini-Turty series of robots, including the code for the odometry, can be found at our github repository.

It turns out that practical systems for odometry can be achieved through the use of steppers motors as the primary means of locomotion. When combined with modern LiDAR, this then enables robot localization, mapping and navigation. Moreover, this use of stepper motors gives rise to a simpler implementation that’s easier to create, cheaper to realize, and provides a result comparable to that achieved with the more conventional system using DC motors and encoders.

Leave a Reply

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