Skip to content

Commit f720093

Browse files
committed
Plane: never allow terrain_alt=1 and relative_alt=0
the Location object does not handle this combination. Throw an internal error and try to cope as best we can
1 parent 7d84a81 commit f720093

File tree

9 files changed

+91
-50
lines changed

9 files changed

+91
-50
lines changed

ArduPlane/GCS_MAVLink_Plane.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -758,12 +758,15 @@ bool GCS_MAVLINK_Plane::handle_guided_request(AP_Mission::Mission_Command &cmd)
758758
*/
759759
void GCS_MAVLINK_Plane::handle_change_alt_request(AP_Mission::Mission_Command &cmd)
760760
{
761-
plane.next_WP_loc.alt = cmd.content.location.alt;
762-
if (cmd.content.location.relative_alt && !cmd.content.location.terrain_alt) {
763-
plane.next_WP_loc.alt += plane.home.alt;
761+
if (cmd.content.location.terrain_alt) {
762+
plane.next_WP_loc.set_alt_cm(cmd.content.location.alt, Location::AltFrame::ABOVE_TERRAIN);
763+
} else {
764+
// convert to absolute alt
765+
float abs_alt_m;
766+
if (cmd.content.location.get_alt_m(Location::AltFrame::ABSOLUTE, abs_alt_m)) {
767+
plane.next_WP_loc.set_alt_m(abs_alt_m, Location::AltFrame::ABSOLUTE);
768+
}
764769
}
765-
plane.next_WP_loc.relative_alt = false;
766-
plane.next_WP_loc.terrain_alt = cmd.content.location.terrain_alt;
767770
plane.reset_offset_altitude();
768771
}
769772

@@ -873,10 +876,9 @@ MAV_RESULT GCS_MAVLINK_Plane::handle_command_int_do_reposition(const mavlink_com
873876
plane.guided_state.target_heading_type = GUIDED_HEADING_NONE;
874877
#endif
875878

876-
// add home alt if needed
877-
if (requested_position.relative_alt && !requested_position.terrain_alt) {
878-
requested_position.alt += plane.home.alt;
879-
requested_position.relative_alt = 0;
879+
// convert to absolute alt
880+
if (!requested_position.terrain_alt) {
881+
requested_position.change_alt_frame(Location::AltFrame::ABSOLUTE);
880882
}
881883

882884
plane.set_guided_WP(requested_position);

ArduPlane/Plane.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -891,9 +891,8 @@ bool Plane::set_target_location(const Location &target_loc)
891891
return false;
892892
}
893893
// add home alt if needed
894-
if (loc.relative_alt && !loc.terrain_alt) {
895-
loc.alt += plane.home.alt;
896-
loc.relative_alt = 0;
894+
if (!loc.terrain_alt) {
895+
loc.change_alt_frame(Location::AltFrame::ABSOLUTE);
897896
}
898897
plane.set_guided_WP(loc);
899898
return true;
@@ -941,6 +940,8 @@ bool Plane::update_target_location(const Location &old_loc, const Location &new_
941940
}
942941
next_WP_loc = new_loc;
943942

943+
fix_terrain_WP(next_WP_loc, __LINE__);
944+
944945
#if HAL_QUADPLANE_ENABLED
945946
if (control_mode == &mode_qland || control_mode == &mode_qloiter) {
946947
mode_qloiter.last_target_loc_set_ms = AP_HAL::millis();

ArduPlane/Plane.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ class Plane : public AP_Vehicle {
903903
void change_target_altitude(int32_t change_cm);
904904
void set_target_altitude_proportion(const Location &loc, float proportion);
905905
#if AP_TERRAIN_AVAILABLE
906-
void set_target_altitude_proportion_terrain(float prev_theight);
906+
bool set_target_altitude_proportion_terrain(void);
907907
#endif
908908
void constrain_target_altitude_location(const Location &loc1, const Location &loc2);
909909
int32_t calc_altitude_error_cm(void);
@@ -917,6 +917,7 @@ class Plane : public AP_Vehicle {
917917
float mission_alt_offset(void);
918918
float height_above_target(void);
919919
float lookahead_adjustment(void);
920+
void fix_terrain_WP(Location &loc, uint32_t linenum);
920921
#if AP_RANGEFINDER_ENABLED
921922
float rangefinder_correction(void);
922923
void rangefinder_height_update(void);

ArduPlane/altitude.cpp

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ void Plane::check_home_alt_change(void)
3434
if (home_alt_cm != auto_state.last_home_alt_cm && hal.util->get_soft_armed()) {
3535
// cope with home altitude changing
3636
const int32_t alt_change_cm = home_alt_cm - auto_state.last_home_alt_cm;
37-
if (next_WP_loc.terrain_alt) {
37+
if (next_WP_loc.terrain_alt && !next_WP_loc.relative_alt) {
3838
/*
3939
next_WP_loc for terrain alt WP are quite strange. They
40-
have terrain_alt=1, but also have relative_alt=0 and
41-
have been calculated to be relative to home. We need to
42-
adjust for the change in home alt
40+
have terrain_alt=1, but could (due to a bug!) also have
41+
relative_alt=0 and have been calculated to be relative
42+
to home. We need to adjust for the change in home alt
4343
*/
4444
next_WP_loc.alt += alt_change_cm;
4545
}
@@ -235,10 +235,6 @@ void Plane::set_target_altitude_location(const Location &loc)
235235
if (loc.terrain_alt && terrain.height_above_terrain(height, true)) {
236236
target_altitude.terrain_following = true;
237237
target_altitude.terrain_alt_cm = loc.alt;
238-
if (!loc.relative_alt) {
239-
// it has home added, remove it
240-
target_altitude.terrain_alt_cm -= home.alt;
241-
}
242238
} else {
243239
target_altitude.terrain_following = false;
244240
}
@@ -322,24 +318,45 @@ void Plane::set_target_altitude_proportion(const Location &loc, float proportion
322318
}
323319
}
324320

321+
#if AP_TERRAIN_AVAILABLE
325322
/*
326-
change target altitude along a path between two terrain altitudes
327-
in prev_WP_loc and next_WP_loc using plane.auto_state.wp_proportion
328-
next_WP_loc must be using terrain_alt
329-
330-
prev_theight must be the height of the terrain in meters at
331-
prev_WP_loc
323+
change target altitude along a path between two locations
324+
(prev_WP_loc and next_WP_loc) where the second location is a terrain
325+
altitude
332326
*/
333-
void Plane::set_target_altitude_proportion_terrain(float prev_theight)
327+
bool Plane::set_target_altitude_proportion_terrain(void)
334328
{
329+
if (!next_WP_loc.terrain_alt ||
330+
!next_WP_loc.relative_alt) {
331+
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
332+
return false;
333+
}
334+
/*
335+
we first need to get the height of the terrain at prev_WP_loc
336+
*/
337+
float prev_WP_height_terrain;
338+
if (!plane.prev_WP_loc.get_alt_m(Location::AltFrame::ABOVE_TERRAIN,
339+
prev_WP_height_terrain)) {
340+
return false;
341+
}
342+
// and next_WP_loc alt as terrain
343+
float next_WP_height_terrain;
344+
if (!plane.next_WP_loc.get_alt_m(Location::AltFrame::ABOVE_TERRAIN,
345+
next_WP_height_terrain)) {
346+
return false;
347+
}
335348
const float p = constrain_float(plane.auto_state.wp_proportion, 0, 1);
336-
float prev_WP_height_abs = prev_WP_loc.alt*0.01;
337-
float prev_WP_height_terrain = prev_WP_height_abs - prev_theight;
338349
Location loc = next_WP_loc;
339-
loc.alt = linear_interpolate(prev_WP_height_terrain*100, next_WP_loc.alt,
340-
p, 0, 1);
350+
const auto alt = linear_interpolate(prev_WP_height_terrain, next_WP_height_terrain,
351+
p, 0, 1);
352+
353+
loc.set_alt_m(alt, Location::AltFrame::ABOVE_TERRAIN);
354+
341355
set_target_altitude_location(loc);
356+
357+
return true;
342358
}
359+
#endif // AP_TERRAIN_AVAILABLE
343360

344361
/*
345362
constrain target altitude to be between two locations. Used to
@@ -927,3 +944,24 @@ float Plane::get_landing_height(bool &rangefinder_active)
927944

928945
return height;
929946
}
947+
948+
/*
949+
if a terrain location doesn't have the relative_alt flag set
950+
then fix the alt and trigger a flow of control error
951+
*/
952+
void Plane::fix_terrain_WP(Location &loc, uint32_t linenum)
953+
{
954+
if (loc.terrain_alt && !loc.relative_alt) {
955+
AP::internalerror().error(AP_InternalError::error_t::flow_of_control, linenum);
956+
/*
957+
we definately have a bug, now we need to guess what was
958+
really meant. The lack of the relative_alt flag notionally
959+
means that home.alt has been added to loc.alt, so remove it,
960+
but only if it doesn't lead to a negative terrain altitude
961+
*/
962+
if (loc.alt - home.alt > -500) {
963+
loc.alt -= home.alt;
964+
}
965+
loc.relative_alt = true;
966+
}
967+
}

ArduPlane/commands.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,15 @@ void Plane::set_next_WP(const Location &loc)
3333
next_WP_loc.lng = current_loc.lng;
3434
// additionally treat zero altitude as current altitude
3535
if (next_WP_loc.alt == 0) {
36-
next_WP_loc.alt = current_loc.alt;
37-
next_WP_loc.relative_alt = false;
38-
next_WP_loc.terrain_alt = false;
36+
next_WP_loc.set_alt_cm(current_loc.alt, Location::AltFrame::ABSOLUTE);
3937
}
4038
}
4139

40+
fix_terrain_WP(next_WP_loc, __LINE__);
41+
4242
// convert relative alt to absolute alt
43-
if (next_WP_loc.relative_alt) {
44-
next_WP_loc.relative_alt = false;
45-
next_WP_loc.alt += home.alt;
43+
if (!next_WP_loc.terrain_alt) {
44+
next_WP_loc.change_alt_frame(Location::AltFrame::ABSOLUTE);
4645
}
4746

4847
// are we already past the waypoint? This happens when we jump
@@ -85,6 +84,8 @@ void Plane::set_guided_WP(const Location &loc)
8584
// ---------------------
8685
next_WP_loc = loc;
8786

87+
fix_terrain_WP(next_WP_loc, __LINE__);
88+
8889
// used to control FBW and limit the rate of climb
8990
// -----------------------------------------------
9091
set_target_altitude_current();

ArduPlane/commands_logic.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ void Plane::do_RTL(int32_t rtl_altitude_AMSL_cm)
340340
auto_state.crosstrack = false;
341341
prev_WP_loc = current_loc;
342342
next_WP_loc = calc_best_rally_or_home_location(current_loc, rtl_altitude_AMSL_cm);
343+
344+
fix_terrain_WP(next_WP_loc, __LINE__);
345+
343346
setup_terrain_target_alt(next_WP_loc);
344347
set_target_altitude_location(next_WP_loc);
345348

ArduPlane/mode.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ bool Mode::is_vtol_man_throttle() const
186186
void Mode::update_target_altitude()
187187
{
188188
Location target_location;
189-
float prev_theight;
190189

191190
if (plane.landing.is_flaring()) {
192191
// during a landing flare, use TECS_LAND_SINK as a target sink
@@ -211,13 +210,9 @@ void Mode::update_target_altitude()
211210
plane.set_target_altitude_location(plane.next_WP_loc);
212211
#if AP_TERRAIN_AVAILABLE
213212
} else if (plane.next_WP_loc.terrain_alt &&
214-
plane.next_WP_loc.relative_alt &&
215-
!plane.prev_WP_loc.relative_alt &&
216-
!plane.prev_WP_loc.terrain_alt &&
217-
plane.terrain.height_amsl(plane.prev_WP_loc, prev_theight)) {
218-
// special case for target as terrain relative, and
219-
// prev_WP_loc absolute
220-
plane.set_target_altitude_proportion_terrain(prev_theight);
213+
plane.set_target_altitude_proportion_terrain()) {
214+
// special case for target as terrain relative handled inside
215+
// set_target_altitude_proportion_terrain
221216
#endif
222217
} else if (plane.target_altitude.offset_cm != 0 &&
223218
!plane.current_loc.past_interval_finish_line(plane.prev_WP_loc, plane.next_WP_loc)) {

ArduPlane/mode_autoland.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ bool ModeAutoLand::_enter()
177177
#if AP_TERRAIN_AVAILABLE
178178
// Update loiter location to be relative terrain if enabled
179179
if (plane.terrain_enabled_in_current_mode()) {
180-
cmd_loiter.content.location.terrain_alt = 1;
180+
cmd_loiter.content.location.set_alt_m(final_wp_alt, Location::AltFrame::ABOVE_TERRAIN);
181181
};
182182
#endif
183183
// land WP at home

ArduPlane/mode_guided.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,10 @@ void ModeGuided::navigate()
108108

109109
bool ModeGuided::handle_guided_request(Location target_loc)
110110
{
111+
plane.fix_terrain_WP(target_loc, __LINE__);
111112
// add home alt if needed
112-
if (target_loc.relative_alt && !target_loc.terrain_alt) {
113-
target_loc.alt += plane.home.alt;
114-
target_loc.relative_alt = 0;
113+
if (!target_loc.terrain_alt) {
114+
target_loc.change_alt_frame(Location::AltFrame::ABSOLUTE);
115115
}
116116

117117
plane.set_guided_WP(target_loc);

0 commit comments

Comments
 (0)