Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
diffdrive Namespace Reference

Namespace containing algorithms related to calculating drive powers, odometry, trajectories, kinematics, etc of differential drive (tank drive) robots. More...

Classes

struct  DrivePowers
 This struct is used to store the left and right drive powers for the robot. Storing these values in a struct allows for easy handling and access to said variables. More...
 

Enumerations

enum class  DifferentialControlMethod { eArcadeDrive , eCurvatureDrive }
 

Functions

DrivePowers CalculateTankDrive (double dLeftSpeed, double dRightSpeed, bool bSquareInputs=false)
 Tank drive inverse kinematics for differential drive robots.
 
DrivePowers CalculateArcadeDrive (double dSpeed, double dRotation, const bool bSquareInputs=false)
 Arcade drive inverse kinematics for differential drive robots.
 
DrivePowers CalculateCurvatureDrive (double dSpeed, double dRotation, const bool bAllowTurnInPlace, const bool bSquareInputs=false)
 Curvature drive inverse kinematics for differential drive robots. The rotation parameter controls the curvature of the robot's path rather than it's rate of heading change. This makes the robot more controllable at high speeds.
 
DrivePowers CalculateMotorPowerFromHeading (double dGoalSpeed, double dGoalHeading, double dActualHeading, const DifferentialControlMethod eDriveMethod, controllers::PIDController &PID, const bool bSquareControlInput=false, const bool bCurvatureDriveAllowTurningWhileStopped=true)
 This function will calculate the drive powers for a given speed and absolute heading. The method used to get the drive powers is determined by the given enumerator (must be arcade or curvature). The turning rate or curvature is determined by the given PID controller which must be properly configured.
 

Detailed Description

Namespace containing algorithms related to calculating drive powers, odometry, trajectories, kinematics, etc of differential drive (tank drive) robots.

Each drive function provides different inverse kinematic relations for a differential drive robot.

This library uses the NWU axes convention (North-West-Up as external reference in the world frame). The positive X axis points ahead, the positive Y axis points to the left, and the positive Z axis points up. Rotations follow the right-hand rule, so counterclockwise rotation around the Z axis is positive.

Inputs smaller then 0.02 will be set to 0, and larger values will be scaled so that the full range is still used. This deadband value can be changed with SetDeadband().

Referenced from: https://github.com/wpilibsuite/allwpilib/

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-09-21

Enumeration Type Documentation

◆ DifferentialControlMethod

enum class diffdrive::DifferentialControlMethod
strong
58 {
59 eArcadeDrive, // Typical drive control method for flightsticks. Uses speed and turn input to determine drive powers.
60 eCurvatureDrive // Similar to arcade drive with flightsticks, but the current turning speed of the robot is dampened when moving fast.
61 };

Function Documentation

◆ CalculateTankDrive()

DrivePowers diffdrive::CalculateTankDrive ( double  dLeftSpeed,
double  dRightSpeed,
bool  bSquareInputs = false 
)
inline

Tank drive inverse kinematics for differential drive robots.

Parameters
dLeftSpeed- The left drive power input for the drive. (-1.0 - 1.0)
dRightSpeed- The right drive power input for the drive. (-1.0 - 1.0)
bSquareInputs- Decreases the input sensitivity at low input speeds.
Returns
DrivePowers - The result drive powers. [left, right]
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-09-22
92 {
93 // Limit the input powers.
94 dLeftSpeed = std::clamp(dLeftSpeed, -1.0, 1.0);
95 dRightSpeed = std::clamp(dRightSpeed, -1.0, 1.0);
96
97 // Determine if we should square the inputs.
98 if (bSquareInputs)
99 {
100 // Square the inputs but keep the sign.
101 dLeftSpeed = std::copysign(dLeftSpeed * dLeftSpeed, dLeftSpeed);
102 dRightSpeed = std::copysign(dRightSpeed * dRightSpeed, dRightSpeed);
103 }
104
105 // Return result drive powers.
106 return {dLeftSpeed, dRightSpeed};
107 }
Here is the caller graph for this function:

◆ CalculateArcadeDrive()

