-
Notifications
You must be signed in to change notification settings - Fork 607
Add pose graph & node event publisher #809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: humble_lifecycle
Are you sure you want to change the base?
Conversation
This should be set to target |
@@ -0,0 +1,2 @@ | |||
int32 node_id | |||
geometry_msgs/Pose2D pose |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is deprecated in ROS 2, please use a SE2 pose
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll fix this.
@@ -0,0 +1,4 @@ | |||
int32 source_id | |||
int32 target_id | |||
geometry_msgs/Pose2D relative_pose |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is deprecated in ROS 2, please use a SE2 pose
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll fix this.
@@ -0,0 +1,3 @@ | |||
int32 new_node_id | |||
builtin_interfaces/Time stamp | |||
geometry_msgs/Pose2D pose No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is deprecated in ROS 2, please use a SE2 pose
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll fix this.
} | ||
|
||
/*****************************************************************************/ | ||
void SlamToolbox::poseGraphPublishTimerCallback() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can have this done in the publishVisualizations
callback like we have TF and the map occ grids themselves
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SteveMacenski As far as I understand, publishVisualizations()
runs on a fixed interval (please correct me if I'm wrong). Since the pose_graph
message can be quite large, we’d like to avoid publishing it periodically.
In our PR, we’re checking publish_pose_graph_requested_
flag inside poseGraphPublishTimerCallback
, and only publish the pose_graph
when the flag is set, for example after a loop closure event.
This allows us to publish the pose_graph only when a loop closure occurs. We chose to use this flag-based approach because occasionally we fail to lock the smapper_mutex_
.
Please let me know if I’ve misunderstood your comment!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, another option could be to check the flag inside publishVisualizations
. That way, we wouldn't need additional poseGraphPublishTimerCallback
. Is this what you meant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the pose_graph message can be quite large, we’d like to avoid publishing it periodically.
I guess I'm suggesting checking on the atomic bool if we have an update to publish only if needed -- but to do that operation here instead of having the timer. Yes :-)
boost::bind(&SlamToolbox::publishVisualizations, this))); | ||
|
||
// Create pose graph publish timer (10Hz) | ||
pose_graph_timer_ = this->create_wall_timer( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would remove this timer
|
||
publishPose(range_scan->GetCorrectedPose(), covariance, scan->header.stamp); | ||
publishNewNodeEvent(range_scan); | ||
requestPoseGraphPublish(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think this should happen on each new node or only when a loop closure happens? This could become quite a large thing to publish every ~second as this grows to a very large space
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just doing the new node is enough. The full graph should wait until its needed to update other info.
If someone is subscribed to the graph and new node topics, then if a new node comes in, they can add to their graph without reinitializing everything since the rest of the graph is stable. We should only force a graph update if other non-new-nodes have changed things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just doing the new node is enough. The full graph should wait until its needed to update other info.
@SteveMacenski We were publishing the full pose_graph on every new node event because I thought other users might expect the topic to be updated more frequently in general cases.
However, I agree with your point. The full graph takes up a lot of space, and incremental updates using new node events alone should be sufficient. Also, handling general cases is beyond the scope of this PR.
We'll remove the full pose_graph publication from every new node event, and update the README to clarify that the pose_graph topic is only published on loop closures.
node_msg.pose.x = lrs->GetCorrectedPose().GetX(); | ||
node_msg.pose.y = lrs->GetCorrectedPose().GetY(); | ||
node_msg.pose.theta = lrs->GetCorrectedPose().GetHeading(); | ||
msg.nodes.push_back(node_msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you know the size of mapper_vertices
then you can reserve
the size so we don't have a ton of copies from resizing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll fix this!
} | ||
} | ||
|
||
msg.edges.push_back(edge_msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you know the size of mapper_edges
then you can reserve
the size so we don't have a ton of copies from resizing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll fix this!
msg.edges.push_back(edge_msg); | ||
} | ||
|
||
pose_graph_pub_->publish(msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msg
should be constructed as a unique pointer and here we can std::move()
to publish. Trust me, for large messages it makes a difference in performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll fix this.
I'm not very familiar with C++, so thanks for pointing that out. Really helpful!
void SlamToolbox::loopClosureCallback() | ||
/*****************************************************************************/ | ||
{ | ||
requestPoseGraphPublish(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could just register this callback as the loopClosureCallback if this is all that this does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll fix this.
@SteveMacenski Sorry to bother you, but could you please explain the branching policy a bit more? Should I open separate PRs for each of ros2, jazzy, kilted, and humble? |
ros2 is the main branch (as true in rclcpp / other repos) -- though sometimes you may see it called For now, ros2 only. Once we're done, we can assess if we can backport to various branches -- but almost certainly we cannot for Humble. |
@SteveMacenski Thanks for your detailed and kind reply! We'll make the updates based on your comments soon. |
Basic Info
Description of contribution in a few bullet points
karto::MapperLoopClosureListener
and publishes/slam_toolbox/loop_closure_event
when Karto signalsEndLoopClosure
./slam_toolbox/new_node_event
when a new node is generated./slam_toolbox/pose_graph
once the internal mapping mutex becomes available, instead of invoking it directly inside the callback.Description of documentation updates required from your changes
Documentation updatedFuture work that may be required in bullet points
N/APerformance Metrics
1.mp4
Question for the Maintainer
I noticed that all other ROS distro branches (e.g., Foxy, Galactic, Rolling) use the lifecycle version,
so I made these changes on the
humble_lifecycle
branch for consistency.Is this the correct branch to work on?
Also, could you please clarify why only the Humble version has two separate branches
(
humble
andhumble_lifecycle
), while the others maintain just a single lifecycle version?