Skip to content

Publish position and events via MQTT#274

Draft
rovo89 wants to merge 16 commits intomainfrom
feat/events-and-position
Draft

Publish position and events via MQTT#274
rovo89 wants to merge 16 commits intomainfrom
feat/events-and-position

Conversation

@rovo89
Copy link
Copy Markdown
Collaborator

@rovo89 rovo89 commented Mar 29, 2026

Summary by CodeRabbit

  • New Features

    • Added event history tracking—retrieve past mowing events with timestamps.
    • Added position history tracking—access mower's recorded path and movement data.
    • Expanded event types—now tracking mower startup, shutdown, mowing state changes, emergency events, GPS connectivity, area changes, and docking operations.
    • Enhanced area metadata—mowing areas now include ID and name in tracking data.
  • Chores

    • Migrated internal communication layer from RPC to MQTT protocol.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 29, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 70b8a7fa-4562-494b-8b55-5fa5f83a9989

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR migrates the RPC provider package from xbot_rpc to xbot_mqtt, introduces event and position history tracking with disk persistence, adds MQTT-based event publishing throughout the mower system, and extends the MowingBehavior class to track area metadata. The changes integrate history management across multiple subsystems.

Changes

Cohort / File(s) Summary
xbot_mqtt library (renamed from xbot_rpc)
src/lib/xbot_mqtt/CMakeLists.txt, src/lib/xbot_mqtt/package.xml, src/lib/xbot_mqtt/include/xbot_mqtt/constants.h, src/lib/xbot_mqtt/include/xbot_mqtt/provider.h, src/lib/xbot_mqtt/src/provider.cpp
Package and namespace renamed from xbot_rpc to xbot_mqtt; all RPC types and error codes updated across CMake, includes, and implementations.
xbot_mqtt helpers and messages
src/lib/xbot_mqtt/include/xbot_mqtt/publish.h, src/lib/xbot_mqtt/msg/MqttPublish.msg
Added new MqttPublish ROS message type and publish helper functions (generateNanoId, publish, publishEvent) with macro-based publisher initialization.
xbot_monitoring dependencies
src/lib/xbot_monitoring/CMakeLists.txt, src/lib/xbot_monitoring/package.xml
Updated dependencies: replaced xbot_rpc with xbot_mqtt and added mower_msgs.
xbot_monitoring history classes
src/lib/xbot_monitoring/src/EventHistory.h, src/lib/xbot_monitoring/src/PositionHistory.h
Added in-memory ring-buffer history classes with JSONL file persistence; PositionHistory includes Ramer–Douglas–Peucker simplification and mowing state tracking.
xbot_monitoring capabilities and integration
src/lib/xbot_monitoring/src/capabilities.h, src/lib/xbot_monitoring/src/xbot_monitoring.cpp
Added "events" and "position" capability flags; integrated EventHistory and PositionHistory with RPC methods, MQTT transport layer, and subscription handlers for pose/events.
mower_logic behavior tracking
src/mower_logic/src/mower_logic/behaviors/MowingBehavior.h, src/mower_logic/src/mower_logic/behaviors/MowingBehavior.cpp
Extended MowingBehavior to track current area ID and name with new const accessors; made get_current_area() const-qualified.
mower_logic MQTT event publishing
src/mower_logic/CMakeLists.txt, src/mower_logic/package.xml, src/mower_logic/src/mower_logic/mower_logic.cpp
Added xbot_mqtt dependency; integrated MQTT event publishing for mower state transitions (enabled/disabled, emergency, GPS timeout, docking, state changes, boot, shutdown); added area change tracking with event emission.
mower_map migration and service update
src/mower_map/CMakeLists.txt, src/mower_map/package.xml, src/mower_map/src/mower_map_service.cpp, src/mower_map/srv/GetMowingAreaSrv.srv
Replaced xbot_rpc with xbot_mqtt in build and dependencies; updated RPC provider and exception types; extended GetMowingAreaSrv response with area_id field and assigned it in service handler.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • JSON RPC 2.0 via MQTT #252: Directly related; involves xbot_rpc renaming to xbot_mqtt and extends the MQTT provider infrastructure with publish helpers and history integration.
  • Publish capabilities via MQTT #254: Both PRs modify monitoring capabilities in xbot_monitoring; the retrieved PR introduces the capabilities framework and the main PR extends it with new event and position capability flags.

