Skip to content

Commit

Permalink
Merge pull request #9213 from breadoven/abo_mc_course_hold_cruise
Browse files Browse the repository at this point in the history
Multirotor course hold/cruise mode
  • Loading branch information
DzikuVx authored Sep 5, 2023
2 parents 61de9c1 + c5c1603 commit 0d8e788
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 163 deletions.
20 changes: 10 additions & 10 deletions docs/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -2662,6 +2662,16 @@ Speed in fully autonomous modes (RTH, WP) [cm/s]. Used for WP mode when no speci

---

### nav_cruise_yaw_rate

Max YAW rate when NAV COURSE HOLD/CRUISE mode is enabled. Set to 0 to disable on fixed wing (Note: On multirotor setting to 0 will disable Course Hold/Cruise mode completely) [dps]

| Default | Min | Max |
| --- | --- | --- |
| 20 | 0 | 120 |

---

### nav_disarm_on_landing

If set to ON, INAV disarms the FC after landing
Expand Down Expand Up @@ -2752,16 +2762,6 @@ Cruise throttle in GPS assisted modes, this includes RTH. Should be set high eno

---

### nav_fw_cruise_yaw_rate

Max YAW rate when NAV CRUISE mode is enabled (0=disable control via yaw stick) [dps]

| Default | Min | Max |
| --- | --- | --- |
| 20 | 0 | 60 |

---

### nav_fw_dive_angle

Max negative pitch angle when diving in GPS assisted modes, is also restrained by global max_angle_inclination_pit
Expand Down
4 changes: 2 additions & 2 deletions src/main/fc/fc_msp_box.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ void initActiveBoxIds(void)
if (!STATE(ALTITUDE_CONTROL) || (STATE(ALTITUDE_CONTROL) && navReadyAltControl)) {
ADD_ACTIVE_BOX(BOXNAVRTH);
ADD_ACTIVE_BOX(BOXNAVWP);
ADD_ACTIVE_BOX(BOXNAVCRUISE);
ADD_ACTIVE_BOX(BOXNAVCOURSEHOLD);
ADD_ACTIVE_BOX(BOXHOMERESET);
ADD_ACTIVE_BOX(BOXGCSNAV);
ADD_ACTIVE_BOX(BOXPLANWPMISSION);
Expand All @@ -240,8 +242,6 @@ void initActiveBoxIds(void)
}

