lanelet2_map_server v1.2.3
Loading...
Searching...
No Matches
lanelet2_lichtblick_display::Lanelet2LichtblickDisplay Class Reference

Lanelet2LichtblickDisplay class. More...

#include <lanelet2_lichtblick_display.hpp>

Inheritance diagram for lanelet2_lichtblick_display::Lanelet2LichtblickDisplay:

Public Member Functions

 Lanelet2LichtblickDisplay ()
 Creates the Lichtblick visualization node and declares its rendering parameters.
 

Private Member Functions

template<typename T >
void declareAndLoadParameter (const std::string &name, T &param, const std::string &description, const bool add_to_auto_reconfigurable_params=true, const bool is_required=false, const bool read_only=false, const std::optional< double > &from_value=std::nullopt, const std::optional< double > &to_value=std::nullopt, const std::optional< double > &step_value=std::nullopt, const std::string &additional_constraints="")
 Declares and loads a ROS parameter.
 
rcl_interfaces::msg::SetParametersResult parametersCallback (const std::vector< rclcpp::Parameter > &parameters)
 Handles reconfiguration when a parameter value is changed.
 
void setup ()
 Sets up subscribers, publishers, etc. to configure the node.
 
void checkMapStatus ()
 Check for a new or changed Lanelet2 map and publish markers if present.
 
void hexToRgb (const std::string &hex, float &r, float &g, float &b)
 Convert a hex color string into normalized RGB float components.
 
void publishMarker (const lanelet::LaneletMapConstPtr &lanelet_map)
 Converts a Lanelet2 map into a MarkerArray and publishes it.
 
void clearAllMarkers ()
 Publishes a DELETEALL action to clear all markers from the topic.
 
void addLineStripMarker (visualization_msgs::msg::MarkerArray &marker_array_msg, int &current_marker_id, const std::string &ns, double line_width, const std::string &color_hex, double opacity, const std_msgs::msg::Header &header, const std::vector< geometry_msgs::msg::Point > &points)
 Creates and adds a LINE_STRIP marker to a marker array.
 

Static Private Member Functions

static geometry_msgs::msg::Point toRos (const Eigen::Vector3d &point)
 Converts an Eigen::Vector3d into a ROS geometry_msgs::msg::Point.
 
static void addMeshMarker (visualization_msgs::msg::MarkerArray &marker_array_msg, int &current_marker_id, const std::string &ns, const std::string &mesh_resource, const geometry_msgs::msg::Point &position, double scale, double z_offset, double opacity, const std_msgs::msg::Header &header, double yaw_ref_line, const geometry_msgs::msg::Point &middle_point)
 Creates and adds a MESH_RESOURCE marker for regulatory elements.
 
static std::optional< std::array< geometry_msgs::msg::Point, 2 > > regulatoryElementReferenceLine (const std::shared_ptr< const lanelet::RegulatoryElement > &regulatory_element)
 Extracts the reference/effect line of a regulatory element.
 
static std::vector< geometry_msgs::msg::Point > regulatoryElementPositions (const std::shared_ptr< const lanelet::RegulatoryElement > &regulatory_element)
 Extracts the sign/signal positions of a regulatory element.
 

Private Attributes

std::vector< std::tuple< std::string, std::function< void(const rclcpp::Parameter &)> > > auto_reconfigurable_params_
 Auto-reconfigurable parameters for dynamic reconfiguration.
 
OnSetParametersCallbackHandle::SharedPtr parameters_callback_
 Callback handle for dynamic parameter reconfiguration.
 
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr marker_array_publisher_
 Publisher Marker Array.
 
rclcpp::TimerBase::SharedPtr timer_
 
std::atomic< bool > need_republish_ {false}
 
std::shared_ptr< Lanelet2MapInterface > lanelet2_map_interface_
 
lanelet::LaneletMapConstPtr last_map_ptr_
 
std::string map_frame_id
 
rclcpp::Time current_timestamp
 
double left_bound_line_width_ = 0.1
 
std::string left_bound_color_hex_ = "#0000FF"
 
double left_bound_line_opacity_ = 0.5
 
double right_bound_line_width_ = 0.1
 
std::string right_bound_color_hex_ = "#FF0000"
 
double right_bound_line_opacity_ = 0.5
 
double centerline_line_width_ = 0.08
 
std::string centerline_color_hex_ = "#008000"
 
double centerline_line_opacity_ = 0.4
 
double lanelet_text_scale_ = 0.5
 
std::string lanelet_text_color_hex_ = "#000000"
 
double lanelet_text_opacity_ = 1.0
 
double reference_line_width_ = 0.2
 
std::string reference_line_color_hex_ = "#FFFF00"
 
double reference_line_opacity_ = 0.5
 
std::string traffic_light_mesh_resource_
 
double traffic_light_scale_ = 1.0
 
double traffic_light_z_offset_ = 1.3
 
double traffic_light_opacity_ = 1.0
 
std::string yield_sign_mesh_resource_
 
double yield_sign_scale_ = 1.0
 
double yield_sign_z_offset_ = 0.0
 
double yield_sign_opacity_ = 1.0
 

Detailed Description

Constructor & Destructor Documentation