Suggested reviewers

  • Apehaenger

Poem

🐰 Hop-hop, the rpc is now MQTT fast,
Events and positions tracked at last,
With circles of data and state-change delight,
The mower now broadcasts from morning to night! 🌾

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main objective: introducing MQTT publishing for position and events, which aligns with the key changes across multiple files including new EventHistory and PositionHistory classes, MQTT provider updates, and event emission logic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/events-and-position

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@rovo89
Copy link
Copy Markdown
Collaborator Author

rovo89 commented Mar 29, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (5)
src/lib/xbot_monitoring/src/xbot_monitoring.cpp (2)

151-153: Minor data race on current_high_level_state.

current_high_level_state is written in high_level_status_callback (line 488) and read in pose_callback (lines 522-523) potentially from different threads via the AsyncSpinner. While the impact is minimal (a missed idle check could add one extra point), consider using std::atomic<uint8_t> for correctness.

🔧 Proposed fix
 EventHistory event_history;
 PositionHistory position_history;
-uint8_t current_high_level_state = mower_msgs::HighLevelStatus::HIGH_LEVEL_STATE_NULL;
+std::atomic<uint8_t> current_high_level_state{mower_msgs::HighLevelStatus::HIGH_LEVEL_STATE_NULL};

Add include at the top:

`#include` <atomic>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/xbot_monitoring/src/xbot_monitoring.cpp` around lines 151 - 153,
current_high_level_state is subject to a data race because it's written in
high_level_status_callback and read in pose_callback from different AsyncSpinner
threads; change its type from uint8_t to std::atomic<uint8_t> and include
<atomic> at the top of the file, then update any direct reads/writes (references
to current_high_level_state) to use the atomic operations (load/store) as needed
to ensure thread-safe access.

743-747: Parameter reuse may cause confusion.

event_history_max_size is used to initialize both event_history and position_history, but the parameter name only references events. Consider either adding a separate position_history_max_size parameter or documenting this dual-use in a comment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/xbot_monitoring/src/xbot_monitoring.cpp` around lines 743 - 747, The
code currently reads a single parameter named event_history_max_size via
paramNh.param and uses it to initialize both event_history.init(...) and
position_history.init(...); introduce clarity by either adding a new parameter
(e.g., position_history_max_size) and use
paramNh.param("position_history_max_size", <fallback>) to initialize
position_history.init(static_cast<size_t>(position_history_max_size)), or if
shared sizing is intentional add a brief comment next to the paramNh.param call
explaining that event_history_max_size intentionally controls both event_history
and position_history; update the initialization lines to use the appropriate
variable names (event_history_max_size vs position_history_max_size) and ensure
defaults remain sensible.
src/lib/xbot_mqtt/include/xbot_mqtt/publish.h (1)

46-59: Details can overwrite injected fields.

If details contains keys "id", "t", or "type", the payload.update(details) call will overwrite the auto-generated values. If this is intentional (allowing caller overrides), consider documenting it. Otherwise, consider merging in the opposite order or using merge_patch.

