Navigation above oddometry

Hi all. I've gotten oddometry down. I've got PID and profiling on the tires (two wheel differential steering). I am having a little trouble with aiming/steering in coordination with profiling.The biggest problem I'm having is connecting the two independent wheels with the motion of the body.

For instance, let's say I drive to a point. If the point gets between the wheels, say very near the axle, how do I handle that? Now the body has to go a few inches, one wheel has to go much further forward than the body in general, and the close wheel has to back up. I can handle the aiming, but the profiling the motors to move the wheels, one forward, one backwards... and coordinating them so the body arrives at the point when the wheels both stop... that's confusing.

Anyone know of some good references/published work on this?

Reply to
Randy M. Dumse
Loading thread data ...

I'm assuming a fairly standard base where the axle bisects the robot and the center of the axle is the center of rotation when the robot turns, as opposed to something else like 4 where where the front two wheels steer. Is this correct?

If so, if you arrive near the desired point, and it is not centered underneath the mid-point of your axle, like this:

O----------x-----p----O

Where 'x' marks the center of the axle and 'p' is your target point and marks where you want 'x' to be.

Could you just rotote 90 degrees such that the configuration now looks like this:

O----------x----------O

p

Then, once p is centered with the axle and perpindicular, you can just drive forward until 'p' is under 'x'.

-Brian

Reply to
Brian Dean

[stuff deleted]

Non-holonomic control. Look up works by Alessandro Astolfi (we are using his approach to the problem for our mobile robots), also C. Canudas de Wit and O. J. Sørdalen.

When the robot "centre" control point [1] has reached the goal point be careful, with our approach you are in a singular position. We overcome that by switching to a slightly simpler controller when very close to the goal.

You can also make your life easier by controlling some other point on the robot than the centre between the wheels (e.g. some point straight in front of the wheels) and instead of controlling to a point you control along a trajectory, and we have created a holonomic system out of the robot.

Have fun

Sjur

[1] A point is given by the co-ordinates [x,y,theta]
Reply to
Sjur Vestli

Yes.

Yes, but notice the progression. Drive near a point and stop. Turn toward the point and stop. Now drive to the point. Here we have multiple steps, and no guarantee when you get to the end of this move, you will not have to reiterate yet again. After all the step before "Drive near a point" must have been "turn toward the point".

I was looking for a single algorithmic solution. Start with: I am here at some velocity; add: the new point is there at some XY distance. How do I steer all the way to it under all circumstances?

