@@ -28,7 +28,6 @@ controlEvaluatorNode::controlEvaluatorNode(const rclcpp::NodeOptions & node_opti
28
28
: Node(" control_evaluator" , node_options)
29
29
{
30
30
using std::placeholders::_1;
31
-
32
31
control_diag_sub_ = create_subscription<DiagnosticArray>(
33
32
" ~/input/diagnostics" , 1 , std::bind (&controlEvaluatorNode::onDiagnostics, this , _1));
34
33
@@ -41,45 +40,140 @@ controlEvaluatorNode::controlEvaluatorNode(const rclcpp::NodeOptions & node_opti
41
40
rclcpp::create_timer (this , get_clock (), 100ms, std::bind (&controlEvaluatorNode::onTimer, this ));
42
41
}
43
42
44
- DiagnosticStatus controlEvaluatorNode::generateDiagnosticStatus (const bool is_emergency_brake) const
43
+ void controlEvaluatorNode::removeOldDiagnostics (const rclcpp::Time & stamp)
44
+ {
45
+ constexpr double KEEP_TIME = 1.0 ;
46
+ diag_queue_.erase (
47
+ std::remove_if (
48
+ diag_queue_.begin (), diag_queue_.end (),
49
+ [stamp](const std::pair<diagnostic_msgs::msg::DiagnosticStatus, rclcpp::Time> & p) {
50
+ return (stamp - p.second ).seconds () > KEEP_TIME;
51
+ }),
52
+ diag_queue_.end ());
53
+ }
54
+
55
+ void controlEvaluatorNode::removeDiagnosticsByName (const std::string & name)
56
+ {
57
+ diag_queue_.erase (
58
+ std::remove_if (
59
+ diag_queue_.begin (), diag_queue_.end (),
60
+ [&name](const std::pair<diagnostic_msgs::msg::DiagnosticStatus, rclcpp::Time> & p) {
61
+ return p.first .name .find (name) != std::string::npos;
62
+ }),
63
+ diag_queue_.end ());
64
+ }
65
+
66
+ void controlEvaluatorNode::addDiagnostic (
67
+ const diagnostic_msgs::msg::DiagnosticStatus & diag, const rclcpp::Time & stamp)
68
+ {
69
+ diag_queue_.push_back (std::make_pair (diag, stamp));
70
+ }
71
+
72
+ void controlEvaluatorNode::updateDiagnosticQueue (
73
+ const DiagnosticArray & input_diagnostics, const std::string & function,
74
+ const rclcpp::Time & stamp)
75
+ {
76
+ const auto it = std::find_if (
77
+ input_diagnostics.status .begin (), input_diagnostics.status .end (),
78
+ [&function](const diagnostic_msgs::msg::DiagnosticStatus & diag) {
79
+ return diag.name .find (function) != std::string::npos;
80
+ });
81
+ if (it != input_diagnostics.status .end ()) {
82
+ removeDiagnosticsByName (it->name );
83
+ addDiagnostic (*it, input_diagnostics.header .stamp );
84
+ }
85
+
86
+ removeOldDiagnostics (stamp);
87
+ }
88
+
89
+ void controlEvaluatorNode::onDiagnostics (const DiagnosticArray::ConstSharedPtr diag_msg)
90
+ {
91
+ // add target diagnostics to the queue and remove old ones
92
+ for (const auto & function : target_functions_) {
93
+ updateDiagnosticQueue (*diag_msg, function, now ());
94
+ }
95
+ }
96
+
97
+ DiagnosticStatus controlEvaluatorNode::generateAEBDiagnosticStatus (const DiagnosticStatus & diag)
45
98
{
46
99
DiagnosticStatus status;
47
100
status.level = status.OK ;
48
- status.name = " autonomous_emergency_braking " ;
101
+ status.name = diag. name ;
49
102
diagnostic_msgs::msg::KeyValue key_value;
50
103
key_value.key = " decision" ;
104
+ const bool is_emergency_brake = (diag.level == DiagnosticStatus::ERROR);
51
105
key_value.value = (is_emergency_brake) ? " stop" : " none" ;
52
106
status.values .push_back (key_value);
107
+
53
108
return status;
54
109
}
55
110
56
- void controlEvaluatorNode::onTimer ()
111
+ DiagnosticStatus controlEvaluatorNode::generateLateralDeviationDiagnosticStatus (
112
+ const Trajectory & traj, const Point & ego_point)
57
113
{
58
- if (!metrics_msg_.status .empty ()) {
59
- metrics_pub_->publish (metrics_msg_);
60
- metrics_msg_.status .clear ();
61
- }
114
+ const double lateral_deviation = metrics::calcLateralDeviation (traj, ego_point);
115
+
116
+ DiagnosticStatus status;
117
+ status.level = status.OK ;
118
+ status.name = " lateral_deviation" ;
119
+ diagnostic_msgs::msg::KeyValue key_value;
120
+ key_value.key = " metric_value" ;
121
+ key_value.value = std::to_string (lateral_deviation);
122
+ status.values .push_back (key_value);
123
+
124
+ return status;
62
125
}
63
126
64
- void controlEvaluatorNode::onDiagnostics (const DiagnosticArray::ConstSharedPtr diag_msg)
127
+ DiagnosticStatus controlEvaluatorNode::generateYawDeviationDiagnosticStatus (
128
+ const Trajectory & traj, const Pose & ego_pose)
65
129
{
66
- const auto start = now ();
67
- const auto aeb_status =
68
- std::find_if (diag_msg->status .begin (), diag_msg->status .end (), [](const auto & status) {
69
- const bool aeb_found = status.name .find (" autonomous_emergency_braking" ) != std::string::npos;
70
- return aeb_found;
71
- });
130
+ const double yaw_deviation = metrics::calcYawDeviation (traj, ego_pose);
72
131
73
- if (aeb_status == diag_msg->status .end ()) return ;
74
-
75
- const bool is_emergency_brake = (aeb_status->level == DiagnosticStatus::ERROR);
76
- metrics_msg_.header .stamp = now ();
77
- metrics_msg_.status .emplace_back (generateDiagnosticStatus (is_emergency_brake));
132
+ DiagnosticStatus status;
133
+ status.level = status.OK ;
134
+ status.name = " yaw_deviation" ;
135
+ diagnostic_msgs::msg::KeyValue key_value;
136
+ key_value.key = " metric_value" ;
137
+ key_value.value = std::to_string (yaw_deviation);
138
+ status.values .push_back (key_value);
78
139
79
- const auto runtime = (now () - start).seconds ();
80
- RCLCPP_DEBUG (get_logger (), " control evaluation calculation time: %2.2f ms" , runtime * 1e3 );
140
+ return status;
81
141
}
82
142
143
+ void controlEvaluatorNode::onTimer ()
144
+ {
145
+ DiagnosticArray metrics_msg;
146
+ const auto traj = traj_sub_.takeData ();
147
+ const auto odom = odometry_sub_.takeData ();
148
+
149
+ // generate decision diagnostics from input diagnostics
150
+ for (const auto & function : target_functions_) {
151
+ const auto it = std::find_if (
152
+ diag_queue_.begin (), diag_queue_.end (),
153
+ [&function](const std::pair<diagnostic_msgs::msg::DiagnosticStatus, rclcpp::Time> & p) {
154
+ return p.first .name .find (function) != std::string::npos;
155
+ });
156
+ if (it == diag_queue_.end ()) {
157
+ continue ;
158
+ }
159
+ // generate each decision diagnostics
160
+ // - AEB decision
161
+ if (it->first .name .find (" autonomous_emergency_braking" ) != std::string::npos) {
162
+ metrics_msg.status .push_back (generateAEBDiagnosticStatus (it->first ));
163
+ }
164
+ }
165
+
166
+ // calculate deviation metrics
167
+ if (odom && traj && !traj->points .empty ()) {
168
+ const Pose ego_pose = odom->pose .pose ;
169
+ metrics_msg.status .push_back (
170
+ generateLateralDeviationDiagnosticStatus (*traj, ego_pose.position ));
171
+ metrics_msg.status .push_back (generateYawDeviationDiagnosticStatus (*traj, ego_pose));
172
+ }
173
+
174
+ metrics_msg.header .stamp = now ();
175
+ metrics_pub_->publish (metrics_msg);
176
+ }
83
177
} // namespace control_diagnostics
84
178
85
179
#include " rclcpp_components/register_node_macro.hpp"
0 commit comments