🔧 If overwriting should be prevented
 inline void publishEvent(ros::Publisher& pub,
                          const std::string& type,
                          nlohmann::json details = nullptr,
                          bool retain = false) {
-    nlohmann::json payload = {
-        {"id",   generateNanoId()},
-        {"t",    ros::Time::now().toSec()},
-        {"type", type},
-    };
-    if (details.is_object()) {
-        payload.update(details);
-    }
+    nlohmann::json payload = details.is_object() ? details : nlohmann::json::object();
+    payload["id"]   = generateNanoId();
+    payload["t"]    = ros::Time::now().toSec();
+    payload["type"] = type;
     publish(pub, "events/json", payload, retain);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/xbot_mqtt/include/xbot_mqtt/publish.h` around lines 46 - 59,
publishEvent currently builds payload with generated "id","t","type" then calls
payload.update(details), which allows details to overwrite those injected
fields; to prevent this, change the merge order or guard keys so injected values
from generateNanoId(), ros::Time::now().toSec(), and the type parameter cannot
be replaced by details: in publishEvent (referencing generateNanoId(),
publishEvent, payload.update, and publish) merge details into payload in a way
that preserves existing keys (e.g., only copy keys from details that are not
"id","t","type" or perform payload = details; then set
payload["id"]=generateNanoId(); payload["t"]=...; payload["type"]=type), and
then call publish(pub, "events/json", payload, retain).
src/lib/xbot_monitoring/src/PositionHistory.h (2)

22-28: Hardcoded relative file path may cause issues.

file_path_ is set to a relative path "positions.jsonl". If the working directory changes between runs or varies across deployment environments, data could be written to unexpected locations or fail to load.

Consider deriving an absolute path from a ROS parameter or a well-known directory (e.g., ~/.ros/ or a package-specific data directory).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/xbot_monitoring/src/PositionHistory.h` around lines 22 - 28, The init
method currently assigns a hardcoded relative path to file_path_
("positions.jsonl"); change init (or overload it) to derive an absolute path
from a ROS parameter (e.g., fetch a param like "position_history_path") with a
sensible fallback such as the user's ROS home directory or a package-specific
data directory, expanding '~' and converting to an absolute path (use
std::filesystem::absolute or equivalent) before assigning file_path_; ensure
loadFromDisk() and startNewSegment() continue to use file_path_ unchanged and
that init documents/validates the resolved path.

124-126: Consider logging malformed lines for debugging.

The catch-all silently discards any errors during line parsing. While this is appropriate for resilience against corrupted files, emitting a ROS_WARN with the line number or content excerpt would aid troubleshooting without breaking the recovery flow.

🔧 Proposed improvement
       } catch (...) {
-        // skip malformed lines
+        ROS_WARN_STREAM("PositionHistory: skipping malformed line in " << file_path_);
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/xbot_monitoring/src/PositionHistory.h` around lines 124 - 126, The
catch-all in PositionHistory.h currently swallows parsing errors; instead, log a
non-fatal warning using ROS_WARN (or ROS_WARN_STREAM) that includes the
offending line number and/or a short excerpt of the line content before
continuing to skip it. Locate the catch (...) in the function that reads/parses
lines (the parsing loop in PositionHistory.h), access the loop's line index and
the buffer/string being parsed (e.g., the variable named line or similar), and
emit a warning like "Malformed line N: '...'" (truncate long lines), then
continue to preserve existing recovery behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/xbot_monitoring/src/EventHistory.h`:
- Around line 24-31: The persistent events file (events.jsonl) is unbounded
because appendToDisk(json_payload) always appends even when add() evicts old
entries from buffer_ (size bounded by max_size_), and the startup rescan (the
loader around lines 48-64) reads the entire file; change appendToDisk and the
eviction path so the on-disk history mirrors the in-memory bounded deque: when
buffer_.pop_front() removes an entry, remove or rotate that record on disk
(e.g., rewrite events.jsonl from current buffer_ or implement log
rotation/truncation) and ensure the startup loader reads only the bounded file;
update add(), appendToDisk(), and the startup load routine accordingly so disk
size stays capped with max_size_.
- Around line 16-19: The code crashes when event_history_max_size == 0 because
both loadFromDisk() and add() run eviction loops that call pop_front() on an
empty deque; fix by treating 0 as "disabled" or clamping before any eviction: in
init(size_t max_size) check if max_size == 0 and either set a disabled_ flag or
set max_size_ = 0 and skip loadFromDisk(); update loadFromDisk(), add(), and any
eviction logic (where you compare deque size to max_size_) to early-return when
max_size_ == 0 (or only perform while (max_size_ > 0 && deque.size() >
max_size_) pop_front()), so no pop_front() is called when history is disabled.

In `@src/lib/xbot_monitoring/src/PositionHistory.h`:
- Around line 97-104: persistSegment currently always appends to file_path_
(positions.jsonl) causing unbounded growth while closed_segments_ is capped by
max_segments_; change persistence to periodically rewrite the file to reflect
the in-memory ring buffer (or rotate logs): when closed_segments_.size() reaches
max_segments_ (or on a periodic threshold) acquire file_mutex_, write all
entries from closed_segments_ (using segmentToJson(seg).dump()) into a temporary
file, flush/close it, then atomically replace file_path_ (rename temp ->
file_path_); otherwise continue appending as before—ensure you use the same
file_mutex_ to serialize this truncate/replace and append logic so on-disk
contents match the bounded closed_segments_ buffer.

In `@src/mower_logic/src/mower_logic/mower_logic.cpp`:
- Line 247: The publishMowerEvent call is being invoked from command/request
paths (e.g., where `enabled` is a requested flag and inside `checkSafety()`),
causing repeated/incorrect MQTT lifecycle publishes; instead detect transitions
on the observed/actual state and emit events there. Move the
`publishMowerEvent("MOWING_STARTED"/"MOWING_STOPPED")` calls out of
command/safety paths and add edge-detection in the observed-state update logic:
store the previous observed mower mode/flags (e.g., observed enabled/mowing,
emergency, docking states), compare to the new observed state when
sensor/feedback or status messages arrive, and only call `publishMowerEvent`
when a true edge (false->true or true->false) occurs; apply the same change for
EMERGENCY_* and DOCKING publishes referenced in this file (also at the other
noted locations).
- Around line 350-357: The code reads area index, id, and name separately from
MowingBehavior::INSTANCE (via get_current_area, get_current_area_id,
get_current_area_name) causing data races and inconsistent combinations; change
MowingBehavior to provide an atomic snapshot accessor (e.g., a thread-safe
method that returns a small struct {int index; int id; std::string name;}
protected by the existing mutex) and update this call site to acquire that
snapshot once, compare snapshot.index to high_level_status.current_area, and
call publishMowerEvent("AREA_CHANGED", ...) using snapshot.id and snapshot.name;
ensure the snapshot method is used everywhere instead of the three separate
getters so string fields are accessed under the same lock.
- Around line 679-681: shutdownHandler currently calls publishMowerEvent and
ros::shutdown which are not async-signal-safe; change the handler to only set a
process-wide std::atomic<bool> (e.g. shutdown_requested) and return immediately,
then in the main thread or ROS spin loop detect that shutdown_requested was set
(use shutdown_requested.exchange(false, std::memory_order_relaxed) or similar to
ensure one-shot handling) and from the main thread call
publishMowerEvent("SHUTDOWN") and ros::shutdown(); update references in the code
to remove non-safe calls from shutdownHandler and use the atomic flag logic to
perform the actual shutdown sequence in normal thread context.

In `@src/mower_map/srv/GetMowingAreaSrv.srv`:
- Line 3: You added a new field `string area_id` to the service contract
`GetMowingAreaSrv`, which will change the generated service MD5 and break ABI
for prebuilt clients; instead, create a new service (e.g., `GetMowingAreaSrvV2`)
that contains the new `string area_id` field and keep the original
`GetMowingAreaSrv` unchanged so existing consumers remain compatible; update any
server and client code to use `GetMowingAreaSrvV2` where the new field is
required and ensure build/system manifests reference the new service name.

---

Nitpick comments:
In `@src/lib/xbot_monitoring/src/PositionHistory.h`:
- Around line 22-28: The init method currently assigns a hardcoded relative path
to file_path_ ("positions.jsonl"); change init (or overload it) to derive an
absolute path from a ROS parameter (e.g., fetch a param like
"position_history_path") with a sensible fallback such as the user's ROS home
directory or a package-specific data directory, expanding '~' and converting to
an absolute path (use std::filesystem::absolute or equivalent) before assigning
file_path_; ensure loadFromDisk() and startNewSegment() continue to use
file_path_ unchanged and that init documents/validates the resolved path.
- Around line 124-126: The catch-all in PositionHistory.h currently swallows
parsing errors; instead, log a non-fatal warning using ROS_WARN (or
ROS_WARN_STREAM) that includes the offending line number and/or a short excerpt
of the line content before continuing to skip it. Locate the catch (...) in the
function that reads/parses lines (the parsing loop in PositionHistory.h), access
the loop's line index and the buffer/string being parsed (e.g., the variable
named line or similar), and emit a warning like "Malformed line N: '...'"
(truncate long lines), then continue to preserve existing recovery behavior.

