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.
arbitrator.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 "arbitrator.hpp"
18#include <carma_planning_msgs/msg/maneuver_plan.hpp>
19#include <carma_planning_msgs/srv/plan_maneuvers.hpp>
20#include "arbitrator_utils.hpp"
21#include <rclcpp/rclcpp.hpp>
22#include <exception>
23#include <cstdlib>
24
25namespace arbitrator
26{
28 {
29 if (!planning_in_progress_ && nh_->get_current_state().id() != lifecycle_msgs::msg::State::TRANSITION_STATE_SHUTTINGDOWN)
30 {
32
33 switch (sm_->get_state())
34 {
35 case INITIAL:
36 RCLCPP_INFO_STREAM(nh_->get_logger(), "Arbitrator spinning in INITIAL state.");
38 break;
39 case PLANNING:
40 RCLCPP_INFO_STREAM(nh_->get_logger(), "Arbitrator spinning in PLANNING state.");
42 break;
43 case WAITING:
44 RCLCPP_INFO_STREAM(nh_->get_logger(), "Arbitrator spinning in WAITING state.");
46 break;
47 case PAUSED:
48 RCLCPP_INFO_STREAM(nh_->get_logger(), "Arbitrator spinning in PAUSED state.");
50 break;
51 case SHUTDOWN:
52 RCLCPP_INFO_STREAM(nh_->get_logger(), "Arbitrator shutting down after being commanded to shutdown!");
53 rclcpp::shutdown();
54 exit(0);
55 break;
56 default:
57 throw std::invalid_argument("State machine attempting to process an illegal state value");
58 }
59 }
60 else
61 {
62 return;
63 }
65 }
66
67 void Arbitrator::guidance_state_cb(carma_planning_msgs::msg::GuidanceState::UniquePtr msg) {
68 // Flag to determine if this is a new state
69 bool is_new_state = (msg->state != previous_guidance_state_);
70
71 switch (msg->state) {
72 case carma_planning_msgs::msg::GuidanceState::STARTUP:
73 // NO-OP
74 break;
75 case carma_planning_msgs::msg::GuidanceState::DRIVERS_READY:
76 if(sm_->get_state() == ArbitratorState::PLANNING ||
77 sm_->get_state() == ArbitratorState::WAITING) {
78 if (is_new_state) {
79 RCLCPP_INFO_STREAM(nh_->get_logger(),
80 "Guidance has been restarted, pausing arbitrator...");
81 }
83 }
84 break;
86 // NO-OP
87 break;
89 if (is_new_state) {
90 RCLCPP_INFO_STREAM(nh_->get_logger(),
91 "Guidance has been engaged!");
92 }
93 if (sm_->get_state() == ArbitratorState::INITIAL) {
95 } else if (sm_->get_state() == ArbitratorState::PAUSED) {
97 }
98 break;
100 if (is_new_state) {
101 RCLCPP_INFO_STREAM(nh_->get_logger(),
102 "Guidance has been disengaged, pausing arbitrator.");
103 }
105 break;
107 if (is_new_state) {
108 RCLCPP_INFO_STREAM(nh_->get_logger(),
109 "Guidance has been shutdown, shutting down arbitrator...");
110 }
112 break;
113 default:
114 break;
115 }
116
117 // Update previous state
118 previous_guidance_state_ = msg->state;
119 }
120
122 {
123 if(!initialized_)
124 {
125 RCLCPP_INFO_STREAM(nh_->get_logger(), "Arbitrator initializing on first initial state spin...");
126 final_plan_pub_ = nh_->create_publisher<carma_planning_msgs::msg::ManeuverPlan>("final_maneuver_plan", 5);
127 guidance_state_sub_ = nh_->create_subscription<carma_planning_msgs::msg::GuidanceState>("guidance_state", 5, std::bind(&Arbitrator::guidance_state_cb, this, std::placeholders::_1));
128 final_plan_pub_->on_activate();
129
130 initialized_ = true;
131 }
132
133 std::this_thread::sleep_for(std::chrono::milliseconds(100));
134 }
135
137 {
138 rclcpp::Time planning_process_start = nh_->get_clock()->now();
139
140 carma_planning_msgs::msg::ManeuverPlan plan = planning_strategy_->generate_plan(vehicle_state_);
141
142 if (!plan.maneuvers.empty())
143 {
144 rclcpp::Time plan_end_time = arbitrator_utils::get_plan_end_time(plan);
145 rclcpp::Time plan_start_time = arbitrator_utils::get_plan_start_time(plan);
146 rclcpp::Duration plan_duration = plan_end_time - plan_start_time;
147
148 if (plan_duration < min_plan_duration_)
149 {
150 RCLCPP_WARN_STREAM(nh_->get_logger(), "Arbitrator is unable to generate a plan with minimum plan duration requirement!");
151 }
152 else
153 {
154 RCLCPP_DEBUG_STREAM(nh_->get_logger(),
155 "Arbitrator is publishing plan id: "
156 << std::string(plan.maneuver_plan_id)
157 << " of duration " << plan_duration.seconds() << " as current maneuver plan");
158 }
159 final_plan_pub_->publish(plan);
160 }
161 else
162 {
163 RCLCPP_WARN_STREAM(nh_->get_logger(), "Arbitrator was unable to generate a plan!");
164 }
165
166 next_planning_process_start_ = planning_process_start + time_between_plans_;
167
169 }
170
172 {
174 }
175
177 {
178 std::this_thread::sleep_for(std::chrono::milliseconds(100));
179 }
180
182 {
183 RCLCPP_INFO_STREAM(nh_->get_logger(), "Arbitrator shutting down...");
184 rclcpp::shutdown(); // Will stop upper level spin and shutdown node
185 }
186
188 {
189 try
190 {
191 tf_ = tf2_buffer_.lookupTransform("map", "vehicle_front", rclcpp::Time(0), rclcpp::Duration(1.0, 0)); //save to local copy of transform 1 sec timeout
192 tf2::fromMsg(tf_, bumper_transform_);
193 vehicle_state_.stamp = tf_.header.stamp;
194 }
195 catch (const tf2::TransformException &ex)
196 {
197 RCLCPP_WARN_STREAM(nh_->get_logger(), ex.what());
198 }
199
200 vehicle_state_.x = bumper_transform_.getOrigin().getX();
201 vehicle_state_.y = bumper_transform_.getOrigin().getY();
202
203 // If the route is available then set the downtrack and lane id
204 if (wm_->getRoute()) {
205
206 vehicle_state_.downtrack = wm_->routeTrackPos( { vehicle_state_.x, vehicle_state_.y } ).downtrack;
207
208 auto lanelets = wm_->getLaneletsBetween(vehicle_state_.downtrack, vehicle_state_.downtrack, true);
209
210 if (lanelets.empty()) {
211
212 RCLCPP_WARN_STREAM(nh_->get_logger(), "Vehicle is not in a lanelet.");
213 vehicle_state_.lane_id = lanelet::InvalId;
214
215 } else {
216
217 vehicle_state_.lane_id = lanelets[0].id();
218 }
219 }
220
221 }
222
223 void Arbitrator::twist_cb(geometry_msgs::msg::TwistStamped::UniquePtr msg)
224 {
225 vehicle_state_.velocity = msg->twist.linear.x;
226 }
227
229 {
230 tf2_listener_.reset(new tf2_ros::TransformListener(tf2_buffer_));
231 tf2_buffer_.setUsingDedicatedThread(true);
232 }
233}
void planning_state()
Function to be called when the Arbitrator begins planning.
Definition: arbitrator.cpp:136
tf2::Stamped< tf2::Transform > bumper_transform_
Definition: arbitrator.hpp:179
rclcpp::Time next_planning_process_start_
Definition: arbitrator.hpp:168
carma_planning_msgs::msg::GuidanceState::_state_type previous_guidance_state_
Definition: arbitrator.hpp:181
void shutdown_state()
Function to be executed when the Arbitrator is to clean up and shutdown.
Definition: arbitrator.cpp:181
void paused_state()
Function to be executed when the Arbitrator is not planning but also not awaiting a new plan cycle.
Definition: arbitrator.cpp:176
void initial_state()
Function to be executed during the initial state of the Arbitrator.
Definition: arbitrator.cpp:121
rclcpp::Duration min_plan_duration_
Definition: arbitrator.hpp:166
carma_ros2_utils::PubPtr< carma_planning_msgs::msg::ManeuverPlan > final_plan_pub_
Definition: arbitrator.hpp:163
std::shared_ptr< carma_ros2_utils::CarmaLifecycleNode > nh_
Definition: arbitrator.hpp:165
void twist_cb(geometry_msgs::msg::TwistStamped::UniquePtr msg)
Callback for the twist subscriber, which will store latest twist locally.
Definition: arbitrator.cpp:223
tf2_ros::Buffer tf2_buffer_
Definition: arbitrator.hpp:176
carma_ros2_utils::SubPtr< carma_planning_msgs::msg::GuidanceState > guidance_state_sub_
Definition: arbitrator.hpp:164
void waiting_state()
Function to be executed when the Arbitrator has finished planning and is awaiting another planning cy...
Definition: arbitrator.cpp:171
carma_wm::WorldModelConstPtr wm_
Definition: arbitrator.hpp:172
rclcpp::Duration time_between_plans_
Definition: arbitrator.hpp:167
std::shared_ptr< PlanningStrategy > planning_strategy_
Definition: arbitrator.hpp:170
void initializeBumperTransformLookup()
Initialize transform Lookup from front bumper to map.
Definition: arbitrator.cpp:228
std::unique_ptr< tf2_ros::TransformListener > tf2_listener_
Definition: arbitrator.hpp:177
void run()
Begin the operation of the arbitrator.
Definition: arbitrator.cpp:27
VehicleState vehicle_state_
Definition: arbitrator.hpp:160
geometry_msgs::msg::TransformStamped tf_
Definition: arbitrator.hpp:174
void bumper_pose_cb()
Callback for the front bumper pose transform.
Definition: arbitrator.cpp:187
void guidance_state_cb(carma_planning_msgs::msg::GuidanceState::UniquePtr msg)
Callback for receiving Guidance state machine updates.
Definition: arbitrator.cpp:67
std::shared_ptr< ArbitratorStateMachine > sm_
Definition: arbitrator.hpp:162
rclcpp::Time get_plan_start_time(const carma_planning_msgs::msg::ManeuverPlan &)
Get the start time of the first maneuver in the plan.
rclcpp::Time get_plan_end_time(const carma_planning_msgs::msg::ManeuverPlan &)
Get the end time of the first maneuver in the plan.