Skip to content

Commit 1823b7f

Browse files
author
Dmitrii Koldaev
committed
use crosswalk user history
Signed-off-by: Dmitrii Koldaev <dmitrii.koldaev@tier4.jp>
1 parent 05e5c80 commit 1823b7f

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

perception/map_based_prediction/config/map_based_prediction.param.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
timeout_set_for_no_intention_to_walk: [1.0, 0.0] # [s] values of map
2828
# parameter for shoulder lane prediction
2929
prediction_time_horizon_rate_for_validate_shoulder_lane_length: 0.8
30+
use_crosswalk_user_history:
31+
match_lost_and_appeared_users: true
32+
remember_lost_users: true
3033

3134
# parameters for lc prediction
3235
lane_change_detection:

perception/map_based_prediction/include/map_based_prediction/map_based_prediction_node.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include <optional>
4949
#include <string>
5050
#include <unordered_map>
51+
#include <unordered_set>
5152
#include <utility>
5253
#include <vector>
5354

@@ -144,6 +145,7 @@ class MapBasedPredictionNode : public rclcpp::Node
144145
std::unordered_map<std::string, std::deque<ObjectData>> objects_history_;
145146
std::map<std::pair<std::string, lanelet::Id>, rclcpp::Time> stopped_times_against_green_;
146147
std::unordered_map<std::string, std::deque<CrosswalkUserData>> crosswalk_users_history_;
148+
std::unordered_map<std::string, std::string> known_matches_;
147149

148150
// Lanelet Map Pointers
149151
std::shared_ptr<lanelet::LaneletMap> lanelet_map_ptr_;
@@ -207,6 +209,9 @@ class MapBasedPredictionNode : public rclcpp::Node
207209
std::vector<double> distance_set_for_no_intention_to_walk_;
208210
std::vector<double> timeout_set_for_no_intention_to_walk_;
209211

212+
bool match_lost_and_appeared_crosswalk_users_;
213+
bool remember_lost_crosswalk_users_;
214+
210215
std::unique_ptr<tier4_autoware_utils::PublishedTimePublisher> published_time_publisher_;
211216

212217
// Member Functions
@@ -244,7 +249,8 @@ class MapBasedPredictionNode : public rclcpp::Node
244249
void updateCrosswalkUserHistory(
245250
const std_msgs::msg::Header & header, const TrackedObject & object,
246251
const std::string & object_id);
247-
252+
std::string tryMatchNewObjectToDisappeared(
253+
const std::string & object_id, std::unordered_map<std::string, TrackedObject> & current_users);
248254
std::vector<PredictedRefPath> getPredictedReferencePath(
249255
const TrackedObject & object, const LaneletsData & current_lanelets_data,
250256
const double object_detected_time);

perception/map_based_prediction/src/map_based_prediction_node.cpp