◆ Lanelet2LichtblickDisplay()

lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::Lanelet2LichtblickDisplay ( )

Creates the Lichtblick visualization node and declares its rendering parameters.

Definition at line 8 of file lanelet2_lichtblick_display.cpp.

8 : Node("lanelet2_lichtblick_display") {
9 this->declareAndLoadParameter("left_bound_line_width", left_bound_line_width_, "Width of the left boundary lines", true, false,
10 false);
11 this->declareAndLoadParameter("left_bound_color_hex", left_bound_color_hex_, "Color of the left boundary lines", true, false,
12 false);
13 this->declareAndLoadParameter("left_bound_line_opacity", left_bound_line_opacity_, "Opacity of the left boundary lines", true,
14 false, false);
15
16 this->declareAndLoadParameter("right_bound_line_width", right_bound_line_width_, "Width of the right boundary lines", true,
17 false, false);
18 this->declareAndLoadParameter("right_bound_color_hex", right_bound_color_hex_, "Color of the right boundary lines", true, false,
19 false);
20 this->declareAndLoadParameter("right_bound_line_opacity", right_bound_line_opacity_, "Opacity of the right boundary lines",
21 true, false, false);
22
23 this->declareAndLoadParameter("centerline_line_width", centerline_line_width_, "Width of the centerlines", true, false, false);
24 this->declareAndLoadParameter("centerline_color_hex", centerline_color_hex_, "Color of the centerlines", true, false, false);
25 this->declareAndLoadParameter("centerline_line_opacity", centerline_line_opacity_, "Opacity of the centerlines", true, false,
26 false);
27
28 this->declareAndLoadParameter("lanelet_text_scale", lanelet_text_scale_, "Scale of the lanelet ID text", true, false, false);
29 this->declareAndLoadParameter("lanelet_text_color", lanelet_text_color_hex_, "Color of the lanelet ID text", true, false,
30 false);
31 this->declareAndLoadParameter("lanelet_text_opacity", lanelet_text_opacity_, "Opacity of the lanelet ID text", true, false,
32 false);
33
34 this->declareAndLoadParameter("reference_line_width", reference_line_width_, "Width of the reference lines", true, false,
35 false);
36 this->declareAndLoadParameter("reference_line_color_hex", reference_line_color_hex_, "Color of the reference lines", true,
37 false, false);
38 this->declareAndLoadParameter("reference_line_opacity", reference_line_opacity_, "Opacity of the reference lines", true, false,
39 false);
40
41 this->declareAndLoadParameter("traffic_light_mesh_resource", traffic_light_mesh_resource_,
42 "Link to the traffic light model to use", true, false, false);
43 this->declareAndLoadParameter("traffic_light_scale", traffic_light_scale_, "Scale of the traffic lights models", true, false,
44 false);
45 this->declareAndLoadParameter("traffic_light_z_offset", traffic_light_z_offset_,
46 "Offset in z-direction of the traffic lights models (depends on model and scale)", true, false,
47 false);
48 this->declareAndLoadParameter("traffic_light_opacity", traffic_light_opacity_, "Opacity of the traffic lights", true, false,
49 false);
50
51 this->declareAndLoadParameter("yield_sign_mesh_resource", yield_sign_mesh_resource_, "Link to the yield sign model to use",
52 true, false, false);
53 this->declareAndLoadParameter("yield_sign_scale", yield_sign_scale_, "Scale of the yield sign models", true, false, false);
54 this->declareAndLoadParameter("yield_sign_z_offset", yield_sign_z_offset_,
55 "Offset in z-direction of the yield sign models (depends on model and scale)", true, false,
56 false);
57 this->declareAndLoadParameter("yield_sign_opacity", yield_sign_opacity_, "Opacity of the yield signs", true, false, false);
58
59 this->setup();
60}
void setup()
Sets up subscribers, publishers, etc. to configure the node.
void declareAndLoadParameter(const std::string &name, T &param, const std::string &description, const bool add_to_auto_reconfigurable_params=true, const bool is_required=false, const bool read_only=false, const std::optional< double > &from_value=std::nullopt, const std::optional< double > &to_value=std::nullopt, const std::optional< double > &step_value=std::nullopt, const std::string &additional_constraints="")
Declares and loads a ROS parameter.

Member Function Documentation

◆ addLineStripMarker()

void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::addLineStripMarker ( visualization_msgs::msg::MarkerArray & marker_array_msg,
int & current_marker_id,
const std::string & ns,
double line_width,
const std::string & color_hex,
double opacity,
const std_msgs::msg::Header & header,
const std::vector< geometry_msgs::msg::Point > & points )
private

Creates and adds a LINE_STRIP marker to a marker array.

  • Encapsulates the repetitive logic for visualizing line segments. It simplifies the main publishing loop by handling all marker properties based on the provided parameters.
  • Parameters
    marker_array_msgThe marker array message to which the new marker will be added.
    current_marker_idA reference to the marker ID counter, which will be incremented.
    nsThe namespace for the marker, used for grouping in the visualization tool.
    line_widthThe width of the line in meters.
    color_hexThe hexadecimal color string.
    opacityThe opacity of the line.
    headerThe ROS header containing the frame ID and timestamp.
    pointsA vector of geometry_msgs::msg::Point objects defining the line segments.

