PX4 Firmware
PX4 Autopilot Software http://px4.io
MulticopterLandDetector.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2013-2016 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file MulticopterLandDetector.cpp
36  *
37  *The MC land-detector goes through 3 states before it will detect landed:
38  *
39  *State 1 (=ground_contact):
40  *ground_contact is detected once the vehicle is not moving along the NED-z direction and has
41  *a thrust value below 0.3 of the thrust_range (thrust_hover - thrust_min). The condition has to be true
42  *for GROUND_CONTACT_TRIGGER_TIME_US in order to detect ground_contact
43  *
44  *State 2 (=maybe_landed):
45  *maybe_landed can only occur if the internal ground_contact hysteresis state is true. maybe_landed criteria requires to have no motion in x and y,
46  *no rotation and a thrust below 0.1 of the thrust_range (thrust_hover - thrust_min). In addition, the mc_pos_control turns off the thrust_sp in
47  *body frame along x and y which helps to detect maybe_landed. The criteria for maybe_landed needs to be true for MAYBE_LAND_DETECTOR_TRIGGER_TIME_US.
48  *
49  *State 3 (=landed)
50  *landed can only be detected if maybe_landed is true for LAND_DETECTOR_TRIGGER_TIME_US. No farther criteria is tested, but the mc_pos_control goes into
51  *idle (thrust_sp = 0) which helps to detect landed. By doing this the thrust-criteria of State 2 will always be met, however the remaining criteria of no rotation and no motion still
52  *have to be valid.
53 
54  *It is to note that if one criteria is not met, then vehicle exits the state directly without blocking.
55  *
56  *If the land-detector does not detect ground_contact, then the vehicle is either flying or falling, where free fall detection heavily relies
57  *on the acceleration. TODO: verify that free fall is reliable
58  *
59  * @author Johan Jansen <jnsn.johan@gmail.com>
60  * @author Morten Lysgaard <morten@lysgaard.no>
61  * @author Julian Oes <julian@oes.ch>
62  */
63 
64 #include <math.h>
65 #include <mathlib/mathlib.h>
66 #include <matrix/math.hpp>
67 
69 
70 
71 namespace land_detector
72 {
73 
75 {
76  _paramHandle.landSpeed = param_find("MPC_LAND_SPEED");
77  _paramHandle.minManThrottle = param_find("MPC_MANTHR_MIN");
78  _paramHandle.minThrottle = param_find("MPC_THR_MIN");
79  _paramHandle.hoverThrottle = param_find("MPC_THR_HOVER");
80 
81  // Use Trigger time when transitioning from in-air (false) to landed (true) / ground contact (true).
85 }
86 
88 {
90 
96 }
97 
99 {
101 
102  _freefall_hysteresis.set_hysteresis_time_from(false, (hrt_abstime)(1e6f * _param_lndmc_ffall_ttri.get()));
103 
104  param_get(_paramHandle.minThrottle, &_params.minThrottle);
105  param_get(_paramHandle.hoverThrottle, &_params.hoverThrottle);
106  param_get(_paramHandle.minManThrottle, &_params.minManThrottle);
107  param_get(_paramHandle.landSpeed, &_params.landSpeed);
108 }
109 
111 {
112  if (_param_lndmc_ffall_thr.get() < 0.1f ||
113  _param_lndmc_ffall_thr.get() > 10.0f) { //if parameter is set to zero or invalid, disable free-fall detection.
114  return false;
115  }
116 
117  if (_vehicle_acceleration.timestamp == 0) {
118  // _sensors is not valid yet, we have to assume we're not falling.
119  return false;
120  }
121 
122  // norm of specific force. Should be close to 9.8 m/s^2 when landed.
124 
125  return (accel.norm() < _param_lndmc_ffall_thr.get()); // true if we are currently falling
126 }
127 
129 {
130  // When not armed, consider to have ground-contact
131  if (!_actuator_armed.armed) {
132  return true;
133  }
134 
135  // land speed threshold
136  float land_speed_threshold = 0.9f * math::max(_params.landSpeed, 0.1f);
137 
138  // Check if we are moving vertically - this might see a spike after arming due to
139  // throttle-up vibration. If accelerating fast the throttle thresholds will still give
140  // an accurate in-air indication.
141  bool vertical_movement = false;
142 
144 
145  // Widen acceptance thresholds for landed state right after arming
146  // so that motor spool-up and other effects do not trigger false negatives.
147  vertical_movement = fabsf(_vehicle_local_position.vz) > _param_lndmc_z_vel_max.get() * 2.5f;
148 
149  } else {
150 
151  // Adjust max_climb_rate if land_speed is lower than 2x max_climb_rate
152  float max_climb_rate = ((land_speed_threshold * 0.5f) < _param_lndmc_z_vel_max.get()) ? (0.5f * land_speed_threshold) :
153  _param_lndmc_z_vel_max.get();
154  vertical_movement = fabsf(_vehicle_local_position.vz) > max_climb_rate;
155  }
156 
157  // Check if we are moving horizontally.
159  + _vehicle_local_position.vy * _vehicle_local_position.vy) > _param_lndmc_xy_vel_max.get();
160 
161  // if we have a valid velocity setpoint and the vehicle is demanded to go down but no vertical movement present,
162  // we then can assume that the vehicle hit ground
164  && (_vehicle_local_position_setpoint.vz >= land_speed_threshold);
165  bool hit_ground = _in_descend && !vertical_movement;
166 
167  // TODO: we need an accelerometer based check for vertical movement for flying without GPS
168  return (_has_low_thrust() || hit_ground) && (!_horizontal_movement || !_has_position_lock())
169  && (!vertical_movement || !_has_altitude_lock());
170 }
171 
173 {
174  // Time base for this function
175  const hrt_abstime now = hrt_absolute_time();
176 
177  // When not armed, consider to be maybe-landed
178  if (!_actuator_armed.armed) {
179  return true;
180  }
181 
182  if (_has_minimal_thrust()) {
183  if (_min_trust_start == 0) {
184  _min_trust_start = now;
185  }
186 
187  } else {
188  _min_trust_start = 0;
189  }
190 
191  float landThresholdFactor = 1.0f;
192 
193  // Widen acceptance thresholds for landed state right after landed
195  landThresholdFactor = 2.5f;
196  }
197 
198  // Next look if all rotation angles are not moving.
199  float max_rotation_scaled = math::radians(_param_lndmc_rot_max.get()) * landThresholdFactor;
200 
201  bool rotating = (fabsf(_vehicle_angular_velocity.xyz[0]) > max_rotation_scaled) ||
202  (fabsf(_vehicle_angular_velocity.xyz[1]) > max_rotation_scaled) ||
203  (fabsf(_vehicle_angular_velocity.xyz[2]) > max_rotation_scaled);
204 
205  // Return status based on armed state and throttle if no position lock is available.
206  if (!_has_altitude_lock() && !rotating) {
207  // The system has minimum trust set (manual or in failsafe)
208  // if this persists for 8 seconds AND the drone is not
209  // falling consider it to be landed. This should even sustain
210  // quite acrobatic flight.
211  return (_min_trust_start > 0) && (hrt_elapsed_time(&_min_trust_start) > 8_s);
212  }
213 
214  // Ground contact, no thrust and no movement -> landed
215  return _ground_contact_hysteresis.get_state() && _has_minimal_thrust() && !rotating;
216 }
217 
219 {
220  // When not armed, consider to be landed
221  if (!_actuator_armed.armed) {
222  return true;
223  }
224 
225  // reset the landed_time
227 
228  _landed_time = 0;
229 
230  } else if (_landed_time == 0) {
231 
233 
234  }
235 
236  // if we have maybe_landed, the mc_pos_control goes into idle (thrust_sp = 0.0)
237  // therefore check if all other condition of the landed state remain true
239 
240 }
241 
243 {
244  /* TODO: add a meaningful altitude */
245  float valid_altitude_max = _param_lndmc_alt_max.get();
246 
247  if (valid_altitude_max < 0.0f) {
248  return INFINITY;
249  }
250 
251  if (_battery_status.warning == battery_status_s::BATTERY_WARNING_LOW) {
252  valid_altitude_max = _param_lndmc_alt_max.get() * 0.75f;
253  }
254 
255  if (_battery_status.warning == battery_status_s::BATTERY_WARNING_CRITICAL) {
256  valid_altitude_max = _param_lndmc_alt_max.get() * 0.5f;
257  }
258 
259  if (_battery_status.warning == battery_status_s::BATTERY_WARNING_EMERGENCY) {
260  valid_altitude_max = _param_lndmc_alt_max.get() * 0.25f;
261  }
262 
263  return valid_altitude_max;
264 }
265 
267 {
268  return _vehicle_local_position.timestamp != 0 &&
271 }
272 
274 {
276 }
277 
279 {
280  bool has_updated = (_vehicle_local_position_setpoint.timestamp != 0)
282 
284  && PX4_ISFINITE(_vehicle_local_position_setpoint.vz));
285 }
286 
288 {
289  // 30% of throttle range between min and hover
290  float sys_min_throttle = _params.minThrottle + (_params.hoverThrottle - _params.minThrottle) *
291  _param_lndmc_low_t_thr.get();
292 
293  // Check if thrust output is less than the minimum auto throttle param.
294  return _actuator_controls.control[actuator_controls_s::INDEX_THROTTLE] <= sys_min_throttle;
295 }
296 
298 {
299  // 10% of throttle range between min and hover once we entered ground contact
300  float sys_min_throttle = _params.minThrottle + (_params.hoverThrottle - _params.minThrottle) * 0.1f;
301 
302  // Determine the system min throttle based on flight mode
304  sys_min_throttle = (_params.minManThrottle + 0.01f);
305  }
306 
307  // Check if thrust output is less than the minimum auto throttle param.
308  return _actuator_controls.control[actuator_controls_s::INDEX_THROTTLE] <= sys_min_throttle;
309 }
310 
312 {
314 }
315 
316 } // namespace land_detector
struct land_detector::MulticopterLandDetector::@99 _params
virtual void _update_topics()
Updates subscribed uORB topics.
vehicle_local_position_s _vehicle_local_position
Definition: LandDetector.h:160
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
Definition: parameters.cpp:589
struct land_detector::MulticopterLandDetector::@98 _paramHandle
Handles for interesting parameters.
actuator_armed_s _actuator_armed
Definition: LandDetector.h:148
static constexpr hrt_abstime LAND_DETECTOR_TRIGGER_TIME_US
Time in us that landing conditions have to hold before triggering a land.
hrt_abstime _min_trust_start
timestamp when minimum trust was applied first
systemlib::Hysteresis _maybe_landed_hysteresis
Definition: LandDetector.h:144
void _update_params() override
Updates parameters.
systemlib::Hysteresis _ground_contact_hysteresis
Definition: LandDetector.h:145
Land detection implementation for multicopters.
vehicle_acceleration_s _vehicle_acceleration
Definition: LandDetector.h:149
static constexpr hrt_abstime LAND_DETECTOR_LAND_PHASE_TIME_US
Time interval in us in which wider acceptance thresholds are used after landed.
static constexpr hrt_abstime GROUND_CONTACT_TRIGGER_TIME_US
Time in us that ground contact condition have to hold before triggering contact ground.
void _update_topics() override
Updates subscribed uORB topics.
bool get_state() const
Definition: hysteresis.h:60
vehicle_angular_velocity_s _vehicle_angular_velocity
bool _horizontal_movement
vehicle is moving horizontally
constexpr T radians(T degrees)
Definition: Limits.hpp:85
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
static hrt_abstime hrt_elapsed_time(const hrt_abstime *then)
Compute the delta between a timestamp taken in the past and now.
Definition: drv_hrt.h:102
vehicle_local_position_setpoint_s _vehicle_local_position_setpoint
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
static constexpr hrt_abstime MAYBE_LAND_DETECTOR_TRIGGER_TIME_US
Time in us that almost landing conditions have to hold before triggering almost landed ...
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
void set_hysteresis_time_from(const bool from_state, const hrt_abstime new_hysteresis_time_us)
Definition: hysteresis.cpp:46
virtual void _update_params()
Updates parameters.
constexpr _Tp max(_Tp a, _Tp b)
Definition: Limits.hpp:60
systemlib::Hysteresis _freefall_hysteresis
Definition: LandDetector.h:142
bool update(void *dst)
Update the struct.
systemlib::Hysteresis _landed_hysteresis
Definition: LandDetector.h:143
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).