Skip to content

Commit 4535e36

Browse files
committed
pbio/drivebase: Document module.
1 parent a7a3ac5 commit 4535e36

File tree

2 files changed

+216
-10
lines changed

2 files changed

+216
-10
lines changed

lib/pbio/doc/doxygen.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,6 +2129,8 @@ PREDEFINED = \
21292129
PBIO_CONFIG_DCMOTOR=1 \
21302130
PBIO_CONFIG_LIGHT=1 \
21312131
PBIO_CONFIG_LIGHT_MATRIX=1 \
2132+
PBIO_CONFIG_NUM_DRIVEBASES=1 \
2133+
PBIO_CONFIG_DRIVEBASE_SPIKE=1 \
21322134
PBIO_CONFIG_SERVO=1 \
21332135
PBIO_CONFIG_TACHO=1 \
21342136
PBIO_CONFIG_ENABLE_SYS \

lib/pbio/src/drivebase.c

Lines changed: 214 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,14 @@ static void drivebase_adopt_settings(pbio_control_settings_t *s_distance, pbio_c
8888
s_heading->speed_default = s_heading->speed_max / 3;
8989
}
9090

91-
// Get the physical and estimated state of a drivebase
91+
/**
92+
* Get the physical and estimated state of a drivebase in units of control.
93+
*
94+
* @param [in] db The drivebase instance
95+
* @param [out] state_distance Physical and estimated state of the distance.
96+
* @param [out] state_heading Physical and estimated state of the heading.
97+
* @return Error code.
98+
*/
9299
static pbio_error_t pbio_drivebase_get_state_control(pbio_drivebase_t *db, pbio_control_state_t *state_distance, pbio_control_state_t *state_heading) {
93100

94101
// Get left servo state
@@ -119,20 +126,43 @@ static pbio_error_t pbio_drivebase_get_state_control(pbio_drivebase_t *db, pbio_
119126
return PBIO_SUCCESS;
120127
}
121128

129+
/**
130+
* Stop the drivebase from updating its controllers.
131+
*
132+
* This does not physically stop the motors if they are already moving.
133+
*
134+
* @param [in] db The drivebase instance
135+
*/
122136
static void pbio_drivebase_stop_drivebase_control(pbio_drivebase_t *db) {
123137
// Stop drivebase control so polling will stop
124138
pbio_control_stop(&db->control_distance);
125139
pbio_control_stop(&db->control_heading);
126140
}
127141

142+
/**
143+
* Stop the motors used by the drivebase from updating its controllers.
144+
*
145+
* This does not physically stop the motors if they are already moving.
146+
*
147+
* @param [in] db The drivebase instance
148+
*/
128149
static void pbio_drivebase_stop_servo_control(pbio_drivebase_t *db) {
129150
// Stop servo control so polling will stop
130151
pbio_control_stop(&db->left->control);
131152
pbio_control_stop(&db->right->control);
132153
}
133154

134-
// This function is attached to a servo object, so it is able to
135-
// stop the drivebase if the servo needs to execute a new command.
155+
/**
156+
* Drivebase stop function that can be called from a servo.
157+
*
158+
* When a new command is issued to a servo, the servo calls this to stop the
159+
* drivebase controller and to stop the other motor physically.
160+
*
161+
* @param [in] drivebase Void pointer to this drivebase instance.
162+
* @param [in] clear_parent Unused. There is currently no higher
163+
* abstraction than a drivebase.
164+
* @return Error code.
165+
*/
136166
static pbio_error_t pbio_drivebase_stop_from_servo(void *drivebase, bool clear_parent) {
137167

138168
// Specify pointer type.
@@ -156,6 +186,16 @@ static pbio_error_t pbio_drivebase_stop_from_servo(void *drivebase, bool clear_p
156186
return pbio_dcmotor_coast(db->right->dcmotor);
157187
}
158188

189+
/**
190+
* Gets drivebase instance from two servo instances.
191+
*
192+
* @param [out] db_address Drivebase instance if available.
193+
* @param [in] left Left servo instance.
194+
* @param [in] right Right servo instance.
195+
* @param [in] wheel_diameter Wheel diameter in mm.
196+
* @param [in] axle_track Distance between wheel-ground contact points.
197+
* @return Error code.
198+
*/
159199
pbio_error_t pbio_drivebase_get_drivebase(pbio_drivebase_t **db_address, pbio_servo_t *left, pbio_servo_t *right, int32_t wheel_diameter, int32_t axle_track) {
160200

161201
// Can't build a drive base with just one motor.
@@ -232,6 +272,13 @@ pbio_error_t pbio_drivebase_get_drivebase(pbio_drivebase_t **db_address, pbio_se
232272
return PBIO_SUCCESS;
233273
}
234274

275+
/**
276+
* Stops a drivebase.
277+
*
278+
* @param [in] db Drivebase instance.
279+
* @param [in] on_completion Which stop type to use.
280+
* @return Error code.
281+
*/
235282
pbio_error_t pbio_drivebase_stop(pbio_drivebase_t *db, pbio_control_on_completion_t on_completion) {
236283

237284
// Don't allow new user command if update loop not registered.
@@ -260,10 +307,27 @@ pbio_error_t pbio_drivebase_stop(pbio_drivebase_t *db, pbio_control_on_completio
260307
return pbio_servo_stop(db->right, on_completion);
261308
}
262309

310+
/**
311+
* Checks if a drivebase is not yet at the position or time target.
312+
*
313+
* If the drivebase is holding position, it is not busy.
314+
*
315+
* @param [in] db The drivebase instance
316+
* @return True if still moving to target, false if not.
317+
*/
263318
bool pbio_drivebase_is_busy(pbio_drivebase_t *db) {
264319
return !pbio_control_is_done(&db->control_distance) || !pbio_control_is_done(&db->control_heading);
265320
}
266321

322+
/**
323+
* Updates one drivebase in the control loop.
324+
*
325+
* This reads the physical and estimated state, and updates the controller if
326+
* it is active.
327+
*
328+
* @param [in] db The drivebase instance
329+
* @return Error code.
330+
*/
267331
static pbio_error_t pbio_drivebase_update(pbio_drivebase_t *db) {
268332

269333
// If passive, then exit
@@ -322,6 +386,9 @@ static pbio_error_t pbio_drivebase_update(pbio_drivebase_t *db) {
322386
return pbio_servo_actuate(db->right, dif_actuation, sum_torque - dif_torque + feed_forward_right);
323387
}
324388

389+
/**
390+
* Updates all currently active (previously set up) drivebases.
391+
*/
325392
void pbio_drivebase_update_all(void) {
326393
// Go through all drive base candidates
327394
for (uint8_t i = 0; i < PBIO_CONFIG_NUM_DRIVEBASES; i++) {
@@ -335,6 +402,17 @@ void pbio_drivebase_update_all(void) {
335402
}
336403
}
337404

405+
/**
406+
* Starts the drivebase controllers to run by a given distance and angle.
407+
*
408+
* @param [in] db The drivebase instance.
409+
* @param [in] distance The distance to run by in mm.
410+
* @param [in] drive_speed The drive speed in mm/s.
411+
* @param [in] angle The angle to turn in deg.
412+
* @param [in] turn_speed The turn speed in deg/s.
413+
* @param [in] on_completion What to do when reaching the target.
414+
* @return Error code.
415+
*/
338416
static pbio_error_t pbio_drivebase_drive_relative(pbio_drivebase_t *db, int32_t distance, int32_t drive_speed, int32_t angle, int32_t turn_speed, pbio_control_on_completion_t on_completion) {
339417

340418
// Don't allow new user command if update loop not registered.
@@ -393,10 +471,32 @@ static pbio_error_t pbio_drivebase_drive_relative(pbio_drivebase_t *db, int32_t
393471
return PBIO_SUCCESS;
394472
}
395473

474+
/**
475+
* Starts the drivebase controllers to run by a given distance.
476+
*
477+
* This will use the default speed.
478+
*
479+
* @param [in] db The drivebase instance.
480+
* @param [in] distance The distance to run by in mm.
481+
* @param [in] on_completion What to do when reaching the target.
482+
* @return Error code.
483+
*/
396484
pbio_error_t pbio_drivebase_drive_straight(pbio_drivebase_t *db, int32_t distance, pbio_control_on_completion_t on_completion) {
397485
// Execute the common drive command at default speed.
398486
return pbio_drivebase_drive_relative(db, distance, 0, 0, 0, on_completion);
399487
}
488+
489+
/**
490+
* Starts the drivebase controllers to run by an arc of given radius and angle.
491+
*
492+
* This will use the default speed.
493+
*
494+
* @param [in] db The drivebase instance.
495+
* @param [in] radius Radius of the arc in mm.
496+
* @param [in] angle Angle in degrees.
497+
* @param [in] on_completion What to do when reaching the target.
498+
* @return Error code.
499+
*/
400500
pbio_error_t pbio_drivebase_drive_curve(pbio_drivebase_t *db, int32_t radius, int32_t angle, pbio_control_on_completion_t on_completion) {
401501

402502
// The angle is signed by the radius so we can go both ways.
@@ -409,6 +509,16 @@ pbio_error_t pbio_drivebase_drive_curve(pbio_drivebase_t *db, int32_t radius, in
409509
return pbio_drivebase_drive_relative(db, arc_length, 0, arc_angle, 0, on_completion);
410510
}
411511

512+
/**
513+
* Starts the drivebase controllers to run for a given duration.
514+
*
515+
* @param [in] db The drivebase instance.
516+
* @param [in] drive_speed The drive speed in mm/s.
517+
* @param [in] turn_speed The turn speed in deg/s.
518+
* @param [in] duration The duration in control ticks.
519+
* @param [in] on_completion What to do when reaching the target.
520+
* @return Error code.
521+
*/
412522
static pbio_error_t pbio_drivebase_drive_timed(pbio_drivebase_t *db, int32_t drive_speed, int32_t turn_speed, uint32_t duration, pbio_control_on_completion_t on_completion) {
413523

414524
// Don't allow new user command if update loop not registered.
@@ -444,10 +554,28 @@ static pbio_error_t pbio_drivebase_drive_timed(pbio_drivebase_t *db, int32_t dri
444554
return PBIO_SUCCESS;
445555
}
446556

557+
/**
558+
* Starts the drivebase controllers to run forever.
559+
*
560+
* @param [in] db The drivebase instance.
561+
* @param [in] speed The drive speed in mm/s.
562+
* @param [in] turn_rate The turn rate in deg/s.
563+
* @return Error code.
564+
*/
447565
pbio_error_t pbio_drivebase_drive_forever(pbio_drivebase_t *db, int32_t speed, int32_t turn_rate) {
448566
return pbio_drivebase_drive_timed(db, speed, turn_rate, DURATION_FOREVER_TICKS, PBIO_CONTROL_ON_COMPLETION_CONTINUE);
449567
}
450568

569+
/**
570+
* Gets the drivebase state in user units.
571+
*
572+
* @param [in] db The drivebase instance.
573+
* @param [out] distance Distance traveled in mm.
574+
* @param [out] drive_speed Current speed in mm/s.
575+
* @param [out] angle Angle turned in degrees.
576+
* @param [out] turn_rate Current turn rate in deg/s.
577+
* @return Error code.
578+
*/
451579
pbio_error_t pbio_drivebase_get_state_user(pbio_drivebase_t *db, int32_t *distance, int32_t *drive_speed, int32_t *angle, int32_t *turn_rate) {
452580

453581
// Get drive base state
@@ -464,6 +592,18 @@ pbio_error_t pbio_drivebase_get_state_user(pbio_drivebase_t *db, int32_t *distan
464592
return PBIO_SUCCESS;
465593
}
466594

595+
596+
/**
597+
* Gets the drivebase settings in user units.
598+
*
599+
* @param [in] db Drivebase instance.
600+
* @param [out] drive_speed Default linear speed in mm/s.
601+
* @param [out] drive_acceleration Linear acceleration in mm/s^2.
602+
* @param [out] drive_deceleration Linear deceleration in mm/s^2.
603+
* @param [out] turn_rate Default turn rate in deg/s.
604+
* @param [out] turn_acceleration Angular acceleration in deg/s^2.
605+
* @param [out] turn_deceleration Angular deceleration in deg/s^2.
606+
*/
467607
pbio_error_t pbio_drivebase_get_drive_settings(pbio_drivebase_t *db, int32_t *drive_speed, int32_t *drive_acceleration, int32_t *drive_deceleration, int32_t *turn_rate, int32_t *turn_acceleration, int32_t *turn_deceleration) {
468608

469609
pbio_control_settings_t *sd = &db->control_distance.settings;
@@ -479,6 +619,17 @@ pbio_error_t pbio_drivebase_get_drive_settings(pbio_drivebase_t *db, int32_t *dr
479619
return PBIO_SUCCESS;
480620
}
481621

622+
/**
623+
* Sets the drivebase settings in user units.
624+
*
625+
* @param [in] db Drivebase instance.
626+
* @param [in] drive_speed Default linear speed in mm/s.
627+
* @param [in] drive_acceleration Linear acceleration in mm/s^2.
628+
* @param [in] drive_deceleration Linear deceleration in mm/s^2.
629+
* @param [in] turn_rate Default turn rate in deg/s.
630+
* @param [in] turn_acceleration Angular acceleration in deg/s^2.
631+
* @param [in] turn_deceleration Angular deceleration in deg/s^2.
632+
*/
482633
pbio_error_t pbio_drivebase_set_drive_settings(pbio_drivebase_t *db, int32_t drive_speed, int32_t drive_acceleration, int32_t drive_deceleration, int32_t turn_rate, int32_t turn_acceleration, int32_t turn_deceleration) {
483634

484635
pbio_control_settings_t *sd = &db->control_distance.settings;
@@ -496,11 +647,25 @@ pbio_error_t pbio_drivebase_set_drive_settings(pbio_drivebase_t *db, int32_t dri
496647

497648
#if PBIO_CONFIG_DRIVEBASE_SPIKE
498649

499-
// The following functions provide spike-like "tank-drive" controls. These will
500-
// not use the pbio functionality for gearing or reversed orientation. Any
501-
// scaling and flipping happens within the functions below.
502650

503-
// Set up a drive base without drivebase geometry.
651+
652+
/**
653+
* Gets spike drivebase instance from two servo instances.
654+
*
655+
* This and the following functions provide spike-like "tank-drive" controls.
656+
* These will not use the pbio functionality for gearing or reversed
657+
* orientation. Any scaling and flipping happens within the functions below.
658+
*
659+
* It is a drivebase, but without wheel size and axle track parameters.
660+
* Instead, the internal conversions are such that the "distance" is expressed
661+
* in motor degrees. Likewise, turning in place by N degrees means that both
662+
* motors turn by that amount.
663+
*
664+
* @param [out] db_address Drivebase instance if available.
665+
* @param [in] left Left servo instance.
666+
* @param [in] right Right servo instance.
667+
* @return Error code.
668+
*/
504669
pbio_error_t pbio_drivebase_get_drivebase_spike(pbio_drivebase_t **db_address, pbio_servo_t *left, pbio_servo_t *right) {
505670
pbio_error_t err = pbio_drivebase_get_drivebase(db_address, left, right, 1, 1);
506671

@@ -511,7 +676,16 @@ pbio_error_t pbio_drivebase_get_drivebase_spike(pbio_drivebase_t **db_address, p
511676
return err;
512677
}
513678

514-
// Drive for a given duration, given two motor speeds.
679+
/**
680+
* Starts driving for a given duration, at the provided motor speeds.
681+
*
682+
* @param [in] db The drivebase instance.
683+
* @param [in] speed_left Left motor speed in deg/s.
684+
* @param [in] speed_right Right motor speed in deg/s.
685+
* @param [in] duration The duration in ms.
686+
* @param [in] on_completion What to do when reaching the target.
687+
* @return Error code.
688+
*/
515689
pbio_error_t pbio_drivebase_spike_drive_time(pbio_drivebase_t *db, int32_t speed_left, int32_t speed_right, int32_t duration, pbio_control_on_completion_t on_completion) {
516690
// Flip left tank motor orientation.
517691
speed_left = -speed_left;
@@ -522,13 +696,32 @@ pbio_error_t pbio_drivebase_spike_drive_time(pbio_drivebase_t *db, int32_t speed
522696
return pbio_drivebase_drive_timed(db, drive_speed, turn_speed, pbio_control_time_ms_to_ticks(duration), on_completion);
523697
}
524698

525-
// Drive forever given two motor speeds.
699+
/**
700+
* Starts driving indefinitely, at the provided motor speeds.
701+
*
702+
* @param [in] db The drivebase instance.
703+
* @param [in] speed_left Left motor speed in deg/s.
704+
* @param [in] speed_right Right motor speed in deg/s.
705+
* @return Error code.
706+
*/
526707
pbio_error_t pbio_drivebase_spike_drive_forever(pbio_drivebase_t *db, int32_t speed_left, int32_t speed_right) {
527708
// Same as driving for time, just without an endpoint.
528709
return pbio_drivebase_spike_drive_time(db, speed_left, speed_right, DURATION_FOREVER_TICKS, PBIO_CONTROL_ON_COMPLETION_CONTINUE);
529710
}
530711

531-
// Drive given two speeds and one angle.
712+
/**
713+
* Drive the motors by a given angle, at the provided motor speeds.
714+
*
715+
* Only the faster motor will travel by the given angle. The slower motor
716+
* travels less, such that they still stop at the same time.
717+
*
718+
* @param [in] db The drivebase instance.
719+
* @param [in] speed_left Left motor speed in deg/s.
720+
* @param [in] speed_right Right motor speed in deg/s.
721+
* @param [in] angle Angle (deg) that the fast motor should travel.
722+
* @param [in] on_completion What to do when reaching the target.
723+
* @return Error code.
724+
*/
532725
pbio_error_t pbio_drivebase_spike_drive_angle(pbio_drivebase_t *db, int32_t speed_left, int32_t speed_right, int32_t angle, pbio_control_on_completion_t on_completion) {
533726

534727
// In the classic tank drive, we flip the left motor here instead of at the low level.
@@ -555,6 +748,17 @@ pbio_error_t pbio_drivebase_spike_drive_angle(pbio_drivebase_t *db, int32_t spee
555748
return pbio_drivebase_drive_relative(db, distance, speed, turn_angle, speed, on_completion);
556749
}
557750

751+
/**
752+
* Converts a speed and a steering ratio into a separate left and right speed.
753+
*
754+
* The steering value must be in the range [-100, 100].
755+
*
756+
* @param [in] speed Overal speed (deg/s).
757+
* @param [in] steering Steering ratio.
758+
* @param [out] speed_left Speed of the left motor (deg/s).
759+
* @param [out] speed_right Speed of the right motor (deg/s).
760+
* @return Error code.
761+
*/
558762
pbio_error_t pbio_drivebase_spike_steering_to_tank(int32_t speed, int32_t steering, int32_t *speed_left, int32_t *speed_right) {
559763

560764
// Steering must be bounded.

0 commit comments

Comments
 (0)