AC_Avoid: add stopping behaviour

This commit is contained in:
Randy Mackay 2017-12-12 21:19:37 +09:00
parent c28cfcdc27
commit 9d74d82ff6
2 changed files with 74 additions and 20 deletions

View File

@ -34,6 +34,13 @@ const AP_Param::GroupInfo AC_Avoid::var_info[] = {
// @User: Standard // @User: Standard
AP_GROUPINFO("MARGIN", 4, AC_Avoid, _margin, 2.0f), AP_GROUPINFO("MARGIN", 4, AC_Avoid, _margin, 2.0f),
// @Param: BEHAVE
// @DisplayName: Avoidance behaviour
// @Description: Avoidance behaviour (slide or stop)
// @Values: 0:Slide,1:Stop
// @User: Standard
AP_GROUPINFO("BEHAVE", 5, AC_Avoid, _behavior, 0),
AP_GROUPEND AP_GROUPEND
}; };
@ -230,13 +237,25 @@ void AC_Avoid::adjust_velocity_circle_fence(float kP, float accel_cmss, Vector2f
float stopping_point_length = stopping_point.length(); float stopping_point_length = stopping_point.length();
if (stopping_point_length > fence_radius - margin_cm) { if (stopping_point_length > fence_radius - margin_cm) {
// Unsafe desired velocity - will not be able to stop before fence breach // Unsafe desired velocity - will not be able to stop before fence breach
// Project stopping point radially onto fence boundary if ((AC_Avoid::BehaviourType)_behavior.get() == BEHAVIOR_SLIDE) {
// Adjusted velocity will point towards this projected point at a safe speed // Project stopping point radially onto fence boundary
Vector2f target = stopping_point * ((fence_radius - margin_cm) / stopping_point_length); // Adjusted velocity will point towards this projected point at a safe speed
Vector2f target_direction = target - position_xy; const Vector2f target = stopping_point * ((fence_radius - margin_cm) / stopping_point_length);
float distance_to_target = target_direction.length(); const Vector2f target_direction = target - position_xy;
float max_speed = get_max_speed(kP, accel_cmss, distance_to_target, dt); const float distance_to_target = target_direction.length();
desired_vel = target_direction * (MIN(speed,max_speed) / distance_to_target); const float max_speed = get_max_speed(kP, accel_cmss, distance_to_target, dt);
desired_vel = target_direction * (MIN(speed,max_speed) / distance_to_target);
} else {
// shorten vector without adjusting its direction
Vector2f intersection;
if (Vector2f::circle_segment_intersection(position_xy, stopping_point, Vector2f(0.0f,0.0f), fence_radius, intersection)) {
const float distance_to_target = MAX((intersection - position_xy).length() - margin_cm, 0.0f);
const float max_speed = get_max_speed(kP, accel_cmss, distance_to_target, dt);
if (max_speed < speed) {
desired_vel *= MAX(max_speed, 0.0f) / speed;
}
}
}
} }
} }
} }
@ -354,26 +373,54 @@ void AC_Avoid::adjust_velocity_polygon(float kP, float accel_cmss, Vector2f &des
} }
// calc margin in cm // calc margin in cm
float margin_cm = MAX(margin * 100.0f, 0); float margin_cm = MAX(margin * 100.0f, 0.0f);
// for stopping
float speed = safe_vel.length();
Vector2f stopping_point = position_xy + safe_vel*((2.0f + get_stopping_distance(kP, accel_cmss, speed))/speed);
uint16_t i, j; uint16_t i, j;
for (i = 1, j = num_points-1; i < num_points; j = i++) { for (i = 1, j = num_points-1; i < num_points; j = i++) {
// end points of current edge // end points of current edge
Vector2f start = boundary[j]; Vector2f start = boundary[j];
Vector2f end = boundary[i]; Vector2f end = boundary[i];
// vector from current position to closest point on current edge if ((AC_Avoid::BehaviourType)_behavior.get() == BEHAVIOR_SLIDE) {
Vector2f limit_direction = Vector2f::closest_point(position_xy, start, end) - position_xy; // vector from current position to closest point on current edge
// distance to closest point Vector2f limit_direction = Vector2f::closest_point(position_xy, start, end) - position_xy;
const float limit_distance = limit_direction.length(); // distance to closest point
if (!is_zero(limit_distance)) { const float limit_distance = limit_direction.length();
// We are strictly inside the given edge. if (!is_zero(limit_distance)) {
// Adjust velocity to not violate this edge. // We are strictly inside the given edge.
limit_direction /= limit_distance; // Adjust velocity to not violate this edge.
limit_velocity(kP, accel_cmss, safe_vel, limit_direction, MAX(limit_distance - margin_cm,0.0f), dt); limit_direction /= limit_distance;
limit_velocity(kP, accel_cmss, safe_vel, limit_direction, MAX(limit_distance - margin_cm,0.0f), dt);
} else {
// We are exactly on the edge - treat this as a fence breach.
// i.e. do not adjust velocity.
return;
}
} else { } else {
// We are exactly on the edge - treat this as a fence breach. // find intersection with line segment
// i.e. do not adjust velocity. Vector2f intersection;
return; if (Vector2f::segment_intersection(position_xy, stopping_point, start, end, intersection)) {
// vector from current position to point on current edge
Vector2f limit_direction = intersection - position_xy;
const float limit_distance = limit_direction.length();
if (!is_zero(limit_distance)) {
if (limit_distance <= margin_cm) {
// we are within the margin so stop vehicle
safe_vel.zero();
} else {
// vehicle inside the given edge, adjust velocity to not violate this edge
limit_direction /= limit_distance;
limit_velocity(kP, accel_cmss, safe_vel, limit_direction, MAX(limit_distance - margin_cm, 0.0f), dt);
}
} else {
// We are exactly on the edge - treat this as a fence breach.
// i.e. do not adjust velocity.
return;
}
}
} }
} }

View File

@ -57,6 +57,12 @@ public:
static const struct AP_Param::GroupInfo var_info[]; static const struct AP_Param::GroupInfo var_info[];
private: private:
// behaviour types (see BEHAVE parameter)
enum BehaviourType {
BEHAVIOR_SLIDE = 0,
BEHAVIOR_STOP = 1
};
/* /*
* Adjusts the desired velocity for the circular fence. * Adjusts the desired velocity for the circular fence.
*/ */
@ -125,6 +131,7 @@ private:
AP_Int16 _angle_max; // maximum lean angle to avoid obstacles (only used in non-GPS flight modes) AP_Int16 _angle_max; // maximum lean angle to avoid obstacles (only used in non-GPS flight modes)
AP_Float _dist_max; // distance (in meters) from object at which obstacle avoidance will begin in non-GPS modes AP_Float _dist_max; // distance (in meters) from object at which obstacle avoidance will begin in non-GPS modes
AP_Float _margin; // vehicle will attempt to stay this distance (in meters) from objects while in GPS modes AP_Float _margin; // vehicle will attempt to stay this distance (in meters) from objects while in GPS modes
AP_Int8 _behavior; // avoidance behaviour (slide or stop)
bool _proximity_enabled = true; // true if proximity sensor based avoidance is enabled (used to allow pilot to enable/disable) bool _proximity_enabled = true; // true if proximity sensor based avoidance is enabled (used to allow pilot to enable/disable)
}; };