|
| 1 | +// Copyright 2026 TIER IV, Inc. |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +#include "epdms_aggregation.hpp" |
| 16 | + |
| 17 | +#include <cmath> |
| 18 | + |
| 19 | +namespace autoware::planning_data_analyzer::metrics |
| 20 | +{ |
| 21 | + |
| 22 | +namespace |
| 23 | +{ |
| 24 | + |
| 25 | +constexpr double kHumanFilterZeroEpsilon = 1.0e-9; |
| 26 | + |
| 27 | +double apply_human_filter( |
| 28 | + const double agent_value, const bool agent_available, const double human_value, |
| 29 | + const bool human_available, bool & applied) |
| 30 | +{ |
| 31 | + applied = agent_available && human_available && std::abs(human_value) <= kHumanFilterZeroEpsilon; |
| 32 | + return applied ? 1.0 : agent_value; |
| 33 | +} |
| 34 | + |
| 35 | +} // namespace |
| 36 | + |
| 37 | +HumanFilterMetrics calculate_human_filter_metrics( |
| 38 | + const EpdmsMetricSnapshot & agent_metrics, const EpdmsMetricSnapshot & human_metrics) |
| 39 | +{ |
| 40 | + HumanFilterMetrics result; |
| 41 | + |
| 42 | + result.human_history_comfort = human_metrics.history_comfort; |
| 43 | + result.human_history_comfort_available = human_metrics.history_comfort_available; |
| 44 | + result.filtered_history_comfort = apply_human_filter( |
| 45 | + agent_metrics.history_comfort, agent_metrics.history_comfort_available, |
| 46 | + human_metrics.history_comfort, human_metrics.history_comfort_available, |
| 47 | + result.history_comfort_filter_applied); |
| 48 | + |
| 49 | + result.human_extended_comfort = human_metrics.extended_comfort; |
| 50 | + result.human_extended_comfort_available = human_metrics.extended_comfort_available; |
| 51 | + result.filtered_extended_comfort = apply_human_filter( |
| 52 | + agent_metrics.extended_comfort, agent_metrics.extended_comfort_available, |
| 53 | + human_metrics.extended_comfort, human_metrics.extended_comfort_available, |
| 54 | + result.extended_comfort_filter_applied); |
| 55 | + |
| 56 | + result.human_ego_progress = human_metrics.ego_progress; |
| 57 | + result.human_ego_progress_available = human_metrics.ego_progress_available; |
| 58 | + result.filtered_ego_progress = apply_human_filter( |
| 59 | + agent_metrics.ego_progress, agent_metrics.ego_progress_available, human_metrics.ego_progress, |
| 60 | + human_metrics.ego_progress_available, result.ego_progress_filter_applied); |
| 61 | + |
| 62 | + result.human_time_to_collision_within_bound = human_metrics.time_to_collision_within_bound; |
| 63 | + result.human_time_to_collision_within_bound_available = |
| 64 | + human_metrics.time_to_collision_within_bound_available; |
| 65 | + result.filtered_time_to_collision_within_bound = apply_human_filter( |
| 66 | + agent_metrics.time_to_collision_within_bound, |
| 67 | + agent_metrics.time_to_collision_within_bound_available, |
| 68 | + human_metrics.time_to_collision_within_bound, |
| 69 | + human_metrics.time_to_collision_within_bound_available, |
| 70 | + result.time_to_collision_within_bound_filter_applied); |
| 71 | + |
| 72 | + result.human_lane_keeping = human_metrics.lane_keeping; |
| 73 | + result.human_lane_keeping_available = human_metrics.lane_keeping_available; |
| 74 | + result.filtered_lane_keeping = apply_human_filter( |
| 75 | + agent_metrics.lane_keeping, agent_metrics.lane_keeping_available, human_metrics.lane_keeping, |
| 76 | + human_metrics.lane_keeping_available, result.lane_keeping_filter_applied); |
| 77 | + |
| 78 | + result.human_drivable_area_compliance = human_metrics.drivable_area_compliance; |
| 79 | + result.human_drivable_area_compliance_available = |
| 80 | + human_metrics.drivable_area_compliance_available; |
| 81 | + result.filtered_drivable_area_compliance = apply_human_filter( |
| 82 | + agent_metrics.drivable_area_compliance, agent_metrics.drivable_area_compliance_available, |
| 83 | + human_metrics.drivable_area_compliance, human_metrics.drivable_area_compliance_available, |
| 84 | + result.drivable_area_compliance_filter_applied); |
| 85 | + |
| 86 | + result.human_no_at_fault_collision = human_metrics.no_at_fault_collision; |
| 87 | + result.human_no_at_fault_collision_available = human_metrics.no_at_fault_collision_available; |
| 88 | + result.filtered_no_at_fault_collision = apply_human_filter( |
| 89 | + agent_metrics.no_at_fault_collision, agent_metrics.no_at_fault_collision_available, |
| 90 | + human_metrics.no_at_fault_collision, human_metrics.no_at_fault_collision_available, |
| 91 | + result.no_at_fault_collision_filter_applied); |
| 92 | + |
| 93 | + result.human_driving_direction_compliance = human_metrics.driving_direction_compliance; |
| 94 | + result.human_driving_direction_compliance_available = |
| 95 | + human_metrics.driving_direction_compliance_available; |
| 96 | + result.filtered_driving_direction_compliance = apply_human_filter( |
| 97 | + agent_metrics.driving_direction_compliance, |
| 98 | + agent_metrics.driving_direction_compliance_available, |
| 99 | + human_metrics.driving_direction_compliance, |
| 100 | + human_metrics.driving_direction_compliance_available, |
| 101 | + result.driving_direction_compliance_filter_applied); |
| 102 | + |
| 103 | + result.human_traffic_light_compliance = human_metrics.traffic_light_compliance; |
| 104 | + result.human_traffic_light_compliance_available = |
| 105 | + human_metrics.traffic_light_compliance_available; |
| 106 | + result.filtered_traffic_light_compliance = apply_human_filter( |
| 107 | + agent_metrics.traffic_light_compliance, agent_metrics.traffic_light_compliance_available, |
| 108 | + human_metrics.traffic_light_compliance, human_metrics.traffic_light_compliance_available, |
| 109 | + result.traffic_light_compliance_filter_applied); |
| 110 | + |
| 111 | + return result; |
| 112 | +} |
| 113 | + |
| 114 | +SyntheticEpdmsMetrics calculate_synthetic_epdms( |
| 115 | + const EpdmsMetricSnapshot & agent_metrics, const HumanFilterMetrics & human_filter_metrics) |
| 116 | +{ |
| 117 | + SyntheticEpdmsMetrics result; |
| 118 | + constexpr double kSyntheticWeightedDenominator = 16.0; |
| 119 | + |
| 120 | + const bool raw_multiplicative_available = agent_metrics.no_at_fault_collision_available && |
| 121 | + agent_metrics.drivable_area_compliance_available && |
| 122 | + agent_metrics.driving_direction_compliance_available && |
| 123 | + agent_metrics.traffic_light_compliance_available; |
| 124 | + const bool raw_weighted_available = agent_metrics.ego_progress_available && |
| 125 | + agent_metrics.time_to_collision_within_bound_available && |
| 126 | + agent_metrics.lane_keeping_available && |
| 127 | + agent_metrics.history_comfort_available && |
| 128 | + agent_metrics.extended_comfort_available; |
| 129 | + result.raw_available = raw_multiplicative_available && raw_weighted_available; |
| 130 | + if (result.raw_available) { |
| 131 | + result.raw_multiplicative_metrics_prod = |
| 132 | + agent_metrics.no_at_fault_collision * agent_metrics.drivable_area_compliance * |
| 133 | + agent_metrics.driving_direction_compliance * agent_metrics.traffic_light_compliance; |
| 134 | + result.raw_weighted_metrics = |
| 135 | + (5.0 * agent_metrics.ego_progress + 5.0 * agent_metrics.time_to_collision_within_bound + |
| 136 | + 2.0 * agent_metrics.lane_keeping + 2.0 * agent_metrics.history_comfort + |
| 137 | + 2.0 * agent_metrics.extended_comfort) / |
| 138 | + kSyntheticWeightedDenominator; |
| 139 | + result.raw_epdms = result.raw_multiplicative_metrics_prod * result.raw_weighted_metrics; |
| 140 | + } |
| 141 | + |
| 142 | + const bool human_filtered_multiplicative_available = |
| 143 | + agent_metrics.no_at_fault_collision_available && |
| 144 | + agent_metrics.drivable_area_compliance_available && |
| 145 | + agent_metrics.driving_direction_compliance_available && |
| 146 | + agent_metrics.traffic_light_compliance_available; |
| 147 | + const bool human_filtered_weighted_available = |
| 148 | + agent_metrics.ego_progress_available && |
| 149 | + agent_metrics.time_to_collision_within_bound_available && |
| 150 | + agent_metrics.lane_keeping_available && agent_metrics.history_comfort_available && |
| 151 | + agent_metrics.extended_comfort_available; |
| 152 | + result.human_filtered_available = |
| 153 | + human_filtered_multiplicative_available && human_filtered_weighted_available; |
| 154 | + if (result.human_filtered_available) { |
| 155 | + result.human_filtered_multiplicative_metrics_prod = |
| 156 | + human_filter_metrics.filtered_no_at_fault_collision * |
| 157 | + human_filter_metrics.filtered_drivable_area_compliance * |
| 158 | + human_filter_metrics.filtered_driving_direction_compliance * |
| 159 | + human_filter_metrics.filtered_traffic_light_compliance; |
| 160 | + const double filtered_ego_progress = |
| 161 | + human_filter_metrics.ego_progress_filter_applied ? 1.0 : agent_metrics.ego_progress; |
| 162 | + result.human_filtered_weighted_metrics = |
| 163 | + (5.0 * filtered_ego_progress + |
| 164 | + 5.0 * human_filter_metrics.filtered_time_to_collision_within_bound + |
| 165 | + 2.0 * human_filter_metrics.filtered_lane_keeping + |
| 166 | + 2.0 * human_filter_metrics.filtered_history_comfort + |
| 167 | + 2.0 * human_filter_metrics.filtered_extended_comfort) / |
| 168 | + kSyntheticWeightedDenominator; |
| 169 | + result.human_filtered_epdms = |
| 170 | + result.human_filtered_multiplicative_metrics_prod * result.human_filtered_weighted_metrics; |
| 171 | + } |
| 172 | + |
| 173 | + return result; |
| 174 | +} |
| 175 | + |
| 176 | +} // namespace autoware::planning_data_analyzer::metrics |
0 commit comments