mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-27 11:43:34 +08:00
Merge pull request #1119 from PX4/navigator_rewrite_drton
Navigator rewrite - DrTon
This commit is contained in:
@@ -1747,6 +1747,13 @@ set_main_state_rc(struct vehicle_status_s *status, struct manual_control_setpoin
|
|||||||
}
|
}
|
||||||
|
|
||||||
print_reject_mode(status, "AUTO_MISSION");
|
print_reject_mode(status, "AUTO_MISSION");
|
||||||
|
|
||||||
|
// fallback to LOITER if home position not set
|
||||||
|
res = main_state_transition(status, MAIN_STATE_AUTO_LOITER);
|
||||||
|
|
||||||
|
if (res != TRANSITION_DENIED) {
|
||||||
|
break; // changed successfully or already in this state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback to POSCTL
|
// fallback to POSCTL
|
||||||
|
|||||||
@@ -271,7 +271,6 @@ main_state_transition(struct vehicle_status_s *status, main_state_t new_main_sta
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MAIN_STATE_AUTO_MISSION:
|
|
||||||
case MAIN_STATE_AUTO_LOITER:
|
case MAIN_STATE_AUTO_LOITER:
|
||||||
/* need global position estimate */
|
/* need global position estimate */
|
||||||
if (status->condition_global_position_valid) {
|
if (status->condition_global_position_valid) {
|
||||||
@@ -279,6 +278,7 @@ main_state_transition(struct vehicle_status_s *status, main_state_t new_main_sta
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MAIN_STATE_AUTO_MISSION:
|
||||||
case MAIN_STATE_AUTO_RTL:
|
case MAIN_STATE_AUTO_RTL:
|
||||||
/* need global position and home position */
|
/* need global position and home position */
|
||||||
if (status->condition_global_position_valid && status->condition_home_position_valid) {
|
if (status->condition_global_position_valid && status->condition_home_position_valid) {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
* Helper class to loiter
|
* Helper class to loiter
|
||||||
*
|
*
|
||||||
* @author Julian Oes <julian@oes.ch>
|
* @author Julian Oes <julian@oes.ch>
|
||||||
|
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -51,28 +52,42 @@
|
|||||||
#include <uORB/topics/position_setpoint_triplet.h>
|
#include <uORB/topics/position_setpoint_triplet.h>
|
||||||
|
|
||||||
#include "loiter.h"
|
#include "loiter.h"
|
||||||
|
#include "navigator.h"
|
||||||
|
|
||||||
Loiter::Loiter(Navigator *navigator, const char *name) :
|
Loiter::Loiter(Navigator *navigator, const char *name) :
|
||||||
MissionBlock(navigator, name)
|
MissionBlock(navigator, name)
|
||||||
{
|
{
|
||||||
/* load initial params */
|
/* load initial params */
|
||||||
updateParams();
|
updateParams();
|
||||||
/* initial reset */
|
|
||||||
on_inactive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loiter::~Loiter()
|
Loiter::~Loiter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Loiter::on_active(struct position_setpoint_triplet_s *pos_sp_triplet)
|
|
||||||
{
|
|
||||||
/* set loiter item, don't reuse an existing position setpoint */
|
|
||||||
return set_loiter_item(pos_sp_triplet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Loiter::on_inactive()
|
Loiter::on_inactive()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Loiter::on_activation()
|
||||||
|
{
|
||||||
|
/* set current mission item to loiter */
|
||||||
|
set_loiter_item(&_mission_item);
|
||||||
|
|
||||||
|
/* convert mission item to current setpoint */
|
||||||
|
struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();
|
||||||
|
pos_sp_triplet->previous.valid = false;
|
||||||
|
mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
|
||||||
|
pos_sp_triplet->next.valid = false;
|
||||||
|
|
||||||
|
_navigator->set_can_loiter_at_sp(pos_sp_triplet->current.type == SETPOINT_TYPE_LOITER);
|
||||||
|
|
||||||
|
_navigator->set_position_setpoint_triplet_updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Loiter::on_active()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,25 +50,15 @@
|
|||||||
class Loiter : public MissionBlock
|
class Loiter : public MissionBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Loiter(Navigator *navigator, const char *name);
|
Loiter(Navigator *navigator, const char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~Loiter();
|
~Loiter();
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is called while the mode is inactive
|
|
||||||
*/
|
|
||||||
virtual void on_inactive();
|
virtual void on_inactive();
|
||||||
|
|
||||||
/**
|
virtual void on_activation();
|
||||||
* This function is called while the mode is active
|
|
||||||
*/
|
virtual void on_active();
|
||||||
virtual bool on_active(struct position_setpoint_triplet_s *pos_sp_triplet);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+186
-133
@@ -54,25 +54,28 @@
|
|||||||
#include <uORB/topics/mission.h>
|
#include <uORB/topics/mission.h>
|
||||||
#include <uORB/topics/mission_result.h>
|
#include <uORB/topics/mission_result.h>
|
||||||
|
|
||||||
#include "navigator.h"
|
|
||||||
#include "mission.h"
|
#include "mission.h"
|
||||||
|
#include "navigator.h"
|
||||||
|
|
||||||
Mission::Mission(Navigator *navigator, const char *name) :
|
Mission::Mission(Navigator *navigator, const char *name) :
|
||||||
MissionBlock(navigator, name),
|
MissionBlock(navigator, name),
|
||||||
_param_onboard_enabled(this, "ONBOARD_EN"),
|
_param_onboard_enabled(this, "ONBOARD_EN"),
|
||||||
|
_param_takeoff_alt(this, "TAKEOFF_ALT"),
|
||||||
_onboard_mission({0}),
|
_onboard_mission({0}),
|
||||||
_offboard_mission({0}),
|
_offboard_mission({0}),
|
||||||
_current_onboard_mission_index(-1),
|
_current_onboard_mission_index(-1),
|
||||||
_current_offboard_mission_index(-1),
|
_current_offboard_mission_index(-1),
|
||||||
_mission_result_pub(-1),
|
_mission_result_pub(-1),
|
||||||
_mission_result({0}),
|
_mission_result({0}),
|
||||||
_mission_type(MISSION_TYPE_NONE)
|
_mission_type(MISSION_TYPE_NONE),
|
||||||
|
_need_takeoff(true),
|
||||||
|
_takeoff(false)
|
||||||
{
|
{
|
||||||
/* load initial params */
|
/* load initial params */
|
||||||
updateParams();
|
updateParams();
|
||||||
|
|
||||||
/* set initial mission items */
|
/* set initial mission items */
|
||||||
on_inactive();
|
on_inactive();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mission::~Mission()
|
Mission::~Mission()
|
||||||
@@ -82,8 +85,6 @@ Mission::~Mission()
|
|||||||
void
|
void
|
||||||
Mission::on_inactive()
|
Mission::on_inactive()
|
||||||
{
|
{
|
||||||
_first_run = true;
|
|
||||||
|
|
||||||
/* check anyway if missions have changed so that feedback to groundstation is given */
|
/* check anyway if missions have changed so that feedback to groundstation is given */
|
||||||
bool onboard_updated;
|
bool onboard_updated;
|
||||||
orb_check(_navigator->get_onboard_mission_sub(), &onboard_updated);
|
orb_check(_navigator->get_onboard_mission_sub(), &onboard_updated);
|
||||||
@@ -96,13 +97,21 @@ Mission::on_inactive()
|
|||||||
if (offboard_updated) {
|
if (offboard_updated) {
|
||||||
update_offboard_mission();
|
update_offboard_mission();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_navigator->get_can_loiter_at_sp() || _navigator->get_vstatus()->condition_landed) {
|
||||||
|
_need_takeoff = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
Mission::on_active(struct position_setpoint_triplet_s *pos_sp_triplet)
|
Mission::on_activation()
|
||||||
{
|
{
|
||||||
bool updated = false;
|
set_mission_items();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Mission::on_active()
|
||||||
|
{
|
||||||
/* check if anything has changed */
|
/* check if anything has changed */
|
||||||
bool onboard_updated;
|
bool onboard_updated;
|
||||||
orb_check(_navigator->get_onboard_mission_sub(), &onboard_updated);
|
orb_check(_navigator->get_onboard_mission_sub(), &onboard_updated);
|
||||||
@@ -117,20 +126,21 @@ Mission::on_active(struct position_setpoint_triplet_s *pos_sp_triplet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* reset mission items if needed */
|
/* reset mission items if needed */
|
||||||
if (onboard_updated || offboard_updated || _first_run) {
|
if (onboard_updated || offboard_updated) {
|
||||||
set_mission_items(pos_sp_triplet);
|
set_mission_items();
|
||||||
updated = true;
|
|
||||||
_first_run = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lets check if we reached the current mission item */
|
/* lets check if we reached the current mission item */
|
||||||
if (_mission_type != MISSION_TYPE_NONE && is_mission_item_reached()) {
|
if (_mission_type != MISSION_TYPE_NONE && is_mission_item_reached()) {
|
||||||
advance_mission();
|
advance_mission();
|
||||||
set_mission_items(pos_sp_triplet);
|
set_mission_items();
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return updated;
|
} else {
|
||||||
|
/* if waypoint position reached allow loiter on the setpoint */
|
||||||
|
if (_waypoint_position_reached && _mission_item.nav_cmd != NAV_CMD_IDLE) {
|
||||||
|
_navigator->set_can_loiter_at_sp(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -151,6 +161,7 @@ Mission::update_onboard_mission()
|
|||||||
}
|
}
|
||||||
/* otherwise, just leave it */
|
/* otherwise, just leave it */
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_onboard_mission.count = 0;
|
_onboard_mission.count = 0;
|
||||||
_onboard_mission.current_index = 0;
|
_onboard_mission.current_index = 0;
|
||||||
@@ -167,10 +178,12 @@ Mission::update_offboard_mission()
|
|||||||
if (_offboard_mission.current_index >= 0
|
if (_offboard_mission.current_index >= 0
|
||||||
&& _offboard_mission.current_index < (int)_offboard_mission.count) {
|
&& _offboard_mission.current_index < (int)_offboard_mission.count) {
|
||||||
_current_offboard_mission_index = _offboard_mission.current_index;
|
_current_offboard_mission_index = _offboard_mission.current_index;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* if less WPs available, reset to first WP */
|
/* if less WPs available, reset to first WP */
|
||||||
if (_current_offboard_mission_index >= (int)_offboard_mission.count) {
|
if (_current_offboard_mission_index >= (int)_offboard_mission.count) {
|
||||||
_current_offboard_mission_index = 0;
|
_current_offboard_mission_index = 0;
|
||||||
|
|
||||||
/* if not initialized, set it to 0 */
|
/* if not initialized, set it to 0 */
|
||||||
} else if (_current_offboard_mission_index < 0) {
|
} else if (_current_offboard_mission_index < 0) {
|
||||||
_current_offboard_mission_index = 0;
|
_current_offboard_mission_index = 0;
|
||||||
@@ -184,6 +197,7 @@ Mission::update_offboard_mission()
|
|||||||
|
|
||||||
if (_offboard_mission.dataman_id == 0) {
|
if (_offboard_mission.dataman_id == 0) {
|
||||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
||||||
}
|
}
|
||||||
@@ -192,11 +206,13 @@ Mission::update_offboard_mission()
|
|||||||
(size_t)_offboard_mission.count,
|
(size_t)_offboard_mission.count,
|
||||||
_navigator->get_geofence(),
|
_navigator->get_geofence(),
|
||||||
_navigator->get_home_position()->alt);
|
_navigator->get_home_position()->alt);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_offboard_mission.count = 0;
|
_offboard_mission.count = 0;
|
||||||
_offboard_mission.current_index = 0;
|
_offboard_mission.current_index = 0;
|
||||||
_current_offboard_mission_index = 0;
|
_current_offboard_mission_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_current_offboard_mission_item();
|
report_current_offboard_mission_item();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,46 +220,55 @@ Mission::update_offboard_mission()
|
|||||||
void
|
void
|
||||||
Mission::advance_mission()
|
Mission::advance_mission()
|
||||||
{
|
{
|
||||||
switch (_mission_type) {
|
if (_takeoff) {
|
||||||
case MISSION_TYPE_ONBOARD:
|
_takeoff = false;
|
||||||
_current_onboard_mission_index++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MISSION_TYPE_OFFBOARD:
|
} else {
|
||||||
_current_offboard_mission_index++;
|
switch (_mission_type) {
|
||||||
break;
|
case MISSION_TYPE_ONBOARD:
|
||||||
|
_current_onboard_mission_index++;
|
||||||
|
break;
|
||||||
|
|
||||||
case MISSION_TYPE_NONE:
|
case MISSION_TYPE_OFFBOARD:
|
||||||
default:
|
_current_offboard_mission_index++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MISSION_TYPE_NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Mission::set_mission_items(struct position_setpoint_triplet_s *pos_sp_triplet)
|
Mission::set_mission_items()
|
||||||
{
|
{
|
||||||
set_previous_pos_setpoint(pos_sp_triplet);
|
/* make sure param is up to date */
|
||||||
|
updateParams();
|
||||||
|
|
||||||
|
struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();
|
||||||
|
|
||||||
|
/* set previous position setpoint to current */
|
||||||
|
set_previous_pos_setpoint();
|
||||||
|
|
||||||
/* try setting onboard mission item */
|
/* try setting onboard mission item */
|
||||||
if (is_current_onboard_mission_item_set(&pos_sp_triplet->current)) {
|
if (_param_onboard_enabled.get() && read_mission_item(true, true, &_mission_item)) {
|
||||||
/* if mission type changed, notify */
|
/* if mission type changed, notify */
|
||||||
if (_mission_type != MISSION_TYPE_ONBOARD) {
|
if (_mission_type != MISSION_TYPE_ONBOARD) {
|
||||||
mavlink_log_info(_navigator->get_mavlink_fd(),
|
mavlink_log_info(_navigator->get_mavlink_fd(), "#audio: onboard mission running");
|
||||||
"#audio: onboard mission running");
|
|
||||||
}
|
}
|
||||||
_mission_type = MISSION_TYPE_ONBOARD;
|
_mission_type = MISSION_TYPE_ONBOARD;
|
||||||
_navigator->set_can_loiter_at_sp(false);
|
|
||||||
|
|
||||||
/* try setting offboard mission item */
|
/* try setting offboard mission item */
|
||||||
} else if (is_current_offboard_mission_item_set(&pos_sp_triplet->current)) {
|
} else if (read_mission_item(false, true, &_mission_item)) {
|
||||||
/* if mission type changed, notify */
|
/* if mission type changed, notify */
|
||||||
if (_mission_type != MISSION_TYPE_OFFBOARD) {
|
if (_mission_type != MISSION_TYPE_OFFBOARD) {
|
||||||
mavlink_log_info(_navigator->get_mavlink_fd(),
|
mavlink_log_info(_navigator->get_mavlink_fd(), "#audio: offboard mission running");
|
||||||
"#audio: offboard mission running");
|
|
||||||
}
|
}
|
||||||
_mission_type = MISSION_TYPE_OFFBOARD;
|
_mission_type = MISSION_TYPE_OFFBOARD;
|
||||||
_navigator->set_can_loiter_at_sp(false);
|
|
||||||
} else {
|
} else {
|
||||||
|
/* no mission available, switch to loiter */
|
||||||
if (_mission_type != MISSION_TYPE_NONE) {
|
if (_mission_type != MISSION_TYPE_NONE) {
|
||||||
mavlink_log_info(_navigator->get_mavlink_fd(),
|
mavlink_log_info(_navigator->get_mavlink_fd(),
|
||||||
"#audio: mission finished");
|
"#audio: mission finished");
|
||||||
@@ -252,125 +277,152 @@ Mission::set_mission_items(struct position_setpoint_triplet_s *pos_sp_triplet)
|
|||||||
"#audio: no mission available");
|
"#audio: no mission available");
|
||||||
}
|
}
|
||||||
_mission_type = MISSION_TYPE_NONE;
|
_mission_type = MISSION_TYPE_NONE;
|
||||||
_navigator->set_can_loiter_at_sp(pos_sp_triplet->current.valid && _waypoint_position_reached);
|
|
||||||
|
|
||||||
set_loiter_item(pos_sp_triplet);
|
/* set loiter mission item */
|
||||||
|
set_loiter_item(&_mission_item);
|
||||||
|
|
||||||
|
/* update position setpoint triplet */
|
||||||
|
pos_sp_triplet->previous.valid = false;
|
||||||
|
mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
|
||||||
|
pos_sp_triplet->next.valid = false;
|
||||||
|
|
||||||
|
_navigator->set_can_loiter_at_sp(pos_sp_triplet->current.type == SETPOINT_TYPE_LOITER);
|
||||||
|
|
||||||
reset_mission_item_reached();
|
reset_mission_item_reached();
|
||||||
report_mission_finished();
|
report_mission_finished();
|
||||||
|
|
||||||
|
_navigator->set_position_setpoint_triplet_updated();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
/* do takeoff on first waypoint for rotary wing vehicles */
|
||||||
Mission::is_current_onboard_mission_item_set(struct position_setpoint_s *current_pos_sp)
|
if (_navigator->get_vstatus()->is_rotary_wing) {
|
||||||
{
|
/* force takeoff if landed (additional protection) */
|
||||||
/* make sure param is up to date */
|
if (!_takeoff && _navigator->get_vstatus()->condition_landed) {
|
||||||
updateParams();
|
_need_takeoff = true;
|
||||||
if (_param_onboard_enabled.get() > 0 &&
|
}
|
||||||
_current_onboard_mission_index >= 0&&
|
|
||||||
_current_onboard_mission_index < (int)_onboard_mission.count) {
|
|
||||||
struct mission_item_s new_mission_item;
|
|
||||||
if (read_mission_item(DM_KEY_WAYPOINTS_ONBOARD, true, &_current_onboard_mission_index,
|
|
||||||
&new_mission_item)) {
|
|
||||||
/* convert the current mission item and set it valid */
|
|
||||||
mission_item_to_position_setpoint(&new_mission_item, current_pos_sp);
|
|
||||||
current_pos_sp->valid = true;
|
|
||||||
|
|
||||||
reset_mission_item_reached();
|
/* new current mission item set, check if we need takeoff */
|
||||||
|
if (_need_takeoff && (
|
||||||
/* TODO: report this somehow */
|
_mission_item.nav_cmd == NAV_CMD_TAKEOFF ||
|
||||||
memcpy(&_mission_item, &new_mission_item, sizeof(struct mission_item_s));
|
_mission_item.nav_cmd == NAV_CMD_WAYPOINT ||
|
||||||
return true;
|
_mission_item.nav_cmd == NAV_CMD_LOITER_TIME_LIMIT ||
|
||||||
|
_mission_item.nav_cmd == NAV_CMD_LOITER_TURN_COUNT ||
|
||||||
|
_mission_item.nav_cmd == NAV_CMD_LOITER_UNLIMITED ||
|
||||||
|
_mission_item.nav_cmd == NAV_CMD_RETURN_TO_LAUNCH)) {
|
||||||
|
_takeoff = true;
|
||||||
|
_need_takeoff = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
if (_takeoff) {
|
||||||
Mission::is_current_offboard_mission_item_set(struct position_setpoint_s *current_pos_sp)
|
/* do takeoff before going to setpoint */
|
||||||
{
|
/* set mission item as next position setpoint */
|
||||||
if (_current_offboard_mission_index >= 0 &&
|
mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->next);
|
||||||
_current_offboard_mission_index < (int)_offboard_mission.count) {
|
|
||||||
dm_item_t dm_current;
|
/* calculate takeoff altitude */
|
||||||
if (_offboard_mission.dataman_id == 0) {
|
float takeoff_alt = _mission_item.altitude;
|
||||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
if (_mission_item.altitude_is_relative) {
|
||||||
|
takeoff_alt += _navigator->get_home_position()->alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* perform takeoff at least to NAV_TAKEOFF_ALT above home/ground, even if first waypoint is lower */
|
||||||
|
if (_navigator->get_vstatus()->condition_landed) {
|
||||||
|
takeoff_alt = fmaxf(takeoff_alt, _navigator->get_global_position()->alt + _param_takeoff_alt.get());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
takeoff_alt = fmaxf(takeoff_alt, _navigator->get_home_position()->alt + _param_takeoff_alt.get());
|
||||||
}
|
}
|
||||||
struct mission_item_s new_mission_item;
|
|
||||||
if (read_mission_item(dm_current, true, &_current_offboard_mission_index, &new_mission_item)) {
|
|
||||||
/* convert the current mission item and set it valid */
|
|
||||||
mission_item_to_position_setpoint(&new_mission_item, current_pos_sp);
|
|
||||||
current_pos_sp->valid = true;
|
|
||||||
|
|
||||||
reset_mission_item_reached();
|
mavlink_log_info(_navigator->get_mavlink_fd(), "#audio: takeoff to %.1fm above home", takeoff_alt - _navigator->get_home_position()->alt);
|
||||||
|
|
||||||
|
_mission_item.lat = _navigator->get_global_position()->lat;
|
||||||
|
_mission_item.lon = _navigator->get_global_position()->lon;
|
||||||
|
_mission_item.altitude = takeoff_alt;
|
||||||
|
_mission_item.altitude_is_relative = false;
|
||||||
|
|
||||||
|
mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* set current position setpoint from mission item */
|
||||||
|
mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
|
||||||
|
|
||||||
|
/* require takeoff after landing or idle */
|
||||||
|
if (pos_sp_triplet->current.type == SETPOINT_TYPE_LAND || pos_sp_triplet->current.type == SETPOINT_TYPE_IDLE) {
|
||||||
|
_need_takeoff = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_navigator->set_can_loiter_at_sp(false);
|
||||||
|
reset_mission_item_reached();
|
||||||
|
|
||||||
|
if (_mission_type == MISSION_TYPE_OFFBOARD) {
|
||||||
report_current_offboard_mission_item();
|
report_current_offboard_mission_item();
|
||||||
memcpy(&_mission_item, &new_mission_item, sizeof(struct mission_item_s));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
// TODO: report onboard mission item somehow
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
/* try to read next mission item */
|
||||||
Mission::get_next_onboard_mission_item(struct position_setpoint_s *next_pos_sp)
|
struct mission_item_s mission_item_next;
|
||||||
{
|
|
||||||
int next_temp_mission_index = _onboard_mission.current_index + 1;
|
|
||||||
|
|
||||||
/* try if there is a next onboard mission */
|
if (read_mission_item(_mission_type == MISSION_TYPE_ONBOARD, false, &mission_item_next)) {
|
||||||
if (_onboard_mission.current_index >= 0 &&
|
/* got next mission item, update setpoint triplet */
|
||||||
next_temp_mission_index < (int)_onboard_mission.count) {
|
mission_item_to_position_setpoint(&mission_item_next, &pos_sp_triplet->next);
|
||||||
struct mission_item_s new_mission_item;
|
|
||||||
if (read_mission_item(DM_KEY_WAYPOINTS_ONBOARD, false, &next_temp_mission_index, &new_mission_item)) {
|
|
||||||
/* convert next mission item to position setpoint */
|
|
||||||
mission_item_to_position_setpoint(&new_mission_item, next_pos_sp);
|
|
||||||
next_pos_sp->valid = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* give up */
|
|
||||||
next_pos_sp->valid = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Mission::get_next_offboard_mission_item(struct position_setpoint_s *next_pos_sp)
|
|
||||||
{
|
|
||||||
/* try if there is a next offboard mission */
|
|
||||||
int next_temp_mission_index = _offboard_mission.current_index + 1;
|
|
||||||
warnx("next index: %d, count; %d", next_temp_mission_index, _offboard_mission.count);
|
|
||||||
if (_offboard_mission.current_index >= 0 &&
|
|
||||||
next_temp_mission_index < (int)_offboard_mission.count) {
|
|
||||||
dm_item_t dm_current;
|
|
||||||
if (_offboard_mission.dataman_id == 0) {
|
|
||||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
|
||||||
} else {
|
} else {
|
||||||
dm_current = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
/* next mission item is not available */
|
||||||
}
|
pos_sp_triplet->next.valid = false;
|
||||||
struct mission_item_s new_mission_item;
|
|
||||||
if (read_mission_item(dm_current, false, &next_temp_mission_index, &new_mission_item)) {
|
|
||||||
/* convert next mission item to position setpoint */
|
|
||||||
mission_item_to_position_setpoint(&new_mission_item, next_pos_sp);
|
|
||||||
next_pos_sp->valid = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* give up */
|
|
||||||
next_pos_sp->valid = false;
|
_navigator->set_position_setpoint_triplet_updated();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Mission::read_mission_item(const dm_item_t dm_item, bool is_current, int *mission_index,
|
Mission::read_mission_item(bool onboard, bool is_current, struct mission_item_s *mission_item)
|
||||||
struct mission_item_s *new_mission_item)
|
|
||||||
{
|
{
|
||||||
|
/* select onboard/offboard mission */
|
||||||
|
int *mission_index_ptr;
|
||||||
|
struct mission_s *mission;
|
||||||
|
dm_item_t dm_item;
|
||||||
|
int mission_index_next;
|
||||||
|
|
||||||
|
if (onboard) {
|
||||||
|
/* onboard mission */
|
||||||
|
mission_index_next = _current_onboard_mission_index + 1;
|
||||||
|
mission_index_ptr = is_current ? &_current_onboard_mission_index : &mission_index_next;
|
||||||
|
|
||||||
|
mission = &_onboard_mission;
|
||||||
|
|
||||||
|
dm_item = DM_KEY_WAYPOINTS_ONBOARD;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* offboard mission */
|
||||||
|
mission_index_next = _current_offboard_mission_index + 1;
|
||||||
|
mission_index_ptr = is_current ? &_current_offboard_mission_index : &mission_index_next;
|
||||||
|
|
||||||
|
mission = &_offboard_mission;
|
||||||
|
|
||||||
|
if (_offboard_mission.dataman_id == 0) {
|
||||||
|
dm_item = DM_KEY_WAYPOINTS_OFFBOARD_0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dm_item = DM_KEY_WAYPOINTS_OFFBOARD_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*mission_index_ptr < 0 || *mission_index_ptr >= (int)mission->count) {
|
||||||
|
/* mission item index out of bounds */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* repeat several to get the mission item because we might have to follow multiple DO_JUMPS */
|
/* repeat several to get the mission item because we might have to follow multiple DO_JUMPS */
|
||||||
for (int i=0; i<10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
const ssize_t len = sizeof(struct mission_item_s);
|
const ssize_t len = sizeof(struct mission_item_s);
|
||||||
|
|
||||||
|
/* read mission item to temp storage first to not overwrite current mission item if data damaged */
|
||||||
|
struct mission_item_s mission_item_tmp;
|
||||||
|
|
||||||
/* read mission item from datamanager */
|
/* read mission item from datamanager */
|
||||||
if (dm_read(dm_item, *mission_index, new_mission_item, len) != len) {
|
if (dm_read(dm_item, *mission_index_ptr, &mission_item_tmp, len) != len) {
|
||||||
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
||||||
mavlink_log_critical(_navigator->get_mavlink_fd(),
|
mavlink_log_critical(_navigator->get_mavlink_fd(),
|
||||||
"#audio: ERROR waypoint could not be read");
|
"#audio: ERROR waypoint could not be read");
|
||||||
@@ -378,18 +430,17 @@ Mission::read_mission_item(const dm_item_t dm_item, bool is_current, int *missio
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check for DO_JUMP item, and whether it hasn't not already been repeated enough times */
|
/* check for DO_JUMP item, and whether it hasn't not already been repeated enough times */
|
||||||
if (new_mission_item->nav_cmd == NAV_CMD_DO_JUMP) {
|
if (mission_item_tmp.nav_cmd == NAV_CMD_DO_JUMP) {
|
||||||
|
|
||||||
/* do DO_JUMP as many times as requested */
|
/* do DO_JUMP as many times as requested */
|
||||||
if (new_mission_item->do_jump_current_count < new_mission_item->do_jump_repeat_count) {
|
if (mission_item_tmp.do_jump_current_count < mission_item_tmp.do_jump_repeat_count) {
|
||||||
|
|
||||||
/* only raise the repeat count if this is for the current mission item
|
/* only raise the repeat count if this is for the current mission item
|
||||||
* but not for the next mission item */
|
* but not for the next mission item */
|
||||||
if (is_current) {
|
if (is_current) {
|
||||||
(new_mission_item->do_jump_current_count)++;
|
(mission_item_tmp.do_jump_current_count)++;
|
||||||
/* save repeat count */
|
/* save repeat count */
|
||||||
if (dm_write(dm_item, *mission_index, DM_PERSIST_IN_FLIGHT_RESET,
|
if (dm_write(dm_item, *mission_index_ptr, DM_PERSIST_IN_FLIGHT_RESET, &mission_item_tmp, len) != len) {
|
||||||
new_mission_item, len) != len) {
|
|
||||||
/* not supposed to happen unless the datamanager can't access the
|
/* not supposed to happen unless the datamanager can't access the
|
||||||
* dataman */
|
* dataman */
|
||||||
mavlink_log_critical(_navigator->get_mavlink_fd(),
|
mavlink_log_critical(_navigator->get_mavlink_fd(),
|
||||||
@@ -399,16 +450,18 @@ Mission::read_mission_item(const dm_item_t dm_item, bool is_current, int *missio
|
|||||||
}
|
}
|
||||||
/* set new mission item index and repeat
|
/* set new mission item index and repeat
|
||||||
* we don't have to validate here, if it's invalid, we should realize this later .*/
|
* we don't have to validate here, if it's invalid, we should realize this later .*/
|
||||||
*mission_index = new_mission_item->do_jump_mission_index;
|
*mission_index_ptr = mission_item_tmp.do_jump_mission_index;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mavlink_log_info(_navigator->get_mavlink_fd(),
|
mavlink_log_info(_navigator->get_mavlink_fd(),
|
||||||
"#audio: DO JUMP repetitions completed");
|
"#audio: DO JUMP repetitions completed");
|
||||||
/* no more DO_JUMPS, therefore just try to continue with next mission item */
|
/* no more DO_JUMPS, therefore just try to continue with next mission item */
|
||||||
(*mission_index)++;
|
(*mission_index_ptr)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* if it's not a DO_JUMP, then we were successful */
|
/* if it's not a DO_JUMP, then we were successful */
|
||||||
|
memcpy(mission_item, &mission_item_tmp, sizeof(struct mission_item_s));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,25 +65,15 @@ class Navigator;
|
|||||||
class Mission : public MissionBlock
|
class Mission : public MissionBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Mission(Navigator *navigator, const char *name);
|
Mission(Navigator *navigator, const char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
virtual ~Mission();
|
virtual ~Mission();
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is called while the mode is inactive
|
|
||||||
*/
|
|
||||||
virtual void on_inactive();
|
virtual void on_inactive();
|
||||||
|
|
||||||
/**
|
virtual void on_activation();
|
||||||
* This function is called while the mode is active
|
|
||||||
*/
|
virtual void on_active();
|
||||||
virtual bool on_active(struct position_setpoint_triplet_s *pos_sp_triplet);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@@ -104,36 +94,13 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Set new mission items
|
* Set new mission items
|
||||||
*/
|
*/
|
||||||
void set_mission_items(struct position_setpoint_triplet_s *pos_sp_triplet);
|
void set_mission_items();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to set the current position setpoint from an onboard mission item
|
* Read current or next mission item from the dataman and watch out for DO_JUMPS
|
||||||
* @return true if mission item successfully set
|
|
||||||
*/
|
|
||||||
bool is_current_onboard_mission_item_set(struct position_setpoint_s *current_pos_sp);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to set the current position setpoint from an offboard mission item
|
|
||||||
* @return true if mission item successfully set
|
|
||||||
*/
|
|
||||||
bool is_current_offboard_mission_item_set(struct position_setpoint_s *current_pos_sp);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to set the next position setpoint from an onboard mission item
|
|
||||||
*/
|
|
||||||
void get_next_onboard_mission_item(struct position_setpoint_s *next_pos_sp);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to set the next position setpoint from an offboard mission item
|
|
||||||
*/
|
|
||||||
void get_next_offboard_mission_item(struct position_setpoint_s *next_pos_sp);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a mission item from the dataman and watch out for DO_JUMPS
|
|
||||||
* @return true if successful
|
* @return true if successful
|
||||||
*/
|
*/
|
||||||
bool read_mission_item(const dm_item_t dm_item, bool is_current, int *mission_index,
|
bool read_mission_item(bool onboard, bool is_current, struct mission_item_s *mission_item);
|
||||||
struct mission_item_s *new_mission_item);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report that a mission item has been reached
|
* Report that a mission item has been reached
|
||||||
@@ -156,12 +123,15 @@ private:
|
|||||||
void publish_mission_result();
|
void publish_mission_result();
|
||||||
|
|
||||||
control::BlockParamFloat _param_onboard_enabled;
|
control::BlockParamFloat _param_onboard_enabled;
|
||||||
|
control::BlockParamFloat _param_takeoff_alt;
|
||||||
|
|
||||||
struct mission_s _onboard_mission;
|
struct mission_s _onboard_mission;
|
||||||
struct mission_s _offboard_mission;
|
struct mission_s _offboard_mission;
|
||||||
|
|
||||||
int _current_onboard_mission_index;
|
int _current_onboard_mission_index;
|
||||||
int _current_offboard_mission_index;
|
int _current_offboard_mission_index;
|
||||||
|
bool _need_takeoff;
|
||||||
|
bool _takeoff;
|
||||||
|
|
||||||
orb_advert_t _mission_result_pub;
|
orb_advert_t _mission_result_pub;
|
||||||
struct mission_result_s _mission_result;
|
struct mission_result_s _mission_result;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <geo/geo.h>
|
#include <geo/geo.h>
|
||||||
|
#include <mavlink/mavlink_log.h>
|
||||||
|
|
||||||
#include <uORB/uORB.h>
|
#include <uORB/uORB.h>
|
||||||
|
|
||||||
@@ -59,8 +60,7 @@ MissionBlock::MissionBlock(Navigator *navigator, const char *name) :
|
|||||||
_waypoint_position_reached(false),
|
_waypoint_position_reached(false),
|
||||||
_waypoint_yaw_reached(false),
|
_waypoint_yaw_reached(false),
|
||||||
_time_first_inside_orbit(0),
|
_time_first_inside_orbit(0),
|
||||||
_mission_item({0}),
|
_mission_item({0})
|
||||||
_mission_item_valid(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +71,10 @@ MissionBlock::~MissionBlock()
|
|||||||
bool
|
bool
|
||||||
MissionBlock::is_mission_item_reached()
|
MissionBlock::is_mission_item_reached()
|
||||||
{
|
{
|
||||||
|
if (_mission_item.nav_cmd == NAV_CMD_IDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (_mission_item.nav_cmd == NAV_CMD_LAND) {
|
if (_mission_item.nav_cmd == NAV_CMD_LAND) {
|
||||||
return _navigator->get_vstatus()->condition_landed;
|
return _navigator->get_vstatus()->condition_landed;
|
||||||
}
|
}
|
||||||
@@ -84,7 +88,6 @@ MissionBlock::is_mission_item_reached()
|
|||||||
hrt_abstime now = hrt_absolute_time();
|
hrt_abstime now = hrt_absolute_time();
|
||||||
|
|
||||||
if (!_waypoint_position_reached) {
|
if (!_waypoint_position_reached) {
|
||||||
|
|
||||||
float dist = -1.0f;
|
float dist = -1.0f;
|
||||||
float dist_xy = -1.0f;
|
float dist_xy = -1.0f;
|
||||||
float dist_z = -1.0f;
|
float dist_z = -1.0f;
|
||||||
@@ -201,44 +204,48 @@ MissionBlock::mission_item_to_position_setpoint(const struct mission_item_s *ite
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MissionBlock::set_previous_pos_setpoint(struct position_setpoint_triplet_s *pos_sp_triplet)
|
MissionBlock::set_previous_pos_setpoint()
|
||||||
{
|
{
|
||||||
/* reuse current setpoint as previous setpoint */
|
struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();
|
||||||
|
|
||||||
if (pos_sp_triplet->current.valid) {
|
if (pos_sp_triplet->current.valid) {
|
||||||
memcpy(&pos_sp_triplet->previous, &pos_sp_triplet->current, sizeof(struct position_setpoint_s));
|
memcpy(&pos_sp_triplet->previous, &pos_sp_triplet->current, sizeof(struct position_setpoint_s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
MissionBlock::set_loiter_item(struct position_setpoint_triplet_s *pos_sp_triplet)
|
MissionBlock::set_loiter_item(struct mission_item_s *item)
|
||||||
{
|
{
|
||||||
/* don't change setpoint if 'can_loiter_at_sp' flag set */
|
if (_navigator->get_vstatus()->condition_landed) {
|
||||||
if (!(_navigator->get_can_loiter_at_sp() && pos_sp_triplet->current.valid)) {
|
/* landed, don't takeoff, but switch to IDLE mode */
|
||||||
/* use current position */
|
item->nav_cmd = NAV_CMD_IDLE;
|
||||||
pos_sp_triplet->current.lat = _navigator->get_global_position()->lat;
|
|
||||||
pos_sp_triplet->current.lon = _navigator->get_global_position()->lon;
|
|
||||||
pos_sp_triplet->current.alt = _navigator->get_global_position()->alt;
|
|
||||||
pos_sp_triplet->current.yaw = NAN; /* NAN means to use current yaw */
|
|
||||||
|
|
||||||
_navigator->set_can_loiter_at_sp(true);
|
} else {
|
||||||
|
item->nav_cmd = NAV_CMD_LOITER_UNLIMITED;
|
||||||
|
|
||||||
|
struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();
|
||||||
|
|
||||||
|
if (_navigator->get_can_loiter_at_sp() && pos_sp_triplet->current.valid) {
|
||||||
|
/* use current position setpoint */
|
||||||
|
item->lat = pos_sp_triplet->current.lat;
|
||||||
|
item->lon = pos_sp_triplet->current.lon;
|
||||||
|
item->altitude = pos_sp_triplet->current.alt;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* use current position */
|
||||||
|
item->lat = _navigator->get_global_position()->lat;
|
||||||
|
item->lon = _navigator->get_global_position()->lon;
|
||||||
|
item->altitude = _navigator->get_global_position()->alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->altitude_is_relative = false;
|
||||||
|
item->yaw = NAN;
|
||||||
|
item->loiter_radius = _navigator->get_loiter_radius();
|
||||||
|
item->loiter_direction = 1;
|
||||||
|
item->acceptance_radius = _navigator->get_acceptance_radius();
|
||||||
|
item->time_inside = 0.0f;
|
||||||
|
item->pitch_min = 0.0f;
|
||||||
|
item->autocontinue = false;
|
||||||
|
item->origin = ORIGIN_ONBOARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos_sp_triplet->current.type != SETPOINT_TYPE_LOITER
|
|
||||||
|| (fabsf(pos_sp_triplet->current.loiter_radius - _navigator->get_loiter_radius()) > FLT_EPSILON)
|
|
||||||
|| pos_sp_triplet->current.loiter_direction != 1
|
|
||||||
|| pos_sp_triplet->previous.valid
|
|
||||||
|| !pos_sp_triplet->current.valid
|
|
||||||
|| pos_sp_triplet->next.valid) {
|
|
||||||
/* position setpoint triplet should be updated */
|
|
||||||
pos_sp_triplet->current.type = SETPOINT_TYPE_LOITER;
|
|
||||||
pos_sp_triplet->current.loiter_radius = _navigator->get_loiter_radius();
|
|
||||||
pos_sp_triplet->current.loiter_direction = 1;
|
|
||||||
|
|
||||||
pos_sp_triplet->previous.valid = false;
|
|
||||||
pos_sp_triplet->current.valid = true;
|
|
||||||
pos_sp_triplet->next.valid = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ~MissionBlock();
|
virtual ~MissionBlock();
|
||||||
|
|
||||||
|
protected:
|
||||||
/**
|
/**
|
||||||
* Check if mission item has been reached
|
* Check if mission item has been reached
|
||||||
* @return true if successfully reached
|
* @return true if successfully reached
|
||||||
@@ -85,22 +86,17 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Set previous position setpoint to current setpoint
|
* Set previous position setpoint to current setpoint
|
||||||
*/
|
*/
|
||||||
void set_previous_pos_setpoint(struct position_setpoint_triplet_s *pos_sp_triplet);
|
void set_previous_pos_setpoint();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a loiter item, if possible reuse the position setpoint, otherwise take the current position
|
* Set a loiter mission item, if possible reuse the position setpoint, otherwise take the current position
|
||||||
*
|
|
||||||
* @param the position setpoint triplet to set
|
|
||||||
* @return true if setpoint has changed
|
|
||||||
*/
|
*/
|
||||||
bool set_loiter_item(position_setpoint_triplet_s *pos_sp_triplet);
|
void set_loiter_item(struct mission_item_s *item);
|
||||||
|
|
||||||
|
mission_item_s _mission_item;
|
||||||
bool _waypoint_position_reached;
|
bool _waypoint_position_reached;
|
||||||
bool _waypoint_yaw_reached;
|
bool _waypoint_yaw_reached;
|
||||||
hrt_abstime _time_first_inside_orbit;
|
hrt_abstime _time_first_inside_orbit;
|
||||||
|
|
||||||
mission_item_s _mission_item;
|
|
||||||
bool _mission_item_valid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ public:
|
|||||||
* Setters
|
* Setters
|
||||||
*/
|
*/
|
||||||
void set_can_loiter_at_sp(bool can_loiter) { _can_loiter_at_sp = can_loiter; }
|
void set_can_loiter_at_sp(bool can_loiter) { _can_loiter_at_sp = can_loiter; }
|
||||||
|
void set_position_setpoint_triplet_updated() { _pos_sp_triplet_updated = true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getters
|
* Getters
|
||||||
@@ -110,6 +111,7 @@ public:
|
|||||||
struct vehicle_status_s* get_vstatus() { return &_vstatus; }
|
struct vehicle_status_s* get_vstatus() { return &_vstatus; }
|
||||||
struct vehicle_global_position_s* get_global_position() { return &_global_pos; }
|
struct vehicle_global_position_s* get_global_position() { return &_global_pos; }
|
||||||
struct home_position_s* get_home_position() { return &_home_pos; }
|
struct home_position_s* get_home_position() { return &_home_pos; }
|
||||||
|
struct position_setpoint_triplet_s* get_position_setpoint_triplet() { return &_pos_sp_triplet; }
|
||||||
int get_onboard_mission_sub() { return _onboard_mission_sub; }
|
int get_onboard_mission_sub() { return _onboard_mission_sub; }
|
||||||
int get_offboard_mission_sub() { return _offboard_mission_sub; }
|
int get_offboard_mission_sub() { return _offboard_mission_sub; }
|
||||||
Geofence& get_geofence() { return _geofence; }
|
Geofence& get_geofence() { return _geofence; }
|
||||||
@@ -162,7 +164,7 @@ private:
|
|||||||
NavigatorMode *_navigation_mode_array[NAVIGATOR_MODE_ARRAY_SIZE]; /**< array of navigation modes */
|
NavigatorMode *_navigation_mode_array[NAVIGATOR_MODE_ARRAY_SIZE]; /**< array of navigation modes */
|
||||||
|
|
||||||
bool _can_loiter_at_sp; /**< flags if current position SP can be used to loiter */
|
bool _can_loiter_at_sp; /**< flags if current position SP can be used to loiter */
|
||||||
bool _update_triplet; /**< flags if position SP triplet needs to be published */
|
bool _pos_sp_triplet_updated; /**< flags if position SP triplet needs to be published */
|
||||||
|
|
||||||
control::BlockParamFloat _param_loiter_radius; /**< loiter radius for fixedwing */
|
control::BlockParamFloat _param_loiter_radius; /**< loiter radius for fixedwing */
|
||||||
control::BlockParamFloat _param_acceptance_radius; /**< acceptance for takeoff */
|
control::BlockParamFloat _param_acceptance_radius; /**< acceptance for takeoff */
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ Navigator::Navigator() :
|
|||||||
_mission(this, "MIS"),
|
_mission(this, "MIS"),
|
||||||
_loiter(this, "LOI"),
|
_loiter(this, "LOI"),
|
||||||
_rtl(this, "RTL"),
|
_rtl(this, "RTL"),
|
||||||
_update_triplet(false),
|
_pos_sp_triplet_updated(false),
|
||||||
_param_loiter_radius(this, "LOITER_RAD"),
|
_param_loiter_radius(this, "LOITER_RAD"),
|
||||||
_param_acceptance_radius(this, "ACC_RAD")
|
_param_acceptance_radius(this, "ACC_RAD")
|
||||||
{
|
{
|
||||||
@@ -371,24 +371,21 @@ Navigator::task_main()
|
|||||||
|
|
||||||
/* iterate through navigation modes and set active/inactive for each */
|
/* iterate through navigation modes and set active/inactive for each */
|
||||||
for(unsigned int i = 0; i < NAVIGATOR_MODE_ARRAY_SIZE; i++) {
|
for(unsigned int i = 0; i < NAVIGATOR_MODE_ARRAY_SIZE; i++) {
|
||||||
if (_navigation_mode == _navigation_mode_array[i]) {
|
_navigation_mode_array[i]->run(_navigation_mode == _navigation_mode_array[i]);
|
||||||
_update_triplet = _navigation_mode_array[i]->on_active(&_pos_sp_triplet);
|
|
||||||
} else {
|
|
||||||
_navigation_mode_array[i]->on_inactive();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if nothing is running, set position setpoint triplet invalid */
|
/* if nothing is running, set position setpoint triplet invalid */
|
||||||
if (_navigation_mode == nullptr) {
|
if (_navigation_mode == nullptr) {
|
||||||
|
// TODO publish empty sp only once
|
||||||
_pos_sp_triplet.previous.valid = false;
|
_pos_sp_triplet.previous.valid = false;
|
||||||
_pos_sp_triplet.current.valid = false;
|
_pos_sp_triplet.current.valid = false;
|
||||||
_pos_sp_triplet.next.valid = false;
|
_pos_sp_triplet.next.valid = false;
|
||||||
_update_triplet = true;
|
_pos_sp_triplet_updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_update_triplet) {
|
if (_pos_sp_triplet_updated) {
|
||||||
publish_position_setpoint_triplet();
|
publish_position_setpoint_triplet();
|
||||||
_update_triplet = false;
|
_pos_sp_triplet_updated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
perf_end(_loop_perf);
|
perf_end(_loop_perf);
|
||||||
|
|||||||
@@ -33,12 +33,14 @@
|
|||||||
/**
|
/**
|
||||||
* @file navigator_mode.cpp
|
* @file navigator_mode.cpp
|
||||||
*
|
*
|
||||||
* Helper class for different modes in navigator
|
* Base class for different modes in navigator
|
||||||
*
|
*
|
||||||
* @author Julian Oes <julian@oes.ch>
|
* @author Julian Oes <julian@oes.ch>
|
||||||
|
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "navigator_mode.h"
|
#include "navigator_mode.h"
|
||||||
|
#include "navigator.h"
|
||||||
|
|
||||||
NavigatorMode::NavigatorMode(Navigator *navigator, const char *name) :
|
NavigatorMode::NavigatorMode(Navigator *navigator, const char *name) :
|
||||||
SuperBlock(NULL, name),
|
SuperBlock(NULL, name),
|
||||||
@@ -56,15 +58,38 @@ NavigatorMode::~NavigatorMode()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NavigatorMode::on_inactive()
|
NavigatorMode::run(bool active) {
|
||||||
{
|
if (active) {
|
||||||
_first_run = true;
|
if (_first_run) {
|
||||||
|
/* first run */
|
||||||
|
_first_run = false;
|
||||||
|
on_activation();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* periodic updates when active */
|
||||||
|
on_active();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* periodic updates when inactive */
|
||||||
|
_first_run = true;
|
||||||
|
on_inactive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
NavigatorMode::on_active(struct position_setpoint_triplet_s *pos_sp_triplet)
|
NavigatorMode::on_inactive()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NavigatorMode::on_activation()
|
||||||
|
{
|
||||||
|
/* invalidate position setpoint by default */
|
||||||
|
_navigator->get_position_setpoint_triplet()->current.valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NavigatorMode::on_active()
|
||||||
{
|
{
|
||||||
pos_sp_triplet->current.valid = false;
|
|
||||||
_first_run = false;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,9 +33,10 @@
|
|||||||
/**
|
/**
|
||||||
* @file navigator_mode.h
|
* @file navigator_mode.h
|
||||||
*
|
*
|
||||||
* Helper class for different modes in navigator
|
* Base class for different modes in navigator
|
||||||
*
|
*
|
||||||
* @author Julian Oes <julian@oes.ch>
|
* @author Julian Oes <julian@oes.ch>
|
||||||
|
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NAVIGATOR_MODE_H
|
#ifndef NAVIGATOR_MODE_H
|
||||||
@@ -65,21 +66,27 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ~NavigatorMode();
|
virtual ~NavigatorMode();
|
||||||
|
|
||||||
|
void run(bool active);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called while the mode is inactive
|
* This function is called while the mode is inactive
|
||||||
*/
|
*/
|
||||||
virtual void on_inactive();
|
virtual void on_inactive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called while the mode is active
|
* This function is called one time when mode become active, poos_sp_triplet must be initialized here
|
||||||
*
|
|
||||||
* @param position setpoint triplet to set
|
|
||||||
* @return true if position setpoint triplet has been changed
|
|
||||||
*/
|
*/
|
||||||
virtual bool on_active(struct position_setpoint_triplet_s *pos_sp_triplet);
|
virtual void on_activation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called while the mode is active
|
||||||
|
*/
|
||||||
|
virtual void on_active();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Navigator *_navigator;
|
Navigator *_navigator;
|
||||||
|
|
||||||
|
private:
|
||||||
bool _first_run;
|
bool _first_run;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -75,62 +75,57 @@ RTL::~RTL()
|
|||||||
void
|
void
|
||||||
RTL::on_inactive()
|
RTL::on_inactive()
|
||||||
{
|
{
|
||||||
_first_run = true;
|
|
||||||
|
|
||||||
/* reset RTL state only if setpoint moved */
|
/* reset RTL state only if setpoint moved */
|
||||||
if (!_navigator->get_can_loiter_at_sp()) {
|
if (!_navigator->get_can_loiter_at_sp()) {
|
||||||
_rtl_state = RTL_STATE_NONE;
|
_rtl_state = RTL_STATE_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
RTL::on_active(struct position_setpoint_triplet_s *pos_sp_triplet)
|
RTL::on_activation()
|
||||||
{
|
{
|
||||||
bool updated = false;
|
/* decide where to enter the RTL procedure when we switch into it */
|
||||||
|
if (_rtl_state == RTL_STATE_NONE) {
|
||||||
|
/* for safety reasons don't go into RTL if landed */
|
||||||
|
if (_navigator->get_vstatus()->condition_landed) {
|
||||||
|
_rtl_state = RTL_STATE_LANDED;
|
||||||
|
mavlink_log_info(_navigator->get_mavlink_fd(), "#audio: no RTL when landed");
|
||||||
|
|
||||||
if (_first_run) {
|
/* if lower than return altitude, climb up first */
|
||||||
_first_run = false;
|
} else if (_navigator->get_global_position()->alt < _navigator->get_home_position()->alt
|
||||||
|
+ _param_return_alt.get()) {
|
||||||
|
_rtl_state = RTL_STATE_CLIMB;
|
||||||
|
|
||||||
/* decide where to enter the RTL procedure when we switch into it */
|
/* otherwise go straight to return */
|
||||||
if (_rtl_state == RTL_STATE_NONE) {
|
} else {
|
||||||
/* for safety reasons don't go into RTL if landed */
|
/* set altitude setpoint to current altitude */
|
||||||
if (_navigator->get_vstatus()->condition_landed) {
|
_rtl_state = RTL_STATE_RETURN;
|
||||||
_rtl_state = RTL_STATE_LANDED;
|
_mission_item.altitude_is_relative = false;
|
||||||
mavlink_log_info(_navigator->get_mavlink_fd(), "#audio: no RTL when landed");
|
_mission_item.altitude = _navigator->get_global_position()->alt;
|
||||||
|
|
||||||
/* if lower than return altitude, climb up first */
|
|
||||||
} else if (_navigator->get_global_position()->alt < _navigator->get_home_position()->alt
|
|
||||||
+ _param_return_alt.get()) {
|
|
||||||
_rtl_state = RTL_STATE_CLIMB;
|
|
||||||
|
|
||||||
/* otherwise go straight to return */
|
|
||||||
} else {
|
|
||||||
/* set altitude setpoint to current altitude */
|
|
||||||
_rtl_state = RTL_STATE_RETURN;
|
|
||||||
_mission_item.altitude_is_relative = false;
|
|
||||||
_mission_item.altitude = _navigator->get_global_position()->alt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_rtl_item(pos_sp_triplet);
|
|
||||||
updated = true;
|
|
||||||
|
|
||||||
} else if (_rtl_state != RTL_STATE_LANDED && is_mission_item_reached()) {
|
|
||||||
advance_rtl();
|
|
||||||
set_rtl_item(pos_sp_triplet);
|
|
||||||
updated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated;
|
set_rtl_item();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTL::set_rtl_item(position_setpoint_triplet_s *pos_sp_triplet)
|
RTL::on_active()
|
||||||
{
|
{
|
||||||
|
if (_rtl_state != RTL_STATE_LANDED && is_mission_item_reached()) {
|
||||||
|
advance_rtl();
|
||||||
|
set_rtl_item();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTL::set_rtl_item()
|
||||||
|
{
|
||||||
|
struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();
|
||||||
|
|
||||||
/* make sure we have the latest params */
|
/* make sure we have the latest params */
|
||||||
updateParams();
|
updateParams();
|
||||||
|
|
||||||
set_previous_pos_setpoint(pos_sp_triplet);
|
set_previous_pos_setpoint();
|
||||||
_navigator->set_can_loiter_at_sp(false);
|
_navigator->set_can_loiter_at_sp(false);
|
||||||
|
|
||||||
switch (_rtl_state) {
|
switch (_rtl_state) {
|
||||||
@@ -277,11 +272,13 @@ RTL::set_rtl_item(position_setpoint_triplet_s *pos_sp_triplet)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_mission_item_reached();
|
||||||
|
|
||||||
/* convert mission item to current position setpoint and make it valid */
|
/* convert mission item to current position setpoint and make it valid */
|
||||||
mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
|
mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
|
||||||
reset_mission_item_reached();
|
|
||||||
pos_sp_triplet->current.valid = true;
|
|
||||||
pos_sp_triplet->next.valid = false;
|
pos_sp_triplet->next.valid = false;
|
||||||
|
|
||||||
|
_navigator->set_position_setpoint_triplet_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -57,35 +57,21 @@ class Navigator;
|
|||||||
class RTL : public MissionBlock
|
class RTL : public MissionBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
RTL(Navigator *navigator, const char *name);
|
RTL(Navigator *navigator, const char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~RTL();
|
~RTL();
|
||||||
|
|
||||||
/**
|
virtual void on_inactive();
|
||||||
* This function is called while the mode is inactive
|
|
||||||
*/
|
|
||||||
void on_inactive();
|
|
||||||
|
|
||||||
/**
|
virtual void on_activation();
|
||||||
* This function is called while the mode is active
|
|
||||||
*
|
|
||||||
* @param position setpoint triplet that needs to be set
|
|
||||||
* @return true if updated
|
|
||||||
*/
|
|
||||||
bool on_active(position_setpoint_triplet_s *pos_sp_triplet);
|
|
||||||
|
|
||||||
|
virtual void on_active();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Set the RTL item
|
* Set the RTL item
|
||||||
*/
|
*/
|
||||||
void set_rtl_item(position_setpoint_triplet_s *pos_sp_triplet);
|
void set_rtl_item();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move to next RTL item
|
* Move to next RTL item
|
||||||
|
|||||||
Reference in New Issue
Block a user