Move robot along curved path (with differential steering)

I am building a robot that looks roughly like this:

(Image taken from this site and modified by myself.)

The two wheels are powered by stepper motors so that I have fine control over the turning angle and speed of the wheels. I want to use Differential Steering to control the robot. The robot has no sensors whatsoever. Instead it assumes that by giving the right commands to the two motors it will be get to the desired position. (The floor will be flat.) I believe this is called dead reckoning.

I want the robot to be able to follow a pre-defined curved path. The path is not drawn on the floor but exists as an array of bezier points. I want to program a controller that can follow this path not only by going from point to point in a straight line but also by following curves:

As I mentioned before, going from point to point in straight lines would not be enough:

There are at least two problems I have to solve:

 

1. Do the math to know how fast to turn each wheel to get from A to B. This is a nice article on the subject: A Tutorial and Elementary Trajectory Model for the Differential Steering System of Robot Wheel Actuators. Equation [5] shows how to calculcate the robots position based on the velocities of the two wheels. But I need it the other way round: I know where I want to go and need to know the wheel velocities. Can you help?

2. Enable the robot to not only go from A to B but follow a pre-defined curve along the way. A first idea would be to split the curve into lots of little curves (i.e. add points along the path). Any thoughts on this approach?

Thanks in advance, I am looking forward to your thoughts.

bdk6, I’m not sure I

bdk6, I’m not sure I understand. Can you explain a bit?

The path is not drawn on the floor, it only exists virtually in the software.

I suggest starting simple.
Hi,

Forgive me if you’ve already thought of these, but I’d suggest doing a number of simple exercises first. These will help you calibrate the software to make up for any slight differences in motors and/or wheel size or just simply between theory and the real world. These should be done on a constant floor that the wheels run on well, for example hardwood or linoleum.

  1. Have the robot go in a straight line. If there is any curvature in the line, you should be able to adjust the motor commands to compensate. For example, if the robot curves slightly to the left, this means that the right motor is having more effect than the left motor, so you either have to adjust the left motor to move a bit more or the right motor to move a bit less.

  2. Have the robot spin in place 10 times. Again, this will tell you how the motors work in a real life situation. Another variant of this to try is have it go 10 times clockwise then stop, then go 10 times counter clockwise. It passes both these tests when it ends up facing the same way at the end of the test then it did at the beginning.

I don’t think I’ve ever had a robot pass all these tests the first time even with encoders just because of motor and wheel size differences. However, I’ve never tried a bot with stepper motors.

I’m in a bit of a hurry

I’m in a bit of a hurry right now, but I grabbed a function out of one of my robots that uses bezier curves to define the trajectory of each foot as it steps. I’ll add more details later when I have a minute, but this should give you an idea of what gets plugged into the formula and wherre. Really the only diffucult part YOU’LL have to work out is getting your bot to the desired positions in the coordinate plane. bdk had a very good post of what needs to be worked out to make this happen. I was lucky in my implementation as I was just dealing with servo angles and not the position of the robot in a dynamic environment.

void pathPlan(int legID){

  if (legMode[legID] == 0) {
    stepDistance = sqrt( sq(stepYStart[legID] - stepYTarget[legID]) + sq(stepZStart[legID] - stepZTarget[legID]) );
 
    footY[legID] -= stepDistance/(gaitNodes-gaitLegUpNodes);
  }
  
  else {
    float m = (1.00/gaitLegUpNodes) * legUpCounter;
    int stepYApex = (stepYTarget[legID] - stepYStart[legID]) / 2;
    int stepZApex = stepZTarget[legID] + stepHeight;

    footY[legID] = stepYStart[legID] - 2  m  stepYStart[legID] + (mm)  stepYStart[legID] + 2  m 
stepYApex - 2  (mm)  stepYApex + (mm)  stepYTarget[legID];

    footZ[legID] = stepZStart[legID] - 2 
 m  stepZStart[legID] + (mm)  stepZStart[legID] + 2  m 
stepZApex - 2 
 (mm)  stepZApex + (mm)  stepZTarget[legID];

    if (legUpCounter < gaitLegUpNodes) {
      legUpCounter++;
    }
    else {
      legUpCounter = 1;
    }   
  }  
}



Wikipedia has a good page on the subject with animated reference images for quadratic bezier curves here.
I’ll try to find a page I had saved that gives a more intuitive explanation of the equation when I get back.

I’m thinking an easy way to

I’m thinking an easy way to do it might be to steal methods from line followers. The only difference is your line is virtual so you’ll need to compare your dead reckoning position to the virtual line (curve) to see if you need to go straight, right, or left. There are more complex ways to do it, but with the loose accuracy of dead reckoning you don’t want to spend a lot of time on something that is an order of magnitude more accurate than what your robot can actually do.

Also, since you’ll also know

Also, since you’ll also know the distance that your robot is from the curve (as oppose to just knowing if it to the left or right of it) you could do a nice PID controller instead of a bang-bang controller (where the commands are either strait, hard right, our hard left)

Just for an update, i was fiddling with this problem and came up with some solutions.

Javascript Fiddle of Fwd/Turn Path:
https://jsfiddle.net/4qexoa9m/29/

Stackoverflow question regarding arc path between two points:

1 Like