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.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
system_controller_node.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2021 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
18#include <chrono>
19#include <thread>
20
21namespace system_controller
22{
23 using std_msec = std::chrono::milliseconds;
24
25 SystemControllerNode::SystemControllerNode(const rclcpp::NodeOptions &options, bool auto_init)
26 : rclcpp::Node("system_controller", options),
27 lifecycle_mgr_(get_node_base_interface(), get_node_graph_interface(), get_node_logging_interface(), get_node_services_interface())
28 {
29
30 if (auto_init)
31 {
32 initialize();
33 }
34 }
35
37 {
38 try
39 {
40
41 RCLCPP_INFO(get_logger(), "Initializing SystemControllerNode");
42
43 // Create subscriptions. History size of 100 is used here to ensure no missed alerts
44 system_alert_sub_ = create_subscription<carma_msgs::msg::SystemAlert>(
46 std::bind(&SystemControllerNode::on_system_alert, this, std::placeholders::_1));
47
48
49 // NOTE: Currently, intra-process comms must be disabled for a publisher that is transient_local: https://github.com/ros2/rclcpp/issues/1753
50 rclcpp::PublisherOptions intra_proc_disabled;
51 intra_proc_disabled.use_intra_process_comm = rclcpp::IntraProcessSetting::Disable;
52
53 // Create a publisher that will send all previously published messages to late-joining subscribers ONLY If the subscriber is transient_local too
54 auto pub_qos_transient_local = rclcpp::QoS(rclcpp::KeepLast(5)); // A publisher with this QoS will store the last 5 messages that it has sent on the topic
55 pub_qos_transient_local.transient_local();
56
57 system_alert_pub_ = create_publisher<carma_msgs::msg::SystemAlert>(
58 system_alert_topic_, pub_qos_transient_local, intra_proc_disabled);
59
60 config_.signal_configure_delay = this->declare_parameter<double>("signal_configure_delay", config_.signal_configure_delay);
61 config_.service_timeout_ms = this->declare_parameter<int64_t>("service_timeout_ms", config_.service_timeout_ms);
62 config_.call_timeout_ms = this->declare_parameter<int64_t>("call_timeout_ms", config_.call_timeout_ms);
63 config_.required_subsystem_nodes = this->declare_parameter<std::vector<std::string>>("required_subsystem_nodes", config_.required_subsystem_nodes);
64
65 RCLCPP_INFO_STREAM(get_logger(), "Config: " << config_);
66
68
69 // Create startup timer
70 startup_timer_ = rclcpp::create_timer(
71 this,
72 get_clock(),
73 std::chrono::milliseconds(static_cast<long>(config_.signal_configure_delay * 1000)),
75
76
77 }
78 catch (const std::exception &e)
79 {
80 on_error(e);
81 }
82 }
83
85 {
86 config_ = config;
87 }
88
89 void SystemControllerNode::on_error(const std::exception &e)
90 {
91
93 startup_timer_->cancel(); // Cancel the timer to ensure we are not interrupted
94
95 std::string reason = "Uncaught exception: " + std::string(e.what());
96
97 RCLCPP_ERROR_STREAM(
98 get_logger(), reason); // Log error
99
100 lifecycle_mgr_.shutdown(std_msec(config_.service_timeout_ms), std_msec(config_.call_timeout_ms), false); // Trigger shutdown when internal error occurs
101
102 rclcpp::shutdown(nullptr, reason); // Fully shutdown this node
103 }
104
106 {
107 try
108 {
109 RCLCPP_INFO(get_logger(), "Attempting to configure system...");
110
111 if (startup_timer_)
112 startup_timer_->cancel(); // Cancel the timer as this callback should only trigger once
113
114 // Walk the managed nodes through their lifecycle
115 // First we configure the nodes
117 {
118 // If some nodes failed to configure then we will shutdown the system
119 RCLCPP_ERROR_STREAM(
120 get_logger(), "System could not be configured on startup. Shutting down.");
121
123 rclcpp::shutdown(nullptr, "System could not be configured on startup. Shutting down.");
124 return;
125 }
126
127 // Second we activate the nodes
129 {
130
131 RCLCPP_ERROR_STREAM(
132 get_logger(), "System could not be activated. Shutting down.");
133
135 rclcpp::shutdown(nullptr, "System could not be activated. Shutting down.");
136 return;
137 }
138
139 RCLCPP_INFO(get_logger(), "System configured successfully");
140 }
141 catch (const std::exception &e)
142 {
143 on_error(e);
144 }
145 }
146
147 void SystemControllerNode::publish_system_alert(carma_msgs::msg::SystemAlert msg)
148 {
149
150 if (!get_node_base_interface())
151 throw std::runtime_error("get_node_base_interface() returned null pointer. May indicate ROS2 bug.");
152
153 msg.source_node = get_node_base_interface()->get_fully_qualified_name(); // The the source name for the message
154
155 system_alert_pub_->publish(msg);
156 }
157
158 void SystemControllerNode::on_system_alert(const carma_msgs::msg::SystemAlert::UniquePtr msg)
159 {
160
161 try
162 {
163
164 RCLCPP_INFO_STREAM(
165 get_logger(), "Received SystemAlert message of type: " << static_cast<int>(msg->type) << " with message: " << msg->description);
166
167
168 if (msg->type == carma_msgs::msg::SystemAlert::SHUTDOWN // If a SHUTDOWN signal was received
169 || ( msg->type == carma_msgs::msg::SystemAlert::FATAL // OR if a required node notified FATAL
170 && std::find(config_.required_subsystem_nodes.begin(), config_.required_subsystem_nodes.end(), msg->source_node)
172 {
173 // TODO might make more sense for external shutdown to be a service call and remove SHUTDOWN from system alert entirely
174 RCLCPP_INFO_STREAM( get_logger(), "Shutting down");
175
177
178 carma_msgs::msg::SystemAlert shutdown_msg; // Notify ros1 nodes of shutdown
179
180 shutdown_msg.type = carma_msgs::msg::SystemAlert::SHUTDOWN;
181 shutdown_msg.description = "SHUTDOWN " + msg->description;
182
183 publish_system_alert(shutdown_msg);
184
185 std::this_thread::sleep_for(std::chrono::milliseconds(5)); // Add a bit of sleep to allow message publication
186
187 rclcpp::shutdown(nullptr, "System Alert requested shutdown"); // Fully shutdown this node
188 }
189 }
190 catch (const std::exception &e)
191 {
192 on_error(e);
193 }
194 }
195
196} // namespace system_controller
197
198#include "rclcpp_components/register_node_macro.hpp"
199
200// Register the component with class_loader
201RCLCPP_COMPONENTS_REGISTER_NODE(system_controller::SystemControllerNode)
void set_config(SystemControllerConfig config)
Reset the configurations of this node. This is mean to support testing or other non-standard launch m...
void startup_delay_callback()
Callback to be triggered when the startup delay has passed.
std::shared_ptr< rclcpp::Publisher< carma_msgs::msg::SystemAlert > > system_alert_pub_
System alert publisher.
rclcpp::TimerBase::SharedPtr startup_timer_
Timer which triggers when the startup delay has passed.
rclcpp::Subscription< carma_msgs::msg::SystemAlert >::SharedPtr system_alert_sub_
The subscriber for the system alert topic.
void on_system_alert(const carma_msgs::msg::SystemAlert::UniquePtr msg)
Callback for system alert messages used to evaluate system fault handling.
ros2_lifecycle_manager::Ros2LifecycleManager lifecycle_mgr_
Lifecycle Manager which will track the managed nodes and call their lifecycle services on request.
void initialize()
Initialize this node by loading parameters from the ROS Network.
void publish_system_alert(carma_msgs::msg::SystemAlert msg)
Publishes a SystemAlert message to the rest of the carma-platform system. NOTE: This callback will au...
void on_error(const std::exception &e)
Exception handling method for processing all internal exceptions;.
SystemControllerConfig config_
The configuration of this node.
const std::string system_alert_topic_
The default topic name for the system alert topic.
std::chrono::milliseconds std_msec
Stuct containing the algorithm configuration values for the SystemController.
uint64_t service_timeout_ms
Timeout in ms for service availability.
uint64_t call_timeout_ms
Timeout in ms for service calls.
double signal_configure_delay
Time in seconds to wait before telling all nodes to configure.
std::vector< std::string > required_subsystem_nodes
List of nodes to consider required and who's failure shall result in system shutdown.