16
16
17
17
#include < boost/optional.hpp>
18
18
19
+ #include < algorithm>
20
+ #include < cmath>
21
+ #include < limits>
19
22
#include < memory>
23
+ #include < optional>
20
24
#include < string>
25
+ #include < utility>
21
26
#include < vector>
22
27
23
28
using namespace std ::literals;
@@ -46,7 +51,7 @@ bool update_param(
46
51
return true ;
47
52
}
48
53
49
- boost ::optional<InfrastructureCommandArray> findCommand (
54
+ std ::optional<InfrastructureCommandArray> findCommand (
50
55
const InfrastructureCommandArray & command_array, const std::string & instrument_id,
51
56
const bool use_first_command, const bool use_command_state)
52
57
{
@@ -72,12 +77,44 @@ boost::optional<InfrastructureCommandArray> findCommand(
72
77
found_flag = true ;
73
78
}
74
79
}
75
- if (found_flag) {
76
- return array;
77
- } else {
78
- return {};
80
+
81
+ return found_flag ? std::optional<InfrastructureCommandArray>{array} : std::nullopt;
82
+ }
83
+
84
+ std::optional<double > calcClosestStopLineDistance (
85
+ const PlanningFactorArray::ConstSharedPtr & planning_factors)
86
+ {
87
+ if (!planning_factors || planning_factors->factors .empty ()) {
88
+ return std::nullopt;
89
+ }
90
+
91
+ const auto vtl_it = std::find_if (
92
+ planning_factors->factors .begin (), planning_factors->factors .end (),
93
+ [](const auto & factor) { return factor.module == " virtual_traffic_light" ; });
94
+
95
+ if (vtl_it == planning_factors->factors .end ()) {
96
+ return std::nullopt;
97
+ }
98
+
99
+ std::vector<double > distances;
100
+ distances.reserve (planning_factors->factors .size () * 2 );
101
+
102
+ for (const auto & factor : planning_factors->factors ) {
103
+ if (factor.module == " virtual_traffic_light" ) {
104
+ for (const auto & control_point : factor.control_points ) {
105
+ distances.push_back (std::abs (control_point.distance ));
106
+ }
107
+ }
108
+ }
109
+
110
+ if (distances.empty ()) {
111
+ return std::nullopt;
79
112
}
113
+
114
+ const auto min_it = std::min_element (distances.begin (), distances.end ());
115
+ return *min_it;
80
116
}
117
+
81
118
} // namespace
82
119
83
120
DummyInfrastructureNode::DummyInfrastructureNode (const rclcpp::NodeOptions & node_options)
@@ -95,11 +132,9 @@ DummyInfrastructureNode::DummyInfrastructureNode(const rclcpp::NodeOptions & nod
95
132
node_param_.instrument_id = declare_parameter<std::string>(" instrument_id" );
96
133
node_param_.approval = declare_parameter<bool >(" approval" );
97
134
node_param_.is_finalized = declare_parameter<bool >(" is_finalized" );
98
-
99
- // Subscriber
100
- sub_command_array_ = create_subscription<InfrastructureCommandArray>(
101
- " ~/input/command_array" , rclcpp::QoS{1 },
102
- std::bind (&DummyInfrastructureNode::onCommandArray, this , _1));
135
+ node_param_.auto_approval_mode = declare_parameter<bool >(" auto_approval_mode" , false );
136
+ node_param_.stop_distance_threshold = declare_parameter<double >(" stop_distance_threshold" , 1.0 );
137
+ node_param_.stop_velocity_threshold = declare_parameter<double >(" stop_velocity_threshold" , 0.1 );
103
138
104
139
// Publisher
105
140
pub_state_array_ = create_publisher<VirtualTrafficLightStateArray>(" ~/output/state_array" , 1 );
@@ -110,17 +145,12 @@ DummyInfrastructureNode::DummyInfrastructureNode(const rclcpp::NodeOptions & nod
110
145
this , get_clock (), update_period_ns, std::bind (&DummyInfrastructureNode::onTimer, this ));
111
146
}
112
147
113
- void DummyInfrastructureNode::onCommandArray (const InfrastructureCommandArray::ConstSharedPtr msg)
114
- {
115
- if (!msg->commands .empty ()) {
116
- command_array_ = msg;
117
- }
118
- }
119
-
120
148
rcl_interfaces::msg::SetParametersResult DummyInfrastructureNode::onSetParam (
121
149
const std::vector<rclcpp::Parameter> & params)
122
150
{
123
151
rcl_interfaces::msg::SetParametersResult result;
152
+ result.successful = true ;
153
+ result.reason = " success" ;
124
154
125
155
try {
126
156
// Copy to local variable
@@ -133,17 +163,23 @@ rcl_interfaces::msg::SetParametersResult DummyInfrastructureNode::onSetParam(
133
163
update_param (params, " instrument_id" , p.instrument_id );
134
164
update_param (params, " approval" , p.approval );
135
165
update_param (params, " is_finalized" , p.is_finalized );
166
+ update_param (params, " auto_approval_mode" , p.auto_approval_mode );
167
+ update_param (params, " stop_distance_threshold" , p.stop_distance_threshold );
168
+ update_param (params, " stop_velocity_threshold" , p.stop_velocity_threshold );
136
169
137
170
// Copy back to member variable
138
171
node_param_ = p;
139
172
} catch (const rclcpp::exceptions::InvalidParameterTypeException & e) {
140
173
result.successful = false ;
141
174
result.reason = e.what ();
142
- return result;
175
+ } catch (const std::exception & e) {
176
+ result.successful = false ;
177
+ result.reason = " Exception occurred: " + std::string (e.what ());
178
+ } catch (...) {
179
+ result.successful = false ;
180
+ result.reason = " Unknown exception occurred" ;
143
181
}
144
182
145
- result.successful = true ;
146
- result.reason = " success" ;
147
183
return result;
148
184
}
149
185
@@ -154,11 +190,33 @@ bool DummyInfrastructureNode::isDataReady()
154
190
return false ;
155
191
}
156
192
193
+ if (!planning_factors_) {
194
+ RCLCPP_INFO_THROTTLE (get_logger (), *get_clock (), 1000 , " waiting for planning_factors msg..." );
195
+ return false ;
196
+ }
197
+
198
+ if (!current_odometry_) {
199
+ RCLCPP_INFO_THROTTLE (get_logger (), *get_clock (), 1000 , " waiting for odometry msg..." );
200
+ return false ;
201
+ }
202
+
157
203
return true ;
158
204
}
159
205
206
+ std::optional<std::string> DummyInfrastructureNode::getCurrentCommandId () const
207
+ {
208
+ if (!command_array_ || command_array_->commands .empty ()) {
209
+ return std::nullopt;
210
+ }
211
+ return command_array_->commands .front ().id ;
212
+ }
213
+
160
214
void DummyInfrastructureNode::onTimer ()
161
215
{
216
+ command_array_ = sub_command_array_.take_data ();
217
+ planning_factors_ = sub_planning_factors_.take_data ();
218
+ current_odometry_ = sub_odometry_.take_data ();
219
+
162
220
if (!isDataReady ()) {
163
221
return ;
164
222
}
@@ -174,24 +232,59 @@ void DummyInfrastructureNode::onTimer()
174
232
state.stamp = get_clock ()->now ();
175
233
state.id = node_param_.instrument_id ;
176
234
state.type = " dummy_infrastructure" ;
177
- state.approval = false ;
235
+ state.approval = node_param_. approval ;
178
236
state.is_finalized = node_param_.is_finalized ;
179
237
state_array.states .push_back (state);
180
238
} else {
181
- for (auto command : found_command_array->commands ) {
182
- VirtualTrafficLightState state;
239
+ const bool is_stopped =
240
+ std::abs (current_odometry_->twist .twist .linear .x ) < node_param_.stop_velocity_threshold ;
241
+ const auto min_distance_opt = calcClosestStopLineDistance (planning_factors_);
242
+ const bool is_near_stop_line =
243
+ min_distance_opt && *min_distance_opt <= node_param_.stop_distance_threshold ;
244
+
245
+ for (const auto & command : found_command_array->commands ) {
246
+ const auto [command_approval, command_is_finalized] =
247
+ checkApprovalCommand (command.id , is_stopped, is_near_stop_line);
248
+ if (command_approval && command_is_finalized) {
249
+ if (approved_command_ids_.find (command.id ) == approved_command_ids_.end ()) {
250
+ approved_command_ids_.insert (command.id );
251
+ RCLCPP_INFO (get_logger (), " Approved new command ID %s" , command.id .c_str ());
252
+ }
253
+ }
254
+ VirtualTrafficLightState state{};
183
255
state.stamp = get_clock ()->now ();
184
256
state.id = command.id ;
185
257
state.type = command.type ;
186
- state.approval = node_param_. approval ;
187
- state.is_finalized = node_param_. is_finalized ;
258
+ state.approval = command_approval ;
259
+ state.is_finalized = command_is_finalized ;
188
260
state_array.states .push_back (state);
189
261
}
190
262
}
191
263
192
264
pub_state_array_->publish (state_array);
193
265
}
194
266
267
+ std::pair<bool , bool > DummyInfrastructureNode::checkApprovalCommand (
268
+ const std::string & command_id, const bool is_stopped, const bool is_near_stop_line) const
269
+ {
270
+ if (!node_param_.auto_approval_mode ) {
271
+ return {node_param_.approval , node_param_.is_finalized };
272
+ }
273
+
274
+ if (approved_command_ids_.find (command_id) != approved_command_ids_.end ()) {
275
+ return {true , true };
276
+ }
277
+
278
+ if (is_stopped && is_near_stop_line) {
279
+ if (approved_command_ids_.find (command_id) == approved_command_ids_.end ()) {
280
+ RCLCPP_INFO (get_logger (), " Command ID %s meets approval conditions" , command_id.c_str ());
281
+ }
282
+ return {true , true };
283
+ }
284
+
285
+ return {false , false };
286
+ }
287
+
195
288
} // namespace autoware::dummy_infrastructure
196
289
197
290
#include < rclcpp_components/register_node_macro.hpp>
0 commit comments