Definition at line 220 of file lanelet2_lichtblick_display.cpp.

227 {
228 if (points.empty()) {
229 return;
230 }
231
232 visualization_msgs::msg::Marker marker;
233 marker.header = header;
234 marker.ns = ns;
235 marker.id = current_marker_id++; // give every marker a unique ID
236 marker.lifetime = rclcpp::Duration(std::chrono::milliseconds(0)); // indefinite since QoS is set to transient local
237 marker.type = visualization_msgs::msg::Marker::LINE_STRIP;
238 marker.action = visualization_msgs::msg::Marker::ADD;
239 marker.scale.x = line_width;
240
241 float r = 0.0F;
242 float g = 0.0F;
243 float b = 0.0F;
244 hexToRgb(color_hex, r, g, b);
245 marker.color.r = r;
246 marker.color.g = g;
247 marker.color.b = b;
248 marker.color.a = static_cast<float>(opacity);
249 marker.points = points;
250
251 marker_array_msg.markers.push_back(marker);
252}
void hexToRgb(const std::string &hex, float &r, float &g, float &b)
Convert a hex color string into normalized RGB float components.

◆ addMeshMarker()

void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::addMeshMarker ( visualization_msgs::msg::MarkerArray & marker_array_msg,
int & current_marker_id,
const std::string & ns,
const std::string & mesh_resource,
const geometry_msgs::msg::Point & position,
double scale,
double z_offset,
double opacity,
const std_msgs::msg::Header & header,
double yaw_ref_line,
const geometry_msgs::msg::Point & middle_point )
staticprivate

Creates and adds a MESH_RESOURCE marker for regulatory elements.

  • Streamlines the process of visualizing 3D models of traffic signs. It handles the common logic for setting marker properties, including calculating the orientation to be orthogonal to a reference line.
  • Parameters
    marker_array_msgThe marker array message to which the new marker will be added.
    current_marker_idA reference to the marker ID counter, which will be incremented.
    nsThe namespace for the marker.
    mesh_resourceThe URI of the 3D mesh model.
    positionThe base position of the mesh marker.
    scaleThe uniform scale factor for the mesh.
    z_offsetA vertical offset to correctly position the mesh above the ground.
    opacityThe opacity of the mesh marker.
    headerThe ROS header.
    yaw_ref_lineThe yaw of the reference line, used to calculate orthogonal orientation.
    middle_pointThe middle point of the reference line, used to determine orientation.

Definition at line 254 of file lanelet2_lichtblick_display.cpp.

264 {
265 visualization_msgs::msg::Marker marker;
266 marker.header = header;
267 marker.ns = ns;
268 marker.id = current_marker_id++; // give every marker a unique ID
269 marker.lifetime = rclcpp::Duration(std::chrono::milliseconds(0)); // indefinite since QoS is set to transient local
270 marker.action = visualization_msgs::msg::Marker::ADD;
271 marker.type = visualization_msgs::msg::Marker::MESH_RESOURCE;
272 marker.mesh_resource = mesh_resource;
273 // uniform scale
274 marker.scale.x = scale;
275 marker.scale.y = scale;
276 marker.scale.z = scale;
277
278 // set the position of the mesh marker (depends on scale and model)
279 geometry_msgs::msg::Point adjusted_position = position;
280 adjusted_position.z = z_offset;
281 marker.pose.position = adjusted_position;
282
283 // calculate orientation orthogonal to the reference line
284 // 1. need vector from traffic sign to the reference line
285 double dx_to_ref = middle_point.x - position.x;
286 double dy_to_ref = middle_point.y - position.y;
287 double yaw_to_ref = std::atan2(dy_to_ref, dx_to_ref);
288 // 2. two possible perpendicular orientations to the reference line
289 double cand1 = yaw_ref_line + M_PI_2; // +90°
290 double cand2 = yaw_ref_line - M_PI_2; // -90°
291 // measure angular difference (normalized) using atan2(sin,cos)
292 double d1 = std::abs(std::atan2(std::sin(yaw_to_ref - cand1), std::cos(yaw_to_ref - cand1)));
293 double d2 = std::abs(std::atan2(std::sin(yaw_to_ref - cand2), std::cos(yaw_to_ref - cand2)));
294 double final_yaw = (d1 < d2) ? cand1 : cand2;
295
296 tf2::Quaternion q;
297 q.setRPY(0, 0, final_yaw + M_PI_2);
298 marker.pose.orientation = tf2::toMsg(q);
299
300 marker.mesh_use_embedded_materials = true;
301 marker.color.a = static_cast<float>(opacity);
302
303 marker_array_msg.markers.push_back(marker);
304}

◆ checkMapStatus()

void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::checkMapStatus ( )
private

Check for a new or changed Lanelet2 map and publish markers if present.

This function queries the Lanelet2MapInterface for the current map pointer and compares it against the internally stored last_map_ptr_. If a new map is detected (pointer change and non-null), it triggers publishMarker(...) to convert the map into visualization markers.

Called periodically by the node's timer.

Definition at line 335 of file lanelet2_lichtblick_display.cpp.

