Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ namespace entity_behavior
{
namespace pedestrian
{
enum class SeeAroundMode { blind, aware };

class FollowLaneAction : public entity_behavior::PedestrianActionNode
{
Expand All @@ -47,9 +46,6 @@ class FollowLaneAction : public entity_behavior::PedestrianActionNode
return entity_behavior::PedestrianActionNode::providedPorts();
}
bool detectObstacleInLane(const lanelet::Ids pedestrian_lanes, const bool see_around) const;

private:
SeeAroundMode should_respect_see_around;
};
} // namespace pedestrian
} // namespace entity_behavior
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

namespace entity_behavior
{
enum class SeeAroundMode { blind, aware };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, but 'see around' might also apply to other entities. Maybe we should move this enum class SeeAroundMode to ActionNode since it's being moved anyway?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this part is only for pedestrian_ignore_see_around

class PedestrianActionNode : public ActionNode
{
public:
Expand All @@ -41,6 +42,9 @@ class PedestrianActionNode : public ActionNode
auto calculateUpdatedEntityStatusInWorldFrame(double target_speed) const
-> traffic_simulator::EntityStatus;
auto calculateUpdatedEntityStatus(double target_speed) const -> traffic_simulator::EntityStatus;

protected:
SeeAroundMode should_respect_see_around;
};
} // namespace entity_behavior

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class WalkStraightAction : public entity_behavior::PedestrianActionNode
{
return entity_behavior::PedestrianActionNode::providedPorts();
}
bool detectObstacleInFront(const bool see_around) const;
};
} // namespace pedestrian
} // namespace entity_behavior
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
// limitations under the License.

#include <behavior_tree_plugin/pedestrian/walk_straight_action.hpp>
#include <geometry/bounding_box.hpp>
#include <geometry/distance.hpp>
#include <geometry/quaternion/get_normal_vector.hpp>
#include <geometry/quaternion/quaternion_to_euler.hpp>
#include <geometry/transform.hpp>
#include <geometry/vector3/norm.hpp>
#include <geometry/vector3/normalize.hpp>
#include <geometry/vector3/operator.hpp>
#include <string>

namespace entity_behavior
Expand All @@ -34,10 +42,102 @@ WalkStraightAction::WalkStraightAction(
const std::string & name, const BT::NodeConfiguration & config)
: entity_behavior::PedestrianActionNode(name, config)
{
auto parameterToSeeAroundMode = [](std::string_view parameter) {
if (parameter == "blind") {
return SeeAroundMode::blind;
} else if (parameter == "aware") {
return SeeAroundMode::aware;
} else {
THROW_SIMULATION_ERROR("Unknown see_around mode. It must be \"blind\" or \"aware\".");
}
};

should_respect_see_around = parameterToSeeAroundMode(
common::getParameter<std::string>("pedestrian_ignore_see_around", "blind"));
}

void WalkStraightAction::getBlackBoardValues() { PedestrianActionNode::getBlackBoardValues(); }

