EVNDrivebase#

Building upon the functionality provided by EVNMotor, EVNDrivebase provides functions useful for controlling differential drive robots.

Note

EVNDrivebase consumes some of the RP2040’s spinlock peripherals. See this page for more info.

Note

EVNDrivebase uses the 2nd core to perform internal updates at a high rate. Between updates, user code can run on the 2nd core, but this configuration may cause timing-sensitive code to fail or lead to unexpected behaviour.

Constructor#

EVNDrivebase(float wheel_dia, float axle_track, EVNMotor* motor_left, EVNMotor* motor_right);
Parameters
  • wheel_dia – Diameter of each wheel (in mm)

  • axle_track – Distance between midpoint of both wheels (in mm)

  • motor_left – Pointer to EVNMotor object for left motor

  • motor_right – Pointer to EVNMotor object for right motor

EVNMotor left_motor(1, EV3_MED);
EVNMotor right_motor(2, EV3_MED, REVERSE);

//wheel diameter - 62.4mm, axle track - 178mm
EVNDrivebase db(62.4, 178, &left_motor, &right_motor);

Note

For those new to C++, pointers can be quite confusing! Think of & as a means for you to provide a link to an object. Here, we pass a link to EVNMotor objects to our EVNDrivebase object, so that it can control the EVNMotor objects for us.

Functions#

void begin();

Initializes drivebase object. Call this function after calling begin() on the EVNMotor objects (which still need to be called!), but before calling any other EVNDrivebase functions (including settings functions).

EVNMotor left_motor(1, EV3_MED);
EVNMotor right_motor(2, EV3_MED, REVERSE);
EVNDrivebase db(62.4, 178, &left_motor, &right_motor);

void setup1()
{
    left_motor.begin();
    right_motor.begin();
    db.begin();
}

Note

EVNDrivebase should be initialized on the 2nd core by calling begin() in void setup1(). However, you can still call the other functions on both cores. We recommend setting drivebase parameters on the 2nd core, while leaving movement to the main core.

Measurements#

float getDistance()
Returns

Distance travelled by drivebase (in mm)

float distance = db.getDistance();
float getAngle()
Returns

Angle turned by drivebase (in deg)

float angle = db.getAngle();
float getHeading()
Returns

Drivebase heading (ranging from 0-360 degrees)

float heading = db.getHeading();
float getX()
Returns

X coordinate of drivebase from origin (origin is the drivebase’s position on startup)

float x = db.getX();
float getY()
Returns

Y coordinate of drivebase from origin (origin is the drivebase’s position on startup)

float y = db.getY();
void resetXY();

Sets drivebase’s current position to be the origin (0, 0).

db.resetXY();
//afterwards, getX() and getY() will return 0
float getDistanceToPoint(float x, float y);
Returns

Euclidean distance between drivebase’s XY position and target XY point

//if drivebase is at origin, the distance to point will be 4
float distance_to_point = db.getDistanceToPoint(3,2);
float getMaxSpeed()
Returns

Maximum speed of drivebase (in mm/s)

float getMaxTurnRate()
Returns

Maximum turning rate of drivebase (in deg/s)

Move Forever#

void drive(float speed, float turn_rate, bool disable_accel_decel = false);
void driveTurnRate(float speed, float turn_rate, bool disable_accel_decel = false);

Runs drivebase at the given speed and turn rate until a new command is called

Parameters
  • speed – Velocity of drivebase (in mm/s)

  • turn_rate – Turning rate of drivebase (in deg/s)

  • disable_accel_decel – Disables acceleration and deceleration control. Defaults to false

//drive at a velocity of 50mm/s and turning rate of 5deg/s
db.drive(50, 5);
void driveRadius(float speed, float radius, bool disable_accel_decel = false);

Runs drivebase at the given speed and radius of turning until a new command is called

Parameters
  • speed – Velocity of drivebase (in mm/s)

  • radius – Turning radius of drivebase (in mm)

  • disable_accel_decel – Disables acceleration and deceleration control. Defaults to false

//drive at a velocity of 50mm/s and move in an arc of radius 50mm
db.driveRadius(50, 50);
void drivePct(float speed_outer_pct, float turn_rate_pct, bool disable_accel_decel = true)

This function simulates a differential drive function where the outer wheel speed is given as a percentage, along with a “turning rate” percentage input to define the turning behaviour as described below:

0% “turning rate”: Both wheels run at speed_outer_pct, same direction 50% “turning rate”: One wheel stationary, other wheel runs at speed_outer_pct (one-wheel turn) 100% “turning rate”: Both wheels run at speed_outer_pct, but in opposite directions

Positive turning rate values turn anti-clockwise, negative values turn clockwise.

Since the inputs range from -100 to 100 (unlike driveRadius, where radius ranges to infinity), it can be easier to use this function for PID control.

Parameters
  • speed_outer_pct – Speed for outer (faster) wheel in % (number from -100 to 100)

  • turn_rate_pct – Turning rate of drivebase in % (number from -100 to 100)

  • disable_accel_decel – Disables acceleration and deceleration control. Defaults to true

