Resources‎ > ‎

Exponential Drive Function

We created this RobotC function for our FTC robot because we wanted finer joystick control at slower speeds without needing to depress a button.
 
Try it out and see if your team likes it as much as we do.
 
 
Background:
 
Last year we had a button that would scale down or up drive motor power if a button was held down while operating the joysticks.  This was hard for our driver to do, and eventually she just gave up and operated continuously at a medium range with a maximum power of 75%.
 
Pushing a bowling ball up this year's "Bowled Over!" ramp meant we needed 100% power, but fine joystick control was also desired for picking up crates and balls.  So, we created a simple function that related joystick values to motor power.  First, we tried a squared relationship, but this was too abrupt.  Then we used RobotC's POW function to raise the joystick value to a power of 1.4.  Then we changed the way a typical dead-zone region worked around zero joystick values, to make it more appropriate for exponential values (basically we weren't moving for the first half of the joystick movement).
 
Note:  computers can't deal with raising negative values to non-integer powers, so we first take the absolute value (ABS) of the joystick values.  At the end we multiply everything by 1 or -1 using RobotC's SGN math function.
 
Instructions:
 
Place the following 3 variable definitions where you can access them easily for making adjustments based on your robot's characteristics and desired performance.

const int cJoyDead = 8;         // joystick range in which movement is considered accidental
const int cMotorMin = 15;       // minimum drive motor power
const float cDriveExp = 1.4;    // exponent for drive power calculations  (1 = linear, 2 = squared)
 
Then place the Exponential Drive function where your joystick handler can call it:
 
int expDrive (int joyVal, float driveExp, int joyDead, int motorMin)
  {
      int joyMax = 128 - joyDead;
      int joySign = sgn(joyVal);
      int joyLive = abs(joyVal) - joyDead;
      return joySign * (motorMin + ((100 - motorMin) * pow(joyLive, driveExp) / pow(joyMax, driveExp)));
  }
 
Finally, replace your current driving statements with the following code:
 
motor[yourLeftMotorName] =  -1 * expDrive(joystick.joy1_y1, cDriveExp, cJoyDead, cMotorMin);
motor[yourRightMotorName] = -1 * expDrive(joystick.joy1_y2, cDriveExp, cJoyDead, cMotorMin);
 
Note:  In the above statement, you redefine which end is the "front" of your robot by changing -1 to 1.