mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-18 08:54:15 +01:00
PathPlanner: added functions to allow circular paths and implement that feature in FixedWingPathFollower
This commit is contained in:
parent
45258a6561
commit
9dfd34dd19
@ -35,5 +35,6 @@ struct path_status {
|
||||
};
|
||||
|
||||
void path_progress(float * start_point, float * end_point, float * cur_point, struct path_status * status);
|
||||
void circle_progress(float * start_point, float * end_point, float * cur_point, struct path_status * status, bool clockwise);
|
||||
|
||||
#endif
|
||||
|
@ -78,3 +78,59 @@ void path_progress(float * start_point, float * end_point, float * cur_point, st
|
||||
status->error = fabs(status->error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute progress along circular path and deviation from it
|
||||
* @param[in] start_point Starting point
|
||||
* @param[in] end_point Center point
|
||||
* @param[in] cur_point Current location
|
||||
* @param[out] status Structure containing progress along path and deviation
|
||||
*/
|
||||
void circle_progress(float * start_point, float * end_point, float * cur_point, struct path_status * status, bool clockwise)
|
||||
{
|
||||
float radius_north, radius_east, diff_north, diff_east;
|
||||
float radius;
|
||||
float normal[2];
|
||||
|
||||
// Radius
|
||||
radius_north = end_point[0] - start_point[0];
|
||||
radius_east = end_point[1] - start_point[1];
|
||||
|
||||
// Current location relative to center
|
||||
diff_north = cur_point[0] - end_point[0];
|
||||
diff_east = cur_point[1] - end_point[1];
|
||||
|
||||
radius = sqrtf( radius_north * radius_north + radius_east * radius_east );
|
||||
|
||||
if(radius < 1e-3) {
|
||||
status->fractional_progress = 1;
|
||||
status->error = 0;
|
||||
status->correction_direction[0] = status->correction_direction[1] = 0;
|
||||
status->path_direction[0] = status->path_direction[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (clockwise) {
|
||||
// Compute the normal to the radius clockwise
|
||||
normal[0] = radius_east / radius;
|
||||
normal[1] = -radius_north / radius;
|
||||
} else {
|
||||
// Compute the normal to the radius counter clockwise
|
||||
normal[0] = -radius_east / radius;
|
||||
normal[1] = radius_north / radius;
|
||||
}
|
||||
|
||||
status->fractional_progress = (clockwise?1:-1) * atan2f( diff_north, diff_east) - atan2f( radius_north, radius_east);
|
||||
|
||||
// error is current radius minus wanted radius - positive if too close
|
||||
status->error = radius - sqrtf( diff_north * diff_north + diff_east * diff_east );
|
||||
|
||||
// Compute direction to correct error
|
||||
status->correction_direction[0] = -status->error * radius_north / radius;
|
||||
status->correction_direction[1] = -status->error * radius_east / radius;
|
||||
|
||||
// Compute direction to travel
|
||||
status->path_direction[0] = normal[0];
|
||||
status->path_direction[1] = normal[1];
|
||||
|
||||
status->error = fabs(status->error);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ static FixedWingPathFollowerSettingsData fixedwingpathfollowerSettings;
|
||||
// Private functions
|
||||
static void pathfollowerTask(void *parameters);
|
||||
static void SettingsUpdatedCb(UAVObjEvent * ev);
|
||||
static void updatePathVelocity();
|
||||
static void updatePathVelocity(int8_t circledirection);
|
||||
static void updateEndpointVelocity();
|
||||
static void updateFixedDesiredAttitude();
|
||||
static void updateFixedAttitude();
|
||||
@ -140,7 +140,6 @@ static float courseIntegral = 0;
|
||||
static float speedIntegral = 0;
|
||||
static float accelIntegral = 0;
|
||||
static float powerIntegral = 0;
|
||||
static uint8_t positionHoldLast = 0;
|
||||
|
||||
// correct speed by measured airspeed
|
||||
static float baroAirspeedBias = 0;
|
||||
@ -212,7 +211,17 @@ static void pathfollowerTask(void *parameters)
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE,SYSTEMALARMS_ALARM_OK);
|
||||
break;
|
||||
case PATHDESIRED_MODE_FLYVECTOR:
|
||||
updatePathVelocity();
|
||||
updatePathVelocity(0);
|
||||
updateFixedDesiredAttitude();
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE,SYSTEMALARMS_ALARM_OK);
|
||||
break;
|
||||
case PATHDESIRED_MODE_FLYCIRCLERIGHT:
|
||||
updatePathVelocity(1);
|
||||
updateFixedDesiredAttitude();
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE,SYSTEMALARMS_ALARM_OK);
|
||||
break;
|
||||
case PATHDESIRED_MODE_FLYCIRCLELEFT:
|
||||
updatePathVelocity(-1);
|
||||
updateFixedDesiredAttitude();
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE,SYSTEMALARMS_ALARM_OK);
|
||||
break;
|
||||
@ -250,7 +259,7 @@ static void pathfollowerTask(void *parameters)
|
||||
* Takes in @ref PositionActual and compares it to @ref PathDesired
|
||||
* and computes @ref VelocityDesired
|
||||
*/
|
||||
static void updatePathVelocity()
|
||||
static void updatePathVelocity(int8_t circledirection)
|
||||
{
|
||||
//float dT = fixedwingpathfollowerSettings.UpdatePeriod / 1000.0f;
|
||||
float downCommand;
|
||||
@ -260,36 +269,44 @@ static void updatePathVelocity()
|
||||
|
||||
float cur[3] = {positionActual.North, positionActual.East, positionActual.Down};
|
||||
struct path_status progress;
|
||||
|
||||
if (!circledirection) {
|
||||
path_progress(pathDesired.Start, pathDesired.End, cur, &progress);
|
||||
} else {
|
||||
circle_progress(pathDesired.Start, pathDesired.End, cur, &progress, circledirection>0 );
|
||||
}
|
||||
|
||||
path_progress(pathDesired.Start, pathDesired.End, cur, &progress);
|
||||
|
||||
float groundspeed = pathDesired.StartingVelocity +
|
||||
(pathDesired.EndingVelocity - pathDesired.StartingVelocity) * progress.fractional_progress;
|
||||
if(progress.fractional_progress > 1)
|
||||
float groundspeed;
|
||||
if (!circledirection && progress.fractional_progress<1) {
|
||||
groundspeed = pathDesired.StartingVelocity +
|
||||
(pathDesired.EndingVelocity - pathDesired.StartingVelocity) * progress.fractional_progress;
|
||||
} else {
|
||||
groundspeed = pathDesired.EndingVelocity;
|
||||
}
|
||||
|
||||
VelocityDesiredData velocityDesired;
|
||||
velocityDesired.North = progress.path_direction[0] * groundspeed;
|
||||
velocityDesired.East = progress.path_direction[1] * groundspeed;
|
||||
|
||||
float error_speed = progress.error * fixedwingpathfollowerSettings.HorizontalPosP;
|
||||
float correction_velocity[2] = {progress.correction_direction[0] * error_speed,
|
||||
progress.correction_direction[1] * error_speed};
|
||||
|
||||
// prevent div by zero
|
||||
if (fabsf(correction_velocity[0])+fabsf(correction_velocity[1]) <1e-6) {
|
||||
correction_velocity[0]=1e-6;
|
||||
}
|
||||
|
||||
float total_vel = sqrtf(powf(correction_velocity[0],2) + powf(correction_velocity[1],2));
|
||||
velocityDesired.North += progress.correction_direction[0] * error_speed;
|
||||
velocityDesired.East += progress.correction_direction[1] * error_speed;
|
||||
|
||||
float total_vel = sqrtf(powf(velocityDesired.North,2) + powf(velocityDesired.East,2));
|
||||
float scale = 1;
|
||||
if(total_vel > fixedwingpathfollowerSettings.HorizontalVelMax)
|
||||
if(total_vel > fixedwingpathfollowerSettings.HorizontalVelMax) {
|
||||
scale = fixedwingpathfollowerSettings.HorizontalVelMax / total_vel;
|
||||
if (total_vel < fixedwingpathfollowerSettings.HorizontalVelMin)
|
||||
} else if (total_vel < fixedwingpathfollowerSettings.HorizontalVelMin && total_vel>1e-6) {
|
||||
scale = fixedwingpathfollowerSettings.HorizontalVelMin / total_vel;
|
||||
|
||||
velocityDesired.North += progress.correction_direction[0] * error_speed * scale;
|
||||
velocityDesired.East += progress.correction_direction[1] * error_speed * scale;
|
||||
} else {
|
||||
/* if we are not supposed to move, head north with minimum velocity - to prevent errors */
|
||||
scale = 1;
|
||||
velocityDesired.North = fixedwingpathfollowerSettings.HorizontalVelMin;
|
||||
velocityDesired.East = 0;
|
||||
}
|
||||
velocityDesired.North*= scale;
|
||||
velocityDesired.East *= scale;
|
||||
|
||||
float altitudeSetpoint = pathDesired.Start[2] + (pathDesired.End[2] - pathDesired.Start[2]) *
|
||||
bound(progress.fractional_progress,0,1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user