Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle "Reset Mission" param in DO_SET_MISSION_CURRENT command #25130

68 changes: 68 additions & 0 deletions Tools/autotest/arducopter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3226,6 +3226,71 @@ def FlyMissionTwice(self):
self.wait_disarmed()
self.delay_sim_time(20)

def FlyMissionTwiceWithReset(self):
'''Fly a mission twice in a row without changing modes in between.
Allow the mission to complete, then reset the mission state machine and restart the mission.'''

self.upload_simple_relhome_mission([
(mavutil.mavlink.MAV_CMD_NAV_TAKEOFF, 0, 0, 20),
(mavutil.mavlink.MAV_CMD_NAV_WAYPOINT, 20, 0, 20),
(mavutil.mavlink.MAV_CMD_NAV_RETURN_TO_LAUNCH, 0, 0, 0),
])

num_wp = self.get_mission_count()
self.set_parameter("AUTO_OPTIONS", 3)
self.change_mode('AUTO')
self.wait_ready_to_arm()

for i in 1, 2:
self.progress("run %u" % i)
# Use the "Reset Mission" param of DO_SET_MISSION_CURRENT to reset mission state machine
self.set_current_waypoint_using_mav_cmd_do_set_mission_current(seq=0, reset=1)
self.arm_vehicle()
self.wait_waypoint(num_wp-1, num_wp-1)
self.wait_disarmed()
self.delay_sim_time(20)

def MissionIndexValidity(self):
'''Confirm that attempting to select an invalid mission item is rejected.'''

self.upload_simple_relhome_mission([
(mavutil.mavlink.MAV_CMD_NAV_TAKEOFF, 0, 0, 20),
(mavutil.mavlink.MAV_CMD_NAV_WAYPOINT, 20, 0, 20),
(mavutil.mavlink.MAV_CMD_NAV_RETURN_TO_LAUNCH, 0, 0, 0),
])

num_wp = self.get_mission_count()
accepted_indices = [0, 1, num_wp-1]
denied_indices = [-1, num_wp]

for seq in accepted_indices:
self.run_cmd(mavutil.mavlink.MAV_CMD_DO_SET_MISSION_CURRENT,
p1=seq,
timeout=1,
want_result=mavutil.mavlink.MAV_RESULT_ACCEPTED)

for seq in denied_indices:
self.run_cmd(mavutil.mavlink.MAV_CMD_DO_SET_MISSION_CURRENT,
p1=seq,
timeout=1,
want_result=mavutil.mavlink.MAV_RESULT_DENIED)

def InvalidJumpTags(self):
'''Verify the behaviour when selecting invalid jump tags.'''

MAX_TAG_NUM = 65535
# Jump tag is not present, so expect FAILED
self.run_cmd(mavutil.mavlink.MAV_CMD_DO_JUMP_TAG,
p1=MAX_TAG_NUM,
timeout=1,
want_result=mavutil.mavlink.MAV_RESULT_FAILED)

# Jump tag is too big, so expect DENIED
self.run_cmd(mavutil.mavlink.MAV_CMD_DO_JUMP_TAG,
p1=MAX_TAG_NUM+1,
timeout=1,
want_result=mavutil.mavlink.MAV_RESULT_DENIED)

def GPSViconSwitching(self):
"""Fly GPS and Vicon switching test"""
self.customise_SITL_commandline(["--uartF=sim:vicon:"])
Expand Down Expand Up @@ -10544,6 +10609,9 @@ def tests2b(self): # this block currently around 9.5mins here
self.ThrottleGainBoost,
self.ScriptMountPOI,
self.FlyMissionTwice,
self.FlyMissionTwiceWithReset,
self.MissionIndexValidity,
self.InvalidJumpTags,
self.IMUConsistency,
self.AHRSTrimLand,
self.GuidedYawRate,
Expand Down
2 changes: 1 addition & 1 deletion Tools/autotest/rover.py
Original file line number Diff line number Diff line change
Expand Up @@ -6055,7 +6055,7 @@ def MAV_CMD_DO_SET_MISSION_CURRENT(self, target_sysid=None, target_compid=1):
timeout=1,
target_sysid=target_sysid,
target_compid=target_compid,
want_result=mavutil.mavlink.MAV_RESULT_FAILED,
want_result=mavutil.mavlink.MAV_RESULT_DENIED,
)

def FlashStorage(self):
Expand Down
2 changes: 2 additions & 0 deletions Tools/autotest/vehicle_test_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -5897,10 +5897,12 @@ def run_cmd_get_ack(self, command, want_result, timeout, quiet=False, mav=None,
def set_current_waypoint_using_mav_cmd_do_set_mission_current(
self,
seq,
reset=0,
target_sysid=1,
target_compid=1):
self.run_cmd(mavutil.mavlink.MAV_CMD_DO_SET_MISSION_CURRENT,
p1=seq,
p2=reset,
timeout=1,
target_sysid=target_sysid,
target_compid=target_compid)
Expand Down
8 changes: 3 additions & 5 deletions libraries/AP_Mission/AP_Mission.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,18 +538,16 @@ int32_t AP_Mission::get_next_ground_course_cd(int32_t default_angle)
}

