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.
intersection_transit_maneuvering.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 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
18#include <rclcpp/rclcpp.hpp>
19#include <functional>
20#include <carma_ros2_utils/carma_lifecycle_node.hpp>
21#include <string>
22#include <algorithm>
23#include <memory>
24#include <boost/uuid/uuid_generators.hpp>
25#include <boost/uuid/uuid_io.hpp>
26#include <trajectory_utils/trajectory_utils.hpp>
27#include <trajectory_utils/conversions/conversions.hpp>
28#include <sstream>
30
31
32using oss = std::ostringstream;
33
35{
36
37namespace std_ph = std::placeholders;
38
43std::ostream& operator<<(std::ostream& os, carma_planning_msgs::msg::ManeuverParameters m) {
44 os << "maneuver_id: " << m.maneuver_id
45 << " negotiation_type: " << unsigned(m.negotiation_type)
46 << " planning_strategic_plugin: " << m.planning_strategic_plugin
47 << " presence_vector: " << unsigned(m.presence_vector)
48 << " planning_tactical_plugin: " << m.planning_tactical_plugin;
49 return os;
50}
51
52std::ostream& operator<<(std::ostream& os, carma_planning_msgs::msg::IntersectionTransitStraightManeuver m) {
53 os << "parameters: { " << m.parameters << " }"
54 << " start_dist: " << m.start_dist
55 << " end_dist: " << m.end_dist
56 << " start_speed: " << m.start_speed
57 << " end_speed: " << m.end_speed
58 << " start_time: " << std::to_string(rclcpp::Time(m.start_time).seconds())
59 << " end_time: " << std::to_string(rclcpp::Time(m.end_time).seconds())
60 << " starting_lane_id: " << m.starting_lane_id
61 << " ending_lane_id: " << m.ending_lane_id;
62 return os;
63}
64
65std::ostream& operator<<(std::ostream& os, carma_planning_msgs::msg::IntersectionTransitLeftTurnManeuver m) {
66 os << "parameters: { " << m.parameters << " }"
67 << " start_dist: " << m.start_dist
68 << " end_dist: " << m.end_dist
69 << " start_speed: " << m.start_speed
70 << " end_speed: " << m.end_speed
71 << " start_time: " << std::to_string(rclcpp::Time(m.start_time).seconds())
72 << " end_time: " << std::to_string(rclcpp::Time(m.end_time).seconds())
73 << " starting_lane_id: " << m.starting_lane_id
74 << " ending_lane_id: " << m.ending_lane_id;
75 return os;
76}
77
78std::ostream& operator<<(std::ostream& os, carma_planning_msgs::msg::IntersectionTransitRightTurnManeuver m) {
79 os << "parameters: { " << m.parameters << " }"
80 << " start_dist: " << m.start_dist
81 << " end_dist: " << m.end_dist
82 << " start_speed: " << m.start_speed
83 << " end_speed: " << m.end_speed
84 << " start_time: " << std::to_string(rclcpp::Time(m.start_time).seconds())
85 << " end_time: " << std::to_string(rclcpp::Time(m.end_time).seconds())
86 << " starting_lane_id: " << m.starting_lane_id
87 << " ending_lane_id: " << m.ending_lane_id;
88 return os;
89}
90
91std::ostream& operator<<(std::ostream& os, carma_planning_msgs::msg::LaneFollowingManeuver m) {
92 os << "parameters: { " << m.parameters << " }"
93 << " start_dist: " << m.start_dist
94 << " end_dist: " << m.end_dist
95 << " start_speed: " << m.start_speed
96 << " end_speed: " << m.end_speed
97 << " start_time: " << std::to_string(rclcpp::Time(m.start_time).seconds())
98 << " end_time: " << std::to_string(rclcpp::Time(m.end_time).seconds())
99 << " lane_ids: [ ";
100
101 for (const auto& i : m.lane_ids)
102 os << i << " ";
103
104 os << "]";
105
106 return os;
107
108}
109
110std::ostream& operator<<(std::ostream& os, carma_planning_msgs::msg::Maneuver m) {
111
112 os << "Maneuver Type: " << unsigned(m.type);
113 switch(m.type) {
114 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT:
115 os << m.intersection_transit_straight_maneuver;
116 break;
117 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN:
118 os << m.intersection_transit_left_turn_maneuver;
119 break;
120 case carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN:
121 os << m.intersection_transit_right_turn_maneuver;
122 break;
123 case carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING:
124 os << m.lane_following_maneuver;
125 break;
126 default:
127 os << " not yet supported for printing. ";
128 }
129
130 return os;
131}
132
134: carma_guidance_plugins::TacticalPlugin(options) {}
135
137{
138 RCLCPP_INFO_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"), "IntersectionTransitManeuveringNode trying to configure");
139
140 object_ = std::make_shared<intersection_transit_maneuvering::Servicer>();
141
142 client_ = create_client<carma_planning_msgs::srv::PlanTrajectory>("inlanecruising_plugin/plan_trajectory");
143
144 object_->set_client(client_);
145
146 //Return success if everthing initialized successfully
147return CallbackReturn::SUCCESS;
148
149}
150
152 return true;
153 }
154
156 return "v4.0"; // Version ID matches the value set in this package's package.xml
157 }
158
159
161 std::shared_ptr<rmw_request_id_t>,
162 carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req,
163 carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp)
164 {
165
166 std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now(); // Start timing the execution time for planning so it can be logged
167
168 std::vector<carma_planning_msgs::msg::Maneuver> maneuver_plan;
169
170 auto related_maneuvers = resp->related_maneuvers;
171
172 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Starting planning for maneuver index: " << req->maneuver_index_to_plan);
173 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"req->maneuver_plan.maneuvers.size(): " << req->maneuver_plan.maneuvers.size());
174
175 for(size_t i = req->maneuver_index_to_plan; i < req->maneuver_plan.maneuvers.size(); i++)
176 {
177 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Looping");
178 if(req->maneuver_plan.maneuvers[i].type == carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT ||
179 req->maneuver_plan.maneuvers[i].type == carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN ||
180 req->maneuver_plan.maneuvers[i].type == carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN )
181 {
182 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Found valid maneuver for planning at index: " << i);
183 maneuver_plan.push_back(req->maneuver_plan.maneuvers[i]);
184 related_maneuvers.push_back(i);
185 }
186 else
187 {
188 break;
189 }
190 }
191
193 auto new_req = std::make_shared<carma_planning_msgs::srv::PlanTrajectory::Request> ();
194
195 for(auto i : converted_maneuvers_)
196 {
197 new_req->maneuver_plan.maneuvers.push_back(i);
198 }
199
200 new_req->header = req->header;
201 new_req->vehicle_state = req->vehicle_state;
202 new_req->initial_trajectory_plan = req->initial_trajectory_plan;
203 carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr ilc_resp = std::make_shared<carma_planning_msgs::srv::PlanTrajectory::Response>();
204 object_->call(new_req,ilc_resp);
205
206 if(ilc_resp->trajectory_plan.trajectory_points.empty())//Since we're using an interface for this process, the call() functionality will come from somewhere else
207 {
208 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Failed to call service");
209 return ;
210 } else {
211 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Call Successful");
212 resp->trajectory_plan = ilc_resp->trajectory_plan;
213 }
214
215
216 resp->related_maneuvers = related_maneuvers; // Set the related maneuvers using the origional maneuver indexs not those sent to inlane-cruising
217 for (auto maneuver : related_maneuvers) {
218 resp->maneuver_status.push_back(carma_planning_msgs::srv::PlanTrajectory::Response::MANEUVER_IN_PROGRESS);
219 }
220
221 std::chrono::system_clock::time_point end_time = std::chrono::system_clock::now(); // Start timing the execution time for planning so it can be logged
222
223 auto duration = end_time - start_time;
224 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"ExecutionTime: " << std::chrono::duration<double>(duration).count());
225 return ;
226 }
227
228 std::vector<carma_planning_msgs::msg::Maneuver> IntersectionTransitManeuveringNode::convert_maneuver_plan(const std::vector<carma_planning_msgs::msg::Maneuver>& maneuvers)
229 {
230 if (maneuvers.size() == 0)
231 {
232 throw std::invalid_argument("No maneuvers to convert");
233 }
234
235 std::vector<carma_planning_msgs::msg::Maneuver> new_maneuver_plan;
236 carma_planning_msgs::msg::Maneuver new_maneuver;
237 new_maneuver.type = carma_planning_msgs::msg::Maneuver::LANE_FOLLOWING; //All of the converted maneuvers will be of type LANE_FOLLOWING
238 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Input Maneuver Type = "<< static_cast<int>(maneuvers.front().type));
239 for(const auto& maneuver : maneuvers)
240 {
241 //Throw exception if the manuever type does not match INTERSECTION_TRANSIT
242 if ( maneuver.type != carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT &&
243 maneuver.type != carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN &&
244 maneuver.type != carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN)
245 {
246 throw std::invalid_argument("Intersection transit maneuvering does not support this maneuver type");
247 }
248
249 //Convert IT Straight
250 if (maneuver.type == carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_STRAIGHT)
251 {
252 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Converting INTERSECTION_TRANSIT_STRAIGHT");
253
254 new_maneuver.lane_following_maneuver.parameters.maneuver_id = maneuver.intersection_transit_straight_maneuver.parameters.maneuver_id;
255 new_maneuver.lane_following_maneuver.parameters.planning_strategic_plugin = maneuver.intersection_transit_straight_maneuver.parameters.planning_strategic_plugin;
256 new_maneuver.lane_following_maneuver.parameters.planning_tactical_plugin = maneuver.intersection_transit_straight_maneuver.parameters.planning_tactical_plugin;
257 new_maneuver.lane_following_maneuver.parameters.negotiation_type = maneuver.intersection_transit_straight_maneuver.parameters.negotiation_type;
258 new_maneuver.lane_following_maneuver.parameters.presence_vector = carma_planning_msgs::msg::ManeuverParameters::HAS_TACTICAL_PLUGIN;
259
260 new_maneuver.lane_following_maneuver.start_dist = maneuver.intersection_transit_straight_maneuver.start_dist;
261 new_maneuver.lane_following_maneuver.start_speed = maneuver.intersection_transit_straight_maneuver.start_speed;
262 new_maneuver.lane_following_maneuver.start_time = maneuver.intersection_transit_straight_maneuver.start_time;
263
264 new_maneuver.lane_following_maneuver.end_dist = maneuver.intersection_transit_straight_maneuver.end_dist;
265 new_maneuver.lane_following_maneuver.end_speed = maneuver.intersection_transit_straight_maneuver.end_speed;
266 new_maneuver.lane_following_maneuver.end_time = maneuver.intersection_transit_straight_maneuver.end_time;
267
268
269 new_maneuver.lane_following_maneuver.lane_ids = { maneuver.intersection_transit_straight_maneuver.starting_lane_id };
270
271 new_maneuver_plan.push_back(new_maneuver);
272 }
273
274 //Convert IT LEFT TURN
275 if (maneuver.type == carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_LEFT_TURN)
276 {
277 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Converting INTERSECTION_TRANSIT_LEFT_TURN");
278
279 new_maneuver.lane_following_maneuver.parameters.maneuver_id = maneuver.intersection_transit_left_turn_maneuver.parameters.maneuver_id;
280 new_maneuver.lane_following_maneuver.parameters.planning_strategic_plugin = maneuver.intersection_transit_left_turn_maneuver.parameters.planning_strategic_plugin;
281 new_maneuver.lane_following_maneuver.parameters.planning_tactical_plugin = maneuver.intersection_transit_left_turn_maneuver.parameters.planning_tactical_plugin;
282 new_maneuver.lane_following_maneuver.parameters.negotiation_type = maneuver.intersection_transit_left_turn_maneuver.parameters.negotiation_type;
283 new_maneuver.lane_following_maneuver.parameters.presence_vector = carma_planning_msgs::msg::ManeuverParameters::HAS_TACTICAL_PLUGIN;
284
285 new_maneuver.lane_following_maneuver.start_dist = maneuver.intersection_transit_left_turn_maneuver.start_dist;
286 new_maneuver.lane_following_maneuver.start_speed = maneuver.intersection_transit_left_turn_maneuver.start_speed;
287 new_maneuver.lane_following_maneuver.start_time = maneuver.intersection_transit_left_turn_maneuver.start_time;
288
289 new_maneuver.lane_following_maneuver.end_dist = maneuver.intersection_transit_left_turn_maneuver.end_dist;
290 new_maneuver.lane_following_maneuver.end_speed = maneuver.intersection_transit_left_turn_maneuver.end_speed;
291 new_maneuver.lane_following_maneuver.end_time = maneuver.intersection_transit_left_turn_maneuver.end_time;
292
293 new_maneuver.lane_following_maneuver.lane_ids = { maneuver.intersection_transit_left_turn_maneuver.starting_lane_id };
294
295 new_maneuver_plan.push_back(new_maneuver);
296 }
297
298 //Convert IT RIGHT TURN
299 if (maneuver.type == carma_planning_msgs::msg::Maneuver::INTERSECTION_TRANSIT_RIGHT_TURN)
300 {
301
302 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Converting INTERSECTION_TRANSIT_RIGHT_TURN");
303
304 new_maneuver.lane_following_maneuver.parameters.maneuver_id = maneuver.intersection_transit_right_turn_maneuver.parameters.maneuver_id;
305 new_maneuver.lane_following_maneuver.parameters.planning_strategic_plugin = maneuver.intersection_transit_right_turn_maneuver.parameters.planning_strategic_plugin;
306 new_maneuver.lane_following_maneuver.parameters.planning_tactical_plugin = maneuver.intersection_transit_right_turn_maneuver.parameters.planning_tactical_plugin;
307 new_maneuver.lane_following_maneuver.parameters.negotiation_type = maneuver.intersection_transit_right_turn_maneuver.parameters.negotiation_type;
308 new_maneuver.lane_following_maneuver.parameters.presence_vector = carma_planning_msgs::msg::ManeuverParameters::HAS_TACTICAL_PLUGIN;
309
310 new_maneuver.lane_following_maneuver.start_dist = maneuver.intersection_transit_right_turn_maneuver.start_dist;
311 new_maneuver.lane_following_maneuver.start_speed = maneuver.intersection_transit_right_turn_maneuver.start_speed;
312 new_maneuver.lane_following_maneuver.start_time = maneuver.intersection_transit_right_turn_maneuver.start_time;
313
314 new_maneuver.lane_following_maneuver.end_dist = maneuver.intersection_transit_right_turn_maneuver.end_dist;
315 new_maneuver.lane_following_maneuver.end_speed = maneuver.intersection_transit_right_turn_maneuver.end_speed;
316 new_maneuver.lane_following_maneuver.end_time = maneuver.intersection_transit_right_turn_maneuver.end_time;
317
318 new_maneuver.lane_following_maneuver.lane_ids = { maneuver.intersection_transit_right_turn_maneuver.starting_lane_id };
319
320 new_maneuver_plan.push_back(new_maneuver);
321 }
322
323 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("intersection_transit_maneuvering"),"Original Maneuver : " << maneuver << std::endl << "Converted Maneuver: " << new_maneuver);
324
325 }//end for-loop
326
327 return new_maneuver_plan;
328
329 }
330
331}
332
333#include "rclcpp_components/register_node_macro.hpp"
334
335// Register the component with class_loader
carma_ros2_utils::ClientPtr< carma_planning_msgs::srv::PlanTrajectory > client_
std::vector< carma_planning_msgs::msg::Maneuver > convert_maneuver_plan(const std::vector< carma_planning_msgs::msg::Maneuver > &maneuvers)
Converts a sequence of INTERSECTION_TRANSIT maneuvers to LANE_FOLLOWING maneuvers.
IntersectionTransitManeuveringNode(const rclcpp::NodeOptions &)
IntersectionTransitManeuveringNode constructor.
bool get_availability() override
Get the availability status of this plugin based on the current operating environment....
carma_ros2_utils::CallbackReturn on_configure_plugin() override
This method should be used to load parameters and will be called on the configure state transition.
std::string get_version_id() override
Returns the version id of this plugin.
void plan_trajectory_callback(std::shared_ptr< rmw_request_id_t >, carma_planning_msgs::srv::PlanTrajectory::Request::SharedPtr req, carma_planning_msgs::srv::PlanTrajectory::Response::SharedPtr resp) override
Extending class provided callback which should return a planned trajectory based on the provided traj...
std::ostringstream oss
auto to_string(const UtmZone &zone) -> std::string
Definition: utm_zone.cpp:21
std::ostream & operator<<(std::ostream &os, carma_planning_msgs::msg::ManeuverParameters m)
Stream operators for carma_planning_msgs::msg::Maneuver and nested messages. NOTE: Does not print met...