@@ -21,7 +21,7 @@ static pbio_drivebase_t drivebases[PBIO_CONFIG_NUM_DRIVEBASES];
2121/**
2222 * Gets the state of the drivebase update loop.
2323 *
24- * This becomes true after a successful call to pbio_drivebase_setup and
24+ * This becomes true after a successful call to pbio_drivebase_get_drivebase and
2525 * becomes false when there is an error. Such as when the cable is unplugged.
2626 *
2727 * @param [in] db The drivebase instance
@@ -117,11 +117,11 @@ static void drivebase_adopt_settings(pbio_control_settings_t *s_distance, pbio_c
117117 * Get the physical and estimated state of a drivebase in units of control.
118118 *
119119 * @param [in] db The drivebase instance
120- * @param [out] state_distance Physical and estimated state of the distance.
121- * @param [out] state_heading Physical and estimated state of the heading.
120+ * @param [out] state_distance Physical and estimated state of the distance based on motor angles .
121+ * @param [out] state_heading Physical and estimated state of the heading based on motor angles .
122122 * @return Error code.
123123 */
124- 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 ) {
124+ static pbio_error_t pbio_drivebase_get_state_via_motors (pbio_drivebase_t * db , pbio_control_state_t * state_distance , pbio_control_state_t * state_heading ) {
125125
126126 // Get left servo state
127127 pbio_control_state_t state_left ;
@@ -150,7 +150,35 @@ static pbio_error_t pbio_drivebase_get_state_control(pbio_drivebase_t *db, pbio_
150150 state_heading -> speed_estimate = state_distance -> speed_estimate - state_right .speed_estimate ;
151151 state_heading -> speed = state_distance -> speed - state_right .speed ;
152152
153+ return PBIO_SUCCESS ;
154+ }
155+
156+ /**
157+ * Get the physical and estimated state of a drivebase in units of control.
158+ *
159+ * @param [in] db The drivebase instance
160+ * @param [out] state_distance Physical and estimated state of the distance.
161+ * @param [out] state_heading Physical and estimated state of the heading.
162+ * @return Error code.
163+ */
164+ 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 ) {
165+
166+ // Gets the "measured" state according to the driver motors.
167+ pbio_error_t err = pbio_drivebase_get_state_via_motors (db , state_distance , state_heading );
168+ if (err != PBIO_SUCCESS ) {
169+ return err ;
170+ }
171+
172+ // Subtract distance offset.
173+ pbio_angle_diff (& state_distance -> position , & db -> distance_offset , & state_distance -> position );
174+ pbio_angle_diff (& state_distance -> position_estimate , & db -> distance_offset , & state_distance -> position_estimate );
175+
176+ // Subtract heading offset
177+ pbio_angle_diff (& state_heading -> position , & db -> heading_offset , & state_heading -> position );
178+ pbio_angle_diff (& state_heading -> position_estimate , & db -> heading_offset , & state_heading -> position_estimate );
179+
153180 // Optionally use gyro to override the heading source for more accuracy.
181+ // The gyro manages its own offset, so we don't need to subtract it here.
154182 if (db -> use_gyro ) {
155183 pbio_imu_get_heading_scaled (& state_heading -> position , & state_heading -> speed , db -> control_heading .settings .ctl_steps_per_app_step );
156184 }
@@ -235,7 +263,7 @@ static pbio_error_t pbio_drivebase_stop_from_servo(void *drivebase, bool clear_p
235263#define ROT_MDEG_OVER_PI (114592) // 360 000 / pi
236264
237265/**
238- * Gets drivebase instance from two servo instances.
266+ * Gets and sets up drivebase instance from two servo instances.
239267 *
240268 * @param [out] db_address Drivebase instance if available.
241269 * @param [in] left Left servo instance.
@@ -329,6 +357,10 @@ pbio_error_t pbio_drivebase_get_drivebase(pbio_drivebase_t **db_address, pbio_se
329357 return PBIO_ERROR_INVALID_ARG ;
330358 }
331359
360+ // Reset offsets so current distance and angle are 0. This relies on the
361+ // geometry, so it is done after the scaling is set.
362+ pbio_drivebase_reset (db , 0 , 0 );
363+
332364 // Finish setup. By default, don't use gyro.
333365 return pbio_drivebase_set_use_gyro (db , false);
334366}
@@ -687,6 +719,50 @@ pbio_error_t pbio_drivebase_get_state_user(pbio_drivebase_t *db, int32_t *distan
687719 return PBIO_SUCCESS ;
688720}
689721
722+ /**
723+ * Stops the drivebase and resets the accumulated drivebase state in user units.
724+ *
725+ * If the gyro is being used for control, it will be reset to the same angle.
726+ *
727+ * @param [in] db The drivebase instance.
728+ * @param [out] distance Distance traveled in mm.
729+ * @param [out] angle Angle turned in degrees.
730+ * @return Error code.
731+ */
732+ pbio_error_t pbio_drivebase_reset (pbio_drivebase_t * db , int32_t distance , int32_t angle ) {
733+
734+ // Physically stops motors and stops the ongoing controllers, simplifying
735+ // the state reset since we won't need to restart ongoing motion.
736+ pbio_error_t err = pbio_drivebase_stop (db , PBIO_CONTROL_ON_COMPLETION_COAST );
737+ if (err != PBIO_SUCCESS ) {
738+ return err ;
739+ }
740+
741+ // Get measured state according to motor encoders.
742+ pbio_control_state_t measured_distance ;
743+ pbio_control_state_t measured_heading ;
744+ err = pbio_drivebase_get_state_via_motors (db , & measured_distance , & measured_heading );
745+ if (err != PBIO_SUCCESS ) {
746+ return err ;
747+ }
748+
749+ // We want to get: reported_new = measured - offset_new
750+ // So we can do: offset_new = measured - reported_new
751+ pbio_angle_t reported_new ;
752+
753+ pbio_angle_from_low_res (& reported_new , distance , db -> control_distance .settings .ctl_steps_per_app_step );
754+ pbio_angle_diff (& measured_distance .position , & reported_new , & db -> distance_offset );
755+
756+ pbio_angle_from_low_res (& reported_new , angle , db -> control_heading .settings .ctl_steps_per_app_step );
757+ pbio_angle_diff (& measured_heading .position , & reported_new , & db -> heading_offset );
758+
759+ // Whether or not the gyro is being used, synchronize heading and drivebase
760+ // angle state.
761+ pbio_imu_set_heading (angle );
762+
763+ return PBIO_SUCCESS ;
764+ }
765+
690766
691767/**
692768 * Gets the drivebase settings in user units.
0 commit comments