Wheeled robot kinematics
Simon Merrett wrote 03/28/2017 at 22:01 • 0 pointsI've motorised an indoor (lawn) bowls wheelchair (using geared steppers) and really struggled to find examples of control code for differential speed steering. I mainly looked to tracked robots for info on skid steering but the write-ups I found only really discussed stop-skid/slew-forward motion, rather than slowing/accelerating one side relative to the other. Any help or pointers gratefully received.
[edit] I've now published my first code for this on Github (https://github.com/SimonMerrett/StepperMobility). I make apologies for the state of it but it might help to have something to look at. I promise to try and tidy it up but I'm no coding expert.
Here's a link to the project that is the intended application for solutions to this request https://hackaday.io/project/20734-stepper-motorised-wheelchair
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
@Simon Merrett, excellent news then. We've got plenty of time to discuss how we arrange this next year.
Here's a teaser, though: https://hackaday.io/project/21343-control-of-a-vehicle-with-two-driving-wheels I thought I'd extend the work I started doing for the mousebot and ended up writing a long document discussing the control of a wheelchair. I hope some of this can be useful for you.
Regarding your question about the motor. If I'm not mistaken they typically used heavy DC motors with gearboxes in electric wheelchairs. In my view, the best option in the future would be synchronous motors (so-called brushless motors) with or without a gearbox (they can be designed to spin at low speeds). That would be the best choice in terms of weight and efficiency, totally win win. However, I imagine gearboxes in existing wheelchairs have lots of friction and probably make the wheelchair hard to move when the motors are off, which helps as a safety measure if the electric system fails when going downhill.
Are you sure? yes | no
In my view, the best option would be to use permanent magnet synchronous motors (so-called brushless motors). From the constructive point of view, they can be cheaper, lighter and more efficient. They can also be design to be direct-drive without gearbox, but I'm not sure if this is a feature you want in a wheelchair, I guess the friction of the gearbox can make the mechanism "less reversible", which can be good for safety.
Are you sure? yes | no
In this kinematic forward motion and turning can be combined by just adding the speeds per wheel. Linear motion is obviously achieved by both wheels turning the the same direction in the same speed. For turning the wheel chair 360° you have to move the outside wheel 2 * PI * track width further that the inner wheel. As the difference in circumference between two circles is linear to the difference in diameter but independent of the diameter itself you can have the turn rate as a difference in speed of the two wheels. If you do this difference by adding half of the value to the outside wheel and subtracting the other from the inner wheel you can turn on spot if the forward speed is zero. (If you want to turn around a different spot than the axle of the driven wheel you can add a small forward or back ward component.)
For faster vehicles it might be good to limit the turning rate with higher speeds. But I am not sure if this is really necessary here. But still your approach of using a factor for slowing down the inner wheel does the opposite: Increasing the turn rate with speed. That's probably a bad thing - although speed may be low enough to not result in problematic behaviour at "high" speeds. It still means you cannot turn on low speeds with suck for manoeuvring in tight spaces.
Are you sure? yes | no
The good thing of having a working prototype is that he can actually test some of that and see what is an actual problem and what is a potential problem but not a problem in practice.
Are you sure? yes | no
Thank you Florian. I didn't really explain my steering method that well - the joystick reading gets converted into an absolute velocity request on a scale. Each number on the scale relates to a timing interval in the acceleration array. If you push the joystick a little forward, the absolute velocity set point is take from the first value in the acceleration array. This is a large number so the counter results in a long delay between pulses and a low velocity. If the joystick is then pushed instantly forwards, the motor will stall if the magnetic field starts rotating at a much faster speed so it makes a note that the user wants to go faster and after some milliseconds, changes the counter match value to the next value in the acceleration array, which is smaller, so the pulses become more rapid and the rotation speeds up. After another period of waiting for the mechnical lag to be reduced, the controller checks to see if the user is still asking for a faster velocity and continues to adjust the counter match value up and down the acceleration array towards the target set by the joystick.
For steering, I have removed a fixed number from the set point on each side. This leads to a proportionally slower steering ratio at higher speeds. If I were at speed 6 of a 22 integer acceleration array and wanted to turn left, it would take e.g. 4 away from the left wheel (=2) and leave the right at 6. Now the right wheel is travelling a significantly higher rate than the left. If the speed is at 22 of 22, the left is travelling at speed 18 and the right at speed 22, which is a much closer range and results in a wide, smoother turn.
You mentioned you were on holiday in the strain wave gear project so I don't want to keep you from family or leisure but please not that I have posted my initial code (which works but I know it should be better) on Github at https://github.com/SimonMerrett/StepperMobility if you get a chance to look some time. Thank you again.
Are you sure? yes | no
I think you are doing too many things at once and separating concerns could help here (a lot). You should consider using a stepper library that already can do stuff like setting maximum acceleration.
At least you should separate stepper control from speed control. You should have code that determines the wanted speed for both wheels. This code should think in m/s. As I wrote before turning adds speed to one wheel and subtracts speed from the other. You may reduce the rate depending on the forward speed but you should not rely on some random calculation that just fits in conveniently.
You then need a component that translates the user set speed into the actual speed limiting acceleration and may be even change in acceleration. (This might be done by a feature rich stepper lib).
Only after that should you think about translating this into delay to the next step.
You could even think about using a full fetched CNC controller like grbl although I don't have any experience adopting it to such a direct drive application.
Are you sure? yes | no
One more comment on the kinematics. So there are two ways of doing this:
Have a car like steering where moving the "steering wheel" does nothing unless you actually move the vehicle. This is what your code does if I understand it correctly.
What I am suggesting is that moving the joystick left and right turns the wheel chair no matter whether it is moving forward or not. This is more like a (cheap) RC helicopter behaves. This has the benefit of being able to turn on the spot which is probably something you want to do in a wheel chair.
Are you sure? yes | no
Florian, I removed steering when in reverse because the rear pair of castor wheels would prevent the motion at low speed. This led to the tyres slipping. Steering is very tight at low forward speed, so the chair is pretty manoeuvrable. It would be good to have left and right steering without requiring a forward joystick input.
I did look at the accelstepper library and others but I wasn't sure if they allow you to set a target velocity to be achieved and then run continuously until given a new set point. They all seemed set up to deliver a fixed number of steps (which would take a variable time to execute at different velocities) so would be difficult to catch the end of with a non-blocking timer. Also couldn't see a way to interrupt the stepper pulse series.
Thanks for all your comments!
Are you sure? yes | no
For a smooth ride you should not only limit the acceleration (change in speed) but also limit the change of acceleration as acceleration is the force pushing and fast changes will feel bumpy.
Are you sure? yes | no
This type of steering is actually more common in robots than the skid steering, most "mouse bots" have the same kinematics. What are you trying to do? Do you need to translate some user input into a speed reference?
The analysis of the kinematics of this type of vehicle is relatively easy. The speed of the centre of each wheel is the rotational speed of the wheel multiplied by its radius. Once you know the speed of the centre of the two wheels the speed (both linear and rotational) of the wheelchair is fully defined. If you draw a diagram of speeds you can find the instantaneous center of rotation (youtube.com/watch?v=EMSP-5yAXrQ), by dividing one of the speeds by the distance to the centre of rotation you can find out the rotational speed of the wheel chair and by averaging the speeds of the two wheels you can find the speed of the centre of the wheelchair. Perhaps you can check these slides: https://www.slideshare.net/adorepump/introduction-to-robotics-presentation. Any course material on planar motion can useful (https://chess.eecs.berkeley.edu/eecs149/documentation/differentialDrive.pdf).
Are you sure? yes | no
Thank you for your reply!
My project is a motorised indoor bowls wheelchair [https://hackaday.io/project/20734-stepper-motorised-wheelchair], so yes I do need to translate user input (joystick position) into a speed command for each wheel.
I have functioning code for this project but I think it could be very much refined to improve the user experience. I am using geared stepper motors so I have to be careful not to allow the magnetic field rotation to increase or decrease too quickly or the motors will stall. In the most extreme case, that would also mean braking (which is based on the motor) would also be lost. The application is indoors on level surfaces and top speed is a slow walk, so I think the risk is acceptable as impact is low.
However, that means that an instantaneous request for max forward velocity cannot be immediately implemented and I am employing a counter that increases or decreases the current speed in controlled steps towards the set point, based on the latest demand reading from the joystick. The steering is done by converting the left-right joystick reading into a factor which makes the motor on the side to be steered towards aim for a lower set-point on the velocity curve array (that is used by the counter to time step pulses).
I've set up a Github account and will link to code soon, when I've worked out how to use the site.
Thanks again - will get into those links.
Are you sure? yes | no
I see. That's a very interesting project indeed. If it helps at all, I posted something here about the kinematics of a similar vehicle. The article and the material were tailored towards a specific spiral-drawing toy robot students had to design. There's a script I made to plan the speed commands of the two motors but it is not very handy. There's also a small document with the equations of motion and a brief explanation of where they come from. (https://hackaday.io/project/11837-very-basic-offline-path-planning-for-2-wheel-bots).
By the way, once you get the basics of this working, I suspect a good idea to make this cheaper (and lighter) in the future is to use DC or (even better) brushless (synchronous) motors rather than steppers.
If you are interested in getting additional -free- help next year, I think the topic of this project could be suitable for one of the 3rd year group projects our electrical engineering students do (I'm based in London). These run from April until late June, unfortunately we are sorted for this year. Please let me know what you think, we'd need to organise this around February or early March (ages from now).
Are you sure? yes | no
@adria.junyent-ferre thank you again. I think extra help would be welcome next year. A colleague has already suggested 3rd year engineering students would be good collaborators.
Did you have a particular alternative motor type or arrangement in mind? I'm interested but not sure what would be the most promising.
Are you sure? yes | no