mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-23 00:59:54 +08:00
Add Trapezoidal Trajectory class and functions
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
#include "odrive_main.h"
|
||||
|
||||
// Standard sign function, implemented to match the Python impelmentation
|
||||
template <typename T> int sign(T val){
|
||||
if(val == T(0))
|
||||
return T(0);
|
||||
else
|
||||
return (std::signbit(val)) ? -1 : 1;
|
||||
}
|
||||
|
||||
float TrapezoidalTrajectory::planTrapezoidal(float Xf, float Xi,
|
||||
float Vf, float Vi,
|
||||
float Af, float Ai,
|
||||
float Vmax, float Amax, float Dmax) {
|
||||
|
||||
float dX = Xf - Xi;
|
||||
int s = sign(dX);
|
||||
|
||||
float Ar = s*Amax; // Maximum Acceleration (signed)
|
||||
float Dr = -1.0f*s*Dmax; // Maximum Deceleration (signed)
|
||||
float Vr = s*Vmax; // Maximum Velocity (signed)
|
||||
|
||||
// Handle the case where initial velocity > Max velocity
|
||||
if(s*Vi > s*Vr){
|
||||
Ar = -1.0f*s*Amax;
|
||||
}
|
||||
|
||||
float Ta = (Vr - Vi)/Ar;
|
||||
float Tv;
|
||||
float Td = (Vf - Vr)/Dr;
|
||||
|
||||
// Peak Velocity handling
|
||||
float dXmin;
|
||||
if(Vf == 0.0f){
|
||||
dXmin = Ta*(Vr + Vi)/2.0f + (Td*Vr)/2.0f; // Basic wedge profile
|
||||
} else if(sign(Vf) == sign(Vr)){
|
||||
dXmin = Ta*(Vr + Vi)/2.0f + Td*(Vr - Vf)/2.0f + Td*Vf; // Wedge profile with a non-zero end
|
||||
} else {
|
||||
dXmin = Ta*(Vr + Vi)/2.0f + Td*(Vr - s*Vf)/2.0f; // Wedge profile that crosses Y axis during decel
|
||||
}
|
||||
|
||||
// Short move handling
|
||||
if(s*dXmin > s*dX){
|
||||
Vr = s*std::sqrt(-1.0f*Ar*(Vf*Vf-2*Dr*dX))/sqrt(Dr-Ar);
|
||||
Ta = std::max(0.0f, (Vr - Vi)/Ar);
|
||||
Tv = 0;
|
||||
Td = std::max(0.0f, (Vf - Vr)/Dr);
|
||||
} else {
|
||||
Tv = (dX - dXmin)/Vr;
|
||||
}
|
||||
|
||||
// Populate object's values
|
||||
yAccel_ = (Ar*Ta*Ta) / 2.0f + (Vi * Ta) + Xi;
|
||||
Xi_ = Xi;
|
||||
Vi_ = Vi;
|
||||
Ai_ = Ai;
|
||||
|
||||
Ar_ = Ar;
|
||||
Dr_ = Dr;
|
||||
Vr_ = Vr;
|
||||
|
||||
Ta_ = Ta;
|
||||
Tv_ = Tv;
|
||||
Td_ = Td;
|
||||
Tav_ = Ta + Tv;
|
||||
|
||||
return Ta + Tv + Td;
|
||||
}
|
||||
|
||||
TrapezoidalTrajectory::TrajectoryStep_t TrapezoidalTrajectory::evalTrapTraj(float t){
|
||||
TrapezoidalTrajectory::TrajectoryStep_t trajStep;
|
||||
if( t <= 0.0f){ // Initial Conditions
|
||||
trajStep.Y = Xi_;
|
||||
trajStep.Yd = Vi_;
|
||||
trajStep.Ydd = Ai_;
|
||||
} else if( t <= Ta_){ // Accelerating
|
||||
trajStep.Y = (Ar_ * (t*t))/2.0f + (Vi_ * t) + Xi_;
|
||||
trajStep.Yd = (Ar_ * t) + Vi_;
|
||||
trajStep.Ydd = Ar_;
|
||||
} else if( t <= Ta_ + Tv_){ // Coasting
|
||||
trajStep.Y = yAccel_ + (Vr_ * (t - Ta_));
|
||||
trajStep.Yd = Vr_;
|
||||
trajStep.Ydd = 0;
|
||||
} else if( t <= Ta_ + Tv_ + Td_){ // Deceleration
|
||||
float Tdc = t - Ta_;
|
||||
trajStep.Y = yAccel_ + (Vr_ * (Tdc)) + Dr_*(Tdc*Tdc)/2.0f;
|
||||
trajStep.Yd = Vr_ + Dr_*Tdc;
|
||||
trajStep.Ydd = Dr_;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
class TrapezoidalTrajectory {
|
||||
private:
|
||||
float yAccel_;
|
||||
|
||||
float Xi_;
|
||||
float Vi_;
|
||||
float Ai_;
|
||||
|
||||
float Ar_;
|
||||
float Dr_;
|
||||
float Vr_;
|
||||
|
||||
float Ta_;
|
||||
float Tv_;
|
||||
float Td_;
|
||||
float Tav_;
|
||||
|
||||
public:
|
||||
struct TrajectoryStep_t{
|
||||
float Y;
|
||||
float Yd;
|
||||
float Ydd;
|
||||
};
|
||||
|
||||
TrapezoidalTrajectory();
|
||||
|
||||
float planTrapezoidal(float Xf, float Xi,
|
||||
float Vf, float Vi,
|
||||
float Af, float Ai,
|
||||
float Vmax, float Amax, float Dmax
|
||||
);
|
||||
|
||||
TrajectoryStep_t evalTrapTraj(float t);
|
||||
|
||||
~TrapezoidalTrajectory();
|
||||
}
|
||||
Reference in New Issue
Block a user