335 {
336 lanelet::LaneletMapConstPtr current_map_ptr = lanelet2_map_interface_->getMapPtr();
337
338 // Check if the map has been loaded or if a new map has been received
339 if (current_map_ptr && current_map_ptr != last_map_ptr_) {
340 RCLCPP_INFO(this->get_logger(), "New Lanelet2 map detected. Publishing markers...");
341
342 map_frame_id = lanelet2_map_interface_->map_frame_id_;
343 this->clearAllMarkers();
344
345 this->publishMarker(current_map_ptr);
346 last_map_ptr_ = current_map_ptr;
347 need_republish_.store(false); // cleared after publish
348 }
349
350 // Check if parameters changed
351 if (need_republish_.load() && last_map_ptr_) {
352 RCLCPP_INFO(this->get_logger(), "Parameters changed. Republishing markers...");
354 need_republish_.store(false);
355 }
356}
void clearAllMarkers()
Publishes a DELETEALL action to clear all markers from the topic.
void publishMarker(const lanelet::LaneletMapConstPtr &lanelet_map)
Converts a Lanelet2 map into a MarkerArray and publishes it.

◆ clearAllMarkers()

void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::clearAllMarkers ( )
private

Publishes a DELETEALL action to clear all markers from the topic.

  • This function creates a single visualization_msgs::msg::Marker with the DELETEALL action and publishes it. This action signals to the visualization toolto remove all markers previously published on the topic, ensuring a clean slate for new visualizations.

Definition at line 208 of file lanelet2_lichtblick_display.cpp.

208 {
209 visualization_msgs::msg::MarkerArray marker_array_msg;
210 visualization_msgs::msg::Marker delete_marker;
211
212 delete_marker.header.frame_id = map_frame_id;
213 delete_marker.header.stamp = this->now();
214 delete_marker.action = visualization_msgs::msg::Marker::DELETEALL;
215
216 marker_array_msg.markers.push_back(delete_marker);
217 marker_array_publisher_->publish(marker_array_msg);
218}
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr marker_array_publisher_
Publisher Marker Array.

◆ declareAndLoadParameter()

template<typename T >
void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::declareAndLoadParameter ( const std::string & name,
T & param,
const std::string & description,
const bool add_to_auto_reconfigurable_params = true,
const bool is_required = false,
const bool read_only = false,
const std::optional< double > & from_value = std::nullopt,
const std::optional< double > & to_value = std::nullopt,
const std::optional< double > & step_value = std::nullopt,
const std::string & additional_constraints = "" )
private

Declares and loads a ROS parameter.

Parameters
namename
paramparameter variable to load into
descriptiondescription
add_to_auto_reconfigurable_paramsenable reconfiguration of parameter
is_requiredwhether failure to load parameter will stop node
read_onlyset parameter to read-only
from_valueparameter range minimum
to_valueparameter range maximum
step_valueparameter range step
additional_constraintsadditional constraints description

Definition at line 63 of file lanelet2_lichtblick_display.cpp.

72 {
73 rcl_interfaces::msg::ParameterDescriptor param_desc;
74 param_desc.description = description;
75 param_desc.additional_constraints = additional_constraints;
76 param_desc.read_only = read_only;
77
78 auto type = rclcpp::ParameterValue(param).get_type();
79
80 if (from_value.has_value() && to_value.has_value()) {
81 if constexpr (std::is_integral_v<T>) {
82 rcl_interfaces::msg::IntegerRange range;
83 T step = static_cast<T>(step_value.has_value() ? step_value.value() : 1);
84 range.set__from_value(static_cast<T>(from_value.value())).set__to_value(static_cast<T>(to_value.value())).set__step(step);
85 param_desc.integer_range = {range};
86 } else if constexpr (std::is_floating_point_v<T>) {
87 rcl_interfaces::msg::FloatingPointRange range;
88 T step = static_cast<T>(step_value.has_value() ? step_value.value() : 1.0);
89 range.set__from_value(static_cast<T>(from_value.value())).set__to_value(static_cast<T>(to_value.value())).set__step(step);
90 param_desc.floating_point_range = {range};
91 } else {
92 RCLCPP_WARN(this->get_logger(), "Parameter type of parameter '%s' does not support specifying a range", name.c_str());
93 }
94 }
95
96 this->declare_parameter(name, type, param_desc);
97
98 try {
99 param = this->get_parameter(name).get_value<T>();
100 std::stringstream ss;
101 ss << "Loaded parameter '" << name << "': ";
102 if constexpr (is_vector_v<T>) {
103 ss << "[";
104 for (const auto& element : param) ss << element << (&element != &param.back() ? ", " : "");
105 ss << "]";
106 } else {
107 ss << param;
108 }
109 RCLCPP_INFO_STREAM(this->get_logger(), ss.str());
110 } catch (rclcpp::exceptions::ParameterUninitializedException&) {
111 if (is_required) {
112 RCLCPP_FATAL_STREAM(this->get_logger(), "Missing required parameter '" << name << "', exiting");
113 exit(EXIT_FAILURE);
114 } else {
115 std::stringstream ss;
116 ss << "Missing parameter '" << name << "', using default value: ";
117 if constexpr (is_vector_v<T>) {
118 ss << "[";
119 for (const auto& element : param) ss << element << (&element != &param.back() ? ", " : "");
120 ss << "]";
121 } else {
122 ss << param;
123 }
124 RCLCPP_WARN_STREAM(this->get_logger(), ss.str());
125 this->set_parameters({rclcpp::Parameter(name, rclcpp::ParameterValue(param))});
126 }
127 }
128
129 if (add_to_auto_reconfigurable_params) {
130 std::function<void(const rclcpp::Parameter&)> setter = [&param](const rclcpp::Parameter& p) { param = p.get_value<T>(); };
131 auto_reconfigurable_params_.push_back(std::make_tuple(name, setter));
132 }
133}
std::vector< std::tuple< std::string, std::function< void(const rclcpp::Parameter &)> > > auto_reconfigurable_params_
Auto-reconfigurable parameters for dynamic reconfiguration.

◆ hexToRgb()

void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::hexToRgb ( const std::string & hex,
float & r,
float & g,
float & b )
private

Convert a hex color string into normalized RGB float components.

Accepted formats: "#RRGGBB", "0xRRGGBB", or "RRGGBB". If the input is invalid (wrong length or parse error), the function writes black (0,0,0) into r,g,b and logs a warning.

Definition at line 170 of file lanelet2_lichtblick_display.cpp.

170 {
171 std::string clean_hex = hex;
172 if (clean_hex.rfind("0x", 0) == 0) {
173 clean_hex = clean_hex.substr(2);
174 } else if (clean_hex.rfind("#", 0) == 0) {
175 clean_hex = clean_hex.substr(1);
176 }
177 if (clean_hex.length() != 6) {
178 RCLCPP_WARN(this->get_logger(), "Invalid hex color string: %s. Defaulting to black.", hex.c_str());
179 r = g = b = 0.0F;
180 return;
181 }
182
183 unsigned int r_int = 0U;
184 unsigned int g_int = 0U;
185 unsigned int b_int = 0U;
186
187 std::istringstream rs(clean_hex.substr(0, 2));
188 rs >> std::hex >> r_int;
189 r = static_cast<float>(r_int) / 255.0F;
190
191 std::istringstream gs(clean_hex.substr(2, 2));
192 gs >> std::hex >> g_int;
193 g = static_cast<float>(g_int) / 255.0F;
194
195 std::istringstream bs(clean_hex.substr(4, 2));
196 bs >> std::hex >> b_int;
197 b = static_cast<float>(b_int) / 255.0F;
198}

◆ parametersCallback()

rcl_interfaces::msg::SetParametersResult lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::parametersCallback ( const std::vector< rclcpp::Parameter > & parameters)
private

Handles reconfiguration when a parameter value is changed.

Parameters
parametersparameters
Returns
parameter change result

Definition at line 135 of file lanelet2_lichtblick_display.cpp.

136 {
137 for (const auto& param : parameters) {
138 for (auto& auto_reconfigurable_param : auto_reconfigurable_params_) {
139 if (param.get_name() == std::get<0>(auto_reconfigurable_param)) {
140 std::get<1>(auto_reconfigurable_param)(param);
141 RCLCPP_INFO(this->get_logger(), "Reconfigured parameter '%s'", param.get_name().c_str());
142 need_republish_.store(true);
143 break;
144 }
145 }
146 }
147
148 rcl_interfaces::msg::SetParametersResult result;
149 result.successful = true;
150
151 return result;
152}

◆ publishMarker()

void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::publishMarker ( const lanelet::LaneletMapConstPtr & lanelet_map)
private

Converts a Lanelet2 map into a MarkerArray and publishes it.

This function iterates over lanelets in lanelet_map and creates markers for the various elements. The marker array is published on the marker_array_publisher_ which is configured with transient_local QoS so late joiners receive the last message.

Parameters
lanelet_maplanelet map to visualize

Definition at line 358 of file lanelet2_lichtblick_display.cpp.

