Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
MapUpdateLoggerNode.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 LEIDOS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17#include <rclcpp/rclcpp.hpp>
18#include <functional>
19#include <autoware_lanelet2_msgs/msg/map_bin.hpp>
20#include <carma_v2x_msgs/msg/traffic_control_request.hpp>
21#include <carma_ros2_utils/carma_ros2_utils.hpp>
22#include <autoware_lanelet2_ros2_interface/utility/message_conversion.hpp>
24#include <carma_debug_ros2_msgs/msg/map_update_readable.hpp>
25#include <carma_debug_ros2_msgs/msg/lanelet_id_regulatory_element_pair.hpp>
26#include <boost/uuid/uuid.hpp>
27#include <boost/uuid/uuid_io.hpp>
28#include <boost/variant.hpp>
29#include <memory>
30#include <lanelet2_extension/regulatory_elements/DigitalMinimumGap.h>
31#include <lanelet2_extension/regulatory_elements/DigitalSpeedLimit.h>
32#include <lanelet2_extension/regulatory_elements/DirectionOfTravel.h>
33#include <lanelet2_extension/regulatory_elements/PassingControlLine.h>
34#include <lanelet2_extension/regulatory_elements/RegionAccessRule.h>
35#include <lanelet2_extension/regulatory_elements/StopRule.h>
36#include <iostream>
37
47class MapUpdateLogger : public rclcpp::Node
48{
49 public:
50 MapUpdateLogger(const rclcpp::NodeOptions& options);
51
52 private:
53 rclcpp::Publisher<carma_debug_ros2_msgs::msg::MapUpdateReadable>::SharedPtr readable_pub_;
54 rclcpp::Subscription<autoware_lanelet2_msgs::msg::MapBin>::SharedPtr update_sub_;
55
63 carma_debug_ros2_msgs::msg::LaneletIdRegulatoryElementPair pairToDebugMessage(const std::pair<lanelet::Id, lanelet::RegulatoryElementPtr>& id_reg_pair);
64
72 carma_debug_ros2_msgs::msg::MapUpdateReadable mapUpdateCallback(const autoware_lanelet2_msgs::msg::MapBin& update);
73
74 void raw_callback(const autoware_lanelet2_msgs::msg::MapBin::SharedPtr msg) {
75 readable_pub_->publish(mapUpdateCallback(*msg));
76 }
77};
78
79MapUpdateLogger::MapUpdateLogger(const rclcpp::NodeOptions& options)
80 : Node("map_update_logger")
81{
82 // Setup publishers
83
84 // NOTE: Currently, intra-process comms must be disabled for publishers that are transient_local: https://github.com/ros2/rclcpp/issues/1753
85 rclcpp::PublisherOptions readable_pub_options;
86 readable_pub_options.use_intra_process_comm = rclcpp::IntraProcessSetting::Disable; // Disable intra-process comms for the map update debug publisher
87
88 auto readable_pub_qos = rclcpp::QoS(rclcpp::KeepAll()); // A publisher with this QoS will store all messages that it has sent on the topic
89 readable_pub_qos.transient_local(); // A publisher with this QoS will re-send all (when KeepAll is used) messages to all late-joining subscribers
90 // NOTE: The subscriber's QoS must be set to transisent_local() as well for earlier messages to be resent to the later-joiner.
91
92 // Create map update debug publisher, which will send all previously published messages to late-joining subscribers ONLY If the subscriber is transient_local too
93 readable_pub_ = this->create_publisher<carma_debug_ros2_msgs::msg::MapUpdateReadable>("map_update_debug", readable_pub_qos, readable_pub_options);
94
95 // Setup subscribers
96
97 // NOTE: Currently, intra-process comms must be disabled for subcribers that are transient_local: https://github.com/ros2/rclcpp/issues/1753
98 rclcpp::SubscriptionOptions update_sub_options;
99 update_sub_options.use_intra_process_comm = rclcpp::IntraProcessSetting::Disable; // Disable intra-process comms for this SubscriptionOptions object
100
101 auto update_sub_qos = rclcpp::QoS(rclcpp::KeepLast(100)); // Set the queue size for a subscriber with this QoS
102 update_sub_qos.transient_local(); // If it is possible that this node is a late-joiner to its topic, it must be set to transient_local to receive earlier messages that were missed.
103 // NOTE: The publisher's QoS must be set to transisent_local() as well for earlier messages to be resent to this later-joiner.
104
105 // Create map update subscriber that will receive earlier messages that were missed ONLY if the publisher is transient_local too
106 update_sub_ = this->create_subscription<autoware_lanelet2_msgs::msg::MapBin>("/environment/map_update", update_sub_qos,
107 std::bind(&MapUpdateLogger::raw_callback, this, std::placeholders::_1), update_sub_options);
108}
109
110carma_debug_ros2_msgs::msg::LaneletIdRegulatoryElementPair MapUpdateLogger::pairToDebugMessage(const std::pair<lanelet::Id, lanelet::RegulatoryElementPtr>& id_reg_pair) {
111 carma_debug_ros2_msgs::msg::LaneletIdRegulatoryElementPair pair;
112 pair.lanelet_id = std::get<0>(id_reg_pair);
113 auto element = std::get<1>(id_reg_pair);
114 std::string rule_name = element->attribute(lanelet::AttributeName::Subtype).value();
115 pair.element.rule_name = rule_name;
116
117 if (rule_name.compare("digital_minimum_gap") == 0) {
118
119 auto cast = std::static_pointer_cast<lanelet::DigitalMinimumGap>(element);
120 pair.element.min_gap = cast->getMinimumGap();
121 pair.element.participants.insert(pair.element.participants.begin(), cast->participants_.begin(), cast->participants_.end());
122
123 } else if (rule_name.compare("digital_speed_limit") == 0) {
124
125 auto cast = std::static_pointer_cast<lanelet::DigitalSpeedLimit>(element);
126 pair.element.speed_limit = cast->getSpeedLimit().value();
127 pair.element.participants.insert(pair.element.participants.begin(), cast->participants_.begin(), cast->participants_.end());
128
129 } else if (rule_name.compare("direction_of_travel") == 0) {
130
131 auto cast = std::static_pointer_cast<lanelet::DirectionOfTravel>(element);
132 pair.element.direction = cast->direction_;
133 pair.element.participants.insert(pair.element.participants.begin(), cast->participants_.begin(), cast->participants_.end());
134
135 } else if (rule_name.compare("passing_control_line") == 0) {
136
137 auto cast = std::static_pointer_cast<lanelet::PassingControlLine>(element);
138 pair.element.left_participants.insert(pair.element.left_participants.begin(), cast->left_participants_.begin(), cast->left_participants_.end());
139 pair.element.right_participants.insert(pair.element.right_participants.begin(), cast->right_participants_.begin(), cast->right_participants_.end());
140
141 } else if (rule_name.compare("region_access_rule") == 0) {
142
143 auto cast = std::static_pointer_cast<lanelet::RegionAccessRule>(element);
144 pair.element.reason = cast->getReason();
145 pair.element.participants.insert(pair.element.participants.begin(), cast->participants_.begin(), cast->participants_.end());
146
147 } else if (rule_name.compare("stop_rule") == 0) {
148
149 auto cast = std::static_pointer_cast<lanelet::StopRule>(element);
150 pair.element.participants.insert(pair.element.participants.begin(), cast->participants_.begin(), cast->participants_.end());
151
152 } else {
153
154 RCLCPP_WARN_STREAM(rclcpp::get_logger("map_update_debug"), "MapUpdateLogger recieved unsupported regulatory element in map update.");
155 pair.element.unsupported_type = true;
156
157 }
158 return pair;
159}
160
161
162carma_debug_ros2_msgs::msg::MapUpdateReadable MapUpdateLogger::mapUpdateCallback(const autoware_lanelet2_msgs::msg::MapBin& update) {
163
164 RCLCPP_INFO_STREAM(get_logger(), "Recieved map update ");
165
166 auto control = std::make_shared<carma_wm::TrafficControl>(carma_wm::TrafficControl());
167 carma_wm::fromBinMsg(update, control);
168
169 carma_debug_ros2_msgs::msg::MapUpdateReadable msg;
170 msg.header = update.header;
171 msg.format_version = update.format_version;
172 msg.map_version = update.map_version;
173 msg.route_id = update.route_id;
174 msg.route_version = update.route_version;
175 msg.invalidates_route = update.invalidates_route;
176
177 msg.traffic_control_id = boost::lexical_cast<std::string>(control->id_);
178
179 for (auto id_reg_pair : control->update_list_) {
180
181 msg.update_list.push_back(pairToDebugMessage(id_reg_pair));
182 }
183
184 for (auto id_reg_pair : control->remove_list_) {
185
186 msg.remove_list.push_back(pairToDebugMessage(id_reg_pair));
187 }
188
189 return msg;
190}
191
192#include "rclcpp_components/register_node_macro.hpp"
193
194// Register the component with class_loader
195RCLCPP_COMPONENTS_REGISTER_NODE(MapUpdateLogger)
196
197
198int main(int argc, char** argv)
199{
200 rclcpp::init(argc, argv);
201
202 rclcpp::spin(std::make_shared<MapUpdateLogger>(rclcpp::NodeOptions()));
203
204 rclcpp::shutdown();
205
206 return 0;
207}
int main(int argc, char **argv)
MapUpdateLogger(const rclcpp::NodeOptions &options)
carma_debug_ros2_msgs::msg::LaneletIdRegulatoryElementPair pairToDebugMessage(const std::pair< lanelet::Id, lanelet::RegulatoryElementPtr > &id_reg_pair)
Converts a TrafficControl pair into the corresponding debug message type.
rclcpp::Publisher< carma_debug_ros2_msgs::msg::MapUpdateReadable >::SharedPtr readable_pub_
void raw_callback(const autoware_lanelet2_msgs::msg::MapBin::SharedPtr msg)
rclcpp::Subscription< autoware_lanelet2_msgs::msg::MapBin >::SharedPtr update_sub_
carma_debug_ros2_msgs::msg::MapUpdateReadable mapUpdateCallback(const autoware_lanelet2_msgs::msg::MapBin &update)
Callback for map updates that converts them to a human readable format.
void fromBinMsg(const autoware_lanelet2_msgs::msg::MapBin &msg, std::shared_ptr< carma_wm::TrafficControl > gf_ptr, lanelet::LaneletMapPtr lanelet_map=nullptr)