DrivePowers diffdrive::CalculateArcadeDrive ( double  dSpeed,
double  dRotation,
const bool  bSquareInputs = false 
)
inline

Arcade drive inverse kinematics for differential drive robots.

Parameters
dSpeed- Speed at which the robot should drive forward/backward. Forward is positive. (-1.0 - 1.0)
dRotation- The rotation rate of the robot. Clockwise is positive. (-1.0 - 1.0)
bSquareInputs- Decreases the input sensitivity at low input speeds.
Returns
DrivePowers - The result drive powers. [left, right]
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-09-22
121 {
122 // Limit the input powers.
123 dSpeed = std::clamp(dSpeed, -1.0, 1.0);
124 dRotation = std::clamp(dRotation, -1.0, 1.0);
125
126 // Determine if we should square the inputs.
127 if (bSquareInputs)
128 {
129 // Square the inputs but keep the sign.
130 dSpeed = std::copysign(dSpeed * dSpeed, dSpeed);
131 dRotation = std::copysign(dRotation * dRotation, dRotation);
132 }
133
134 // Find the maximum possible value of throttle and turn along the vector that the speed and rotation is pointing.
135 double dGreaterInput = std::max(std::abs(dSpeed), std::abs(dRotation));
136 double dLesserInput = std::min(std::abs(dSpeed), std::abs(dRotation));
137 // If the biggest input is zero, then the wheel speeds should be zero.
138 if (dGreaterInput == 0.0)
139 {
140 // Return zero drive power output.
141 return {0.0, 0.0};
142 }
143
144 // Differential drive inverse kinematics for arcade drive.
145 double dLeftSpeed = dSpeed + dRotation;
146 double dRightSpeed = dSpeed - dRotation;
147 // Desaturate the input. Normalize to (-1.0, 1.0).
148 double dSaturatedInput = (dGreaterInput + dLesserInput) / dGreaterInput;
149 dLeftSpeed /= dSaturatedInput;
150 dRightSpeed /= dSaturatedInput;
151
152 // Return result drive powers.
153 return {dLeftSpeed, dRightSpeed};
154 }
Here is the caller graph for this function:

◆ CalculateCurvatureDrive()

DrivePowers diffdrive::CalculateCurvatureDrive ( double  dSpeed,
double  dRotation,
const bool  bAllowTurnInPlace,
const bool  bSquareInputs = false 
)
inline

Curvature drive inverse kinematics for differential drive robots. The rotation parameter controls the curvature of the robot's path rather than it's rate of heading change. This makes the robot more controllable at high speeds.

Parameters
dSpeed- Speed at which the robot should drive forward/backwards. Forward is positive. (-1.0, 1.0)
dRotation- The normalized curvature of the robot. Clockwise is positive. (-1.0, 1.0)
bAllowTurnInPlace- Whether or not forward input is required to turn. True makes this control exactly like a car.
bSquareInputs- Decreases the input sensitivity at low input speeds.
Returns
DrivePowers - The result drive powers. [left, right]
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-09-22
171 {
172 // Create instance variables.
173 double dLeftSpeed = 0.0;
174 double dRightSpeed = 0.0;
175
176 // Limit the input powers.
177 dSpeed = std::clamp(dSpeed, -1.0, 1.0);
178 dRotation = std::clamp(dRotation, -1.0, 1.0);
179
180 // Determine if we should square the inputs.
181 if (bSquareInputs)
182 {
183 // Square the inputs but keep the sign.
184 dSpeed = std::copysign(dSpeed * dSpeed, dSpeed);
185 dRotation = std::copysign(dRotation * dRotation, dRotation);
186 }
187
188 // Check if turn-in-place is allowed.
189 if (bAllowTurnInPlace && dSpeed <= 0.01)
190 {
191 // Differential drive inverse kinematics for curvature drive with turn while stopped.
192 dLeftSpeed = dSpeed + dRotation;
193 dRightSpeed = dSpeed - dRotation;
194 }
195 else
196 {
197 // Differential drive inverse kinematics for curvature drive.
198 dLeftSpeed = dSpeed + std::abs(dSpeed) * dRotation;
199 dRightSpeed = dSpeed - std::abs(dSpeed) * dRotation;
200 }
201
202 // Desaturate the input. Normalize to (-1.0, 1.0).
203 double dMaxMagnitude = std::max(std::abs(dLeftSpeed), std::abs(dRightSpeed));
204 if (dMaxMagnitude > 1.0)
205 {
206 dLeftSpeed /= dMaxMagnitude;
207 dRightSpeed /= dMaxMagnitude;
208 }
209
210 // Return result drive powers.
211 return {dLeftSpeed, dRightSpeed};
212 }
Here is the caller graph for this function:

