7 #include "RTT/SEGGER_RTT.h" 17 #define REDUCTION_FACTOR_P 1000 18 #define REDUCTION_FACTOR_I 10000 19 #define REDUCTION_FACTOR_D 10000 22 #define INT_POS_PERIOD 10 25 #define POS_PERIOD 100 28 #define CONTROL_PERIOD 1 30 #define RESET_PERIOD 300 33 #define ABS(x) (((x) > 0) ? (x) : -(x)) 36 #define SIGN(x) (((x) < 0) ? (-1) : 1) 50 volatile bool dist_command_received;
53 volatile int32_t current_distance;
56 volatile uint8_t master_stop;
60 volatile bool dist_command_updated;
62 volatile bool translation_ended;
63 volatile bool rotation_ended;
65 BSEMAPHORE_DECL(reset_orientation_sem, TRUE);
66 volatile int8_t reset_orientation_direction;
67 volatile int16_t reset_orientation_orientation;
88 static volatile int32_t target_dist;
89 static volatile uint16_t target_heading;
91 static volatile bool orientation_control = TRUE;
94 THD_WORKING_AREA(wa_control, CONTROL_STACK_SIZE);
95 THD_WORKING_AREA(wa_int_pos, INT_POS_STACK_SIZE);
96 THD_WORKING_AREA(wa_reset_pos, INT_POS_STACK_SIZE);
133 float compute_target(
float t,
float inc_acceleration,
float dec_acceleration,
134 float cruising_speed,
float final_x)
139 inc_acceleration = ABS(inc_acceleration);
140 dec_acceleration = - ABS(dec_acceleration);
141 cruising_speed = ABS(cruising_speed);
144 inc_acceleration = - ABS(inc_acceleration);
145 dec_acceleration = ABS(dec_acceleration);
146 cruising_speed = - ABS(cruising_speed);
150 float t1 = cruising_speed / inc_acceleration;
151 float t2 = final_x / cruising_speed + cruising_speed / 2 * (1 / inc_acceleration + 1 / dec_acceleration);
155 float t4_square = 2 * final_x / (inc_acceleration * (1 - inc_acceleration / dec_acceleration));
157 if (t * t <= t4_square)
return inc_acceleration * t * t / 2;
159 float t4_inv = 2 / sqrt(t4_square);
160 float delta_t = t - t4_inv * final_x / inc_acceleration;
162 if (delta_t >= 0)
return final_x;
163 return dec_acceleration / 2 * delta_t * delta_t + final_x;
166 float t3 = t2 - cruising_speed /dec_acceleration;
170 else if (t <= t1 && t <= t2)
return inc_acceleration * t * t / 2;
171 else if (t <= t2)
return t1 * cruising_speed / 2 + cruising_speed * (t - t1);
173 return final_x + cruising_speed * cruising_speed / 2 / dec_acceleration \
174 + (t - t2) * (cruising_speed + dec_acceleration / 2 * (t - t2));
184 extern THD_FUNCTION(int_pos_thread, p) {
193 float linear_t = 0.0;
194 float angular_t = 0.0;
196 int16_t prev_goal_heading = 0;
197 int16_t delta_heading = 0;
198 int16_t initial_heading = 0;
199 int16_t tmp_target_heading = 0;
200 uint32_t update_position_counter = 0U;
205 start_time = chVTGetSystemTime();
210 update_position_counter++;
212 if (update_position_counter > (uint32_t)(POS_PERIOD / INT_POS_PERIOD)) {
214 update_position_counter = 0U;
219 if (dist_command_received) {
221 dist_command_received = FALSE;
225 dist_command_updated = TRUE;
228 linear_t += (float)INT_POS_PERIOD / 1000.0;
240 if (goal.heading != prev_goal_heading) {
243 prev_goal_heading = goal.heading;
247 if (delta_heading < -(HEADING_MAX_VALUE / 2)) {
248 delta_heading += HEADING_MAX_VALUE;
249 }
else if (delta_heading > (HEADING_MAX_VALUE / 2)) {
250 delta_heading -= HEADING_MAX_VALUE;
254 angular_t += (float)INT_POS_PERIOD / 1000.0;
258 tmp_target_heading = initial_heading + ((int16_t) compute_target(angular_t,
264 if (tmp_target_heading < 0) {
265 target_heading = tmp_target_heading + HEADING_MAX_VALUE;
266 }
else if (tmp_target_heading >= HEADING_MAX_VALUE) {
267 target_heading = tmp_target_heading - HEADING_MAX_VALUE;
269 target_heading = tmp_target_heading;
273 static int cpt_print = 0;
274 if (cpt_print++ % 50 == 0) {
280 printf(
"target %d / %d (%d) %d / %d (%d)\r\n", target_heading, goal.heading,
orientation, target_dist, goal.mean_dist, current_distance);
283 chThdSleepMilliseconds(INT_POS_PERIOD - ST2MS(chVTGetSystemTime() - start_time));
287 extern THD_FUNCTION(control_thread, p) {
300 int16_t prev_goal_heading;
303 int16_t cur_target_heading;
306 int32_t prev_command[2] = {0, 0};
308 int32_t prev_linear_command = 0;
309 int32_t linear_command = 0;
310 int32_t prev_angular_command = 0;
311 int32_t angular_command = 0;
315 int32_t max_linear_delta_pwm_command;
316 int32_t max_angular_delta_pwm_command;
321 int32_t remaining_time;
324 prev_goal_heading = goal.heading;
325 cur_target_heading = target_heading;
330 start_time = chVTGetSystemTime();
334 if (dist_command_updated) {
336 dist_command_updated = FALSE;
339 linear_control.epsilon_sum = 0;
340 saved_ticks.left = left_ticks;
341 saved_ticks.right = right_ticks;
345 if (prev_goal_heading != goal.heading) {
346 prev_goal_heading = goal.heading;
347 angular_control.epsilon_sum = 0;
355 current_distance = 1000 * ((left_ticks - saved_ticks.left) + (right_ticks - saved_ticks.right)) / (2 *
settings.
ticks_per_m);
362 linear_control.prev_epsilon = linear_control.epsilon;
363 linear_control.epsilon = target_dist - current_distance;
364 linear_control.epsilon_sum += linear_control.epsilon;
366 if (master_stop == FALSE) {
372 linear_pid.d = (
settings.
linear_coeff.
d * (linear_control.epsilon - linear_control.prev_epsilon)) / REDUCTION_FACTOR_D;
374 prev_linear_command = linear_command;
375 linear_command = linear_pid.p + linear_pid.i + linear_pid.d;
378 if ((int32_t)(linear_command - prev_linear_command) > max_linear_delta_pwm_command) {
379 linear_command = prev_linear_command + max_linear_delta_pwm_command;
380 }
else if ((int32_t)(linear_command - prev_linear_command) < -max_linear_delta_pwm_command) {
381 linear_command = prev_linear_command - max_linear_delta_pwm_command;
385 if (ABS(current_distance) >= goal.heading_dist_sync_ref) {
386 cur_target_heading = target_heading;
390 angular_control.prev_epsilon = angular_control.epsilon;
391 angular_control.epsilon = cur_target_heading -
orientation;
395 if (angular_control.epsilon > (HEADING_MAX_VALUE / 2)) {
396 angular_control.epsilon -= HEADING_MAX_VALUE;
397 }
else if (angular_control.epsilon < -(HEADING_MAX_VALUE / 2)) {
398 angular_control.epsilon += HEADING_MAX_VALUE;
401 angular_control.epsilon_sum += angular_control.epsilon;
408 angular_pid.d = (
settings.
angular_coeff.
d * (angular_control.epsilon - angular_control.prev_epsilon)) / REDUCTION_FACTOR_D;
410 prev_angular_command = angular_command;
411 angular_command = angular_pid.p + angular_pid.i + angular_pid.d;
414 if ((int32_t)(angular_command - prev_angular_command) > max_angular_delta_pwm_command) {
415 angular_command = prev_angular_command + max_angular_delta_pwm_command;
416 }
else if ((int32_t)(angular_command - prev_angular_command) < -max_angular_delta_pwm_command) {
417 angular_command = prev_angular_command - max_angular_delta_pwm_command;
420 if (FALSE == orientation_control) {
427 tmp_command = ABS(linear_command + angular_command);
428 if (tmp_command > MAX_PWM) {
429 linear_command *= MAX_PWM;
430 linear_command /= tmp_command;
432 angular_command *= MAX_PWM;
433 angular_command /= tmp_command;
437 tmp_command = ABS(linear_command - angular_command);
438 if (tmp_command > MAX_PWM) {
439 linear_command *= MAX_PWM;
440 linear_command /= tmp_command;
442 angular_command *= MAX_PWM;
443 angular_command /= tmp_command;
448 command[
MOTOR_LEFT] = linear_command + angular_command;
456 command[
MOTOR_RIGHT] = linear_command - angular_command;
467 if (((command[motor] < 0) && (prev_command[motor] >= 0))
468 || ((command[motor] >= 0) && (prev_command[motor] < 0))) {
473 if (command[motor] < 0) {
480 linear_control.epsilon_sum = 0;
481 angular_control.epsilon_sum = 0;
489 tmp_command = SIGN(linear_command) * (ABS(linear_command) - max_linear_delta_pwm_command);
490 if (SIGN(tmp_command) != SIGN(linear_command)) {
493 linear_command = tmp_command;
497 tmp_command = SIGN(angular_command) * (ABS(angular_command) - max_angular_delta_pwm_command);
498 if (SIGN(tmp_command) != SIGN(angular_command)) {
501 angular_command = tmp_command;
504 command[
MOTOR_RIGHT] = linear_command + angular_command;
505 command[
MOTOR_LEFT] = linear_command - angular_command;
510 goal.mean_dist -= current_distance;
511 dist_command_received = TRUE;
516 remaining_time = CONTROL_PERIOD - ST2MS(chVTGetSystemTime() - start_time);
517 if (remaining_time > 0) {
518 chThdSleepMilliseconds(remaining_time);
523 extern THD_FUNCTION(reset_pos_thread, p) {
524 int32_t saved_current_distance;
529 chBSemWait(&reset_orientation_sem);
532 orientation_control = FALSE;
535 goal.mean_dist = SIGN(reset_orientation_direction) * 0x0FFFFFFF;
536 dist_command_received = TRUE;
538 saved_current_distance = 0;
541 chThdSleepMilliseconds(RESET_PERIOD);
542 if (saved_current_distance == current_distance) {
545 orientation_control = TRUE;
547 dist_command_received = TRUE;
550 saved_current_distance = current_distance;
uint16_t max_linear_acceleration
uint16_t cruise_angular_speed
void update_position(void)
Update the position according to the information given by the coding wheels.
int motor_set_speed(motor_t motor, uint8_t speed)
Set the rotation speed of the specified motor.
void update_orientation(void)
Update the current orientation.
pid_coeffs_t linear_coeff
motor_t
Alias to select the motor to work on.
pid_coeffs_t angular_coeff
uint16_t linear_allowance
uint16_t max_angular_acceleration
int32_t set_orientation(int16_t heading)
Set the euler heading angle offset.
void motor_toggle_direction(motor_t motor)
Revert the rotation direction of the specified motor.
uint16_t angular_allowance
void compute_movement(void)
Compute the coding wheels movements.
uint16_t cruise_linear_speed
volatile robot_settings_t settings
Global variable used to store the configuration in use.