+89-1
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,10 @@ MapBasedPredictionNode::MapBasedPredictionNode(const rclcpp::NodeOptions & node_
822822
* parameter control the estimated path length = vx * th * (rate) */
823823
prediction_time_horizon_rate_for_validate_lane_length_ =
824824
declare_parameter<double>("prediction_time_horizon_rate_for_validate_shoulder_lane_length");
825-
825+
match_lost_and_appeared_crosswalk_users_ =
826+
declare_parameter<bool>("use_crosswalk_user_history.match_lost_and_appeared_users");
827+
remember_lost_crosswalk_users_ =
828+
declare_parameter<bool>("use_crosswalk_user_history.remember_lost_users");
826829
use_vehicle_acceleration_ = declare_parameter<bool>("use_vehicle_acceleration");
827830
speed_limit_multiplier_ = declare_parameter<double>("speed_limit_multiplier");
828831
acceleration_exponential_half_life_ =
@@ -969,6 +972,14 @@ void MapBasedPredictionNode::objectsCallback(const TrackedObjects::ConstSharedPt
969972

970973
auto invalidated_crosswalk_users = removeOldObjectsHistory(
971974
objects_detected_time, object_buffer_time_length_, crosswalk_users_history_);
975+
// delete matches that point to invalid object
976+
for (auto it = known_matches_.begin(); it != known_matches_.end();) {
977+
if (invalidated_crosswalk_users.count(it->second)) {
978+
it = known_matches_.erase(it);
979+
} else {
980+
++it;
981+
}
982+
}
972983

973984
// result output
974985
PredictedObjects output;
@@ -978,6 +989,19 @@ void MapBasedPredictionNode::objectsCallback(const TrackedObjects::ConstSharedPt
978989
// result debug
979990
visualization_msgs::msg::MarkerArray debug_markers;
980991

992+
// get current crosswalk users for later prediction
993+
std::unordered_map<std::string, TrackedObject> current_crosswalk_users;
994+
for (const auto & object : in_objects->objects) {
995+
const auto label_for_prediction =
996+
changeLabelForPrediction(object.classification.front().label, object, lanelet_map_ptr_);
997+
if (
998+
label_for_prediction == ObjectClassification::PEDESTRIAN ||
999+
label_for_prediction == ObjectClassification::BICYCLE) {
1000+
current_crosswalk_users[tier4_autoware_utils::toHexString(object.object_id)] = object;
1001+
}
1002+
}
1003+
std::unordered_set<std::string> predicted_crosswalk_users_ids;
1004+
9811005
for (const auto & object : in_objects->objects) {
9821006
std::string object_id = tier4_autoware_utils::toHexString(object.object_id);
9831007
TrackedObject transformed_object = object;
@@ -998,6 +1022,12 @@ void MapBasedPredictionNode::objectsCallback(const TrackedObjects::ConstSharedPt
9981022
switch (label) {
9991023
case ObjectClassification::PEDESTRIAN:
10001024
case ObjectClassification::BICYCLE: {
1025+
std::string object_id = tier4_autoware_utils::toHexString(object.object_id);
1026+
if (match_lost_and_appeared_crosswalk_users_) {
1027+
object_id = tryMatchNewObjectToDisappeared(object_id, current_crosswalk_users);
1028+
}
1029+
predicted_crosswalk_users_ids.insert(object_id);
1030+
updateCrosswalkUserHistory(output.header, transformed_object, object_id);
10011031
const auto predicted_object_crosswalk =
10021032
getPredictedObjectAsCrosswalkUser(transformed_object);
10031033
output.objects.push_back(predicted_object_crosswalk);
@@ -1163,6 +1193,19 @@ void MapBasedPredictionNode::objectsCallback(const TrackedObjects::ConstSharedPt
11631193
}
11641194
}
11651195

1196+
// process lost crosswalk users to tackle unstable detection
1197+
if (remember_lost_crosswalk_users_) {
1198+
for (const auto & [id, crosswalk_user] : crosswalk_users_history_) {
1199+
// get a predicted path for crosswalk users in history who didn't get path yet using latest
1200+
// message
1201+
if (predicted_crosswalk_users_ids.count(id) == 0) {
1202+
const auto predicted_object =
1203+
getPredictedObjectAsCrosswalkUser(crosswalk_user.back().tracked_object);
1204+
output.objects.push_back(predicted_object);
1205+
}
1206+
}
1207+
}
1208+
11661209
// Publish Results
11671210
pub_objects_->publish(output);
11681211
published_time_publisher_->publish_if_subscribed(pub_objects_, output.header.stamp);
@@ -1188,6 +1231,51 @@ void MapBasedPredictionNode::updateCrosswalkUserHistory(
11881231
}
11891232
}
11901233

1234+
std::string MapBasedPredictionNode::tryMatchNewObjectToDisappeared(
1235+
const std::string & object_id, std::unordered_map<std::string, TrackedObject> & current_users)
1236+
{
1237+
if (known_matches_.count(object_id)) {
1238+
std::string match_id = known_matches_[object_id];
1239+
// object in the history is already matched to something (possibly itself)
1240+
if (crosswalk_users_history_.count(match_id)) {
1241+
// avoid matching two appeared users to one user in history
1242+
current_users[match_id] = crosswalk_users_history_[match_id].back().tracked_object;
1243+
return match_id;
1244+
} else {
1245+
RCLCPP_WARN_STREAM(
1246+
get_logger(), "Crosswalk user was " << object_id << "was matched to " << match_id
1247+
<< " but the history has deleted. Rematching");
1248+
}
1249+
}
1250+
std::string match_id = object_id;
1251+
double best_score = std::numeric_limits<double>::max();
1252+
auto pos0 = current_users[object_id].kinematics.pose_with_covariance.pose.position;
1253+
for (const auto & [user_id, user_history] : crosswalk_users_history_) {
1254+
// user present in current_users and will be matched to itself
1255+
if (current_users.count(user_id)) {
1256+
continue;
1257+
}
1258+
// TODO(dkoldaev): implement more sophisticated scoring, for now simply dst to last position in
1259+
// history
1260+
auto pos = user_history.back().tracked_object.kinematics.pose_with_covariance.pose.position;
1261+
double score = std::hypot(pos.x - pos0.x, pos.y - pos0.y);
1262+
if (score < best_score) {
1263+
best_score = score;
1264+
match_id = user_id;
1265+
}
1266+
}
1267+
1268+
if (object_id != match_id) {
1269+
RCLCPP_INFO_STREAM(
1270+
get_logger(), "[Map Based Prediction]: Matched " << object_id << " to " << match_id);
1271+
// avoid matching two appeared users to one user in history
1272+
current_users[match_id] = crosswalk_users_history_[match_id].back().tracked_object;
1273+
}
1274+
1275+
known_matches_[object_id] = match_id;
1276+
return match_id;
1277+
}
1278+
11911279
bool MapBasedPredictionNode::doesPathCrossAnyFence(const PredictedPath & predicted_path)
11921280
{
11931281
const lanelet::ConstLineStrings3d & all_fences =

0 commit comments

Comments
 (0)