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.
platooning_control_worker.cpp
Go to the documentation of this file.
1
2/*------------------------------------------------------------------------------
3* Copyright (C) 2024 LEIDOS.
4*
5* Licensed under the Apache License, Version 2.0 (the "License"); you may not
6* use this file except in compliance with the License. You may obtain a copy of
7* the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14* License for the specific language governing permissions and limitations under
15* the License.
16
17------------------------------------------------------------------------------*/
18
20
21
22namespace platooning_control
23{
24
26 {
28
29 }
30
32 return speedCmd_;
33 }
34
35 void PlatooningControlWorker::generate_speed(const carma_planning_msgs::msg::TrajectoryPlanPoint& point)
36 {
37 double speed_cmd = 0;
38
39 if (!last_cmd_set_)
40 {
41 // last speed command for smooth speed transition
43 last_cmd_set_ = true;
44 }
45
47 if(!leader.staticId.empty() && leader.staticId != ctrl_config_->vehicle_id)
48 {
49 double controllerOutput = 0.0;
50
51
52 double leaderCurrentPosition = leader.vehiclePosition;
53 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "The current leader position is " << leaderCurrentPosition);
54
55 double desiredHostPosition = leaderCurrentPosition - desired_gap_;
56 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "desiredHostPosition = " << desiredHostPosition);
57
58 double hostVehiclePosition = leaderCurrentPosition - actual_gap_;
59 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "hostVehiclePosition = " << hostVehiclePosition);
60
61 controllerOutput = pid_ctrl_.calculate(desiredHostPosition, hostVehiclePosition);
62
63 double adjSpeedCmd = controllerOutput + leader.commandSpeed;
64 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "Adjusted Speed Cmd = " << adjSpeedCmd << "; Controller Output = " << controllerOutput
65 << "; Leader CmdSpeed= " << leader.commandSpeed << "; Adjustment Cap " << ctrl_config_->adjustment_cap_mps);
66 // After we get a adjSpeedCmd, we apply three filters on it if the filter is enabled
67 // First: we do not allow the difference between command speed of the host vehicle and the leader's commandSpeed higher than adjustmentCap
68
69 speed_cmd = adjSpeedCmd;
70 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "A speed command is generated from command generator: " << speed_cmd << " m/s");
71
72 if(ctrl_config_->enable_max_adjustment_filter)
73 {
74 if(speed_cmd > leader.commandSpeed + ctrl_config_->adjustment_cap_mps) {
75 speed_cmd = leader.commandSpeed + ctrl_config_->adjustment_cap_mps;
76 } else if(speed_cmd < leader.commandSpeed - ctrl_config_->adjustment_cap_mps) {
77 speed_cmd = leader.commandSpeed - ctrl_config_->adjustment_cap_mps;
78 }
79 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "The adjusted cmd speed after max adjustment cap is " << speed_cmd << " m/s");
80 }
81
82 }
83
84 else if (leader.staticId == ctrl_config_->vehicle_id)
85 {
86 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "Host vehicle is the leader");
87 speed_cmd = currentSpeed;
88
89 if(ctrl_config_->enable_max_adjustment_filter)
90 {
91 if(speed_cmd > ctrl_config_->adjustment_cap_mps)
92 {
93 speed_cmd = ctrl_config_->adjustment_cap_mps;
94 }
95
96 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "The adjusted leader cmd speed after max adjustment cap is " << speed_cmd << " m/s");
97 }
98
100 }
101
102 else
103 {
104 // If there is no leader available, the vehicle will stop. This means there is a mis-communication between platooning strategic and control plugins.
105 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "There is no leader available");
106 speed_cmd = 0.0;
108 }
109
110
111
112 // Third: we allow do not a large gap between two consecutive speed commands
113 if(ctrl_config_->enable_max_accel_filter) {
114
115 double max = lastCmdSpeed + (ctrl_config_->max_accel_mps2 * (ctrl_config_->cmd_timestamp_ms / 1000.0));
116 double min = lastCmdSpeed - (ctrl_config_->max_accel_mps2 * (ctrl_config_->cmd_timestamp_ms / 1000.0));
117 if(speed_cmd > max) {
118 speed_cmd = max;
119 } else if (speed_cmd < min) {
120 speed_cmd = min;
121 }
122 lastCmdSpeed = speed_cmd;
123 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("platooning_control"), "The speed command after max accel cap is: " << speed_cmd << " m/s");
124 }
125
126 speedCmd_ = speed_cmd;
127
129
130 }
131
132 // TODO get the actual leader from strategic plugin
134 platoon_leader = leader;
135 }
136
138 currentSpeed = speed;
139
140 }
141}
This class includes logic for PID controller. PID controller is used in this plugin to maintain the i...
double calculate(double setpoint, double pv)
function to calculate control command based on setpoint and process vale
void set_leader(const PlatoonLeaderInfo &leader)
Sets the platoon leader object using info from msg.
void set_current_speed(double speed)
set current speed
double get_last_speed_command() const
Returns latest speed command.
std::shared_ptr< PlatooningControlPluginConfig > ctrl_config_
PlatooningControlWorker()
Default constructor for platooning control worker.
void generate_speed(const carma_planning_msgs::msg::TrajectoryPlanPoint &point)
Generates speed commands (in m/s) based on the trajectory point.