Skip to content

Commit 9dac0da

Browse files
committed
implement MRM automatic recovery feature
1 parent cd1e5db commit 9dac0da

File tree

4 files changed

+203
-0
lines changed

4 files changed

+203
-0
lines changed

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
@@ -12,7 +12,11 @@
1212

1313
<depend>diagnostic_msgs</depend>
1414
<depend>rclcpp</depend>
15+
<depend>std_srvs</depend>
1516
<depend>tier4_system_msgs</depend>
17+
<depend>autoware_auto_system_msgs</depend>
18+
<depend>autoware_adapi_v1_msgs</depend>
19+
<depend>component_interface_utils</depend>
1620
<depend>yaml_cpp_vendor</depend>
1721

1822
<test_depend>ament_cmake_gtest</test_depend>
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+
std::string level_to_string(DiagnosticLevel level)
23+
{
24+
switch (level) {
25+
case DiagnosticStatus::OK:
26+
return "OK";
27+
case DiagnosticStatus::WARN:
28+
return "WARN";
29+
case DiagnosticStatus::ERROR:
30+
return "ERROR";
31+
case DiagnosticStatus::STALE:
32+
return "STALE";
33+
}
34+
return "UNKNOWN";
35+
}
36+
37+
38+
RecoveryNode::RecoveryNode() : Node("recovery")
39+
{
40+
using std::placeholders::_1;
41+
const auto qos_graph = rclcpp::QoS(1);
42+
const auto qos_aw_state = rclcpp::QoS(1);
43+
const auto qos_mrm_state = rclcpp::QoS(1);
44+
45+
const auto callback_graph = std::bind(&RecoveryNode::on_graph, this, _1);
46+
sub_graph_ = create_subscription<DiagnosticGraph>("/diagnostics_graph", qos_graph, callback_graph);
47+
const auto callback_aw_state = std::bind(&RecoveryNode::on_aw_state, this, _1);
48+
sub_aw_state_ = create_subscription<AutowareState>("/autoware/state", qos_aw_state, callback_aw_state);
49+
const auto callback_mrm_state = std::bind(&RecoveryNode::on_mrm_state, this, _1);
50+
sub_mrm_state_ = create_subscription<MrmState>("/system/fail_safe/mrm_state",
51+
qos_mrm_state, callback_mrm_state);
52+
callback_group_ = create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
53+
srv_clear_mrm_ = create_client<std_srvs::srv::Trigger>("/system/clear_mrm",
54+
rmw_qos_profile_services_default, callback_group_);
55+
56+
fatal_error_ = false;
57+
mrm_occur_ = false;
58+
}
59+
60+
void RecoveryNode::on_graph(const DiagnosticGraph::ConstSharedPtr msg)
61+
{
62+
bool autonomous_available = false;
63+
for (const auto & node : msg->nodes) {
64+
if (node.status.name == "/autoware/modes/autonomous") {
65+
autonomous_available = node.status.level == DiagnosticStatus::OK;
66+
}
67+
// aggregate non-recoverable error
68+
if (node.status.name == "/autoware/fatal_error/autonomous_available") {
69+
if (node.status.level != DiagnosticStatus::OK){
70+
fatal_error_ = true;
71+
}
72+
}
73+
}
74+
75+
// 1. Not emergency
76+
// 2. Non-recovoerable errors have not happened
77+
// 3. on MRM
78+
if (autonomous_available && !fatal_error_ && mrm_occur_){
79+
clear_mrm();
80+
}
81+
}
82+
83+
void RecoveryNode::on_aw_state(const AutowareState::ConstSharedPtr msg){
84+
if (msg->state != AutowareState::DRIVING)
85+
fatal_error_ = false;
86+
}
87+
88+
void RecoveryNode::on_mrm_state(const MrmState::ConstSharedPtr msg){
89+
mrm_occur_ = msg->state != MrmState::NORMAL;
90+
}
91+
92+
void RecoveryNode::clear_mrm(){
93+
const auto req = std::make_shared<std_srvs::srv::Trigger::Request>();
94+
95+
if (!srv_clear_mrm_->service_is_ready()) {
96+
throw component_interface_utils::ServiceUnready("MRM clear server is not ready.");
97+
}
98+
auto logger = get_logger();
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+
{
104+
return;
105+
}
106+
if (!res.get()->success) {
107+
RCLCPP_INFO(logger, "Recovering MRM failed.");
108+
throw component_interface_utils::NoEffectWarning("MRM clear server is not available.");
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,69 @@
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 <std_msgs/msg/string.hpp>
24+
#include <std_srvs/srv/trigger.hpp>
25+
#include <component_interface_utils/rclcpp.hpp>
26+
#include <autoware_auto_system_msgs/msg/autoware_state.hpp>
27+
#include <autoware_adapi_v1_msgs/msg/mrm_state.hpp>
28+
29+
#include <functional>
30+
#include <map> // Use map for sorting keys.
31+
#include <memory>
32+
#include <string>
33+
#include <vector>
34+
35+
namespace diagnostic_graph_aggregator
36+
{
37+
38+
class RecoveryNode : public rclcpp::Node
39+
{
40+
public:
41+
RecoveryNode();
42+
43+
private:
44+
using AutowareState = autoware_auto_system_msgs::msg::AutowareState;
45+
using MrmState = autoware_adapi_v1_msgs::msg::MrmState;
46+
47+
bool fatal_error_;
48+
bool mrm_occur_;
49+
rclcpp::Subscription<DiagnosticGraph>::SharedPtr sub_graph_;
50+
rclcpp::Subscription<AutowareState>::SharedPtr sub_aw_state_;
51+
rclcpp::Subscription<MrmState>::SharedPtr sub_mrm_state_;
52+
53+
// service
54+
rclcpp::Client<std_srvs::srv::Trigger>::SharedPtr srv_clear_mrm_;
55+
56+
// callback group for service
57+
rclcpp::CallbackGroup::SharedPtr callback_group_;
58+
59+
void on_graph(const DiagnosticGraph::ConstSharedPtr msg);
60+
void on_aw_state(const AutowareState::ConstSharedPtr msg);
61+
void on_mrm_state(const MrmState::ConstSharedPtr msg);
62+
63+
void clear_mrm();
64+
65+
};
66+
67+
} // namespace diagnostic_graph_aggregator
68+
69+
#endif // NODE__RECOVERY_HPP_

0 commit comments

Comments
 (0)