bool checkPointIsInfront(
const geometry_msgs::msg::Pose & pose, const geometry_msgs::msg::Point & point)
{
const auto self_yaw = math::geometry::convertQuaternionToEulerAngle(pose.orientation).z;
const auto dx = point.x - pose.position.x;
const auto dy = point.y - pose.position.y;
const auto vec_yaw = std::atan2(dy, dx);
const auto yaw_diff = std::atan2(std::sin(vec_yaw - self_yaw), std::cos(vec_yaw - self_yaw));

return std::fabs(yaw_diff) <= boost::math::constants::half_pi<double>();
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool checkPointIsInfront(
const geometry_msgs::msg::Pose & pose, const geometry_msgs::msg::Point & point)
{
const auto self_yaw = math::geometry::convertQuaternionToEulerAngle(pose.orientation).z;
const auto dx = point.x - pose.position.x;
const auto dy = point.y - pose.position.y;
const auto vec_yaw = std::atan2(dy, dx);
const auto yaw_diff = std::atan2(std::sin(vec_yaw - self_yaw), std::cos(vec_yaw - self_yaw));
return std::fabs(yaw_diff) <= boost::math::constants::half_pi<double>();
}
bool isPointInFront(
const geometry_msgs::msg::Pose & pose, const geometry_msgs::msg::Point & target_point)
{
const auto self_yaw = math::geometry::convertQuaternionToEulerAngle(pose.orientation).z;
const auto angle_to_target_point = std::atan2(target_point.y - pose.position.y, target_point.x - pose.position.x);
const auto yaw_difference = std::atan2(std::sin(angle_to_target_point - self_yaw), std::cos(angle_to_target_point - self_yaw));
return std::fabs(yaw_difference) <= boost::math::constants::half_pi<double>();
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

bool WalkStraightAction::detectObstacleInFront(const bool see_around) const
{
if (should_respect_see_around == SeeAroundMode::blind) {
return false;
}

if (!see_around) {
return false;
}

auto hasObstacleInFrontOfPedestrian = [this](double distance) {
using math::geometry::operator-;
using math::geometry::operator*;

const auto & pedestrian_pose = canonicalized_entity_status_->getMapPose();

for (const auto & [_, entity_status] : other_entity_status_) {
const auto & other_position = entity_status.getMapPose().position;
const auto norm = math::geometry::norm(other_position - pedestrian_pose.position);
if (norm > distance) continue;

if (checkPointIsInfront(pedestrian_pose, other_position)) {
// is in front of pedestrian check if collide
const auto bounding_box_map_points = math::geometry::transformPoints(
pedestrian_pose,
math::geometry::getPointsFromBbox(canonicalized_entity_status_->getBoundingBox()));

std::vector<geometry_msgs::msg::Point> front_points;
std::vector<geometry_msgs::msg::Point> check_area_points;
for (const auto & point : bounding_box_map_points) {
if (checkPointIsInfront(pedestrian_pose, point)) {
front_points.push_back(point);
}
}
auto orientation_vector =
math::geometry::normalize(
math::geometry::convertQuaternionToEulerAngle(pedestrian_pose.orientation)) *
distance;
for (auto & point : front_points) {
check_area_points.push_back(point);
point.x += orientation_vector.x;
point.y += orientation_vector.z;
point.z += orientation_vector.y;
check_area_points.push_back(point);
}
const auto check_polygon = math::geometry::toBoostPolygon(check_area_points);
const auto poly =
math::geometry::toPolygon2D(entity_status.getMapPose(), entity_status.getBoundingBox());
if (
boost::geometry::intersects(check_polygon, poly) ||
boost::geometry::intersects(poly, check_polygon)) {
return true;
} else if (boost::geometry::disjoint(check_polygon, poly)) {
return false;
}
return true;
}
}
return false;
};

const double min_stop = calculateStopDistance(behavior_parameter_.dynamic_constraints);
const double stable_distance =
min_stop + canonicalized_entity_status_->getBoundingBox().dimensions.x;

return hasObstacleInFrontOfPedestrian(stable_distance);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, the names need to be improved to make them more informative - they should refer to what is actually being calculated (what the object contains).

In general, you always need to remember {} for if statements, const for immutable objects, and some relative step-by-step logic.

What is suggested here is only part of the changes; the whole thing needs to be reconsidered.

Suggested change
bool WalkStraightAction::detectObstacleInFront(const bool see_around) const
{
if (should_respect_see_around == SeeAroundMode::blind) {
return false;
}
if (!see_around) {
return false;
}
auto hasObstacleInFrontOfPedestrian = [this](double distance) {
using math::geometry::operator-;
using math::geometry::operator*;
const auto & pedestrian_pose = canonicalized_entity_status_->getMapPose();
for (const auto & [_, entity_status] : other_entity_status_) {
const auto & other_position = entity_status.getMapPose().position;
const auto norm = math::geometry::norm(other_position - pedestrian_pose.position);
if (norm > distance) continue;
if (checkPointIsInfront(pedestrian_pose, other_position)) {
// is in front of pedestrian check if collide
const auto bounding_box_map_points = math::geometry::transformPoints(
pedestrian_pose,
math::geometry::getPointsFromBbox(canonicalized_entity_status_->getBoundingBox()));
std::vector<geometry_msgs::msg::Point> front_points;
std::vector<geometry_msgs::msg::Point> check_area_points;
for (const auto & point : bounding_box_map_points) {
if (checkPointIsInfront(pedestrian_pose, point)) {
front_points.push_back(point);
}
}
auto orientation_vector =
math::geometry::normalize(
math::geometry::convertQuaternionToEulerAngle(pedestrian_pose.orientation)) *
distance;
for (auto & point : front_points) {
check_area_points.push_back(point);
point.x += orientation_vector.x;
point.y += orientation_vector.z;
point.z += orientation_vector.y;
check_area_points.push_back(point);
}
const auto check_polygon = math::geometry::toBoostPolygon(check_area_points);
const auto poly =
math::geometry::toPolygon2D(entity_status.getMapPose(), entity_status.getBoundingBox());
if (
boost::geometry::intersects(check_polygon, poly) ||
boost::geometry::intersects(poly, check_polygon)) {
return true;
} else if (boost::geometry::disjoint(check_polygon, poly)) {
return false;
}
return true;
}
}
return false;
};
const double min_stop = calculateStopDistance(behavior_parameter_.dynamic_constraints);
const double stable_distance =
min_stop + canonicalized_entity_status_->getBoundingBox().dimensions.x;
return hasObstacleInFrontOfPedestrian(stable_distance);
}
bool WalkStraightAction::detectObstacleInFront(const bool see_around) const
{
auto isObstacleInFrontOfPedestrian = [this](double detection_horizon) {
using math::geometry::operator-;
using math::geometry::operator*;
const auto & pedestrian_pose = canonicalized_entity_status_->getMapPose();
for (const auto & [_, entity_status] : other_entity_status_) {
const auto & other_position = entity_status.getMapPose().position;
if (const auto distance = math::geometry::norm(other_position - pedestrian_pose.position); distance <= detection_horizon) {
if (isPointInfront(pedestrian_pose, other_position)) {
/// @note if in front of pedestrian -> check if collide
const auto bounding_box_map_points = math::geometry::transformPoints(pedestrian_pose, math::geometry::getPointsFromBbox(canonicalized_entity_status_->getBoundingBox()));
std::vector<geometry_msgs::msg::Point> bounding_box_front_points;
for (const auto & point : bounding_box_map_points) {
if (isPointInfront(pedestrian_pose, point)) {
bounding_box_front_points.push_back(point);
}
}
/// @attention rename orientation_vector...
const auto orientation_vector = math::geometry::normalize(math::geometry::convertQuaternionToEulerAngle(pedestrian_pose.orientation)) * detection_horizon;
/// @attention [reply on github] Why is the point added twice to check_area_points?
std::vector<geometry_msgs::msg::Point> pedestrian_check_area_points;
for (auto & point : pedestrian_front_points) {
pedestrian_check_area_points.push_back(point);
point.x += orientation_vector.x;
point.y += orientation_vector.z;
point.z += orientation_vector.y;
pedestrian_check_area_points.push_back(point);
}
const auto pedestrian_check_area_polygon = math::geometry::toBoostPolygon(pedestrian_check_area_points);
const auto other_entity_polygon = math::geometry::toPolygon2D(entity_status.getMapPose(), entity_status.getBoundingBox());
if (boost::geometry::intersects(pedestrian_check_area_polygon, other_entity_polygon) or boost::geometry::intersects(other_entity_polygon, pedestrian_check_area_polygon)) {
return true;
} else if (boost::geometry::disjoint(pedestrian_check_area_polygon, other_entity_polygon)) {
return false;
} else {
return true;
}
}
}
}
return false;
};
if (not see_around or should_respect_see_around == SeeAroundMode::blind) {
return false;
} else {
const double detection_horizon = calculateStopDistance(behavior_parameter_.dynamic_constraints) + canonicalized_entity_status_->getBoundingBox().dimensions.x;
return isObstacleInFrontOfPedestrian(detection_horizon);
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed names and restructured function.

bool WalkStraightAction::checkPreconditions()
{
return request_ == traffic_simulator::behavior::Request::WALK_STRAIGHT;
Expand All @@ -48,6 +148,10 @@ BT::NodeStatus WalkStraightAction::doAction()
if (!target_speed_) {
target_speed_ = 1.111;
}

const auto obstacle_detector_result = detectObstacleInFront(behavior_parameter_.see_around);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name “obstacle_detector_result” suggests that it is a complex object, but I don't think it is, is it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed name

target_speed_ = obstacle_detector_result ? 0.0 : target_speed_;

setCanonicalizedEntityStatus(calculateUpdatedEntityStatusInWorldFrame(target_speed_.value()));
return BT::NodeStatus::RUNNING;
}
Expand Down