CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AC_Fence/AC_PolyFence_loader.h
Views: 1798
1
#pragma once
2
3
#include "AC_Fence_config.h"
4
#include <AP_Math/AP_Math.h>
5
6
// CIRCLE_INCLUSION_INT stores the radius an a 32-bit integer in
7
// metres. This was a bug, and CIRCLE_INCLUSION was created to store
8
// as a 32-bit float instead. We save as _INT in the case that the
9
// radius looks like an integer as a backwards-compatibility measure.
10
// For 4.2 we might consider only loading _INT and always saving as
11
// float, and in 4.3 considering _INT invalid
12
enum class AC_PolyFenceType : uint8_t {
13
END_OF_STORAGE = 99,
14
POLYGON_INCLUSION = 98,
15
POLYGON_EXCLUSION = 97,
16
CIRCLE_EXCLUSION_INT = 96,
17
RETURN_POINT = 95,
18
CIRCLE_INCLUSION_INT = 94,
19
CIRCLE_EXCLUSION = 93,
20
CIRCLE_INCLUSION = 92,
21
};
22
23
// a FenceItem is just a means of passing data about an item into
24
// and out of the polyfence loader. It uses a AC_PolyFenceType to
25
// indicate the item type, assuming each fence type is made up of
26
// only one sort of item.
27
// TODO: make this a union (or use subclasses) to save memory
28
class AC_PolyFenceItem {
29
public:
30
AC_PolyFenceType type;
31
Vector2l loc;
32
uint8_t vertex_count;
33
float radius;
34
};
35
36
#if AP_FENCE_ENABLED
37
38
#include <AP_Common/AP_Common.h>
39
#include <AP_Common/Location.h>
40
#include <GCS_MAVLink/GCS_MAVLink.h>
41
42
class AC_PolyFence_loader
43
{
44
45
public:
46
47
AC_PolyFence_loader(AP_Int8 &total, const AP_Int16 &options) :
48
_total(total),
49
_options(options) {}
50
51
/* Do not allow copies */
52
CLASS_NO_COPY(AC_PolyFence_loader);
53
54
void init();
55
56
// methods primarily for MissionItemProtocol_Fence to use:
57
// return the total number of points stored
58
uint16_t num_stored_items() const { return _eeprom_item_count; }
59
bool get_item(const uint16_t seq, AC_PolyFenceItem &item) WARN_IF_UNUSED;
60
61
///
62
/// exclusion polygons
63
///
64
/// returns number of polygon exclusion zones defined
65
uint8_t get_exclusion_polygon_count() const {
66
return _num_loaded_exclusion_boundaries;
67
}
68
69
/// returns pointer to array of exclusion polygon points and num_points is filled in with the number of points in the polygon
70
/// points are offsets in cm from EKF origin in NE frame
71
Vector2f* get_exclusion_polygon(uint16_t index, uint16_t &num_points) const;
72
73
/// return system time of last update to the exclusion polygon points
74
uint32_t get_exclusion_polygon_update_ms() const {
75
return _load_time_ms;
76
}
77
78
///
79
/// inclusion polygons
80
///
81
/// returns number of polygon inclusion zones defined
82
uint8_t get_inclusion_polygon_count() const {
83
return _num_loaded_inclusion_boundaries;
84
}
85
86
/// returns pointer to array of inclusion polygon points and num_points is filled in with the number of points in the polygon
87
/// points are offsets in cm from EKF origin in NE frame
88
Vector2f* get_inclusion_polygon(uint16_t index, uint16_t &num_points) const;
89
90
/// return system time of last update to the inclusion polygon points
91
uint32_t get_inclusion_polygon_update_ms() const {
92
return _load_time_ms;
93
}
94
95
///
96
/// exclusion circles
97
///
98
/// returns number of exclusion circles defined
99
uint8_t get_exclusion_circle_count() const {
100
return _num_loaded_circle_exclusion_boundaries;
101
}
102
103
/// returns the specified exclusion circle
104
/// center is offsets in cm from EKF origin in NE frame, radius is in meters
105
bool get_exclusion_circle(uint8_t index, Vector2f &center_pos_cm, float &radius) const;
106
107
/// return system time of last update to the exclusion circles
108
uint32_t get_exclusion_circle_update_ms() const {
109
return _load_time_ms;
110
}
111
112
///
113
/// inclusion circles
114
///
115
/// returns number of inclusion circles defined
116
uint8_t get_inclusion_circle_count() const {
117
return _num_loaded_circle_inclusion_boundaries;
118
}
119
120
/// returns the specified inclusion circle
121
/// center is offsets in cm from EKF origin in NE frame, radius is in meters
122
bool get_inclusion_circle(uint8_t index, Vector2f &center_pos_cm, float &radius) const;
123
124
// false if margin < fence radius
125
bool check_inclusion_circle_margin(float margin) const;
126
127
///
128
/// mavlink
129
///
130
/// handler for polygon fence messages with GCS
131
void handle_msg(class GCS_MAVLINK &link, const mavlink_message_t& msg);
132
133
// breached() - returns true if the vehicle has breached any fence
134
bool breached() const WARN_IF_UNUSED;
135
// breached(Location&) - returns true if location is outside the boundary
136
bool breached(const Location& loc) const WARN_IF_UNUSED;
137
138
// returns true if a polygonal include fence could be returned
139
bool inclusion_boundary_available() const WARN_IF_UNUSED {
140
return _num_loaded_inclusion_boundaries != 0;
141
}
142
143
// loaded - returns true if the fences have been loaded from
144
// storage and are available for use
145
bool loaded() const WARN_IF_UNUSED {
146
return _load_time_ms != 0;
147
};
148
149
// maximum number of fence points we can store in eeprom
150
uint16_t max_items() const;
151
152
// write_fence - validate and write count new_items to permanent storage
153
bool write_fence(const AC_PolyFenceItem *new_items, uint16_t count) WARN_IF_UNUSED;
154
155
/*
156
* Loaded Fence functionality
157
*
158
* methods and members to do with fences stored in memory. The
159
* locations are translated into offset-from-origin-in-metres
160
*/
161
162
// load polygon points stored in eeprom into
163
// _loaded_offsets_from_origin and perform validation. returns
164
// true if load successfully completed
165
bool load_from_eeprom() WARN_IF_UNUSED;
166
167
// allow threads to lock against AHRS update
168
HAL_Semaphore &get_loaded_fence_semaphore(void) {
169
return _loaded_fence_sem;
170
}
171
172
// call @10Hz to check for fence load being valid
173
void update();
174
175
// get_return_point - returns latitude/longitude of return point.
176
// This works with storage - the returned vector is absolute
177
// lat/lon.
178
bool get_return_point(Vector2l &ret) WARN_IF_UNUSED;
179
180
// return total number of fences - polygons and circles
181
uint16_t total_fence_count() const {
182
return (get_exclusion_polygon_count() +
183
get_inclusion_polygon_count() +
184
get_exclusion_circle_count() +
185
get_inclusion_circle_count());
186
}
187
188
189
#if AP_SDCARD_STORAGE_ENABLED
190
bool failed_sdcard_storage(void) const {
191
return _failed_sdcard_storage;
192
}
193
#endif
194
195
private:
196
// multi-thread access support
197
HAL_Semaphore _loaded_fence_sem;
198
199
/*
200
* Fence storage Index related functions
201
*/
202
// FenceIndex - a class used to store information about a fence in
203
// fence storage.
204
class FenceIndex {
205
public:
206
AC_PolyFenceType type;
207
uint16_t count;
208
uint16_t storage_offset;
209
};
210
// index_fence_count - returns the number of fences of type
211
// currently in the index
212
uint16_t index_fence_count(const AC_PolyFenceType type);
213
214
// void_index - free resources for the index, forcing a reindex
215
// (typically via check_indexed)
216
void void_index() {
217
delete[] _index;
218
_index = nullptr;
219
_index_attempted = false;
220
_indexed = false;
221
}
222
223
// check_indexed - read eeprom and create index if the index does
224
// not already exist
225
bool check_indexed() WARN_IF_UNUSED;
226
227
// find_first_fence - return first fence in index of specific type
228
FenceIndex *find_first_fence(const AC_PolyFenceType type) const;
229
230
// find_index_for_seq - returns true if seq is contained within a
231
// fence. If it is, entry will be the relevant FenceIndex. i
232
// will be the offset within _loaded_offsets_from_origin where the
233
// first point in the fence is found
234
bool find_index_for_seq(const uint16_t seq, const FenceIndex *&entry, uint16_t &i) const WARN_IF_UNUSED;
235
// find_storage_offset_for_seq - uses the index to return an
236
// offset into storage for an item
237
bool find_storage_offset_for_seq(const uint16_t seq, uint16_t &offset, AC_PolyFenceType &type, uint16_t &vertex_count_offset) const WARN_IF_UNUSED;
238
239
uint16_t sum_of_polygon_point_counts_and_returnpoint();
240
241
/*
242
* storage-related methods - dealing with fence_storage
243
*/
244
245
// new_fence_storage_magic - magic number indicating fence storage
246
// has been formatted for use by polygon fence storage code.
247
// FIXME: ensure this is out-of-band for old lat/lon point storage
248
static const uint8_t new_fence_storage_magic = 235;
249
250
// validate_fence - returns true if new_items look completely valid
251
bool validate_fence(const AC_PolyFenceItem *new_items, uint16_t count) const WARN_IF_UNUSED;
252
253
// _eos_offset - stores the offset in storage of the
254
// end-of-storage marker. Used by low-level manipulation code to
255
// extend storage
256
uint16_t _eos_offset;
257
258
// formatted - returns true if the fence storage space seems to be
259
// formatted for new-style fence storage
260
bool formatted() const WARN_IF_UNUSED;
261
// format - format the storage space for use by
262
// the new polyfence code
263
bool format() WARN_IF_UNUSED;
264
265
266
/*
267
* Loaded Fence functionality
268
*
269
* methods and members to do with fences stored in memory. The
270
* locations are translated into offset-from-origin-in-metres
271
*/
272
273
// remove resources dedicated to the transformed fences - for
274
// example, in _loaded_offsets_from_origin
275
void unload();
276
277
// pointer into _loaded_offsets_from_origin where the return point
278
// can be found:
279
Vector2f *_loaded_return_point;
280
281
// pointer into _loaded_points_lla where the return point
282
// can be found:
283
Vector2l *_loaded_return_point_lla;
284
285
class InclusionBoundary {
286
public:
287
Vector2f *points; // pointer into the _loaded_offsets_from_origin array
288
Vector2l *points_lla; // pointer into the _loaded_points_lla array
289
uint8_t count; // count of points in the boundary
290
};
291
InclusionBoundary *_loaded_inclusion_boundary;
292
293
uint8_t _num_loaded_inclusion_boundaries;
294
295
class ExclusionBoundary {
296
public:
297
Vector2f *points; // pointer into the _loaded_offsets_from_origin array
298
Vector2l *points_lla; // pointer into the _loaded_points_lla_lla array
299
uint8_t count; // count of points in the boundary
300
};
301
ExclusionBoundary *_loaded_exclusion_boundary;
302
303
uint8_t _num_loaded_exclusion_boundaries;
304
305
// _loaded_offsets_from_origin - stores x/y offset-from-origin
306
// coordinate pairs. Various items store their locations in this
307
// allocation - the polygon boundaries and the return point, for
308
// example.
309
Vector2f *_loaded_offsets_from_origin;
310
Vector2l *_loaded_points_lla;
311
312
class ExclusionCircle {
313
public:
314
Vector2f pos_cm; // vector offset from home in cm
315
Vector2l point; // lat/lng of zone
316
float radius;
317
};
318
ExclusionCircle *_loaded_circle_exclusion_boundary;
319
320
uint8_t _num_loaded_circle_exclusion_boundaries;
321
322
class InclusionCircle {
323
public:
324
Vector2f pos_cm; // vector offset from home in cm
325
Vector2l point; // lat/lng of zone
326
float radius;
327
};
328
InclusionCircle *_loaded_circle_inclusion_boundary;
329
330
uint8_t _num_loaded_circle_inclusion_boundaries;
331
332
// _load_attempted - true if we have attempted to load the fences
333
// from storage into _loaded_circle_exclusion_boundary,
334
// _loaded_offsets_from_origin etc etc
335
bool _load_attempted;
336
337
// _load_time_ms - from millis(), system time when fence load last
338
// succeeded. Will be zero if fences are not loaded
339
uint32_t _load_time_ms;
340
341
// scale_latlon_from_origin - given a latitude/longitude
342
// transforms the point to an offset-from-origin and deposits
343
// the result into pos_cm.
344
bool scale_latlon_from_origin(const Location &origin,
345
const Vector2l &point,
346
Vector2f &pos_cm) WARN_IF_UNUSED;
347
348
// read_polygon_from_storage - reads vertex_count
349
// latitude/longitude points from offset in permanent storage,
350
// transforms them into an offset-from-origin and deposits the
351
// results into next_storage_point.
352
bool read_polygon_from_storage(const Location &origin,
353
uint16_t &read_offset,
354
const uint8_t vertex_count,
355
Vector2f *&next_storage_point,
356
Vector2l *&next_storage_point_lla) WARN_IF_UNUSED;
357
358
#if AC_POLYFENCE_FENCE_POINT_PROTOCOL_SUPPORT
359
/*
360
* FENCE_POINT protocol compatibility
361
*/
362
void handle_msg_fetch_fence_point(GCS_MAVLINK &link, const mavlink_message_t& msg);
363
void handle_msg_fence_point(GCS_MAVLINK &link, const mavlink_message_t& msg);
364
// contains_compatible_fence - returns true if the permanent fence
365
// storage contains fences that are compatible with the old
366
// FENCE_POINT protocol.
367
bool contains_compatible_fence() const WARN_IF_UNUSED;
368
369
// get_or_create_include_fence - returns a point to an include
370
// fence to be used for the FENCE_POINT-supplied polygon. May
371
// format the storage appropriately.
372
FenceIndex *get_or_create_include_fence();
373
// get_or_create_include_fence - returns a point to a return point
374
// to be used for the FENCE_POINT-supplied return point. May
375
// format the storage appropriately.
376
FenceIndex *get_or_create_return_point();
377
#endif
378
379
// primitives to write parts of fencepoints out:
380
bool write_type_to_storage(uint16_t &offset, AC_PolyFenceType type) WARN_IF_UNUSED;
381
bool write_latlon_to_storage(uint16_t &offset, const Vector2l &latlon) WARN_IF_UNUSED;
382
bool read_latlon_from_storage(uint16_t &read_offset, Vector2l &latlon) const WARN_IF_UNUSED;
383
384
// methods to write specific types of fencepoint out:
385
bool write_eos_to_storage(uint16_t &offset);
386
387
// _total - reference to FENCE_TOTAL parameter. This is used
388
// solely for compatibility with the FENCE_POINT protocol
389
AP_Int8 &_total;
390
const AP_Int16 &_options;
391
uint8_t _old_total;
392
393
394
// scan_eeprom - a method that traverses the fence storage area,
395
// calling the supplied callback for each fence found. If the
396
// scan fails (for example, the storage is corrupt), then this
397
// method will return false.
398
FUNCTOR_TYPEDEF(scan_fn_t, void, const AC_PolyFenceType, uint16_t);
399
bool scan_eeprom(scan_fn_t scan_fn) WARN_IF_UNUSED;
400
// scan_eeprom_count_fences - a static function designed to be
401
// massed to scan_eeprom which counts the number of fences and
402
// fence items present. The results of this counting appear in _eeprom_fence_count and _eeprom_item_count
403
void scan_eeprom_count_fences(const AC_PolyFenceType type, uint16_t read_offset);
404
uint16_t _eeprom_fence_count;
405
uint16_t _eeprom_item_count;
406
407
// scan_eeprom_index_fences - a static function designed to be
408
// passed to scan_eeprom. _index must be a pointer to
409
// memory sufficient to hold information about all fences present
410
// in storage - so it is expected that scan_eeprom_count_fences
411
// has been used to count those fences and the allocation already
412
// made. After this method has been called _index will
413
// be filled with information about the fences in the fence
414
// storage - type, item counts and storage offset.
415
void scan_eeprom_index_fences(const AC_PolyFenceType type, uint16_t read_offset);
416
// array specifying type of each fence in storage (and a count of
417
// items in that fence)
418
FenceIndex *_index;
419
bool _indexed; // true if indexing successful
420
bool _index_attempted; // true if we attempted to index the eeprom
421
// _num_fences - count of the number of fences in _index. This
422
// should be equal to _eeprom_fence_count
423
uint16_t _num_fences;
424
425
// count_eeprom_fences - refresh the count of fences in permanent storage
426
bool count_eeprom_fences() WARN_IF_UNUSED;
427
// index_eeprom - (re)allocate and fill in _index
428
bool index_eeprom() WARN_IF_UNUSED;
429
430
uint16_t fence_storage_space_required(const AC_PolyFenceItem *new_items, uint16_t count);
431
432
#if AP_SDCARD_STORAGE_ENABLED
433
// true if we failed to load SDCard storage on init
434
bool _failed_sdcard_storage;
435
#endif
436
};
437
438
#endif // AP_FENCE_ENABLED
439
440