2from rclpy.node
import Node
3from custom_interfaces.msg
import (
12from geometry_msgs.msg
import TwistWithCovarianceStamped, TransformStamped
15 get_mean_squared_difference,
16 get_average_difference,
17 get_inter_cones_distance,
21 compute_closest_distances,
23 get_mean_squared_error,
26 format_vehicle_state_msg,
28 find_closest_elements,
32from tf2_ros.transform_listener
import TransformListener
34 ADAPTER_CONSTRUCTOR_DICTINARY,
35 ADAPTER_POINT_CLOUD_TOPIC_DICTIONARY,
36 ADAPTER_POINT_CLOUD_TOPIC_QOS_DICTIONARY,
40import rclpy.subscription
41from std_msgs.msg
import Float32, Float32MultiArray, MultiArrayDimension, Int32, Float64
42from sensor_msgs.msg
import PointCloud2
46from message_filters
import TimeSynchronizer
47from std_msgs.msg
import Float32, Float64MultiArray
53from ament_index_python.packages
import get_package_prefix
58 A ROS2 node for computing and publishing the system's real-time metrics
63 Initializes the Evaluator Node.
64 This function sets up the necessary parameters, subscriptions, and publishers for the Evaluator Node.
65 It also initializes variables for storing metrics over time.
72 self.get_logger().info(
"Evaluator Node has started")
78 self.get_logger().error(
79 "Simulated perception is not supported for FSDS adapter"
85 self, ConeArray,
"/perception/cones"
88 self, ConeArray,
"/state_estimation/map"
91 self, Velocities,
"/state_estimation/velocities"
94 self, Pose,
"/state_estimation/vehicle_pose"
97 self, PathPointArray,
"/path_planning/path"
105 [[p.x, p.y, p.v]
for p
in msg.pathpoint_array],
114 sqrt(msg.velocity_x**2 + msg.velocity_y**2),
130 self, PathPointArray,
"/path_planning/mock_path"
137 [[p.x, p.y, p.v]
for p
in msg.pathpoint_array],
143 "/state_estimation/execution_time/correction_step",
149 "/state_estimation/execution_time/prediction_step",
155 "/path_planning/execution_time",
161 "/perception/execution_time",
167 "/control/execution_time",
178 Float32,
"/evaluator/perception/mean_difference", 10
181 Float32,
"/evaluator/perception/mean_squared_difference", 10
184 Float32,
"/evaluator/perception/root_mean_squared_difference", 10
187 Float32,
"/evaluator/perception/inter_cones_distance", 10
190 Int32,
"/evaluator/perception/false_positives", 10
193 Float32,
"/evaluator/perception/precision", 10
196 Float32,
"/evaluator/perception/recall", 10
199 Int32,
"/evaluator/perception/number_duplicates", 10
205 "/evaluator/state_estimation/velocities_difference",
210 "/evaluator/state_estimation/vehicle_pose_difference",
214 Float32,
"/evaluator/state_estimation/map_mean_squared_difference", 10
217 Float32,
"/evaluator/state_estimation/map_mean_difference", 10
220 Float32,
"/evaluator/state_estimation/map_root_mean_squared_difference", 10
224 Int32,
"/evaluator/state_estimation/false_positives", 10
227 Int32,
"/evaluator/state_estimation/number_duplicates", 10
230 Int32,
"/evaluator/state_estimation/difference_with_map", 10
235 Float32,
"/evaluator/planning/gt_me", 10
238 Float32,
"/evaluator/planning/gt_mse", 10
241 Float32,
"/evaluator/planning/gt_rmse", 10
245 Float32,
"/evaluator/planning/left_cones_me", 10
248 Float32,
"/evaluator/planning/left_cones_mse", 10
251 self.create_publisher(Float32,
"/evaluator/planning/left_cones_rmse", 10)
255 Float32,
"/evaluator/planning/right_cones_me", 10
258 Float32,
"/evaluator/planning/right_cones_mse", 10
261 self.create_publisher(Float32,
"/evaluator/planning/right_cones_rmse", 10)
265 Float32,
"/evaluator/planning/cones_me", 10
268 Float32,
"/evaluator/planning/cones_mse", 10
271 Float32,
"/evaluator/planning/cones_rmse", 10
276 Float32,
"/evaluator/control/position/error", 10
279 Float32,
"/evaluator/control/velocity/error", 10
341 Float32,
"/evaluator/perception/mean_mean_error", 10
345 Float32,
"/evaluator/perception/mean_mean_squared_error", 10
349 Float32,
"/evaluator/perception/mean_mean_root_squared_error", 10
353 Float32,
"/evaluator/perception/mean_precision", 10
357 Float32,
"/evaluator/perception/mean_recall", 10
362 Float32,
"/evaluator/state_estimation/map_mean_mean_difference", 10
366 Float32,
"/evaluator/state_estimation/map_mean_mean_squared_difference", 10
371 "/evaluator/state_estimation/map_mean_mean_root_squared_difference",
377 "/evaluator/state_estimation/vehicle_pose_mean_difference",
383 "/evaluator/state_estimation/vehicle_pose_mean_squared_difference",
388 self.create_publisher(
390 "/evaluator/state_estimation/vehicle_pose_mean_root_squared_difference",
397 "/evaluator/state_estimation/velocities_mean_difference",
403 "/evaluator/state_estimation/velocities_mean_squared_difference",
408 self.create_publisher(
410 "/evaluator/state_estimation/velocities_mean_root_squared_difference",
417 Float32,
"/evaluator/planning/mean_mean_difference", 10
421 Float32,
"/evaluator/planning/mean_mean_squared_difference", 10
425 Float32,
"/evaluator/planning/mean_mean_root_squared_difference", 10
430 Float32,
"/evaluator/control/position/mean_error", 10
433 Float32,
"/evaluator/control/position/mean_squared_error", 10
436 Float32,
"/evaluator/control/position/root_mean_squared_error", 10
440 Float32,
"/evaluator/control/velocity/mean_error", 10
444 "/evaluator/control/velocity/mean_squared_error",
449 "/evaluator/control/velocity/root_mean_squared_error",
454 self._adapter_: Adapter = ADAPTER_CONSTRUCTOR_DICTINARY[self.
_adapter_name_](
461 package_share_directory = get_package_prefix(package_name)
462 config_path = os.path.join(
463 package_share_directory,
"..",
"..",
"config", dir, f
"{filename}.yaml"
468 """Load configuration from YAML file."""
470 "evaluator",
"global",
"global_config"
472 self.get_logger().debug(f
"Loading global config from: {global_config_path}")
473 with open(global_config_path,
"r")
as file:
474 global_config = yaml.safe_load(file)
476 adapter = global_config[
"global"][
"adapter"]
479 "use_simulated_perception"
483 "use_simulated_velocities"
488 "evaluator",
"evaluator", adapter
490 self.get_logger().debug(f
"Loading specific config from: {specific_config_path}")
491 with open(specific_config_path,
"r")
as file:
492 specific_config = yaml.safe_load(file)
495 self.
csv_suffix = specific_config[
"evaluator"][
"csv_suffix"].replace(
" ",
"_")
499 Writes metrics to csv and exits when Ctrl+C is pressed.
500 This function is triggered when the program receives a termination signal (e.g., SIGINT or SIGTERM)
501 and it saves the collected metrics to CSV files, then exits the program with a status code of 0.
502 The metrics are saved in separate CSV files based on their category.
505 sig (int): The signal number. (not used in this function)
506 frame (frame): The current stack frame. (not used in this function)
508 - Metrics are saved in the "performance/evaluator_metrics" directory as "<metric_name>_<timestamp>.csv".
509 - If a category has no metrics, no CSV file will be created for that category.
511 # Create an instance of the Evaluator class
512 evaluator = Evaluator()
513 # Register the signal handler function
514 signal.signal(signal.SIGINT, evaluator.signal_handler)
519 finish_time = datetime.datetime.now().strftime(
"%Y-%m-%d_%H:%M:%S")
532 for filename, metrics
in metrics_dict.items():
534 datetime_filename = f
"{filename}_{self._adapter_name_}_{finish_time}_{self.csv_suffix}.csv"
536 metrics,
"performance/evaluator_metrics/" + datetime_filename
542 Converts metrics to csv and writes them to a file.
544 metrics (list): A list of dictionaries representing the metrics.
545 filename (str): The name of the CSV file to write the metrics to.
551 start_time = metrics[0][
"timestamp"]
552 for metric
in metrics:
553 elapsed_time = (metric[
"timestamp"] - start_time).total_seconds()
554 metric[
"time"] = elapsed_time
557 with open(filename,
"w", newline=
"")
as csvfile:
558 fieldnames = metrics[0].keys()
559 writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
561 writer.writerows(metrics)
565 Callback function to store the execution time of the correction step.
568 msg (Float64): Message containing the correction step execution time.
573 {
"timestamp": datetime.datetime.now(),
"execution_time": msg.data}
578 Callback function to store the execution time of the prediction step.
580 msg (Float64): Message containing the prediction step execution time.
585 {
"timestamp": datetime.datetime.now(),
"execution_time": msg.data}
590 Callback function to store the perception execution time.
593 msg (Float64): Message containing the Perception execution time.
598 {
"timestamp": datetime.datetime.now(),
"execution_time": msg.data}
603 Callback function to store the planning execution time.
606 msg (Float64): Message containing the planning execution time.
611 {
"timestamp": datetime.datetime.now(),
"execution_time": msg.data}
617 groundtruth_pose: np.ndarray,
620 Computes state estimation metrics and publishes them.
622 pose (np.ndarray): Vehicle state estimation data. [x,y,theta]
623 groundtruth_pose (np.ndarray): Ground truth vehicle state data. [x,y,theta]
626 self.get_logger().debug(
"Received pose")
629 vehicle_pose_error = Float32MultiArray()
630 vehicle_pose_error.layout.dim = [MultiArrayDimension()]
631 vehicle_pose_error.layout.dim[0].size = 3
632 vehicle_pose_error.layout.dim[0].label =
"Vehicle Pose Error: [x, y, theta]"
633 vehicle_pose_error.data = [0.0] * 3
634 if groundtruth_pose != []:
635 vehicle_pose_error.data[0] = abs(pose[0] - groundtruth_pose[0])
636 vehicle_pose_error.data[1] = abs(pose[1] - groundtruth_pose[1])
637 vehicle_pose_error.data[2] = abs(pose[2] - groundtruth_pose[2]) % (
641 self.get_logger().debug(
642 "Computed slam metrics:\n \
643 Vehicle state error: {}".format(
652 mean_vehicle_pose_error = Float32MultiArray()
653 mean_squared_vehicle_pose_error = Float32MultiArray()
654 mean_root_squared_vehicle_pose_error = Float32MultiArray()
655 mean_vehicle_pose_error.layout.dim = [MultiArrayDimension()]
656 mean_squared_vehicle_pose_error.layout.dim = [MultiArrayDimension()]
657 mean_root_squared_vehicle_pose_error.layout.dim = [MultiArrayDimension()]
658 mean_vehicle_pose_error.layout.dim[0].size = 3
659 mean_squared_vehicle_pose_error.layout.dim[0].size = 3
660 mean_root_squared_vehicle_pose_error.layout.dim[0].size = 3
661 mean_vehicle_pose_error.data = [0.0] * 3
662 mean_squared_vehicle_pose_error.data = [0.0] * 3
663 mean_root_squared_vehicle_pose_error.data = [0.0] * 3
668 vehicle_pose_error.data[i] ** 2
670 mean_vehicle_pose_error.data[i] = (
673 mean_squared_vehicle_pose_error.data[i] = (
676 mean_root_squared_vehicle_pose_error.data[i] = (
683 mean_squared_vehicle_pose_error
686 mean_root_squared_vehicle_pose_error
691 "timestamp": datetime.datetime.now(),
692 "vehicle_pose_error_x": vehicle_pose_error.data[0],
693 "vehicle_pose_error_y": vehicle_pose_error.data[1],
694 "vehicle_pose_error_theta": vehicle_pose_error.data[2],
695 "mean_vehicle_pose_error_x": mean_vehicle_pose_error.data[0],
696 "mean_vehicle_pose_error_y": mean_vehicle_pose_error.data[1],
697 "mean_vehicle_pose_error_theta": mean_vehicle_pose_error.data[2],
698 "mean_squared_vehicle_pose_error_x": mean_squared_vehicle_pose_error.data[
701 "mean_squared_vehicle_pose_error_y": mean_squared_vehicle_pose_error.data[
704 "mean_squared_vehicle_pose_error_theta": mean_squared_vehicle_pose_error.data[
707 "mean_root_squared_vehicle_pose_error_x": mean_root_squared_vehicle_pose_error.data[
710 "mean_root_squared_vehicle_pose_error_y": mean_root_squared_vehicle_pose_error.data[
713 "mean_root_squared_vehicle_pose_error_theta": mean_root_squared_vehicle_pose_error.data[
722 groundtruth_map: np.ndarray,
725 Computes state estimation metrics and publishes them.
728 pose (np.ndarray): Vehicle state estimation data. [x,y,theta]
729 groundtruth_pose (np.ndarray): Ground truth vehicle state data. [x,y,theta]
730 map (np.ndarray): Map data. [[x,y,color,confidence]]
731 groundtruth_map (np.ndarray): Ground truth map data. [[x,y,color,confidence]]
733 if map.size == 0
or groundtruth_map.size == 0:
736 self.get_logger().debug(
"Received map")
739 cone_positions = map[:, :2]
740 groundtruth_cone_positions = groundtruth_map[:, :2]
741 mean_difference = Float32()
742 mean_difference.data = get_average_difference(
743 cone_positions, groundtruth_cone_positions
746 mean_squared_difference = Float32()
747 mean_squared_difference.data = get_mean_squared_difference(
748 cone_positions, groundtruth_cone_positions
751 num_duplicates = Int32()
752 num_duplicates.data = int(get_duplicates(cone_positions, 0.1))
754 root_mean_squared_difference = Float32()
755 root_mean_squared_difference.data = sqrt(
756 get_mean_squared_difference(cone_positions, groundtruth_cone_positions)
759 false_positives = Int32()
760 false_positives.data = int(
761 get_false_positives(cone_positions, groundtruth_cone_positions, 2)
764 difference_with_map = Int32()
765 difference_with_map.data = cone_positions.size - groundtruth_cone_positions.size
767 self.get_logger().debug(
768 "Computed slam metrics:\n \
769 Mean difference: {}\n \
770 Mean squared difference: {}\n \
771 Root mean squared difference: {}".format(
773 mean_squared_difference,
774 root_mean_squared_difference,
788 cone_positions, groundtruth_cone_positions
791 cone_positions, groundtruth_cone_positions
794 cone_positions, groundtruth_cone_positions
797 mean_mean_error = Float32()
799 mean_mean_squared_error = Float32()
801 mean_mean_root_squared_error = Float32()
802 mean_mean_root_squared_error.data = (
813 "timestamp": datetime.datetime.now(),
814 "mean_difference": mean_difference.data,
815 "mean_squared_difference": mean_squared_difference.data,
816 "root_mean_squared_difference": root_mean_squared_difference.data,
817 "mean_mean_error": mean_mean_error.data,
818 "mean_mean_squared_error": mean_mean_squared_error.data,
819 "mean_mean_root_squared_error": mean_mean_root_squared_error.data,
820 "false_positives": false_positives.data,
821 "difference_with_map": difference_with_map.data,
822 "num_duplicates": num_duplicates.data,
828 velocities: np.ndarray,
829 groundtruth_velocities: np.ndarray,
832 Computes state estimation metrics and publishes them.
835 velocities (np.ndarray): Vehicle state velocities. [vx, vy, w]
836 groundtruth_velocities (np.ndarray): Ground truth vehicle state velocities. [vx, vy, w]
839 self.get_logger().debug(
"Received vehicle speed estimation")
842 velocities_error = Float32MultiArray()
843 velocities_error.layout.dim = [MultiArrayDimension()]
844 velocities_error.layout.dim[0].size = 3
845 velocities_error.layout.dim[0].label =
"vehicle state error: [vx, vy, w]"
846 velocities_error.data = [0.0] * 3
847 if groundtruth_velocities != []:
848 velocities_error.data[0] = abs(velocities[0] - groundtruth_velocities[0])
849 velocities_error.data[1] = abs(velocities[1] - groundtruth_velocities[1])
850 velocities_error.data[2] = abs(velocities[2] - groundtruth_velocities[2])
852 self.get_logger().debug(
853 "Computed state estimation metrics:\n \
854 Vehicle velocities error: {}".format(
864 mean_velocities_error = Float32MultiArray()
865 mean_squared_velocities_error = Float32MultiArray()
866 mean_root_squared_velocities_error = Float32MultiArray()
867 mean_velocities_error.layout.dim = [MultiArrayDimension()]
868 mean_squared_velocities_error.layout.dim = [MultiArrayDimension()]
869 mean_root_squared_velocities_error.layout.dim = [MultiArrayDimension()]
870 mean_velocities_error.layout.dim[0].size = 3
871 mean_squared_velocities_error.layout.dim[0].size = 3
872 mean_root_squared_velocities_error.layout.dim[0].size = 3
873 mean_velocities_error.data = [0.0] * 3
874 mean_squared_velocities_error.data = [0.0] * 3
875 mean_root_squared_velocities_error.data = [0.0] * 3
879 mean_velocities_error.data[i] = (
882 mean_squared_velocities_error.data[i] = (
885 mean_root_squared_velocities_error.data[i] = (
892 mean_squared_velocities_error
895 mean_root_squared_velocities_error
900 "timestamp": datetime.datetime.now(),
901 "velocities_error_v1": velocities_error.data[0],
902 "velocities_error_v2": velocities_error.data[1],
903 "velocities_error_w": velocities_error.data[2],
904 "mean_velocities_error_v1": mean_velocities_error.data[0],
905 "mean_velocities_error_v2": mean_velocities_error.data[1],
906 "mean_velocities_error_w": mean_velocities_error.data[2],
907 "mean_squared_velocities_error_v1": mean_squared_velocities_error.data[0],
908 "mean_squared_velocities_error_v2": mean_squared_velocities_error.data[1],
909 "mean_squared_velocities_error_w": mean_squared_velocities_error.data[2],
910 "mean_root_squared_velocities_error_v1": mean_root_squared_velocities_error.data[
913 "mean_root_squared_velocities_error_v2": mean_root_squared_velocities_error.data[
916 "mean_root_squared_velocities_error_w": mean_root_squared_velocities_error.data[
923 self, perception_output: np.ndarray, perception_ground_truth: np.ndarray
926 Computes perception metrics and publishes them.
929 perception_output (np.ndarray): Perceived cones.
930 perception_ground_truth (np.ndarray): Ground truth cones.
933 if len(perception_output) == 0
or len(perception_ground_truth) == 0:
934 self.get_logger().debug(
"Perception, ground truth or cones info missing")
939 cone_positions = perception_output[:, :2]
940 groundtruth_cone_positions = perception_ground_truth[:, :2]
941 mean_difference = Float32()
942 mean_difference.data = get_average_difference(
943 cone_positions, groundtruth_cone_positions
945 mean_squared_error = Float32()
946 mean_squared_error.data = get_mean_squared_difference(
947 cone_positions, groundtruth_cone_positions
949 inter_cones_distance = Float32()
950 inter_cones_distance.data = float(get_inter_cones_distance(cone_positions))
951 root_mean_squared_difference = Float32()
952 root_mean_squared_difference.data = sqrt(mean_squared_error.data)
954 false_positives = Int32()
955 false_positives.data = int(
956 get_false_positives(cone_positions, groundtruth_cone_positions, 0.1)
958 precision = Float32()
959 precision.data = float(
960 (len(cone_positions) - false_positives.data) / len(cone_positions)
964 (len(cone_positions) - false_positives.data)
965 / len(groundtruth_cone_positions)
968 num_duplicates = Int32()
969 num_duplicates.data = int(get_duplicates(perception_output, 0.1))
971 self.get_logger().debug(
972 "Computed perception metrics:\n \
973 Mean difference: {}\n \
974 Inter cones distance: {}\n \
975 Mean squared difference: {}\n \
976 Root mean squared difference: {}\n \
977 False positives: {}\n \
980 Duplicates: {}".format(
982 inter_cones_distance,
984 root_mean_squared_difference,
997 root_mean_squared_difference
1006 cone_positions, groundtruth_cone_positions
1009 cone_positions, groundtruth_cone_positions
1012 cone_positions, groundtruth_cone_positions
1017 - get_false_positives(cone_positions, groundtruth_cone_positions, 0.1)
1019 / len(cone_positions)
1024 - get_false_positives(cone_positions, groundtruth_cone_positions, 0.1)
1026 / len(groundtruth_cone_positions)
1029 mean_mean_error = Float32()
1031 mean_mean_squared_error = Float32()
1032 mean_mean_squared_error.data = (
1035 mean_mean_root_squared_error = Float32()
1036 mean_mean_root_squared_error.data = (
1039 mean_precision = Float32()
1041 mean_recall = Float32()
1048 mean_mean_root_squared_error
1055 "timestamp": datetime.datetime.now(),
1056 "mean_difference": mean_difference.data,
1057 "inter_cones_distance": inter_cones_distance.data,
1058 "mean_squared_difference": mean_squared_error.data,
1059 "root_mean_squared_difference": root_mean_squared_difference.data,
1060 "mean_mean_error": mean_mean_error.data,
1061 "mean_mean_squared_error": mean_mean_squared_error.data,
1062 "mean_mean_root_squared_error": mean_mean_root_squared_error.data,
1063 "false_positives": false_positives.data,
1064 "precision": precision.data,
1065 "recall": recall.data,
1066 "mean_precision": mean_precision.data,
1067 "mean_recall": mean_recall.data,
1068 "duplicates": num_duplicates.data,
1075 path_gt: np.ndarray,
1076 left_cones_gt: np.ndarray,
1077 right_cones_gt: np.ndarray,
1080 Computes planning metrics and publishes them.
1083 path (np.ndarray): Path computed by the planner.
1084 left_cones_gt (np.ndarray): Ground truth of the left cones.
1085 right_cones_gt (np.ndarray): Ground truth of the right cones.
1087 self.get_logger().debug(
"Received planning")
1093 or len(path_gt) == 0
1094 or len(left_cones_gt) == 0
1095 or len(right_cones_gt) == 0
1097 self.get_logger().debug(
1098 "Path, path ground truth or map ground truth info missing"
1103 blue_cones = left_cones_gt
1104 yellow_cones = right_cones_gt
1106 useful_blue_cones = find_closest_elements(path, blue_cones)
1107 useful_yellow_cones = find_closest_elements(path, yellow_cones)
1108 distance_to_cones_left = compute_closest_distances(path, useful_blue_cones)
1109 distance_to_cones_right = compute_closest_distances(path, useful_yellow_cones)
1110 general_distance_to_cones = np.concatenate(
1111 [distance_to_cones_left, distance_to_cones_right]
1114 mean_cones_difference_left = get_average_error(distance_to_cones_left)
1115 mean_squared_cones_difference_left = get_mean_squared_error(
1116 distance_to_cones_left
1118 root_mean_squared_cones_difference_left = (
1119 mean_squared_cones_difference_left ** (1 / 2)
1121 mean_cones_difference_right = get_average_error(distance_to_cones_right)
1122 mean_squared_cones_difference_right = get_mean_squared_error(
1123 distance_to_cones_right
1125 root_mean_squared_cones_difference_right = (
1126 mean_squared_cones_difference_right ** (1 / 2)
1128 mean_cones_difference = get_average_error(general_distance_to_cones)
1139 mean_squared_cones_difference = get_mean_squared_error(
1140 general_distance_to_cones
1142 root_mean_squared_cones_difference = mean_squared_cones_difference ** (1 / 2)
1144 useful_gt_points = find_closest_elements(path, path_gt)
1145 distance_to_gt = compute_closest_distances(path, useful_gt_points)
1147 mean_gt_difference = get_average_error(distance_to_gt)
1148 mean_squared_gt_difference = get_mean_squared_error(distance_to_gt)
1149 root_mean_squared_gt_difference = mean_squared_gt_difference ** (1 / 2)
1152 self.get_logger().debug(
1153 "Computed planning metrics:\n \
1154 Mean difference to cones: {}\n \
1155 Mean squared difference to cones: {}\n \
1156 Mean difference to ground truth: {}\n \
1157 Mean squared difference to ground truth: {}".format(
1158 mean_cones_difference,
1159 mean_squared_cones_difference,
1161 mean_squared_gt_difference,
1168 Float32(data=mean_squared_gt_difference)
1171 Float32(data=root_mean_squared_gt_difference)
1175 Float32(data=mean_cones_difference_left)
1178 Float32(data=mean_squared_cones_difference_left)
1181 Float32(data=root_mean_squared_cones_difference_left)
1185 Float32(data=mean_cones_difference_right)
1188 Float32(data=mean_squared_cones_difference_right)
1191 Float32(data=root_mean_squared_cones_difference_right)
1195 Float32(data=mean_cones_difference)
1198 Float32(data=mean_squared_cones_difference)
1201 Float32(data=root_mean_squared_cones_difference)
1231 "timestamp": datetime.datetime.now(),
1232 "mean_difference_to_gt": mean_gt_difference.data,
1233 "mean_squared_difference_to_gt": mean_squared_gt_difference.data,
1234 "root_mean_squared_difference_to_gt": root_mean_squared_gt_difference.data,
1235 "mean_difference_left_cones": mean_cones_difference_left.data,
1236 "mean_squared_difference_left_cones": mean_squared_cones_difference_left.data,
1237 "root_mean_squared_difference_left_cones": root_mean_squared_cones_difference_left.data,
1238 "mean_difference_right_cones": mean_cones_difference_right.data,
1239 "mean_squared_difference_right_cones": mean_squared_cones_difference_right.data,
1240 "root_mean_squared_difference_right_cones": root_mean_squared_cones_difference_right.data,
1241 "mean_difference_to_cones": mean_cones_difference.data,
1242 "mean_squared_difference_to_cones": mean_squared_cones_difference.data,
1243 "root_mean_squared_difference_to_cones": root_mean_squared_cones_difference.data,
1249 Computes control metrics and publishes them.
1251 msg (Float64): Control execution time message.
1253 self.get_logger().debug(
"Received control")
1256 closest_point_distance = float(
"inf")
1257 closest_point =
None
1259 dist = compute_distance(path_point[:2], self.
position)
1260 if dist < closest_point_distance:
1261 closest_point_distance = dist
1262 closest_point = path_point
1264 if closest_point
is None:
1265 self.get_logger().warn(
"No closest point found.")
1268 velocity_error_value = self.velocity - self.closest_point_velocity
1270 position_error = Float32()
1271 position_error.data = closest_point_distance
1273 velocity_error = Float32()
1274 velocity_error.data = float(velocity_error_value)
1276 self.get_logger().debug(
1277 "Computed control metrics:\n \
1278 Pose Difference: {}\n \
1279 Velocity Difference: {}\n ".format(
1298 control_velocity_mean_error = Float32()
1299 control_velocity_mean_error.data = float(
1303 control_velocity_mean_squared_error = Float32()
1304 control_velocity_mean_squared_error.data = float(
1308 control_velocity_root_mean_squared_error = Float32()
1309 control_velocity_root_mean_squared_error.data = sqrt(
1314 control_position_mean_error = Float32()
1315 control_position_mean_error.data = float(
1319 control_position_mean_squared_error = Float32()
1320 control_position_mean_squared_error.data = float(
1324 control_position_root_mean_squared_error = Float32()
1325 control_position_root_mean_squared_error.data = sqrt(
1332 control_position_mean_squared_error
1335 control_position_root_mean_squared_error
1340 control_velocity_mean_squared_error
1343 control_velocity_root_mean_squared_error
1347 {
"timestamp": datetime.datetime.now(),
"execution_time": msg.data[0]}
1352 "timestamp": datetime.datetime.now(),
1353 "position_error": position_error.data,
1354 "position_mean_error": control_position_mean_error.data,
1355 "position_mean_squared_error": control_position_mean_squared_error.data,
1356 "position_root_mean_squared_error": control_position_root_mean_squared_error.data,
1357 "velocity_error": velocity_error.data,
1358 "velocity_mean_error": control_velocity_mean_error.data,
1359 "velocity_mean_squared_error": control_velocity_mean_squared_error.data,
1360 "velocity_root_mean_squared_error": control_velocity_root_mean_squared_error.data,
1367 Main function for the evaluator module.
1369 args (list): Optional command-line arguments.
1371 rclpy.init(args=args)
1377if __name__ ==
"__main__":
A ROS2 node for computing and publishing the system's real-time metrics.
_planning_mean_squared_difference_to_left_cones
None compute_and_publish_perception(self, np.ndarray perception_output, np.ndarray perception_ground_truth)
Computes perception metrics and publishes them.
_state_estimation_root_mean_squared_vehicle_pose_error
get_config_yaml_path(self, package_name, dir, filename)
_planning_root_mean_squared_difference_to_gt
_state_estimation_mean_vehicle_pose_error
_planning_mean_difference_to_left_cones
prediction_step_time_callback
_state_estimation_mean_squared_vehicle_pose_error
None compute_and_publish_velocities(self, np.ndarray velocities, np.ndarray groundtruth_velocities)
Computes state estimation metrics and publishes them.
_perception_mean_precision
None planning_execution_time_callback(self, Float64 msg)
Callback function to store the planning execution time.
None compute_and_publish_pose(self, np.ndarray pose, np.ndarray groundtruth_pose)
Computes state estimation metrics and publishes them.
_perception_mean_mean_squared_error
_control_position_squared_error_sum
_control_position_mean_error_
use_simulated_velocities_
planning_gt_subscription_
_se_map_mean_root_squared_sum_error
use_simulated_perception_
_perception_root_squared_sum_error
_planning_squared_sum_error
_planning_mean_difference_to_cones
_planning_root_mean_squared_difference_to_cones
_planning_mean_mean_squared_error
None prediction_step_time_callback(self, Float64 msg)
_map_mean_squared_difference_
_se_map_squared_sum_error
_planning_mean_difference_to_right_cones
_correction_step_time_subscription_
_control_velocity_squared_error_sum
None correction_step_time_callback(self, Float64 msg)
Callback function to store the execution time of the correction step.
_state_estimation_mean_velocities_error
_control_velocity_mean_error_
_control_velocity_error_sum
_perception_inter_cones_distance_
None signal_handler(self, int sig, frame)
Writes metrics to csv and exits when Ctrl+C is pressed.
_se_correction_execution_time_
_perception_squared_sum_error
_planning_mean_root_squared_sum_error
_state_estimation_mean_squared_velocities_error
_perception_mean_squared_difference_
_perception_number_duplicates
_planning_root_mean_squared_difference_to_left_cones
compute_and_publish_planning(self, np.ndarray path, np.ndarray path_gt, np.ndarray left_cones_gt, np.ndarray right_cones_gt)
Computes planning metrics and publishes them.
_map_mean_mean_root_squared_error
_planning_root_mean_squared_difference_to_right_cones
vehicle_pose_subscription_
_perception_execution_time_subscription_
_control_execution_time_subscription_
_control_velocity_root_mean_squared_error_
_vehicle_pose_difference_
_perception_false_positives_
_control_position_mean_squared_error_
None compute_and_publish_map(self, np.ndarray map, np.ndarray groundtruth_map)
Computes state estimation metrics and publishes them.
None metrics_to_csv(self, list metrics, str filename)
_planning_mean_squared_difference_to_gt
None perception_execution_time_callback(self, Float64 msg)
Callback function to store the perception execution time.
_planning_mean_mean_root_squared_error
_control_position_error_sum
_control_position_root_mean_squared_error_
_perception_mean_mean_root_squared_error
_state_estimation_root_mean_squared_velocities_error
planning_execution_time_callback
_se_prediction_execution_time_
_sum_squared_velocities_error
compute_and_publish_control
_map_mean_mean_squared_error
_perception_mean_difference_
compute_and_publish_control(self, Float64 msg)
Computes control metrics and publishes them.
_perception_root_mean_squared_difference_
_planning_mean_mean_error
_control_velocity_mean_squared_error_
_planning_mean_squared_difference_to_cones
_planning_execution_time_
_map_root_mean_squared_difference_
_perception_mean_mean_error
correction_step_time_callback
_planning_execution_time_subscription_
_planning_mean_difference_to_gt
_sum_squared_vehicle_pose_error
_prediction_step_time_subscription_
perception_execution_time_callback
_perception_precision_sum
_perception_execution_time_
_planning_mean_squared_difference_to_right_cones