Skip to content

Commit 7de8f39

Browse files
Schmluknathanhhughes
authored andcommitted
Port/traversability (#35)
* port traversability visualization, builds * fix segfaults * run linting on all files * address review comments
1 parent 6853db3 commit 7de8f39

File tree

13 files changed

+660
-16
lines changed

13 files changed

+660
-16
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,6 @@ pyrightconfig.json
214214
.vscode/
215215

216216
.clangd
217+
218+
# ROS2
219+
log/

hydra_ros/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ add_library(
4141
src/frontend/object_visualizer.cpp
4242
src/frontend/places_visualizer.cpp
4343
src/frontend/ros_frontend_publisher.cpp
44+
src/frontend/traversability_visualizer.cpp
4445
src/input/feature_receiver.cpp
4546
src/input/image_receiver.cpp
4647
src/input/pointcloud_adaptor.cpp
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* -----------------------------------------------------------------------------
2+
* Copyright 2022 Massachusetts Institute of Technology.
3+
* All Rights Reserved
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*
26+
* Research was sponsored by the United States Air Force Research Laboratory and
27+
* the United States Air Force Artificial Intelligence Accelerator and was
28+
* accomplished under Cooperative Agreement Number FA8750-19-2-1000. The views
29+
* and conclusions contained in this document are those of the authors and should
30+
* not be interpreted as representing the official policies, either expressed or
31+
* implied, of the United States Air Force or the U.S. Government. The U.S.
32+
* Government is authorized to reproduce and distribute reprints for Government
33+
* purposes notwithstanding any copyright notation herein.
34+
* -------------------------------------------------------------------------- */
35+
#pragma once
36+
37+
#include <config_utilities/dynamic_config.h>
38+
#include <hydra/frontend/traversability_place_extractor.h>
39+
#include <hydra_visualizer/color/colormap_utilities.h>
40+
#include <ianvs/node_handle.h>
41+
42+
#include <mutex>
43+
44+
#include <visualization_msgs/msg/marker.hpp>
45+
46+
namespace hydra {
47+
48+
class TraversabilityVisualizer : public places::TraversabilityPlaceExtractor::Sink {
49+
public:
50+
struct Config {
51+
//! Namespace to use for the visualizer node.
52+
std::string ns = "~/traversability";
53+
//! Colormap to use for traversability values.
54+
visualizer::RangeColormap::Config traversability_colormap{
55+
createSpectrumColormap({spark_dsg::Color::red(),
56+
spark_dsg::Color::yellow(),
57+
spark_dsg::Color::green()})};
58+
//! Colormap to use for confidence values.
59+
visualizer::RangeColormap::Config confidence_colormap{
60+
createSpectrumColormap({spark_dsg::Color::black(),
61+
spark_dsg::Color::blue(),
62+
spark_dsg::Color::cyan()})};
63+
//! Colors to use for the different traversability states (unknown, traversable,
64+
//! intraversable, traversed).
65+
std::vector<spark_dsg::Color> state_colors{spark_dsg::Color::black(),
66+
spark_dsg::Color::blue(),
67+
spark_dsg::Color::red(),
68+
spark_dsg::Color::green()};
69+
//! Height where the slice is visualized [m].
70+
float drawing_offset_z = 0.0f;
71+
//! True: Use height relative to the robot, false: use absolute height.
72+
bool use_relative_offset = true;
73+
//! Alpha value to use for the voxel colors.
74+
double alpha = 0.3;
75+
};
76+
77+
explicit TraversabilityVisualizer(const Config& config);
78+
79+
virtual ~TraversabilityVisualizer() = default;
80+
81+
std::string printInfo() const override;
82+
83+
void call(uint64_t timestamp_ns,
84+
const Eigen::Vector3d& world_t_body,
85+
const places::TraversabilityLayer& layer) const override;
86+
87+
protected:
88+
config::DynamicConfig<Config> config_;
89+
Config active_config_; // Current config to use for a call.
90+
mutable std::mutex config_mutex_;
91+
ianvs::NodeHandle nh_;
92+
rclcpp::Publisher<visualization_msgs::msg::Marker>::SharedPtr layer_pub_;
93+
std::unique_ptr<visualizer::RangeColormap> traversability_colormap_;
94+
std::unique_ptr<visualizer::RangeColormap> confidence_colormap_;
95+
96+
void visualizeLayer(const std_msgs::msg::Header& header,
97+
const Eigen::Vector3d& world_t_body,
98+
const places::TraversabilityLayer& layer) const;
99+
100+
static visualizer::RangeColormap::Config createSpectrumColormap(
101+
std::vector<spark_dsg::Color> colors);
102+
103+
Color debugColor(float value) const;
104+
105+
void onConfigUpdate();
106+
107+
private:
108+
inline static const auto registration_ =
109+
config::RegistrationWithConfig<places::TraversabilityPlaceExtractor::Sink,
110+
TraversabilityVisualizer,
111+
Config>("TraversabilityVisualizer");
112+
};
113+
114+
void declare_config(TraversabilityVisualizer::Config& config);
115+
116+
} // namespace hydra

hydra_ros/src/frontend/places_visualizer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
#include <rclcpp/time.hpp>
4646

47+
#include "hydra_ros/frontend/gvd_visualization_utilities.h"
4748
#include "hydra_ros/visualizer/voxel_drawing.h"
4849

4950
namespace hydra {
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/* -----------------------------------------------------------------------------
2+
* Copyright 2022 Massachusetts Institute of Technology.
3+
* All Rights Reserved
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*
26+
* Research was sponsored by the United States Air Force Research Laboratory and
27+
* the United States Air Force Artificial Intelligence Accelerator and was
28+
* accomplished under Cooperative Agreement Number FA8750-19-2-1000. The views
29+
* and conclusions contained in this document are those of the authors and should
30+
* not be interpreted as representing the official policies, either expressed or
31+
* implied, of the United States Air Force or the U.S. Government. The U.S.
32+
* Government is authorized to reproduce and distribute reprints for Government
33+
* purposes notwithstanding any copyright notation herein.
34+
* -------------------------------------------------------------------------- */
35+
#include "hydra_ros/frontend/traversability_visualizer.h"
36+
37+
#include <config_utilities/config.h>
38+
#include <config_utilities/printing.h>
39+
#include <config_utilities/validation.h>
40+
#include <hydra/common/global_info.h>
41+
#include <hydra_visualizer/color/color_parsing.h>
42+
#include <hydra_visualizer/color/colormap_utilities.h>
43+
#include <spark_dsg/colormaps.h>
44+
45+
#include "hydra_ros/frontend/gvd_visualization_utilities.h"
46+
#include "hydra_ros/visualizer/voxel_drawing.h"
47+
48+
namespace hydra {
49+
50+
using visualization_msgs::msg::Marker;
51+
using visualization_msgs::msg::MarkerArray;
52+
using visualizer::ContinuousPalette;
53+
using visualizer::DivergentPalette;
54+
using visualizer::RangeColormap;
55+
56+
void declare_config(TraversabilityVisualizer::Config& config) {
57+
using namespace config;
58+
name("TraversabilityVisualizer::Config");
59+
field(config.ns, "ns");
60+
field(config.traversability_colormap, "traversability_colormap");
61+
field(config.confidence_colormap, "confidence_colormap");
62+
field(config.state_colors, "state_colors");
63+
field(config.drawing_offset_z, "drawing_offset_z", "m");
64+
field(config.use_relative_offset, "use_relative_offset");
65+
check(config.state_colors.size(), EQ, 4, "state_colors");
66+
}
67+
68+
TraversabilityVisualizer::TraversabilityVisualizer(const Config& config)
69+
: config_("traversability_visualizer",
70+
config::checkValid(config),
71+
[this]() { onConfigUpdate(); }),
72+
nh_(ianvs::NodeHandle::this_node(config.ns)),
73+
layer_pub_(nh_.create_publisher<visualization_msgs::msg::Marker>("layer", 10)) {
74+
onConfigUpdate();
75+
}
76+
77+
visualizer::RangeColormap::Config TraversabilityVisualizer::createSpectrumColormap(
78+
std::vector<spark_dsg::Color> colors) {
79+
visualizer::RangeColormap::Config config;
80+
config.palette = visualizer::SpectrumPalette::Config{std::move(colors)};
81+
return config;
82+
}
83+
84+
std::string TraversabilityVisualizer::printInfo() const {
85+
return config::toString(active_config_);
86+
}
87+
88+
void TraversabilityVisualizer::onConfigUpdate() {
89+
std::lock_guard<std::mutex> lock(config_mutex_);
90+
active_config_ = config_.get();
91+
traversability_colormap_ = std::make_unique<visualizer::RangeColormap>(
92+
active_config_.traversability_colormap);
93+
confidence_colormap_ =
94+
std::make_unique<visualizer::RangeColormap>(active_config_.confidence_colormap);
95+
}
96+
97+
void TraversabilityVisualizer::call(uint64_t timestamp_ns,
98+
const Eigen::Vector3d& world_t_body,
99+
const places::TraversabilityLayer& layer) const {
100+
std_msgs::msg::Header header;
101+
header.frame_id = GlobalInfo::instance().getFrames().map;
102+
header.stamp = rclcpp::Time(timestamp_ns);
103+
std::lock_guard<std::mutex> lock(config_mutex_);
104+
visualizeLayer(header, world_t_body, layer);
105+
}
106+
107+
void TraversabilityVisualizer::visualizeLayer(
108+
const std_msgs::msg::Header& header,
109+
const Eigen::Vector3d& world_t_body,
110+
const places::TraversabilityLayer& layer) const {
111+
visualization_msgs::msg::Marker msg;
112+
msg.header = header;
113+
msg.action = visualization_msgs::msg::Marker::ADD;
114+
msg.id = 0;
115+
msg.ns = "traversability";
116+
msg.type = visualization_msgs::msg::Marker::CUBE_LIST;
117+
msg.scale.x = layer.voxel_size;
118+
msg.scale.y = layer.voxel_size;
119+
msg.scale.z = layer.voxel_size;
120+
msg.pose.orientation.w = 1.0;
121+
122+
visualization_msgs::msg::Marker msg2 = msg;
123+
msg2.ns = "confidence";
124+
125+
visualization_msgs::msg::Marker msg3 = msg;
126+
msg3.ns = "state";
127+
128+
visualization_msgs::msg::Marker msg4 = msg;
129+
msg4.ns = "debug";
130+
131+
auto height = active_config_.drawing_offset_z;
132+
if (active_config_.use_relative_offset) {
133+
height += world_t_body.z();
134+
}
135+
geometry_msgs::msg::Point pos;
136+
pos.z = height;
137+
138+
for (const auto& block : layer) {
139+
for (size_t x = 0; x < block.voxels_per_side; ++x) {
140+
pos.x = block.origin().x() + (x + 0.5f) * layer.voxel_size;
141+
for (size_t y = 0; y < block.voxels_per_side; ++y) {
142+
const auto& voxel = block.voxel(x, y);
143+
if (voxel.confidence <= 0.0f) {
144+
continue; // Unobserved voxels.
145+
}
146+
pos.y = block.origin().y() + (y + 0.5f) * layer.voxel_size;
147+
msg.points.push_back(pos);
148+
msg.colors.push_back(visualizer::makeColorMsg(
149+
traversability_colormap_->getColor(voxel.traversability),
150+
active_config_.alpha));
151+
msg2.colors.push_back(visualizer::makeColorMsg(
152+
confidence_colormap_->getColor(voxel.confidence), active_config_.alpha));
153+
msg3.colors.push_back(visualizer::makeColorMsg(
154+
active_config_.state_colors[static_cast<uint8_t>(voxel.state)],
155+
active_config_.alpha));
156+
msg4.colors.push_back(visualizer::makeColorMsg(debugColor(voxel.debug_value),
157+
active_config_.alpha));
158+
}
159+
}
160+
}
161+
msg2.points = msg.points;
162+
msg3.points = msg.points;
163+
msg4.points = msg.points;
164+
165+
layer_pub_->publish(msg);
166+
layer_pub_->publish(msg2);
167+
layer_pub_->publish(msg3);
168+
layer_pub_->publish(msg4);
169+
}
170+
171+
Color TraversabilityVisualizer::debugColor(float value) const {
172+
// Connected components.
173+
if (value < 0.0f) {
174+
return Color::black();
175+
}
176+
return spark_dsg::colormaps::rainbowId(static_cast<int>(value), 5);
177+
}
178+
179+
} // namespace hydra

hydra_visualizer/CMakeLists.txt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,30 @@ find_package(visualization_msgs REQUIRED)
2929

3030
add_library(
3131
${PROJECT_NAME}
32-
src/drawing.cpp
33-
src/layer_info.cpp
34-
src/scene_graph_renderer.cpp
35-
src/visualizer_node.cpp
32+
src/plugins/traversability_plugin.cpp
3633
src/adapters/graph_color.cpp
3734
src/adapters/mesh_color.cpp
3835
src/adapters/text.cpp
3936
src/color/colormap_utilities.cpp
37+
src/drawing.cpp
38+
src/groundtruth/bounding_box_publisher.cpp
39+
src/groundtruth/region_publisher.cpp
4040
src/io/graph_file_wrapper.cpp
4141
src/io/graph_ros_wrapper.cpp
4242
src/io/graph_zmq_wrapper.cpp
43-
src/groundtruth/region_publisher.cpp
44-
src/groundtruth/bounding_box_publisher.cpp
43+
src/layer_info.cpp
4544
src/plugins/basis_point_plugin.cpp
46-
src/plugins/places_freespace_plugin.cpp
45+
src/plugins/footprint_plugin.cpp
4746
src/plugins/khronos_object_plugin.cpp
4847
src/plugins/mesh_plugin.cpp
49-
src/plugins/footprint_plugin.cpp
48+
src/plugins/places_freespace_plugin.cpp
5049
src/plugins/pose_plugin.cpp
50+
src/scene_graph_renderer.cpp
5151
src/utils/ear_clipping.cpp
5252
src/utils/marker_group_pub.cpp
5353
src/utils/marker_tracker.cpp
5454
src/utils/polygon_utilities.cpp
55+
src/visualizer_node.cpp
5556
)
5657
target_include_directories(
5758
${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"

hydra_visualizer/config/visualizer_plugins.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ plugins:
1313
khronos_objects:
1414
type: KhronosObjectPlugin
1515
dynamic_color_mode: CONSTANT # ID, SEMANTIC, CONSTANT
16+
places_traversability:
17+
type: TraversabilityPlugin
1618
agent_poses:
1719
type: PosePlugin
1820
num_to_skip: 0

hydra_visualizer/include/hydra_visualizer/adapters/text.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,14 @@ struct NameIdTextAdapter : GraphTextAdapter {
9999

100100
void declare_config(NameIdTextAdapter::Config& config);
101101

102+
struct AttributesTextAdaptor : GraphTextAdapter {
103+
struct Config {};
104+
explicit AttributesTextAdaptor(const Config&) {}
105+
virtual ~AttributesTextAdaptor() = default;
106+
std::string getText(const spark_dsg::DynamicSceneGraph& graph,
107+
const spark_dsg::SceneGraphNode& node) const override;
108+
};
109+
110+
void declare_config(AttributesTextAdaptor::Config& config);
111+
102112
} // namespace hydra::visualizer

hydra_visualizer/include/hydra_visualizer/color/colormap_utilities.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,9 @@ struct RangeColormap {
166166
} const config;
167167

168168
explicit RangeColormap(const Config& config);
169-
spark_dsg::Color getColor(double value, double min, double max) const;
170-
spark_dsg::Color operator()(double value, double min, double max) const {
169+
170+
spark_dsg::Color getColor(double value, double min = 0.0, double max = 1.0) const;
171+
spark_dsg::Color operator()(double value, double min = 0.0, double max = 1.0) const {
171172
return getColor(value, min, max);
172173
}
173174

0 commit comments

Comments
 (0)