Skip to content

Commit fbc7a9d

Browse files
authored
feat(dummy_infrastructure): auto approval when ego stops at stop line (#10223)
feat(dummy_infrastructur): auto approval when ego stops at stop line Signed-off-by: kosuke55 <kosuke.tnp@gmail.com>
1 parent 2a86019 commit fbc7a9d

File tree

6 files changed

+178
-37
lines changed

6 files changed

+178
-37
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
/**:
22
ros__parameters:
33
update_rate_hz: 10.0
4-
use_first_command: true
5-
use_command_state: false
6-
instrument_id: ""
7-
approval: false
8-
is_finalized: false
4+
use_first_command: false
5+
use_command_state: true
6+
instrument_id: '0'
7+
approval: true
8+
is_finalized: true
9+
auto_approval_mode: true
10+
stop_distance_threshold: 1.0
11+
stop_velocity_threshold: 0.1

system/autoware_dummy_infrastructure/include/autoware/dummy_infrastructure/dummy_infrastructure_node.hpp

+26-5
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,27 @@
1515
#ifndef AUTOWARE__DUMMY_INFRASTRUCTURE__DUMMY_INFRASTRUCTURE_NODE_HPP_
1616
#define AUTOWARE__DUMMY_INFRASTRUCTURE__DUMMY_INFRASTRUCTURE_NODE_HPP_
1717

18+
#include "autoware_utils/ros/polling_subscriber.hpp"
19+
1820
#include <rclcpp/rclcpp.hpp>
1921

22+
#include <nav_msgs/msg/odometry.hpp>
23+
#include <tier4_planning_msgs/msg/planning_factor_array.hpp>
2024
#include <tier4_v2x_msgs/msg/infrastructure_command_array.hpp>
2125
#include <tier4_v2x_msgs/msg/virtual_traffic_light_state_array.hpp>
2226

2327
#include <chrono>
2428
#include <memory>
29+
#include <optional>
30+
#include <set>
2531
#include <string>
32+
#include <utility>
2633
#include <vector>
2734

2835
namespace autoware::dummy_infrastructure
2936
{
37+
using nav_msgs::msg::Odometry;
38+
using tier4_planning_msgs::msg::PlanningFactorArray;
3039
using tier4_v2x_msgs::msg::InfrastructureCommand;
3140
using tier4_v2x_msgs::msg::InfrastructureCommandArray;
3241
using tier4_v2x_msgs::msg::VirtualTrafficLightState;
@@ -45,17 +54,23 @@ class DummyInfrastructureNode : public rclcpp::Node
4554
std::string instrument_id{};
4655
bool approval{};
4756
bool is_finalized{};
57+
bool auto_approval_mode{};
58+
double stop_distance_threshold{};
59+
double stop_velocity_threshold{};
4860
};
4961

5062
private:
51-
// Subscriber
52-
rclcpp::Subscription<InfrastructureCommandArray>::SharedPtr sub_command_array_{};
53-
54-
// Callback
55-
void onCommandArray(const InfrastructureCommandArray::ConstSharedPtr msg);
63+
autoware_utils::InterProcessPollingSubscriber<InfrastructureCommandArray> sub_command_array_{
64+
this, "~/input/command_array"};
65+
autoware_utils::InterProcessPollingSubscriber<PlanningFactorArray> sub_planning_factors_{
66+
this, "~/input/planning_factors"};
67+
autoware_utils::InterProcessPollingSubscriber<Odometry> sub_odometry_{this, "~/input/odometry"};
5668

5769
// Data Buffer
5870
InfrastructureCommandArray::ConstSharedPtr command_array_{};
71+
PlanningFactorArray::ConstSharedPtr planning_factors_{};
72+
Odometry::ConstSharedPtr current_odometry_{};
73+
std::set<std::string> approved_command_ids_{};
5974

6075
// Publisher
6176
rclcpp::Publisher<VirtualTrafficLightStateArray>::SharedPtr pub_state_array_{};
@@ -66,6 +81,12 @@ class DummyInfrastructureNode : public rclcpp::Node
6681
bool isDataReady();
6782
void onTimer();
6883

84+
// Auto approval check
85+
std::pair<bool, bool> getApprovalConditions() const;
86+
std::optional<std::string> getCurrentCommandId() const;
87+
std::pair<bool, bool> checkApprovalCommand(
88+
const std::string & command_id, const bool is_stopped, const bool is_near_stop_line) const;
89+
6990
// Parameter Server
7091
OnSetParametersCallbackHandle::SharedPtr set_param_res_;
7192
rcl_interfaces::msg::SetParametersResult onSetParam(

system/autoware_dummy_infrastructure/launch/dummy_infrastructure.launch.xml

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<launch>
33
<!-- Input -->
44
<arg name="input/command_array" default="/planning/scenario_planning/status/infrastructure_commands"/>
5+
<arg name="input/planning_factors" default="/planning/planning_factors/virtual_traffic_light"/>
6+
<arg name="input/odometry" default="/localization/kinematic_state"/>
57

68
<!-- Output -->
79
<arg name="output/state_array" default="/system/v2x/virtual_traffic_light_states"/>
@@ -13,6 +15,8 @@
1315
<node pkg="autoware_dummy_infrastructure" exec="autoware_dummy_infrastructure_node" name="dummy_infrastructure" output="screen">
1416
<!-- Input -->
1517
<remap from="~/input/command_array" to="$(var input/command_array)"/>
18+
<remap from="~/input/planning_factors" to="$(var input/planning_factors)"/>
19+
<remap from="~/input/odometry" to="$(var input/odometry)"/>
1620

1721
<!-- Output -->
1822
<remap from="~/output/state_array" to="$(var output/state_array)"/>

system/autoware_dummy_infrastructure/package.xml

+2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
<build_depend>libboost-dev</build_depend>
1919

20+
<depend>autoware_utils</depend>
2021
<depend>rclcpp</depend>
2122
<depend>rclcpp_components</depend>
23+
<depend>tier4_planning_msgs</depend>
2224
<depend>tier4_v2x_msgs</depend>
2325

2426
<test_depend>ament_lint_auto</test_depend>

system/autoware_dummy_infrastructure/schema/dummy_infrastructure.schema.json

+20-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,27 @@
2929
"approval": {
3030
"type": "boolean",
3131
"default": "false",
32-
"description": "set approval filed to ros param"
32+
"description": "Set approval field to ros param"
3333
},
3434
"is_finalized": {
3535
"type": "boolean",
3636
"default": "false",
3737
"description": "Stop at stop_line if finalization isn't completed"
38+
},
39+
"auto_approval_mode": {
40+
"type": "boolean",
41+
"default": "false",
42+
"description": "Automatically approve commands when vehicle has stopped near a virtual traffic light"
43+
},
44+
"stop_distance_threshold": {
45+
"type": "number",
46+
"default": "1.0",
47+
"description": "Distance threshold to determine if the vehicle is near a stop line [m]"
48+
},
49+
"stop_velocity_threshold": {
50+
"type": "number",
51+
"default": "0.1",
52+
"description": "Velocity threshold to determine if the vehicle has stopped [m/s]"
3853
}
3954
},
4055
"required": [
@@ -43,7 +58,10 @@
4358
"use_command_state",
4459
"instrument_id",
4560
"approval",
46-
"is_finalized"
61+
"is_finalized",
62+
"auto_approval_mode",
63+
"stop_distance_threshold",
64+
"stop_velocity_threshold"
4765
],
4866
"additionalProperties": false
4967
}

system/autoware_dummy_infrastructure/src/dummy_infrastructure_node/dummy_infrastructure_node.cpp

+118-25
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@
1616

1717
#include <boost/optional.hpp>
1818

19+
#include <algorithm>
20+
#include <cmath>
21+
#include <limits>
1922
#include <memory>
23+
#include <optional>
2024
#include <string>
25+
#include <utility>
2126
#include <vector>
2227

2328
using namespace std::literals;
@@ -46,7 +51,7 @@ bool update_param(
4651
return true;
4752
}
4853

49-
boost::optional<InfrastructureCommandArray> findCommand(
54+
std::optional<InfrastructureCommandArray> findCommand(
5055
const InfrastructureCommandArray & command_array, const std::string & instrument_id,
5156
const bool use_first_command, const bool use_command_state)
5257
{
@@ -72,12 +77,44 @@ boost::optional<InfrastructureCommandArray> findCommand(
7277
found_flag = true;
7378
}
7479
}
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;
79112
}
113+
114+
const auto min_it = std::min_element(distances.begin(), distances.end());
115+
return *min_it;
80116
}
117+
81118
} // namespace
82119

83120
DummyInfrastructureNode::DummyInfrastructureNode(const rclcpp::NodeOptions & node_options)
@@ -95,11 +132,9 @@ DummyInfrastructureNode::DummyInfrastructureNode(const rclcpp::NodeOptions & nod
95132
node_param_.instrument_id = declare_parameter<std::string>("instrument_id");
96133
node_param_.approval = declare_parameter<bool>("approval");
97134
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);
103138

104139
// Publisher
105140
pub_state_array_ = create_publisher<VirtualTrafficLightStateArray>("~/output/state_array", 1);
@@ -110,17 +145,12 @@ DummyInfrastructureNode::DummyInfrastructureNode(const rclcpp::NodeOptions & nod
110145
this, get_clock(), update_period_ns, std::bind(&DummyInfrastructureNode::onTimer, this));
111146
}
112147

113-
void DummyInfrastructureNode::onCommandArray(const InfrastructureCommandArray::ConstSharedPtr msg)
114-
{
115-
if (!msg->commands.empty()) {
116-
command_array_ = msg;
117-
}
118-
}
119-
120148
rcl_interfaces::msg::SetParametersResult DummyInfrastructureNode::onSetParam(
121149
const std::vector<rclcpp::Parameter> & params)
122150
{
123151
rcl_interfaces::msg::SetParametersResult result;
152+
result.successful = true;
153+
result.reason = "success";
124154

125155
try {
126156
// Copy to local variable
@@ -133,17 +163,23 @@ rcl_interfaces::msg::SetParametersResult DummyInfrastructureNode::onSetParam(
133163
update_param(params, "instrument_id", p.instrument_id);
134164
update_param(params, "approval", p.approval);
135165
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);
136169

137170
// Copy back to member variable
138171
node_param_ = p;
139172
} catch (const rclcpp::exceptions::InvalidParameterTypeException & e) {
140173
result.successful = false;
141174
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";
143181
}
144182

145-
result.successful = true;
146-
result.reason = "success";
147183
return result;
148184
}
149185

@@ -154,11 +190,33 @@ bool DummyInfrastructureNode::isDataReady()
154190
return false;
155191
}
156192

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+
157203
return true;
158204
}
159205

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+
160214
void DummyInfrastructureNode::onTimer()
161215
{
216+
command_array_ = sub_command_array_.take_data();
217+
planning_factors_ = sub_planning_factors_.take_data();
218+
current_odometry_ = sub_odometry_.take_data();
219+
162220
if (!isDataReady()) {
163221
return;
164222
}
@@ -174,24 +232,59 @@ void DummyInfrastructureNode::onTimer()
174232
state.stamp = get_clock()->now();
175233
state.id = node_param_.instrument_id;
176234
state.type = "dummy_infrastructure";
177-
state.approval = false;
235+
state.approval = node_param_.approval;
178236
state.is_finalized = node_param_.is_finalized;
179237
state_array.states.push_back(state);
180238
} 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{};
183255
state.stamp = get_clock()->now();
184256
state.id = command.id;
185257
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;
188260
state_array.states.push_back(state);
189261
}
190262
}
191263

192264
pub_state_array_->publish(state_array);
193265
}
194266

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+
195288
} // namespace autoware::dummy_infrastructure
196289

197290
#include <rclcpp_components/register_node_macro.hpp>

0 commit comments

Comments
 (0)