PX4 Firmware
PX4 Autopilot Software http://px4.io
FlightTaskAutoLine.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2018 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 FlightAutoLine.cpp
36  */
37 
38 #include "FlightTaskAutoLine.hpp"
39 #include <mathlib/mathlib.h>
40 
41 using namespace matrix;
42 
43 static constexpr float SIGMA_NORM = 0.001f;
44 
46 {
47  if (!PX4_ISFINITE(_yaw_setpoint)) {
48  // no valid heading -> set heading along track
49  _generateHeadingAlongTrack();
50  }
51 
52  if (_param_mpc_yaw_mode.get() == 4 && !_yaw_sp_aligned) {
53  // Wait for the yaw setpoint to be aligned
54  if (!_position_locked) {
55  _velocity_setpoint.setAll(0.f);
56  _position_setpoint = _position;
57  _position_locked = true;
58  }
59 
60  } else {
61  _position_locked = false;
62  _generateAltitudeSetpoints();
63  _generateXYsetpoints();
64  }
65 }
66 
68 {
69  // angle goes from 0 to 2 with 0 = large angle, 2 = small angle: 0 = PI ; 2 = PI*0
70  float angle = 2.0f; // minimum angle
71  _speed_at_target = 0.0f;
72 
73  if (Vector2f(&(_target - _next_wp)(0)).length() > 0.001f &&
74  (Vector2f(&(_target - _prev_wp)(0)).length() > _target_acceptance_radius)) {
75  // angle = cosf(x) + 1.0f
76  angle =
77  Vector2f(&(_target - _prev_wp)(0)).unit_or_zero()
78  * Vector2f(&(_target - _next_wp)(0)).unit_or_zero()
79  + 1.0f;
80  _speed_at_target = math::expontialFromLimits(angle, 0.0f, _param_mpc_cruise_90.get(), _mc_cruise_speed);
81  }
82 }
83 
84 
86 {
87  Vector2f prev_to_dest(_target - _prev_wp);
88  _compute_heading_from_2D_vector(_yaw_setpoint, prev_to_dest);
89 
90 }
91 
93 {
94  _setSpeedAtTarget();
95  Vector2f pos_sp_to_dest(_target - _position_setpoint);
96  const bool has_reached_altitude = fabsf(_target(2) - _position(2)) < _param_nav_mc_alt_rad.get();
97 
98  if ((_speed_at_target < 0.001f && pos_sp_to_dest.length() < _target_acceptance_radius) ||
99  (!has_reached_altitude && pos_sp_to_dest.length() < _target_acceptance_radius)) {
100 
101  // Vehicle reached target in xy and no passing required. Lock position
102  _position_setpoint(0) = _target(0);
103  _position_setpoint(1) = _target(1);
104  _velocity_setpoint(0) = _velocity_setpoint(1) = 0.0f;
105 
106  } else {
107  // Vehicle needs to pass waypoint
108  // Ensure that vehicle never gets stuck because of too low target-speed
109  _speed_at_target = math::max(_speed_at_target, 0.5f);
110 
111  // Get various path specific vectors. */
112  Vector2f u_prev_to_dest = Vector2f(_target - _prev_wp).unit_or_zero();
113  Vector2f prev_to_pos(_position - _prev_wp);
114  Vector2f closest_pt = Vector2f(_prev_wp) + u_prev_to_dest * (prev_to_pos * u_prev_to_dest);
115  Vector2f closest_to_dest(_target - _position);
116  Vector2f prev_to_dest(_target - _prev_wp);
117  float speed_sp_track = _mc_cruise_speed;
118  float speed_sp_prev_track = math::max(Vector2f(_velocity_setpoint) * u_prev_to_dest, 0.0f);
119 
120  // Distance to target when brake should occur. The assumption is made that
121  // 1.5 * cruising speed is enough to break.
122  float target_threshold = 1.5f * _mc_cruise_speed;
123  float speed_threshold = _mc_cruise_speed;
124  const float threshold_max = target_threshold;
125 
126  if (target_threshold > 0.5f * prev_to_dest.length()) {
127  // Target threshold cannot be more than distance from previous to target
128  target_threshold = 0.5f * prev_to_dest.length();
129  }
130 
131  // Compute maximum speed at target threshold */
132  if (threshold_max > _target_acceptance_radius) {
133  float m = (_mc_cruise_speed - _speed_at_target) / (threshold_max - _target_acceptance_radius);
134  speed_threshold = m * (target_threshold - _target_acceptance_radius) + _speed_at_target; // speed at transition
135  }
136 
137  // Either accelerate or decelerate
138  if (closest_to_dest.length() < target_threshold) {
139 
140  // Vehicle is close to destination. Start to decelerate
141 
142  if (!has_reached_altitude) {
143  // Altitude is not reached yet. Vehicle has to stop first before proceeding
144  _speed_at_target = 0.0f;
145  }
146 
147  float acceptance_radius = _target_acceptance_radius;
148 
149  if (_speed_at_target < 0.01f) {
150  // If vehicle wants to stop at the target, then set acceptance radius to zero as well.
151  acceptance_radius = 0.0f;
152  }
153 
154  if ((target_threshold - acceptance_radius) >= SIGMA_NORM) {
155 
156  // Slow down depending on distance to target minus acceptance radius.
157  float m = (speed_threshold - _speed_at_target) / (target_threshold - acceptance_radius);
158  speed_sp_track = m * (closest_to_dest.length() - acceptance_radius) + _speed_at_target; // speed at transition
159 
160  } else {
161  speed_sp_track = _speed_at_target;
162  }
163 
164  // If we are close to target and the previous speed setpoint along track was smaller than
165  // current speed setpoint along track, then take over the previous one.
166  // This ensures smoothness since we anyway want to slow down.
167  if ((speed_sp_prev_track < speed_sp_track)
168  && (speed_sp_track * speed_sp_prev_track > 0.0f)
169  && (speed_sp_prev_track > _speed_at_target)) {
170  speed_sp_track = speed_sp_prev_track;
171  }
172 
173  } else {
174 
175  // Vehicle is still far from destination. Accelerate or keep maximum target speed.
176  float acc_track = (speed_sp_track - speed_sp_prev_track) / _deltatime;
177 
178  // If yaw offset is large, only accelerate with 0.5 m/s^2.
179  float acc_max = (_yaw_sp_aligned) ? _param_mpc_acc_hor.get() : 0.5f;
180 
181  if (acc_track > acc_max) {
182  // accelerate towards target
183  speed_sp_track = acc_max * _deltatime + speed_sp_prev_track;
184  }
185 
186  // ensure that desired speed does not exceed speed at threshold
187  speed_sp_track = math::min(speed_threshold, speed_sp_track);
188  }
189 
190  speed_sp_track = math::constrain(speed_sp_track, 0.0f, _mc_cruise_speed);
191 
192  _position_setpoint(0) = closest_pt(0);
193  _position_setpoint(1) = closest_pt(1);
194  Vector2f velocity_sp_xy = u_prev_to_dest * speed_sp_track;
195  _velocity_setpoint(0) = velocity_sp_xy(0);
196  _velocity_setpoint(1) = velocity_sp_xy(1);
197  }
198 }
199 
201 {
202  // Total distance between previous and target set-point.
203  const float dist = fabsf(_target(2) - _prev_wp(2));
204 
205  // If target has not been reached, then compute set-point depending on maximum velocity.
206  if ((dist > SIGMA_NORM) && (fabsf(_position(2) - _target(2)) > 0.1f)) {
207 
208  // get various distances */
209  const float dist_to_prev = fabsf(_position(2) - _prev_wp(2));
210  const float dist_to_target = fabsf(_target(2) - _position(2));
211 
212  // check sign
213  const bool flying_upward = _target(2) < _position(2);
214 
215  // limit vertical downwards speed (positive z) close to ground
216  // for now we use the altitude above home and assume that we want to land at same height as we took off
217  float vel_limit = math::gradual(_alt_above_ground,
218  _param_mpc_land_alt2.get(), _param_mpc_land_alt1.get(),
219  _param_mpc_land_speed.get(), _constraints.speed_down);
220 
221  // Speed at threshold is by default maximum speed. Threshold defines
222  // the point in z at which vehicle slows down to reach target altitude.
223  float speed_sp = (flying_upward) ? _constraints.speed_up : vel_limit;
224 
225  // Target threshold defines the distance to target(2) at which
226  // the vehicle starts to slow down to approach the target smoothly.
227  float target_threshold = speed_sp * 1.5f;
228 
229  // If the total distance in z is NOT 2x distance of target_threshold, we
230  // will need to adjust the final_velocity in z.
231  const bool is_2_target_threshold = dist >= 2.0f * target_threshold;
232  const float min_vel = 0.2f; // minimum velocity: this is needed since estimation is not perfect
233  const float slope = (speed_sp - min_vel) / (target_threshold); // defines the the acceleration when slowing down */
234 
235  if (!is_2_target_threshold) {
236  // Adjust final_velocity since we are already are close to target and therefore it is not necessary to accelerate
237  // upwards with full speed.
238  target_threshold = dist * 0.5f;
239  // get the velocity at target_threshold
240  speed_sp = slope * (target_threshold) + min_vel;
241  }
242 
243  // we want to slow down
244  if (dist_to_target < target_threshold) {
245 
246  speed_sp = slope * dist_to_target + min_vel;
247 
248  } else if (dist_to_prev < target_threshold) {
249  // we want to accelerate
250 
251  const float acc = (speed_sp - fabsf(_velocity_setpoint(2))) / _deltatime;
252  const float acc_max = (flying_upward) ? (_param_mpc_acc_up_max.get() * 0.5f) : (_param_mpc_acc_down_max.get() * 0.5f);
253 
254  if (acc > acc_max) {
255  speed_sp = acc_max * _deltatime + fabsf(_velocity_setpoint(2));
256  }
257  }
258 
259  // make sure vel_sp_z is always positive
260  if (speed_sp < 0.0f) {
261  PX4_WARN("speed cannot be smaller than 0");
262  speed_sp = 0.0f;
263  }
264 
265  // get the sign of vel_sp_z
266  _velocity_setpoint(2) = (flying_upward) ? -speed_sp : speed_sp;
267  _position_setpoint(2) = NAN; // We don't care about position setpoint
268 
269  } else {
270 
271  // vehicle reached desired target altitude
272  _velocity_setpoint(2) = 0.0f;
273  _position_setpoint(2) = _target(2);
274  }
275 }
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
Definition: Limits.hpp:66
Flight task for autonomous, gps driven mode.
static constexpr float SIGMA_NORM
void _setSpeedAtTarget()
Sets desiered speed at target.
void _generateAltitudeSetpoints()
Generate velocity and position setpoints for following line along z.
void _generateSetpoints() override
Generate setpoints along line.
void _generateXYsetpoints()
Generate velocity and position setpoints for following line along xy.
const T gradual(const T &value, const T &x_low, const T &x_high, const T &y_low, const T &y_high)
Definition: Functions.hpp:139
void _generateHeadingAlongTrack()
Generates heading along track.
const T expontialFromLimits(const T &X_in, const T &Y_min, const T &Y_mid, const T &Y_max)
Definition: Functions.hpp:176
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
Vector2< float > Vector2f
Definition: Vector2.hpp:69
Type length() const
Definition: Vector.hpp:83
constexpr _Tp min(_Tp a, _Tp b)
Definition: Limits.hpp:54
constexpr _Tp max(_Tp a, _Tp b)
Definition: Limits.hpp:60