Skip to content

Commit 2cc49d9

Browse files
author
jonas
committed
refactor(navigator): better memory handling
1 parent 38ccd0d commit 2cc49d9

9 files changed

Lines changed: 55 additions & 55 deletions

File tree

src/lib/dataman_client/DatamanClient.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -600,13 +600,17 @@ bool DatamanCache::loadWait(dm_item_t item, uint32_t index, uint8_t *buffer, uin
600600
bool item_found = false;
601601

602602
if (_items) {
603-
for (uint32_t i = 0; i < _num_items; ++i) {
603+
// Start scanning at the last hit
604+
for (uint32_t n = 0; n < _num_items; ++n) {
605+
const uint32_t i = (_search_hint + n) % _num_items;
606+
604607
if ((_items[i].response.item == item) &&
605608
(_items[i].response.index == index)) {
606609
item_found = true;
607610

608611
if (_items[i].cache_state == State::ResponseReceived) {
609612
memcpy(buffer, _items[i].response.data, length);
613+
_search_hint = i;
610614
success = true;
611615
break;
612616
}
@@ -672,17 +676,14 @@ bool DatamanCache::updateCachedItem(dm_item_t item, uint32_t index, const uint8_
672676
return false;
673677
}
674678

679+
// Only patch data that is fully received and stable. Slots in other states are skipped:
680+
// an in-flight async read will fetch the new SD card data shortly anyway, and invalidated
681+
// slots can still carry a stale key match for the same item/index.
675682
for (uint32_t i = 0; i < _num_items; ++i) {
676-
if ((_items[i].response.item == item) && (_items[i].response.index == index)) {
677-
678-
// Only patch data that is fully received and stable. If it is RequestPrepared,
679-
// an async read is flying and will fetch the new SD card data shortly anyway.
680-
if (_items[i].cache_state == State::ResponseReceived) {
681-
memcpy(_items[i].response.data, buffer, length);
682-
return true;
683-
}
684-
685-
return false; // Item exists but is not in a safe state to patch
683+
if ((_items[i].response.item == item) && (_items[i].response.index == index)
684+
&& (_items[i].cache_state == State::ResponseReceived)) {
685+
memcpy(_items[i].response.data, buffer, length);
686+
return true;
686687
}
687688
}
688689

@@ -760,6 +761,7 @@ void DatamanCache::resetCacheState()
760761
_update_index = 0;
761762
_item_counter = 0;
762763
_load_index = 0;
764+
_search_hint = 0;
763765
}
764766

765767
void DatamanCache::invalidate()

src/lib/dataman_client/DatamanClient.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ class DatamanCache
317317
uint32_t _update_index{0}; ///< index for tracking last index used by update function
318318
uint32_t _item_counter{0}; ///< number of items to process with update function
319319
uint32_t _num_items{0}; ///< number of items that cache can store
320+
uint32_t _search_hint{0}; ///< slot of the last loadWait hit, speeds up sequential lookups
320321

321322
DatamanClient _client{};
322323

src/modules/navigator/mission_route_cache.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444

4545
#include "mission_route_cache.h"
4646

47+
#include "mission_route_types.h"
48+
4749
#include <inttypes.h>
4850

4951
#include <px4_platform_common/log.h>
@@ -75,12 +77,6 @@ bool MissionRouteCache::queueMissionCacheLoads(const mission_s &mission)
7577
// Rebuild the mission cache from scratch, callers retry the full queue on failure.
7678
_dataman_cache_mission.invalidate();
7779

78-
if (static_cast<int32_t>(_dataman_cache_mission.size()) < mission.count) {
79-
PX4_ERR("Mission cache capacity too small! requested: %d, capacity: %d",
80-
static_cast<int>(mission.count), static_cast<int>(_dataman_cache_mission.size()));
81-
return false;
82-
}
83-
8480
const dm_item_t mission_dataman_id = static_cast<dm_item_t>(mission.mission_dataman_id);
8581

8682
for (int32_t index = 0; index < mission.count; ++index) {
@@ -134,7 +130,7 @@ bool MissionRouteCache::missionLandItemCacheFullyLoaded() const
134130
return false;
135131
}
136132

137-
return isMissionLandCommand(land_item.nav_cmd);
133+
return mission_route::isLandingCmd(land_item.nav_cmd);
138134
}
139135

140136
bool MissionRouteCache::safePointCacheFullyLoaded() const
@@ -242,7 +238,7 @@ bool MissionRouteCache::getMissionLandItem(int32_t &index, mission_item_s &land_
242238
return false;
243239
}
244240

245-
if (!isMissionLandCommand(cached_land_item.nav_cmd)) {
241+
if (!mission_route::isLandingCmd(cached_land_item.nav_cmd)) {
246242
return false;
247243
}
248244

@@ -288,7 +284,7 @@ bool MissionRouteCache::syncMissionItem(const mission_s &mission, int32_t index,
288284
return false;
289285
}
290286

291-
if (!isMissionLandCommand(mission_item.nav_cmd)) {
287+
if (!mission_route::isLandingCmd(mission_item.nav_cmd)) {
292288
_dataman_cache_land_item.invalidate();
293289
_mission_land.ready = false;
294290
_mission_land.validation_pending = false;
@@ -300,7 +296,7 @@ bool MissionRouteCache::syncMissionItem(const mission_s &mission, int32_t index,
300296
_mission_land.validation_pending = false;
301297
_mission_land.retry.clear();
302298

303-
if (isMissionLandCommand(mission_item.nav_cmd)) {
299+
if (mission_route::isLandingCmd(mission_item.nav_cmd)) {
304300
_mission_land.validation_pending = queueMissionLandItem();
305301

306302
if (!_mission_land.validation_pending) {
@@ -332,6 +328,13 @@ void MissionRouteCache::updateMissionCache(const mission_s &mission)
332328
state.ready = mission.count == 0;
333329
state.too_large = missionExceedsCacheLimit(mission);
334330

331+
// If mission exceed the capacity (e.g. the boot-time cache allocation failed) no recovery is possible.
332+
if (!state.too_large && static_cast<int32_t>(_dataman_cache_mission.size()) < mission.count) {
333+
PX4_ERR("Mission cache capacity too small, cache disabled! requested: %d, capacity: %d",
334+
static_cast<int>(mission.count), static_cast<int>(_dataman_cache_mission.size()));
335+
state.too_large = true;
336+
}
337+
335338
if (!state.too_large && mission.count > 0) {
336339
state.validation_pending = queueMissionCacheLoads(mission);
337340

src/modules/navigator/mission_route_cache.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ class MissionRouteCache : public mission_route::Provider
9494
&& (_mission_land.validation_pending || _mission_land.retry.retry_at != 0);
9595
}
9696

97-
inline bool isMissionLandCommand(uint16_t nav_cmd) const { return nav_cmd == NAV_CMD_LAND || nav_cmd == NAV_CMD_VTOL_LAND;}
9897
int missionCount() const override;
9998
bool loadMissionItem(int index, mission_item_s &mission_item) const override;
10099
int safePointCount() const override;

src/modules/navigator/mission_route_types.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ bool Position::valid() const
5454
&& (fabs(lat) <= 90.0) && (fabs(lon) <= 180.0);
5555
}
5656

57+
bool isLandingCmd(uint16_t nav_cmd)
58+
{
59+
return nav_cmd == NAV_CMD_LAND || nav_cmd == NAV_CMD_VTOL_LAND;
60+
}
61+
5762
float getAbsoluteAltitudeForMissionItem(const mission_item_s &mission_item, float home_altitude_amsl)
5863
{
5964
if (mission_item.altitude_is_relative) {

src/modules/navigator/mission_route_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ struct Position {
6464
bool valid() const;
6565
};
6666

67+
bool isLandingCmd(uint16_t nav_cmd);
68+
6769
float getAbsoluteAltitudeForMissionItem(const mission_item_s &mission_item, float home_altitude_amsl);
6870

6971
/** @brief Extract the valid position from a rally-point safe-point item. */

src/modules/navigator/navigator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class Navigator : public ModuleBase, public ModuleParams
175175
vehicle_land_detected_s *get_land_detected() { return &_land_detected; }
176176
vehicle_local_position_s *get_local_position() { return &_local_pos; }
177177
vehicle_status_s *get_vstatus() { return &_vstatus; }
178-
MissionRouteCache *get_mission_route_cache() { return &_mission_route_cache; }
178+
MissionRouteCache &get_mission_route_cache() { return _mission_route_cache; }
179179

180180
PrecLand *get_precland() { return &_precland; } /**< allow others, e.g. Mission, to use the precision land block */
181181
Course *get_course() { return &_course; }

src/modules/navigator/rtl.cpp

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,7 @@ RTL::RTL(Navigator *navigator) :
7676

7777
void RTL::updateDatamanCache()
7878
{
79-
MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
80-
81-
if (mission_route_cache != nullptr) {
82-
mission_route_cache->update(_mission_sub.get());
83-
}
79+
_navigator->get_mission_route_cache().update(_mission_sub.get());
8480
}
8581

8682
void RTL::on_inactive()
@@ -265,7 +261,7 @@ void RTL::setRtlTypeAndDestination()
265261
{
266262
uint8_t safe_point_index = RTL_STATUS_NO_SAFE_POINT;
267263
RtlType new_rtl_type{RtlType::RTL_DIRECT};
268-
MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
264+
const MissionRouteCache &mission_route_cache = _navigator->get_mission_route_cache();
269265

270266
// init destination with Home (used also with Type 2 and 4 as backup)
271267
DestinationType destination_type = DestinationType::DESTINATION_TYPE_HOME;
@@ -343,10 +339,9 @@ void RTL::setRtlTypeAndDestination()
343339

344340
// Publish rtl status
345341
rtl_status_s rtl_status{};
346-
rtl_status.safe_points_id = mission_route_cache != nullptr ? mission_route_cache->safePointsId() : 0;
347-
rtl_status.is_evaluation_pending = mission_route_cache != nullptr
348-
&& (mission_route_cache->safePointUpdatePending()
349-
|| mission_route_cache->missionLandItemUpdatePending());
342+
rtl_status.safe_points_id = mission_route_cache.safePointsId();
343+
rtl_status.is_evaluation_pending = mission_route_cache.safePointUpdatePending()
344+
|| mission_route_cache.missionLandItemUpdatePending();
350345
rtl_status.has_vtol_approach = _home_has_land_approach || _one_rally_point_has_land_approach;
351346
rtl_status.rtl_type = static_cast<uint8_t>(_rtl_type);
352347
rtl_status.safe_point_index = safe_point_index;
@@ -358,19 +353,19 @@ PositionYawSetpoint RTL::findClosestSafePoint(float min_dist, uint8_t &safe_poin
358353
{
359354
const bool vtol_in_fw_mode = _vehicle_status_sub.get().is_vtol
360355
&& (_vehicle_status_sub.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
361-
MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
356+
const MissionRouteCache &mission_route_cache = _navigator->get_mission_route_cache();
362357

363358
PositionYawSetpoint safe_point{static_cast<double>(NAN), static_cast<double>(NAN), NAN, NAN};
364359
_one_rally_point_has_land_approach = false;
365360

366-
if (mission_route_cache == nullptr || !mission_route_cache->safePointsReady()) {
361+
if (!mission_route_cache.safePointsReady()) {
367362
return safe_point;
368363
}
369364

370-
for (int current_seq = 0; current_seq < mission_route_cache->safePointCount(); ++current_seq) {
365+
for (int current_seq = 0; current_seq < mission_route_cache.safePointCount(); ++current_seq) {
371366
mission_item_s mission_safe_point;
372367

373-
if (!mission_route_cache->loadSafePointItem(current_seq, mission_safe_point)) {
368+
if (!mission_route_cache.loadSafePointItem(current_seq, mission_safe_point)) {
374369
PX4_ERR("dm_read failed");
375370
continue;
376371
}
@@ -401,7 +396,7 @@ PositionYawSetpoint RTL::findClosestSafePoint(float min_dist, uint8_t &safe_poin
401396
safepoint_position.lat, safepoint_position.lon)};
402397

403398
const bool current_safe_point_has_approaches{
404-
mission_route_cache->hasVtolLandApproachesAtSafePointIndex(current_seq, _home_pos_sub.get().alt)
399+
mission_route_cache.hasVtolLandApproachesAtSafePointIndex(current_seq, _home_pos_sub.get().alt)
405400
};
406401

407402
_one_rally_point_has_land_approach |= current_safe_point_has_approaches;
@@ -431,12 +426,11 @@ void RTL::findRtlDestination(DestinationType &destination_type, PositionYawSetpo
431426
const bool vtol_in_fw_mode = _vehicle_status_sub.get().is_vtol
432427
&& (_vehicle_status_sub.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
433428

434-
MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
429+
const MissionRouteCache &mission_route_cache = _navigator->get_mission_route_cache();
435430
float min_dist = FLT_MAX;
436431

437432
if (_param_rtl_type.get() != RTL_TYPE_SAFE_POINT_DIRECT) {
438-
_home_has_land_approach = mission_route_cache != nullptr
439-
&& mission_route_cache->hasVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
433+
_home_has_land_approach = mission_route_cache.hasVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
440434

441435
const bool prioritize_safe_points_over_home = ((_param_rtl_type.get() == 1) && !vtol_in_rw_mode);
442436
const bool required_approach_missing_for_home = (vtol_in_fw_mode && (_param_rtl_appr_force.get() == 1) && !_home_has_land_approach);
@@ -454,7 +448,7 @@ void RTL::findRtlDestination(DestinationType &destination_type, PositionYawSetpo
454448
|| (fabsf(FLT_MAX - min_dist) < FLT_EPSILON)) && hasMissionLandStart()) {
455449
mission_item_s land_mission_item{};
456450
int32_t land_index = -1;
457-
const bool success = mission_route_cache != nullptr && mission_route_cache->getMissionLandItem(land_index, land_mission_item);
451+
const bool success = mission_route_cache.getMissionLandItem(land_index, land_mission_item);
458452

459453
if (!success) {
460454

@@ -629,14 +623,8 @@ loiter_point_s RTL::selectLandingApproach(const PositionYawSetpoint &destination
629623
return landing_approach;
630624
}
631625

632-
const MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
633-
634-
if (mission_route_cache == nullptr) {
635-
return landing_approach;
636-
}
637-
638626
const land_approaches_s vtol_land_approaches =
639-
mission_route_cache->getVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
627+
_navigator->get_mission_route_cache().getVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
640628

641629
if (vtol_land_approaches.isAnyApproachValid()) {
642630
landing_approach = chooseBestLandingApproach(vtol_land_approaches);

src/modules/navigator/test/test_RTL.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class RTLTest : public NavigatorDatamanTestBase
218218
ASSERT_TRUE(_dataman_client.writeSync(DM_KEY_SAFE_POINTS_STATE, 0,
219219
reinterpret_cast<uint8_t *>(&empty_stats), sizeof(empty_stats)));
220220

221-
_navigator.get_mission_route_cache()->invalidate();
221+
_navigator.get_mission_route_cache().invalidate();
222222

223223
publishHomePosition(makePositionYawSetpointFromOffset(kBaseLat, kBaseLon, 0.f, 0.f, kAlt));
224224
publishVehicleStatus(false, vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
@@ -227,7 +227,7 @@ class RTLTest : public NavigatorDatamanTestBase
227227

228228
void TearDown() override
229229
{
230-
_navigator.get_mission_route_cache()->invalidate();
230+
_navigator.get_mission_route_cache().invalidate();
231231

232232
if (_home_pub != nullptr) {
233233
orb_unadvertise(_home_pub);
@@ -267,10 +267,10 @@ class RTLTest : public NavigatorDatamanTestBase
267267
mission.safe_points_id = ++_safe_points_id;
268268
mission.safepoint_dataman_id = DM_KEY_SAFE_POINTS_0;
269269

270-
MissionRouteCache *mission_route_cache = _navigator.get_mission_route_cache();
271-
mission_route_cache->invalidate();
272-
ASSERT_TRUE(MissionRouteCacheTestPeer::runCacheUntil(*mission_route_cache, mission,
273-
[&] { return mission_route_cache->safePointsReady(); }))
270+
MissionRouteCache &mission_route_cache = _navigator.get_mission_route_cache();
271+
mission_route_cache.invalidate();
272+
ASSERT_TRUE(MissionRouteCacheTestPeer::runCacheUntil(mission_route_cache, mission,
273+
[&] { return mission_route_cache.safePointsReady(); }))
274274
<< "test safe points did not load";
275275
}
276276

0 commit comments

Comments
 (0)