//drive forwards at 100% speed
db.drivePct(100, 0);
//drive forwards at 50% speed
db.drivePct(50, 0);
//drive backwards at 100% speed
db.drivePct(-100, 0);
//one-wheel clockwise turn at full speed
db.drivePct(100, 50);
//rotate clockwise on the spot at full speed
db.drivePct(100, 100);

Move by a Fixed Amount#

void straight(float speed, float distance, uint8_t stop_action = STOP_BRAKE, bool wait = true);

Runs drivebase in a straight line for the specified distance, then performs given stop action.

Drivebase speed direction is reversed when the speed or distance inputs are negative (e.g. straight(100, -100), straight(-100, 100), or straight(-100, -100) will all move the drivebase backwards).

Parameters
  • speed – Velocity of drivebase (in mm/s)

  • distance – Distance to travel (in mm)

  • stop_action

    Behaviour of the motor upon completing its command. Defaults to STOP_BRAKE

    • STOP_BRAKE – Brake (Slow decay)

    • STOP_COAST – Coast (Fast decay)

    • STOP_HOLD – Hold position

    • STOP_NONE – Continue running at current speed (and deceleration to a stop removed)

  • wait – Block function from returning until command is finished

//move in a straight line at a velocity of 50mm/s for a distance of 50mm
db.straight(50, 50);
void curve(float speed, float radius, float angle, uint8_t stop_action = STOP_BRAKE, bool wait = true);
void curveRadius(float speed, float radius, float angle, uint8_t stop_action = STOP_BRAKE, bool wait = true);

Runs drivebase in a curve of specified radius until its heading has shifted by the given angle, then performs given stop action.

Drivebase turning direction is reversed when the radius or angle inputs are negative (e.g. curve(100, 100, -100), curve(100, -100, 100), or curve(100, -100, -100) will all use a negative (clockwise) turning rate).

Parameters
  • speed – Velocity of drivebase (in mm/s)

  • radius – Turning radius of drivebase (in mm)

  • angle – Angle to travel by (in deg)

  • stop_action

    Behaviour of the motor upon completing its command. Defaults to STOP_BRAKE

    • STOP_BRAKE – Brake (Slow decay)

    • STOP_COAST – Coast (Fast decay)

    • STOP_HOLD – Hold position

    • STOP_NONE – Continue running at current speed (and deceleration to a stop removed)

  • wait – Block function from returning until command is finished

//drive at a velocity of 50mm/s in an arc of radius 50mm until the drivebase has rotated by 90 degrees
db.curve(50, 50, 90, STOP_BRAKE);
void curveTurnRate(float speed, float turn_rate, float angle, uint8_t stop_action = STOP_BRAKE, bool wait = true);

Runs drivebase at given speed and turn rate until its heading has shifted by the given angle, then runs specified stop action

Drivebase turning direction is reversed when the turn_rate or angle inputs are negative (e.g. curveTurnRate(100, 100, -100), curveTurnRate(100, -100, 100), or curveTurnRate(100, -100, -100) will all use a negative (clockwise) turning rate).

Parameters
  • speed – Velocity of drivebase (in mm/s)

  • turn_rate – Turning rate of drivebase (in deg/s)

  • angle – Angle to travel by (in deg)

  • stop_action

    Behaviour of the motor upon completing its command. Defaults to STOP_BRAKE

    • STOP_BRAKE – Brake (Slow decay)

    • STOP_COAST – Coast (Fast decay)

    • STOP_HOLD – Hold position

    • STOP_NONE – Continue running at current speed (and deceleration to a stop removed)

  • wait – Block function from returning until command is finished

//drive at a velocity of 50mm/s at a turning rate of 5deg/s until the drivebase has rotated by 90 degrees
db.curveTurnRate(50, 5, 90, STOP_BRAKE);
void turn(float turn_rate, float degrees, uint8_t stop_action = STOP_BRAKE, bool wait = true);
void turnDegrees(float turn_rate, float degrees, uint8_t stop_action = STOP_BRAKE, bool wait = true);

Rotate drivebase on the spot by the given angle, then performs given stop action

Parameters
  • turn_rate – Turning rate of drivebase (in deg/s)

  • angle – Angle to travel by (in deg)

  • stop_action

    Behaviour of the motor upon completing its command. Defaults to STOP_BRAKE

    • STOP_BRAKE – Brake (Slow decay)

    • STOP_COAST – Coast (Fast decay)

    • STOP_HOLD – Hold position

    • STOP_NONE – Continue running at current speed (and deceleration to a stop removed)

  • wait – Block function from returning until command is finished

//rotate at a rate of 5deg/s until the drivebase has rotated by 90 degrees
db.turn(5, 90, STOP_BRAKE);
void turnHeading(float turn_rate, float heading, uint8_t stop_action = STOP_BRAKE, bool wait = true);

Rotate drivebase on the spot to the given heading, then performs given stop action