In `@src/lib/xbot_monitoring/src/xbot_monitoring.cpp`:
- Around line 151-153: current_high_level_state is subject to a data race
because it's written in high_level_status_callback and read in pose_callback
from different AsyncSpinner threads; change its type from uint8_t to
std::atomic<uint8_t> and include <atomic> at the top of the file, then update
any direct reads/writes (references to current_high_level_state) to use the
atomic operations (load/store) as needed to ensure thread-safe access.
- Around line 743-747: The code currently reads a single parameter named
event_history_max_size via paramNh.param and uses it to initialize both
event_history.init(...) and position_history.init(...); introduce clarity by
either adding a new parameter (e.g., position_history_max_size) and use
paramNh.param("position_history_max_size", <fallback>) to initialize
position_history.init(static_cast<size_t>(position_history_max_size)), or if
shared sizing is intentional add a brief comment next to the paramNh.param call
explaining that event_history_max_size intentionally controls both event_history
and position_history; update the initialization lines to use the appropriate
variable names (event_history_max_size vs position_history_max_size) and ensure
defaults remain sensible.

In `@src/lib/xbot_mqtt/include/xbot_mqtt/publish.h`:
- Around line 46-59: publishEvent currently builds payload with generated
"id","t","type" then calls payload.update(details), which allows details to
overwrite those injected fields; to prevent this, change the merge order or
guard keys so injected values from generateNanoId(), ros::Time::now().toSec(),
and the type parameter cannot be replaced by details: in publishEvent
(referencing generateNanoId(), publishEvent, payload.update, and publish) merge
details into payload in a way that preserves existing keys (e.g., only copy keys
from details that are not "id","t","type" or perform payload = details; then set
payload["id"]=generateNanoId(); payload["t"]=...; payload["type"]=type), and
then call publish(pub, "events/json", payload, retain).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a8a42da9-2278-448a-a162-dafb87a4b27c

