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

WP mission waypoint enforce altitude option #7644

Merged
merged 4 commits into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -3852,6 +3852,16 @@ Defines how Pitch/Roll input from RC receiver affects flight in POSHOLD mode: AT

---

### nav_wp_enforce_altitude

Forces craft to achieve the set WP altitude as well as position before moving to next WP. Position is held and altitude adjusted as required before moving on.

| Default | Min | Max |
| --- | --- | --- |
| OFF | OFF | ON |

---

### nav_wp_load_on_boot

If set to ON, waypoints will be automatically loaded from EEPROM to the FC during startup.
Expand Down
1 change: 1 addition & 0 deletions src/main/cms/cms_menu_navigation.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ static const OSD_Entry cmsx_menuMissionSettingsEntries[] =
OSD_SETTING_ENTRY("MISSION FAILSAFE", SETTING_FAILSAFE_MISSION),
OSD_SETTING_ENTRY("WP LOAD ON BOOT", SETTING_NAV_WP_LOAD_ON_BOOT),
OSD_SETTING_ENTRY("WP REACHED RADIUS", SETTING_NAV_WP_RADIUS),
OSD_SETTING_ENTRY("WP ENFORCE ALTITUDE", SETTING_NAV_WP_ENFORCE_ALTITUDE),
OSD_SETTING_ENTRY("WP SAFE DISTANCE", SETTING_NAV_WP_SAFE_DISTANCE),
#ifdef USE_MULTI_MISSION
OSD_SETTING_ENTRY("MULTI MISSION NUMBER", SETTING_NAV_WP_MULTI_MISSION_INDEX),
Expand Down
5 changes: 5 additions & 0 deletions src/main/fc/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2392,6 +2392,11 @@ groups:
field: general.waypoint_radius
min: 10
max: 10000
- name: nav_wp_enforce_altitude
description: "Forces craft to achieve the set WP altitude as well as position before moving to next WP. Position is held and altitude adjusted as required before moving on."
default_value: OFF
field: general.flags.waypoint_enforce_altitude
type: bool
- name: nav_wp_safe_distance
description: "First waypoint in the mission should be closer than this value [cm]. A value of 0 disables this check."
default_value: 10000
Expand Down
14 changes: 9 additions & 5 deletions src/main/io/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -4193,13 +4193,17 @@ textAttributes_t osdGetSystemMessage(char *buff, size_t buff_size, bool isCenter
tfp_sprintf(messageBuf, "TO WP %u/%u (%s)", getGeoWaypointNumber(posControl.activeWaypointIndex), posControl.geoWaypointCount, buf);
messages[messageCount++] = messageBuf;
} else if (NAV_Status.state == MW_NAV_STATE_HOLD_TIMED) {
// WP hold time countdown in seconds
timeMs_t currentTime = millis();
int holdTimeRemaining = posControl.waypointList[posControl.activeWaypointIndex].p1 - (int)((currentTime - posControl.wpReachedTime)/1000);
if (holdTimeRemaining >=0) {
if (navConfig()->general.flags.waypoint_enforce_altitude && !posControl.wpAltitudeReached) {
messages[messageCount++] = OSD_MESSAGE_STR(OSD_MSG_ADJUSTING_WP_ALT);
} else {
// WP hold time countdown in seconds
timeMs_t currentTime = millis();
int holdTimeRemaining = posControl.waypointList[posControl.activeWaypointIndex].p1 - (int)(MS2S(currentTime - posControl.wpReachedTime));
holdTimeRemaining = holdTimeRemaining >= 0 ? holdTimeRemaining : 0;
tfp_sprintf(messageBuf, "HOLDING WP FOR %2u S", holdTimeRemaining);

messages[messageCount++] = messageBuf;
}
messages[messageCount++] = messageBuf;
} else {
const char *navStateMessage = navigationStateMessage();
if (navStateMessage) {
Expand Down
1 change: 1 addition & 0 deletions src/main/io/osd.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
#define OSD_MSG_HEADING_HOME "EN ROUTE TO HOME"
#define OSD_MSG_WP_FINISHED "WP END>HOLDING POSITION"
#define OSD_MSG_PREPARE_NEXT_WP "PREPARING FOR NEXT WAYPOINT"
#define OSD_MSG_ADJUSTING_WP_ALT "ADJUSTING WP ALTITUDE"
#define OSD_MSG_MISSION_PLANNER "(WP MISSION PLANNER)"
#define OSD_MSG_WP_RTH_CANCEL "CANCEL WP TO EXIT RTH"
#define OSD_MSG_WP_MISSION_LOADED "* MISSION LOADED *"
Expand Down
45 changes: 39 additions & 6 deletions src/main/navigation/navigation.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
#include "sensors/acceleration.h"
#include "sensors/boardalignment.h"


#define WP_ALTITUDE_MARGIN_CM 100 // WP enforce altitude tolerance, used when WP altitude setting enforced when WP reached
// Multirotors:
#define MR_RTH_CLIMB_OVERSHOOT_CM 100 // target this amount of cm *above* the target altitude to ensure it is actually reached (Vz > 0 at target alt)
#define MR_RTH_CLIMB_MARGIN_MIN_CM 100 // start cruising home this amount of cm *before* reaching the cruise altitude (while continuing the ascend)
Expand Down Expand Up @@ -97,7 +97,7 @@ STATIC_ASSERT(NAV_MAX_WAYPOINTS < 254, NAV_MAX_WAYPOINTS_exceeded_allowable_rang
PG_REGISTER_ARRAY(navWaypoint_t, NAV_MAX_WAYPOINTS, nonVolatileWaypointList, PG_WAYPOINT_MISSION_STORAGE, 1);
#endif

PG_REGISTER_WITH_RESET_TEMPLATE(navConfig_t, navConfig, PG_NAV_CONFIG, 14);
PG_REGISTER_WITH_RESET_TEMPLATE(navConfig_t, navConfig, PG_NAV_CONFIG, 15);

PG_RESET_TEMPLATE(navConfig_t, navConfig,
.general = {
Expand All @@ -117,8 +117,9 @@ PG_RESET_TEMPLATE(navConfig_t, navConfig,
.nav_overrides_motor_stop = SETTING_NAV_OVERRIDES_MOTOR_STOP_DEFAULT,
.safehome_usage_mode = SETTING_SAFEHOME_USAGE_MODE_DEFAULT,
.mission_planner_reset = SETTING_NAV_MISSION_PLANNER_RESET_DEFAULT, // Allow mode switch toggle to reset Mission Planner WPs
.waypoint_mission_restart = SETTING_NAV_WP_MISSION_RESTART_DEFAULT, // WP mission restart action
.waypoint_mission_restart = SETTING_NAV_WP_MISSION_RESTART_DEFAULT, // WP mission restart action
.soaring_motor_stop = SETTING_NAV_FW_SOARING_MOTOR_STOP_DEFAULT, // stops motor when Saoring mode enabled
.waypoint_enforce_altitude = SETTING_NAV_WP_ENFORCE_ALTITUDE_DEFAULT, // Forces set wp altitude to be achieved
},

// General navigation parameters
Expand Down Expand Up @@ -243,6 +244,7 @@ void calculateInitialHoldPosition(fpVector3_t * pos);
void calculateFarAwayTarget(fpVector3_t * farAwayPos, int32_t yaw, int32_t distance);
void calculateNewCruiseTarget(fpVector3_t * origin, int32_t yaw, int32_t distance);
static bool isWaypointPositionReached(const fpVector3_t * pos, const bool isWaypointHome);
bool isWaypointAltitudeReached(void);
static void mapWaypointToLocalPosition(fpVector3_t * localPos, const navWaypoint_t * waypoint, geoAltitudeConversionMode_e altConv);
static navigationFSMEvent_t nextForNonGeoStates(void);
static bool isWaypointMissionValid(void);
Expand Down Expand Up @@ -1482,6 +1484,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_PRE_ACTION(nav
calculateAndSetActiveWaypoint(&posControl.waypointList[posControl.activeWaypointIndex]);
posControl.wpInitialDistance = calculateDistanceToDestination(&posControl.activeWaypoint.pos);
posControl.wpInitialAltitude = posControl.actualState.abs.pos.z;
posControl.wpAltitudeReached = false;
return NAV_FSM_EVENT_SUCCESS; // will switch to NAV_STATE_WAYPOINT_IN_PROGRESS

// We use p3 as the volatile jump counter (p2 is the static value)
Expand Down Expand Up @@ -1583,9 +1586,17 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_REACHED(naviga
{
UNUSED(previousState);

if (navConfig()->general.flags.waypoint_enforce_altitude) {
posControl.wpAltitudeReached = isWaypointAltitudeReached();
}

switch ((navWaypointActions_e)posControl.waypointList[posControl.activeWaypointIndex].action) {
case NAV_WP_ACTION_WAYPOINT:
return NAV_FSM_EVENT_SUCCESS; // NAV_STATE_WAYPOINT_NEXT
if (navConfig()->general.flags.waypoint_enforce_altitude && !posControl.wpAltitudeReached) {
return NAV_FSM_EVENT_SWITCH_TO_WAYPOINT_HOLD_TIME;
} else {
return NAV_FSM_EVENT_SUCCESS; // NAV_STATE_WAYPOINT_NEXT
}

case NAV_WP_ACTION_JUMP:
case NAV_WP_ACTION_SET_HEAD:
Expand Down Expand Up @@ -1614,14 +1625,31 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_HOLD_TIME(navi
return NAV_FSM_EVENT_SWITCH_TO_EMERGENCY_LANDING;
}

if (navConfig()->general.flags.waypoint_enforce_altitude && !posControl.wpAltitudeReached) {
// Adjust altitude to waypoint setting
if (STATE(AIRPLANE)) {
int8_t altitudeChangeDirection = posControl.activeWaypoint.pos.z > navGetCurrentActualPositionAndVelocity()->pos.z ? 1 : -1;
updateClimbRateToAltitudeController(altitudeChangeDirection * navConfig()->general.max_auto_climb_rate, ROC_TO_ALT_NORMAL);
} else {
setDesiredPosition(&posControl.activeWaypoint.pos, 0, NAV_POS_UPDATE_Z);
}

posControl.wpAltitudeReached = isWaypointAltitudeReached();

if (posControl.wpAltitudeReached) {
posControl.wpReachedTime = millis();
} else {
return NAV_FSM_EVENT_NONE;
}
}

timeMs_t currentTime = millis();

if (posControl.waypointList[posControl.activeWaypointIndex].p1 <= 0 ||
(posControl.wpReachedTime != 0 && currentTime - posControl.wpReachedTime >= (timeMs_t)posControl.waypointList[posControl.activeWaypointIndex].p1*1000L)) {
return NAV_FSM_EVENT_SUCCESS;
}


return NAV_FSM_EVENT_NONE; // will re-process state in >10ms
}

Expand Down Expand Up @@ -2132,6 +2160,11 @@ bool isWaypointReached(const navWaypointPosition_t * waypoint, const bool isWayp
return isWaypointPositionReached(&waypoint->pos, isWaypointHome);
}

bool isWaypointAltitudeReached(void)
{
return ABS(navGetCurrentActualPositionAndVelocity()->pos.z - posControl.activeWaypoint.pos.z) < WP_ALTITUDE_MARGIN_CM;
}

static void updateHomePositionCompatibility(void)
{
geoConvertLocalToGeodetic(&GPS_home, &posControl.gpsOrigin, &posControl.rthState.homePosition.pos);
Expand Down Expand Up @@ -2596,7 +2629,7 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, climbRateToAlti
lastUpdateTimeUs = currentTimeUs;
posControl.desiredState.pos.z = altitudeToUse;
}
else {
else { // ROC_TO_ALT_NORMAL

/*
* If max altitude is set, reset climb rate if altitude is reached and climb rate is > 0
Expand Down
1 change: 1 addition & 0 deletions src/main/navigation/navigation.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ typedef struct navConfig_s {
uint8_t soaring_motor_stop; // stop motor when Soaring mode enabled
uint8_t mission_planner_reset; // Allow WP Mission Planner reset using mode toggle (resets WPs to 0)
uint8_t waypoint_mission_restart; // Waypoint mission restart action
uint8_t waypoint_enforce_altitude; // Forces waypoint altitude to be achieved
} flags;

uint8_t pos_failure_timeout; // Time to wait before switching to emergency landing (0 - disable)
Expand Down
11 changes: 6 additions & 5 deletions src/main/navigation/navigation_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,12 +371,13 @@ typedef struct {
int8_t loadedMultiMissionStartWP; // selected multi mission start WP
int8_t loadedMultiMissionWPCount; // number of WPs in selected multi mission
#endif
navWaypointPosition_t activeWaypoint; // Local position and initial bearing, filled on waypoint activation
navWaypointPosition_t activeWaypoint; // Local position and initial bearing, filled on waypoint activation
int8_t activeWaypointIndex;
float wpInitialAltitude; // Altitude at start of WP
float wpInitialDistance; // Distance when starting flight to WP
float wpDistance; // Distance to active WP
timeMs_t wpReachedTime; // Time the waypoint was reached
float wpInitialAltitude; // Altitude at start of WP
float wpInitialDistance; // Distance when starting flight to WP
float wpDistance; // Distance to active WP
timeMs_t wpReachedTime; // Time the waypoint was reached
bool wpAltitudeReached; // WP altitude achieved

/* Internals & statistics */
int16_t rcAdjustment[4];
Expand Down