Skip to content

Commit 2b85fc6

Browse files
Feature/hydra object rebase (#73)
* ability to parse instance id to map to mesh color * instance color does not get colored for graphs * add frame to mesh delta * fix agent node settings * cherry-pick mutex changes * drop instance ID config fields * rework mutex * rename field --------- Co-authored-by: Multyxu <multyxu@gmail.com>
1 parent b9b474a commit 2b85fc6

10 files changed

Lines changed: 64 additions & 26 deletions

File tree

hydra_ros/include/hydra_ros/utils/dsg_streaming_interface.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,22 @@ namespace hydra {
4949
class DsgSender {
5050
public:
5151
struct Config {
52+
//! Frame ID to publish scene graph under
5253
std::string frame_id;
54+
//! Timer name to record serialization timing
5355
std::string timer_name = "publish_dsg";
56+
//! Include mesh in serialized scene graph message
5457
bool serialize_dsg_mesh = true;
58+
//! Publish mesh separately from scene graph
5559
bool publish_mesh = false;
60+
//! Minimum amount of time separating mesh messages
5661
double min_mesh_separation_s = 0.0;
62+
//! Minimum amount of time separating scene graph messages
5763
double min_dsg_separation_s = 0.0;
5864

65+
//! Create a config with a specific timer name
5966
Config with_name(const std::string& name) const;
67+
//! Create a config with a specific frame ID
6068
Config with_frame(const std::string& frame) const;
6169
} const config;
6270

hydra_ros/src/frontend/ros_frontend_publisher.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ void RosFrontendPublisher::call(uint64_t timestamp_ns,
9494
backend_input.mesh_update->timestamp_ns = timestamp_ns;
9595
auto delta_msg = std::make_shared<MeshDeltaMsg>();
9696
kimera_pgmo::conversions::to_ros(*backend_input.mesh_update, *delta_msg);
97+
delta_msg->header.frame_id = GlobalInfo::instance().getFrames().odom;
9798
mesh_update_pub_->publish(*delta_msg);
9899

99100
stored_delta_.insert({backend_input.mesh_update->info.sequence_number, delta_msg});

hydra_visualizer/config/visualizer_config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ renderer:
4242
2p*:
4343
z_offset_scale: 0.0
4444
visualize: true
45-
nodes: {scale: 0.15, alpha: 0.9, use_sphere: false, color: {type: PartitionColorAdapter}}
46-
edges: {scale: 0.05, alpha: 0.9, draw_interlayer: false}
45+
nodes: {scale: 0.15, alpha: 1.0, use_sphere: true, color: {type: PartitionColorAdapter}}
46+
edges: {scale: 0.15, alpha: 1.0, draw_interlayer: false, color: {type: ''}}
4747
text: {draw_layer: true, height: 0.9, scale: 0.8}
4848
3p1:
4949
z_offset_scale: 3.0

hydra_visualizer/include/hydra_visualizer/io/graph_ros_wrapper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ class GraphRosWrapper : public GraphWrapper {
6464
bool has_change_;
6565
ianvs::NodeHandle nh_;
6666
rclcpp::Subscription<hydra_msgs::msg::DsgUpdate>::SharedPtr sub_;
67+
6768
rclcpp::Time last_time_;
6869
std::string last_frame_id_;
70+
mutable std::mutex graph_mutex_;
6971
spark_dsg::DynamicSceneGraph::Ptr graph_;
7072
};
7173

hydra_visualizer/include/hydra_visualizer/io/graph_wrapper.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,23 @@
3535
#pragma once
3636
#include <spark_dsg/dynamic_scene_graph.h>
3737

38+
#include <mutex>
39+
3840
#include <rclcpp/time.hpp>
3941

4042
namespace hydra {
4143

4244
struct StampedGraph {
45+
//! Underlying scene graph
4346
spark_dsg::DynamicSceneGraph::Ptr graph;
47+
//! Frame ID for scene graph
4448
std::string frame_id = "";
49+
//! Timestamp of scene graph
4550
std::optional<rclcpp::Time> timestamp = std::nullopt;
51+
//! Optional lock object for scene graph (for ROS and ZMQ wrappers)
52+
std::unique_lock<std::mutex> lock = {};
53+
54+
//! Whether or not the scene graph is valid
4655
inline operator bool() const { return graph != nullptr; }
4756
};
4857

hydra_visualizer/include/hydra_visualizer/plugins/mesh_plugin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class MeshPlugin : public VisualizerPlugin {
5252

5353
struct Config {
5454
config::VirtualConfig<MeshColoring, true> coloring;
55+
double min_mesh_separation_s = 0.0;
5556
};
5657

5758
MeshPlugin(const Config& config, ianvs::NodeHandle nh, const std::string& name);
@@ -70,6 +71,7 @@ class MeshPlugin : public VisualizerPlugin {
7071

7172
std::string getMsgNamespace() const;
7273

74+
std::optional<rclcpp::Time> last_pub_;
7375
rclcpp::Publisher<kimera_pgmo_msgs::msg::Mesh>::SharedPtr mesh_pub_;
7476
};
7577

hydra_visualizer/src/io/graph_ros_wrapper.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,21 @@ bool GraphRosWrapper::hasChange() const { return has_change_; }
6666
void GraphRosWrapper::clearChangeFlag() { has_change_ = false; }
6767

6868
StampedGraph GraphRosWrapper::get() const {
69-
return {graph_, last_frame_id_, last_time_};
69+
// lock and pass information to the visualizer
70+
std::unique_lock<std::mutex> lock(graph_mutex_);
71+
return {graph_, last_frame_id_, last_time_, std::move(lock)};
7072
}
7173

7274
void GraphRosWrapper::callback(const DsgUpdate::ConstSharedPtr& msg) {
73-
// not designed to be threadsafe; should lock and clone graph on return if desired
75+
// technically we shouldn't need a mutex here because the wrapper subscriber should be
76+
// in the same callback group as the rest of the node, but easy enough to pass a lock
77+
// to the visualizer
78+
std::lock_guard<std::mutex> lock(graph_mutex_);
79+
7480
last_time_ = msg->header.stamp;
7581
last_frame_id_ = msg->header.frame_id;
7682
if (last_frame_id_.empty()) {
77-
LOG(ERROR) << "Received scene grpah with empty frame_id field!";
83+
LOG(ERROR) << "Received scene graph with empty frame_id field!";
7884
return;
7985
}
8086

hydra_visualizer/src/io/graph_zmq_wrapper.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,13 @@ void GraphZmqWrapper::clearChangeFlag() {
8787
}
8888

8989
StampedGraph GraphZmqWrapper::get() const {
90-
std::lock_guard<std::mutex> lock(graph_mutex_);
90+
std::unique_lock<std::mutex> lock(graph_mutex_);
9191
if (!graph_) {
9292
return {nullptr};
9393
}
9494

95-
return {graph_->clone(), config.frame_id};
95+
// pass the lock for the visualizer to use the graph
96+
return {graph_, config.frame_id, std::nullopt, std::move(lock)};
9697
}
9798

9899
void GraphZmqWrapper::spin() {
@@ -106,6 +107,7 @@ void GraphZmqWrapper::spin() {
106107
if (receiver_->graph()) {
107108
graph_ = receiver_->graph()->clone();
108109
}
110+
109111
has_change_ = true;
110112
VLOG(1) << "Got graph!";
111113
}

hydra_visualizer/src/plugins/mesh_plugin.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,25 @@ static const auto registration =
5353

5454
}
5555

56+
using MeshMsg = kimera_pgmo_msgs::msg::Mesh;
57+
58+
using config::checkValid;
5659
using spark_dsg::DynamicSceneGraph;
60+
using visualizer::makeMeshMsg;
5761

5862
void declare_config(MeshPlugin::Config& config) {
5963
using namespace config;
6064
name("MeshPlugin::Config");
6165
field(config.coloring, "coloring");
66+
field(config.min_mesh_separation_s, "min_mesh_separation_s", "s");
6267
}
6368

6469
MeshPlugin::MeshPlugin(const Config& config,
6570
ianvs::NodeHandle nh,
6671
const std::string& name)
6772
: VisualizerPlugin(name),
68-
config_(
69-
"mesh_plugin", config::checkValid(config), [this]() { has_change_ = true; }),
70-
mesh_pub_(nh.create_publisher<kimera_pgmo_msgs::msg::Mesh>(
71-
name, rclcpp::QoS(1).transient_local())) {}
73+
config_("mesh_plugin", checkValid(config), [this]() { has_change_ = true; }),
74+
mesh_pub_(nh.create_publisher<MeshMsg>(name, rclcpp::QoS(1).transient_local())) {}
7275

7376
MeshPlugin::~MeshPlugin() {}
7477

@@ -80,9 +83,13 @@ void MeshPlugin::draw(const std_msgs::msg::Header& header,
8083
}
8184

8285
const auto config = config_.get();
86+
const rclcpp::Time now(header.stamp);
87+
if (last_pub_ && (now - *last_pub_).seconds() < config.min_mesh_separation_s) {
88+
return;
89+
}
8390

84-
auto msg = visualizer::makeMeshMsg(
85-
header, *mesh, getMsgNamespace(), config.coloring.create());
91+
last_pub_ = now;
92+
auto msg = makeMeshMsg(header, *mesh, getMsgNamespace(), config.coloring.create());
8693
mesh_pub_->publish(msg);
8794
}
8895

hydra_visualizer/src/visualizer_node.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,21 +122,22 @@ void DsgVisualizer::spinOnce(bool force) {
122122
return;
123123
}
124124

125-
const auto stamped_graph = graph_->get();
126-
if (!stamped_graph) {
127-
return;
128-
}
129-
130-
std_msgs::msg::Header header;
131-
header.frame_id = stamped_graph.frame_id;
132-
header.stamp = stamped_graph.timestamp.value_or(nh_.now());
125+
{ // start scope for stamped graph (for optional critical region)
126+
const auto stamped_graph = graph_->get();
127+
if (!stamped_graph) {
128+
return;
129+
}
133130

134-
renderer_->draw(header, *stamped_graph.graph);
135-
for (const auto& plugin : plugins_) {
136-
if (plugin) {
137-
plugin->draw(header, *stamped_graph.graph);
131+
std_msgs::msg::Header header;
132+
header.frame_id = stamped_graph.frame_id;
133+
header.stamp = stamped_graph.timestamp.value_or(nh_.now());
134+
renderer_->draw(header, *stamped_graph.graph);
135+
for (const auto& plugin : plugins_) {
136+
if (plugin) {
137+
plugin->draw(header, *stamped_graph.graph);
138+
}
138139
}
139-
}
140+
} // end scope for stamped graph
140141

141142
graph_->clearChangeFlag();
142143
renderer_->clearChangeFlag();

0 commit comments

Comments
 (0)