Skip to content

Commit e8f4e19

Browse files
authored
Feature/rg traversability (#53)
* draft of region visualization * add tmp launch files * fix traversability viualization for now * update to new traversability attrs * add region places visualization plugin * update visualizer config * draft region growing edge coloring * update visualization * update vis config * remove tmp launch files * drop TMP code
1 parent 56dc4ac commit e8f4e19

8 files changed

Lines changed: 175 additions & 66 deletions

File tree

hydra_ros/src/frontend/traversability_visualizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ TraversabilityVisualizer::TraversabilityVisualizer(const Config& config)
7070
config::checkValid(config),
7171
[this]() { onConfigUpdate(); }),
7272
nh_(ianvs::NodeHandle::this_node(config.ns)),
73-
layer_pub_(nh_.create_publisher<visualization_msgs::msg::Marker>("layer", 10)) {
73+
layer_pub_(nh_.create_publisher<visualization_msgs::msg::Marker>("layer", 100)) {
7474
onConfigUpdate();
7575
}
7676

hydra_visualizer/config/visualizer_config.yaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ renderer:
99
nodes: {scale: 0.40, color: {type: LabelColorAdapter}, alpha: 0.8, use_sphere: false}
1010
text: {draw: true, collapse: true, adapter: {type: LabelTextAdapter}, height: 0.5, scale: 0.45}
1111
bounding_boxes: {draw: true, collapse: true, scale: 0.05, edge_scale: 0.05, alpha: 0.9, edge_break_ratio: 0.5}
12-
edges: {interlayer_use_source: true, interlayer_scale: 0.08, interlayer_alpha: 0.9}
12+
edges: {interlayer_use_source: true, interlayer_scale: 0.08, interlayer_alpha: 0.5}
1313
3:
1414
z_offset_scale: 3.0
1515
visualize: true
@@ -47,10 +47,11 @@ renderer:
4747
visualize: true
4848
nodes: {scale: 0.2, color: {type: LabelColorAdapter}, alpha: 0.9, use_sphere: true}
4949
boundaries: {draw: true, collapse: false, wireframe_scale: 0.1, use_node_color: true, alpha: 1.0}
50+
text: {draw: true, collapse: true, adapter: {type: IdTextAdapter}, height: 0.5, scale: 0.45}
5051
edges:
51-
scale: 0.01
52-
alpha: 0.5
53-
color: {type: UniformEdgeColorAdapter}
52+
scale: 0.1
53+
alpha: 0.8
54+
color: {type: TraversabilityEdgeColorAdapter}
5455
interlayer_use_source: false
5556
interlayer_scale: 0.08
5657
interlayer_alpha: 0.4

hydra_visualizer/include/hydra_visualizer/adapters/edge_color.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,30 @@ struct ValueEdgeColorAdapter : EdgeColorAdapter {
126126

127127
void declare_config(ValueEdgeColorAdapter::Config& config);
128128

129+
struct TraversabilityEdgeColorAdapter : EdgeColorAdapter {
130+
struct Config {
131+
visualizer::RangeColormap::Config colormap{
132+
config::VirtualConfig<visualizer::ContinuousPalette>{
133+
visualizer::QualityPalette::Config()}};
134+
spark_dsg::Color active_color = spark_dsg::Color::pink();
135+
spark_dsg::Color backend_color = spark_dsg::Color::blue();
136+
} const config;
137+
138+
explicit TraversabilityEdgeColorAdapter(const Config& config);
139+
void setGraph(const spark_dsg::DynamicSceneGraph& graph,
140+
spark_dsg::LayerId layer) override;
141+
EdgeColor getColor(const spark_dsg::DynamicSceneGraph& graph,
142+
const spark_dsg::SceneGraphEdge& edge) const override;
143+
144+
private:
145+
double min_value_;
146+
double max_value_;
147+
const visualizer::RangeColormap colormap_;
148+
REGISTER_COLOR_ADAPTER(TraversabilityEdgeColorAdapter);
149+
};
150+
151+
void declare_config(TraversabilityEdgeColorAdapter::Config& config);
152+
129153
#undef REGISTER_COLOR_ADAPTER
130154

131155
} // namespace hydra

hydra_visualizer/include/hydra_visualizer/plugins/traversability_plugin.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class TraversabilityPlugin : public VisualizerPlugin {
5858
float slice_height = 2.0f;
5959

6060
//! line width of the boundary markers
61-
float line_width = 0.05f;
61+
float line_width = 0.07f;
6262
};
6363

6464
TraversabilityPlugin(const Config& config,
@@ -82,6 +82,14 @@ class TraversabilityPlugin : public VisualizerPlugin {
8282
const spark_dsg::SceneGraphLayer& layer,
8383
visualization_msgs::msg::MarkerArray& msg) const;
8484

85+
void drawBlockBoundary(const Config& config,
86+
const spark_dsg::TraversabilityNodeAttributes& attrs,
87+
visualization_msgs::msg::Marker& marker) const;
88+
89+
void drawRegionBoundary(const Config& config,
90+
const spark_dsg::TravNodeAttributes& attrs,
91+
visualization_msgs::msg::Marker& marker) const;
92+
8593
void addBoundaryPoint(const Config& config,
8694
visualization_msgs::msg::Marker& marker,
8795
const Eigen::Vector3d& point,
@@ -91,6 +99,14 @@ class TraversabilityPlugin : public VisualizerPlugin {
9199
config::DynamicConfig<Config> config_;
92100
rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr pub_;
93101
mutable MarkerTracker tracker_;
102+
103+
// Start and stop indices for the corner points of the boundary along the state
104+
// direction.
105+
inline static const std::array<std::pair<size_t, size_t>, 4> state_pairs_ = {
106+
std::make_pair(1, 0),
107+
std::make_pair(1, 2),
108+
std::make_pair(2, 3),
109+
std::make_pair(0, 3)};
94110
};
95111

96112
void declare_config(TraversabilityPlugin::Config& config);

hydra_visualizer/launch/static_visualizer.launch.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ launch:
88
- arg: {name: visualizer_config_path, default: $(find-pkg-share hydra_visualizer)/config/visualizer_config.yaml}
99
- arg: {name: visualizer_plugins_path, default: $(find-pkg-share hydra_visualizer)/config/visualizer_plugins.yaml}
1010
- arg: {name: external_plugins_path, default: $(find-pkg-share hydra_visualizer)/config/external_plugins.yaml}
11-
- arg: {name: use_color_adapter, default: 'false', description: Start visualizer using mesh color adapter}
1211
# visualizer node and control for launching
1312
- node:
1413
pkg: hydra_visualizer
@@ -22,7 +21,6 @@ launch:
2221
--config-utilities-file $(var external_plugins_path)
2322
--config-utilities-yaml {glog_level: 0, glog_verbosity: $(var verbosity)}
2423
--config-utilities-yaml {graph: {type: GraphFromFile, frame_id: $(var visualizer_frame), filepath: $(var scene_graph)}}
25-
--config-utilities-yaml {plugins: {mesh: {use_color_adapter: $(var use_color_adapter)}}}
2624
# rviz node and control for launching
2725
- arg: {name: start_rviz, default: 'true', description: automatically start rviz}
2826
- arg: {name: rviz_path, default: $(find-pkg-share hydra_visualizer)/rviz/static_visualizer.rviz, description: rviz file to load}

hydra_visualizer/launch/streaming_visualizer.launch.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ launch:
88
- arg: {name: visualizer_config_path, default: $(find-pkg-share hydra_visualizer)/config/visualizer_config.yaml}
99
- arg: {name: visualizer_plugins_path, default: $(find-pkg-share hydra_visualizer)/config/visualizer_plugins.yaml}
1010
- arg: {name: external_plugins_path, default: $(find-pkg-share hydra_visualizer)/config/external_plugins.yaml}
11-
- arg: {name: use_color_adapter, default: 'false', description: Start visualizer using mesh color adapter}
1211
# communication
1312
- arg: {name: use_zmq, default: 'false', description: use zmq to receive scene graphs}
1413
- arg: {name: visualizer_frame, default: map, description: frame ID for zmq to use}
@@ -28,7 +27,6 @@ launch:
2827
--config-utilities-file $(var external_plugins_path)
2928
--config-utilities-yaml {glog_level: 1, glog_verbosity: $(var verbosity)}
3029
--config-utilities-yaml {graph: {type: $(if $(var use_zmq) GraphFromZmq GraphFromRos), url: $(var zmq_url), frame_id: $(var visualizer_frame)}}
31-
--config-utilities-yaml {plugins: {mesh: {use_color_adapter: $(var use_color_adapter)}}}
3230
# rviz node and control for launching
3331
- arg: {name: start_rviz, default: 'true', description: automatically start rviz}
3432
- arg: {name: rviz_path, default: $(find-pkg-share hydra_visualizer)/rviz/streaming_visualizer.rviz, description: rviz file to load}

hydra_visualizer/src/adapters/edge_color.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,53 @@ void declare_config(ValueEdgeColorAdapter::Config& config) {
115115
field(config.value_functor, "value_functor");
116116
}
117117

118+
TraversabilityEdgeColorAdapter::TraversabilityEdgeColorAdapter(const Config& config)
119+
: config(config), min_value_(0.0), max_value_(1.0), colormap_(config.colormap) {}
120+
121+
void TraversabilityEdgeColorAdapter::setGraph(const DynamicSceneGraph& graph,
122+
LayerId layer) {
123+
if (!graph.hasLayer(layer)) {
124+
return;
125+
}
126+
bool is_first = true;
127+
for (const auto& [key, edge] : graph.getLayer(layer).edges()) {
128+
const auto value = edge.attributes().weight;
129+
if (value < 0.0) {
130+
continue;
131+
}
132+
if (is_first) {
133+
min_value_ = value;
134+
max_value_ = value;
135+
is_first = false;
136+
} else {
137+
min_value_ = std::min(value, min_value_);
138+
max_value_ = std::max(value, max_value_);
139+
}
140+
}
141+
}
142+
143+
EdgeColor TraversabilityEdgeColorAdapter::getColor(const DynamicSceneGraph&,
144+
const SceneGraphEdge& edge) const {
145+
const double weight = edge.attributes().weight;
146+
if (weight == -1.0) {
147+
return {config.active_color, config.active_color};
148+
}
149+
if (weight == -2.0) {
150+
return {config.backend_color, config.backend_color};
151+
}
152+
if (weight < 0.0) {
153+
return {Color::gray(), Color::gray()};
154+
}
155+
const auto color = colormap_.getColor(weight, min_value_, max_value_);
156+
return {color, color};
157+
}
158+
159+
void declare_config(TraversabilityEdgeColorAdapter::Config& config) {
160+
using namespace config;
161+
name("TraversabilityEdgeColorAdapter::Config");
162+
field(config.colormap, "colormap");
163+
field(config.active_color, "active_color");
164+
field(config.backend_color, "backend_color");
165+
}
166+
118167
} // namespace hydra

hydra_visualizer/src/plugins/traversability_plugin.cpp

Lines changed: 79 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ using spark_dsg::SceneGraphLayer;
6363
using spark_dsg::SceneGraphNode;
6464
using spark_dsg::TraversabilityNodeAttributes;
6565
using spark_dsg::TraversabilityState;
66+
using spark_dsg::TravNodeAttributes;
6667
using visualization_msgs::msg::Marker;
6768
using visualization_msgs::msg::MarkerArray;
6869

@@ -128,74 +129,96 @@ void TraversabilityPlugin::drawBoundaries(const Config& config,
128129
marker.ns = "boundaries";
129130
marker.pose.orientation.w = 1.0;
130131
marker.scale.x = config.line_width;
131-
132-
// Start and stop indices for the corner points of the boundary along the state
133-
// direction.
134-
static const std::array<std::pair<size_t, size_t>, 4> state_pairs = {
135-
std::make_pair(1, 0),
136-
std::make_pair(1, 2),
137-
std::make_pair(2, 3),
138-
std::make_pair(0, 3)};
139-
132+
marker.scale.y = config.line_width;
133+
marker.scale.z = config.line_width;
140134
for (const auto& [node_id, node] : layer.nodes()) {
141-
const auto& attrs = node->attributes<TraversabilityNodeAttributes>();
142-
143135
// Reset the marker.
144136
marker.id = id++;
145137
marker.points.clear();
146138
marker.colors.clear();
147139

148-
// Get the world frame positions of the boundary points, adjusted for the line width
149-
// for non-overlapping rendering. bot-right, bot-left, top-left, top-right
150-
std::vector<Eigen::Vector3d> pts;
151-
pts.reserve(4);
152-
pts.emplace_back(attrs.boundary.max.x() - config.line_width,
153-
attrs.boundary.min.y() + config.line_width,
154-
0);
155-
pts.emplace_back(attrs.boundary.min.x() + config.line_width,
156-
attrs.boundary.min.y() + config.line_width,
157-
0);
158-
pts.emplace_back(attrs.boundary.min.x() + config.line_width,
159-
attrs.boundary.max.y() - config.line_width,
160-
0);
161-
pts.emplace_back(attrs.boundary.max.x() - config.line_width,
162-
attrs.boundary.max.y() - config.line_width,
163-
0);
164-
for (auto& point : pts) {
165-
point += attrs.position;
166-
point.z() = config.slice_height;
140+
auto block_attrs = node->tryAttributes<TraversabilityNodeAttributes>();
141+
if (block_attrs) {
142+
drawBlockBoundary(config, *block_attrs, marker);
143+
} else {
144+
auto region_attrs = node->tryAttributes<TravNodeAttributes>();
145+
if (region_attrs) {
146+
drawRegionBoundary(config, *region_attrs, marker);
147+
}
167148
}
168149

169-
// Draw the boundary points as a line segment, where individual states break up the
170-
// line in equal parts if present.
171-
for (size_t i = 0; i < 4; ++i) {
172-
const auto& states = attrs.boundary.states[i];
173-
const size_t start = state_pairs[i].first;
174-
const size_t end = state_pairs[i].second;
175-
tf2::convert(pts[start], marker.points.emplace_back()); // First point.
176-
177-
if (states.empty()) {
178-
// Single unknown boundary.
179-
addBoundaryPoint(config, marker, pts[end], TraversabilityState::UNKNOWN, true);
180-
continue;
181-
}
150+
tracker_.add(marker, msg);
151+
}
152+
}
182153

183-
// Add line segments for continuous states.
184-
auto current_state = states[0];
185-
for (size_t j = 1; j < states.size(); ++j) {
186-
if (states[j] != current_state) {
187-
const double fraction = static_cast<double>(j) / (states.size() - 1);
188-
Eigen::Vector3d segment_point =
189-
pts[start] * (1.0 - fraction) + pts[end] * fraction;
190-
addBoundaryPoint(config, marker, segment_point, current_state);
191-
current_state = states[j];
192-
}
154+
void TraversabilityPlugin::drawBlockBoundary(
155+
const Config& config,
156+
const spark_dsg::TraversabilityNodeAttributes& attrs,
157+
visualization_msgs::msg::Marker& marker) const {
158+
// Get the world frame positions of the boundary points, adjusted for the line width
159+
// for non-overlapping rendering. bot-right, bot-left, top-left, top-right
160+
std::vector<Eigen::Vector3d> pts;
161+
pts.reserve(4);
162+
pts.emplace_back(attrs.boundary.max.x() - config.line_width,
163+
attrs.boundary.min.y() + config.line_width,
164+
0);
165+
pts.emplace_back(attrs.boundary.min.x() + config.line_width,
166+
attrs.boundary.min.y() + config.line_width,
167+
0);
168+
pts.emplace_back(attrs.boundary.min.x() + config.line_width,
169+
attrs.boundary.max.y() - config.line_width,
170+
0);
171+
pts.emplace_back(attrs.boundary.max.x() - config.line_width,
172+
attrs.boundary.max.y() - config.line_width,
173+
0);
174+
for (auto& point : pts) {
175+
point += attrs.position;
176+
point.z() = config.slice_height;
177+
}
178+
179+
// Draw the boundary points as a line segment, where individual states break up the
180+
// line in equal parts if present.
181+
for (size_t i = 0; i < 4; ++i) {
182+
const auto& states = attrs.boundary.states[i];
183+
const size_t start = state_pairs_[i].first;
184+
const size_t end = state_pairs_[i].second;
185+
tf2::convert(pts[start], marker.points.emplace_back()); // First point.
186+
187+
if (states.empty()) {
188+
// Single unknown boundary.
189+
addBoundaryPoint(config, marker, pts[end], TraversabilityState::UNKNOWN, true);
190+
continue;
191+
}
192+
193+
// Add line segments for continuous states.
194+
auto current_state = states[0];
195+
for (size_t j = 1; j < states.size(); ++j) {
196+
if (states[j] != current_state) {
197+
const double fraction = static_cast<double>(j) / (states.size() - 1);
198+
Eigen::Vector3d segment_point =
199+
pts[start] * (1.0 - fraction) + pts[end] * fraction;
200+
addBoundaryPoint(config, marker, segment_point, current_state);
201+
current_state = states[j];
193202
}
194-
addBoundaryPoint(config, marker, pts[end], current_state, true);
195203
}
204+
addBoundaryPoint(config, marker, pts[end], current_state, true);
205+
}
206+
}
196207

197-
// Wrap around the last point to the first point.
198-
tracker_.add(marker, msg);
208+
void TraversabilityPlugin::drawRegionBoundary(
209+
const Config& config,
210+
const TravNodeAttributes& attrs,
211+
visualization_msgs::msg::Marker& marker) const {
212+
marker.type = Marker::LINE_STRIP;
213+
for (size_t i = 0; i < attrs.radii.size(); ++i) {
214+
tf2::convert(attrs.getBoundaryPoint(i), marker.points.emplace_back());
215+
marker.colors.emplace_back(
216+
visualizer::makeColorMsg(config.colors[static_cast<size_t>(attrs.states[i])]));
217+
}
218+
// Close the circle.
219+
if (!attrs.radii.empty()) {
220+
marker.points.emplace_back(marker.points.front());
221+
marker.colors.emplace_back(marker.colors.front());
199222
}
200223
}
201224

0 commit comments

Comments
 (0)