Skip to content

Commit 07d6ef3

Browse files
authoredApr 18, 2025··
Merge pull request #1566 from tier4/feature/pedestrian_awareness
Feature/pedestrian awareness
2 parents 7b3dba6 + 2b70665 commit 07d6ef3

File tree

6 files changed

+106
-0
lines changed

6 files changed

+106
-0
lines changed
 

‎docs/developer_guide/NPCBehavior.md

+23
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,29 @@ graph TD
159159
| FollowLane | Entity following the lane which it is exist. | | |
160160
| WalkStraight | Entity walk forward and without considering lane. | | |
161161

162+
### Property `isBlind`
163+
164+
**Summary** - Specifies whether the behavior takes surrounding entities into consideration.
165+
166+
**Purpose** - Prevents specific scenarios from failing, such as a pedestrian colliding with a stopped vehicle, by behaving considerately toward surrounding entities.
167+
168+
**Specification** - The vehicle stops only when it enters a lane currently occupied by another entity and the entity is located ahead.
169+
170+
**Note** - For pedestrians, this feature is disabled by default to maintain backward compatibility. It can be enabled by setting the `pedestrian_ignore_see_around` to `aware` in the launch file execution options.
171+
172+
**Default behavior** - If the property is not specified, the default value is `"false"`.
173+
174+
**Example** -
175+
```
176+
ObjectController:
177+
Controller:
178+
name: '...'
179+
Properties:
180+
Property:
181+
- name: "isBlind"
182+
value: "false"
183+
```
184+
162185
## Pedestrian NPC (with Do-Nothing)
163186

164187
When this behavior is used, entity can only be moved by specifying its pose, velocity, acceleration, jerk, etc. via the `API::setEntityStatus` function, etc.

‎openscenario/openscenario_interpreter/src/syntax/add_entity_action.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ try {
139139
}
140140

