Skip to content

Commit ff46fd6

Browse files
author
jonas
committed
refactor(navigator): better memory handling
1 parent 0b9c829 commit ff46fd6

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
@@ -318,6 +318,7 @@ class DatamanCache
318318
uint32_t _update_index{0}; ///< index for tracking last index used by update function
319319
uint32_t _item_counter{0}; ///< number of items to process with update function
320320
uint32_t _num_items{0}; ///< number of items that cache can store
321+
uint32_t _search_hint{0}; ///< slot of the last loadWait hit, speeds up sequential lookups
321322

322323
DatamanClient _client{};
323324

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
@@ -181,7 +181,7 @@ class Navigator : public ModuleBase, public ModuleParams
181181
uint8_t get_takeoff_state() { return _takeoff_status_sub.get().takeoff_state; }
182182
vehicle_local_position_s *get_local_position() { return &_local_pos; }
183183
vehicle_status_s *get_vstatus() { return &_vstatus; }
184-
MissionRouteCache *get_mission_route_cache() { return &_mission_route_cache; }
184+
MissionRouteCache &get_mission_route_cache() { return _mission_route_cache; }
185185

186186
PrecLand *get_precland() { return &_precland; } /**< allow others, e.g. Mission, to use the precision land block */
187187
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;
@@ -372,10 +368,9 @@ void RTL::setRtlTypeAndDestination()
372368

373369
// Publish rtl status
374370
rtl_status_s rtl_status{};
375-
rtl_status.safe_points_id = mission_route_cache != nullptr ? mission_route_cache->safePointsId() : 0;
376-
rtl_status.is_evaluation_pending = mission_route_cache != nullptr
377-
&& (mission_route_cache->safePointUpdatePending()
378-
|| mission_route_cache->missionLandItemUpdatePending());
371+
rtl_status.safe_points_id = mission_route_cache.safePointsId();
372+
rtl_status.is_evaluation_pending = mission_route_cache.safePointUpdatePending()
373+
|| mission_route_cache.missionLandItemUpdatePending();
379374
rtl_status.has_vtol_approach = _home_has_land_approach || _one_rally_point_has_land_approach;
380375
rtl_status.rtl_type = static_cast<uint8_t>(_rtl_type);
381376
rtl_status.safe_point_index = safe_point_index;
@@ -387,19 +382,19 @@ PositionYawSetpoint RTL::findClosestSafePoint(float min_dist, uint8_t &safe_poin
387382
{
388383
const bool vtol_in_fw_mode = _vehicle_status_sub.get().is_vtol
389384
&& (_vehicle_status_sub.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
390-
MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
385+
const MissionRouteCache &mission_route_cache = _navigator->get_mission_route_cache();
391386

392387
PositionYawSetpoint safe_point{static_cast<double>(NAN), static_cast<double>(NAN), NAN, NAN};
393388
_one_rally_point_has_land_approach = false;
394389

395-
if (mission_route_cache == nullptr || !mission_route_cache->safePointsReady()) {
390+
if (!mission_route_cache.safePointsReady()) {
396391
return safe_point;
397392
}
398393

399-
for (int current_seq = 0; current_seq < mission_route_cache->safePointCount(); ++current_seq) {
394+
for (int current_seq = 0; current_seq < mission_route_cache.safePointCount(); ++current_seq) {
400395
mission_item_s mission_safe_point;
401396

402-
if (!mission_route_cache->loadSafePointItem(current_seq, mission_safe_point)) {
397+
if (!mission_route_cache.loadSafePointItem(current_seq, mission_safe_point)) {
403398
PX4_ERR("dm_read failed");
404399
continue;
405400
}
@@ -430,7 +425,7 @@ PositionYawSetpoint RTL::findClosestSafePoint(float min_dist, uint8_t &safe_poin
430425
safepoint_position.lat, safepoint_position.lon)};
431426

432427
const bool current_safe_point_has_approaches{
433-
mission_route_cache->hasVtolLandApproachesAtSafePointIndex(current_seq, _home_pos_sub.get().alt)
428+
mission_route_cache.hasVtolLandApproachesAtSafePointIndex(current_seq, _home_pos_sub.get().alt)
434429
};
435430

436431
_one_rally_point_has_land_approach |= current_safe_point_has_approaches;
@@ -460,12 +455,11 @@ void RTL::findRtlDestination(DestinationType &destination_type, PositionYawSetpo
460455
const bool vtol_in_fw_mode = _vehicle_status_sub.get().is_vtol
461456
&& (_vehicle_status_sub.get().vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
462457

463-
MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
458+
const MissionRouteCache &mission_route_cache = _navigator->get_mission_route_cache();
464459
float min_dist = FLT_MAX;
465460

466461
if (_param_rtl_type.get() != RTL_TYPE_SAFE_POINT_DIRECT) {
467-
_home_has_land_approach = mission_route_cache != nullptr
468-
&& mission_route_cache->hasVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
462+
_home_has_land_approach = mission_route_cache.hasVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
469463

470464
const bool prioritize_safe_points_over_home = ((_param_rtl_type.get() == 1) && !vtol_in_rw_mode);
471465
const bool required_approach_missing_for_home = (vtol_in_fw_mode && (_param_rtl_appr_force.get() == 1) && !_home_has_land_approach);
@@ -483,7 +477,7 @@ void RTL::findRtlDestination(DestinationType &destination_type, PositionYawSetpo
483477
|| (fabsf(FLT_MAX - min_dist) < FLT_EPSILON)) && hasMissionLandStart()) {
484478
mission_item_s land_mission_item{};
485479
int32_t land_index = -1;
486-
const bool success = mission_route_cache != nullptr && mission_route_cache->getMissionLandItem(land_index, land_mission_item);
480+
const bool success = mission_route_cache.getMissionLandItem(land_index, land_mission_item);
487481

488482
if (!success) {
489483

@@ -658,14 +652,8 @@ loiter_point_s RTL::selectLandingApproach(const PositionYawSetpoint &destination
658652
return landing_approach;
659653
}
660654

661-
const MissionRouteCache *mission_route_cache = _navigator->get_mission_route_cache();
662-
663-
if (mission_route_cache == nullptr) {
664-
return landing_approach;
665-
}
666-
667655
const land_approaches_s vtol_land_approaches =
668-
mission_route_cache->getVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
656+
_navigator->get_mission_route_cache().getVtolLandApproachesNearLocation(destination, _home_pos_sub.get().alt);
669657

670658
if (vtol_land_approaches.isAnyApproachValid()) {
671659
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)