Skip to content

Commit 28d4aba

Browse files
authored
Merge pull request #2804 from PavelGuzenfeld/fix/2403-download-geofence
Implement download_geofence mirroring download_mission
2 parents 201faa8 + 7b91119 commit 28d4aba

File tree

17 files changed

+1731
-42
lines changed

17 files changed

+1731
-42
lines changed

c/src/cmavsdk/plugins/geofence/geofence.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,46 @@ mavsdk_geofence_upload_geofence(
378378
return translate_result(ret_value);
379379
}
380380

381+
// DownloadGeofence async
382+
void mavsdk_geofence_download_geofence_async(
383+
mavsdk_geofence_t geofence,
384+
mavsdk_geofence_download_geofence_callback_t callback,
385+
void* user_data)
386+
{
387+
auto wrapper = reinterpret_cast<mavsdk_geofence_wrapper*>(geofence);
388+
389+
wrapper->cpp_plugin->download_geofence_async(
390+
[callback, user_data](
391+
mavsdk::Geofence::Result result,
392+
mavsdk::Geofence::GeofenceData value) {
393+
if (callback) {
394+
callback(
395+
translate_result(result),
396+
translate_geofence_data_to_c(value),
397+
user_data);
398+
}
399+
});
400+
}
401+
402+
403+
// DownloadGeofence sync
404+
mavsdk_geofence_result_t
405+
mavsdk_geofence_download_geofence(
406+
mavsdk_geofence_t geofence,
407+
mavsdk_geofence_geofence_data_t* geofence_data_out)
408+
{
409+
auto wrapper = reinterpret_cast<mavsdk_geofence_wrapper*>(geofence);
410+
411+
auto result_pair = wrapper->cpp_plugin->download_geofence(
412+
);
413+
414+
if (geofence_data_out != nullptr) {
415+
*geofence_data_out = translate_geofence_data_to_c(result_pair.second);
416+
}
417+
418+
return translate_result(result_pair.first);
419+
}
420+
381421
// ClearGeofence async
382422
void mavsdk_geofence_clear_geofence_async(
383423
mavsdk_geofence_t geofence,

c/src/cmavsdk/plugins/geofence/geofence.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ CMAVSDK_EXPORT void mavsdk_geofence_byte_buffer_destroy(uint8_t** buffer);
300300

301301
// ===== Callback Typedefs =====
302302
typedef void (*mavsdk_geofence_upload_geofence_callback_t)(const mavsdk_geofence_result_t result, void* user_data);
303+
typedef void (*mavsdk_geofence_download_geofence_callback_t)(const mavsdk_geofence_result_t result, const mavsdk_geofence_geofence_data_t geofence_data, void* user_data);
303304
typedef void (*mavsdk_geofence_clear_geofence_callback_t)(const mavsdk_geofence_result_t result, void* user_data);
304305

305306
// ===== Geofence Creation/Destruction =====
@@ -343,6 +344,37 @@ mavsdk_geofence_upload_geofence(
343344
mavsdk_geofence_geofence_data_t geofence_data);
344345

345346

347+
/**
348+
* @brief Download geofences from the vehicle.
349+
*
350+
* Downloads polygon and circular geofences from the vehicle.
351+
*
352+
* @param geofence The geofence instance.
353+
*
354+
* @param callback Function to call when new data is available.
355+
* @param user_data User data to pass to the callback.
356+
*/
357+
CMAVSDK_EXPORT void mavsdk_geofence_download_geofence_async(
358+
mavsdk_geofence_t geofence,
359+
mavsdk_geofence_download_geofence_callback_t callback,
360+
void* user_data);
361+
362+
363+
/**
364+
* @brief Get the current download geofence (blocking).
365+
*
366+
* This function blocks until a value is available.
367+
*
368+
* @param telemetry The telemetry instance.
369+
* @param download_geofence_out Pointer to store the result.
370+
*/
371+
CMAVSDK_EXPORT
372+
mavsdk_geofence_result_t
373+
mavsdk_geofence_download_geofence(
374+
mavsdk_geofence_t geofence,
375+
mavsdk_geofence_geofence_data_t* geofence_data_out);
376+
377+
346378
/**
347379
* @brief Clear all geofences saved on the vehicle.
348380
*

cpp/docs/en/cpp/api_reference/classmavsdk_1_1_geofence.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Type | Description
2626
enum [FenceType](#classmavsdk_1_1_geofence_1a51196ded958aa9d4b3f25cde95da48e5) | [Geofence](classmavsdk_1_1_geofence.md) types.
2727
enum [Result](#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642) | Possible results returned for geofence requests.
2828
std::function< void([Result](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642))> [ResultCallback](#classmavsdk_1_1_geofence_1af9662e645781e4e64ed8b7c65d3d9309) | Callback type for asynchronous [Geofence](classmavsdk_1_1_geofence.md) calls.
29+
std::function< void([Result](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642), [GeofenceData](structmavsdk_1_1_geofence_1_1_geofence_data.md))> [DownloadGeofenceCallback](#classmavsdk_1_1_geofence_1a1fcce00cf17acb7e6f9cc3120f5b1e93) | Callback type for download_geofence_async.
2930

3031
## Public Member Functions
3132

@@ -38,6 +39,8 @@ Type | Name | Description
3839
&nbsp; | [Geofence](#classmavsdk_1_1_geofence_1a60e1f1a3123050c73980cba61b4b4009) (const [Geofence](classmavsdk_1_1_geofence.md) & other) | Copy constructor.
3940
void | [upload_geofence_async](#classmavsdk_1_1_geofence_1a1f0c6431b86b77c29f19eafb4e55dcdb) ([GeofenceData](structmavsdk_1_1_geofence_1_1_geofence_data.md) geofence_data, const [ResultCallback](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1af9662e645781e4e64ed8b7c65d3d9309) callback) | Upload geofences.
4041
[Result](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642) | [upload_geofence](#classmavsdk_1_1_geofence_1ab2e825f0955e7a320117a21d649bab09) ([GeofenceData](structmavsdk_1_1_geofence_1_1_geofence_data.md) geofence_data)const | Upload geofences.
42+
void | [download_geofence_async](#classmavsdk_1_1_geofence_1aedb57c09762303d17bf911cb46bc3403) (const [DownloadGeofenceCallback](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1a1fcce00cf17acb7e6f9cc3120f5b1e93) callback) | Download geofences from the vehicle.
43+
std::pair< [Result](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642), [Geofence::GeofenceData](structmavsdk_1_1_geofence_1_1_geofence_data.md) > | [download_geofence](#classmavsdk_1_1_geofence_1a6470bac1295b64eed9fc03c380bfbe24) () const | Download geofences from the vehicle.
4144
void | [clear_geofence_async](#classmavsdk_1_1_geofence_1a6947151765b621a93d35885599812752) (const [ResultCallback](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1af9662e645781e4e64ed8b7c65d3d9309) callback) | Clear all geofences saved on the vehicle.
4245
[Result](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642) | [clear_geofence](#classmavsdk_1_1_geofence_1a54b2a696e8aebae6916116adb92c03c3) () const | Clear all geofences saved on the vehicle.
4346
const [Geofence](classmavsdk_1_1_geofence.md) & | [operator=](#classmavsdk_1_1_geofence_1a174d03979e425bf8440dfe9bbabaf7d2) (const [Geofence](classmavsdk_1_1_geofence.md) &)=delete | Equality operator (object is not copyable).
@@ -117,6 +120,16 @@ using mavsdk::Geofence::ResultCallback = std::function<void(Result)>
117120
Callback type for asynchronous [Geofence](classmavsdk_1_1_geofence.md) calls.
118121

119122

123+
### typedef DownloadGeofenceCallback {#classmavsdk_1_1_geofence_1a1fcce00cf17acb7e6f9cc3120f5b1e93}
124+
125+
```cpp
126+
using mavsdk::Geofence::DownloadGeofenceCallback = std::function<void(Result, GeofenceData)>
127+
```
128+
129+
130+
Callback type for download_geofence_async.
131+
132+
120133
## Member Enumeration Documentation
121134

122135

@@ -190,6 +203,40 @@ This function is blocking. See 'upload_geofence_async' for the non-blocking coun
190203

191204
&emsp;[Result](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642) - Result of request.
192205

206+
### download_geofence_async() {#classmavsdk_1_1_geofence_1aedb57c09762303d17bf911cb46bc3403}
207+
```cpp
208+
void mavsdk::Geofence::download_geofence_async(const DownloadGeofenceCallback callback)
209+
```
210+
211+
212+
Download geofences from the vehicle.
213+
214+
Downloads polygon and circular geofences from the vehicle.
215+
216+
217+
This function is non-blocking. See 'download_geofence' for the blocking counterpart.
218+
219+
**Parameters**
220+
221+
* const [DownloadGeofenceCallback](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1a1fcce00cf17acb7e6f9cc3120f5b1e93) **callback** -
222+
223+
### download_geofence() {#classmavsdk_1_1_geofence_1a6470bac1295b64eed9fc03c380bfbe24}
224+
```cpp
225+
std::pair< Result, Geofence::GeofenceData > mavsdk::Geofence::download_geofence() const
226+
```
227+
228+
229+
Download geofences from the vehicle.
230+
231+
Downloads polygon and circular geofences from the vehicle.
232+
233+
234+
This function is blocking. See 'download_geofence_async' for the non-blocking counterpart.
235+
236+
**Returns**
237+
238+
&emsp;std::pair< [Result](classmavsdk_1_1_geofence.md#classmavsdk_1_1_geofence_1ab64d6e3b9aeb9b6d5e45ae8a843a2642), [Geofence::GeofenceData](structmavsdk_1_1_geofence_1_1_geofence_data.md) > - Result of request.
239+
193240
### clear_geofence_async() {#classmavsdk_1_1_geofence_1a6947151765b621a93d35885599812752}
194241
```cpp
195242
void mavsdk::Geofence::clear_geofence_async(const ResultCallback callback)

cpp/src/mavsdk/plugins/geofence/geofence.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ Geofence::Result Geofence::upload_geofence(GeofenceData geofence_data) const
3333
return _impl->upload_geofence(geofence_data);
3434
}
3535

36+
void Geofence::download_geofence_async(const DownloadGeofenceCallback callback)
37+
{
38+
_impl->download_geofence_async(callback);
39+
}
40+
41+
std::pair<Geofence::Result, Geofence::GeofenceData> Geofence::download_geofence() const
42+
{
43+
return _impl->download_geofence();
44+
}
45+
3646
void Geofence::clear_geofence_async(const ResultCallback callback)
3747
{
3848
_impl->clear_geofence_async(callback);

cpp/src/mavsdk/plugins/geofence/geofence_impl.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,101 @@ void GeofenceImpl::upload_geofence_async(
5656
});
5757
}
5858

59+
std::pair<Geofence::Result, Geofence::GeofenceData> GeofenceImpl::download_geofence()
60+
{
61+
auto prom = std::promise<std::pair<Geofence::Result, Geofence::GeofenceData>>();
62+
auto fut = prom.get_future();
63+
64+
download_geofence_async([&prom](Geofence::Result result, Geofence::GeofenceData geofence_data) {
65+
prom.set_value(std::make_pair(result, geofence_data));
66+
});
67+
return fut.get();
68+
}
69+
70+
void GeofenceImpl::download_geofence_async(const Geofence::DownloadGeofenceCallback& callback)
71+
{
72+
if (_last_download.lock()) {
73+
_system_impl->call_user_callback([callback]() {
74+
if (callback) {
75+
callback(Geofence::Result::Busy, Geofence::GeofenceData{});
76+
}
77+
});
78+
return;
79+
}
80+
81+
_last_download = _system_impl->mission_transfer_client().download_items_async(
82+
MAV_MISSION_TYPE_FENCE,
83+
_system_impl->get_system_id(),
84+
[this, callback](
85+
MavlinkMissionTransferClient::Result result,
86+
std::vector<MavlinkMissionTransferClient::ItemInt> items) {
87+
auto result_pair = (result == MavlinkMissionTransferClient::Result::Success) ?
88+
disassemble_items(items) :
89+
std::make_pair(convert_result(result), Geofence::GeofenceData{});
90+
_system_impl->call_user_callback([callback, result_pair]() {
91+
if (callback) {
92+
callback(result_pair.first, result_pair.second);
93+
}
94+
});
95+
});
96+
}
97+
98+
std::pair<Geofence::Result, Geofence::GeofenceData>
99+
GeofenceImpl::disassemble_items(const std::vector<MavlinkMissionTransferClient::ItemInt>& items)
100+
{
101+
Geofence::GeofenceData geofence_data;
102+
103+
size_t i = 0;
104+
while (i < items.size()) {
105+
const auto& item = items[i];
106+
107+
if (item.command == MAV_CMD_NAV_FENCE_POLYGON_VERTEX_INCLUSION ||
108+
item.command == MAV_CMD_NAV_FENCE_POLYGON_VERTEX_EXCLUSION) {
109+
Geofence::Polygon polygon;
110+
polygon.fence_type = (item.command == MAV_CMD_NAV_FENCE_POLYGON_VERTEX_INCLUSION) ?
111+
Geofence::FenceType::Inclusion :
112+
Geofence::FenceType::Exclusion;
113+
114+
const auto vertex_count = static_cast<size_t>(item.param1);
115+
if (vertex_count == 0 || i + vertex_count > items.size()) {
116+
LogErr() << "Invalid polygon vertex count: " << vertex_count;
117+
return {Geofence::Result::InvalidArgument, {}};
118+
}
119+
120+
for (size_t j = 0; j < vertex_count; ++j) {
121+
const auto& vertex_item = items[i + j];
122+
Geofence::Point point;
123+
point.latitude_deg = vertex_item.x * 1e-7;
124+
point.longitude_deg = vertex_item.y * 1e-7;
125+
polygon.points.push_back(point);
126+
}
127+
128+
geofence_data.polygons.push_back(polygon);
129+
i += vertex_count;
130+
131+
} else if (
132+
item.command == MAV_CMD_NAV_FENCE_CIRCLE_INCLUSION ||
133+
item.command == MAV_CMD_NAV_FENCE_CIRCLE_EXCLUSION) {
134+
Geofence::Circle circle;
135+
circle.fence_type = (item.command == MAV_CMD_NAV_FENCE_CIRCLE_INCLUSION) ?
136+
Geofence::FenceType::Inclusion :
137+
Geofence::FenceType::Exclusion;
138+
circle.point.latitude_deg = item.x * 1e-7;
139+
circle.point.longitude_deg = item.y * 1e-7;
140+
circle.radius = item.param1;
141+
142+
geofence_data.circles.push_back(circle);
143+
++i;
144+
145+
} else {
146+
LogWarn() << "Unknown geofence item command: " << item.command;
147+
++i;
148+
}
149+
}
150+
151+
return {Geofence::Result::Success, geofence_data};
152+
}
153+
59154
Geofence::Result GeofenceImpl::clear_geofence()
60155
{
61156
auto prom = std::promise<Geofence::Result>();

cpp/src/mavsdk/plugins/geofence/geofence_impl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class GeofenceImpl : public PluginImplBase {
2828
void upload_geofence_async(
2929
const Geofence::GeofenceData& geofence_data, const Geofence::ResultCallback& callback);
3030

31+
std::pair<Geofence::Result, Geofence::GeofenceData> download_geofence();
32+
33+
void download_geofence_async(const Geofence::DownloadGeofenceCallback& callback);
34+
3135
Geofence::Result clear_geofence();
3236

3337
void clear_geofence_async(const Geofence::ResultCallback& callback);
@@ -40,7 +44,12 @@ class GeofenceImpl : public PluginImplBase {
4044
std::vector<MavlinkMissionTransferClient::ItemInt>
4145
assemble_items(const Geofence::GeofenceData& geofence_data);
4246

47+
static std::pair<Geofence::Result, Geofence::GeofenceData>
48+
disassemble_items(const std::vector<MavlinkMissionTransferClient::ItemInt>& items);
49+
4350
static Geofence::Result convert_result(MavlinkMissionTransferClient::Result result);
51+
52+
std::weak_ptr<MavlinkMissionTransferClient::WorkItem> _last_download{};
4453
};
4554

4655
} // namespace mavsdk

cpp/src/mavsdk/plugins/geofence/include/plugins/geofence/geofence.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,31 @@ class Geofence : public PluginBase {
213213
*/
214214
Result upload_geofence(GeofenceData geofence_data) const;
215215

216+
/**
217+
* @brief Callback type for download_geofence_async.
218+
*/
219+
using DownloadGeofenceCallback = std::function<void(Result, GeofenceData)>;
220+
221+
/**
222+
* @brief Download geofences from the vehicle.
223+
*
224+
* Downloads polygon and circular geofences from the vehicle.
225+
*
226+
* This function is non-blocking. See 'download_geofence' for the blocking counterpart.
227+
*/
228+
void download_geofence_async(const DownloadGeofenceCallback callback);
229+
230+
/**
231+
* @brief Download geofences from the vehicle.
232+
*
233+
* Downloads polygon and circular geofences from the vehicle.
234+
*
235+
* This function is blocking. See 'download_geofence_async' for the non-blocking counterpart.
236+
*
237+
* @return Result of request.
238+
*/
239+
std::pair<Result, Geofence::GeofenceData> download_geofence() const;
240+
216241
/**
217242
* @brief Clear all geofences saved on the vehicle.
218243
*

0 commit comments

Comments
 (0)