// set_current_cmd - jumps to command specified by index
bool AP_Mission::set_current_cmd(uint16_t index, bool rewind)
bool AP_Mission::set_current_cmd(uint16_t index)
{
// read command to check for DO_LAND_START
Mission_Command cmd;
if (!read_cmd_from_storage(index, cmd) || (cmd.id != MAV_CMD_DO_LAND_START)) {
_flags.in_landing_sequence = false;
}

// mission command has been set and not as rewind command, don't track history.
if (!rewind) {
reset_wp_history();
}
// mission command has been set, don't track history.
reset_wp_history();

// sanity check index and that we have a mission
if (index >= (unsigned)_cmd_total || _cmd_total == 1) {
Expand Down
4 changes: 3 additions & 1 deletion libraries/AP_Mission/AP_Mission.h
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ class AP_Mission
}

// set_current_cmd - jumps to command specified by index
bool set_current_cmd(uint16_t index, bool rewind = false);
bool set_current_cmd(uint16_t index);

// restart current navigation command. Used to handle external changes to mission
// returns true on success, false if current nav command has been deleted
Expand Down Expand Up @@ -724,6 +724,8 @@ class AP_Mission
// Returns 0 if no appropriate JUMP_TAG match can be found.
uint16_t get_index_of_jump_tag(const uint16_t tag) const;

bool is_valid_index(const uint16_t index) const { return index < _cmd_total; }

#if AP_SDCARD_STORAGE_ENABLED
bool failed_sdcard_storage(void) const {
return _failed_sdcard_storage;
Expand Down
1 change: 1 addition & 0 deletions libraries/GCS_MAVLink/GCS.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ class GCS_MAVLINK
virtual MAV_RESULT _handle_command_preflight_calibration_baro(const mavlink_message_t &msg);

virtual MAV_RESULT handle_command_do_set_mission_current(const mavlink_command_long_t &packet);
MAV_RESULT handle_command_do_jump_tag(const mavlink_command_long_t &packet);

MAV_RESULT handle_command_battery_reset(const mavlink_command_int_t &packet);
void handle_command_long(const mavlink_message_t &msg);
Expand Down
47 changes: 40 additions & 7 deletions libraries/GCS_MAVLink/GCS_Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4452,8 +4452,6 @@ MAV_RESULT GCS_MAVLINK::handle_command_run_prearm_checks(const mavlink_command_i
// the current waypoint, rather than this DO command. It is hoped we
// can move to this command in the future to avoid acknowledgement
// issues with MISSION_SET_CURRENT
// This also handles DO_JUMP_TAG by converting the tag to an index
// and setting the index as if it was a normal do_set_mission_current
MAV_RESULT GCS_MAVLINK::handle_command_do_set_mission_current(const mavlink_command_long_t &packet)
{
AP_Mission *mission = AP::mission();
Expand All @@ -4462,11 +4460,43 @@ MAV_RESULT GCS_MAVLINK::handle_command_do_set_mission_current(const mavlink_comm
}

const uint32_t seq = (uint32_t)packet.param1;
if (packet.command == MAV_CMD_DO_JUMP_TAG) {
if (!mission->jump_to_tag(seq)) {
return MAV_RESULT_FAILED;
}
} else if (!mission->set_current_cmd(seq)) {
if (!mission->is_valid_index(seq)) {
return MAV_RESULT_DENIED;
}

// From https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_MISSION_CURRENT:
// Param 2: Reset Mission
// - Resets mission. 1: true, 0: false. Resets jump counters to initial values
// and changes mission state "completed" to be "active" or "paused".
const bool reset_and_restart = is_equal(packet.param2, 1.0f);
if (reset_and_restart) {
mission->reset();
}
if (!mission->set_current_cmd(seq)) {
return MAV_RESULT_FAILED;
}
if (reset_and_restart) {
mission->resume();
}

// volunteer the new current waypoint for all listeners
send_message(MSG_CURRENT_WAYPOINT);

return MAV_RESULT_ACCEPTED;
}

MAV_RESULT GCS_MAVLINK::handle_command_do_jump_tag(const mavlink_command_long_t &packet)
{
AP_Mission *mission = AP::mission();
if (mission == nullptr) {
return MAV_RESULT_UNSUPPORTED;
}

const uint32_t tag = (uint32_t)packet.param1;
if (tag > UINT16_MAX) {
return MAV_RESULT_DENIED;
}
if (!mission->jump_to_tag(tag)) {
return MAV_RESULT_FAILED;
}

Expand Down Expand Up @@ -4735,6 +4765,9 @@ MAV_RESULT GCS_MAVLINK::handle_command_long_packet(const mavlink_command_long_t
#endif

case MAV_CMD_DO_JUMP_TAG:
result = handle_command_do_jump_tag(packet);
break;

case MAV_CMD_DO_SET_MISSION_CURRENT:
result = handle_command_do_set_mission_current(packet);
break;
Expand Down