mirror of https://github.com/ArduPilot/ardupilot
geofence: added fence status reporting and faster altitude check
This commit is contained in:
parent
2e2b320560
commit
b3327c64de
|
@ -819,7 +819,7 @@ static void update_GPS(void)
|
||||||
current_loc.lat = g_gps->latitude; // Lat * 10**7
|
current_loc.lat = g_gps->latitude; // Lat * 10**7
|
||||||
|
|
||||||
// see if we've breached the geo-fence
|
// see if we've breached the geo-fence
|
||||||
geofence_check();
|
geofence_check(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,6 +980,8 @@ static void update_alt()
|
||||||
current_loc.alt += g.altitude_mix * (read_barometer() + home.alt);
|
current_loc.alt += g.altitude_mix * (read_barometer() + home.alt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
geofence_check(true);
|
||||||
|
|
||||||
// Calculate new climb rate
|
// Calculate new climb rate
|
||||||
//if(medium_loopCounter == 0 && slow_loopCounter == 0)
|
//if(medium_loopCounter == 0 && slow_loopCounter == 0)
|
||||||
// add_altitude_data(millis() / 100, g_gps->altitude / 10);
|
// add_altitude_data(millis() / 100, g_gps->altitude / 10);
|
||||||
|
|
|
@ -120,6 +120,14 @@ static NOINLINE void send_attitude(mavlink_channel_t chan)
|
||||||
omega.z);
|
omega.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GEOFENCE_ENABLED == ENABLED
|
||||||
|
static NOINLINE void send_fence_status(mavlink_channel_t chan)
|
||||||
|
{
|
||||||
|
geofence_send_status(chan);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t packet_drops)
|
static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t packet_drops)
|
||||||
{
|
{
|
||||||
#ifdef MAVLINK10
|
#ifdef MAVLINK10
|
||||||
|
@ -612,6 +620,13 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
|
||||||
send_statustext(chan);
|
send_statustext(chan);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if GEOFENCE_ENABLED == ENABLED
|
||||||
|
case MSG_FENCE_STATUS:
|
||||||
|
CHECK_PAYLOAD_SIZE(FENCE_STATUS);
|
||||||
|
send_fence_status(chan);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case MSG_RETRY_DEFERRED:
|
case MSG_RETRY_DEFERRED:
|
||||||
break; // just here to prevent a warning
|
break; // just here to prevent a warning
|
||||||
}
|
}
|
||||||
|
@ -820,6 +835,7 @@ GCS_MAVLINK::data_stream_send(uint16_t freqMin, uint16_t freqMax)
|
||||||
send_message(MSG_CURRENT_WAYPOINT);
|
send_message(MSG_CURRENT_WAYPOINT);
|
||||||
send_message(MSG_GPS_RAW); // TODO - remove this message after location message is working
|
send_message(MSG_GPS_RAW); // TODO - remove this message after location message is working
|
||||||
send_message(MSG_NAV_CONTROLLER_OUTPUT);
|
send_message(MSG_NAV_CONTROLLER_OUTPUT);
|
||||||
|
send_message(MSG_FENCE_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freqLoopMatch(streamRatePosition, freqMin, freqMax)) {
|
if (freqLoopMatch(streamRatePosition, freqMin, freqMax)) {
|
||||||
|
@ -1635,6 +1651,8 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
|
||||||
// receive a fence point from GCS and store in EEPROM
|
// receive a fence point from GCS and store in EEPROM
|
||||||
case MAVLINK_MSG_ID_FENCE_POINT: {
|
case MAVLINK_MSG_ID_FENCE_POINT: {
|
||||||
mavlink_fence_point_t packet;
|
mavlink_fence_point_t packet;
|
||||||
|
if (mavlink_check_target(packet.target_system, packet.target_component))
|
||||||
|
break;
|
||||||
mavlink_msg_fence_point_decode(msg, &packet);
|
mavlink_msg_fence_point_decode(msg, &packet);
|
||||||
if (g.fence_action != FENCE_ACTION_NONE) {
|
if (g.fence_action != FENCE_ACTION_NONE) {
|
||||||
send_text(SEVERITY_LOW,PSTR("fencing must be disabled"));
|
send_text(SEVERITY_LOW,PSTR("fencing must be disabled"));
|
||||||
|
@ -1652,12 +1670,14 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
|
||||||
// send a fence point to GCS
|
// send a fence point to GCS
|
||||||
case MAVLINK_MSG_ID_FENCE_FETCH_POINT: {
|
case MAVLINK_MSG_ID_FENCE_FETCH_POINT: {
|
||||||
mavlink_fence_fetch_point_t packet;
|
mavlink_fence_fetch_point_t packet;
|
||||||
|
if (mavlink_check_target(packet.target_system, packet.target_component))
|
||||||
|
break;
|
||||||
mavlink_msg_fence_fetch_point_decode(msg, &packet);
|
mavlink_msg_fence_fetch_point_decode(msg, &packet);
|
||||||
if (packet.idx >= g.fence_total) {
|
if (packet.idx >= g.fence_total) {
|
||||||
send_text(SEVERITY_LOW,PSTR("bad fence point"));
|
send_text(SEVERITY_LOW,PSTR("bad fence point"));
|
||||||
} else {
|
} else {
|
||||||
Vector2f point = get_fence_point_with_index(packet.idx);
|
Vector2f point = get_fence_point_with_index(packet.idx);
|
||||||
mavlink_msg_fence_point_send(chan, packet.idx, g.fence_total, point.x, point.y);
|
mavlink_msg_fence_point_send(chan, 0, 0, packet.idx, g.fence_total, point.x, point.y);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,7 @@ enum ap_message {
|
||||||
MSG_NEXT_WAYPOINT,
|
MSG_NEXT_WAYPOINT,
|
||||||
MSG_NEXT_PARAM,
|
MSG_NEXT_PARAM,
|
||||||
MSG_STATUSTEXT,
|
MSG_STATUSTEXT,
|
||||||
|
MSG_FENCE_STATUS,
|
||||||
MSG_RETRY_DEFERRED // this must be last
|
MSG_RETRY_DEFERRED // this must be last
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@ static struct geofence_state {
|
||||||
uint8_t num_points;
|
uint8_t num_points;
|
||||||
bool boundary_uptodate;
|
bool boundary_uptodate;
|
||||||
bool fence_triggered;
|
bool fence_triggered;
|
||||||
|
uint16_t breach_count;
|
||||||
|
uint8_t breach_type;
|
||||||
|
uint32_t breach_time;
|
||||||
/* point 0 is the return point */
|
/* point 0 is the return point */
|
||||||
Vector2f boundary[MAX_FENCEPOINTS];
|
Vector2f boundary[MAX_FENCEPOINTS];
|
||||||
} *geofence_state;
|
} *geofence_state;
|
||||||
|
@ -29,10 +32,10 @@ static struct geofence_state {
|
||||||
*/
|
*/
|
||||||
static Vector2f get_fence_point_with_index(unsigned i)
|
static Vector2f get_fence_point_with_index(unsigned i)
|
||||||
{
|
{
|
||||||
uint32_t mem;
|
uint32_t mem;
|
||||||
Vector2f ret;
|
Vector2f ret;
|
||||||
|
|
||||||
if (i > (unsigned)g.fence_total) {
|
if (i > (unsigned)g.fence_total) {
|
||||||
return Vector2f(0,0);
|
return Vector2f(0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,24 +45,24 @@ static Vector2f get_fence_point_with_index(unsigned i)
|
||||||
mem += sizeof(float);
|
mem += sizeof(float);
|
||||||
eeprom_read_block(&ret.y, (void *)mem, sizeof(float));
|
eeprom_read_block(&ret.y, (void *)mem, sizeof(float));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save a fence point
|
// save a fence point
|
||||||
static void set_fence_point_with_index(Vector2f &point, unsigned i)
|
static void set_fence_point_with_index(Vector2f &point, unsigned i)
|
||||||
{
|
{
|
||||||
uint32_t mem;
|
uint32_t mem;
|
||||||
|
|
||||||
if (i >= (unsigned)g.fence_total.get()) {
|
if (i >= (unsigned)g.fence_total.get()) {
|
||||||
// not allowed
|
// not allowed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem = FENCE_START_BYTE + (i * FENCE_WP_SIZE);
|
mem = FENCE_START_BYTE + (i * FENCE_WP_SIZE);
|
||||||
|
|
||||||
eeprom_write_block(&point.x, (void *)mem, sizeof(float));
|
eeprom_write_block(&point.x, (void *)mem, sizeof(float));
|
||||||
mem += 4;
|
mem += 4;
|
||||||
eeprom_write_block(&point.y, (void *)mem, sizeof(float));
|
eeprom_write_block(&point.y, (void *)mem, sizeof(float));
|
||||||
|
|
||||||
if (geofence_state != NULL) {
|
if (geofence_state != NULL) {
|
||||||
geofence_state->boundary_uptodate = false;
|
geofence_state->boundary_uptodate = false;
|
||||||
|
@ -135,10 +138,39 @@ static bool geofence_enabled(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
return true if we have breached the geo-fence minimum altiude
|
||||||
|
*/
|
||||||
|
static bool geofence_check_minalt(void)
|
||||||
|
{
|
||||||
|
if (g.fence_maxalt <= g.fence_minalt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (g.fence_minalt == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (current_loc.alt < (g.fence_minalt*100) + home.alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
return true if we have breached the geo-fence maximum altiude
|
||||||
|
*/
|
||||||
|
static bool geofence_check_maxalt(void)
|
||||||
|
{
|
||||||
|
if (g.fence_maxalt <= g.fence_minalt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (g.fence_maxalt == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (current_loc.alt > (g.fence_maxalt*100) + home.alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
check if we have breached the geo-fence
|
check if we have breached the geo-fence
|
||||||
*/
|
*/
|
||||||
static void geofence_check(void)
|
static void geofence_check(bool altitude_check_only)
|
||||||
{
|
{
|
||||||
if (!geofence_enabled()) {
|
if (!geofence_enabled()) {
|
||||||
return;
|
return;
|
||||||
|
@ -147,30 +179,36 @@ static void geofence_check(void)
|
||||||
/* allocate the geo-fence state if need be */
|
/* allocate the geo-fence state if need be */
|
||||||
if (geofence_state == NULL || !geofence_state->boundary_uptodate) {
|
if (geofence_state == NULL || !geofence_state->boundary_uptodate) {
|
||||||
geofence_load();
|
geofence_load();
|
||||||
if (g.fence_action == FENCE_ACTION_NONE) {
|
if (!geofence_enabled()) {
|
||||||
// may have been disabled by load
|
// may have been disabled by load
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool outside = false;
|
bool outside = false;
|
||||||
|
uint8_t breach_type = FENCE_BREACH_NONE;
|
||||||
|
|
||||||
if (g.fence_maxalt > g.fence_minalt &&
|
if (geofence_check_minalt()) {
|
||||||
((g.fence_minalt != 0 && current_loc.alt < (g.fence_minalt*100) + home.alt) ||
|
|
||||||
(current_loc.alt > (g.fence_maxalt*100) + home.alt))) {
|
|
||||||
// we are too high or low
|
|
||||||
outside = true;
|
outside = true;
|
||||||
} else {
|
breach_type = FENCE_BREACH_MINALT;
|
||||||
|
} else if (geofence_check_maxalt()) {
|
||||||
|
outside = true;
|
||||||
|
breach_type = FENCE_BREACH_MAXALT;
|
||||||
|
} else if (!altitude_check_only) {
|
||||||
Vector2f location;
|
Vector2f location;
|
||||||
location.x = 1.0e-7 * current_loc.lat;
|
location.x = 1.0e-7 * current_loc.lat;
|
||||||
location.y = 1.0e-7 * current_loc.lng;
|
location.y = 1.0e-7 * current_loc.lng;
|
||||||
outside = Polygon_outside(location, &geofence_state->boundary[1], geofence_state->num_points-1);
|
outside = Polygon_outside(location, &geofence_state->boundary[1], geofence_state->num_points-1);
|
||||||
|
if (outside) {
|
||||||
|
breach_type = FENCE_BREACH_BOUNDARY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!outside) {
|
if (!outside) {
|
||||||
if (geofence_state->fence_triggered) {
|
if (geofence_state->fence_triggered && !altitude_check_only) {
|
||||||
// we have moved back inside the fence
|
// we have moved back inside the fence
|
||||||
geofence_state->fence_triggered = false;
|
geofence_state->fence_triggered = false;
|
||||||
|
gcs_send_text_P(SEVERITY_LOW,PSTR("geo-fence OK"));
|
||||||
}
|
}
|
||||||
// we're inside, all is good with the world
|
// we're inside, all is good with the world
|
||||||
return;
|
return;
|
||||||
|
@ -186,6 +224,9 @@ static void geofence_check(void)
|
||||||
|
|
||||||
// we are outside, and have not previously triggered.
|
// we are outside, and have not previously triggered.
|
||||||
geofence_state->fence_triggered = true;
|
geofence_state->fence_triggered = true;
|
||||||
|
geofence_state->breach_count++;
|
||||||
|
geofence_state->breach_time = millis();
|
||||||
|
geofence_state->breach_type = breach_type;
|
||||||
gcs_send_text_P(SEVERITY_LOW,PSTR("geo-fence triggered"));
|
gcs_send_text_P(SEVERITY_LOW,PSTR("geo-fence triggered"));
|
||||||
|
|
||||||
// see what action the user wants
|
// see what action the user wants
|
||||||
|
@ -234,9 +275,24 @@ static bool geofence_stickmixing(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
static void geofence_send_status(mavlink_channel_t chan)
|
||||||
|
{
|
||||||
|
if (geofence_enabled() && geofence_state != NULL) {
|
||||||
|
mavlink_msg_fence_status_send(chan,
|
||||||
|
(int8_t)geofence_state->fence_triggered,
|
||||||
|
geofence_state->breach_count,
|
||||||
|
geofence_state->breach_type,
|
||||||
|
geofence_state->breach_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else // GEOFENCE_ENABLED
|
#else // GEOFENCE_ENABLED
|
||||||
|
|
||||||
static void geofence_check(void) { }
|
static void geofence_check(bool altitude_check_only) { }
|
||||||
static bool geofence_stickmixing(void) { return true; }
|
static bool geofence_stickmixing(void) { return true; }
|
||||||
|
static bool geofence_enabled(void) { return false; }
|
||||||
|
|
||||||
#endif // GEOFENCE_ENABLED
|
#endif // GEOFENCE_ENABLED
|
||||||
|
|
Loading…
Reference in New Issue