📥 Commits

Reviewing files that changed from the base of the PR and between 7596011 and 300fb5e.

📒 Files selected for processing (26)
  • src/lib/xbot_monitoring/CMakeLists.txt
  • src/lib/xbot_monitoring/package.xml
  • src/lib/xbot_monitoring/src/EventHistory.h
  • src/lib/xbot_monitoring/src/PositionHistory.h
  • src/lib/xbot_monitoring/src/capabilities.h
  • src/lib/xbot_monitoring/src/xbot_monitoring.cpp
  • src/lib/xbot_mqtt/CMakeLists.txt
  • src/lib/xbot_mqtt/include/xbot_mqtt/constants.h
  • src/lib/xbot_mqtt/include/xbot_mqtt/provider.h
  • src/lib/xbot_mqtt/include/xbot_mqtt/publish.h
  • src/lib/xbot_mqtt/msg/MqttPublish.msg
  • src/lib/xbot_mqtt/msg/RpcError.msg
  • src/lib/xbot_mqtt/msg/RpcRequest.msg
  • src/lib/xbot_mqtt/msg/RpcResponse.msg
  • src/lib/xbot_mqtt/package.xml
  • src/lib/xbot_mqtt/src/provider.cpp
  • src/lib/xbot_mqtt/srv/RegisterMethodsSrv.srv
  • src/mower_logic/CMakeLists.txt
  • src/mower_logic/package.xml
  • src/mower_logic/src/mower_logic/behaviors/MowingBehavior.cpp
  • src/mower_logic/src/mower_logic/behaviors/MowingBehavior.h
  • src/mower_logic/src/mower_logic/mower_logic.cpp
  • src/mower_map/CMakeLists.txt
  • src/mower_map/package.xml
  • src/mower_map/src/mower_map_service.cpp
  • src/mower_map/srv/GetMowingAreaSrv.srv

