6.3.8 What about differential steering?

You can treat each motor independently in a differentially steered, and you can use one struct MotionProfile for each motor. This also means you probably need different versions step_func and accel_func, one for each motor.

This approach works fine when the two motors are symmetric and have exactly the same profile. However, for error correction and turning, it is often necessary to speed up one and slow down the other one. As a result, treating two motors independently is often a bad idea, leading to many problems down the line.

From the top level, it is best to look at motion from two physical perspectives. First, there is linear motion. Second, there is angular motion.

Consider the following scenario. Your robot is heading north (zero degree). It makes a 90-degree turn clockwise using differential steering at an average velocity of 300mm/s. Also, let us assume the turning radius is 600mm, and each wheel is 100mm from the center of the robot.

This means the left wheel needs to move at $300\mathrm{mm/s}\times \frac{600+100}{600}=350\mathrm{mm/s}$. The right wheel, on the other hand, needs to move at $300\mathrm{mm/s} \times \frac{600-100}{600} = 250\mathrm{mm/s}$.

At the same time, you can also express this motion as a linear speed of 300mm/s, with an angular speed of 100mm/s. The linear speed is easy to interpret. However, the angular speed needs some explanation. The angular speed is the difference of speed between the two wheels.

Once you separate into these two profiles (linear and angular), each profile has its own parameters. As a result, each profile also ends up with its own displacement, target velocity and velocity. It is also important to know that the limits ( ${v_\mathrm{max}}$ and ${a_\mathrm{max}}$) for these two profiles will be different.

In our example, we keep the target velocity for the linear profile as 300mm/s, and its displacement is kept the same. However, for the angular profile, the displace was originally zero. It is then set to $200mm \times \pi \div 2$, which is approximately 314mm. The target velocity for the angular profile is set to whatever maximum that the robot is capable of. The logic of 1 automatically takes care of the angular aspects of turning.

Here comes our next question. So far, we don't have anything that is useful for controling the motors.

The linear and angular motion profiles need to combined so we can control the stepper motors. This can be done easily. Afterall, the angular profile describes how the two motors differ. As a result, $v_\mathrm{L} = v_\mathrm{lin} + \frac{v_\mathrm{ang}}{2}$, and $v_\mathrm{R} = v_\mathrm{lin} - \frac{v_\mathrm{ang}}{2}$.

What does this mean for our C code? As it turns out, we don't need to track the displacement or acceleration for the individual motors anymore. Instead, we only know need the velocity (step frequency) of each motor.

We can now create our macro structure for a differentially steered robot as follows:


\begin{lstlisting}{}
struct DiffSteer
{
struct MotionProfile linear;
struct M...
...ofile angular;
struct FreqDiv left;
struct FreqDiv right;
};
\end{lstlisting}

Assuming ds is a struct DiffSteer, we need to update ds.left.freq and ds.right.freq whenever ds.linear.vel.freq or ds.angular.vel.freq updates. This is easy, since we can put this logic in the call back functions ds.linear.acc.cb_func and ds.angular.acc.cb_func.

However, you need to track the sign/direction of each motor separately. It is not necessary to track this as a separate property. You can use ds.linear.vel.freq, ds.linear.v_sign, ds.angular.vel.freq, ds.angular.v_sign to determine the direction of each motor.

Copyright © 2006-02-15 by Tak Auyeung