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