◆ CalculateMotorPowerFromHeading()

DrivePowers diffdrive::CalculateMotorPowerFromHeading ( double  dGoalSpeed,
double  dGoalHeading,
double  dActualHeading,
const DifferentialControlMethod  eDriveMethod,
controllers::PIDController PID,
const bool  bSquareControlInput = false,
const bool  bCurvatureDriveAllowTurningWhileStopped = true 
)
inline

This function will calculate the drive powers for a given speed and absolute heading. The method used to get the drive powers is determined by the given enumerator (must be arcade or curvature). The turning rate or curvature is determined by the given PID controller which must be properly configured.

Parameters
dGoalSpeed- The goal speed for the robot.
dGoalHeading- The goal absolute heading for the robot. (0-360 degrees, CW positive.)
dActualHeading- The actual current heading of the robot.
eDriveMethod- The differential drive method to use for navigation. MUST NOT BE TANK.
PID- A reference to the PID controller to use for hitting the heading setpoint.
bSquareControlInput- Can provide smoother control at goal heading.
bCurvatureDriveAllowTurningWhileStopped- Allow DifferentialControlMethod::eCurvatureDrive to turn in-place.
Returns
DrivePowers - The resultant drive powers.
Note
This method does not support tank drive as a control method.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-10-19
242 {
243 // Create instance variables.
244 DrivePowers stOutputPowers;
245
246 // Get control output from PID controller.
247 double dTurnOutput = PID.Calculate(dActualHeading, dGoalHeading);
248
249 // Calculate drive powers from inverse kinematics of goal speed and turning adjustment.
250 switch (eDriveMethod)
251 {
252 case DifferentialControlMethod::eArcadeDrive:
253 {
254 // Based on our turn output, inverse-proportionally scale down our goal speed along a squared curve profile. This helps with pivot turns.
255 dGoalSpeed *= 1.0 - std::pow(dTurnOutput, 2);
256 // Calculate drive power with inverse kinematics.
257 stOutputPowers = CalculateArcadeDrive(dGoalSpeed, dTurnOutput, bSquareControlInput);
258 break;
259 }
260 case DifferentialControlMethod::eCurvatureDrive:
261 {
262 // Based on our turn output, inverse-proportionally scale down our goal speed along a squared curve profile. This helps with pivot turns.
263 dGoalSpeed *= 1.0 - std::pow(dTurnOutput, 2);
264 // Calculate drive power with inverse kinematics.
265 stOutputPowers = CalculateCurvatureDrive(dGoalSpeed, dTurnOutput, bCurvatureDriveAllowTurningWhileStopped, bSquareControlInput);
266 break;
267 }
268 default:
269 {
270 // Submit logger message.
271 LOG_ERROR(logging::g_qSharedLogger, "eTankDrive is not supported for the CalculateMotorPowerFromHeading() method!");
272 break;
273 }
274 }
275
276 // Return result powers.
277 return stOutputPowers;
278 }
double Calculate(const double dActual, const double dSetpoint)
Calculate the next control output given the current actual and a setpoint.
Definition PIDController.cpp:74
DrivePowers CalculateArcadeDrive(double dSpeed, double dRotation, const bool bSquareInputs=false)
Arcade drive inverse kinematics for differential drive robots.
Definition DifferentialDrive.hpp:120
This struct is used to store the left and right drive powers for the robot. Storing these values in a...
Definition DifferentialDrive.hpp:73
Here is the call graph for this function:
Here is the caller graph for this function: