Skip to content

Commit 8b085b2

Browse files
Feature/mesh point plugin (#57)
* add ability to extend layer visualizations with plugins * (wip) turn on point plugin for objects * make node draw config field do something * add dsg publisher from file * Specialize mesh point code by attribute type * Revert config changes * turn 2d place visualization back on
1 parent 5efef46 commit 8b085b2

14 files changed

Lines changed: 434 additions & 9 deletions

hydra_ros/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ install(
115115
install(TARGETS hydra_ros_node RUNTIME DESTINATION lib/${PROJECT_NAME})
116116
install(
117117
PROGRAMS app/csv_to_tf
118+
app/dsg_file_publisher
118119
app/dsg_republisher
119120
app/odom_to_tf
120121
app/noisy_tf_publisher

hydra_ros/app/dsg_file_publisher

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python3
2+
"""Script that loads and publishes a dsg from a file."""
3+
4+
import argparse
5+
import pathlib
6+
7+
import rclpy
8+
import spark_dsg as dsg
9+
import std_msgs.msg
10+
from rclpy.node import Node
11+
12+
import hydra_ros
13+
14+
15+
class DsgFilePublisher(Node):
16+
"""Node that loads and publishes a DSG from file."""
17+
18+
def __init__(
19+
self,
20+
filepath,
21+
frame: str = "map",
22+
publish_rate: float = 0.0,
23+
publish_with_mesh: bool = True,
24+
):
25+
"""Load and send the DSG."""
26+
super().__init__("dsg_file_publisher")
27+
filepath = pathlib.Path(filepath).expanduser().absolute()
28+
if not filepath.exists():
29+
self.get_logger().fatal(f"File '{filepath}' does not exist!")
30+
raise ValueError(f"invalid file {filepath}")
31+
32+
self._frame = frame
33+
self.get_logger().info(f"Loading '{filepath}'...")
34+
self._graph = dsg.DynamicSceneGraph.load(filepath)
35+
self.get_logger().info(f"Loaded '{filepath}'!")
36+
self._pub = hydra_ros.DsgPublisher(self, "dsg")
37+
if publish_rate > 0.0:
38+
self._timer = self._create_timer(1.0 / publish_rate, self._send_graph)
39+
else:
40+
self._send_graph()
41+
42+
def _send_graph(self):
43+
header = std_msgs.msg.Header()
44+
header.stamp = self.get_clock().now().to_msg()
45+
header.frame_id = self._frame
46+
self._pub.publish_with_header(self._graph, header)
47+
48+
49+
def main(args=None):
50+
"""Start and run node."""
51+
parser = argparse.ArgumentParser("Node that publishes a 3SDG from a file")
52+
parser.add_argument("filepath")
53+
parser.add_argument("--publish_rate", default=0.0, help="rate to publish")
54+
parser.add_argument("--frame", "-f", default="map", help="frame ID for publishing")
55+
args, rest = parser.parse_known_args()
56+
rclpy.init(args=rest)
57+
58+
try:
59+
node = DsgFilePublisher(
60+
args.filepath, frame=args.frame, publish_rate=args.publish_rate
61+
)
62+
rclpy.spin(node)
63+
node.destroy_node()
64+
finally:
65+
rclpy.utilities.try_shutdown()
66+
67+
68+
if __name__ == "__main__":
69+
main()

hydra_visualizer/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ find_package(visualization_msgs REQUIRED)
2929

3030
add_library(
3131
${PROJECT_NAME}
32-
src/plugins/traversability_plugin.cpp
3332
src/adapters/edge_color.cpp
3433
src/adapters/mesh_color.cpp
3534
src/adapters/node_color.cpp
@@ -46,8 +45,10 @@ add_library(
4645
src/plugins/footprint_plugin.cpp
4746
src/plugins/khronos_object_plugin.cpp
4847
src/plugins/mesh_plugin.cpp
48+
src/plugins/mesh_point_plugin.cpp
4949
src/plugins/places_freespace_plugin.cpp
5050
src/plugins/pose_plugin.cpp
51+
src/plugins/traversability_plugin.cpp
5152
src/scene_graph_renderer.cpp
5253
src/utils/ear_clipping.cpp
5354
src/utils/layer_key_selector.cpp

hydra_visualizer/config/visualizer_config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ renderer:
66
2:
77
z_offset_scale: 2.0
88
visualize: true
9-
nodes: {scale: 0.40, color: {type: LabelColorAdapter}, alpha: 0.8, use_sphere: false}
9+
nodes: {draw: true, 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}
1212
3:
@@ -43,3 +43,4 @@ renderer:
4343
- {from: 3*, to: 2p*, draw: false}
4444
- {from: 3*, to: 2, use_child_color: true, scale: 0.08, alpha: 0.5}
4545
- {from: 4, to: 3*, scale: 0.08, alpha: 0.4}
46+
layer_plugins: []

hydra_visualizer/include/hydra_visualizer/color/colormap_utilities.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ enum class NamedColors {
5757

5858
spark_dsg::Color colorFromName(NamedColors color);
5959

60+
void fillColorMsg(const spark_dsg::Color& color, std_msgs::msg::ColorRGBA& msg);
61+
6062
std_msgs::msg::ColorRGBA makeColorMsg(const spark_dsg::Color& color,
6163
std::optional<double> alpha = std::nullopt);
6264

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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+
#include <spark_dsg/dynamic_scene_graph.h>
37+
38+
#include <visualization_msgs/msg/marker_array.hpp>
39+
40+
#include "hydra_visualizer/layer_info.h"
41+
#include "hydra_visualizer/utils/marker_tracker.h"
42+
43+
namespace hydra {
44+
45+
struct LayerPlugin {
46+
public:
47+
using Ptr = std::unique_ptr<LayerPlugin>;
48+
49+
virtual ~LayerPlugin() = default;
50+
51+
virtual void draw(const std_msgs::msg::Header& header,
52+
const visualizer::LayerInfo& info,
53+
const spark_dsg::SceneGraphLayer& layer,
54+
const spark_dsg::Mesh* mesh,
55+
visualization_msgs::msg::MarkerArray& msg,
56+
MarkerTracker& tracker) = 0;
57+
58+
virtual bool hasChange() const { return has_change_; }
59+
60+
virtual void clearChangeFlag() { has_change_ = false; }
61+
62+
protected:
63+
bool has_change_ = false;
64+
};
65+
66+
} // namespace hydra
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
39+
#include "hydra_visualizer/plugins/layer_plugin.h"
40+
41+
namespace hydra {
42+
43+
/**
44+
* @brief Plugin to draw mesh points that comprise a node
45+
*
46+
* Works for 2D places or objects
47+
*/
48+
class MeshPointPlugin : public LayerPlugin {
49+
public:
50+
struct Config {
51+
//! Draw size for mesh points
52+
double point_size = 0.02;
53+
//! Use spheres for mesh points instead of cubes
54+
bool use_spheres = false;
55+
//! Use the node color instead of the mesh color
56+
bool use_node_color = true;
57+
//! Alpha for mesh points
58+
double alpha = 1.0;
59+
};
60+
61+
MeshPointPlugin(const Config& config, const std::string& ns);
62+
63+
void draw(const std_msgs::msg::Header& header,
64+
const visualizer::LayerInfo& info,
65+
const spark_dsg::SceneGraphLayer& layer,
66+
const spark_dsg::Mesh* mesh,
67+
visualization_msgs::msg::MarkerArray& msg,
68+
MarkerTracker& tracker) override;
69+
70+
private:
71+
std::string ns_;
72+
config::DynamicConfig<Config> config_;
73+
};
74+
75+
void declare_config(MeshPointPlugin::Config& config);
76+
77+
} // namespace hydra

hydra_visualizer/include/hydra_visualizer/scene_graph_renderer.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <visualization_msgs/msg/marker_array.hpp>
4141

4242
#include "hydra_visualizer/layer_info.h"
43+
#include "hydra_visualizer/plugins/layer_plugin.h"
4344
#include "hydra_visualizer/utils/layer_key_selector.h"
4445
#include "hydra_visualizer/utils/marker_tracker.h"
4546

@@ -68,6 +69,11 @@ class SceneGraphRenderer {
6869
using LayerConfigWrapper = config::DynamicConfig<visualizer::LayerConfig>;
6970
using EdgeConfigWrapper = config::DynamicConfig<InterlayerEdgeConfig>;
7071

72+
struct LayerPluginsConfig {
73+
spark_dsg::LayerKey layer;
74+
std::vector<config::VirtualConfig<LayerPlugin, true>> plugins;
75+
};
76+
7177
struct Config {
7278
//! @brief Overall graph config
7379
GraphRenderConfig graph;
@@ -83,6 +89,8 @@ class SceneGraphRenderer {
8389
};
8490
//! @brief Configuration for interlayer edges
8591
std::vector<InterlayerEdges> interlayer_edges;
92+
//! @brief Extra per-layer plugins
93+
std::vector<LayerPluginsConfig> layer_plugins;
8694
};
8795

8896
explicit SceneGraphRenderer(const Config& config, ianvs::NodeHandle nh);
@@ -124,6 +132,7 @@ class SceneGraphRenderer {
124132
ianvs::NodeHandle nh_;
125133
config::DynamicConfig<GraphRenderConfig> graph_config_;
126134
rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr pub_;
135+
std::map<spark_dsg::LayerKey, std::list<LayerPlugin::Ptr>> layer_plugins_;
127136

128137
mutable MarkerTracker tracker_;
129138
mutable std::atomic<bool> has_change_;
@@ -132,6 +141,7 @@ class SceneGraphRenderer {
132141
mutable std::map<std::string, std::unique_ptr<EdgeConfigWrapper>> interlayer_edges_;
133142
};
134143

144+
void declare_config(SceneGraphRenderer::LayerPluginsConfig& config);
135145
void declare_config(SceneGraphRenderer::Config& config);
136146

137147
} // namespace hydra

hydra_visualizer/include/hydra_visualizer/utils/layer_key_selector.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,12 @@ struct SelectorConversion {
7070
std::string& error);
7171
};
7272

73+
struct LayerKeyConversion {
74+
static std::string toIntermediate(const spark_dsg::LayerKey& value,
75+
std::string& error);
76+
static void fromIntermediate(const std::string& intermediate,
77+
spark_dsg::LayerKey& value,
78+
std::string& error);
79+
};
80+
7381
} // namespace hydra

hydra_visualizer/src/color/colormap_utilities.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,15 @@ spark_dsg::Color colorFromName(NamedColors color) {
120120
}
121121
}
122122

123-
std_msgs::msg::ColorRGBA makeColorMsg(const Color& color, std::optional<double> alpha) {
124-
std_msgs::msg::ColorRGBA msg;
123+
void fillColorMsg(const Color& color, std_msgs::msg::ColorRGBA& msg) {
125124
msg.r = static_cast<double>(color.r) / 255.0;
126125
msg.g = static_cast<double>(color.g) / 255.0;
127126
msg.b = static_cast<double>(color.b) / 255.0;
127+
}
128+
129+
std_msgs::msg::ColorRGBA makeColorMsg(const Color& color, std::optional<double> alpha) {
130+
std_msgs::msg::ColorRGBA msg;
131+
fillColorMsg(color, msg);
128132
msg.a = alpha.value_or(static_cast<double>(color.a) / 255.0);
129133
return msg;
130134
}

0 commit comments

Comments
 (0)