Cubic Mapping Controls

Remote-control hobbyists often use exponential control to drive their servos. Instead of linearly mapping controller inputs to servo positions, an exponential map dampens the response near the center zone of the controller, giving the operator finer control while still preserving full servo deflection.

This principle can be mimicked in RobotC, and used as a drive controller for your robot's wheelbase. Here is the classic cubic mapping function:

inline int cubicMap(int x)
{
       return ((((x*3)/25)*((x*3)/25)*((x*3)/25)/27 + x/2)*2)/3; 
}

This function maps [-127,127] \rightarrow [-127,127] along a cubic curve that
looks like this:

If you use this mapping to drive your wheelbase, you will have greater
control at slow speeds while still retaining full power at full stick
deflection.

Derivation

I wrote this function for the old PIC controllers, back before 32-bits and floating point operations were available. (If you're wondering what all the multiplies and divides are doing, they keep the integer operations from overflowing).

This was my problem specification:

  • Dampen response near center zone.
  • Keep full range ( map [-127,127] \rightarrow [-127,127] )
  • Minimize dead-zone.
I started with the simplest cubic function that fits the range: f(x) = x^3 / (127^2)
The problem with this is, it dampens a bit too severely: an input of 25 is required before the function attains a non-zero integral value. To decrease this deadzone, the basic cubic map can be averaged with a linear map. After tweaking the weights, I found that this arrangement has a deadzone of only +/- 3, and exhibits sufficient dampening:

 f(x) = \left(\frac{1}{127^2}\right) \left(\frac{1}{3} x^3 + \frac{2}{3} x\right)

The final function listed above is equivalent to this one, but with extra arithmetic to optimize for integer operations.