I am trying to control the Rover 5 robot using an Android app with a touch-based joystick control in the app UI. I want to calculate the speed of the left and right motors in the rover when joystick is moved.

From the joystick, I get two values, pan and tilt. I convert them into the polar coordinate system with r and theta. Where r ranges from 0 to 100 and theta from 0 to 360. I want to derive an equation which can convert the (r, theta) to (left_speed, right_speed) for rover. The speed values also are in the [0;100] range.

Now, here is what I have figured out till now. For any value of r,

If theta = 0 then left_speed = r, right_speed = -r (turning right on spot)
If theta = 90 then left_speed = r, right_speed = r (moving forward at speed r)
If theta = 180 then left_speed = -r, right_speed = r (turning left on spot)
If theta = 270 then left_speed = -r, right_speed = -r (moving backwards at speed r)

For other values, I want it moving and turning simultaneously. For example,

If theta = 45 then left_speed = alpha*r, right_speed = beta*r (moving forward while turning right)

So, basically for any (r, theta), I can set speeds as,

(left_speed, right_speed) = (alpha*r, beta*r)

I need to formulate an equation where I can generalize all these cases by finding alpha and beta based on theta.

How can I do this? Is there is any existing work I can refer to?

  • $\begingroup$ I assume you mean "If theta = 180 then left_speed = -r..." $\endgroup$ Commented Nov 2, 2013 at 0:50
  • $\begingroup$ Yes, thanks for pointing it out. Edited the question $\endgroup$
    – Punit Soni
    Commented Nov 2, 2013 at 1:14

2 Answers 2


You're trying to find a formula to convert a given $(r, \theta)$ to left and right thrust percentages, where $r$ represents your throttle percentage. The naive implementation is to base your function on 100% throttle:

  • At $0 ^{\circ}$, left and right thrust are equal to $r$
  • At $\pm45 ^{\circ}$, one side's thrust equals $r$ and the other side's equals 0
  • At $\pm 90 ^{\circ}$, one side's thrust equals $r$ and the other side's equals $-r$
  • At $180 ^{\circ}$, left and right thrust are equal to $-r$

This produces a function like the following:

Thrust ratios for 100% throttle

The problem with this implementation is that you are only providing the desired $r$ when $\theta$ is at an exact multiple of $90 ^{\circ}$. At all other points, you sacrifice total speed for control. You can see this in the graph: "Absolute Thrust", the amount of thrust being delivered by both motors, is not (and cannot be) constant in this regime. Simply scaling this function is not optimal.

The maximum absolute thrust that can be sustained over the entire range of $\theta$ occurs when $r=50\%$ -- this is what your function should be based on.

Thrust ratios for 100% throttle

In this implementation, total thrust remains constant between $\pm45 ^{\circ}$, and absolute thrust is constant no matter what direction is chosen -- the motors trade off their thrust to maintain the desired $r$. Above $r=50\%$, the range of angles where your total thrust can satisfy $r$ begins to shrink -- you begin to sacrifice control for speed.

This produces a python function like the following:

# assumes theta in degrees and r = 0 to 100 %
# returns a tuple of percentages: (left_thrust, right_thrust)
def throttle_angle_to_thrust(r, theta):
    theta = ((theta + 180) % 360) - 180  # normalize value to [-180, 180)
    r = min(max(0, r), 100)              # normalize value to [0, 100]
    v_a = r * (45 - theta % 90) / 45          # falloff of main motor
    v_b = min(100, 2 * r + v_a, 2 * r - v_a)  # compensation of other motor
    if theta < -90: return -v_b, -v_a
    if theta < 0:   return -v_a, v_b
    if theta < 90:  return v_b, v_a
    return v_a, -v_b

The result is the following: animated right/left function

  • $\begingroup$ Thanks Ian. As far as I understood, you are trying to balance the loads on both motors, right? $\endgroup$
    – Punit Soni
    Commented Nov 3, 2013 at 8:12
  • $\begingroup$ Not quite. You are trying to make $(\text{left_speed} + \text{right_speed}) / 2 = r$, instead of having it be dependent on $\theta$. Notice that when $r > 50\%$, the dotted purple line is no longer constant with respect to $\theta$. You want to minimize this effect. $\endgroup$
    – Ian
    Commented Nov 3, 2013 at 17:13
  • 2
    $\begingroup$ How did you make those fancy plots? $\endgroup$ Commented Nov 4, 2013 at 14:45
  • $\begingroup$ I did the plots in Microsoft Excel and produced the animation in Gimp. $\endgroup$
    – Ian
    Commented Nov 4, 2013 at 22:01
  • 1
    $\begingroup$ After translating this function to my language (C#) I was getting unexpected results. I found out the modulus operator might behave differently in some languages. I.E. in C# I was getting negative values for, e.g. -10 % 90 = -10, whereas in other languages (e.g. Excel) it would return 80 for -10. So to fix this just check if your modulus returns less than zero then add 90 to it. $\endgroup$ Commented Sep 10, 2018 at 13:58

What you want is angular velocity proportional to the cosine of the angle, it seems, with positive to the right, and negative to the left.

So, since we know that angular velocity is given by $\frac{V_l - V_r}{D}$ where $D$ is the diameter of the robot, we're all set. Try this:

if $\theta\ge0$ and $\theta\le90$: $V_l \gets r$ and $V_r \gets r\sin(2\theta-90)$

if $\theta < 0$ and $\theta\geq-90$: $V_r \gets -r$ and $V_l \gets r\sin(2\theta+90)$

Swap the velocities for the other quadrants. Note, this won't "feel" like driving a car, as moving the stick to the lower-right will turn backwards and rotate right, whereas a car in reverse with the wheel right will move backwards and turn leftward. Just a weirdness of differential drives... You can adjust for this by just applying the fourth quadrant rules to the third quadrant $\theta$ and visa-versa.

I used $\theta \in [-180,+180]$, which you can get by:

$\theta \gets \text{atan2}(\sin\theta,\cos\theta)$ (watch your units though, atan2 is usually radians.

  • $\begingroup$ This look pretty good. I arrived to this solution thinking intuitively. I will give this a try and see how it actually feels when driveing. Thanks. $\endgroup$
    – Punit Soni
    Commented Nov 5, 2013 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.