if (STATE(AIRPLANE)) {
ADD_ACTIVE_BOX(BOXNAVCRUISE);
ADD_ACTIVE_BOX(BOXNAVCOURSEHOLD);
ADD_ACTIVE_BOX(BOXSOARING);
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/main/fc/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2584,6 +2584,12 @@ groups:
default_value: ON
field: general.flags.mission_planner_reset
type: bool
- name: nav_cruise_yaw_rate
description: "Max YAW rate when NAV COURSE HOLD/CRUISE mode is enabled. Set to 0 to disable on fixed wing (Note: On multirotor setting to 0 will disable Course Hold/Cruise mode completely) [dps]"
default_value: 20
field: general.cruise_yaw_rate
min: 0
max: 120
- name: nav_mc_bank_angle
description: "Maximum banking angle (deg) that multicopter navigation is allowed to set. Machine must be able to satisfy this angle without loosing altitude"
default_value: 30
Expand Down Expand Up @@ -2819,12 +2825,6 @@ groups:
field: fw.launch_abort_deadband
min: 2
max: 250
- name: nav_fw_cruise_yaw_rate
description: "Max YAW rate when NAV CRUISE mode is enabled (0=disable control via yaw stick) [dps]"
default_value: 20
field: fw.cruise_yaw_rate
min: 0
max: 60
- name: nav_fw_allow_manual_thr_increase
description: "Enable the possibility to manually increase the throttle in auto throttle controlled modes for fixed wing"
default_value: OFF
Expand Down
13 changes: 5 additions & 8 deletions src/main/flight/pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,17 +898,14 @@ float pidHeadingHold(float dT)
{
float headingHoldRate;

/* Convert absolute error into relative to current heading */
int16_t error = DECIDEGREES_TO_DEGREES(attitude.values.yaw) - headingHoldTarget;

/*
* Convert absolute error into relative to current heading
*/
if (error <= -180) {
error += 360;
}

if (error >= +180) {
/* Convert absolute error into relative to current heading */
if (error > 180) {
error -= 360;
} else if (error < -180) {
error += 360;
}

/*
Expand Down
10 changes: 10 additions & 0 deletions src/main/io/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -4905,6 +4905,16 @@ textAttributes_t osdGetSystemMessage(char *buff, size_t buff_size, bool isCenter
// by OSD_FLYMODE.
messages[messageCount++] = OSD_MESSAGE_STR(OSD_MSG_ALTITUDE_HOLD);
}
if (STATE(MULTIROTOR) && FLIGHT_MODE(NAV_COURSE_HOLD_MODE)) {
if (posControl.cruise.multicopterSpeed >= 50.0f) {
char buf[6];
osdFormatVelocityStr(buf, posControl.cruise.multicopterSpeed, false, false);
tfp_sprintf(messageBuf, "(SPD %s)", buf);
} else {
strcpy(messageBuf, "(HOLD)");
}
messages[messageCount++] = messageBuf;
}
if (IS_RC_MODE_ACTIVE(BOXAUTOTRIM) && !feature(FEATURE_FW_AUTOTRIM)) {
messages[messageCount++] = OSD_MESSAGE_STR(OSD_MSG_AUTOTRIM);
}
Expand Down
140 changes: 77 additions & 63 deletions src/main/navigation/navigation.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ PG_RESET_TEMPLATE(navConfig_t, navConfig,
.land_detect_sensitivity = SETTING_NAV_LAND_DETECT_SENSITIVITY_DEFAULT, // Changes sensitivity of landing detection
.auto_disarm_delay = SETTING_NAV_AUTO_DISARM_DELAY_DEFAULT, // 2000 ms - time delay to disarm when auto disarm after landing enabled
.rth_linear_descent_start_distance = SETTING_NAV_RTH_LINEAR_DESCENT_START_DISTANCE_DEFAULT,
.cruise_yaw_rate = SETTING_NAV_CRUISE_YAW_RATE_DEFAULT, // 20dps
},

// MC-specific
Expand Down Expand Up @@ -207,7 +208,6 @@ PG_RESET_TEMPLATE(navConfig_t, navConfig,
.launch_manual_throttle = SETTING_NAV_FW_LAUNCH_MANUAL_THROTTLE_DEFAULT,// OFF
.launch_abort_deadband = SETTING_NAV_FW_LAUNCH_ABORT_DEADBAND_DEFAULT, // 100 us

.cruise_yaw_rate = SETTING_NAV_FW_CRUISE_YAW_RATE_DEFAULT, // 20dps
.allow_manual_thr_increase = SETTING_NAV_FW_ALLOW_MANUAL_THR_INCREASE_DEFAULT,
.useFwNavYawControl = SETTING_NAV_USE_FW_YAW_CONTROL_DEFAULT,
.yawControlDeadband = SETTING_NAV_FW_YAW_DEADBAND_DEFAULT,
Expand Down Expand Up @@ -422,7 +422,7 @@ static const navigationFSMStateDescriptor_t navFSM[NAV_STATE_COUNT] = {
.persistentId = NAV_PERSISTENT_ID_COURSE_HOLD_IN_PROGRESS,
.onEntry = navOnEnteringState_NAV_STATE_COURSE_HOLD_IN_PROGRESS,
.timeoutMs = 10,
.stateFlags = NAV_CTL_POS | NAV_CTL_YAW | NAV_REQUIRE_ANGLE | NAV_RC_POS | NAV_RC_YAW,
.stateFlags = NAV_CTL_POS | NAV_CTL_YAW | NAV_REQUIRE_ANGLE | NAV_REQUIRE_MAGHOLD | NAV_RC_POS | NAV_RC_YAW,
.mapToFlightModes = NAV_COURSE_HOLD_MODE,
.mwState = MW_NAV_STATE_NONE,
.mwError = MW_NAV_ERROR_NONE,
Expand Down Expand Up @@ -481,7 +481,7 @@ static const navigationFSMStateDescriptor_t navFSM[NAV_STATE_COUNT] = {
.persistentId = NAV_PERSISTENT_ID_CRUISE_IN_PROGRESS,
.onEntry = navOnEnteringState_NAV_STATE_CRUISE_IN_PROGRESS,
.timeoutMs = 10,
.stateFlags = NAV_CTL_ALT | NAV_CTL_POS | NAV_CTL_YAW | NAV_REQUIRE_ANGLE | NAV_RC_POS | NAV_RC_YAW | NAV_RC_ALT,
.stateFlags = NAV_CTL_ALT | NAV_CTL_POS | NAV_CTL_YAW | NAV_REQUIRE_ANGLE | NAV_REQUIRE_MAGHOLD | NAV_REQUIRE_THRTILT | NAV_RC_POS | NAV_RC_YAW | NAV_RC_ALT,
.mapToFlightModes = NAV_ALTHOLD_MODE | NAV_COURSE_HOLD_MODE,
.mwState = MW_NAV_STATE_NONE,
.mwError = MW_NAV_ERROR_NONE,
Expand Down Expand Up @@ -948,7 +948,7 @@ static navigationFSMStateFlags_t navGetStateFlags(navigationFSMState_t state)
return navFSM[state].stateFlags;
}

static flightModeFlags_e navGetMappedFlightModes(navigationFSMState_t state)
flightModeFlags_e navGetMappedFlightModes(navigationFSMState_t state)
{
return navFSM[state].mapToFlightModes;
}
Expand Down Expand Up @@ -1055,7 +1055,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_COURSE_HOLD_INITIALIZE(
{
UNUSED(previousState);

if (!STATE(FIXED_WING_LEGACY)) { // Only on FW for now
if (STATE(MULTIROTOR) && !navConfig()->general.cruise_yaw_rate) { // course hold not possible on MR without yaw control
return NAV_FSM_EVENT_ERROR;
}

Expand All @@ -1067,7 +1067,13 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_COURSE_HOLD_INITIALIZE(

resetPositionController();

posControl.cruise.course = posControl.actualState.cog; // Store the course to follow
if (STATE(AIRPLANE)) {
posControl.cruise.course = posControl.actualState.cog; // Store the course to follow
} else { // Multicopter
posControl.cruise.course = posControl.actualState.yaw;
posControl.cruise.multicopterSpeed = constrainf(posControl.actualState.velXY, 10.0f, navConfig()->general.max_manual_speed);
posControl.desiredState.pos = posControl.actualState.abs.pos;
}
posControl.cruise.previousCourse = posControl.cruise.course;
posControl.cruise.lastCourseAdjustmentTime = 0;

Expand All @@ -1088,15 +1094,24 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_COURSE_HOLD_IN_PROGRESS
DEBUG_SET(DEBUG_CRUISE, 0, 2);
DEBUG_SET(DEBUG_CRUISE, 2, 0);

if (posControl.flags.isAdjustingPosition) {
if (STATE(AIRPLANE) && posControl.flags.isAdjustingPosition) { // inhibit for MR, pitch/roll only adjusts speed using pitch
return NAV_FSM_EVENT_SWITCH_TO_COURSE_ADJ;
}

// User is yawing. We record the desidered yaw and we change the desidered target in the meanwhile
if (posControl.flags.isAdjustingHeading) {
const bool mcRollStickHeadingAdjustmentActive = STATE(MULTIROTOR) && ABS(rcCommand[ROLL]) > rcControlsConfig()->pos_hold_deadband;

// User demanding yaw -> yaw stick on FW, yaw or roll sticks on MR
// We record the desired course and change the desired target in the meanwhile
if (posControl.flags.isAdjustingHeading || mcRollStickHeadingAdjustmentActive) {
int16_t cruiseYawRate = DEGREES_TO_CENTIDEGREES(navConfig()->general.cruise_yaw_rate);
int16_t headingAdjustCommand = rcCommand[YAW];
if (mcRollStickHeadingAdjustmentActive && ABS(rcCommand[ROLL]) > ABS(headingAdjustCommand)) {
headingAdjustCommand = -rcCommand[ROLL];
}

timeMs_t timeDifference = currentTimeMs - posControl.cruise.lastCourseAdjustmentTime;
if (timeDifference > 100) timeDifference = 0; // if adjustment was called long time ago, reset the time difference.
float rateTarget = scaleRangef((float)rcCommand[YAW], -500.0f, 500.0f, -DEGREES_TO_CENTIDEGREES(navConfig()->fw.cruise_yaw_rate), DEGREES_TO_CENTIDEGREES(navConfig()->fw.cruise_yaw_rate));
float rateTarget = scaleRangef((float)headingAdjustCommand, -500.0f, 500.0f, -cruiseYawRate, cruiseYawRate);
float centidegsPerIteration = rateTarget * MS2S(timeDifference);
posControl.cruise.course = wrap_36000(posControl.cruise.course - centidegsPerIteration);
DEBUG_SET(DEBUG_CRUISE, 1, CENTIDEGREES_TO_DEGREES(posControl.cruise.course));
Expand Down Expand Up @@ -1129,7 +1144,9 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_COURSE_HOLD_ADJUSTING(n

static navigationFSMEvent_t navOnEnteringState_NAV_STATE_CRUISE_INITIALIZE(navigationFSMState_t previousState)
{
if (!STATE(FIXED_WING_LEGACY)) { return NAV_FSM_EVENT_ERROR; } // only on FW for now
if (STATE(MULTIROTOR) && !navConfig()->general.cruise_yaw_rate) { // course hold not possible on MR without yaw control
return NAV_FSM_EVENT_ERROR;
}

navOnEnteringState_NAV_STATE_ALTHOLD_INITIALIZE(previousState);

Expand Down Expand Up @@ -2448,13 +2465,13 @@ void checkSafeHomeState(bool shouldBeEnabled)
safehomeNotApplicable = safehomeNotApplicable || (MULTI_FUNC_FLAG(MF_SUSPEND_SAFEHOMES) && !posControl.flags.forcedRTHActivated);
#endif

if (safehomeNotApplicable) {
shouldBeEnabled = false;
} else if (navConfig()->general.flags.safehome_usage_mode == SAFEHOME_USAGE_RTH_FS && shouldBeEnabled) {
// if safehomes are only used with failsafe and we're trying to enable safehome
// then enable the safehome only with failsafe
shouldBeEnabled = posControl.flags.forcedRTHActivated;
}
if (safehomeNotApplicable) {
shouldBeEnabled = false;
} else if (navConfig()->general.flags.safehome_usage_mode == SAFEHOME_USAGE_RTH_FS && shouldBeEnabled) {
// if safehomes are only used with failsafe and we're trying to enable safehome
// then enable the safehome only with failsafe
shouldBeEnabled = posControl.flags.forcedRTHActivated;
}
// no safe homes found when arming or safehome feature in the correct state, then we don't need to do anything
if (posControl.safehomeState.distance == 0 || posControl.safehomeState.isApplied == shouldBeEnabled) {
return;
Expand Down Expand Up @@ -2485,8 +2502,8 @@ bool findNearestSafeHome(void)
gpsLocation_t shLLH;
shLLH.alt = 0;
for (uint8_t i = 0; i < MAX_SAFE_HOMES; i++) {
if (!safeHomeConfig(i)->enabled)
continue;
if (!safeHomeConfig(i)->enabled)
continue;

shLLH.lat = safeHomeConfig(i)->lat;
shLLH.lon = safeHomeConfig(i)->lon;
Expand Down Expand Up @@ -3426,33 +3443,34 @@ bool isNavHoldPositionActive(void)
navigationIsExecutingAnEmergencyLanding();
}

float getActiveWaypointSpeed(void)
float getActiveSpeed(void)
{
if (posControl.flags.isAdjustingPosition) {
// In manual control mode use different cap for speed
/* Currently only applicable for multicopter */

// Speed limit for modes where speed manually controlled
if (posControl.flags.isAdjustingPosition || FLIGHT_MODE(NAV_COURSE_HOLD_MODE)) {
return navConfig()->general.max_manual_speed;
}
else {
uint16_t waypointSpeed = navConfig()->general.auto_speed;

if (navGetStateFlags(posControl.navState) & NAV_AUTO_WP) {
if (posControl.waypointCount > 0 && (posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_WAYPOINT || posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_HOLD_TIME || posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_LAND)) {
float wpSpecificSpeed = 0.0f;
if(posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_HOLD_TIME)
wpSpecificSpeed = posControl.waypointList[posControl.activeWaypointIndex].p2; // P1 is hold time
else
wpSpecificSpeed = posControl.waypointList[posControl.activeWaypointIndex].p1; // default case
uint16_t waypointSpeed = navConfig()->general.auto_speed;

if (wpSpecificSpeed >= 50.0f && wpSpecificSpeed <= navConfig()->general.max_auto_speed) {
waypointSpeed = wpSpecificSpeed;
} else if (wpSpecificSpeed > navConfig()->general.max_auto_speed) {
waypointSpeed = navConfig()->general.max_auto_speed;
}
if (navGetStateFlags(posControl.navState) & NAV_AUTO_WP) {
if (posControl.waypointCount > 0 && (posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_WAYPOINT || posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_HOLD_TIME || posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_LAND)) {
float wpSpecificSpeed = 0.0f;
if(posControl.waypointList[posControl.activeWaypointIndex].action == NAV_WP_ACTION_HOLD_TIME)
wpSpecificSpeed = posControl.waypointList[posControl.activeWaypointIndex].p2; // P1 is hold time
else
wpSpecificSpeed = posControl.waypointList[posControl.activeWaypointIndex].p1; // default case

if (wpSpecificSpeed >= 50.0f && wpSpecificSpeed <= navConfig()->general.max_auto_speed) {
waypointSpeed = wpSpecificSpeed;
} else if (wpSpecificSpeed > navConfig()->general.max_auto_speed) {
waypointSpeed = navConfig()->general.max_auto_speed;
}
}

return waypointSpeed;
}

return waypointSpeed;
}

bool isWaypointNavTrackingActive(void)
Expand All @@ -3471,29 +3489,21 @@ static void processNavigationRCAdjustments(void)
{
/* Process pilot's RC input. Disable all pilot's input when in FAILSAFE_MODE */
navigationFSMStateFlags_t navStateFlags = navGetStateFlags(posControl.navState);
if ((navStateFlags & NAV_RC_ALT) && (!FLIGHT_MODE(FAILSAFE_MODE))) {
posControl.flags.isAdjustingAltitude = adjustAltitudeFromRCInput();
}
else {
posControl.flags.isAdjustingAltitude = false;
}

if (navStateFlags & NAV_RC_POS) {
posControl.flags.isAdjustingPosition = adjustPositionFromRCInput() && !FLIGHT_MODE(FAILSAFE_MODE);
if (STATE(MULTIROTOR) && FLIGHT_MODE(FAILSAFE_MODE)) {
if (FLIGHT_MODE(FAILSAFE_MODE)) {
if (STATE(MULTIROTOR) && navStateFlags & NAV_RC_POS) {
resetMulticopterBrakingMode();
}
}
else {
posControl.flags.isAdjustingAltitude = false;
posControl.flags.isAdjustingPosition = false;
}

if ((navStateFlags & NAV_RC_YAW) && (!FLIGHT_MODE(FAILSAFE_MODE))) {
posControl.flags.isAdjustingHeading = adjustHeadingFromRCInput();
}
else {
posControl.flags.isAdjustingHeading = false;

return;
}

posControl.flags.isAdjustingAltitude = (navStateFlags & NAV_RC_ALT) && adjustAltitudeFromRCInput();
posControl.flags.isAdjustingPosition = (navStateFlags & NAV_RC_POS) && adjustPositionFromRCInput();
posControl.flags.isAdjustingHeading = (navStateFlags & NAV_RC_YAW) && adjustHeadingFromRCInput();
}

/*-----------------------------------------------------------
Expand Down Expand Up @@ -3850,17 +3860,16 @@ int8_t navigationGetHeadingControlState(void)
}

// For multirotors it depends on navigation system mode
// Course hold requires Auto Control to update heading hold target whilst RC adjustment active
if (navGetStateFlags(posControl.navState) & NAV_REQUIRE_MAGHOLD) {
if (posControl.flags.isAdjustingHeading) {
if (posControl.flags.isAdjustingHeading && !FLIGHT_MODE(NAV_COURSE_HOLD_MODE)) {
return NAV_HEADING_CONTROL_MANUAL;
}
else {
return NAV_HEADING_CONTROL_AUTO;
}
}
else {
return NAV_HEADING_CONTROL_NONE;

return NAV_HEADING_CONTROL_AUTO;
}

return NAV_HEADING_CONTROL_NONE;
}

bool navigationTerrainFollowingEnabled(void)
Expand Down Expand Up @@ -4398,3 +4407,8 @@ bool isAdjustingHeading(void) {
int32_t getCruiseHeadingAdjustment(void) {
return wrap_18000(posControl.cruise.course - posControl.cruise.previousCourse);
}

int32_t navigationGetHeadingError(void)
{
return wrap_18000(posControl.desiredState.yaw - posControl.actualState.cog);
}
2 changes: 1 addition & 1 deletion src/main/navigation/navigation.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ typedef struct navConfig_s {
uint8_t land_detect_sensitivity; // Sensitivity of landing detector
uint16_t auto_disarm_delay; // safety time delay for landing detector
uint16_t rth_linear_descent_start_distance; // Distance from home to start the linear descent (0 = immediately)
uint8_t cruise_yaw_rate; // Max yaw rate (dps) when CRUISE MODE is enabled
} general;

struct {
Expand Down Expand Up @@ -315,7 +316,6 @@ typedef struct navConfig_s {
uint8_t launch_max_angle; // Max tilt angle (pitch/roll combined) to consider launch successful. Set to 180 to disable completely [deg]
bool launch_manual_throttle; // Allows launch with manual throttle control
uint8_t launch_abort_deadband; // roll/pitch stick movement deadband for launch abort
uint8_t cruise_yaw_rate; // Max yaw rate (dps) when CRUISE MODE is enabled
bool allow_manual_thr_increase;
bool useFwNavYawControl;
uint8_t yawControlDeadband;
Expand Down
Loading

0 comments on commit 0d8e788

Please sign in to comment.