Skip to content

Commit 5966f6b

Browse files
Maarrkzyromskij
andcommitted
ArduPlane: enable soaring in LOITER and GUIDED modes. Maintain altitude on exit.
Co-authored-by: Julian <53869112+zyromskij@users.noreply.github.com> Reviewed-by: Peter Barker <pbarker@barker.dropbear.id.au>
1 parent 7db137f commit 5966f6b

6 files changed

Lines changed: 75 additions & 18 deletions

File tree

ArduPlane/Plane.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,11 @@ class Plane : public AP_Vehicle {
11981198
// soaring.cpp
11991199
#if HAL_SOARING_ENABLED
12001200
void update_soaring();
1201+
1202+
// Handles the altitude target, returns true *once* after soaring is deactivated,
1203+
// the calling mode can use that to return to its normal operation after thermaling
1204+
bool set_soaring_altitude();
1205+
bool soaring_was_active = false;
12011206
#endif
12021207

12031208
// RC_Channel.cpp

ArduPlane/mode.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,16 @@ class Mode
119119
// true if mode can have terrain following disabled by switch
120120
virtual bool allows_terrain_disable() const { return false; }
121121

122-
// true if automatic switch to thermal mode is supported.
123-
virtual bool does_automatic_thermal_switch() const {return false; }
124-
125122
// subclasses override this if they require navigation.
126123
virtual void navigate() { return; }
127124

128125
// this allows certain flight modes to mix RC input with throttle
129126
// depending on airspeed_nudge_cm
130127
virtual bool allows_throttle_nudging() const { return false; }
131128

129+
// true if automatic switch to thermal mode is supported.
130+
virtual bool does_automatic_thermal_switch() const { return false; }
131+
132132
// true if the mode sets the vehicle destination, which controls
133133
// whether control input is ignored with STICK_MIXING=0
134134
virtual bool does_auto_navigation() const { return false; }
@@ -261,15 +261,15 @@ class ModeAuto : public Mode
261261
const char *name() const override { return "Auto"; }
262262
const char *name4() const override { return "AUTO"; }
263263

264-
bool does_automatic_thermal_switch() const override { return true; }
265-
266264
// methods that affect movement of the vehicle in this mode
267265
void update() override;
268266

269267
void navigate() override;
270268

271269
bool allows_throttle_nudging() const override { return true; }
272270

271+
bool does_automatic_thermal_switch() const override { return true; }
272+
273273
bool does_auto_navigation() const override;
274274

275275
bool does_auto_throttle() const override;
@@ -368,6 +368,8 @@ class ModeGuided : public Mode
368368

369369
bool allows_throttle_nudging() const override { return true; }
370370

371+
bool does_automatic_thermal_switch() const override { return true; }
372+
371373
bool does_auto_navigation() const override { return true; }
372374

373375
bool does_auto_throttle() const override { return true; }
@@ -445,6 +447,8 @@ class ModeLoiter : public Mode
445447

446448
bool allows_throttle_nudging() const override { return true; }
447449

450+
bool does_automatic_thermal_switch() const override { return true; }
451+
448452
bool does_auto_navigation() const override { return true; }
449453

450454
bool does_auto_throttle() const override { return true; }
@@ -646,11 +650,11 @@ class ModeFBWB : public Mode
646650

647651
bool allows_terrain_disable() const override { return true; }
648652

649-
bool does_automatic_thermal_switch() const override { return true; }
650-
651653
// methods that affect movement of the vehicle in this mode
652654
void update() override;
653655

656+
bool does_automatic_thermal_switch() const override { return true; }
657+
654658
bool does_auto_throttle() const override { return true; }
655659

656660
bool mode_allows_autotuning() const override { return true; }
@@ -672,15 +676,15 @@ class ModeCruise : public Mode
672676

673677
bool allows_terrain_disable() const override { return true; }
674678

675-
bool does_automatic_thermal_switch() const override { return true; }
676-
677679
// methods that affect movement of the vehicle in this mode
678680
void update() override;
679681

680682
void navigate() override;
681683

682684
bool get_target_heading_cd(int32_t &target_heading) const;
683685

686+
bool does_automatic_thermal_switch() const override { return true; }
687+
684688
bool does_auto_throttle() const override { return true; }
685689

686690
void update_target_altitude() override {};

ArduPlane/mode_guided.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
bool ModeGuided::_enter()
55
{
6+
#if HAL_SOARING_ENABLED
7+
plane.g2.soaring_controller.init_cruising();
8+
#endif // HAL_SOARING_ENABLED
9+
610
plane.guided_throttle_passthru = false;
711
/*
812
when entering guided mode we set the target as the current
@@ -94,6 +98,17 @@ void ModeGuided::update()
9498
SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, plane.guided_state.forced_throttle);
9599

96100
} else {
101+
#if HAL_SOARING_ENABLED
102+
if (plane.set_soaring_altitude()) {
103+
// Just stopped soaring in this mode
104+
105+
// Return to guided target point at current altitude
106+
Location loc = plane.next_WP_loc;
107+
loc.copy_alt_from(plane.current_loc);
108+
plane.set_guided_WP(loc);
109+
}
110+
#endif // HAL_SOARING_ENABLED
111+
97112
// TECS control
98113
plane.calc_throttle();
99114

@@ -197,6 +212,9 @@ void ModeGuided::update_target_altitude()
197212
} else
198213
#endif // AP_PLANE_OFFBOARD_GUIDED_SLEW_ENABLED
199214
{
215+
#if HAL_SOARING_ENABLED
216+
plane.set_soaring_altitude();
217+
#endif // HAL_SOARING_ENABLED
200218
Mode::update_target_altitude();
201219
}
202220
}

ArduPlane/mode_loiter.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
bool ModeLoiter::_enter()
55
{
6+
#if HAL_SOARING_ENABLED
7+
plane.g2.soaring_controller.init_cruising();
8+
#endif // HAL_SOARING_ENABLED
9+
610
plane.do_loiter_at_location();
711
plane.setup_terrain_target_alt(plane.next_WP_loc);
812

@@ -25,6 +29,15 @@ void ModeLoiter::update()
2529
plane.update_fbwb_speed_height();
2630
} else {
2731
plane.calc_nav_pitch();
32+
#if HAL_SOARING_ENABLED
33+
if (plane.set_soaring_altitude()) {
34+
// Just stopped soaring in this mode
35+
36+
// Return to loitering at target point with current altitude
37+
plane.set_target_altitude_current();
38+
plane.next_WP_loc.set_alt_cm(plane.target_altitude.amsl_cm, Location::AltFrame::ABSOLUTE);
39+
}
40+
#endif // HAL_SOARING_ENABLED
2841
plane.calc_throttle();
2942
}
3043

ArduPlane/navigation.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -430,15 +430,11 @@ void Plane::update_fbwb_speed_height(void)
430430
change_target_altitude(alt_change_cm);
431431

432432
#if HAL_SOARING_ENABLED
433-
if (g2.soaring_controller.is_active()) {
434-
if (g2.soaring_controller.get_throttle_suppressed()) {
435-
// we're in soaring mode with throttle suppressed
436-
set_target_altitude_current();
437-
} else {
438-
// we're in soaring mode climbing back to altitude. Set target to SOAR_ALT_CUTOFF plus 10m to ensure we positively climb
439-
// through SOAR_ALT_CUTOFF, thus triggering throttle suppression and return to glide.
440-
target_altitude.amsl_cm = 100*plane.g2.soaring_controller.get_alt_cutoff() + 1000 + AP::ahrs().get_home().alt;
441-
}
433+
if (plane.set_soaring_altitude()) {
434+
// Just stopped soaring in this mode
435+
436+
// Continue flying with current altitude
437+
plane.set_target_altitude_current();
442438
}
443439
#endif
444440

ArduPlane/soaring.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,25 @@ void Plane::update_soaring() {
5858
g2.soaring_controller.set_throttle_suppressed(false);
5959
}
6060

61+
bool Plane::set_soaring_altitude()
62+
{
63+
if (!g2.soaring_controller.is_active()) {
64+
// Notify the calling mode that we're exiting soaring and it needs to reset altitude
65+
bool previous = soaring_was_active;
66+
soaring_was_active = false;
67+
return previous;
68+
}
69+
70+
if (g2.soaring_controller.get_throttle_suppressed()) {
71+
// we're in soaring mode with throttle suppressed
72+
set_target_altitude_current();
73+
} else {
74+
// we're in soaring mode climbing back to altitude. Set target to SOAR_ALT_CUTOFF plus 10m to ensure we positively climb
75+
// through SOAR_ALT_CUTOFF, thus triggering throttle suppression and return to glide.
76+
target_altitude.amsl_cm = 100 * (plane.g2.soaring_controller.get_alt_cutoff() + 10) + AP::ahrs().get_home().alt;
77+
}
78+
soaring_was_active = true;
79+
return false;
80+
}
81+
6182
#endif // SOARING_ENABLED

0 commit comments

Comments
 (0)