141141
TeleportAction::teleport(entity_ref, position);
142+
AssignControllerAction(entity.as<ScenarioObject>().object_controller)(entity_ref);
142143
},
143144
[&](const MiscObject & misc_object) {
144145
if (position.is<WorldPosition>()) {

‎simulation/behavior_tree_plugin/include/behavior_tree_plugin/pedestrian/follow_lane_action.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
#include <behaviortree_cpp_v3/bt_factory.h>
2020

2121
#include <behavior_tree_plugin/pedestrian/pedestrian_action_node.hpp>
22+
#include <geometry/vector3/operator.hpp>
23+
#include <get_parameter/get_parameter.hpp>
2224
#include <memory>
25+
#include <scenario_simulator_exception/exception.hpp>
2326
#include <string>
2427
#include <traffic_simulator/hdmap_utils/hdmap_utils.hpp>
2528
#include <traffic_simulator_msgs/msg/entity_status.hpp>
@@ -29,6 +32,8 @@ namespace entity_behavior
2932
{
3033
namespace pedestrian
3134
{
35+
enum class SeeAroundMode { blind, aware };
36+
3237
class FollowLaneAction : public entity_behavior::PedestrianActionNode
3338
{
3439
public:
@@ -39,6 +44,10 @@ class FollowLaneAction : public entity_behavior::PedestrianActionNode
3944
{
4045
return entity_behavior::PedestrianActionNode::providedPorts();
4146
}
47+
bool detectObstacleInLane(const lanelet::Ids pedestrian_lanes, const bool see_around) const;
48+
49+
private:
50+
SeeAroundMode should_respect_see_around;
4251
};
4352
} // namespace pedestrian
4453
} // namespace entity_behavior

‎simulation/behavior_tree_plugin/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
<depend>behaviortree_cpp_v3</depend>
1313
<depend>geometry</depend>
14+
<depend>get_parameter</depend>
1415
<depend>pluginlib</depend>
1516
<depend>rclcpp</depend>
1617
<depend>traffic_simulator</depend>

‎simulation/behavior_tree_plugin/src/pedestrian/follow_lane_action.cpp

+68
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,73 @@ namespace pedestrian
2626
FollowLaneAction::FollowLaneAction(const std::string & name, const BT::NodeConfiguration & config)
2727
: entity_behavior::PedestrianActionNode(name, config)
2828
{
29+
auto parameterToSeeAroundMode = [](std::string_view parameter) {
30+
if (parameter == "blind") {
31+
return SeeAroundMode::blind;
32+
} else if (parameter == "aware") {
33+
return SeeAroundMode::aware;
34+
} else {
35+
THROW_SIMULATION_ERROR("Unknown see_around mode. It must be \"blind\" or \"aware\".");
36+
}
37+
};
38+
39+
should_respect_see_around = parameterToSeeAroundMode(
40+
common::getParameter<std::string>("pedestrian_ignore_see_around", "blind"));
2941
}
3042

3143
void FollowLaneAction::getBlackBoardValues() { PedestrianActionNode::getBlackBoardValues(); }
3244

45+
bool FollowLaneAction::detectObstacleInLane(
46+
const lanelet::Ids pedestrian_lanes, const bool see_around) const
47+
{
48+
if (should_respect_see_around == SeeAroundMode::blind) {
49+
return false;
50+
}
51+
52+
if (!see_around) {
53+
return false;
54+
}
55+
56+
auto hasObstacleInPedestrianLanes = [this](const lanelet::Ids pedestrian_lanes_local) {
57+
lanelet::Ids other_entity_lane_ids;
58+
for (const auto & [_, status] : other_entity_status) {
59+
if (status.isInLanelet()) {
60+
other_entity_lane_ids.push_back(status.getLaneletId());
61+
}
62+
}
63+
std::unordered_set<lanelet::Id> other_lane_id_set(
64+
other_entity_lane_ids.begin(), other_entity_lane_ids.end());
65+
for (const auto & pedestrian_lane : pedestrian_lanes_local) {
66+
if (other_lane_id_set.count(pedestrian_lane)) {
67+
return true;
68+
}
69+
}
70+
return false;
71+
};
72+
73+
auto hasObstacleInFrontOfPedestrian = [this]() {
74+
using math::geometry::operator-;
75+
76+
const auto & pedestrian_position = canonicalized_entity_status->getMapPose().position;
77+
78+
for (const auto & [_, entity_status] : other_entity_status) {
79+
const auto & other_position = entity_status.getMapPose().position;
80+
const auto relative_position = other_position - pedestrian_position;
81+
const double relative_angle_rad = std::atan2(relative_position.y, relative_position.x);
82+
if (relative_angle_rad > 0) {
83+
return true;
84+
}
85+
}
86+
return false;
87+
};
88+
89+
if (hasObstacleInPedestrianLanes(pedestrian_lanes) && hasObstacleInFrontOfPedestrian()) {
90+
return true;
91+
} else {
92+
return false;
93+
}
94+
}
95+
3396
BT::NodeStatus FollowLaneAction::tick()
3497
{
3598
getBlackBoardValues();
@@ -47,6 +110,11 @@ BT::NodeStatus FollowLaneAction::tick()
47110
if (!target_speed) {
48111
target_speed = hdmap_utils->getSpeedLimit(following_lanelets);
49112
}
113+
114+
const auto obstacle_detector_result =
115+
detectObstacleInLane(following_lanelets, behavior_parameter.see_around);
116+
target_speed = obstacle_detector_result ? 0.0 : target_speed;
117+
50118
setCanonicalizedEntityStatus(calculateUpdatedEntityStatus(target_speed.value()));
51119
return BT::NodeStatus::RUNNING;
52120
}

‎test_runner/scenario_test_runner/launch/scenario_test_runner.launch.py

+4
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def launch_setup(context, *args, **kwargs):
8585
output_directory = LaunchConfiguration("output_directory", default=Path("/tmp"))
8686
override_parameters = LaunchConfiguration("override_parameters", default="")
8787
parameter_file_path = LaunchConfiguration("parameter_file_path", default=Path(get_package_share_directory("scenario_test_runner")) / "config/parameters.yaml")
88+
pedestrian_ignore_see_around = LaunchConfiguration("pedestrian_ignore_see_around", default="blind")
8889
port = LaunchConfiguration("port", default=5555)
8990
publish_empty_context = LaunchConfiguration("publish_empty_context", default=False)
9091
record = LaunchConfiguration("record", default=True)
@@ -114,6 +115,7 @@ def launch_setup(context, *args, **kwargs):
114115
print(f"output_directory := {output_directory.perform(context)}")
115116
print(f"override_parameters := {override_parameters.perform(context)}")
116117
print(f"parameter_file_path := {parameter_file_path.perform(context)}")
118+
print(f"pedestrian_ignore_see_around := {pedestrian_ignore_see_around.perform(context)}")
117119
print(f"port := {port.perform(context)}")
118120
print(f"publish_empty_context := {publish_empty_context.perform(context)}")
119121
print(f"record := {record.perform(context)}")
@@ -142,6 +144,7 @@ def make_parameters():
142144
{"consider_pose_by_road_slope": consider_pose_by_road_slope},
143145
{"initialize_duration": initialize_duration},
144146
{"launch_autoware": launch_autoware},
147+
{"pedestrian_ignore_see_around": pedestrian_ignore_see_around},
145148
{"port": port},
146149
{"publish_empty_context" : publish_empty_context},
147150
{"record": record},
@@ -200,6 +203,7 @@ def collect_prefixed_parameters():
200203
DeclareLaunchArgument("launch_rviz", default_value=launch_rviz ),
201204
DeclareLaunchArgument("output_directory", default_value=output_directory ),
202205
DeclareLaunchArgument("parameter_file_path", default_value=parameter_file_path ),
206+
DeclareLaunchArgument("pedestrian_ignore_see_around", default_value=pedestrian_ignore_see_around ),
203207
DeclareLaunchArgument("publish_empty_context", default_value=publish_empty_context ),
204208
DeclareLaunchArgument("rviz_config", default_value=rviz_config ),
205209
DeclareLaunchArgument("scenario", default_value=scenario ),

0 commit comments

Comments
 (0)
Please sign in to comment.