Comment thread src/lib/xbot_monitoring/src/EventHistory.h
Comment thread src/lib/xbot_monitoring/src/EventHistory.h
Comment thread src/lib/xbot_monitoring/src/PositionHistory.h Outdated
// status change ?
const auto last_status = status_state_subscriber.getMessage();
if (last_status.mow_enabled != enabled) {
publishMowerEvent(enabled ? "MOWING_STARTED" : "MOWING_STOPPED");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Emit MQTT lifecycle events from confirmed state edges.

These publishes are currently driven by requested state / level-triggered safety conditions. checkSafety() can re-enter them every 0.5s while services retry, feedback lags, or an abort is still in flight, so history can record duplicates or transitions that never actually happened. Please emit MOWING_*, EMERGENCY_*, and DOCKING from observed state edges instead of these command paths.

Also applies to: 324-324, 593-594

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/mower_logic/src/mower_logic/mower_logic.cpp` at line 247, The
publishMowerEvent call is being invoked from command/request paths (e.g., where
`enabled` is a requested flag and inside `checkSafety()`), causing
repeated/incorrect MQTT lifecycle publishes; instead detect transitions on the
observed/actual state and emit events there. Move the
`publishMowerEvent("MOWING_STARTED"/"MOWING_STOPPED")` calls out of
command/safety paths and add edge-detection in the observed-state update logic:
store the previous observed mower mode/flags (e.g., observed enabled/mowing,
emergency, docking states), compare to the new observed state when
sensor/feedback or status messages arrive, and only call `publishMowerEvent`
when a true edge (false->true or true->false) occurs; apply the same change for
EMERGENCY_* and DOCKING publishes referenced in this file (also at the other
noted locations).

Comment thread src/mower_logic/src/mower_logic/mower_logic.cpp
Comment thread src/mower_logic/src/mower_logic/mower_logic.cpp Outdated
Comment thread src/mower_map/srv/GetMowingAreaSrv.srv
@rovo89 rovo89 force-pushed the feat/events-and-position branch 2 times, most recently from 898c3ad to 5b153cc Compare March 29, 2026 20:39
Comment on lines +526 to +528
position_history.addPoint(msg->pose.pose.position.x,
msg->pose.pose.position.y,
msg->header.stamp);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you have the state and the AbsolutePose anyways we could also store both.

This would give us:

  • Indication what the mower was doing at the moment (travel lines vs mow lines)
  • Indication in which areas the position was good / bad so that we can optimize issues.

Probably make this generic, so that we could color the mower's historic positions for generic things (e.g. wifi signal strength etc) and have a dropdown in the GUI for that.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would also be an option. Just thought I'd keep the message size minimal since those message will come pretty frequently, and the state that xbot_monitoring has might be slightly delayed, being sent only at 1 Hz. Might need another round of thinking to get this right. Not sure if you've seen it, for the history I have the state per "segment", starting a new one periodically or whenever the state changes.

@rovo89 rovo89 force-pushed the feat/events-and-position branch from 8af8ddd to 10fdb7a Compare April 24, 2026 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants