21 namespace std_ph = std::placeholders;
26 double compute_2d_distance(
const geometry_msgs::msg::Point& pt1,
const geometry_msgs::msg::Point& pt2)
28 double dx = pt2.x - pt1.x;
29 double dy = pt2.y - pt1.y;
30 double dz = pt2.z - pt1.z;
32 return sqrt(dx * dx + dy * dy + dz * dz);
37 : carma_ros2_utils::CarmaLifecycleNode(options)
59 get_parameter<double>(
"x",
config_.
x);
60 get_parameter<double>(
"y",
config_.
y);
61 get_parameter<double>(
"z",
config_.
z);
62 get_parameter<double>(
"t",
config_.
t);
66 RCLCPP_INFO_STREAM(get_logger(),
"Loaded params "<<
config_);
69 host_marker_pub_ = create_publisher<visualization_msgs::msg::MarkerArray>(
"host_marker", 1);
70 cav_marker_pub_ = create_publisher<visualization_msgs::msg::MarkerArray>(
"cav_marker", 1);
71 label_marker_pub_ = create_publisher<visualization_msgs::msg::MarkerArray>(
"label_marker", 1);
74 host_mob_path_sub_ = create_subscription<carma_v2x_msgs::msg::MobilityPath>(
"mobility_path_msg", 10,
77 cav_mob_path_sub_ = create_subscription<carma_v2x_msgs::msg::MobilityPath>(
"incoming_mobility_path", 10,
80 georeference_sub_ = create_subscription<std_msgs::msg::String>(
"georeference", 10,
84 return CallbackReturn::SUCCESS;
93 return CallbackReturn::SUCCESS;
124 map_projector_ = std::make_shared<lanelet::projection::LocalFrameProjector>(msg->data.c_str());
131 RCLCPP_DEBUG_STREAM(get_logger(),
"Received a msg from sender: " << msg->m_header.sender_id <<
", and plan id:" << msg->m_header.plan_id <<
", for receiver:"
132 << msg->m_header.recipient_id <<
", time:" << msg->m_header.timestamp <<
", at now: " <<
std::to_string(this->now().seconds()));
138 RCLCPP_DEBUG_STREAM(get_logger(),
"Already received this plan id:" << msg->m_header.plan_id <<
"from sender_id: " << msg->m_header.sender_id);
144 RCLCPP_ERROR(get_logger(),
"Cannot visualize mobility path as map projection not yet available");
148 if (msg->m_header.timestamp == 0)
157 cav_color.
green = 1.0;
162 RCLCPP_DEBUG_STREAM(get_logger(),
"Composed host marker successfuly!");
167 cav_color.
blue = 1.0;
170 RCLCPP_DEBUG_STREAM(get_logger(),
"Composed cav marker successfuly! with sender_id: " << msg->m_header.sender_id);
177 visualization_msgs::msg::MarkerArray output;
179 visualization_msgs::msg::Marker marker;
180 marker.header.frame_id =
"map";
182 rclcpp::Time marker_header_stamp = rclcpp::Time((msg.m_header.timestamp/1000.0) * 1e9);
183 marker.header.stamp = builtin_interfaces::msg::Time(marker_header_stamp);
184 marker.type = visualization_msgs::msg::Marker::ARROW;
185 marker.action = visualization_msgs::msg::Marker::ADD;
186 marker.ns =
"mobilitypath_visualizer";
191 marker.frame_locked =
true;
193 marker.color.r = (float)color.
red;
194 marker.color.g = (
float)color.
green;
195 marker.color.b = (float)color.
blue;
196 marker.color.a = 1.0f;
200 auto curr_location_msg = msg;
203 geometry_msgs::msg::Point arrow_start;
204 geometry_msgs::msg::Point arrow_end;
206 if (msg.trajectory.offsets.empty())
208 marker.action = visualization_msgs::msg::Marker::DELETE;
212 RCLCPP_DEBUG_STREAM(get_logger(),
"ECEF point x: " << curr_location_msg.trajectory.location.ecef_x <<
", y:" << curr_location_msg.trajectory.location.ecef_y);
213 arrow_start =
ECEFToMapPoint(curr_location_msg.trajectory.location);
214 RCLCPP_DEBUG_STREAM(get_logger(),
"Map point x: " << arrow_start.x <<
", y:" << arrow_start.y);
216 curr_location_msg.trajectory.location.ecef_x += + msg.trajectory.offsets[0].offset_x;
217 curr_location_msg.trajectory.location.ecef_y += + msg.trajectory.offsets[0].offset_y;
218 curr_location_msg.trajectory.location.ecef_z += + msg.trajectory.offsets[0].offset_z;
219 arrow_end =
ECEFToMapPoint(curr_location_msg.trajectory.location);
221 marker.points.push_back(arrow_start);
222 marker.points.push_back(arrow_end);
225 output.markers.push_back(marker);
227 for (
size_t i = 1;
i < count;
i++)
230 rclcpp::Time marker_cur_time(marker.header.stamp);
232 rclcpp::Time updated_time = marker_cur_time + rclcpp::Duration(0.1 * 1e9);
233 marker.header.stamp = builtin_interfaces::msg::Time(updated_time);
235 if (
i >= msg.trajectory.offsets.size()) {
236 marker.action = visualization_msgs::msg::Marker::DELETE;
237 output.markers.push_back(marker);
242 RCLCPP_DEBUG_STREAM(get_logger(),
"ECEF Point- DEBUG x: " << curr_location_msg.trajectory.location.ecef_x <<
", y:" << curr_location_msg.trajectory.location.ecef_y);
243 arrow_start =
ECEFToMapPoint(curr_location_msg.trajectory.location);
244 RCLCPP_DEBUG_STREAM(get_logger(),
"Map Point- DEBUG x: " << arrow_start.x <<
", y:" << arrow_start.y);
246 curr_location_msg.trajectory.location.ecef_x += msg.trajectory.offsets[
i].offset_x;
247 curr_location_msg.trajectory.location.ecef_y += msg.trajectory.offsets[
i].offset_y;
248 curr_location_msg.trajectory.location.ecef_z += msg.trajectory.offsets[
i].offset_z;
249 arrow_end =
ECEFToMapPoint(curr_location_msg.trajectory.location);
251 marker.points.push_back(arrow_start);
252 marker.points.push_back(arrow_end);
254 output.markers.push_back(marker);
256 RCLCPP_DEBUG_STREAM(get_logger(),
"Last ECEF Point- DEBUG x: " << curr_location_msg.trajectory.location.ecef_x <<
", y:" << curr_location_msg.trajectory.location.ecef_y);
257 RCLCPP_DEBUG_STREAM(get_logger(),
"Last Map Point- DEBUG x: " << arrow_end.x <<
", y:" << arrow_end.y);
267 throw std::invalid_argument(
"No map projector available for ecef conversion");
269 geometry_msgs::msg::Point output;
271 lanelet::BasicPoint3d map_point =
map_projector_->projectECEF( { (double)ecef_point.ecef_x/100.0, (
double)ecef_point.ecef_y/100.0, (double)ecef_point.ecef_z/100.0 } , -1);
272 output.x = map_point.x();
273 output.y = map_point.y();
274 output.z = map_point.z();
282 visualization_msgs::msg::MarkerArray output;
283 visualization_msgs::msg::Marker marker;
284 marker.header.frame_id =
"map";
285 marker.type = visualization_msgs::msg::Marker::TEXT_VIEW_FACING;
286 marker.action = visualization_msgs::msg::Marker::ADD;
287 marker.ns =
"mobilitypath_visualizer";
292 marker.color.r = 1.0;
293 marker.color.g = 1.0;
294 marker.color.b = 1.0;
295 marker.color.a = 1.0;
296 marker.frame_locked =
true;
297 marker.lifetime = builtin_interfaces::msg::Duration((rclcpp::Duration(
config_.
t * 1e9)));
299 for (
auto const& cav_marker: cav_markers)
302 while(idx < host_marker.markers.size() && idx < cav_marker.markers.size())
304 if (
compute_2d_distance(cav_marker.markers[idx].points[0], host_marker.markers[idx].points[0]) <= 1.0)
306 marker.id = (int32_t)idx;
307 marker.header.stamp = host_marker.markers[idx].header.stamp;
308 marker.pose.position.x = cav_marker.markers[idx].points[0].x;
309 marker.pose.position.y = cav_marker.markers[idx].points[0].y;
310 marker.pose.position.z = cav_marker.markers[idx].points[0].z;
311 marker.pose.orientation.w = 1.0f;
313 std::string collision_time =
std::to_string((rclcpp::Time(cav_marker.markers[idx].header.stamp) - rclcpp::Time(host_marker.markers[0].header.stamp)).seconds());
314 collision_time = collision_time.substr(0,collision_time.size() - 4);
315 marker.text =
"Collision in " + collision_time +
"s!";
317 output.markers.push_back(marker);
322 if (
compute_2d_distance(cav_marker.markers[idx-1].points[1], host_marker.markers[idx-1].points[1]) <= 1.0)
325 marker.id = (int32_t)idx;
326 marker.header.stamp = host_marker.markers[idx-1].header.stamp;
327 marker.pose.position.x = cav_marker.markers[idx-1].points[1].x;
328 marker.pose.position.y = cav_marker.markers[idx-1].points[1].y;
329 marker.pose.position.z = cav_marker.markers[idx-1].points[1].z;
331 rclcpp::Time cav_marker_stamp(cav_marker.markers[idx-1].header.stamp);
332 rclcpp::Time host_marker_stamp(host_marker.markers[0].header.stamp);
333 rclcpp::Duration duration = cav_marker_stamp - host_marker_stamp;
335 collision_time = collision_time.substr(0,collision_time.size() - 4);
336 marker.text =
"Collision in " + collision_time +
"s!";
337 output.markers.push_back(marker);
345 const std::vector<visualization_msgs::msg::MarkerArray>& cav_markers)
const
347 if (host_marker.markers.empty() || host_marker.markers[0].action == visualization_msgs::msg::Marker::DELETE)
350 std::vector<visualization_msgs::msg::MarkerArray> synchronized_output;
351 for (
auto const& curr_cav: cav_markers)
353 visualization_msgs::msg::MarkerArray synchronized_marker_array;
354 signed int curr_idx = 0;
355 double time_step = 0.1;
359 if (rclcpp::Time(curr_cav.markers[0].header.stamp) > rclcpp::Time(host_marker.markers[0].header.stamp) ||
360 curr_cav.markers[0].action == visualization_msgs::msg::Marker::DELETE)
366 rclcpp::Time curr_cav_marker_stamp(curr_cav.markers.back().header.stamp);
367 rclcpp::Time host_marker_stamp(host_marker.markers[0].header.stamp);
370 if (curr_cav_marker_stamp + rclcpp::Duration(time_step * 1e9) < host_marker_stamp){
375 while (curr_idx < curr_cav.markers.size() && rclcpp::Time(curr_cav.markers[curr_idx].header.stamp) <= rclcpp::Time(host_marker.markers[0].header.stamp))
386 double dt = (rclcpp::Time(host_marker.markers[0].header.stamp) - rclcpp::Time(curr_cav.markers[curr_idx].header.stamp)).seconds();
388 rclcpp::Time curr_time(host_marker.markers[0].header.stamp);
392 while (curr_idx < curr_cav.markers.size())
394 if (curr_cav.markers[curr_idx].action == visualization_msgs::msg::Marker::DELETE)
397 visualization_msgs::msg::Marker curr_marker = curr_cav.markers[curr_idx];
398 if (dt != 0.0 && !curr_cav.markers[curr_idx].points.empty())
400 double dx = (curr_cav.markers[curr_idx].points[1].x - curr_cav.markers[curr_idx].points[0].x)/time_step * dt;
401 double dy = (curr_cav.markers[curr_idx].points[1].y - curr_cav.markers[curr_idx].points[0].y)/time_step * dt;
402 double dz = (curr_cav.markers[curr_idx].points[1].z - curr_cav.markers[curr_idx].points[0].z)/time_step * dt;
404 curr_marker.points[0].x += dx;
405 curr_marker.points[0].y += dy;
406 curr_marker.points[0].z += dz;
409 curr_marker.header.stamp = curr_time;
410 synchronized_marker_array.markers.push_back(curr_marker);
412 curr_time += rclcpp::Duration(time_step, 0.0);
419 while (curr_idx < synchronized_marker_array.markers.size()-1)
421 if (curr_cav.markers[curr_idx].action == visualization_msgs::msg::Marker::DELETE)
424 if (!synchronized_marker_array.markers[curr_idx].points.empty())
425 synchronized_marker_array.markers[curr_idx].points[1] = synchronized_marker_array.markers[curr_idx + 1].points[0];
429 if (!synchronized_marker_array.markers[curr_idx].points.empty())
432 double dx = (synchronized_marker_array.markers[curr_idx].points[1].x - synchronized_marker_array.markers[curr_idx].points[0].x)/(time_step - dt) * time_step;
433 double dy = (synchronized_marker_array.markers[curr_idx].points[1].y - synchronized_marker_array.markers[curr_idx].points[0].y)/(time_step - dt) * time_step;
434 double dz = (synchronized_marker_array.markers[curr_idx].points[1].z - synchronized_marker_array.markers[curr_idx].points[0].z)/(time_step - dt) * time_step;
436 synchronized_marker_array.markers[curr_idx].points[1].x = synchronized_marker_array.markers[curr_idx].points[0].x + dx;
437 synchronized_marker_array.markers[curr_idx].points[1].y = synchronized_marker_array.markers[curr_idx].points[0].y + dy;
438 synchronized_marker_array.markers[curr_idx].points[1].z = synchronized_marker_array.markers[curr_idx].points[0].z + dz;
442 synchronized_output.push_back(synchronized_marker_array);
446 return synchronized_output;
450#include "rclcpp_components/register_node_macro.hpp"
rclcpp::TimerBase::SharedPtr timer_
carma_ros2_utils::PubPtr< visualization_msgs::msg::MarkerArray > label_marker_pub_
visualization_msgs::msg::MarkerArray composeLabelMarker(const visualization_msgs::msg::MarkerArray &host_marker, const std::vector< visualization_msgs::msg::MarkerArray > &cav_markers) const
Compose a label marker that displays whether if any of the cav's path cross with that of host (respec...
std::unordered_map< std::string, carma_v2x_msgs::msg::MobilityPath > latest_cav_mob_path_msg_
carma_ros2_utils::CallbackReturn handle_on_configure(const rclcpp_lifecycle::State &)
carma_ros2_utils::SubPtr< carma_v2x_msgs::msg::MobilityPath > cav_mob_path_sub_
carma_ros2_utils::SubPtr< std_msgs::msg::String > georeference_sub_
visualization_msgs::msg::MarkerArray host_marker_
std::vector< visualization_msgs::msg::MarkerArray > matchTrajectoryTimestamps(const visualization_msgs::msg::MarkerArray &host_marker, const std::vector< visualization_msgs::msg::MarkerArray > &cav_markers) const
Matches timestamps of CAV's individual points of cav_markers to that of host_marker and interpolates ...
std::unordered_map< std::string, size_t > prev_marker_list_size_
carma_ros2_utils::PubPtr< visualization_msgs::msg::MarkerArray > cav_marker_pub_
visualization_msgs::msg::MarkerArray label_marker_
bool host_marker_received_
MobilityPathVisualizer(const rclcpp::NodeOptions &)
Constructor.
std::vector< visualization_msgs::msg::MarkerArray > cav_markers_
carma_ros2_utils::CallbackReturn handle_on_activate(const rclcpp_lifecycle::State &)
geometry_msgs::msg::Point ECEFToMapPoint(const carma_v2x_msgs::msg::LocationECEF &ecef_point) const
Accepts ECEF point in cm to convert to a point in map in meters.
visualization_msgs::msg::MarkerArray composeVisualizationMarker(const carma_v2x_msgs::msg::MobilityPath &msg, const MarkerColor &color)
Compose a visualization marker for mobilitypath messages.
void callbackMobilityPath(carma_v2x_msgs::msg::MobilityPath::UniquePtr msg)
std::shared_ptr< lanelet::projection::LocalFrameProjector > map_projector_
void georeferenceCallback(std_msgs::msg::String::UniquePtr msg)
Callback for map projection string to define lat/lon -> map conversion.
std::string georeference_
carma_ros2_utils::PubPtr< visualization_msgs::msg::MarkerArray > host_marker_pub_
carma_ros2_utils::SubPtr< carma_v2x_msgs::msg::MobilityPath > host_mob_path_sub_
auto to_string(const UtmZone &zone) -> std::string
double compute_2d_distance(const geometry_msgs::msg::Point &pt1, const geometry_msgs::msg::Point &pt2)
Stuct containing the algorithm configuration values for <package_name>