Ask Your Question

Differential Drive calculation

asked 2018-01-05 09:30:42 -0500

cerebraldad gravatar image

Thanks in advance for you help guys.

I've been fiddling with ROS for quite a few months now and I have a good basic understanding of how to advertise and subscribe to nodes, I even built a speech action!

I am, however, very confused on how to translate Twist messages into movement on an actual robot. In the Sim, robots just magically move :)

My plan is to use an arduino to send signals to a Sabertooth 2x25 which has the ability to accept analog linear (0V-5V), Servo signal (1000us-2000us), Simplified Serial (1-255 and some combination controls both motors) and Serial at 38400 baud - which i completely don't understand...

My understanding is the Twist msg contains linear and angular values for all 3 axis and in order to use these some trig. calculations - in some relation to the wheel base width - will allow the robot move using the left and right motors independently. I dont understand the math here...

I currently have a sketch that takes the "cmd_vel" topic and maps a value (-1 to 1) to (0 to 180) from "linear.x" to move a servo using a node that publishes from the keyboard.

I need some direction, because I want to use a Twist topic for both autonomous movement and remote teleop (rc transmitter) input.

I found the "differential drive", "simple drive" and a few other packages - but I fail to see how they help since they publish to a twist topic and I cant seem to find any documentation on how to utilize these messages.

Does anyone have a secret decoder ring?

Thank you, Keith

edit retag flag offensive close merge delete


Do you have any encoders on your wheels to measure the current speed? Also I recommend my answer in

Humpelstilzchen gravatar image Humpelstilzchen  ( 2018-01-08 02:25:04 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted

answered 2018-01-05 11:05:01 -0500

The twist message uses m/s for linear velocity units and radians/s for the angular velocity units.

You'll need to do a bit of trial and error to find out the ratio between these units and the values you need to pass to the motor controllers to make the robot move at approximately the right speed.

The linear movement is the easiest simply multiply the x linear velocity by the linear ratio (which you'll need to find through experimentation) and set each wheel to this speed. There's a good chance you'll need to negate one since one wheel motor will be a 180 degree rotation of the other, so depending on the controller one may need to be backwards for the robot to move forwards in a straight line.

The angular movement is almost exactly the same except you need to find a different ratio, between rads/sec and control output and make sure the wheels turn in opposite directions.

Simply add the angular and linear speeds for each wheel together to get the final speed.

Finally, there is obviously a maximum speed that the robots wheels can turn and twist messages can easily exceed this. If you scale both wheel velocities down by the same ratio so that they are within the range the motors are capable of then the robot will follow the same trajectory as commanded to by the twist message but at a lower speed.

It's actually fairly simple (no trig required) although you'll need to find the ratios for your particular robot to get the control outputs to accurately reflect the twist commands.

edit flag offensive delete link more


Shouldn't "find out the ratio" be "calculate the appropriate conversion factor based on wheel diameter and gear ratios for your setup"?

I get why you write what you do (to compensate for any slippage or friction), but it would perhaps be better to compensate for that after conversion, not during.

gvdhoorn gravatar image gvdhoorn  ( 2018-01-05 11:08:09 -0500 )edit

And should "scaling the wheel velocities down" be "clamp the wheel velocities"? Scaling, though typically linear, would deviate from the semantics of the Twist message: its fields use SI units so that users can assume certain things. Scaling would seem to make that impossible?

gvdhoorn gravatar image gvdhoorn  ( 2018-01-05 11:09:56 -0500 )edit

Other than that, +1 though.

gvdhoorn gravatar image gvdhoorn  ( 2018-01-05 11:10:35 -0500 )edit

I agree scaling deviates from the commanded behaviour of the twist message, I guess the question is how do you want your robot to respond if commanded to do something it's not physically capable of?

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-01-05 12:18:47 -0500 )edit

Clamping the wheel velocities would result in the direction and velocity being different from the twist command, scaling them would result in the direction being correct but the velocity being wrong. This would seem like a more graceful degradation, what are your thoughts?

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-01-05 12:19:54 -0500 )edit

Is this sort of "reinventing the wheel"? (pun intended) - I find it hard to believe there isn't a package or script for this...

cerebraldad gravatar image cerebraldad  ( 2018-01-05 12:27:53 -0500 )edit

In part it is definitely re-inventing the wheel, but a generic node to do this would need to be able to interface with whatever controls to motors. There is such a variety here it's probably not worth a node. A ros library function for this would be a good idea though!

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-01-05 12:34:05 -0500 )edit

Google-ing just now I found something like this: ros_arduino_bridge what is everyone's thoughts on this - any insight?

cerebraldad gravatar image cerebraldad  ( 2018-01-05 12:38:46 -0500 )edit

answered 2018-01-05 15:58:41 -0500

You can find a basic implementation of sending motion commands to a Arduino with motor shield here: . The approach taken uses joystick commands for linear and angular velocities (both axes scaling from -1 to 1) here, computes a left and right motor command (still on the "ROS side") and then sends commands for both motors to the Arduino using the DiffDriveCommand message over to the Arduino via rosserial. This command is then applied here in the Arduino side code.

The problem with very basic setups that only use simple motor drivers and no encoders is that you can only command open loop PWM to motors and you cannot control the motor (and hence wheel) velocity, so making the robot actually accurately follow velocities you might compute is not trivial (this is why the above mentioned example uses just joystick commands between min and max "effort"). You can of course experimentally determine how fast the robot goes for different PWM values, but will change with ground and wheel types, payload and all sorts of other factors. That being said, actually calculating desired velocities is relatively simple and this PDF appears to provide a pretty good overview of how to do it.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools



Asked: 2018-01-05 09:30:42 -0500

Seen: 2,706 times

Last updated: Jan 05 '18