diff --git a/ArduPlane/GCS_Mavlink.cpp b/ArduPlane/GCS_Mavlink.cpp index 4ffb021e3d..97e4cbead5 100644 --- a/ArduPlane/GCS_Mavlink.cpp +++ b/ArduPlane/GCS_Mavlink.cpp @@ -1146,6 +1146,82 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg) break; } + case MAVLINK_MSG_ID_COMMAND_INT: + { + // decode + mavlink_command_int_t packet; + mavlink_msg_command_int_decode(msg, &packet); + + uint8_t result = MAV_RESULT_UNSUPPORTED; + + switch(packet.command) { + + case MAV_CMD_DO_REPOSITION: + Location requested_position {}; + requested_position.lat = packet.x; + requested_position.lng = packet.y; + + // check the floating representation for overflow of altitude + if (abs(packet.z * 100.0f) >= 0x7fffff) { + result = MAV_RESULT_FAILED; + break; + } + requested_position.alt = (int32_t)(packet.z * 100.0f); + + // load option flags + if (packet.frame == MAV_FRAME_GLOBAL_RELATIVE_ALT_INT) { + requested_position.flags.relative_alt = 1; + } + else if (packet.frame == MAV_FRAME_GLOBAL_TERRAIN_ALT_INT) { + requested_position.flags.terrain_alt = 1; + } + else if (packet.frame != MAV_FRAME_GLOBAL_INT) { + // not a supported frame + break; + } + + if (is_zero(packet.param4)) { + requested_position.flags.loiter_ccw = 0; + } else { + requested_position.flags.loiter_ccw = 1; + } + + if (location_sanitize(plane.current_loc, requested_position)) { + // if the location wasn't already sane don't load it + result = MAV_RESULT_FAILED; // failed as the location is not valid + break; + } + + // location is valid load and set + if (((int32_t)packet.param2 & MAV_DO_REPOSITION_FLAGS_CHANGE_MODE) || + (plane.control_mode == GUIDED)) { + plane.set_mode(GUIDED); + plane.guided_WP_loc = requested_position; + + // add home alt if needed + if (plane.guided_WP_loc.flags.relative_alt) { + plane.guided_WP_loc.alt += plane.home.alt; + plane.guided_WP_loc.flags.relative_alt = 0; + } + + plane.set_guided_WP(); + + result = MAV_RESULT_ACCEPTED; + } else { + result = MAV_RESULT_FAILED; // failed as we are not in guided + } + break; + } + + mavlink_msg_command_ack_send_buf( + msg, + chan, + packet.command, + result); + + break; + } + case MAVLINK_MSG_ID_COMMAND_LONG: { // decode diff --git a/ArduPlane/capabilities.cpp b/ArduPlane/capabilities.cpp index fd9ab981be..d7e552944d 100644 --- a/ArduPlane/capabilities.cpp +++ b/ArduPlane/capabilities.cpp @@ -6,4 +6,5 @@ void Plane::init_capabilities(void) { hal.util->set_capabilities(MAV_PROTOCOL_CAPABILITY_MISSION_FLOAT); hal.util->set_capabilities(MAV_PROTOCOL_CAPABILITY_PARAM_FLOAT); + hal.util->set_capabilities(MAV_PROTOCOL_CAPABILITY_COMMAND_INT); } diff --git a/ArduPlane/commands.cpp b/ArduPlane/commands.cpp index e4d8b9acd3..ef8f9e6f53 100644 --- a/ArduPlane/commands.cpp +++ b/ArduPlane/commands.cpp @@ -71,7 +71,7 @@ void Plane::set_next_WP(const struct Location &loc) void Plane::set_guided_WP(void) { - if (g.loiter_radius < 0) { + if (g.loiter_radius < 0 || guided_WP_loc.flags.loiter_ccw) { loiter.direction = -1; } else { loiter.direction = 1; diff --git a/ArduPlane/navigation.cpp b/ArduPlane/navigation.cpp index 6393d1d428..3358f3b471 100644 --- a/ArduPlane/navigation.cpp +++ b/ArduPlane/navigation.cpp @@ -140,7 +140,11 @@ void Plane::update_loiter(uint16_t radius) if (radius <= 1) { // if radius is <=1 then use the general loiter radius. if it's small, use default radius = (abs(g.loiter_radius) <= 1) ? LOITER_RADIUS_DEFAULT : abs(g.loiter_radius); - loiter.direction = (g.loiter_radius < 0) ? -1 : 1; + if (next_WP_loc.flags.loiter_ccw == 1) { + loiter.direction = -1; + } else { + loiter.direction = (g.loiter_radius < 0) ? -1 : 1; + } } if (loiter.start_time_ms == 0 &&