A good deal of the problem I was having was the profiling of the wheels. I was working with a large (high mass compared to what I'm used to) robot. We had to prolong acceleration to keep from loosing odometery from wheel slippage. So it took up to 2 seconds to reach top speed. So likewise, I had to take a similar amount of time to slow down to reach the target point.

I finally think I've got it. I learned lots of things along the way, which were kind of surprising. For instance, you can't slow down at your maximum deceleration rater, and steer at the same time. To wit: If you need to turn, and you are slowing your inside wheel and outside wheel at maximum rate, you can't also slow your inside wheel down "more" to achieve a turn, and you can't speed your outside wheel up, or you'll miss and overshoot the end point! You must keep something in reserve if you also want to do steering corrections as you go. Very much like a skid in an automobile. Apply maximum braking, and you cannot control your heading, use a little less and maintain directional control.

The biggest trick in it all for me was to switch from thinking of two wheels profiled and always moving forward, to a profiled body move, with wheels which would support that body movement. For instance to do a right angle turn, I had to have a negative velocity on the inside wheel. Once I worked out I had to make the profiling work in the negative and positive direction, it finally came together.

Thanks to all that responded.

Reply to
Randy M. Dumse

I corrected the spelling of odometry in the title. I thought I'd document the approach I worked out, and perhaps some others would find it useful. Please overlook I am replying to my own post.

First have a look at Gary Lucas's article on the SRS site

formatting link
and one on differential steering on his site

formatting link
Notice Gary said, "Rather than looking at the problem as a matter of controlling two motors, I looked at the robot as a whole." I on the other hand had started out making PID work on one motor, then added two motors, and then I took a profiling program I'd written for an arm, and applied it to these motor PIDs. So I came up quite the other way 'round.

My problem was I had two motors under PID control, but no coordination between them. The result was one wheel, or the other, would fall behind in its profiled target point. Although PID would compensate, it would not be until after the error occurred. So the wheel that had the least turning resistance would run steadier speed. The lagging, then corrected wheel, would cause the turned body to straighten on course, but each lag would cause an accumulated error, which became a lateral displacement. Here a little ASCII art might be useful: | is the straight path, and \ is a lag followed by a correction.

actual intended ^ ^ | | \ | | | | | | | \ | | | | | | | \ | | | ^

I think a higher update rate would have made this problem less visible, but that is a bit like sweeping it under the rug.

So while both wheels on the robot were PID controlled, the body did not move in a straight line. This was a surprise when discovered, but makes sense in retrospect. The underspeed of one wheel would cause the I term to generate a correcting overspeed, but while this would again turn the robot straight, it wouldn't correct for the lateral movement imparted during the underspeed.

Interestingly, the odometry doing the tracking of position knew this displacement was taking place. If the problem was measurable, it should be correctable. This started my beginning work on the steering program.

Here is basically how my steering works. If the heading was not the same as the course, then an error is generated. You might first imagine one would speed the outside wheel up and bit and slow down the inside wheel to get a course correction. But! This assumes you can speed up the outside wheel. If you are trying to go full speed, the outside wheel simply can't be made to go faster. In fact, if you've turned off course, it is because the outside wheel didn't go as fast as the inside wheel, so it may already be going as fast as it can and too slow anyway. So the art of steering can be accomplished by slowing down the inside wheel.

How much should the inside wheel be slowed down? It was tempting to just adjust the course so the robot would steer again toward the course. However, if the robot veered off course, correcting back to course would produce a curved path of veer, and return, veer and return. Instead, to hold a straight line, a correction should over compensate, to not only steer toward the point, but past it, to regain the original line.

The greater the error of the actual path traveled the greater the turning force required. Yet this can be over done as well, producing an oscillating path, or even a loss of path. So I computed the difference to slow the inside wheel by taking the relative bearing times a settable gain factor times, and limiting the output to + or - PI, then taking the cosine and multiplying this by the outside wheels actual speed, and applying this to the inside wheels commanded speed.

Here is where the profiling became a problem. The formula gave an instantaneous result for course correction, but for larger turning problems, which occur when the robot reaches a way point and then has to make for another, say, 90 degrees from the original heading, the differential between the wheels would be delayed by the profiling. Consequently, the robot would build up angular momentum, and shoot past the desired heading, and thereby reversing the inside vs. the outside wheel. The result was an unpleasant "waggle" around the new course line.

The problem was solved by setting a maximum differential allowed between the two tires, essentially a limit on angular rotation. The difference between the two wheels was measured against the commanded rotation. If the difference was greater than the commanded rotation, then both wheels were slowed. Slowing down for a corner is a very reasonable and pleasing response. This deceleration of both wheels continued until the outside wheel was at one half of the commanded velocity, which means on a hard turn, the cosine result would command the inside wheel to turn backwards at the same rate as the outside wheel.

In short, the robot would do a decelerated curve into a radial spin (turn on central axis), if its target point changed radically. Yet, when the new heading was approached, the gained-cosine result would lessen, and then become positive, gradually. The limited commanded rotation meant the difference the inside tire had to regain was not so far as to cause overshoot. The inside wheel could soon "catch" the outside wheel and hold the new heading.

While the individual wheels are PID controlled, and the steering manages them by controlling the profiling above the PID routine, and the steering response is more P than PID, I like this algorithm. Given any point to drive to, and a change to any other point, this algorithm will produce smooth and accurate turning to, and then steering to, the new point.

Hope someone finds this helpful or interesting. Feel free to comment.

Reply to
Randy M. Dumse

Thanks for posting that. There are many who willingly take advice from this group, but few who come back and present the result of that advice.

Reply to
Garrett Mace

: Hope someone finds this helpful or interesting. Feel free to comment.

I'ld be interested to see the code that you used to do this, if you can make it available. This sounds like something where the code is simpler than trying to describe it !

-Chris

Reply to
Christopher X. Candreva

Maybe, but I suppose not too many will be able to read the Forth procedural part of this IsoMax(TM) thread, so I'll heavily comment it and you can tell me if it makes any sense then.

: STEER-ADJUST ( Get outside wheel pointer for indexed variable CHO

( Get outside wheel velocity out of indexed variable ( store in easy access variable CURVEL 2@ OUTVEL 2!

( get vel conv to float, leave on stack for later ( get relative bearing of target point ( multiply by steering gain OUTVEL 2@ D>F RELBEARING F@ Ksteer F*

( limit result to normal angle range from -pi to +pi -PI FMAX PI FMIN

( convert angle to cosine value ( mutiply cosine value times outside wheel velocity ( and store diminished value in the inside wheel velocity var FCOS F* F>D INSVEL 2!

( get command rotation limit ( get outside wheel velocity and inside wheel velocity variables ( subtract the wheel velocities to find difference ( and take the absolute value of the difference ( and see if that difference is larger than command rotation limit CMDROT 2@ OUTVEL 2@ INSVEL 2@ D- DABS DU<

IF

( Get the outside wheel velocity ( Get that channels command acceleration value ( and subtract it, so as to decelerate the outside wheel OUTVEL 2@ CHO CMDACC 2@ D- ( PREPARE DECELERATION

( Get the command rotation limit and divide in half ( take the max value between half/rot and decelerated value CMDROT 2@ D2/ DMAX ( BUT ONLY TO HALF ROT MAX

( Store in outside wheel velocity variable OUTVEL 2!

( Get outside wheel velocity variable ( and subtract command rotation limit from it ( and store the result in the inside wheel velocity variable OUTVEL 2@ CMDROT 2@ D- INSVEL 2!

ELSE

( Set outside wheel velocity var for full body speed ( and profiling will take from here up to there BODVEL 2@ OUTVEL 2!

THEN

( Get inside wheel velocity out of easy access variable ( store in indexed variable INSVEL 2@ CHI CMDVEL 2!

( Get outside wheel velocity out of easy access variable ( store in indexed variable OUTVEL 2@ CHO CMDVEL 2! ; EEWORD

And for interest sake, here's the same code in original format without the extra comments.

: STEER-ADJUST CHO CURVEL 2@ OUTVEL 2! OUTVEL 2@ D>F RELBEARING F@ Ksteer F* -PI FMAX PI FMIN FCOS F* F>D INSVEL 2! CMDROT 2@ OUTVEL 2@ INSVEL 2@ D- DABS DU< IF OUTVEL 2@ CHO CMDACC 2@ D- ( PREPARE DECELERATION CMDROT 2@ D2/ DMAX ( BUT ONLY TO HALF ROT MAX OUTVEL 2! OUTVEL 2@ CMDROT 2@ D- INSVEL 2! ELSE BODVEL 2@ OUTVEL 2! THEN INSVEL 2@ CHI CMDVEL 2! OUTVEL 2@ CHO CMDVEL 2! ; EEWORD

Reply to
Randy M. Dumse

PolyTech Forum website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.