PX4 Firmware
PX4 Autopilot Software http://px4.io
FlightTaskAuto.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  * @file FlightTaskAuto.cpp
35  */
36 
37 #include "FlightTaskAuto.hpp"
38 #include <mathlib/mathlib.h>
39 #include <float.h>
40 
41 using namespace matrix;
42 
43 static constexpr float SIGMA_NORM = 0.001f;
44 
46  _obstacle_avoidance(this)
47 {
48 
49 }
50 
52 {
53  bool ret = FlightTask::activate(last_setpoint);
57  _yawspeed_setpoint = 0.0f;
59  return ret;
60 }
61 
63 {
64  bool ret = FlightTask::updateInitialize();
65 
70 
71  // require valid reference and valid target
72  ret = ret && _evaluateGlobalReference() && _evaluateTriplets();
73  // require valid position
74  ret = ret && PX4_ISFINITE(_position(0))
75  && PX4_ISFINITE(_position(1))
76  && PX4_ISFINITE(_position(2))
77  && PX4_ISFINITE(_velocity(0))
78  && PX4_ISFINITE(_velocity(1))
79  && PX4_ISFINITE(_velocity(2));
80 
81  return ret;
82 }
83 
85 {
86  // All the auto FlightTasks have to comply with defined maximum yaw rate
87  // If the FlightTask generates a yaw or a yawrate setpoint that exceeds this value
88  // it will see its setpoint constrained here
89  _limitYawRate();
91  return true;
92 }
93 
95 {
96  const float yawrate_max = math::radians(_param_mpc_yawrauto_max.get());
97 
98  _yaw_sp_aligned = true;
99 
100  if (PX4_ISFINITE(_yaw_setpoint) && PX4_ISFINITE(_yaw_sp_prev)) {
101  // Limit the rate of change of the yaw setpoint
102  const float dyaw_desired = matrix::wrap_pi(_yaw_setpoint - _yaw_sp_prev);
103  const float dyaw_max = yawrate_max * _deltatime;
104  const float dyaw = math::constrain(dyaw_desired, -dyaw_max, dyaw_max);
105  float yaw_setpoint_sat = _yaw_sp_prev + dyaw;
106  yaw_setpoint_sat = matrix::wrap_pi(yaw_setpoint_sat);
107 
108  // The yaw setpoint is aligned when it is within tolerance
109  _yaw_sp_aligned = fabsf(_yaw_setpoint - yaw_setpoint_sat) < math::radians(_param_mis_yaw_err.get());
110 
111  _yaw_setpoint = yaw_setpoint_sat;
113  }
114 
115  if (PX4_ISFINITE(_yawspeed_setpoint)) {
116  _yawspeed_setpoint = math::constrain(_yawspeed_setpoint, -yawrate_max, yawrate_max);
117 
118  // The yaw setpoint is aligned when its rate is not saturated
119  _yaw_sp_aligned = fabsf(_yawspeed_setpoint) < yawrate_max;
120  }
121 }
122 
124 {
125  // TODO: fix the issues mentioned below
126  // We add here some conditions that are only required because:
127  // 1. navigator continuously sends triplet during mission due to yaw setpoint. This
128  // should be removed in the navigator and only updates if the current setpoint actually has changed.
129  //
130  // 2. navigator should be responsible to send always three valid setpoints. If there is only one setpoint,
131  // then previous will be set to current vehicle position and next will be set equal to setpoint.
132  //
133  // 3. navigator originally only supports gps guided maneuvers. However, it now also supports some flow-specific features
134  // such as land and takeoff. The navigator should use for auto takeoff/land with flow the position in xy at the moment the
135  // takeoff/land was initiated. Until then we do this kind of logic here.
136 
137  // Check if triplet is valid. There must be at least a valid altitude.
138 
140  // Best we can do is to just set all waypoints to current state and return false.
143  return false;
144  }
145 
147 
148  // Always update cruise speed since that can change without waypoint changes.
150 
151  if (!PX4_ISFINITE(_mc_cruise_speed) || (_mc_cruise_speed < 0.0f)) {
152  // If no speed is planned use the default cruise speed as limit
154  }
155 
156  // Ensure planned cruise speed is below the maximum such that the smooth trajectory doesn't get capped
157  _mc_cruise_speed = math::min(_mc_cruise_speed, _param_mpc_xy_vel_max.get());
158 
159  // Temporary target variable where we save the local reprojection of the latest navigator current triplet.
160  Vector3f tmp_target;
161 
162  if (!PX4_ISFINITE(_sub_triplet_setpoint.get().current.lat)
163  || !PX4_ISFINITE(_sub_triplet_setpoint.get().current.lon)) {
164  // No position provided in xy. Lock position
165  if (!PX4_ISFINITE(_lock_position_xy(0))) {
166  tmp_target(0) = _lock_position_xy(0) = _position(0);
167  tmp_target(1) = _lock_position_xy(1) = _position(1);
168 
169  } else {
170  tmp_target(0) = _lock_position_xy(0);
171  tmp_target(1) = _lock_position_xy(1);
172  }
173 
174  } else {
175  // reset locked position if current lon and lat are valid
177 
178  // Convert from global to local frame.
180  _sub_triplet_setpoint.get().current.lat, _sub_triplet_setpoint.get().current.lon, &tmp_target(0), &tmp_target(1));
181  }
182 
184 
185  // Check if anything has changed. We do that by comparing the temporary target
186  // to the internal _triplet_target.
187  // TODO This is a hack and it would be much better if the navigator only sends out a waypoints once they have changed.
188 
189  bool triplet_update = true;
190 
191  if (PX4_ISFINITE(_triplet_target(0))
192  && PX4_ISFINITE(_triplet_target(1))
193  && PX4_ISFINITE(_triplet_target(2))
194  && fabsf(_triplet_target(0) - tmp_target(0)) < 0.001f
195  && fabsf(_triplet_target(1) - tmp_target(1)) < 0.001f
196  && fabsf(_triplet_target(2) - tmp_target(2)) < 0.001f) {
197  // Nothing has changed: just keep old waypoints.
198  triplet_update = false;
199 
200  } else {
201  _triplet_target = tmp_target;
203 
204  if (!PX4_ISFINITE(_triplet_target(0)) || !PX4_ISFINITE(_triplet_target(1))) {
205  // Horizontal target is not finite.
206  _triplet_target(0) = _position(0);
207  _triplet_target(1) = _position(1);
208  }
209 
210  if (!PX4_ISFINITE(_triplet_target(2))) {
211  _triplet_target(2) = _position(2);
212  }
213 
214  // If _triplet_target has updated, update also _triplet_prev_wp and _triplet_next_wp.
216 
221 
222  } else {
224  }
225 
226  if (_type == WaypointType::loiter) {
228 
233 
234  } else {
236  }
237  }
238 
239  if (_ext_yaw_handler != nullptr) {
240  // activation/deactivation of weather vane is based on parameter WV_EN and setting of navigator (allow_weather_vane)
243  }
244 
245  // set heading
246  if (_ext_yaw_handler != nullptr && _ext_yaw_handler->is_active()) {
249 
252  _yaw_setpoint = NAN;
253 
254  } else {
257 
258  } else {
260  }
261 
262  _yawspeed_setpoint = NAN;
263  }
264 
265  // Calculate the current vehicle state and check if it has updated.
266  State previous_state = _current_state;
268 
269  if (triplet_update || (_current_state != previous_state)) {
272  }
273 
274  if (_param_com_obs_avoid.get()
275  && _sub_vehicle_status.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING) {
282  }
283 
284  return true;
285 }
286 
288 {
289 
290  Vector2f v; // Vector that points towards desired location
291 
292  switch (_param_mpc_yaw_mode.get()) {
293 
294  case 0: // Heading points towards the current waypoint.
295  case 4: // Same as 0 but yaw fisrt and then go
297  break;
298 
299  case 1: // Heading points towards home.
302  }
303 
304  break;
305 
306  case 2: // Heading point away from home.
309  }
310 
311  break;
312 
313  case 3: // Along trajectory.
314  // The heading depends on the kind of setpoint generation. This needs to be implemented
315  // in the subclasses where the velocity setpoints are generated.
316  v.setAll(NAN);
317  break;
318  }
319 
320  if (PX4_ISFINITE(v.length())) {
321  // We only adjust yaw if vehicle is outside of acceptance radius. Once we enter acceptance
322  // radius, lock yaw to current yaw.
323  // This prevents excessive yawing.
324  if (v.length() > _target_acceptance_radius) {
326  _yaw_lock = false;
327 
328  } else {
329  if (!_yaw_lock) {
331  _yaw_lock = true;
332  }
333  }
334 
335  } else {
336  _yaw_lock = false;
337  _yaw_setpoint = NAN;
338  }
339 }
340 
342 {
343  return (PX4_ISFINITE(sp.lat) && PX4_ISFINITE(sp.lon) && PX4_ISFINITE(sp.alt));
344 }
345 
347 {
348  // check if reference has changed and update.
349  // Only update if reference timestamp has changed AND no valid reference altitude
350  // is available.
351  // TODO: this needs to be revisited and needs a more clear implementation
353  // don't need to update anything
354  return true;
355  }
356 
357  double ref_lat = _sub_vehicle_local_position.get().ref_lat;
358  double ref_lon = _sub_vehicle_local_position.get().ref_lon;
360 
362  // we have no valid global altitude
363  // set global reference to local reference
364  _reference_altitude = 0.0f;
365  }
366 
368  // we have no valid global alt/lat
369  // set global reference to local reference
370  ref_lat = 0.0;
371  ref_lon = 0.0;
372  }
373 
374  // init projection
375  map_projection_init(&_reference_position, ref_lat, ref_lon);
376 
377  // check if everything is still finite
378  return PX4_ISFINITE(_reference_altitude) && PX4_ISFINITE(ref_lat) && PX4_ISFINITE(ref_lon);
379 }
380 
382 {
384 
385  // only adjust limits if the new limit is lower
386  if (_constraints.speed_xy >= _param_mpc_xy_cruise.get()) {
387  _constraints.speed_xy = _param_mpc_xy_cruise.get();
388  }
389 }
390 
392 {
393  // guard against any bad velocity values
394  const float vx = _sub_triplet_setpoint.get().current.vx;
395  const float vy = _sub_triplet_setpoint.get().current.vy;
396  bool velocity_valid = PX4_ISFINITE(vx) && PX4_ISFINITE(vy) &&
398 
399  if (velocity_valid) {
400  return Vector2f(vx, vy);
401 
402  } else {
403  // just return zero speed
404  return Vector2f{};
405  }
406 }
407 
409 {
410  // Calculate the vehicle current state based on the Navigator triplets and the current position.
411  Vector2f u_prev_to_target = Vector2f(_triplet_target - _triplet_prev_wp).unit_or_zero();
412  Vector2f pos_to_target(_triplet_target - _position);
413  Vector2f prev_to_pos(_position - _triplet_prev_wp);
414  // Calculate the closest point to the vehicle position on the line prev_wp - target
415  _closest_pt = Vector2f(_triplet_prev_wp) + u_prev_to_target * (prev_to_pos * u_prev_to_target);
416 
417  State return_state = State::none;
418 
419  if (u_prev_to_target * pos_to_target < 0.0f) {
420  // Target is behind.
421  return_state = State::target_behind;
422 
423  } else if (u_prev_to_target * prev_to_pos < 0.0f && prev_to_pos.length() > _mc_cruise_speed) {
424  // Current position is more than cruise speed in front of previous setpoint.
425  return_state = State::previous_infront;
426 
427  } else if (Vector2f(Vector2f(_position) - _closest_pt).length() > _mc_cruise_speed) {
428  // Vehicle is more than cruise speed off track.
429  return_state = State::offtrack;
430 
431  }
432 
433  return return_state;
434 }
435 
437 {
438  // The internal Waypoints might differ from _triplet_prev_wp, _triplet_target and _triplet_next_wp.
439  // The cases where it differs:
440  // 1. The vehicle already passed the target -> go straight to target
441  // 2. The vehicle is more than cruise speed in front of previous waypoint -> go straight to previous waypoint
442  // 3. The vehicle is more than cruise speed from track -> go straight to closest point on track
443  switch (_current_state) {
448  break;
449 
454  break;
455 
456  case State::offtrack:
460  break;
461 
462  case State::none:
466  break;
467 
468  default:
469  break;
470 
471  }
472 }
473 
475 {
476  if (PX4_ISFINITE(v.length()) && v.length() > SIGMA_NORM) {
477  v.normalize();
478  // To find yaw: take dot product of x = (1,0) and v
479  // and multiply by the sign given of cross product of x and v.
480  // Dot product: (x(0)*v(0)+(x(1)*v(1)) = v(0)
481  // Cross product: x(0)*v(1) - v(0)*x(1) = v(1)
482  heading = math::sign(v(1)) * wrap_pi(acosf(v(0)));
483  return true;
484  }
485 
486  // heading unknown and therefore do not change heading
487  return false;
488 }
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
Definition: Limits.hpp:66
matrix::Vector3f _velocity
current vehicle velocity
Definition: FlightTask.hpp:208
matrix::Vector3f _next_wp
The next waypoint after target (local frame).
bool is_active()
Definition: WeatherVane.hpp:59
bool _isFinite(const position_setpoint_s &sp)
Checks if all waypoint triplets are finite.
float _yawspeed_setpoint
Definition: FlightTask.hpp:226
float _yaw_setpoint
Definition: FlightTask.hpp:225
virtual bool activate(vehicle_local_position_setpoint_s last_setpoint)
Call once on the event where you switch to the task.
Definition: FlightTask.cpp:12
virtual void _setDefaultConstraints()
Set constraints to default values.
Definition: FlightTask.cpp:163
float _deltatime
passed time in seconds since the task was last updated
Definition: FlightTask.hpp:201
bool activate(vehicle_local_position_setpoint_s last_setpoint) override
Call once on the event where you switch to the task.
Map from global triplet to local quadruple.
uORB::SubscriptionData< position_setpoint_triplet_s > _sub_triplet_setpoint
static constexpr float SIGMA_NORM
struct position_setpoint_s next
bool updateFinalize() override
Call after update() to constrain the generated setpoints in order to comply with the constraints of t...
bool updateInitialize() override
Call before activate() or update() to initialize time and input data.
void checkAvoidanceProgress(const matrix::Vector3f &pos, const matrix::Vector3f &prev_wp, float target_acceptance_radius, const matrix::Vector2f &closest_pt)
Checks the vehicle progress between previous and current position waypoint of the triplet...
void _updateInternalWaypoints()
Depending on state of vehicle, the internal waypoints might differ from target (for instance if offtr...
matrix::Vector2f _closest_pt
closest point to the vehicle position on the line previous - target
void normalize()
Definition: Vector.hpp:87
void activate()
Definition: WeatherVane.hpp:55
matrix::Vector3f _triplet_target
current triplet from navigator which may differ from the intenal one (_target) depending on the vehic...
struct position_setpoint_s previous
bool _evaluateGlobalReference()
Check is global reference is available.
void deactivate()
Definition: WeatherVane.hpp:57
matrix::Vector3f _position_setpoint
Setpoints which the position controller has to execute.
Definition: FlightTask.hpp:220
void _set_heading_from_mode()
Vehicle is in normal tracking mode from triplet previous to triplet target.
WaypointType
This enum has to agree with position_setpoint_s type definition The only reason for not using the str...
struct position_setpoint_s current
Vehilce is behind previous waypoint.
uORB::SubscriptionData< home_position_s > _sub_home_position
bool _evaluateTriplets()
Checks and sets triplets.
matrix::Vector3f _triplet_next_wp
next triplet from navigator which may differ from the intenal one (_next_wp) depending on the vehicle...
matrix::Vector2f _getTargetVelocityXY()
only used for follow-me and only here because of legacy reason.
void _limitYawRate()
Limits the rate of change of the yaw setpoint.
float get_weathervane_yawrate()
Definition: WeatherVane.cpp:54
bool _yaw_lock
if within acceptance radius, lock yaw to current yaw
matrix::Vector3f _target
Target waypoint (local frame).
hrt_abstime _time_stamp_reference
time stamp when last reference update occured.
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
virtual bool updateInitialize()
Call before activate() or update() to initialize time and input data.
Definition: FlightTask.cpp:27
Vector2< float > Vector2f
Definition: Vector2.hpp:69
Type length() const
Definition: Vector.hpp:83
ObstacleAvoidance _obstacle_avoidance
class adjusting setpoints according to external avoidance module&#39;s input
void _setDefaultConstraints() override
Set constraints to default values.
matrix::Vector3f _position
current vehicle position
Definition: FlightTask.hpp:207
matrix::Vector3f _velocity_setpoint
Definition: FlightTask.hpp:221
uORB::SubscriptionData< vehicle_local_position_s > _sub_vehicle_local_position
Definition: FlightTask.hpp:171
bool _compute_heading_from_2D_vector(float &heading, matrix::Vector2f v)
Computes and sets heading a 2D vector.
vehicle_constraints_s _constraints
Vehicle constraints.
Definition: FlightTask.hpp:244
float _reference_altitude
Altitude relative to ground.
WaypointType _type
Type of current target triplet.
matrix::Vector3f _triplet_prev_wp
previous triplet from navigator which may differ from the intenal one (_prev_wp) depending on the veh...
constexpr _Tp min(_Tp a, _Tp b)
Definition: Limits.hpp:54
const T & get() const
Type wrap_pi(Type x)
Wrap value in range [-π, π)
float _target_acceptance_radius
Acceptances radius of the target.
virtual bool _checkTakeoff()
Determine when to trigger a takeoff (ignored in flight)
Definition: FlightTask.cpp:174
matrix::Vector2f _lock_position_xy
if no valid triplet is received, lock positition to current position
int sign(T val)
Definition: Functions.hpp:49
Vector3< float > Vector3f
Definition: Vector3.hpp:136
void updateAvoidanceDesiredWaypoints(const matrix::Vector3f &curr_wp, const float curr_yaw, const float curr_yawspeed, const matrix::Vector3f &next_wp, const float next_yaw, const float next_yawspeed, const bool ext_yaw_active, const int wp_type)
Updates the desired waypoints to send to the obstacle avoidance system.
int map_projection_project(const struct map_projection_reference_s *ref, double lat, double lon, float *x, float *y)
Definition: geo.cpp:132
State _getCurrentState()
Computes the current vehicle state based on the vehicle position and navigator triplets.
Vehicle is more than cruise speed away from track.
matrix::Vector3f _prev_wp
Previous waypoint (local frame).
map_projection_reference_s _reference_position
Structure used to project lat/lon setpoint into local frame.
float _yaw
current vehicle yaw heading
Definition: FlightTask.hpp:209
Vehicle is in front of target.
uORB::SubscriptionData< manual_control_setpoint_s > _sub_manual_control_setpoint
matrix::Vector3f _prev_prev_wp
Pre-previous waypoint (local frame).
float _mc_cruise_speed
Requested cruise speed.
int map_projection_init(struct map_projection_reference_s *ref, double lat_0, double lon_0)
Initializes the map transformation given by the argument and sets the timestamp to now...
Definition: geo.cpp:105
void setAll(Type val)
Definition: Matrix.hpp:426
WeatherVane * _ext_yaw_handler
external weathervane library, used to implement a yaw control law that turns the vehicle nose into th...
uORB::SubscriptionData< vehicle_status_s > _sub_vehicle_status