APM:Libraries
AP_SmartRTL.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <AP_Buffer/AP_Buffer.h>
4 #include <AP_HAL/AP_HAL.h>
5 #include <AP_Common/Bitmask.h>
6 #include <AP_Math/AP_Math.h>
7 #include <AP_AHRS/AP_AHRS.h>
8 #include <DataFlash/DataFlash.h>
9 #include <GCS_MAVLink/GCS.h>
10 
11 // definitions and macros
12 #define SMARTRTL_ACCURACY_DEFAULT 2.0f // default _ACCURACY parameter value. Points will be no closer than this distance (in meters) together.
13 #define SMARTRTL_POINTS_DEFAULT 150 // default _POINTS parameter value. High numbers improve path pruning but use more memory and CPU for cleanup. Memory used will be 20bytes * this number.
14 #define SMARTRTL_POINTS_MAX 500 // the absolute maximum number of points this library can support.
15 #define SMARTRTL_TIMEOUT 15000 // the time in milliseconds with no points saved to the path (for whatever reason), before SmartRTL is disabled for the flight
16 #define SMARTRTL_CLEANUP_POINT_TRIGGER 50 // simplification will trigger when this many points are added to the path
17 #define SMARTRTL_CLEANUP_START_MARGIN 10 // routine cleanup algorithms begin when the path array has only this many empty slots remaining
18 #define SMARTRTL_CLEANUP_POINT_MIN 10 // cleanup algorithms will remove points if they remove at least this many points
19 #define SMARTRTL_SIMPLIFY_EPSILON (_accuracy * 0.5f)
20 #define SMARTRTL_SIMPLIFY_STACK_LEN_MULT (2.0f/3.0f)+1 // simplify buffer size as compared to maximum number of points.
21  // The minimum is int((s/2-1)+min(s/2, SMARTRTL_POINTS_MAX-s)), where s = pow(2, floor(log(SMARTRTL_POINTS_MAX)/log(2)))
22  // To avoid this annoying math, a good-enough overestimate is ceil(SMARTRTL_POINTS_MAX*2.0f/3.0f)
23 #define SMARTRTL_SIMPLIFY_TIME_US 200 // maximum time (in microseconds) the simplification algorithm will run before returning
24 #define SMARTRTL_PRUNING_DELTA (_accuracy * 0.99) // How many meters apart must two points be, such that we can assume that there is no obstacle between them. must be smaller than _ACCURACY parameter
25 #define SMARTRTL_PRUNING_LOOP_BUFFER_LEN_MULT 0.25f // pruning loop buffer size as compared to maximum number of points
26 #define SMARTRTL_PRUNING_LOOP_TIME_US 200 // maximum time (in microseconds) that the loop finding algorithm will run before returning
27 
28 class AP_SmartRTL {
29 
30 public:
31 
32  // constructor, destructor
33  AP_SmartRTL(bool example_mode = false);
34 
35  // initialise safe rtl including setting up background processes
36  void init();
37 
38  // return true if smart_rtl is usable (it may become unusable if the user took off without GPS lock or the path became too long)
39  bool is_active() const { return _active; }
40 
41  // returns number of points on the path
42  uint16_t get_num_points() const;
43 
44  // get a point on the path
45  const Vector3f& get_point(uint16_t index) const { return _path[index]; }
46 
47  // get next point on the path to home, returns true on success
48  bool pop_point(Vector3f& point);
49 
50  // clear return path and set return location if position_ok is true. This should be called as part of the arming procedure
51  // if position_ok is false, SmartRTL will not be available.
52  // example sketches use the method that allows providing vehicle position directly
53  void set_home(bool position_ok);
54  void set_home(bool position_ok, const Vector3f& current_pos);
55 
56  // call this at 3hz (or higher) regardless of what mode the vehicle is in
57  // example sketches use method that allows providing vehicle position directly
58  void update(bool position_ok, bool save_position);
59  void update(bool position_ok, const Vector3f& current_pos);
60 
61  // enum for argument passed to request_through_cleanup
63  THOROUGH_CLEAN_DEFAULT = 0, // perform simplify and prune (used by vehicle code)
64  THOROUGH_CLEAN_ALL, // same as above but used by example sketch
65  THOROUGH_CLEAN_SIMPLIFY_ONLY, // perform simplify only (used by example sketch)
66  THOROUGH_CLEAN_PRUNE_ONLY, // perform prune only (used by example sketch)
67  };
68 
69  // triggers thorough cleanup including simplification, pruning and removal of all unnecessary points
70  // returns true if the thorough cleanup was completed, false if it has not yet completed
71  // this method should be called repeatedly until it returns true before initiating the return journey
72  // clean_type should only be set by the example sketch
74 
75  // cancel request for thorough cleanup
77 
78  // run background cleanup - should be run regularly from the IO thread
80 
81  // parameter var table
82  static const struct AP_Param::GroupInfo var_info[];
83 
84 private:
85 
86  // enums for logging latest actions
87  enum SRTL_Actions {
99  };
100 
101  // add point to end of path
102  bool add_point(const Vector3f& point);
103 
104  // routine cleanup attempts to remove 10 points (see SMARTRTL_CLEANUP_POINT_MIN definition) by simplification or loop pruning
105  void routine_cleanup(uint16_t path_points_count, uint16_t path_points_complete_limit);
106 
107  // thorough cleanup simplifies and prunes all loops. returns true if the cleanup was completed.
108  // path_points_count is _path_points_count but passed in to avoid having to take the semaphore
109  bool thorough_cleanup(uint16_t path_points_count, ThoroughCleanupType clean_type);
110 
111  // the two cleanup steps run from the background thread
112  // these are public so that they can be tested by the example sketch
113  void detect_simplifications();
114  void detect_loops();
115 
116  // restart simplify or pruning if new points have been added to path
117  // path_points_count is _path_points_count but passed in to avoid having to take the semaphore
119 
120  // restart pruning if new points have been simplified
122 
123  // restart simplify algorithm so that detect_simplify will check all new points that have been added
124  // to the path since it last completed.
125  // path_points_count is _path_points_count but passed in to avoid having to take the semaphore
127 
128  // reset simplify algorithm so that it will re-check all points in the path
129  void reset_simplification();
130 
131  // restart pruning algorithm so that detect_loops will check all new points that have been added
132  // to the path since it last completed.
133  // path_points_count is _path_points_count but passed in to avoid having to take the semaphore
134  void restart_pruning(uint16_t path_points_count);
135 
136  // reset pruning algorithm so that it will re-check all points in the path
137  void reset_pruning();
138 
139  // remove all simplify-able points from the path
141 
142  // remove loops until at least num_point_to_remove have been removed from path
143  // does not necessarily prune all loops
144  // returns false if it failed to remove points (because it could not take semaphore)
145  bool remove_points_by_loops(uint16_t num_points_to_remove);
146 
147  // add loop to loops array
148  // returns true if loop added successfully, false on failure (because loop array is full)
149  // checks if loop overlaps with an existing loop, keeps only the longer loop
150  // example: segment_a(point2~point3) overlaps with segment_b (point5~point6), add_loop(3,5,midpoint)
151  bool add_loop(uint16_t start_index, uint16_t end_index, const Vector3f& midpoint);
152 
153  // dist_point holds the closest distance reached between 2 line segments, and the point exactly between them
154  typedef struct {
155  float distance;
157  } dist_point;
158 
159  // get the closest distance between 2 line segments and the point midway between the closest points
160  static dist_point segment_segment_dist(const Vector3f& p1, const Vector3f& p2, const Vector3f& p3, const Vector3f& p4);
161 
162  // de-activate SmartRTL, send warning to GCS and log to dataflash
163  void deactivate(SRTL_Actions action, const char *reason);
164 
165  // logging
166  void log_action(SRTL_Actions action, const Vector3f &point = Vector3f());
167 
168  // parameters
169  AP_Float _accuracy;
170  AP_Int16 _points_max;
171 
172  // SmartRTL State Variables
173  bool _active; // true if SmartRTL is usable. may become unusable if the path becomes too long to keep in memory, and too convoluted to be cleaned up, SmartRTL will be permanently deactivated (for the remainder of the flight)
174  bool _example_mode; // true when being called from the example sketch, logging and background tasks are disabled
175  bool _home_saved; // true once home has been saved successfully by the set_home or update methods
176  uint32_t _last_good_position_ms; // the last system time a last good position was reported. If no position is available for a while, SmartRTL will be disabled.
177  uint32_t _last_position_save_ms; // the system time a position was saved to the path (used for timeout)
178  uint32_t _thorough_clean_request_ms;// the last system time the thorough cleanup was requested (set by thorough_cleanup method, used by background cleanup)
179  uint32_t _thorough_clean_complete_ms; // set to _thorough_clean_request_ms when the background thread completes the thorough cleanup
180  ThoroughCleanupType _thorough_clean_type; // used by example sketch to test simplify and prune separately
181 
182  // path variables
183  Vector3f* _path; // points are stored in meters from EKF origin in NED
184  uint16_t _path_points_max; // after the array has been allocated, we will need to know how big it is. We can't use the parameter, because a user could change the parameter in-flight
185  uint16_t _path_points_count;// number of points in the path array
186  uint16_t _path_points_completed_limit; // set by main thread to the path_point_count when a point is popped. used by simplify and prune algorithms to detect path shrinking
187  AP_HAL::Semaphore *_path_sem; // semaphore for updating path
188 
189  // Simplify
190  // structure and buffer to hold the "to-do list" for the simplify algorithm.
191  typedef struct {
192  uint16_t start;
193  uint16_t finish;
195  struct {
196  bool complete; // true after simplify_detection has completed
197  bool removal_required; // true if some simplify-able points have been found on the path, set true by detect_simplifications, set false by remove_points_by_simplify_bitmask
198  uint16_t path_points_count; // copy of _path_points_count taken when the simply algorithm started
199  uint16_t path_points_completed = SMARTRTL_POINTS_MAX; // number of points in that path that have already been simplified and should be ignored
201  uint16_t stack_max; // maximum number of elements in the _simplify_stack array
202  uint16_t stack_count; // number of elements in _simplify_stack array
203  Bitmask bitmask = Bitmask(SMARTRTL_POINTS_MAX); // simplify algorithm clears bits for each point that can be removed
204  } _simplify;
205 
206  // Pruning
207  typedef struct {
208  uint16_t start_index; // index of the first point in the loop
209  uint16_t end_index; // index of the last point in the loop
210  Vector3f midpoint; // midpoint which should replace the first point when the loop is removed
211  float length_squared; // length squared (in meters) of the loop (used so we can remove the longest loops)
212  } prune_loop_t;
213  struct {
214  bool complete;
215  uint16_t path_points_count; // copy of _path_points_count taken when the prune algorithm started
216  uint16_t path_points_completed; // number of points in that path that have already been checked for loops and should be ignored
217  uint16_t i; // loop search's outer loop index
218  uint16_t j; // loop search's inner loop index
219  prune_loop_t* loops;// the result of the pruning algorithm
220  uint16_t loops_max; // maximum number of elements in the _prunable_loops array
221  uint16_t loops_count; // number of elements in the _prunable_loops array
222  } _prune;
223 
224  // returns true if the two loops overlap (used within add_loop to determine which loops to keep or throw away)
225  bool loops_overlap(const prune_loop_t& loop1, const prune_loop_t& loop2) const;
226 };
prune_loop_t * loops
Definition: AP_SmartRTL.h:219
uint32_t _last_position_save_ms
Definition: AP_SmartRTL.h:177
Vector3< float > Vector3f
Definition: vector3.h:246
Vector3f * _path
Definition: AP_SmartRTL.h:183
void restart_simplify_if_new_points(uint16_t path_points_count)
uint16_t j
Definition: AP_SmartRTL.h:218
void restart_pruning_if_new_points()
bool loops_overlap(const prune_loop_t &loop1, const prune_loop_t &loop2) const
uint32_t _thorough_clean_request_ms
Definition: AP_SmartRTL.h:178
Interface definition for the various Ground Control System.
uint16_t i
Definition: AP_SmartRTL.h:217
void remove_points_by_simplify_bitmask()
bool request_thorough_cleanup(ThoroughCleanupType clean_type=THOROUGH_CLEAN_DEFAULT)
void routine_cleanup(uint16_t path_points_count, uint16_t path_points_complete_limit)
bool add_point(const Vector3f &point)
static const struct AP_Param::GroupInfo var_info[]
Definition: AP_SmartRTL.h:82
const Vector3f & get_point(uint16_t index) const
Definition: AP_SmartRTL.h:45
#define SMARTRTL_POINTS_MAX
Definition: AP_SmartRTL.h:14
uint16_t _path_points_completed_limit
Definition: AP_SmartRTL.h:186
void reset_pruning()
uint32_t _last_good_position_ms
Definition: AP_SmartRTL.h:176
AP_HAL::Semaphore * _path_sem
Definition: AP_SmartRTL.h:187
void restart_simplification(uint16_t path_points_count)
bool is_active() const
Definition: AP_SmartRTL.h:39
AP_SmartRTL(bool example_mode=false)
Definition: AP_SmartRTL.cpp:75
void run_background_cleanup()
uint16_t _path_points_max
Definition: AP_SmartRTL.h:184
uint16_t loops_count
Definition: AP_SmartRTL.h:221
uint16_t _path_points_count
Definition: AP_SmartRTL.h:185
simplify_start_finish_t * stack
Definition: AP_SmartRTL.h:200
void update(bool position_ok, bool save_position)
uint16_t get_num_points() const
uint16_t path_points_count
Definition: AP_SmartRTL.h:198
static dist_point segment_segment_dist(const Vector3f &p1, const Vector3f &p2, const Vector3f &p3, const Vector3f &p4)
void detect_loops()
Bitmask bitmask
Definition: AP_SmartRTL.h:203
AP_Float _accuracy
Definition: AP_SmartRTL.h:169
struct AP_SmartRTL::@183 _simplify
uint16_t stack_count
Definition: AP_SmartRTL.h:202
bool pop_point(Vector3f &point)
uint16_t path_points_completed
Definition: AP_SmartRTL.h:199
bool remove_points_by_loops(uint16_t num_points_to_remove)
void cancel_request_for_thorough_cleanup()
bool add_loop(uint16_t start_index, uint16_t end_index, const Vector3f &midpoint)
void detect_simplifications()
bool _example_mode
Definition: AP_SmartRTL.h:174
struct AP_SmartRTL::@184 _prune
uint16_t stack_max
Definition: AP_SmartRTL.h:201
void set_home(bool position_ok)
void deactivate(SRTL_Actions action, const char *reason)
void reset_simplification()
void log_action(SRTL_Actions action, const Vector3f &point=Vector3f())
bool _home_saved
Definition: AP_SmartRTL.h:175
fifo (queue) buffer template class
Vector2l point
Definition: polygon.cpp:34
uint16_t loops_max
Definition: AP_SmartRTL.h:220
bool removal_required
Definition: AP_SmartRTL.h:197
bool thorough_cleanup(uint16_t path_points_count, ThoroughCleanupType clean_type)
AP_Int16 _points_max
Definition: AP_SmartRTL.h:170
ThoroughCleanupType _thorough_clean_type
Definition: AP_SmartRTL.h:180
uint32_t _thorough_clean_complete_ms
Definition: AP_SmartRTL.h:179
void restart_pruning(uint16_t path_points_count)