358 {
359 if (lanelet_map->laneletLayer.empty()) {
360 RCLCPP_WARN(this->get_logger(), "Lanelet2 map is empty.");
361 return;
362 }
363 visualization_msgs::msg::MarkerArray marker_array_msg;
364 int current_marker_id = 0;
365 rclcpp::Time current_timestamp = this->now();
366
367 std_msgs::msg::Header header;
368 header.frame_id = map_frame_id;
369 header.stamp = current_timestamp;
370 float r = 0.0F;
371 float g = 0.0F;
372 float b = 0.0F;
373
374 // Iterate through all lanelets in the map
375 for (const auto& lanelet : lanelet_map->laneletLayer) {
376 // --- Visualize Lines ---
377 std::vector<geometry_msgs::msg::Point> left_points, right_points, centerline_points;
378 for (const auto& p : lanelet.leftBound()) left_points.push_back(toRos(p.basicPoint()));
379 for (const auto& p : lanelet.rightBound()) right_points.push_back(toRos(p.basicPoint()));
380 for (const auto& p : lanelet.centerline()) centerline_points.push_back(toRos(p.basicPoint()));
381
382 addLineStripMarker(marker_array_msg, current_marker_id, "lanelet_left_boundaries", left_bound_line_width_,
383 left_bound_color_hex_, left_bound_line_opacity_, header, left_points);
384 addLineStripMarker(marker_array_msg, current_marker_id, "lanelet_right_boundaries", right_bound_line_width_,
386 addLineStripMarker(marker_array_msg, current_marker_id, "lanelet_centerlines", centerline_line_width_, centerline_color_hex_,
387 centerline_line_opacity_, header, centerline_points);
388
389 // --- Visualize Lanelet ID Text ---
390 if (!lanelet.centerline().empty()) {
391 visualization_msgs::msg::Marker text_marker;
392 text_marker.header.frame_id = map_frame_id;
393 text_marker.header.stamp = current_timestamp;
394 text_marker.ns = "lanelet_ids";
395 text_marker.id = current_marker_id++;
396 text_marker.action = visualization_msgs::msg::Marker::ADD;
397 text_marker.lifetime = rclcpp::Duration(std::chrono::milliseconds(0));
398 text_marker.type = visualization_msgs::msg::Marker::TEXT_VIEW_FACING;
399
400 // position the text at the geometric center of the lanelet's centerline
401 geometry_msgs::msg::Point centerline_center;
402 double sum_x = 0.0, sum_y = 0.0, sum_z = 0.0;
403 for (const auto& p : lanelet.centerline()) {
404 sum_x += p.x();
405 sum_y += p.y();
406 sum_z += p.z();
407 }
408 if (!lanelet.centerline().empty()) {
409 const auto centerline_size = static_cast<double>(lanelet.centerline().size());
410 centerline_center.x = sum_x / centerline_size;
411 centerline_center.y = sum_y / centerline_size;
412 centerline_center.z = sum_z / centerline_size;
413 }
414 text_marker.pose.position = centerline_center;
415 text_marker.scale.z = lanelet_text_scale_; // For TEXT_VIEW_FACING, scale.z controls the character height
416
418 text_marker.color.r = r;
419 text_marker.color.g = g;
420 text_marker.color.b = b;
421 text_marker.color.a = static_cast<float>(lanelet_text_opacity_);
422
423 text_marker.text = std::to_string(lanelet.id());
424
425 marker_array_msg.markers.push_back(text_marker);
426 }
427
428 const auto& regulatory_elements = lanelet.regulatoryElements();
429 for (const auto& regulatory_element : regulatory_elements) {
430 // Check if the element is a reference line
431 if (auto reference_line = regulatoryElementReferenceLine(regulatory_element)) {
432 std::vector<geometry_msgs::msg::Point> ref_points = {reference_line->at(0), reference_line->at(1)};
433 addLineStripMarker(marker_array_msg, current_marker_id, "reference_lines", reference_line_width_,
435
436 // Common regulatory element logic
437 // https://github.com/fzi-forschungszentrum-informatik/Lanelet2/blob/master/lanelet2_core/doc/RegulatoryElementTagging.md
438 std::string subtype = regulatory_element->attribute("subtype").value();
439 double dx = reference_line->at(1).x - reference_line->at(0).x;
440 double dy = reference_line->at(1).y - reference_line->at(0).y;
441 double yaw_ref_line = std::atan2(dy, dx);
442 geometry_msgs::msg::Point middle_point;
443 middle_point.x = (reference_line->at(0).x + reference_line->at(1).x) / 2.0;
444 middle_point.y = (reference_line->at(0).y + reference_line->at(1).y) / 2.0;
445
446 std::vector<geometry_msgs::msg::Point> positions = regulatoryElementPositions(regulatory_element);
447 for (const auto& p : positions) {
448 if (subtype == "traffic_light") {
449 addMeshMarker(marker_array_msg, current_marker_id, "traffic_lights", traffic_light_mesh_resource_, p,
451 middle_point);
452 } else if (subtype == "right_of_way") {
453 addMeshMarker(marker_array_msg, current_marker_id, "yield_signs", yield_sign_mesh_resource_, p, yield_sign_scale_,
454 yield_sign_z_offset_, yield_sign_opacity_, header, yaw_ref_line, middle_point);
455 }
456 }
457 }
458 }
459 }
460
461 // Publish the marker array
462 marker_array_publisher_->publish(marker_array_msg);
463}
static void addMeshMarker(visualization_msgs::msg::MarkerArray &marker_array_msg, int &current_marker_id, const std::string &ns, const std::string &mesh_resource, const geometry_msgs::msg::Point &position, double scale, double z_offset, double opacity, const std_msgs::msg::Header &header, double yaw_ref_line, const geometry_msgs::msg::Point &middle_point)
Creates and adds a MESH_RESOURCE marker for regulatory elements.
static geometry_msgs::msg::Point toRos(const Eigen::Vector3d &point)
Converts an Eigen::Vector3d into a ROS geometry_msgs::msg::Point.
static std::optional< std::array< geometry_msgs::msg::Point, 2 > > regulatoryElementReferenceLine(const std::shared_ptr< const lanelet::RegulatoryElement > &regulatory_element)
Extracts the reference/effect line of a regulatory element.
void addLineStripMarker(visualization_msgs::msg::MarkerArray &marker_array_msg, int &current_marker_id, const std::string &ns, double line_width, const std::string &color_hex, double opacity, const std_msgs::msg::Header &header, const std::vector< geometry_msgs::msg::Point > &points)
Creates and adds a LINE_STRIP marker to a marker array.
static std::vector< geometry_msgs::msg::Point > regulatoryElementPositions(const std::shared_ptr< const lanelet::RegulatoryElement > &regulatory_element)
Extracts the sign/signal positions of a regulatory element.

◆ regulatoryElementPositions()

std::vector< geometry_msgs::msg::Point > lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::regulatoryElementPositions ( const std::shared_ptr< const lanelet::RegulatoryElement > & regulatory_element)
staticprivate

Extracts the sign/signal positions of a regulatory element.

Only the first point of referenced line strings is considered.

Parameters
[in]regulatory_elementregulatory element
Returns
positions

Definition at line 321 of file lanelet2_lichtblick_display.cpp.

322 {
323 std::vector<geometry_msgs::msg::Point> positions;
324 const std::vector<lanelet::ConstLineString3d> sign_lines =
325 regulatory_element->getParameters<lanelet::ConstLineString3d>(lanelet::RoleName::Refers);
326 for (const auto& const_sign_line : sign_lines) {
327 const std::vector<Eigen::Vector3d> sign_line = const_sign_line.basicLineString();
328 if (!sign_line.empty()) {
329 positions.push_back(toRos(sign_line.front()));
330 }
331 }
332 return positions;
333}

◆ regulatoryElementReferenceLine()

std::optional< std::array< geometry_msgs::msg::Point, 2 > > lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::regulatoryElementReferenceLine ( const std::shared_ptr< const lanelet::RegulatoryElement > & regulatory_element)
staticprivate

Extracts the reference/effect line of a regulatory element.

Only the first reference line of the regulatory element is considered. Only the end points of that reference line are considered.

Parameters
[in]regulatory_elementregulatory element
Returns
reference line

Definition at line 306 of file lanelet2_lichtblick_display.cpp.

307 {
308 const std::vector<lanelet::ConstLineString3d> reference_lines =
309 regulatory_element->getParameters<lanelet::ConstLineString3d>(lanelet::RoleName::RefLine);
310 if (reference_lines.empty()) {
311 return std::nullopt;
312 }
313 const std::vector<Eigen::Vector3d> reference_line = reference_lines.front().basicLineString();
314 if (reference_line.size() < 2) {
315 return std::nullopt;
316 }
317 std::array<geometry_msgs::msg::Point, 2> reference_line_ros = {toRos(reference_line.front()), toRos(reference_line.back())};
318 return reference_line_ros;
319}

◆ setup()

void lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::setup ( )
private

Sets up subscribers, publishers, etc. to configure the node.

Definition at line 154 of file lanelet2_lichtblick_display.cpp.

154 {
155 // callback for dynamic parameter configuration
156 parameters_callback_ = this->add_on_set_parameters_callback(
157 std::bind(&Lanelet2LichtblickDisplay::parametersCallback, this, std::placeholders::_1));
158
159 // publisher for visualization markers
160 auto qos = rclcpp::QoS(rclcpp::KeepLast(1)).transient_local();
161 marker_array_publisher_ = this->create_publisher<visualization_msgs::msg::MarkerArray>("~/lichtblick_lanelet2_map", qos);
162 RCLCPP_INFO(this->get_logger(), "Publishing to '%s' with transient_local QoS", marker_array_publisher_->get_topic_name());
163
164 lanelet2_map_interface_ = std::make_shared<Lanelet2MapInterface>(*this, "lanelet2_map_server");
165
166 // periodically check for map updates
167 timer_ = this->create_wall_timer(std::chrono::milliseconds(2000), std::bind(&Lanelet2LichtblickDisplay::checkMapStatus, this));
168}
void checkMapStatus()
Check for a new or changed Lanelet2 map and publish markers if present.
OnSetParametersCallbackHandle::SharedPtr parameters_callback_
Callback handle for dynamic parameter reconfiguration.
rcl_interfaces::msg::SetParametersResult parametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Handles reconfiguration when a parameter value is changed.

◆ toRos()

geometry_msgs::msg::Point lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::toRos ( const Eigen::Vector3d & point)
staticprivate

Converts an Eigen::Vector3d into a ROS geometry_msgs::msg::Point.

Simple helper to copy x, y, z components from Eigen to the ROS message.

Parameters
pointEigen 3D point
Returns
geometry_msgs::msg::Point ROS point message

Definition at line 200 of file lanelet2_lichtblick_display.cpp.

200 {
201 geometry_msgs::msg::Point ros_point;
202 ros_point.x = point.x();
203 ros_point.y = point.y();
204 ros_point.z = point.z();
205 return ros_point;
206}

Member Data Documentation

◆ auto_reconfigurable_params_

std::vector<std::tuple<std::string, std::function<void(const rclcpp::Parameter&)> > > lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::auto_reconfigurable_params_
private

Auto-reconfigurable parameters for dynamic reconfiguration.

Definition at line 208 of file lanelet2_lichtblick_display.hpp.

◆ centerline_color_hex_

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::centerline_color_hex_ = "#008000"
private

Definition at line 240 of file lanelet2_lichtblick_display.hpp.

◆ centerline_line_opacity_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::centerline_line_opacity_ = 0.4
private

Definition at line 241 of file lanelet2_lichtblick_display.hpp.

◆ centerline_line_width_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::centerline_line_width_ = 0.08
private

Definition at line 239 of file lanelet2_lichtblick_display.hpp.

◆ current_timestamp

rclcpp::Time lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::current_timestamp
private

Definition at line 228 of file lanelet2_lichtblick_display.hpp.

◆ lanelet2_map_interface_

std::shared_ptr<Lanelet2MapInterface> lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::lanelet2_map_interface_
private

Definition at line 224 of file lanelet2_lichtblick_display.hpp.

◆ lanelet_text_color_hex_

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::lanelet_text_color_hex_ = "#000000"
private

Definition at line 244 of file lanelet2_lichtblick_display.hpp.

◆ lanelet_text_opacity_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::lanelet_text_opacity_ = 1.0
private

Definition at line 245 of file lanelet2_lichtblick_display.hpp.

◆ lanelet_text_scale_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::lanelet_text_scale_ = 0.5
private

Definition at line 243 of file lanelet2_lichtblick_display.hpp.

◆ last_map_ptr_

lanelet::LaneletMapConstPtr lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::last_map_ptr_
private

Definition at line 225 of file lanelet2_lichtblick_display.hpp.

◆ left_bound_color_hex_

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::left_bound_color_hex_ = "#0000FF"
private

Definition at line 232 of file lanelet2_lichtblick_display.hpp.

◆ left_bound_line_opacity_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::left_bound_line_opacity_ = 0.5
private

Definition at line 233 of file lanelet2_lichtblick_display.hpp.

◆ left_bound_line_width_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::left_bound_line_width_ = 0.1
private

Definition at line 231 of file lanelet2_lichtblick_display.hpp.

◆ map_frame_id

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::map_frame_id
private

Definition at line 226 of file lanelet2_lichtblick_display.hpp.

◆ marker_array_publisher_

rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::marker_array_publisher_
private

Publisher Marker Array.

Definition at line 218 of file lanelet2_lichtblick_display.hpp.

◆ need_republish_

std::atomic<bool> lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::need_republish_ {false}
private

Definition at line 222 of file lanelet2_lichtblick_display.hpp.

222{false};

◆ parameters_callback_

OnSetParametersCallbackHandle::SharedPtr lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::parameters_callback_
private

Callback handle for dynamic parameter reconfiguration.

Definition at line 213 of file lanelet2_lichtblick_display.hpp.

◆ reference_line_color_hex_

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::reference_line_color_hex_ = "#FFFF00"
private

Definition at line 248 of file lanelet2_lichtblick_display.hpp.

◆ reference_line_opacity_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::reference_line_opacity_ = 0.5
private

Definition at line 249 of file lanelet2_lichtblick_display.hpp.

◆ reference_line_width_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::reference_line_width_ = 0.2
private

Definition at line 247 of file lanelet2_lichtblick_display.hpp.

◆ right_bound_color_hex_

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::right_bound_color_hex_ = "#FF0000"
private

Definition at line 236 of file lanelet2_lichtblick_display.hpp.

◆ right_bound_line_opacity_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::right_bound_line_opacity_ = 0.5
private

Definition at line 237 of file lanelet2_lichtblick_display.hpp.

◆ right_bound_line_width_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::right_bound_line_width_ = 0.1
private

Definition at line 235 of file lanelet2_lichtblick_display.hpp.

◆ timer_

rclcpp::TimerBase::SharedPtr lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::timer_
private

Definition at line 220 of file lanelet2_lichtblick_display.hpp.

◆ traffic_light_mesh_resource_

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::traffic_light_mesh_resource_
private

Definition at line 251 of file lanelet2_lichtblick_display.hpp.

◆ traffic_light_opacity_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::traffic_light_opacity_ = 1.0
private

Definition at line 254 of file lanelet2_lichtblick_display.hpp.

◆ traffic_light_scale_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::traffic_light_scale_ = 1.0
private

Definition at line 252 of file lanelet2_lichtblick_display.hpp.

◆ traffic_light_z_offset_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::traffic_light_z_offset_ = 1.3
private

Definition at line 253 of file lanelet2_lichtblick_display.hpp.

◆ yield_sign_mesh_resource_

std::string lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::yield_sign_mesh_resource_
private

Definition at line 256 of file lanelet2_lichtblick_display.hpp.

◆ yield_sign_opacity_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::yield_sign_opacity_ = 1.0
private

Definition at line 259 of file lanelet2_lichtblick_display.hpp.

◆ yield_sign_scale_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::yield_sign_scale_ = 1.0
private

Definition at line 257 of file lanelet2_lichtblick_display.hpp.

◆ yield_sign_z_offset_

double lanelet2_lichtblick_display::Lanelet2LichtblickDisplay::yield_sign_z_offset_ = 0.0
private

Definition at line 258 of file lanelet2_lichtblick_display.hpp.


The documentation for this class was generated from the following files: