ES3011/robot_controller/trapezoidal.ino

88 lines
3.1 KiB
C++

#include "trapezoidal.h"
// trapezoidal impl, not fuzzed
// returns the position and velocity at the given time on a trapezoidal motion plan
// this could be baked if too computationally expensive
// not fully fuzzed
struct Setpoint trapezoidal_planner(struct Trapezoidal* trapezoidal, float time) {
float max_vel = trapezoidal->max_vel;
float max_acc = trapezoidal->max_acc;
float dist = trapezoidal->dist;
struct Setpoint setpoint = {0.0, 0.0};
float time_accelerating = max_acc / max_vel;
float distance_while_accelerating = 0.5 * max_acc * time_accelerating * time_accelerating;
if (2.0 * distance_while_accelerating > dist) {
// triangular
float peak_velocity_time = sqrt(dist/max_acc);
float peak_velocity = max_acc * peak_velocity_time;
if (time < peak_velocity_time) {
// accelerating
setpoint.velocity = max_acc * time;
setpoint.position = 0.5 * max_acc * time * time;
} else if (time < peak_velocity_time * 2.0) {
// slowing down
float time_decay = time - peak_velocity_time;
setpoint.velocity = peak_velocity - (time_decay * max_acc);
setpoint.position = (0.5 * max_acc * peak_velocity_time * peak_velocity_time) // acceleration phase
+ peak_velocity * time_decay
- 0.5 * max_acc * time_decay * time_decay;
} else {
setpoint.velocity = 0;
setpoint.position = dist;
setpoint.complete = true;
}
} else {
// trapezoidal
float cruise_distance = dist - 2.0 * distance_while_accelerating;
float cruise_time = cruise_distance / max_vel;
float total_time = 2 * time_accelerating + cruise_time;
if (time < time_accelerating) {
// still accelerating
setpoint.velocity = time * max_acc;
setpoint.position = 0.5 * max_acc * time * time;
} else if (time < time_accelerating + cruise_time) {
// cruising
setpoint.velocity = max_vel;
setpoint.position = distance_while_accelerating + max_vel * (time - time_accelerating);
} else if (time < total_time) {
// slowing down
float time_decay = time - (time_accelerating + cruise_time);
setpoint.velocity = max_vel - time_decay * max_acc;
setpoint.position = distance_while_accelerating + cruise_distance
+ (max_vel * time_decay)
- 0.5 * max_acc * time_decay * time_decay;
} else {
//done
setpoint.velocity = 0.0;
setpoint.position = dist;
setpoint.complete = true;
}
}
return setpoint;
}
float trapezoidal_time(struct Trapezoidal* trapezoidal) {
float max_vel = trapezoidal->max_vel;
float max_acc = trapezoidal->max_acc;
float dist = trapezoidal->dist;
float time_accelerating = max_acc / max_vel;
float distance_while_accelerating = 0.5 * max_acc * time_accelerating * time_accelerating;
if (2.0 * distance_while_accelerating > dist) {
// triangular
float peak_velocity_time = sqrt(dist/max_acc);
return peak_velocity_time * 2.0;
} else {
// trapezoidal
float cruise_distance = dist - 2.0 * distance_while_accelerating;
float cruise_time = cruise_distance / max_vel;
float total_time = 2 * time_accelerating + cruise_time;
return total_time;
}
}