@@ -36,15 +36,24 @@ std::optional<MetricStatMap> MetricsCalculator::calculate(const Metric & metric)
36
36
if (!hasPassedTime (target_stamp)) {
37
37
return {};
38
38
}
39
- const auto target_objects = getObjectsByStamp (target_stamp);
40
- const ClassObjectsMap class_objects_map = separateObjectsByClass (target_objects);
39
+ const auto target_stamp_objects = getObjectsByStamp (target_stamp);
40
+ const auto class_objects_map = separateObjectsByClass (target_stamp_objects);
41
+
42
+ // filter stopped objects
43
+ constexpr double stopped_velocity_threshold = 0.1 ;
44
+ const auto stopped_objects =
45
+ filterObjectsByVelocity (target_stamp_objects, stopped_velocity_threshold);
46
+ const auto class_stopped_objects_map = separateObjectsByClass (stopped_objects);
47
+
41
48
switch (metric) {
42
49
case Metric::lateral_deviation:
43
50
return calcLateralDeviationMetrics (class_objects_map);
44
51
case Metric::yaw_deviation:
45
52
return calcYawDeviationMetrics (class_objects_map);
46
53
case Metric::predicted_path_deviation:
47
54
return calcPredictedPathDeviationMetrics (class_objects_map);
55
+ case Metric::yaw_rate:
56
+ return calcYawRateMetrics (class_stopped_objects_map);
48
57
default :
49
58
return {};
50
59
}
@@ -124,16 +133,46 @@ rclcpp::Time MetricsCalculator::getClosestStamp(const rclcpp::Time stamp) const
124
133
return closest_stamp;
125
134
}
126
135
127
- std::optional<PredictedObject > MetricsCalculator::getObjectByStamp (
128
- const std::string uuid, const rclcpp::Time stamp) const
136
+ std::optional<StampObjectMapIterator > MetricsCalculator::getClosestObjectIterator (
137
+ const std::string & uuid, const rclcpp::Time & stamp) const
129
138
{
130
139
const auto closest_stamp = getClosestStamp (stamp);
131
- auto it = std::lower_bound (
140
+ const auto it = std::lower_bound (
132
141
object_map_.at (uuid).begin (), object_map_.at (uuid).end (), closest_stamp,
133
142
[](const auto & pair, const rclcpp::Time & val) { return pair.first < val; });
134
143
135
- if (it != object_map_.at (uuid).end () && it->first == closest_stamp) {
136
- return it->second ;
144
+ return it != object_map_.at (uuid).end () ? std::optional<StampObjectMapIterator>(it)
145
+ : std::nullopt;
146
+ }
147
+
148
+ std::optional<PredictedObject> MetricsCalculator::getObjectByStamp (
149
+ const std::string uuid, const rclcpp::Time stamp) const
150
+ {
151
+ const auto obj_it_opt = getClosestObjectIterator (uuid, stamp);
152
+ if (obj_it_opt.has_value ()) {
153
+ const auto it = obj_it_opt.value ();
154
+ if (it->first == getClosestStamp (stamp)) {
155
+ return it->second ;
156
+ }
157
+ }
158
+ return std::nullopt;
159
+ }
160
+
161
+ std::optional<std::pair<rclcpp::Time, PredictedObject>> MetricsCalculator::getPreviousObjectByStamp (
162
+ const std::string uuid, const rclcpp::Time stamp) const
163
+ {
164
+ const auto obj_it_opt = getClosestObjectIterator (uuid, stamp);
165
+ if (obj_it_opt.has_value ()) {
166
+ auto it = obj_it_opt.value ();
167
+ if (it != object_map_.at (uuid).begin ()) {
168
+ // If it is exactly the closest stamp, move one back to get the previous
169
+ if (it->first == getClosestStamp (stamp)) {
170
+ --it;
171
+ } else {
172
+ // If it is not the closest stamp, it already points to the previous one due to lower_bound
173
+ }
174
+ return std::make_pair (it->first , it->second );
175
+ }
137
176
}
138
177
return std::nullopt;
139
178
}
@@ -313,6 +352,44 @@ Stat<double> MetricsCalculator::calcPredictedPathDeviationMetrics(
313
352
return stat;
314
353
}
315
354
355
+ MetricStatMap MetricsCalculator::calcYawRateMetrics (const ClassObjectsMap & class_objects_map) const
356
+ {
357
+ // calculate yaw rate for each object
358
+
359
+ MetricStatMap metric_stat_map{};
360
+
361
+ for (const auto & [label, objects] : class_objects_map) {
362
+ Stat<double > stat{};
363
+ const auto stamp = rclcpp::Time (objects.header .stamp );
364
+
365
+ for (const auto & object : objects.objects ) {
366
+ const auto uuid = tier4_autoware_utils::toHexString (object.object_id );
367
+ if (!hasPassedTime (uuid, stamp)) {
368
+ continue ;
369
+ }
370
+ const auto previous_object_with_stamp_opt = getPreviousObjectByStamp (uuid, stamp);
371
+ if (!previous_object_with_stamp_opt.has_value ()) {
372
+ continue ;
373
+ }
374
+ const auto [previous_stamp, previous_object] = previous_object_with_stamp_opt.value ();
375
+
376
+ const auto time_diff = (stamp - previous_stamp).seconds ();
377
+ if (time_diff == 0 ) {
378
+ continue ;
379
+ }
380
+ const auto current_yaw =
381
+ tf2::getYaw (object.kinematics .initial_pose_with_covariance .pose .orientation );
382
+ const auto previous_yaw =
383
+ tf2::getYaw (previous_object.kinematics .initial_pose_with_covariance .pose .orientation );
384
+ const auto yaw_rate =
385
+ std::abs (tier4_autoware_utils::normalizeRadian (current_yaw - previous_yaw) / time_diff);
386
+ stat.add (yaw_rate);
387
+ }
388
+ metric_stat_map[" yaw_rate_" + convertLabelToString (label)] = stat;
389
+ }
390
+ return metric_stat_map;
391
+ }
392
+
316
393
void MetricsCalculator::setPredictedObjects (const PredictedObjects & objects)
317
394
{
318
395
// using TimeStamp = builtin_interfaces::msg::Time;
0 commit comments