Parameters
  • turn_rate – Turning rate of drivebase (in deg/s)

  • heading – Heading to travel to (in deg)

  • stop_action

    Behaviour of the motor upon completing its command. Defaults to STOP_BRAKE

    • STOP_BRAKE – Brake (Slow decay)

    • STOP_COAST – Coast (Fast decay)

    • STOP_HOLD – Hold position

    • STOP_NONE – Continue running at current speed (and deceleration to a stop removed)

  • wait – Block function from returning until command is finished

//rotate at a rate of 5deg/s (or -5deg/s) until the drivebase has a heading of 90degrees
db.turnHeading(5, 90, STOP_BRAKE);
bool completed();
Returns

Boolean indicating whether the drivebase’s command has reached completion

//wait until drivebase has completed its command
while (!db.completed());

Move to Point#

void driveToXY(float speed, float turn_rate, float x, float y, uint8_t stop_action = STOP_BRAKE, bool restore_initial_heading = true);

Rotates drivebase to face target XY position, drives forward to target, and rotates back to original heading

Parameters
  • speed – Velocity of drivebase (in mm/s)

  • turn_rate – Turning rate of drivebase (in deg/s)

  • x – X coordinate of target

  • y – Y coordinate of target

  • stop_action

    Behaviour of the motor upon completing its command. Defaults to STOP_BRAKE

    • STOP_BRAKE – Brake (Slow decay)

    • STOP_COAST – Coast (Fast decay)

    • STOP_HOLD – Hold position

    • STOP_NONE – Continue running at current speed (and deceleration to a stop removed)

  • wait – Block function from returning until command is finished

//drive to point (60, 60) at a velocity of 100mm/s and turning rate of 50deg/s
db.driveToXY(100, 50, 60, 60, STOP_BRAKE);

Note

This feature is experimental! And also, it’s pretty much a party trick. Its behaviour may be changed in future versions.

Stopping#

void stop()

Brakes both drivebase motors (slow decay).

db.stop();
void coast()

Coasts both drivebase motors to a stop (fast decay). Compared to braking with stop(), the drivebase comes to a stop more slowly.

db.coast();
void hold()

Hold drivebase motors in their current positions. Restricts the motor shafts from moving.

db.hold();

Control Settings#

To view the default accel/decel values, look at src\evn_motor_defs.h in the Github repository.

The PD values for the speed and turn rate controllers are obtained from the motor objects linked to drivebase.

If both motors are the same motor type, then the EVNMotor PD value for that motor type will be used by default. Otherwise, the CUSTOM_MOTOR PD values are used.

void setSpeedKp(float kp);

Sets proportional gain values for the speed controller (controls average drivebase speed).

The error for the controller is the difference between the robot’s target distance travelled and the robot’s current distance travelled (in motor degrees).

Parameters

kp – Proportional gain

db.setSpeedKp(20);
void setSpeedKd(float kd);

Sets derivative gain values for the speed controller (controls average drivebase speed).

The error for the controller is the difference between the robot’s target distance travelled and the robot’s current distance travelled (in motor degrees).

Parameters

kd – Derivative gain

db.setSpeedKd(0.2);
void setTurnRateKp(float kp);

Sets proportional gain values for the turn rate controller (controls rate of turning of drivebase).

The error for the controller is the difference between the robot’s target angle and the robot’s current angle (in motor degrees).

This controller serves 2 purposes: to ensure the drivebase turns at the correct rate, and to stop either motor if the other is stalled, syncing their movement.

Parameters

kp – Proportional gain

db.setTurnRateKp(20);
void setTurnRateKd(float kd);

Sets derivative gain values for the turn rate controller (controls rate of turning of drivebase).

The error for the controller is the difference between the robot’s target angle and the robot’s current angle (in motor degrees).

This controller serves 2 purposes: to ensure the drivebase turns at the correct rate, and to stop either motor if the other is stalled, syncing their movement.

Parameters

kd – Derivative gain

db.setTurnRateKd(0.2);
void setSpeedAccel(float accel_mm_per_s_sq);

Sets speed acceleration value for drivebase (in mm/s^2).

Parameters

accel_mm_per_s_sq – Acceleration in mm/s^2

db.setSpeedAccel(500);
void setSpeedDecel(float decel_mm_per_s_sq);

Sets speed deceleration value for drivebase (in mm/s^2).

Parameters

decel_mm_per_s_sq – Deceleration in mm/s^2

db.setSpeedDecel(500);
void setTurnRateAccel(float accel_deg_per_s_sq);

Sets turn rate acceleration value for drivebase (in deg/s^2).

Parameters

accel_deg_per_s_sq – Acceleration in deg/s^2

db.setTurnRateAccel(500);
void setTurnRateDecel(float decel_deg_per_s_sq);

Sets turn rate deceleration value for drivebase (in deg/s^2).

Parameters

decel_deg_per_s_sq – Deceleration in deg/s^2

db.setTurnRateDecel(500);
void setDebug(uint8_t debug_type)

Used to toggle debug mode, where drivebase will print the error for either speed or turn rate PD control over Serial. Can be used to observe or tune PD controller behaviour.

Parameters

debug_type

Type of debug mode to run

  • DEBUG_OFF

  • DEBUG_SPEED

  • DEBUG_TURN_RATE