@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright ( c ) 2018 PX4 Development Team . All rights reserved .
* Copyright ( c ) 2018 - 2019 PX4 Development Team . All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
@ -45,33 +45,31 @@ VelocitySmoothing::VelocitySmoothing(float initial_accel, float initial_vel, flo
@@ -45,33 +45,31 @@ VelocitySmoothing::VelocitySmoothing(float initial_accel, float initial_vel, flo
void VelocitySmoothing : : reset ( float accel , float vel , float pos )
{
_jerk = 0.f ;
_accel = accel ;
_vel = vel ;
_pos = pos ;
_state . j = 0.f ;
_st ate . a = accel ;
_state . v = vel ;
_state . x = pos ;
}
float VelocitySmoothing : : saturateT1ForAccel ( float accel_prev , float max_jerk , float T1 )
float VelocitySmoothing : : saturateT1ForAccel ( float a0 , float j_ max, float T1 , float a_max )
{
/* Check maximum acceleration, saturate and recompute T1 if needed */
float accel_T1 = accel_prev + max_jerk * T1 ;
float accel_T1 = a0 + j_max * T1 ;
float T1_new = T1 ;
if ( accel_T1 > _max_accel ) {
T1_new = ( _max_accel - accel_prev ) / max_jerk ;
if ( accel_T1 > a _max) {
T1_new = ( a _max - a0 ) / j_ max;
} else if ( accel_T1 < - _max_accel ) {
T1_new = ( - _max_accel - accel_prev ) / max_jerk ;
} else if ( accel_T1 < - a _max) {
T1_new = ( - a _max - a0 ) / j_ max;
}
return T1_new ;
}
float VelocitySmoothing : : computeT1 ( float accel_prev , float vel_prev , float vel_setpoint , float max_jerk )
float VelocitySmoothing : : computeT1 ( float a0 , float v3 , float j_max , float a_ max)
{
float b = 2.f * accel_prev / max_jerk ;
float c = vel_prev / max_jerk + accel_prev * accel_prev / ( 2.f * max_jerk * max_jerk ) - vel_setpoint / max_jerk ;
float delta = b * b - 4.f * c ;
float delta = 2.f * a0 * a0 + 4.f * j_max * v3 ;
if ( delta < 0.f ) {
// Solution is not real
@ -79,11 +77,11 @@ float VelocitySmoothing::computeT1(float accel_prev, float vel_prev, float vel_s
@@ -79,11 +77,11 @@ float VelocitySmoothing::computeT1(float accel_prev, float vel_prev, float vel_s
}
float sqrt_delta = sqrtf ( delta ) ;
float T1_plus = ( - b + sqrt_delta ) * 0.5f ;
float T1_minus = ( - b - sqrt_delta ) * 0.5f ;
float T1_plus = ( - a0 + 0.5f * sqrt_delta ) / j_max ;
float T1_minus = ( - a0 - 0.5f * sqrt_delta ) / j_max ;
float T3_plus = accel_prev / max_jerk + T1_plus ;
float T3_minus = accel_prev / max_jerk + T1_minus ;
float T3_plus = a0 / j_max + T1_plus ;
float T3_minus = a0 / j_max + T1_minus ;
float T1 = 0.f ;
@ -94,21 +92,16 @@ float VelocitySmoothing::computeT1(float accel_prev, float vel_prev, float vel_s
@@ -94,21 +92,16 @@ float VelocitySmoothing::computeT1(float accel_prev, float vel_prev, float vel_s
T1 = T1_minus ;
}
T1 = saturateT1ForAccel ( accel_prev , max_jerk , T1 ) ;
if ( T1 < _dt ) {
T1 = 0.f ;
}
T1 = saturateT1ForAccel ( a0 , j_max , T1 , a_max ) ;
return math : : max ( T1 , 0.f ) ;
}
float VelocitySmoothing : : computeT1 ( float T123 , float accel_prev , float vel_prev , float vel_setpoint , float max_jerk )
float VelocitySmoothing : : computeT1 ( float T123 , float a0 , float v3 , float j_max , float a_ max)
{
float a = - max_jerk ;
float b = max_jerk * T123 - accel_prev ;
float delta = T123 * T123 * max_jerk * max_jerk + 2.f * T123 * accel_prev * max_jerk - accel_prev * accel_prev
+ 4.f * max_jerk * ( vel_prev - vel_setpoint ) ;
float a = - j_max ;
float b = j_max * T123 - a0 ;
float delta = T123 * T123 * j_max * j_max + 2.f * T123 * a0 * j_max - a0 * a0 - 4.f * j_max * v3 ;
if ( delta < 0.f ) {
// Solution is not real
@ -120,8 +113,8 @@ float VelocitySmoothing::computeT1(float T123, float accel_prev, float vel_prev,
@@ -120,8 +113,8 @@ float VelocitySmoothing::computeT1(float T123, float accel_prev, float vel_prev,
float T1_plus = math : : max ( ( - b + sqrt_delta ) * denominator_inv , 0.f ) ;
float T1_minus = math : : max ( ( - b - sqrt_delta ) * denominator_inv , 0.f ) ;
float T3_plus = accel_prev / max_jerk + T1_plus ;
float T3_minus = accel_prev / max_jerk + T1_minus ;
float T3_plus = a0 / j_max + T1_plus ;
float T3_minus = a0 / j_max + T1_minus ;
float T13_plus = T1_plus + T3_plus ;
float T13_minus = T1_minus + T3_minus ;
@ -135,31 +128,20 @@ float VelocitySmoothing::computeT1(float T123, float accel_prev, float vel_prev,
@@ -135,31 +128,20 @@ float VelocitySmoothing::computeT1(float T123, float accel_prev, float vel_prev,
T1 = T1_plus ;
}
T1 = saturateT1ForAccel ( accel_prev , max_jerk , T1 ) ;
if ( T1 < _dt ) {
T1 = 0.f ;
}
T1 = saturateT1ForAccel ( a0 , j_max , T1 , a_max ) ;
return T1 ;
}
float VelocitySmoothing : : computeT2 ( float T1 , float T3 , float accel_prev , float vel_prev , float vel_setpoint ,
float max_jerk )
float VelocitySmoothing : : computeT2 ( float T1 , float T3 , float a0 , float v3 , float j_max )
{
float f = accel_prev * T1 + max_jerk * T1 * T1 * 0.5f + vel_prev + accel_prev * T3 + max_jerk * T1 * T3
- max_jerk * T3 * T3 * 0.5f ;
float T2 = 0.f ;
float den = accel_prev + max_jerk * T1 ;
float den = a0 + j_max * T1 ;
if ( math : : abs_t ( den ) > FLT_EPSILON ) {
T2 = ( vel_setpoint - f ) / den ;
}
if ( T2 < _dt ) {
T2 = 0.f ;
T2 = ( - 0.5f * T1 * T1 * j_max - T1 * T3 * j_max - T1 * a0 + 0.5f * T3 * T3 * j_max - T3 * a0 + v3 ) / den ;
}
return math : : max ( T2 , 0.f ) ;
@ -171,56 +153,51 @@ float VelocitySmoothing::computeT2(float T123, float T1, float T3)
@@ -171,56 +153,51 @@ float VelocitySmoothing::computeT2(float T123, float T1, float T3)
return math : : max ( T2 , 0.f ) ;
}
float VelocitySmoothing : : computeT3 ( float T1 , float accel_prev , float max_jerk )
float VelocitySmoothing : : computeT3 ( float T1 , float a0 , float j_ max)
{
float T3 = accel_prev / max_jerk + T1 ;
if ( T1 < FLT_EPSILON & & T3 < _dt & & T3 > 0.f ) {
T3 = _dt ;
_max_jerk_T1 = accel_prev / T3 ;
}
float T3 = a0 / j_max + T1 ;
return math : : max ( T3 , 0.f ) ;
}
void VelocitySmoothing : : integrateT ( float dt , float jerk , float accel_prev , float vel_prev , float pos_prev ,
float & accel_out , float & vel_out , float & pos_out )
void VelocitySmoothing : : updateDurations ( float t_now , float vel_setpoint )
{
accel_out = jerk * dt + accel_prev ;
_vel_sp = math : : constrain ( vel_setpoint , - _max_vel , _max_vel ) ;
_t0 = t_now ;
_state_init = _state ;
vel_out = dt * 0.5f * ( accel_out + accel_prev ) + vel_prev ;
/* Depending of the direction, start accelerating positively or negatively */
_direction = math : : sign ( _vel_sp - _state . v ) ;
pos_out = dt / 3.f * ( vel_out + accel_prev * dt * 0.5f + 2.f * vel_prev ) + _pos ;
}
if ( _direction ! = 0 ) {
updateDurations ( ) ;
void VelocitySmoothing : : updateDurations ( float dt , float vel_setpoint )
{
_vel_sp = math : : constrain ( vel_setpoint , - _max_vel , _max_vel ) ;
_dt = math : : max ( dt , FLT_EPSILON ) ;
updateDurations ( ) ;
} else {
_T1 = _T2 = _T3 = 0.f ;
}
}
void VelocitySmoothing : : updateDurations ( float T123 )
{
float T1 , T2 , T3 ;
/* Depending of the direction, start accelerating positively or negatively */
_max_jerk_T1 = ( _vel_sp - _vel > 0.f ) ? _max_jerk : - _max_jerk ;
float jerk_max_T1 = _direction * _max_jerk ;
float delta_v = _vel_sp - _state . v ;
// compute increasing acceleration time
if ( T123 < 0.f ) {
T1 = computeT1 ( _accel , _vel , _vel_sp , _max_jerk_T1 ) ;
T1 = computeT1 ( _state . a , delta_v , jerk_max_T1 , _max_accel ) ;
} else {
T1 = computeT1 ( T123 , _accel , _vel , _vel_sp , _max_jerk_T1 ) ;
T1 = computeT1 ( T123 , _state . a , delta_v , jerk_max_T1 , _max_accel ) ;
}
// compute decreasing acceleration time
T3 = computeT3 ( T1 , _accel , _max_jerk _T1 ) ;
T3 = computeT3 ( T1 , _state . a , jerk _max_T1) ;
// compute constant acceleration time
if ( T123 < 0.f ) {
T2 = computeT2 ( T1 , T3 , _accel , _vel , _vel_sp , _max_jerk _T1 ) ;
T2 = computeT2 ( T1 , T3 , _state . a , delta_v , jerk_max _T1 ) ;
} else {
T2 = computeT2 ( T123 , T1 , T3 ) ;
@ -231,52 +208,57 @@ void VelocitySmoothing::updateDurations(float T123)
@@ -231,52 +208,57 @@ void VelocitySmoothing::updateDurations(float T123)
_T3 = T3 ;
}
void VelocitySmoothing : : integrate ( float & accel_setpoint_smooth , float & vel_setpoint_smooth ,
float & pos_setpoint_smooth )
Trajectory VelocitySmoothing : : evaluatePoly ( float j , float a0 , float v0 , float x0 , float t , int d )
{
integrate ( _dt , 1.f , accel_setpoint_smooth , vel_setpoint_smooth , pos_setpoint_smooth ) ;
}
Trajectory traj ;
float jt = d * j ;
float t2 = t * t ;
float t3 = t2 * t ;
void VelocitySmoothing : : integrate ( float dt , float integration_scale_factor , float & accel_setpoint_smooth ,
float & vel_setpoint_smooth ,
float & pos_setpoint_smooth )
{
/* Apply correct jerk (min, max or zero) */
if ( _T1 > FLT_EPSILON ) {
_jerk = _max_jerk_T1 ;
if ( _T1 < dt & & dt > _dt ) {
// _T1 was supposed to be _dt, however, now, dt is bigger than _dt. We have to reduce the jerk to avoid an acceleration overshoot.
_jerk * = _dt / dt ; // Keep the same area _dt * _jerk = dt * jerk_new
}
traj . j = jt ;
traj . a = a0 + jt * t ;
traj . v = v0 + a0 * t + 0.5f * jt * t2 ;
traj . x = x0 + v0 * t + 0.5f * a0 * t2 + 1.f / 6.f * jt * t3 ;
} else if ( _T2 > FLT_EPSILON ) {
_jerk = 0.f ;
} else if ( _T3 > FLT_EPSILON ) {
_jerk = - _max_jerk_T1 ;
return traj ;
}
if ( _T3 < dt & & dt > _dt ) {
// Same as for _T1 < dt above
_jerk * = _dt / dt ;
}
void VelocitySmoothing : : updateTraj ( float t_now , float & accel_setpoint_smooth , float & vel_setpoint_smooth , float & pos_setpoint_smooth )
{
const float t = t_now - _t0 ;
if ( t < = _T1 ) {
float t1 = t ;
_state = evaluatePoly ( _max_jerk , _state_init . a , _state_init . v , _state_init . x , t1 , _direction ) ;
} else if ( t < = _T1 + _T2 ) {
float t1 = _T1 ;
float t2 = t - _T1 ;
_state = evaluatePoly ( _max_jerk , _state_init . a , _state_init . v , _state_init . x , t1 , _direction ) ;
_state = evaluatePoly ( 0.f , _state . a , _state . v , _state . x , t2 , 0.f ) ;
} else if ( t < = _T1 + _T2 + _T3 ) {
float t1 = _T1 ;
float t2 = _T2 ;
float t3 = t - _T1 - _T2 ;
_state = evaluatePoly ( _max_jerk , _state_init . a , _state_init . v , _state_init . x , t1 , _direction ) ;
_state = evaluatePoly ( 0.f , _state . a , _state . v , _state . x , t2 , 0.f ) ;
_state = evaluatePoly ( _max_jerk , _state . a , _state . v , _state . x , t3 , - _direction ) ;
} else {
_jerk = 0.f ;
float t1 = _T1 ;
float t2 = _T2 ;
float t3 = _T3 ;
float t4 = t - _T1 - _T2 - _T3 ;
_state = evaluatePoly ( _max_jerk , _state_init . a , _state_init . v , _state_init . x , t1 , _direction ) ;
_state = evaluatePoly ( 0.f , _state . a , _state . v , _state . x , t2 , 0.f ) ;
_state = evaluatePoly ( _max_jerk , _state . a , _state . v , _state . x , t3 , - _direction ) ;
_state = evaluatePoly ( 0.f , 0.f , _state . v , _state . x , t4 , 0.f ) ;
}
/* Integrate the trajectory */
float accel_new , vel_new , pos_new ;
integrateT ( dt * integration_scale_factor , _jerk , _accel , _vel , _pos , accel_new , vel_new , pos_new ) ;
_accel = accel_new ;
_vel = vel_new ;
_pos = pos_new ;
/* set output variables */
accel_setpoint_smooth = _accel ;
vel_setpoint_smooth = _vel ;
pos_setpoint_smooth = _pos ;
accel_setpoint_smooth = _state . a ;
vel_setpoint_smooth = _state . v ;
pos_setpoint_smooth = _state . x ;
}
void VelocitySmoothing : : timeSynchronization ( VelocitySmoothing * traj , int n_traj )