Skip to content

Commit ec00e29

Browse files
authored
feat: implement MRM automatic recovery feature (#1515)
* implement service for clear MRM behavior * clang format * implement MRM automatic recovery feature * launch option of recovery node * Update comment of system.launch.xml * code refactoring * introduce mrm_by_fatal_error flag * run precommit
1 parent 23b5356 commit ec00e29

File tree

5 files changed

+212
-0
lines changed

5 files changed

+212
-0
lines changed

launch/tier4_system_launch/launch/system.launch.xml

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
<arg name="launch_system_monitor" default="true" description="launch system monitor"/>
2121
<arg name="launch_dummy_diag_publisher" description="launch dummy diag publisher"/>
22+
<arg name="launch_system_recover_operator" default="false" description="launch recover operator"/>
2223
<arg name="run_mode" default="online" description="options: online, logging_simulation, planning_simulation"/>
2324
<arg name="sensor_model" description="sensor model name"/>
2425

@@ -154,4 +155,9 @@
154155
<arg name="launch_rqt_runtime_monitor_err" value="$(var launch_rqt_runtime_monitor_err)"/>
155156
</include>
156157
</group>
158+
159+
<!-- System Recover Operator -->
160+
<group if="$(var launch_system_recover_operator)">
161+
<node pkg="diagnostic_graph_aggregator" exec="recovery" name="recovery"/>
162+
</group>
157163
</launch>

system/diagnostic_graph_aggregator/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ ament_auto_add_executable(converter
2222
)
2323
target_include_directories(converter PRIVATE src/common)
2424

25+
ament_auto_add_executable(recovery
26+
src/node/recovery.cpp
27+
)
28+
target_include_directories(recovery PRIVATE src/common)
29+
2530
ament_auto_add_executable(tree
2631
src/tool/tree.cpp
2732
src/tool/utils/loader.cpp

system/diagnostic_graph_aggregator/package.xml

+4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010
<buildtool_depend>ament_cmake_auto</buildtool_depend>
1111
<buildtool_depend>autoware_cmake</buildtool_depend>
1212

13+
<depend>autoware_adapi_v1_msgs</depend>
14+
<depend>autoware_auto_system_msgs</depend>
15+
<depend>component_interface_utils</depend>
1316
<depend>diagnostic_msgs</depend>
1417
<depend>rclcpp</depend>
18+
<depend>std_srvs</depend>
1519
<depend>tier4_system_msgs</depend>
1620
<depend>yaml_cpp_vendor</depend>
1721

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright 2023 The Autoware Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "recovery.hpp"
16+
17+
#include <algorithm>
18+
19+
namespace diagnostic_graph_aggregator
20+
{
21+
22+
RecoveryNode::RecoveryNode() : Node("recovery")
23+
{
24+
using std::placeholders::_1;
25+
const auto qos_graph = rclcpp::QoS(1);
26+
const auto qos_aw_state = rclcpp::QoS(1);
27+
const auto qos_mrm_state = rclcpp::QoS(1);
28+
29+
const auto callback_graph = std::bind(&RecoveryNode::on_graph, this, _1);
30+
sub_graph_ =
31+
create_subscription<DiagnosticGraph>("/diagnostics_graph", qos_graph, callback_graph);
32+
const auto callback_aw_state = std::bind(&RecoveryNode::on_aw_state, this, _1);
33+
sub_aw_state_ =
34+
create_subscription<AutowareState>("/autoware/state", qos_aw_state, callback_aw_state);
35+
const auto callback_mrm_state = std::bind(&RecoveryNode::on_mrm_state, this, _1);
36+
sub_mrm_state_ =
37+
create_subscription<MrmState>("/system/fail_safe/mrm_state", qos_mrm_state, callback_mrm_state);
38+
callback_group_ = create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
39+
srv_clear_mrm_ = create_client<std_srvs::srv::Trigger>(
40+
"/system/clear_mrm", rmw_qos_profile_services_default, callback_group_);
41+
42+
fatal_error_ = false;
43+
mrm_occur_ = false;
44+
autonomous_available_ = false;
45+
mrm_by_fatal_error_ = false;
46+
}
47+
48+
void RecoveryNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)
49+
{
50+
for (const auto & node : msg->nodes) {
51+
if (node.status.name == "/autoware/modes/autonomous") {
52+
autonomous_available_ = node.status.level == DiagnosticStatus::OK;
53+
}
54+
// aggregate non-recoverable error
55+
if (node.status.name == "/autoware/fatal_error/autonomous_available") {
56+
if (node.status.level != DiagnosticStatus::OK) {
57+
fatal_error_ = true;
58+
} else {
59+
fatal_error_ = false;
60+
}
61+
}
62+
}
63+
}
64+
65+
void RecoveryNode::on_aw_state(const AutowareState::ConstSharedPtr msg)
66+
{
67+
auto_driving_ = msg->state == AutowareState::DRIVING;
68+
}
69+
70+
void RecoveryNode::on_mrm_state(const MrmState::ConstSharedPtr msg)
71+
{
72+
// set flag if mrm happened by fatal error
73+
if (msg->state != MrmState::NORMAL && fatal_error_) {
74+
mrm_by_fatal_error_ = true;
75+
}
76+
// reset flag if recoverd (transition from mrm to normal)
77+
if (mrm_occur_ && msg->state == MrmState::NORMAL) {
78+
mrm_by_fatal_error_ = false;
79+
}
80+
mrm_occur_ = msg->state != MrmState::NORMAL;
81+
// 1. Not emergency
82+
// 2. Non-recovoerable MRM have not happened
83+
// 3. on MRM
84+
// 4. on autonomous driving
85+
if (autonomous_available_ && !mrm_by_fatal_error_ && mrm_occur_ && auto_driving_) {
86+
clear_mrm();
87+
}
88+
}
89+
90+
void RecoveryNode::clear_mrm()
91+
{
92+
const auto req = std::make_shared<std_srvs::srv::Trigger::Request>();
93+
94+
auto logger = get_logger();
95+
if (!srv_clear_mrm_->service_is_ready()) {
96+
RCLCPP_ERROR(logger, "MRM clear server is not ready.");
97+
return;
98+
}
99+
RCLCPP_INFO(logger, "Recover MRM automatically.");
100+
auto res = srv_clear_mrm_->async_send_request(req);
101+
std::future_status status = res.wait_for(std::chrono::milliseconds(50));
102+
if (status == std::future_status::timeout) {
103+
RCLCPP_INFO(logger, "Service timeout");
104+
return;
105+
}
106+
if (!res.get()->success) {
107+
RCLCPP_INFO(logger, "Recovering MRM failed.");
108+
return;
109+
}
110+
RCLCPP_INFO(logger, "Recovering MRM succeed.");
111+
}
112+
113+
} // namespace diagnostic_graph_aggregator
114+
115+
int main(int argc, char ** argv)
116+
{
117+
using diagnostic_graph_aggregator::RecoveryNode;
118+
rclcpp::init(argc, argv);
119+
rclcpp::executors::SingleThreadedExecutor executor;
120+
auto node = std::make_shared<RecoveryNode>();
121+
executor.add_node(node);
122+
executor.spin();
123+
executor.remove_node(node);
124+
rclcpp::shutdown();
125+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright 2023 The Autoware Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef NODE__RECOVERY_HPP_
16+
#define NODE__RECOVERY_HPP_
17+
18+
#include "graph/types.hpp"
19+
20+
#include <rclcpp/rclcpp.hpp>
21+
22+
// Autoware
23+
#include <component_interface_utils/rclcpp.hpp>
24+
25+
#include <autoware_adapi_v1_msgs/msg/mrm_state.hpp>
26+
#include <autoware_auto_system_msgs/msg/autoware_state.hpp>
27+
#include <std_msgs/msg/string.hpp>
28+
#include <std_srvs/srv/trigger.hpp>
29+
30+
#include <functional>
31+
#include <map> // Use map for sorting keys.
32+
#include <memory>
33+
#include <string>
34+
#include <vector>
35+
36+
namespace diagnostic_graph_aggregator
37+
{
38+
39+
class RecoveryNode : public rclcpp::Node
40+
{
41+
public:
42+
RecoveryNode();
43+
44+
private:
45+
using AutowareState = autoware_auto_system_msgs::msg::AutowareState;
46+
using MrmState = autoware_adapi_v1_msgs::msg::MrmState;
47+
48+
bool fatal_error_;
49+
bool autonomous_available_;
50+
bool mrm_occur_;
51+
bool auto_driving_;
52+
bool mrm_by_fatal_error_;
53+
rclcpp::Subscription<DiagnosticGraph>::SharedPtr sub_graph_;
54+
rclcpp::Subscription<AutowareState>::SharedPtr sub_aw_state_;
55+
rclcpp::Subscription<MrmState>::SharedPtr sub_mrm_state_;
56+
57+
// service
58+
rclcpp::Client<std_srvs::srv::Trigger>::SharedPtr srv_clear_mrm_;
59+
60+
// callback group for service
61+
rclcpp::CallbackGroup::SharedPtr callback_group_;
62+
63+
void on_graph(const DiagnosticGraph::ConstSharedPtr msg);
64+
void on_aw_state(const AutowareState::ConstSharedPtr msg);
65+
void on_mrm_state(const MrmState::ConstSharedPtr msg);
66+
67+
void clear_mrm();
68+
};
69+
70+
} // namespace diagnostic_graph_aggregator
71+
72+
#endif // NODE__RECOVERY_HPP_

0 commit comments

Comments
 (0)