diff --git a/agv_calib_brain/.codex b/agv_calib_brain/.codex
new file mode 100644
index 0000000..e69de29
diff --git a/agv_calib_brain/.isaac_cache/ack_m_isaac_fixed.urdf b/agv_calib_brain/.isaac_cache/ack_m_isaac_fixed.urdf
new file mode 100644
index 0000000..dace892
--- /dev/null
+++ b/agv_calib_brain/.isaac_cache/ack_m_isaac_fixed.urdf
@@ -0,0 +1,301 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/agv_calib_brain/.isaac_cache/ack_m_isaac_fixed.usd b/agv_calib_brain/.isaac_cache/ack_m_isaac_fixed.usd
new file mode 100644
index 0000000..ab778e1
--- /dev/null
+++ b/agv_calib_brain/.isaac_cache/ack_m_isaac_fixed.usd
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ac7fb8e48883155d1feffe880c55a972c5562b34bc340f0002ff80965d20cfac
+size 75606548
diff --git a/agv_calib_brain/.isaac_cache/checkerboard.png b/agv_calib_brain/.isaac_cache/checkerboard.png
new file mode 100644
index 0000000..26b3c06
Binary files /dev/null and b/agv_calib_brain/.isaac_cache/checkerboard.png differ
diff --git a/agv_calib_brain/.isaac_cache/down_camera_charuco.png b/agv_calib_brain/.isaac_cache/down_camera_charuco.png
new file mode 100644
index 0000000..c7d2c92
Binary files /dev/null and b/agv_calib_brain/.isaac_cache/down_camera_charuco.png differ
diff --git a/agv_calib_brain/.isaac_cache/workshop_scene_manifest.json b/agv_calib_brain/.isaac_cache/workshop_scene_manifest.json
new file mode 100644
index 0000000..36dd910
--- /dev/null
+++ b/agv_calib_brain/.isaac_cache/workshop_scene_manifest.json
@@ -0,0 +1,840 @@
+{
+ "vehicle": {
+ "vehicle_id": "demo_agv_001",
+ "vehicle_source": "urdf_direct",
+ "source_urdf_path": "/home/nvidia/study/AutoCalib-Workshop/agv_calib_brain/src/simulation/isaac_workshop_sim/assets/urdf/ackermann_front_steer_rear_drive.urdf",
+ "urdf_path": "/home/nvidia/study/AutoCalib-Workshop/agv_calib_brain/src/simulation/isaac_workshop_sim/assets/urdf/ackermann_front_steer_rear_drive.urdf",
+ "usd_path": null,
+ "stage_prim_path": "/ackermann_front_steer_rear_drive",
+ "drive_wheels": [
+ "rear_left_wheel_link",
+ "rear_right_wheel_link"
+ ],
+ "steer_wheels": [
+ "front_left_wheel_link",
+ "front_right_wheel_link"
+ ],
+ "initial_pose": {
+ "x_m": 0.0,
+ "y_m": 0.0,
+ "z_m": 0.0,
+ "yaw_rad": 0.0
+ }
+ },
+ "workshop": {
+ "workcell_zone_id": "isaac_workcell_zone_a",
+ "room_length_m": 10.0,
+ "room_width_m": 6.0,
+ "room_height_m": 3.5,
+ "checkerboard": {
+ "rows": 6,
+ "cols": 9,
+ "square_size_m": 0.12,
+ "texture_path": "/home/nvidia/study/AutoCalib-Workshop/agv_calib_brain/.isaac_cache/checkerboard.png",
+ "reserved_wall_zones": {
+ "front": [
+ {
+ "axis_min": -2.82,
+ "axis_max": -0.9199999999999999,
+ "z_min": 0.0,
+ "z_max": 3.5,
+ "reason": "2d_lidar_extrinsic_corner_bay"
+ }
+ ],
+ "right": [
+ {
+ "axis_min": 2.9200000000000004,
+ "axis_max": 4.82,
+ "z_min": 0.0,
+ "z_max": 3.5,
+ "reason": "2d_lidar_extrinsic_corner_bay"
+ }
+ ]
+ },
+ "layout": [
+ {
+ "id": "front_wall_r00_c01",
+ "wall": "front",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 4.985,
+ 0.0,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 90
+ ]
+ },
+ {
+ "id": "front_wall_r00_c02",
+ "wall": "front",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 4.985,
+ 1.4999999999999998,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 90
+ ]
+ },
+ {
+ "id": "front_wall_r01_c01",
+ "wall": "front",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 4.985,
+ 0.0,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 90
+ ]
+ },
+ {
+ "id": "front_wall_r01_c02",
+ "wall": "front",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 4.985,
+ 1.4999999999999998,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 90
+ ]
+ },
+ {
+ "id": "back_wall_r00_c00",
+ "wall": "back",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -4.985,
+ -1.4999999999999998,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ -90
+ ]
+ },
+ {
+ "id": "back_wall_r00_c01",
+ "wall": "back",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -4.985,
+ 0.0,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ -90
+ ]
+ },
+ {
+ "id": "back_wall_r00_c02",
+ "wall": "back",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -4.985,
+ 1.4999999999999998,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ -90
+ ]
+ },
+ {
+ "id": "back_wall_r01_c00",
+ "wall": "back",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -4.985,
+ -1.4999999999999998,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ -90
+ ]
+ },
+ {
+ "id": "back_wall_r01_c01",
+ "wall": "back",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -4.985,
+ 0.0,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ -90
+ ]
+ },
+ {
+ "id": "back_wall_r01_c02",
+ "wall": "back",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -4.985,
+ 1.4999999999999998,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ -90
+ ]
+ },
+ {
+ "id": "left_wall_r00_c00",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -3.749999999999999,
+ 2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r00_c01",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -2.249999999999999,
+ 2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r00_c02",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -0.7499999999999996,
+ 2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r00_c03",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 0.75,
+ 2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r00_c04",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 2.25,
+ 2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r00_c05",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 3.75,
+ 2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r01_c00",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -3.749999999999999,
+ 2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r01_c01",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -2.249999999999999,
+ 2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r01_c02",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -0.7499999999999996,
+ 2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r01_c03",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 0.75,
+ 2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r01_c04",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 2.25,
+ 2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "left_wall_r01_c05",
+ "wall": "left",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 3.75,
+ 2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 0
+ ]
+ },
+ {
+ "id": "right_wall_r00_c00",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -3.749999999999999,
+ -2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r00_c01",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -2.249999999999999,
+ -2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r00_c02",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -0.7499999999999996,
+ -2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r00_c03",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 0.75,
+ -2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r00_c04",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 2.25,
+ -2.985,
+ 1.2100000000000002
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r01_c00",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -3.749999999999999,
+ -2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r01_c01",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -2.249999999999999,
+ -2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r01_c02",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ -0.7499999999999996,
+ -2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r01_c03",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 0.75,
+ -2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ },
+ {
+ "id": "right_wall_r01_c04",
+ "wall": "right",
+ "mount": "flush",
+ "purpose": "wall_checkerboard_array",
+ "position": [
+ 2.25,
+ -2.985,
+ 2.33
+ ],
+ "rotation_deg": [
+ 90,
+ 0,
+ 180
+ ]
+ }
+ ]
+ },
+ "down_camera_intrinsic_target": {
+ "enabled": true,
+ "texture_path": "/home/nvidia/study/AutoCalib-Workshop/agv_calib_brain/.isaac_cache/down_camera_charuco.png",
+ "pattern": "charuco",
+ "squares_x": 30,
+ "squares_y": 10,
+ "square_size_x_m": 0.09000000000000001,
+ "square_size_y_m": 0.09,
+ "layout": [
+ {
+ "id": "down_camera_3d_charuco_ramp",
+ "target_type": "down_camera_intrinsic",
+ "pattern": "charuco",
+ "purpose": "intrinsic_calibration_with_depth_and_pose_gradient",
+ "center": [
+ 0.0,
+ -2.15,
+ 0.028499999999999998
+ ],
+ "length_m": 2.7,
+ "width_m": 0.9,
+ "squares_x": 30,
+ "squares_y": 10,
+ "square_size_m": 0.09,
+ "min_height_m": 0.012,
+ "max_height_m": 0.045,
+ "recommended_drive_axis": "+x",
+ "recommended_speed_mps": 0.1,
+ "surfaces": [
+ {
+ "id": "low_flat_charuco",
+ "type": "flat",
+ "x_range_m": [
+ -1.35,
+ -0.756
+ ],
+ "z_range_m": [
+ 0.012,
+ 0.012
+ ]
+ },
+ {
+ "id": "continuous_slope_charuco",
+ "type": "continuous_slope",
+ "x_range_m": [
+ -0.756,
+ 0.6479999999999999
+ ],
+ "z_range_m": [
+ 0.012,
+ 0.045
+ ]
+ },
+ {
+ "id": "high_flat_charuco",
+ "type": "flat",
+ "x_range_m": [
+ 0.6479999999999999,
+ 1.35
+ ],
+ "z_range_m": [
+ 0.045,
+ 0.045
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "ros_topics": {
+ "cmd_vel": "/vehicle/demo_agv_001/actuator/cmd_vel",
+ "camera_image": "/AutoCalib_Workshop/camera/image_raw",
+ "lidar_prefix": "/AutoCalib_Workshop/lidar",
+ "front_camera_image": "/sensor/front_camera/image_raw",
+ "down_camera_image": "/sensor/down_camera/image_raw",
+ "lidar_3d_pointcloud": "/sensor/lidar_3d/pointcloud",
+ "lidar_2d_scan": "/sensor/lidar_2d/scan",
+ "imu": "/sensor/imu/data",
+ "external_telemetry": "/isaac/external_localization/telemetry",
+ "chassis_telemetry": "/chassis/telemetry",
+ "control_telemetry": "/control/telemetry",
+ "sensor_telemetry": "/sensor_calibration/telemetry"
+ },
+ "chassis_calibration": {
+ "chassis_type": "ackermann",
+ "straight_track_length_m": 5.0,
+ "straight_track_width_m": 0.7,
+ "arc_track_radius_m": 1.6,
+ "wheel_radius_m": 0.1,
+ "wheel_track_m": 0.52,
+ "wheel_base_m": 0.8
+ },
+ "control_calibration": {
+ "reference_path": [
+ {
+ "x_m": -2.5,
+ "y_m": 0.0,
+ "yaw_rad": 0.0,
+ "target_speed_ms": 0.3
+ },
+ {
+ "x_m": 2.5,
+ "y_m": 0.0,
+ "yaw_rad": 0.0,
+ "target_speed_ms": 0.3
+ }
+ ],
+ "parameter_version": "isaac_control_baseline_v1"
+ },
+ "external_truth": {
+ "localization_source_id": "isaac_sim_truth_source",
+ "reference_source_name": "isaac_sim_truth_source",
+ "workcell_zone_id": "isaac_workcell_zone_a",
+ "expected_position_stddev_m": 0.01,
+ "expected_yaw_stddev_rad": 0.01,
+ "expected_time_sync_offset_ms": 2.0
+ },
+ "sensors": [
+ {
+ "sensor_id": "demo_front_camera",
+ "sensor_type": "front_camera",
+ "frame_id": "front_camera_link",
+ "image_topic": "/sensor/front_camera/image_raw",
+ "telemetry_topic": "/sensor_calibration/telemetry",
+ "mount_pose": {
+ "x_m": 0.82,
+ "y_m": 0.0,
+ "z_m": 0.32,
+ "roll_rad": 0.0,
+ "pitch_rad": -1.5707963267948966,
+ "yaw_rad": 0.0
+ }
+ },
+ {
+ "sensor_id": "demo_down_camera",
+ "sensor_type": "down_camera",
+ "frame_id": "down_camera_link",
+ "image_topic": "/sensor/down_camera/image_raw",
+ "mount_pose": {
+ "x_m": 0.4,
+ "y_m": 0.0,
+ "z_m": 0.3,
+ "roll_rad": 0.0,
+ "pitch_rad": 0.0,
+ "yaw_rad": 0.0
+ }
+ },
+ {
+ "sensor_id": "demo_lidar_3d",
+ "sensor_type": "lidar_3d",
+ "frame_id": "lidar_3d_link",
+ "pointcloud_topic": "/sensor/lidar_3d/pointcloud",
+ "mount_pose": {
+ "x_m": 0.55,
+ "y_m": 0.0,
+ "z_m": 0.46,
+ "roll_rad": 0.0,
+ "pitch_rad": 0.0,
+ "yaw_rad": 0.0
+ }
+ },
+ {
+ "sensor_id": "demo_lidar_2d",
+ "sensor_type": "lidar_2d",
+ "frame_id": "lidar_2d_link",
+ "scan_topic": "/sensor/lidar_2d/scan",
+ "mount_pose": {
+ "x_m": 0.7,
+ "y_m": 0.0,
+ "z_m": 0.24,
+ "roll_rad": 0.0,
+ "pitch_rad": 0.0,
+ "yaw_rad": 0.0
+ }
+ },
+ {
+ "sensor_id": "demo_imu",
+ "sensor_type": "imu",
+ "frame_id": "imu_link",
+ "imu_topic": "/sensor/imu/data",
+ "mount_pose": {
+ "x_m": 0.4,
+ "y_m": 0.0,
+ "z_m": 0.26,
+ "roll_rad": 0.0,
+ "pitch_rad": 0.0,
+ "yaw_rad": 0.0
+ }
+ }
+ ],
+ "lidar_2d_calibration_targets": {
+ "enabled": true,
+ "target_width_m": 0.82,
+ "target_height_m": 1.6,
+ "target_thickness_m": 0.04,
+ "target_bottom_z_m": 0.08,
+ "slope_angle_deg": 45.0,
+ "targets": [
+ {
+ "id": "front_vertical_reference_panel",
+ "wall": "front",
+ "type": "vertical_reference",
+ "position": [
+ 4.920000000000001,
+ -2.34,
+ 0.88
+ ],
+ "scale": [
+ 0.04,
+ 0.82,
+ 1.6
+ ],
+ "rotation_deg": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "nominal_plane": "x = room_length/2 - standoff - thickness"
+ },
+ {
+ "id": "front_45deg_height_encoding_panel",
+ "wall": "front",
+ "type": "height_encoding_slope",
+ "position": [
+ 4.1000000000000005,
+ -1.4,
+ 0.88
+ ],
+ "scale": [
+ 0.04,
+ 0.82,
+ 2.262741699796952
+ ],
+ "rotation_deg": [
+ 0.0,
+ -45.0,
+ 0.0
+ ],
+ "slope_angle_deg": 45.0,
+ "height_to_range_sign": "higher_scan_plane_farther_from_front_wall"
+ },
+ {
+ "id": "right_vertical_reference_panel",
+ "wall": "right",
+ "type": "vertical_reference",
+ "position": [
+ 3.87,
+ -2.92,
+ 0.88
+ ],
+ "scale": [
+ 0.82,
+ 0.04,
+ 1.6
+ ],
+ "rotation_deg": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "nominal_plane": "y = -room_width/2 + standoff + thickness"
+ }
+ ]
+ },
+ "orchestrator_session_config_hint": {
+ "vehicle_id": "demo_agv_001",
+ "localization_source_id": "isaac_sim_truth_source",
+ "workcell_zone_id": "isaac_workcell_zone_a",
+ "reference_target_id": "isaac_external_truth"
+ }
+}
diff --git a/agv_calib_brain/README.md b/agv_calib_brain/README.md
new file mode 100644
index 0000000..e896c6b
--- /dev/null
+++ b/agv_calib_brain/README.md
@@ -0,0 +1,134 @@
+# AGV 自动标定车间 - 总述
+
+本项目是 AGV(自动导引车)自动化标定车间的软件系统,用于在车间环境中对 AGV 进行底盘参数标定、运控参数标定、传感器内参/外参标定,以及手眼标定。
+
+## 项目概述
+
+### 核心能力
+
+| 标定类型 | 说明 | 状态 |
+|---------|------|------|
+| 外部真值接入 | 通过外部定位系统(如 OptiTrack、激光雷达定位)获取车辆位姿真值 | ✅ 已验证 |
+| 底盘参数标定 | 标定轮距、轴距、转向角等底盘几何参数 | ✅ 已验证(模板) |
+| 运控参数标定 | 标定横向/纵向控制器的 PID/MPC/LQR 参数 | ✅ 已验证(模板) |
+| 传感器内参标定 | 相机(前视/下视)、IMU 的内参标定 | ✅ 已验证(模板) |
+| 传感器外参标定 | 相机、雷达等传感器相对于车体坐标系的外参标定 | 🚧 待完善 |
+| 手眼标定 | 机械臂与相机之间的变换关系标定 | 🚧 待开发 |
+
+### 技术架构
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ 车间工控机(Ubuntu) │
+│ ┌─────────────────┐ ┌──────────────┐ ┌─────────────────────┐ │
+│ │ workshop_ │ │ 底盘标定服务 │ │ 传感器标定服务 │ │
+│ │ orchestrator_v2 │ │ chassis_ │ │ sensor_calibration_ │ │
+│ │ (总控) │ │ calibration │ │ service │ │
+│ └────────┬────────┘ └──────────────┘ └─────────────────────┘ │
+│ │ │
+│ ┌────────▼────────┐ ┌──────────────┐ ┌─────────────────────┐ │
+│ │ vehicle_agent_ │ │ 运控标定服务 │ │ 外部位姿服务 │ │
+│ │ gateway │ │ control_ │ │ external_ │ │
+│ │ (WiFi6/TCP网关) │ │ calibration │ │ localization_ │ │
+│ └─────────────────┘ └──────────────┘ └─────────────────────┘ │
+└─────────────────────────────────────────────────────────────────┘
+ │ WiFi6/TCP
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ 车端电脑(Windows/Linux) │
+│ ┌─────────────────┐ ┌──────────────┐ ┌─────────────────────┐ │
+│ │ 车端 Agent │ │ 底盘控制器 │ │ 传感器驱动 │ │
+│ │ (TCP<->CAN/PLC) │ │ (CAN/PLC) │ │ (相机/雷达/IMU) │ │
+│ └─────────────────┘ └──────────────┘ └─────────────────────┘ │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+## 目录结构
+
+```
+agv_calib_brain/
+├── src/
+│ ├── core/ # 核心标定逻辑
+│ │ ├── workshop_orchestrator/ # 车间总控编排器
+│ │ ├── chassis_calibration_service/ # 底盘标定服务
+│ │ ├── control_calibration_service/ # 运控标定服务
+│ │ ├── sensor_calibration_service/ # 传感器标定服务
+│ │ ├── external_localization_service/ # 外部位姿服务
+│ │ └── vehicle_profile_manager/ # 车辆画像管理
+│ │
+│ ├── communication/ # 通信层
+│ │ ├── win_ubuntu_bridge/ # 车间<->车端通信桥
+│ │ └── interfaces/ # ROS2 接口定义
+│ │
+│ ├── simulation/ # 仿真验证
+│ │ ├── isaac_workshop_sim/ # Isaac Sim 标定车间
+│ │ ├── vehicle_agent_sim/ # 仿真车端 Agent
+│ │ ├── vehicle_sensor_agent_sim/ # 仿真传感器 Agent
+│ │ └── tools/ # 仿真工具脚本
+│ │
+│ ├── deployment/ # 部署配置
+│ │ └── profiles/ # 仿真/部署配置文件
+│ │
+│ ├── site_deployment/ # 真实现场部署
+│ │ └── (真实车辆 SDK、PLC/CAN 适配)
+│ │
+│ └── apps/ # 操作员工具
+│
+├── run_isaac_real_sim_test.sh # 一键启动 Isaac 仿真测试
+├── stop_isaac_real_sim_stack.sh # 停止仿真栈
+├── SIMULATION_GUIDE.md # 仿真环境启动指南
+└── README.md # 本文件
+```
+
+## 快速开始
+
+### 1. 编译
+
+```bash
+cd /home/nvidia/study/AutoCalib-Workshop/agv_calib_brain
+colcon build
+source install/setup.bash
+```
+
+### 2. 一键启动完整仿真
+
+```bash
+# 启动 Isaac + 车端 Agent + 车间总控 + 执行验收
+./run_isaac_real_sim_test.sh --headless
+```
+
+### 3. 查看详细指南
+
+- **仿真启动指南**: [SIMULATION_GUIDE.md](./SIMULATION_GUIDE.md) - 如何单独启动各组件
+- **源码目录说明**: [src/README.md](./src/README.md) - 源码组织结构
+
+## 主要验证场景
+
+| 场景 | 启动方式 | 验证内容 |
+|------|---------|---------|
+| 快速闭环验证 | `launch_sim_stack.py --component vehicle-agent` + `minimal_workshop_demo.launch.py` | 车间总控能创建 session、生成阶段计划、调用车端接口 |
+| Isaac topic 检查 | `run_isaac_real_sim_test.sh --headless`(前半段) | Isaac 能发布传感器和真值 topic |
+| 完整 Isaac 仿真闭环 | `run_isaac_real_sim_test.sh --headless` | 场景、agent、桥接、总控一起运行 |
+| 传感器转发链路 | `--component vehicle-agent,sensor-ingest` | 车端能订阅 Isaac topic,车间端能拉取数据 |
+
+## 四条核心通信链路
+
+| 链路 | 方向 | 功能 | 组件 |
+|------|------|------|------|
+| 外部真值链路 | 外部系统 → 车端 | 位姿、速度、时间戳 | `external-pose-bridge` |
+| 底盘链路 | 车间 → 车端 | 下发标定动作、读取遥测 | `vehicle-agent-gateway` |
+| 运控链路 | 车间 → 车端 | 下发控制任务、读取误差 | `vehicle-agent-gateway` |
+| 传感器链路 | 车端 → 车间 | 相机、雷达、IMU 数据 | `sensor-ingest` |
+
+## 开发状态
+
+- ✅ **已完成**: 车间总控编排器、四类标定服务框架、车辆画像管理、Isaac 仿真环境、WiFi6/TCP 通信链路、端到端验收脚本
+- 🚧 **进行中**: 传感器外参标定采样链路、真实算法参数收敛
+- ⏳ **待开发**: 手眼标定、真实现场部署验证
+
+## 关键设计原则
+
+1. **主控只编排流程** - `workshop_orchestrator_v2` 负责阶段调度,具体标定由独立 ROS2 包实现
+2. **仿真与现场分离** - Isaac 代码只在 `simulation/`,真实车辆代码只在 `site_deployment/`
+3. **统一通信协议** - 车间与车端通过 WiFi6/TCP 通信,协议由 `communication/` 定义
+4. **车辆画像驱动** - 车辆能力、传感器配置通过 `vehicle_profile` 描述,支持多车型
diff --git a/agv_calib_brain/SIMULATION_GUIDE.md b/agv_calib_brain/SIMULATION_GUIDE.md
new file mode 100644
index 0000000..f41f66b
--- /dev/null
+++ b/agv_calib_brain/SIMULATION_GUIDE.md
@@ -0,0 +1,150 @@
+# 仿真环境启动指南
+
+本文档说明如何单独启动 Isaac 仿真环境的各个组件。
+
+## 前置条件
+
+```bash
+# 先 source ROS2 环境
+source install/setup.bash
+```
+
+## 单独启动组件
+
+### 1. Isaac 仿真环境
+
+```bash
+# 带可视化界面
+python3 src/simulation/tools/launch_sim_stack.py --component isaac
+
+# headless 模式(无界面)
+python3 src/simulation/tools/launch_sim_stack.py --component isaac --headless
+```
+
+### 2. 仿真车端统一 Agent
+
+包含底盘、运控、传感器数据转发:
+
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component vehicle-agent
+```
+
+### 3. 外部位姿桥
+
+将 Isaac 真值转发给车端:
+
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component external-pose-bridge
+```
+
+### 4. 车间侧传感器 Ingest
+
+从车端轮询传感器数据:
+
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component sensor-ingest
+```
+
+### 5. 车间 Gateway
+
+ROS2 节点,对接底盘/运控:
+
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component gateway
+```
+
+## 启动完整仿真链路
+
+### 方式一:一键启动所有仿真组件(不含车间总控)
+
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component all
+```
+
+### 方式二:分步启动(推荐用于调试)
+
+终端 1 - 启动 Isaac:
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component isaac
+```
+
+终端 2 - 启动车端 Agent:
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component vehicle-agent
+```
+
+终端 3 - 启动外部位姿桥:
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component external-pose-bridge
+```
+
+终端 4 - 启动传感器 Ingest:
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component sensor-ingest
+```
+
+终端 5 - 启动车间 Gateway:
+```bash
+python3 src/simulation/tools/launch_sim_stack.py --component gateway
+```
+
+终端 6 - 启动车间总控:
+```bash
+ros2 launch win_ubuntu_bridge minimal_workshop_demo.launch.py \
+ use_gateway:=true \
+ chassis_host:=127.0.0.1 \
+ control_host:=127.0.0.1 \
+ sensor_registry:=demo_front_camera,demo_down_camera,demo_lidar_3d,demo_lidar_2d,demo_imu
+```
+
+## 验证仿真环境
+
+启动后检查 topic:
+
+```bash
+# 查看 Isaac 发布的传感器数据
+ros2 topic list | grep isaac
+
+# 检查各传感器数据频率
+ros2 topic hz /sensor/front_camera/image_raw
+ros2 topic hz /sensor/down_camera/image_raw
+ros2 topic hz /sensor/lidar_3d/pointcloud
+ros2 topic hz /sensor/lidar_2d/scan
+ros2 topic hz /sensor/imu/data
+
+# 检查外部位姿
+ros2 topic hz /isaac/external_localization/telemetry
+```
+
+## 执行端到端验收测试
+
+仿真环境启动后,执行验收:
+
+```bash
+python3 src/simulation/tools/smoke_test_workshop_orchestrator.py \
+ --verbose-feedback \
+ --no-publish-fake-external-telemetry
+```
+
+## 停止仿真环境
+
+按 `Ctrl+C` 停止各组件,或使用:
+
+```bash
+./stop_isaac_real_sim_stack.sh
+```
+
+## 快捷脚本
+
+也可以使用一键测试脚本(启动所有组件并执行验收):
+
+```bash
+# 完整测试(启动 + 验收 + 停止)
+./run_isaac_real_sim_test.sh
+
+# 保持运行(不执行验收)
+./run_isaac_real_sim_test.sh --no-smoke --keep-running
+
+# headless 模式
+./run_isaac_real_sim_test.sh --headless
+```
diff --git a/agv_calib_brain/run_isaac_real_sim_test.sh b/agv_calib_brain/run_isaac_real_sim_test.sh
new file mode 100755
index 0000000..ceae4a7
--- /dev/null
+++ b/agv_calib_brain/run_isaac_real_sim_test.sh
@@ -0,0 +1,499 @@
+#!/usr/bin/env bash
+# 一键启动 Isaac 真实仿真闭环测试。
+#
+# 默认流程:
+# 1. 使用 conda 环境 AutoCalib_Workshop 启动 Isaac 标定车间;
+# 2. 启动仿真车端统一 agent、外部位姿桥和车间侧传感器 ingest;
+# 3. 启动车间总控 demo;
+# 4. 使用 Isaac 真实发布的真值/传感器数据执行 orchestrator 端到端验收;
+# 5. 验收结束后自动停止后台进程。
+
+set -Eeuo pipefail
+
+WORKSPACE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+CONDA_ENV_NAME="${CONDA_ENV_NAME:-AutoCalib_Workshop}"
+ROS_LOG_DIR="${ROS_LOG_DIR:-/tmp/roslog}"
+RUN_LOG_ROOT="${RUN_LOG_ROOT:-${WORKSPACE_DIR}/log/isaac_real_sim_$(date +%Y%m%d_%H%M%S)}"
+
+HEADLESS=0
+DO_BUILD=0
+RUN_SMOKE=1
+KEEP_RUNNING=0
+WITH_SENSOR_INGEST=1
+WAIT_FOR_ISAAC_TOPICS=1
+ISAAC_WAIT_SEC="${ISAAC_WAIT_SEC:-180}"
+WORKSHOP_WARMUP_SEC="${WORKSHOP_WARMUP_SEC:-5}"
+START_GRACE_SEC="${START_GRACE_SEC:-2}"
+SMOKE_TASKS=""
+
+PIDS=()
+NAMES=()
+LOGS=()
+CLEANED=0
+
+usage() {
+ cat <<'EOF'
+用法:
+ ./run_isaac_real_sim_test.sh [选项]
+
+默认会验证:
+ 1. Isaac 发布外部真值、前视相机、下视相机、3D 雷达、2D 雷达、IMU topic。
+ 2. 仿真车端统一 agent、外部位姿桥、车间侧传感器 ingest 都能启动并通信。
+ 3. 车间总控能创建 session,并默认执行 external,chassis,control,sensor_intrinsic 阶段。
+ 4. 传感器数据能从 Isaac -> 车端 -> WiFi6/TCP -> 车间侧链路流动。
+
+当前不验证:
+ 1. 真实底盘参数是否已经收敛。
+ 2. 真实相机内参、传感器外参是否已经被算法正确求解。
+ 3. 棋盘格角点数量、点云几何质量、时间同步精度等采样质量。
+
+选项:
+ --headless 以 headless 模式启动 Isaac。
+ --build 启动前先执行 colcon build。
+ --no-smoke 只启动仿真链路,不执行 orchestrator 验收。
+ --keep-running 验收结束后保持仿真链路运行,按 Ctrl+C 停止。
+ --no-sensor-ingest 不启动车间侧传感器 ingest 轮询进程。
+ --skip-topic-check 不等待 Isaac 真值/传感器 topic,直接继续启动后续链路。
+ --isaac-wait-sec SEC 等待 Isaac topic 的最长时间,默认 180 秒。
+ --warmup-sec SEC 总控 demo 启动后等待采集真值历史的时间,默认 5 秒。
+ --tasks LIST 覆盖 smoke_test_workshop_orchestrator.py 的任务列表。
+ 例: external,chassis,control,sensor_intrinsic
+ --conda-env NAME Isaac 进程使用的 conda 环境,默认 AutoCalib_Workshop。
+ -h, --help 显示帮助。
+
+环境变量:
+ CONDA_ENV_NAME 同 --conda-env。
+ ROS_LOG_DIR ROS 日志目录,默认 /tmp/roslog。
+ RUN_LOG_ROOT 本脚本各后台进程日志目录。
+
+示例:
+ ./run_isaac_real_sim_test.sh --headless
+ ./run_isaac_real_sim_test.sh --headless --keep-running
+ ./run_isaac_real_sim_test.sh --no-smoke
+EOF
+}
+
+log() {
+ echo "[INFO] $*"
+}
+
+warn() {
+ echo "[WARN] $*" >&2
+}
+
+die() {
+ echo "[ERROR] $*" >&2
+ exit 1
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --headless)
+ HEADLESS=1
+ shift
+ ;;
+ --build)
+ DO_BUILD=1
+ shift
+ ;;
+ --no-smoke)
+ RUN_SMOKE=0
+ KEEP_RUNNING=1
+ shift
+ ;;
+ --keep-running)
+ KEEP_RUNNING=1
+ shift
+ ;;
+ --no-sensor-ingest)
+ WITH_SENSOR_INGEST=0
+ shift
+ ;;
+ --skip-topic-check)
+ WAIT_FOR_ISAAC_TOPICS=0
+ shift
+ ;;
+ --isaac-wait-sec)
+ [[ $# -ge 2 ]] || die "--isaac-wait-sec 需要参数"
+ ISAAC_WAIT_SEC="$2"
+ shift 2
+ ;;
+ --warmup-sec)
+ [[ $# -ge 2 ]] || die "--warmup-sec 需要参数"
+ WORKSHOP_WARMUP_SEC="$2"
+ shift 2
+ ;;
+ --tasks)
+ [[ $# -ge 2 ]] || die "--tasks 需要参数"
+ SMOKE_TASKS="$2"
+ shift 2
+ ;;
+ --conda-env)
+ [[ $# -ge 2 ]] || die "--conda-env 需要参数"
+ CONDA_ENV_NAME="$2"
+ shift 2
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ *)
+ die "未知参数: $1"
+ ;;
+ esac
+done
+
+resolve_conda_sh() {
+ if [[ -n "${CONDA_SH:-}" && -f "${CONDA_SH}" ]]; then
+ echo "${CONDA_SH}"
+ return 0
+ fi
+
+ local candidate
+ for candidate in \
+ "${HOME}/anaconda3/etc/profile.d/conda.sh" \
+ "${HOME}/miniconda3/etc/profile.d/conda.sh" \
+ "/opt/conda/etc/profile.d/conda.sh"
+ do
+ if [[ -f "${candidate}" ]]; then
+ echo "${candidate}"
+ return 0
+ fi
+ done
+
+ if command -v conda >/dev/null 2>&1; then
+ local base
+ base="$(conda info --base 2>/dev/null || true)"
+ if [[ -n "${base}" && -f "${base}/etc/profile.d/conda.sh" ]]; then
+ echo "${base}/etc/profile.d/conda.sh"
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+source_ros_env() {
+ set +u
+ if [[ -f /opt/ros/humble/setup.bash ]]; then
+ source /opt/ros/humble/setup.bash
+ fi
+ source "${WORKSPACE_DIR}/install/setup.bash"
+ set -u
+}
+
+cleanup() {
+ if [[ "${CLEANED}" -eq 1 ]]; then
+ return
+ fi
+ CLEANED=1
+
+ if [[ "${#PIDS[@]}" -eq 0 ]]; then
+ return
+ fi
+
+ log "正在停止后台进程..."
+ local i pid name
+ for ((i=${#PIDS[@]}-1; i>=0; i--)); do
+ pid="${PIDS[$i]}"
+ name="${NAMES[$i]}"
+ if kill -0 "${pid}" >/dev/null 2>&1; then
+ log "发送 SIGINT: ${name} pid=${pid}"
+ kill -INT "${pid}" >/dev/null 2>&1 || true
+ fi
+ done
+
+ sleep 3
+ for ((i=${#PIDS[@]}-1; i>=0; i--)); do
+ pid="${PIDS[$i]}"
+ name="${NAMES[$i]}"
+ if kill -0 "${pid}" >/dev/null 2>&1; then
+ warn "${name} 未退出,发送 SIGTERM: pid=${pid}"
+ kill -TERM "${pid}" >/dev/null 2>&1 || true
+ fi
+ done
+
+ sleep 2
+ for ((i=${#PIDS[@]}-1; i>=0; i--)); do
+ pid="${PIDS[$i]}"
+ name="${NAMES[$i]}"
+ if kill -0 "${pid}" >/dev/null 2>&1; then
+ warn "${name} 仍未退出,发送 SIGKILL: pid=${pid}"
+ kill -KILL "${pid}" >/dev/null 2>&1 || true
+ fi
+ done
+}
+
+on_signal() {
+ trap - INT TERM
+ cleanup
+ exit 130
+}
+
+trap cleanup EXIT
+trap on_signal INT TERM
+
+start_bg() {
+ local name="$1"
+ shift
+ local logfile="${RUN_LOG_ROOT}/${name}.log"
+
+ log "启动 ${name},日志: ${logfile}"
+ "$@" >"${logfile}" 2>&1 &
+ local pid=$!
+ PIDS+=("${pid}")
+ NAMES+=("${name}")
+ LOGS+=("${logfile}")
+
+ sleep "${START_GRACE_SEC}"
+ if ! kill -0 "${pid}" >/dev/null 2>&1; then
+ warn "${name} 启动后立即退出,最近日志如下:"
+ tail -n 120 "${logfile}" >&2 || true
+ exit 1
+ fi
+}
+
+wait_for_tcp_port() {
+ local host="$1"
+ local port="$2"
+ local timeout_sec="$3"
+ local name="$4"
+ local deadline=$((SECONDS + timeout_sec))
+
+ log "等待 ${name} TCP ${host}:${port}"
+ while (( SECONDS < deadline )); do
+ if timeout 1 bash -c "/dev/null 2>&1; then
+ log "${name} 已就绪"
+ return 0
+ fi
+ sleep 1
+ done
+
+ warn "等待 ${name} 超时"
+ return 1
+}
+
+wait_for_ros_topic_once() {
+ local topic="$1"
+ local timeout_sec="$2"
+ local deadline=$((SECONDS + timeout_sec))
+ local echo_args=(--qos-reliability best_effort --once "${topic}")
+
+ case "${topic}" in
+ /sensor/front_camera/*|/sensor/down_camera/*|/sensor/lidar_3d/*)
+ echo_args=(--qos-reliability best_effort --once "${topic}" --field header)
+ ;;
+ esac
+
+ log "等待 Isaac topic: ${topic}"
+ while (( SECONDS < deadline )); do
+ if timeout 8s ros2 topic echo "${echo_args[@]}" >/dev/null 2>&1; then
+ log "已收到 topic: ${topic}"
+ return 0
+ fi
+ sleep 2
+ done
+
+ warn "等待 topic 超时: ${topic}"
+ warn "可检查 Isaac 日志: ${RUN_LOG_ROOT}/isaac.log"
+ if [[ -f "${RUN_LOG_ROOT}/isaac.log" ]]; then
+ warn "Isaac 最近日志:"
+ tail -n 120 "${RUN_LOG_ROOT}/isaac.log" >&2 || true
+ fi
+ return 1
+}
+
+wait_for_ros_service() {
+ local service="$1"
+ local timeout_sec="$2"
+ local deadline=$((SECONDS + timeout_sec))
+
+ log "等待 ROS service: ${service}"
+ while (( SECONDS < deadline )); do
+ if ros2 service list 2>/dev/null | grep -qx "${service}"; then
+ log "service 已就绪: ${service}"
+ return 0
+ fi
+ sleep 1
+ done
+
+ warn "等待 service 超时: ${service}"
+ return 1
+}
+
+check_no_existing_workshop_orchestrator() {
+ local nodes
+ nodes="$(timeout 5s ros2 node list 2>/dev/null || true)"
+ if [[ -z "${nodes}" ]]; then
+ return
+ fi
+
+ local count
+ count="$(printf '%s\n' "${nodes}" | grep -xc "/workshop_orchestrator_v2" || true)"
+ if [[ "${count}" -gt 0 ]]; then
+ die "检测到已有 /workshop_orchestrator_v2 节点。请先关闭旧的 workshop-demo/仿真脚本,或执行 ./stop_isaac_real_sim_stack.sh --kill 清理遗留进程,否则 create_session 和 execute_session 可能连到不同实例。"
+ fi
+}
+
+mkdir -p "${ROS_LOG_DIR}" "${RUN_LOG_ROOT}"
+
+if [[ "${DO_BUILD}" -eq 1 ]]; then
+ log "执行 colcon build"
+ (
+ cd "${WORKSPACE_DIR}"
+ set +u
+ if [[ -f /opt/ros/humble/setup.bash ]]; then
+ source /opt/ros/humble/setup.bash
+ fi
+ set -u
+ colcon build
+ )
+fi
+
+[[ -f "${WORKSPACE_DIR}/install/setup.bash" ]] || die "找不到 install/setup.bash,请先执行 colcon build,或使用 --build"
+
+CONDA_SH_PATH="$(resolve_conda_sh || true)"
+[[ -n "${CONDA_SH_PATH}" ]] || die "找不到 conda.sh,无法激活 conda 环境 ${CONDA_ENV_NAME}"
+
+source_ros_env
+
+log "工作空间: ${WORKSPACE_DIR}"
+log "ROS_LOG_DIR: ${ROS_LOG_DIR}"
+log "进程日志目录: ${RUN_LOG_ROOT}"
+log "Isaac conda 环境: ${CONDA_ENV_NAME}"
+
+export PYTHONUNBUFFERED=1
+check_no_existing_workshop_orchestrator
+
+ISAAC_HEADLESS_ARG=""
+if [[ "${HEADLESS}" -eq 1 ]]; then
+ ISAAC_HEADLESS_ARG="--headless"
+fi
+
+start_bg "isaac" bash -lc "
+ set -Eeuo pipefail
+ cd '${WORKSPACE_DIR}'
+ set +u
+ source '${CONDA_SH_PATH}'
+ conda activate '${CONDA_ENV_NAME}'
+ if [[ -f /opt/ros/humble/setup.bash ]]; then
+ source /opt/ros/humble/setup.bash
+ fi
+ source '${WORKSPACE_DIR}/install/setup.bash'
+ set -u
+ export ROS_LOG_DIR='${ROS_LOG_DIR}'
+ exec python3 src/simulation/tools/launch_sim_stack.py --component isaac ${ISAAC_HEADLESS_ARG}
+"
+
+if [[ "${WAIT_FOR_ISAAC_TOPICS}" -eq 1 ]]; then
+ wait_for_ros_topic_once "/isaac/external_localization/telemetry" "${ISAAC_WAIT_SEC}" || exit 1
+ wait_for_ros_topic_once "/sensor/front_camera/image_raw" "${ISAAC_WAIT_SEC}" || exit 1
+ wait_for_ros_topic_once "/sensor/down_camera/image_raw" "${ISAAC_WAIT_SEC}" || exit 1
+ wait_for_ros_topic_once "/sensor/lidar_3d/pointcloud" "${ISAAC_WAIT_SEC}" || exit 1
+ wait_for_ros_topic_once "/sensor/imu/data" "${ISAAC_WAIT_SEC}" || exit 1
+ wait_for_ros_topic_once "/sensor/lidar_2d/scan" "${ISAAC_WAIT_SEC}" || exit 1
+fi
+
+start_bg "vehicle-agent" bash -lc "
+ set -Eeuo pipefail
+ cd '${WORKSPACE_DIR}'
+ set +u
+ if [[ -f /opt/ros/humble/setup.bash ]]; then
+ source /opt/ros/humble/setup.bash
+ fi
+ source '${WORKSPACE_DIR}/install/setup.bash'
+ set -u
+ export ROS_LOG_DIR='${ROS_LOG_DIR}'
+ exec python3 src/simulation/tools/launch_sim_stack.py --component vehicle-agent
+"
+wait_for_tcp_port "127.0.0.1" 9000 30 "vehicle-agent unified WiFi6" || exit 1
+
+start_bg "external-pose-bridge" bash -lc "
+ set -Eeuo pipefail
+ cd '${WORKSPACE_DIR}'
+ set +u
+ if [[ -f /opt/ros/humble/setup.bash ]]; then
+ source /opt/ros/humble/setup.bash
+ fi
+ source '${WORKSPACE_DIR}/install/setup.bash'
+ set -u
+ export ROS_LOG_DIR='${ROS_LOG_DIR}'
+ exec python3 src/simulation/tools/launch_sim_stack.py --component external-pose-bridge
+"
+
+if [[ "${WITH_SENSOR_INGEST}" -eq 1 ]]; then
+ start_bg "sensor-ingest" bash -lc "
+ set -Eeuo pipefail
+ cd '${WORKSPACE_DIR}'
+ set +u
+ if [[ -f /opt/ros/humble/setup.bash ]]; then
+ source /opt/ros/humble/setup.bash
+ fi
+ source '${WORKSPACE_DIR}/install/setup.bash'
+ set -u
+ export ROS_LOG_DIR='${ROS_LOG_DIR}'
+ exec python3 src/simulation/tools/launch_sim_stack.py --component sensor-ingest
+ "
+fi
+
+start_bg "workshop-demo" bash -lc "
+ set -Eeuo pipefail
+ cd '${WORKSPACE_DIR}'
+ set +u
+ if [[ -f /opt/ros/humble/setup.bash ]]; then
+ source /opt/ros/humble/setup.bash
+ fi
+ source '${WORKSPACE_DIR}/install/setup.bash'
+ set -u
+ export ROS_LOG_DIR='${ROS_LOG_DIR}'
+ exec ros2 launch win_ubuntu_bridge minimal_workshop_demo.launch.py \
+ use_gateway:=true \
+ chassis_host:=127.0.0.1 \
+ control_host:=127.0.0.1 \
+ sensor_registry:=demo_front_camera,demo_down_camera,demo_lidar_3d,demo_lidar_2d,demo_imu
+"
+
+wait_for_ros_service "/workshop_v2/create_session" 60 || exit 1
+
+log "等待 ${WORKSHOP_WARMUP_SEC}s,让 external_localization_service 累积 Isaac 真值历史"
+sleep "${WORKSHOP_WARMUP_SEC}"
+
+SMOKE_STATUS=0
+if [[ "${RUN_SMOKE}" -eq 1 ]]; then
+ SMOKE_ARGS=(
+ --verbose-feedback
+ --no-publish-fake-external-telemetry
+ )
+ if [[ -n "${SMOKE_TASKS}" ]]; then
+ SMOKE_ARGS+=(--tasks "${SMOKE_TASKS}")
+ fi
+
+ SMOKE_LOG="${RUN_LOG_ROOT}/smoke.log"
+ log "执行 orchestrator 端到端验收,日志: ${SMOKE_LOG}"
+ set +e
+ (
+ cd "${WORKSPACE_DIR}"
+ source_ros_env
+ export ROS_LOG_DIR="${ROS_LOG_DIR}"
+ python3 src/simulation/tools/smoke_test_workshop_orchestrator.py "${SMOKE_ARGS[@]}"
+ ) 2>&1 | tee "${SMOKE_LOG}"
+ SMOKE_STATUS=${PIPESTATUS[0]}
+ set -e
+
+ if [[ "${SMOKE_STATUS}" -eq 0 ]]; then
+ log "仿真闭环验收通过"
+ else
+ warn "仿真闭环验收失败,退出码: ${SMOKE_STATUS}"
+ fi
+else
+ log "已按 --no-smoke 跳过 orchestrator 验收"
+fi
+
+if [[ "${KEEP_RUNNING}" -eq 1 ]]; then
+ log "仿真链路保持运行中。按 Ctrl+C 停止。"
+ while true; do
+ sleep 3600
+ done
+fi
+
+exit "${SMOKE_STATUS}"
diff --git a/agv_calib_brain/src/README.md b/agv_calib_brain/src/README.md
index 7ed7d72..818ced4 100644
--- a/agv_calib_brain/src/README.md
+++ b/agv_calib_brain/src/README.md
@@ -1,141 +1,59 @@
-# 🧠 AGV 标定中央大脑
+# 源码目录结构
-**环境**: Ubuntu 22.04 + ROS 2 Humble | **语言**: C++ | **通信**: gRPC over Wi-Fi 6
+`src` 按“仿真、核心逻辑、通信、现场部署”的边界组织,而不是按临时实验文件组织。
-> 标定车间的"发令大脑",通过局域网跨平台遥控 Windows 车端执行动作并拉取遥测数据。
+## 目录说明
----
+- `apps/`
+ 面向操作人员的工具和界面原型。
-## 📋 目录
+- `communication/`
+ ROS 2 接口包、TCP 帧协议、车间工控机到车端电脑的 gateway。这个层应该同时服务于仿真和现场部署。
-1. [系统依赖安装](#1-系统依赖一键安装)
-2. [VS Code 插件配置](#2-vs-code-核心插件配置)
-3. [解决 IntelliSense 报错](#3-解决-vs-code-红色波浪线)
-4. [编译与运行](#4-编译与运行)
+- `core/`
+ 标定流程和标定算法,包括 `workshop_orchestrator`、底盘标定、运控标定、传感器标定、车辆参数管理等可复用核心逻辑。
----
+- `simulation/`
+ 部署前仿真验证代码。Isaac 车间、仿真车辆、仿真车端 agent、仿真传感器、仿真标定靶和旧版仿真包都放在这里。
-## 1. 系统依赖一键安装
+- `deployment/`
+ 部署 profile 和从仿真迁移到现场前的检查清单。这里放配置基准,不放算法实现。
-在 Ubuntu 22.04 终端执行以下命令:
+- `docs/`
+ 源码树内的设计说明、边界说明和迁移规则。
+
+- `site_deployment/`
+ 真实现场部署代码,例如真实车端电脑适配器、真实车辆 SDK、PLC/CAN 或厂商控制器对接代码。
+
+## 边界规则
+
+- Isaac API 只放在 `simulation/`。
+- 真实车辆 SDK、PLC、CAN、厂商控制器相关代码只放在 `site_deployment/`。
+- ROS 2 接口、TCP 协议和 gateway 放在 `communication/`。
+- 编排流程和标定算法放在 `core/`。
+- 部署 profile 放在 `deployment/`。
+- 设计说明和迁移边界说明放在 `docs/`。
+
+## 主要入口
+
+Isaac 车间仿真:
```bash
-sudo apt update
-sudo apt install -y build-essential cmake pkg-config gdb
-sudo apt install -y protobuf-compiler-grpc libgrpc++-dev libprotobuf-dev protobuf-compiler
+python3 src/simulation/isaac_workshop_sim/scripts/build_calibration_room.py
```
-> ⚠️ **警告**: 严禁自行去 GitHub 源码编译 gRPC,直接使用 Ubuntu 官方 APT 源即可,避免浪费时间与报错。
-
----
-
-## 2. VS Code 核心插件配置
-
-打开 VS Code → 扩展商店 (Extensions),**必须安装**以下 4 个插件:
-
-| 插件名称 | 开发者 | 用途 |
-|---------|--------|------|
-| **C/C++** | Microsoft | 代码补全与 GDB 调试 |
-| **CMake Tools** | Microsoft | 底部快速构建状态栏 |
-| **ROS** | Microsoft | 自动识别 `colcon` 工作空间 |
-| **vscode-proto3** | zxh404 | `.proto` 文件语法高亮 |
-
----
-
-## 3. 解决 VS Code 红色波浪线 (IntelliSense 报错)
-
-**问题原因**: gRPC 生成的 `.pb.h` 文件在 `colcon build` 阶段动态生成于 `build/` 目录,VS Code 初始无法识别。
-
-**修复步骤**:
-
-1. 按 `Ctrl+Shift+P` → 输入 `C/C++: Edit Configurations (JSON)`
-2. 确保 `c_cpp_properties.json` 包含以下配置:
-
-```json
-{
- "configurations": [
- {
- "name": "ROS2",
- "includePath": [
- "${workspaceFolder}/**",
- "/opt/ros/humble/include/**",
- "${workspaceFolder}/build/agv_calib_brain/grpc_gen/**"
- ],
- "compilerPath": "/usr/bin/gcc",
- "cStandard": "c17",
- "cppStandard": "c++17",
- "intelliSenseMode": "linux-gcc-x64"
- }
- ]
-}
-```
-
-> 💡 **提示**: `grpc_gen` 是 CMakeLists 中配置的自动生成源码路径,请根据实际情况微调。
-
----
-
-## 4. 编译与运行 (CMake 自动化)
-
-### 4.0 最小联调闭环
-
-当前仓库已经补齐了一个最小可运行闭环:
-
-- `vehicle_profile_manager`:提供默认车辆画像
-- `external_localization_service`:提供外部真值校核的最小执行端
-- `workshop_orchestrator_v2`:负责编排会话、计划和报告
-
-启动顺序:
+仿真车端 agent:
```bash
-source /opt/ros/humble/setup.bash
-source install/setup.bash
-ros2 launch win_ubuntu_bridge minimal_workshop_demo.launch.py
+python3 src/simulation/vehicle_agent_sim/scripts/isaac_vehicle_agent_sim.py
```
-如果只想单独跑编排器:
+按 profile 启动完整仿真链路:
```bash
-ros2 launch workshop_orchestrator_v2 workshop_orchestrator_v2.launch.py
+python3 src/simulation/tools/launch_sim_stack.py
```
-可先调用这些接口做联调:
+这条链路中,车间工控机与车端电脑之间的底盘、运控、外部真值位姿和传感器数据都通过 TCP/WiFi6 仿真边界传输;Isaac topic 只留在仿真内部。
-- `/vehicle_profile_manager/get_vehicle_profile`
-- `/vehicle_profile_manager/evaluate_vehicle_calibration_applicability`
-- `/external_localization/get_readiness`
-- `/external_localization/execute_task`
-- `/workshop_v2/create_session`
-- `/workshop_v2/execute_session`
-- `/workshop_v2/get_report`
-
-最小会话建议至少包含:
-
-- `session.config.localization_source_id = demo_vehicle_001`
-- `session.config.workcell_zone_id = demo_workcell`
-- 一个 `requested_tasks`,其中 `stage_type = EXTERNAL_REFERENCE_READY_CHECK_STAGE`
-- 该任务的 `task_params` 至少包含:
- - `external.static_sample_count`
- - `external.dynamic_sample_count`
- - `external.max_position_stddev_m`
- - `external.max_yaw_stddev_rad`
- - `external.max_tracking_loss_ratio`
- - `external.max_time_sync_offset_ms`
- - `external.timeout_sec`
-
-
-> ✨ **无需手动执行 `protoc`** —— CMakeLists.txt 已配置自动化脚本,编译时自动生成 C++ 网络源码。
-
-### 4.1 编译
-
-```bash
-# 回到工作空间根目录(如 ~/agv_ws)
-source /opt/ros/humble/setup.bash
-colcon build --packages-select agv_calib_brain --symlink-install
-```
-
-### 4.2 运行
-
-```bash
-source install/setup.bash
-ros2 run agv_calib_brain brain_node
-```
\ No newline at end of file
+车间 gateway 和 `workshop_orchestrator` 仍然按 ROS 2 包名启动;源码分别在 `communication/` 和 `core/` 下。
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/differential_chassis_algorithm.cpp b/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/differential_chassis_algorithm.cpp
deleted file mode 100644
index 2ff4629..0000000
--- a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/differential_chassis_algorithm.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "chassis_calibration_service/chassis_calibration_common.hpp"
-
-namespace chassis_calibration_service
-{
-
-bool DifferentialChassisAlgorithm::run(
- const ChassisCalibrationInput & input,
- ChassisCalibrationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // TODO: 在这里填写差速底盘标定算法。
- // 算法工程师应从这里读取并计算:
- // - 任务请求:input.request(request_id、任务目的、selected_primitive、straight_line 参数、timeout 等)
- // - 底盘反馈:由上层扩展到 ChassisCalibrationInput 中的实时数据(轮速、左右电机反馈、IMU、里程计、定位等)
- // - 输出:output.response.result(success、error_code、validation_summary、estimated_params、artifacts 等)
- fill_common_result(input, output);
- output.response.result.message = "differential chassis template executed.";
- output.response.result.recommended_parameter_version = "differential_template_v1";
- return true;
-}
-
-} // namespace chassis_calibration_service
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/pure_pursuit_control_calibration_algorithm.cpp b/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/pure_pursuit_control_calibration_algorithm.cpp
deleted file mode 100644
index a9b20dc..0000000
--- a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/pure_pursuit_control_calibration_algorithm.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "control_calibration_service/control_calibration_common.hpp"
-
-namespace control_calibration_service
-{
-
-bool PurePursuitControlCalibrationAlgorithm::run(
- const ControlCalibrationInput & input,
- ControlCalibrationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // Pure Pursuit 控制标定模板:
- // 适合基于参考轨迹和前视点策略的横向控制评估。
- // 算法工程师通常会在这里处理:
- // 1. 参考轨迹读取:
- // - input.reference_trajectory
- // - input.reference_stop_at_end / input.reference_timeout_sec
- // 2. 观测输入:
- // - input.control_telemetry_history 中的横向误差、航向误差、转向输出
- // - input.chassis_telemetry_history 中的速度、姿态和底盘运动状态
- // - input.truth_source_diagnostics / 真值历史,用于判断轨迹对齐是否可靠
- // 3. 参数输出:
- // - 可将前视距离、速度相关增益等写入 output.response.result.estimated_parameter_set
- // 4. 验收输出:
- // - 将最大误差、均方误差、振荡情况、自动验收结论写入 validation_summary
- fill_common_result(input, output);
- output.response.result.message = "pure pursuit control calibration template executed.";
- output.response.result.recommended_parameter_version = "pure_pursuit_template_v1";
- return true;
-}
-
-} // namespace control_calibration_service
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_localization_service_node.cpp b/agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_localization_service_node.cpp
deleted file mode 100644
index 02f81b6..0000000
--- a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_localization_service_node.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-#include "external_localization_service/external_localization_service_node.hpp"
-
-#include
-#include
-
-#include "calibration_common_interfaces/msg/error_code.hpp"
-#include "calibration_common_interfaces/msg/job_state.hpp"
-
-namespace external_localization_service
-{
-
-namespace
-{
-int64_t now_us()
-{
- return std::chrono::duration_cast(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
-}
-} // namespace
-
-using calibration_common_interfaces::msg::ErrorCode;
-using calibration_common_interfaces::msg::JobState;
-
-ExternalLocalizationServiceNode::ExternalLocalizationServiceNode(const rclcpp::NodeOptions & options)
-: Node("external_localization_service", options)
-{
- readiness_service_ = create_service(
- "/external_localization/get_readiness",
- std::bind(&ExternalLocalizationServiceNode::handle_readiness, this, std::placeholders::_1, std::placeholders::_2));
-
- execute_task_action_server_ = rclcpp_action::create_server(
- this,
- "/external_localization/execute_task",
- std::bind(&ExternalLocalizationServiceNode::handle_goal, this, std::placeholders::_1, std::placeholders::_2),
- std::bind(&ExternalLocalizationServiceNode::handle_cancel, this, std::placeholders::_1),
- std::bind(&ExternalLocalizationServiceNode::handle_accepted, this, std::placeholders::_1));
-}
-
-void ExternalLocalizationServiceNode::handle_readiness(
- const std::shared_ptr request,
- std::shared_ptr response)
-{
- (void)request;
-
- // 这里先保留最小 readiness 逻辑。
- // 后续若接入真实外部定位设备/真值源桥接程序,可在这里增加:
- // - 真值源在线检查
- // - 同步状态检查
- // - 覆盖范围检查
- // - 观测质量检查
- // - 切源稳定性检查
- response->response.success = true;
- response->response.error_code.code = ErrorCode::OK;
- response->response.message = "external_localization_service is ready.";
- response->response.agent_ready = true;
- response->response.ready_for_reference_validation = true;
- response->response.checked_timestamp_us = now_us();
- response->response.validation_summary.time_sync_ok = true;
- response->response.validation_summary.coverage_ok = true;
- response->response.validation_summary.quality_ok = true;
- response->response.validation_summary.tracking_stable = true;
- response->response.validation_summary.recommended_as_truth_source = true;
- response->response.validation_summary.position_stddev_m = 0.0;
- response->response.validation_summary.yaw_stddev_rad = 0.0;
- response->response.validation_summary.tracking_loss_ratio = 0.0;
- response->response.validation_summary.time_sync_offset_ms = 0.0;
-}
-
-rclcpp_action::GoalResponse ExternalLocalizationServiceNode::handle_goal(
- const rclcpp_action::GoalUUID & /*uuid*/,
- std::shared_ptr goal)
-{
- std::string reject_reason;
- if (!executor_.validate_goal(*goal, reject_reason)) {
- RCLCPP_WARN(get_logger(), "Reject external_localization goal: %s", reject_reason.c_str());
- return rclcpp_action::GoalResponse::REJECT;
- }
- return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
-}
-
-rclcpp_action::CancelResponse ExternalLocalizationServiceNode::handle_cancel(
- const std::shared_ptr /*goal_handle*/)
-{
- return rclcpp_action::CancelResponse::ACCEPT;
-}
-
-void ExternalLocalizationServiceNode::handle_accepted(
- const std::shared_ptr goal_handle)
-{
- std::thread(std::bind(&ExternalLocalizationServiceNode::execute_goal, this, goal_handle)).detach();
-}
-
-void ExternalLocalizationServiceNode::execute_goal(
- const std::shared_ptr goal_handle)
-{
- auto feedback = std::make_shared();
- feedback->feedback.job_id = goal_handle->get_goal()->goal.header.request_id;
- feedback->feedback.state.state = JobState::RUNNING;
- feedback->feedback.progress = 0.5;
- feedback->feedback.error_code.code = ErrorCode::OK;
- feedback->feedback.message = "external localization task is running.";
- feedback->feedback.server_timestamp_us = now_us();
- feedback->feedback.safe_to_retry = false;
- goal_handle->publish_feedback(feedback);
-
- auto result = std::make_shared();
- std::string failure_reason;
- if (!executor_.build_result(*goal_handle->get_goal(), *result, failure_reason)) {
- result->result.success = false;
- result->result.error_code.code = ErrorCode::INVALID_ARGUMENT;
- result->result.message = failure_reason;
- goal_handle->abort(result);
- return;
- }
-
- goal_handle->succeed(result);
-}
-
-} // namespace external_localization_service
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/marker_alignment_algorithm.cpp b/agv_calib_brain/src/agv_calib_core/external_localization_service/src/marker_alignment_algorithm.cpp
deleted file mode 100644
index 3936365..0000000
--- a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/marker_alignment_algorithm.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "external_localization_service/external_localization_common.hpp"
-
-namespace external_localization_service
-{
-
-bool MarkerAlignmentAlgorithm::run(
- const ExternalLocalizationInput & input,
- ExternalLocalizationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // 标靶对齐模板:
- // 【本文件负责什么】
- // - 负责标靶检测结果读取、坐标系对齐求解和残差统计相关算法实现。
- // - 后续算法工程师应主要修改本文件,不要改 node 层和模板分发层。
- //
- // 【建议优先读取的输入】
- // 1. input.marker_alignment_task
- // - target_board_id、min_valid_observation_count、timeout_sec 等关键约束。
- // 2. input.latest_external_localization_telemetry / input.external_localization_telemetry_history
- // - 读取观测位姿、标准差、丢失率、时间同步偏差和质量评分。
- // 3. input.marker_alignment_diagnostics
- // - 读取标靶检测失败、角点不足、姿态求解不稳定等问题描述。
- // 4. input.sensor_quality_diagnostics
- // - 如果标靶检测依赖相机 / LiDAR 质量,可在这里读取辅助质量信息。
- //
- // 【必写输出】
- // 1. output.response.result.result.workshop_to_localization
- // - 这是标靶对齐最核心的输出结果。
- // 2. output.response.result.result.residual_error_m / residual_error_rad
- // - 写回对齐残差,供 orchestrator 判断是否自动验收。
- // 3. output.response.result.validation_summary
- // - 写位置标准差、航向标准差、时间同步偏差等摘要。
- //
- // 【可选输出】
- // - output.response.result.artifacts
- // 可挂标靶检测日志、可视化结果、拟合报告、残差统计文件等。
- //
- // 【常见失败原因】
- // - 有效观测数不足、标靶检测失败、姿态求解不稳定、时间同步异常、质量评分过低。
- //
- // 【在这里添加真实算法】
- // - 请在 fill_external_localization_common_success(...) 之前或之后补充真实对齐求解逻辑。
- // - 当前文件仅提供交付模板,不包含真实外部定位算法。
-
- fill_external_localization_common_success(
- input,
- output,
- "标靶对齐完成。",
- "demo_external_marker_alignment_v1");
-
- output.response.result.result.workshop_frame_id = "workshop";
- output.response.result.result.localization_frame_id = "localization";
- output.response.result.result.workshop_to_localization.z_m = 0.0;
- output.response.result.result.position_repeatability_m = 0.0;
- output.response.result.result.yaw_repeatability_rad = 0.0;
- output.response.result.result.residual_error_m = 0.0;
- output.response.result.result.residual_error_rad = 0.0;
- output.response.result.result.tracking_loss_ratio = 0.0;
- output.response.result.result.time_sync_offset_ms = 0.0;
- output.response.result.result.validated_as_truth_source = true;
- return true;
-}
-
-} // namespace external_localization_service
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/reference_pose_collection_algorithm.cpp b/agv_calib_brain/src/agv_calib_core/external_localization_service/src/reference_pose_collection_algorithm.cpp
deleted file mode 100644
index eb45138..0000000
--- a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/reference_pose_collection_algorithm.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "external_localization_service/external_localization_common.hpp"
-
-namespace external_localization_service
-{
-
-bool ReferencePoseCollectionAlgorithm::run(
- const ExternalLocalizationInput & input,
- ExternalLocalizationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // 参考位姿采集模板:
- // 【本文件负责什么】
- // - 负责参考位姿采集与静态重复性分析相关算法实现。
- // - 后续算法工程师应主要修改本文件,不要改 node 层和模板分发层。
- //
- // 【建议优先读取的输入】
- // 1. input.reference_pose_collection_task
- // - sample_count、require_vehicle_static、timeout_sec、min_sample_interval_sec 等采样约束。
- // 2. input.latest_external_localization_telemetry / input.external_localization_telemetry_history
- // - 每帧外部定位位姿、位置标准差、航向标准差、时间同步偏差、质量评分。
- // 3. input.latest_chassis_telemetry / input.chassis_telemetry_history
- // - 用于判断车辆是否真实静止,避免采入无效参考位姿。
- // 4. input.truth_source_diagnostics / input.acquisition_diagnostics
- // - 记录时间同步异常、观测缺失、采样不足、落盘失败等问题。
- //
- // 【必写输出】
- // 1. output.response.result.validation_summary
- // - 写位置标准差、航向标准差、时间同步偏差、是否推荐为真值源等摘要。
- // 2. output.response.result.result
- // - 写 workshop_frame_id / localization_frame_id / repeatability / residual 等结果。
- // 3. output.response.result.suitable_for_commit
- // - 明确当前采集结果是否建议进入下一阶段。
- //
- // 【可选输出】
- // - output.response.result.artifacts
- // 可挂采样日志、原始位姿文件、统计报告等文件引用。
- //
- // 【常见失败原因】
- // - 车辆未静止、有效样本不足、时间同步超标、外部定位观测丢失、采样频率不足。
- //
- // 【在这里添加真实算法】
- // - 请在 fill_external_localization_common_success(...) 之前或之后补充真实采样与统计逻辑。
- // - 当前文件仅提供交付模板,不包含真实外部定位算法。
-
- fill_external_localization_common_success(
- input,
- output,
- "参考位姿采集完成。",
- "demo_external_reference_pose_collection_v1");
-
- output.response.result.result.workshop_frame_id = "workshop";
- output.response.result.result.localization_frame_id = "localization";
- output.response.result.result.position_repeatability_m = 0.0;
- output.response.result.result.yaw_repeatability_rad = 0.0;
- output.response.result.result.residual_error_m = 0.0;
- output.response.result.result.residual_error_rad = 0.0;
- output.response.result.result.tracking_loss_ratio = 0.0;
- output.response.result.result.time_sync_offset_ms = 0.0;
- output.response.result.result.validated_as_truth_source = true;
- return true;
-}
-
-} // namespace external_localization_service
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/truth_source_validation_algorithm.cpp b/agv_calib_brain/src/agv_calib_core/external_localization_service/src/truth_source_validation_algorithm.cpp
deleted file mode 100644
index 6987fc9..0000000
--- a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/truth_source_validation_algorithm.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "external_localization_service/external_localization_common.hpp"
-
-namespace external_localization_service
-{
-
-bool TruthSourceValidationAlgorithm::run(
- const ExternalLocalizationInput & input,
- ExternalLocalizationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // 真值源验证模板:
- // 【本文件负责什么】
- // - 负责静态重复性、动态稳定性、时间同步与丢失率等真值源验证算法实现。
- // - 后续算法工程师应主要修改本文件,不要改 node 层和模板分发层。
- //
- // 【建议优先读取的输入】
- // 1. input.truth_source_validation_task
- // - static_sample_count、dynamic_sample_count、require_short_motion_segment 等任务要求。
- // 2. input.external_localization_telemetry_history
- // - 外部定位历史观测窗口,是稳定性、同步性、重复性分析的核心输入。
- // 3. input.chassis_telemetry_history / input.control_telemetry_history
- // - 如果要求短运动段验证,需要结合车辆实际运动状态和控制输出做时序对齐。
- // 4. input.sensor_telemetry_history
- // - 用于判断辅助传感器质量是否影响外部定位观测可信度。
- // 5. input.truth_source_diagnostics
- // - 记录时间同步超标、观测丢失、切源异常等问题。
- //
- // 【必写输出】
- // 1. output.response.result.validation_summary
- // - 这是 orchestrator 自动验收最关键的摘要区域。
- // 2. output.response.result.result
- // - 写 repeatability、tracking_loss_ratio、time_sync_offset_ms 等核心结果。
- // 3. output.response.result.data_quality_passed / suitable_for_commit
- // - 明确当前真值源是否可进入后续标定闭环。
- //
- // 【可选输出】
- // - output.response.result.artifacts
- // 可挂稳定性分析报告、同步统计图、丢失率分析文件等。
- //
- // 【常见失败原因】
- // - 动态窗口不足、时间同步偏差超阈值、观测丢失率过高、重复性不满足要求。
- //
- // 【在这里添加真实算法】
- // - 请在 fill_external_localization_common_success(...) 之前或之后补充真实验证逻辑。
- // - 当前文件仅提供交付模板,不包含真实外部定位算法。
-
- fill_external_localization_common_success(
- input,
- output,
- "真值源验证完成。",
- "demo_external_truth_source_validation_v1");
-
- output.response.result.validation_summary.time_sync_ok = true;
- output.response.result.validation_summary.coverage_ok = true;
- output.response.result.validation_summary.quality_ok = true;
- output.response.result.validation_summary.tracking_stable = true;
- output.response.result.validation_summary.recommended_as_truth_source = true;
- output.response.result.validation_summary.position_stddev_m = 0.0;
- output.response.result.validation_summary.yaw_stddev_rad = 0.0;
- output.response.result.validation_summary.tracking_loss_ratio = 0.0;
- output.response.result.validation_summary.time_sync_offset_ms = 0.0;
-
- output.response.result.result.workshop_frame_id = "workshop";
- output.response.result.result.localization_frame_id = "localization";
- output.response.result.result.position_repeatability_m = 0.0;
- output.response.result.result.yaw_repeatability_rad = 0.0;
- output.response.result.result.residual_error_m = 0.0;
- output.response.result.result.residual_error_rad = 0.0;
- output.response.result.result.tracking_loss_ratio = 0.0;
- output.response.result.result.time_sync_offset_ms = 0.0;
- output.response.result.result.validated_as_truth_source = true;
- return true;
-}
-
-} // namespace external_localization_service
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_calibration_service_node.cpp b/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_calibration_service_node.cpp
deleted file mode 100644
index 624f09b..0000000
--- a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_calibration_service_node.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-#include "sensor_calibration_service/sensor_calibration_service_node.hpp"
-
-#include
-#include
-
-#include "calibration_common_interfaces/msg/error_code.hpp"
-#include "calibration_common_interfaces/msg/job_state.hpp"
-#include "calibration_sensor_interfaces/msg/sensor_calibration_job_result.hpp"
-#include "calibration_sensor_interfaces/msg/sensor_readiness_response.hpp"
-
-namespace sensor_calibration_service
-{
-
-namespace
-{
-int64_t now_us()
-{
- return std::chrono::duration_cast(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
-}
-} // namespace
-
-using calibration_common_interfaces::msg::ErrorCode;
-using calibration_common_interfaces::msg::JobState;
-
-SensorCalibrationServiceNode::SensorCalibrationServiceNode(const rclcpp::NodeOptions & options)
-: Node("sensor_calibration_service", options)
-{
- readiness_service_ = create_service(
- "/sensor_calibration/get_readiness",
- std::bind(&SensorCalibrationServiceNode::handle_readiness, this, std::placeholders::_1, std::placeholders::_2));
-
- execute_task_action_server_ = rclcpp_action::create_server(
- this,
- "/sensor_calibration/execute_task",
- std::bind(&SensorCalibrationServiceNode::handle_goal, this, std::placeholders::_1, std::placeholders::_2),
- std::bind(&SensorCalibrationServiceNode::handle_cancel, this, std::placeholders::_1),
- std::bind(&SensorCalibrationServiceNode::handle_accepted, this, std::placeholders::_1));
-}
-
-void SensorCalibrationServiceNode::handle_readiness(
- const std::shared_ptr request,
- std::shared_ptr response)
-{
- (void)request;
- response->response.success = true;
- response->response.error_code.code = ErrorCode::OK;
- response->response.message = "sensor_calibration_service is ready.";
- response->response.agent_ready = true;
- response->response.capture_pipeline_ready = true;
- response->response.storage_ready = true;
- response->response.telemetry_ready = true;
- response->response.vehicle_safe_to_move = true;
- response->response.arm_ready = true;
- response->response.ready_sensor_ids.push_back("demo_sensor_001");
- response->response.checked_timestamp_us = now_us();
-}
-
-rclcpp_action::GoalResponse SensorCalibrationServiceNode::handle_goal(
- const rclcpp_action::GoalUUID & /*uuid*/,
- std::shared_ptr goal)
-{
- if (goal->goal.header.request_id.empty()) {
- return rclcpp_action::GoalResponse::REJECT;
- }
- return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
-}
-
-rclcpp_action::CancelResponse SensorCalibrationServiceNode::handle_cancel(
- const std::shared_ptr /*goal_handle*/)
-{
- return rclcpp_action::CancelResponse::ACCEPT;
-}
-
-void SensorCalibrationServiceNode::handle_accepted(
- const std::shared_ptr goal_handle)
-{
- std::thread(std::bind(&SensorCalibrationServiceNode::execute_goal, this, goal_handle)).detach();
-}
-
-void SensorCalibrationServiceNode::execute_goal(
- const std::shared_ptr goal_handle)
-{
- // 先回一帧 RUNNING feedback,告诉 orchestrator 当前任务已经进入执行阶段。
- auto feedback = std::make_shared();
- feedback->feedback.state.state = JobState::RUNNING;
- goal_handle->publish_feedback(feedback);
-
- // ===== 组装算法输入上下文 =====
- // 当前模板阶段先把“算法最常用的任务侧输入”显式展开。
- // 后续如果要接真实车辆画像、已生效参数查询、历史遥测缓存、外部定位缓存,
- // 也应继续在这里补齐并写入 SensorCalibrationInput。
- SensorCalibrationAlgorithmTemplate::Input input;
- input.request = *goal_handle->get_goal();
- input.task_type = goal_handle->get_goal()->goal.selected_task;
- input.task_subtype = goal_handle->get_goal()->goal.task_subtype;
- input.target_sensor_id = resolve_target_sensor_id(*goal_handle->get_goal());
- input.camera_intrinsic_task = goal_handle->get_goal()->goal.camera_intrinsic;
- input.imu_intrinsic_task = goal_handle->get_goal()->goal.imu_intrinsic;
- input.sensor_to_base_extrinsic_task = goal_handle->get_goal()->goal.sensor_to_base_extrinsic;
- input.hand_eye_task = goal_handle->get_goal()->goal.hand_eye;
- input.required_image_count = goal_handle->get_goal()->goal.camera_intrinsic.required_image_count;
- input.required_static_segment_count = goal_handle->get_goal()->goal.imu_intrinsic.required_static_segment_count;
- input.required_motion_segment_count = goal_handle->get_goal()->goal.imu_intrinsic.required_motion_segment_count;
- input.required_sample_count = goal_handle->get_goal()->goal.sensor_to_base_extrinsic.required_sample_count;
- input.required_pose_count = goal_handle->get_goal()->goal.hand_eye.required_pose_count;
- switch (goal_handle->get_goal()->goal.selected_task.value) {
- case TaskType::CAMERA_INTRINSIC:
- input.reference_timeout_sec = goal_handle->get_goal()->goal.camera_intrinsic.timeout_sec;
- break;
- case TaskType::IMU_INTRINSIC:
- input.reference_timeout_sec = goal_handle->get_goal()->goal.imu_intrinsic.timeout_sec;
- break;
- case TaskType::SENSOR_TO_BASE_EXTRINSIC:
- input.reference_timeout_sec = goal_handle->get_goal()->goal.sensor_to_base_extrinsic.timeout_sec;
- break;
- case TaskType::HAND_EYE:
- input.reference_timeout_sec = goal_handle->get_goal()->goal.hand_eye.timeout_sec;
- break;
- default:
- input.reference_timeout_sec = 0.0;
- break;
- }
- input.reference_board_id = goal_handle->get_goal()->goal.camera_intrinsic.target_board_id;
- input.reference_base_frame_id = goal_handle->get_goal()->goal.sensor_to_base_extrinsic.base_frame_id;
- input.reference_arm_id = goal_handle->get_goal()->goal.hand_eye.arm_id;
- input.sensor_history_available = false;
- input.chassis_history_available = false;
- input.control_history_available = false;
- input.truth_history_available = false;
-
- SensorCalibrationAlgorithmTemplate::Output output;
- std::string failure_reason;
- if (!algorithm_.run(input, output, failure_reason)) {
- auto result = std::make_shared();
- result->result.success = false;
- result->result.error_code.code = ErrorCode::INVALID_STATE;
- result->result.message = failure_reason;
- result->result.job_id = goal_handle->get_goal()->goal.header.request_id;
- result->result.data_quality_passed = false;
- result->result.suitable_for_commit = false;
- goal_handle->abort(result);
- return;
- }
-
- auto result = std::make_shared(output.response);
- goal_handle->succeed(result);
-}
-
-std::string SensorCalibrationServiceNode::resolve_target_sensor_id(const ExecuteTask::Goal & goal) const
-{
- switch (goal.goal.selected_task.value) {
- case TaskType::CAMERA_INTRINSIC:
- return goal.goal.camera_intrinsic.sensor_id;
- case TaskType::IMU_INTRINSIC:
- return goal.goal.imu_intrinsic.sensor_id;
- case TaskType::SENSOR_TO_BASE_EXTRINSIC:
- return goal.goal.sensor_to_base_extrinsic.sensor_id;
- case TaskType::HAND_EYE:
- return goal.goal.hand_eye.sensor_id;
- default:
- return "";
- }
-}
-
-} // namespace sensor_calibration_service
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_to_base_extrinsic_calibration_algorithm.cpp b/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_to_base_extrinsic_calibration_algorithm.cpp
deleted file mode 100644
index 246fec8..0000000
--- a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_to_base_extrinsic_calibration_algorithm.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "sensor_calibration_service/sensor_calibration_common.hpp"
-
-namespace sensor_calibration_service
-{
-
-bool FrontCameraExtrinsicCalibrationAlgorithm::run(
- const SensorCalibrationInput & input,
- SensorCalibrationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // 前视相机到 base_link 外参标定模板。
- fill_common_result(input, output);
- output.response.result.message = "front camera extrinsic calibration template executed.";
- output.response.result.recommended_parameter_version = "front_camera_extrinsic_template_v1";
- return true;
-}
-
-bool DownwardCameraExtrinsicCalibrationAlgorithm::run(
- const SensorCalibrationInput & input,
- SensorCalibrationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // 下视相机到 base_link 外参标定模板。
- fill_common_result(input, output);
- output.response.result.message = "downward camera extrinsic calibration template executed.";
- output.response.result.recommended_parameter_version = "downward_camera_extrinsic_template_v1";
- return true;
-}
-
-bool ImuExtrinsicCalibrationAlgorithm::run(
- const SensorCalibrationInput & input,
- SensorCalibrationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // IMU 到 base_link 外参标定模板。
- fill_common_result(input, output);
- output.response.result.message = "imu extrinsic calibration template executed.";
- output.response.result.recommended_parameter_version = "imu_extrinsic_template_v1";
- return true;
-}
-
-bool Lidar2DExtrinsicCalibrationAlgorithm::run(
- const SensorCalibrationInput & input,
- SensorCalibrationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // 2D 激光雷达到 base_link 外参标定模板。
- fill_common_result(input, output);
- output.response.result.message = "2d lidar extrinsic calibration template executed.";
- output.response.result.recommended_parameter_version = "lidar_2d_extrinsic_template_v1";
- return true;
-}
-
-bool Lidar3DExtrinsicCalibrationAlgorithm::run(
- const SensorCalibrationInput & input,
- SensorCalibrationOutput & output,
- std::string & failure_reason) const
-{
- (void)failure_reason;
-
- // 3D 激光雷达到 base_link 外参标定模板。
- fill_common_result(input, output);
- output.response.result.message = "3d lidar extrinsic calibration template executed.";
- output.response.result.recommended_parameter_version = "lidar_3d_extrinsic_template_v1";
- return true;
-}
-
-} // namespace sensor_calibration_service
diff --git a/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/src/vehicle_profile_manager_node.cpp b/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/src/vehicle_profile_manager_node.cpp
deleted file mode 100644
index 96e9f6a..0000000
--- a/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/src/vehicle_profile_manager_node.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-#include "vehicle_profile_manager/vehicle_profile_manager_node.hpp"
-
-#include
-
-#include "calibration_common_interfaces/msg/error_code.hpp"
-#include "calibration_vehicle_profile_interfaces/msg/chassis_type.hpp"
-#include "calibration_vehicle_profile_interfaces/msg/workflow_stage_type.hpp"
-#include "rclcpp_components/register_node_macro.hpp"
-
-namespace vehicle_profile_manager
-{
-
-using calibration_common_interfaces::msg::ErrorCode;
-using calibration_vehicle_profile_interfaces::msg::ChassisType;
-using calibration_vehicle_profile_interfaces::msg::WorkflowStageType;
-
-VehicleProfileManagerNode::VehicleProfileManagerNode(const rclcpp::NodeOptions & options)
-: Node("vehicle_profile_manager", options)
-{
- get_profile_service_ = create_service(
- "/vehicle_profile_manager/get_vehicle_profile",
- std::bind(
- &VehicleProfileManagerNode::handle_get_profile, this,
- std::placeholders::_1, std::placeholders::_2));
-
- register_service_ = create_service(
- "/vehicle_profile_manager/register_or_update_vehicle_profile",
- std::bind(
- &VehicleProfileManagerNode::handle_register, this,
- std::placeholders::_1, std::placeholders::_2));
-
- applicability_service_ = create_service(
- "/vehicle_profile_manager/evaluate_vehicle_calibration_applicability",
- std::bind(
- &VehicleProfileManagerNode::handle_applicability, this,
- std::placeholders::_1, std::placeholders::_2));
-
- heartbeat_service_ = create_service(
- "/vehicle_profile_manager/heartbeat",
- std::bind(
- &VehicleProfileManagerNode::handle_heartbeat, this,
- std::placeholders::_1, std::placeholders::_2));
-
- load_demo_profile();
-
- RCLCPP_INFO(get_logger(), "VehicleProfileManagerNode 启动,已预载 demo 车辆画像。");
-}
-
-void VehicleProfileManagerNode::handle_get_profile(
- const std::shared_ptr request,
- std::shared_ptr response)
-{
- const auto & vehicle_id = request->request.vehicle_id;
- auto it = profiles_.find(vehicle_id);
- if (it == profiles_.end()) {
- response->response.success = false;
- response->response.error_code.code = ErrorCode::INVALID_ARGUMENT;
- response->response.message = "找不到 vehicle_id=[" + vehicle_id + "] 的车辆画像。";
- return;
- }
- response->response.success = true;
- response->response.error_code.code = ErrorCode::OK;
- response->response.message = "查询成功。";
- response->response.profile = it->second;
-}
-
-void VehicleProfileManagerNode::handle_register(
- const std::shared_ptr request,
- std::shared_ptr response)
-{
- const auto & vehicle_id = request->request.profile.base_info.vehicle_id;
- if (vehicle_id.empty()) {
- response->response.success = false;
- response->response.error_code.code = ErrorCode::INVALID_ARGUMENT;
- response->response.message = "vehicle_id 不能为空。";
- return;
- }
- profiles_[vehicle_id] = request->request.profile;
- RCLCPP_INFO(get_logger(), "已注册/更新车辆画像 vehicle_id=[%s]", vehicle_id.c_str());
- response->response.success = true;
- response->response.error_code.code = ErrorCode::OK;
- response->response.message = "注册/更新成功。";
-}
-
-void VehicleProfileManagerNode::handle_applicability(
- const std::shared_ptr request,
- std::shared_ptr response)
-{
- const auto & profile = request->request.profile_snapshot;
- auto stages = evaluate_supported_stages(profile);
-
- response->response.success = true;
- response->response.error_code.code = ErrorCode::OK;
- response->response.message = "适用性评估完成。";
- response->response.overall_supported = !stages.empty();
- response->response.recommended_workflow_stages = stages;
-}
-
-void VehicleProfileManagerNode::handle_heartbeat(
- const std::shared_ptr /*request*/,
- std::shared_ptr response)
-{
- const auto now_us = std::chrono::duration_cast(
- std::chrono::system_clock::now().time_since_epoch()).count();
- response->response.success = true;
- response->response.error_code.code = ErrorCode::OK;
- response->response.message = "vehicle_profile_manager 在线。";
- response->response.server_timestamp_us = now_us;
- response->response.vehicle_ready = true;
-}
-
-std::vector
-VehicleProfileManagerNode::evaluate_supported_stages(const VehicleProfile & profile) const
-{
- std::vector stages;
-
- auto make_stage = [](uint8_t v) {
- WorkflowStageType s;
- s.value = v;
- return s;
- };
-
- // 预检和画像校验始终支持。
- stages.push_back(make_stage(WorkflowStageType::PROFILE_VALIDATION_STAGE));
- stages.push_back(make_stage(WorkflowStageType::WORKSHOP_PRECHECK_STAGE));
-
- // 底盘标定:底盘类型已指定时支持。
- if (profile.chassis_type.value != ChassisType::CHASSIS_TYPE_UNSPECIFIED) {
- stages.push_back(make_stage(WorkflowStageType::CHASSIS_CALIBRATION_STAGE));
- stages.push_back(make_stage(WorkflowStageType::CONTROL_CALIBRATION_STAGE));
- }
-
- // 传感器标定:有传感器配置时支持。
- if (!profile.sensors.empty()) {
- stages.push_back(make_stage(WorkflowStageType::SENSOR_INTRINSIC_CALIBRATION_STAGE));
- stages.push_back(make_stage(WorkflowStageType::SENSOR_EXTRINSIC_CALIBRATION_STAGE));
- }
-
- // 手眼标定:有机械臂且有传感器时支持。
- if (profile.arm_profile.has_mechanical_arm && !profile.sensors.empty()) {
- stages.push_back(make_stage(WorkflowStageType::HAND_EYE_CALIBRATION_STAGE));
- }
-
- // 最终阶段始终加入。
- stages.push_back(make_stage(WorkflowStageType::PARAMETER_COMMIT_STAGE));
- stages.push_back(make_stage(WorkflowStageType::REPORT_ARCHIVE_STAGE));
-
- return stages;
-}
-
-void VehicleProfileManagerNode::load_demo_profile()
-{
- VehicleProfile demo;
-
- // 基础信息
- demo.base_info.vehicle_id = "demo_agv_001";
- demo.base_info.vehicle_name = "Demo AGV";
- demo.base_info.model_name = "DemoModel-X1";
- demo.base_info.manufacturer = "Demo Manufacturer";
-
- // 底盘类型:差速
- demo.chassis_type.value = ChassisType::DIFFERENTIAL;
-
- // base_link
- demo.base_link_frame = "base_link";
-
- // 画像版本
- demo.profile_version = "demo_v1";
-
- // 启用的工作流阶段
- demo.enabled_workflow_stages = evaluate_supported_stages(demo);
-
- profiles_[demo.base_info.vehicle_id] = demo;
- RCLCPP_INFO(get_logger(), "已预载 demo 车辆画像 vehicle_id=[%s]",
- demo.base_info.vehicle_id.c_str());
-}
-
-} // namespace vehicle_profile_manager
-
-RCLCPP_COMPONENTS_REGISTER_NODE(vehicle_profile_manager::VehicleProfileManagerNode)
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/launch/workshop_orchestrator_v2.launch.py b/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/launch/workshop_orchestrator_v2.launch.py
deleted file mode 100644
index 35a8946..0000000
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/launch/workshop_orchestrator_v2.launch.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from launch import LaunchDescription
-from launch_ros.actions import Node
-
-
-def generate_launch_description():
- return LaunchDescription([
- Node(
- package="workshop_orchestrator_v2",
- executable="workshop_orchestrator_v2_node",
- name="workshop_orchestrator_v2",
- output="screen",
- )
- ])
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp b/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp
deleted file mode 100644
index e568d9b..0000000
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-#include "workshop_orchestrator_v2/precheck_runner.hpp"
-
-#include "calibration_workshop_orchestration_interfaces/msg/precheck_item.hpp"
-
-namespace workshop_orchestrator_v2
-{
-
-bool PrecheckRunner::has_metadata_key(const StagePlan & stage, const std::string & key) const
-{
- for (const auto & kv : stage.metadata) {
- if (kv.key == key) {
- return true;
- }
- }
- return false;
-}
-
-bool PrecheckRunner::has_metadata_prefix(const StagePlan & stage, const std::string & prefix) const
-{
- for (const auto & kv : stage.metadata) {
- if (kv.key.rfind(prefix, 0) == 0) {
- return true;
- }
- }
- return false;
-}
-
-WorkshopPrecheckResponse PrecheckRunner::run(const WorkshopSession & session) const
-{
- WorkshopPrecheckResponse response;
- response.success = true;
- response.error_code = make_error_code(ErrorCode::OK);
- response.checked_timestamp_us = now_us();
-
- auto append_item = [&](const std::string & code,
- const std::string & name,
- bool passed,
- const std::string & message,
- uint8_t stage_type,
- uint8_t module_type) {
- calibration_workshop_orchestration_interfaces::msg::PrecheckItem item;
- item.item_code = code;
- item.display_name = name;
- item.passed = passed;
- item.blocking = true;
- item.error_code = make_error_code(passed ? ErrorCode::OK : ErrorCode::INVALID_STATE);
- item.message = message;
- item.related_stage_type = make_stage_type(stage_type);
- item.related_module_type = make_module_type(module_type);
- response.items.push_back(item);
- if (!passed) {
- response.blocking_issue_count += 1;
- response.all_passed = false;
- }
- };
-
- response.all_passed = true;
- response.blocking_issue_count = 0;
-
- append_item(
- "plan_not_empty",
- "Execution plan exists",
- !session.stage_plan.empty(),
- session.stage_plan.empty() ? "Session has no executable stages." : "Session has executable stages.",
- WorkflowStageType::WORKFLOW_STAGE_UNSPECIFIED,
- CalibrationModuleType::CALIBRATION_MODULE_UNSPECIFIED);
-
- for (const auto & stage : session.stage_plan) {
- if (stage.module_type.value == CalibrationModuleType::CHASSIS_MODULE) {
- const bool passed =
- has_metadata_key(stage, metadata_keys::CHASSIS_PRIMITIVE_TYPE) &&
- has_metadata_key(stage, metadata_keys::CHASSIS_STRAIGHT_LINE_DISTANCE_M) &&
- has_metadata_key(stage, metadata_keys::CHASSIS_STRAIGHT_LINE_SPEED_MS);
- append_item(
- stage.stage_id + ".metadata",
- stage.display_name + " metadata",
- passed,
- passed ? "底盘阶段输入完整。" : "底盘阶段缺少 primitive_type 或直线动作参数。",
- stage.stage_type.value,
- stage.module_type.value);
- } else if (stage.module_type.value == CalibrationModuleType::CONTROL_MODULE) {
- const bool passed =
- has_metadata_key(stage, metadata_keys::CONTROL_TASK_TYPE) &&
- has_metadata_prefix(stage, metadata_keys::CONTROL_TRAJECTORY_PREFIX);
- append_item(
- stage.stage_id + ".metadata",
- stage.display_name + " metadata",
- passed,
- passed ? "运控阶段输入完整。" : "运控阶段缺少 control.task_type 或轨迹点输入。",
- stage.stage_type.value,
- stage.module_type.value);
- } else if (
- stage.module_type.value == CalibrationModuleType::SENSOR_INTRINSIC_MODULE ||
- stage.module_type.value == CalibrationModuleType::SENSOR_EXTRINSIC_MODULE ||
- stage.module_type.value == CalibrationModuleType::HAND_EYE_MODULE) {
- bool passed =
- has_metadata_key(stage, metadata_keys::SENSOR_ID) &&
- has_metadata_key(stage, metadata_keys::SENSOR_TASK_SUBTYPE);
- std::string message = passed ? "传感器阶段基础输入完整。" : "传感器阶段缺少 sensor.sensor_id 或 sensor.task_subtype。";
-
- if (passed && stage.module_type.value == CalibrationModuleType::SENSOR_INTRINSIC_MODULE) {
- const bool has_image_count = has_metadata_key(stage, metadata_keys::CAMERA_INTRINSIC_REQUIRED_IMAGE_COUNT);
- const bool has_board = has_metadata_key(stage, metadata_keys::CAMERA_INTRINSIC_TARGET_BOARD_ID);
- passed = has_image_count || has_board;
- message = passed ? "传感器内参阶段输入完整。" : "传感器内参阶段缺少图像数或标定板信息。";
- }
-
- if (passed && stage.module_type.value == CalibrationModuleType::SENSOR_EXTRINSIC_MODULE) {
- passed =
- has_metadata_key(stage, metadata_keys::SENSOR_EXTRINSIC_BASE_FRAME_ID) &&
- has_metadata_key(stage, metadata_keys::SENSOR_EXTRINSIC_REQUIRED_SAMPLE_COUNT);
- message = passed ? "传感器外参阶段输入完整。" : "传感器外参阶段缺少 base_frame_id 或 required_sample_count。";
- }
-
- if (passed && stage.module_type.value == CalibrationModuleType::HAND_EYE_MODULE) {
- passed =
- has_metadata_key(stage, metadata_keys::HAND_EYE_ARM_ID) &&
- has_metadata_key(stage, metadata_keys::HAND_EYE_REQUIRED_POSE_COUNT);
- message = passed ? "手眼阶段输入完整。" : "手眼阶段缺少 arm_id 或 required_pose_count。";
- }
-
- append_item(
- stage.stage_id + ".metadata",
- stage.display_name + " metadata",
- passed,
- message,
- stage.stage_type.value,
- stage.module_type.value);
- } else if (stage.module_type.value == CalibrationModuleType::EXTERNAL_LOCALIZATION_MODULE) {
- const bool passed =
- has_metadata_key(stage, metadata_keys::EXTERNAL_STATIC_SAMPLE_COUNT) &&
- has_metadata_key(stage, metadata_keys::EXTERNAL_DYNAMIC_SAMPLE_COUNT) &&
- has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_POSITION_STDDEV_M) &&
- has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_YAW_STDDEV_RAD) &&
- has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_TRACKING_LOSS_RATIO) &&
- has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_TIME_SYNC_OFFSET_MS) &&
- has_metadata_key(stage, metadata_keys::EXTERNAL_TIMEOUT_SEC);
- append_item(
- stage.stage_id + ".metadata",
- stage.display_name + " metadata",
- passed,
- passed ? "external 阶段输入完整。" : "external 阶段缺少真值校核阈值配置。",
- stage.stage_type.value,
- stage.module_type.value);
- }
- }
-
- response.ready_for_start = response.all_passed;
- response.message = response.ready_for_start ? "Precheck passed." : "Precheck failed.";
- return response;
-}
-
-} // namespace workshop_orchestrator_v2
diff --git a/agv_calib_brain/src/UI/README.md b/agv_calib_brain/src/apps/operator_ui/README.md
similarity index 95%
rename from agv_calib_brain/src/UI/README.md
rename to agv_calib_brain/src/apps/operator_ui/README.md
index e922f36..de21973 100644
--- a/agv_calib_brain/src/UI/README.md
+++ b/agv_calib_brain/src/apps/operator_ui/README.md
@@ -1,5 +1,4 @@
-
-# workshop_ui_pyside6_config_aligned
+# 操作员界面原型
这版 PySide6 原型的目标不是单纯展示界面,而是:
diff --git a/agv_calib_brain/src/UI/main.py b/agv_calib_brain/src/apps/operator_ui/main.py
similarity index 100%
rename from agv_calib_brain/src/UI/main.py
rename to agv_calib_brain/src/apps/operator_ui/main.py
diff --git a/agv_calib_brain/src/UI/requirements.txt b/agv_calib_brain/src/apps/operator_ui/requirements.txt
similarity index 100%
rename from agv_calib_brain/src/UI/requirements.txt
rename to agv_calib_brain/src/apps/operator_ui/requirements.txt
diff --git a/agv_calib_brain/src/UI/standalone_dashboard.py b/agv_calib_brain/src/apps/operator_ui/standalone_dashboard.py
similarity index 100%
rename from agv_calib_brain/src/UI/standalone_dashboard.py
rename to agv_calib_brain/src/apps/operator_ui/standalone_dashboard.py
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/vehicle_internal_interfaces/CMakeLists.txt
new file mode 100644
index 0000000..0af7709
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.8)
+project(vehicle_internal_interfaces)
+
+find_package(ament_cmake REQUIRED)
+find_package(rosidl_default_generators REQUIRED)
+find_package(calibration_vehicle_profile_interfaces REQUIRED)
+
+set(msg_files
+ "msg/VehicleControlMode.msg"
+ "msg/AckermannDriveCommand.msg"
+ "msg/VehicleSafetyCommand.msg"
+ "msg/AckermannActuatorState.msg"
+ "msg/VehicleInternalState.msg"
+ "msg/VehicleHealthStatus.msg"
+ "msg/VehicleTimeSyncStatus.msg"
+ "msg/SensorLinkStatus.msg"
+)
+
+rosidl_generate_interfaces(${PROJECT_NAME}
+ ${msg_files}
+ DEPENDENCIES calibration_vehicle_profile_interfaces
+)
+
+ament_export_dependencies(rosidl_default_runtime)
+ament_package()
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/README.md b/agv_calib_brain/src/communication/vehicle_internal_interfaces/README.md
new file mode 100644
index 0000000..8a3f940
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/README.md
@@ -0,0 +1,17 @@
+# 车辆内部接口
+
+这个包定义车端电脑和车辆本体之间的内部 ROS2 消息。
+
+它不直接作为车间电脑和车端电脑之间的 WiFi6 协议。WiFi6 对外协议仍由 `calibration_*_interfaces/proto` 定义。这个包用于把真实 Windows 小车的 CAN、串口、厂商 SDK 或仿真 Isaac topic 统一映射成车端内部语义。
+
+当前消息包括:
+
+- `AckermannDriveCommand`:阿克曼底盘速度、转角、制动、超时命令。
+- `VehicleSafetyCommand`:上使能、下使能、急停、清故障、标定低速模式。
+- `AckermannActuatorState`:速度、转角、轮速、电机电流、制动/油门反馈。
+- `VehicleInternalState`:车辆模式、安全状态、底盘执行器状态、电源与运动状态。
+- `VehicleHealthStatus`:控制器在线、总线状态、通信质量和车端资源状态。
+- `VehicleTimeSyncStatus`:车端、传感器、外部真值之间的时间同步状态。
+- `SensorLinkStatus`:车载传感器在线状态、帧率、丢帧和延迟。
+
+仿真中,`vehicle_agent_sim` 会把车间电脑下发的控制请求转换为 `AckermannDriveCommand`,同时继续发布 Isaac 当前需要的 `cmd_vel`。真实部署时,Windows 车端应把这些内部消息映射到实际车辆接口。
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/AckermannActuatorState.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/AckermannActuatorState.msg
new file mode 100644
index 0000000..c055ec3
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/AckermannActuatorState.msg
@@ -0,0 +1,35 @@
+# =========================================================
+# 阿克曼底盘内部执行器状态
+# 发送方:车辆控制器 / Isaac 底盘执行器适配层
+# 接收方:车端电脑
+# =========================================================
+
+# 状态时间戳
+int64 hardware_timestamp_us
+
+# 实际纵向速度
+float64 actual_speed_ms
+# 实际纵向加速度
+float64 actual_accel_ms2
+# 实际前轮等效转角
+float64 actual_steering_angle_rad
+# 实际转向角速度
+float64 actual_steering_rate_rads
+
+# 左后驱动轮速度
+float64 rear_left_wheel_speed_ms
+# 右后驱动轮速度
+float64 rear_right_wheel_speed_ms
+# 左前轮等效转角
+float64 front_left_steering_angle_rad
+# 右前轮等效转角
+float64 front_right_steering_angle_rad
+
+# 驱动电机电流
+float64 drive_motor_current_amp
+# 转向电机电流
+float64 steering_motor_current_amp
+# 制动压力或制动比例,范围 [0, 1]
+float64 brake_pressure
+# 驱动控制输出,范围 [0, 1]
+float64 throttle_output
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/AckermannDriveCommand.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/AckermannDriveCommand.msg
new file mode 100644
index 0000000..4043f27
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/AckermannDriveCommand.msg
@@ -0,0 +1,33 @@
+# =========================================================
+# 阿克曼底盘内部控制命令
+# 发送方:车端电脑
+# 接收方:车辆运动控制器 / Isaac 底盘执行器适配层
+# =========================================================
+
+# 命令时间戳
+int64 command_timestamp_us
+# 命令 ID,用于追踪和去重
+string command_id
+# 命令来源,例如 vehicle_agent_sim / real_vehicle_agent
+string source
+# 控制模式
+vehicle_internal_interfaces/VehicleControlMode control_mode
+
+# 目标纵向速度
+float64 target_speed_ms
+# 目标纵向加速度;0 表示由车辆控制器默认限幅
+float64 target_accel_ms2
+# 目标前轮等效转角,左正右负
+float64 target_steering_angle_rad
+# 目标转向角速度;0 表示由车辆控制器默认限幅
+float64 target_steering_rate_rads
+
+# 制动命令,范围 [0, 1]
+float64 brake_command
+# 油门 / 驱动命令,范围 [0, 1];仿真可选
+float64 throttle_command
+# 命令超时时间
+float64 command_timeout_sec
+
+# 是否要求控制器在超时或任务结束后停车
+bool stop_when_timeout
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/SensorLinkStatus.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/SensorLinkStatus.msg
new file mode 100644
index 0000000..9b66414
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/SensorLinkStatus.msg
@@ -0,0 +1,33 @@
+# =========================================================
+# 车端传感器链路状态
+# 发送方:车端传感器代理
+# 接收方:车端电脑 / 车间电脑桥接层
+# =========================================================
+
+# 状态时间戳
+int64 hardware_timestamp_us
+
+# 传感器 ID
+string sensor_id
+# 传感器类型
+calibration_vehicle_profile_interfaces/SensorType sensor_type
+# 传感器 frame
+string frame_id
+# 车端订阅或驱动 topic / 通道名
+string source_channel
+
+# 是否在线
+bool online
+# 当前帧率
+float64 frame_rate_hz
+# 最近一帧年龄
+float64 latest_frame_age_ms
+# 累计帧数
+uint64 frame_count
+# 丢帧比例
+float64 dropped_frame_ratio
+# 最近一帧传输延迟
+float64 latest_transport_latency_ms
+
+# 当前链路状态说明
+string status_message
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleControlMode.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleControlMode.msg
new file mode 100644
index 0000000..edb284f
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleControlMode.msg
@@ -0,0 +1,15 @@
+# =========================================================
+# 车辆内部控制模式
+# 作用:车端电脑与车辆控制器之间约定当前车辆控制状态
+# =========================================================
+
+uint8 MODE_UNSPECIFIED=0
+uint8 DISABLED=1
+uint8 MANUAL=2
+uint8 AUTO=3
+uint8 CALIBRATION=4
+uint8 ESTOP=5
+uint8 FAULT=6
+
+# 当前模式
+uint8 value
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleHealthStatus.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleHealthStatus.msg
new file mode 100644
index 0000000..3e081dd
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleHealthStatus.msg
@@ -0,0 +1,40 @@
+# =========================================================
+# 车辆内部健康诊断状态
+# 发送方:车端电脑 / 车辆控制器
+# 接收方:车端电脑内部监控或车间电脑桥接层
+# =========================================================
+
+# 状态时间戳
+int64 hardware_timestamp_us
+
+# 车端电脑进程是否在线
+bool vehicle_agent_online
+# 车辆主控制器是否在线
+bool vehicle_controller_online
+# 驱动控制器是否在线
+bool drive_controller_online
+# 转向控制器是否在线
+bool steering_controller_online
+# 传感器总线是否在线
+bool sensor_bus_online
+# CAN 或厂商控制链路是否在线
+bool vehicle_bus_online
+# 外部真值链路是否在线
+bool external_truth_link_online
+
+# 通信质量
+float64 vehicle_bus_rx_hz
+float64 vehicle_bus_drop_ratio
+float64 command_latency_ms
+float64 telemetry_latency_ms
+
+# 车端电脑资源
+float64 cpu_load_ratio
+float64 memory_used_ratio
+float64 disk_used_ratio
+float64 temperature_c
+
+# 诊断摘要
+bool healthy
+string diagnostic_code
+string diagnostic_message
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleInternalState.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleInternalState.msg
new file mode 100644
index 0000000..6d71723
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleInternalState.msg
@@ -0,0 +1,35 @@
+# =========================================================
+# 车辆内部综合状态
+# 发送方:车辆控制器 / Isaac 底盘执行器适配层
+# 接收方:车端电脑
+# =========================================================
+
+# 状态时间戳
+int64 hardware_timestamp_us
+# 当前控制模式
+vehicle_internal_interfaces/VehicleControlMode current_mode
+
+# 车辆是否已上使能
+bool vehicle_enabled
+# 急停是否触发
+bool estop_engaged
+# 是否处于低速标定模式
+bool calibration_low_speed_mode
+# 是否存在故障
+bool fault_active
+# 主故障码
+string primary_fault_code
+# 主故障说明
+string primary_fault_message
+
+# 当前底盘状态
+vehicle_internal_interfaces/AckermannActuatorState ackermann_state
+
+# 电源状态
+float64 battery_voltage_v
+float64 battery_current_amp
+float64 battery_soc
+
+# 车辆运动状态
+float64 yaw_rate_rads
+float64 lateral_accel_ms2
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleSafetyCommand.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleSafetyCommand.msg
new file mode 100644
index 0000000..c92d5e2
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleSafetyCommand.msg
@@ -0,0 +1,30 @@
+# =========================================================
+# 车辆内部安全命令
+# 发送方:车端电脑
+# 接收方:车辆安全控制器 / 底盘控制器
+# =========================================================
+
+# 命令时间戳
+int64 command_timestamp_us
+# 命令 ID
+string command_id
+# 命令来源
+string source
+
+# 上使能车辆
+bool enable_vehicle
+# 下使能车辆
+bool disable_vehicle
+# 触发急停
+bool engage_estop
+# 解除急停
+bool release_estop
+# 清除可恢复故障
+bool clear_faults
+# 切换到标定低速安全模式
+bool enter_calibration_low_speed_mode
+# 退出标定低速安全模式
+bool exit_calibration_low_speed_mode
+
+# 操作原因
+string reason
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleTimeSyncStatus.msg b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleTimeSyncStatus.msg
new file mode 100644
index 0000000..075ebac
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/msg/VehicleTimeSyncStatus.msg
@@ -0,0 +1,27 @@
+# =========================================================
+# 车辆内部时间同步状态
+# 发送方:车端电脑
+# 接收方:车间电脑桥接层 / 车端诊断
+# =========================================================
+
+# 状态时间戳
+int64 hardware_timestamp_us
+
+# 同步源,例如 ptp / ntp / external_truth / sim_clock
+string sync_source
+# 是否认为已同步
+bool synchronized
+
+# 车端系统时钟相对传感器硬件时钟偏差
+float64 system_to_sensor_offset_ms
+# 车端系统时钟相对外部真值时钟偏差
+float64 system_to_external_truth_offset_ms
+# 同步抖动
+float64 jitter_ms
+# 近期最大时间同步误差
+float64 max_offset_ms
+# 时间同步链路延迟
+float64 sync_transport_latency_ms
+
+# 说明
+string status_message
diff --git a/agv_calib_brain/src/communication/vehicle_internal_interfaces/package.xml b/agv_calib_brain/src/communication/vehicle_internal_interfaces/package.xml
new file mode 100644
index 0000000..b73288b
--- /dev/null
+++ b/agv_calib_brain/src/communication/vehicle_internal_interfaces/package.xml
@@ -0,0 +1,21 @@
+
+
+ vehicle_internal_interfaces
+ 0.0.1
+ ROS 2 interfaces for vehicle-computer to vehicle-controller internal communication.
+
+ user
+ Proprietary
+
+ ament_cmake
+ rosidl_default_generators
+
+ calibration_vehicle_profile_interfaces
+
+ rosidl_default_runtime
+
+ rosidl_interface_packages
+
+ ament_cmake
+
+
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/FILE_TREE.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/FILE_TREE.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/FILE_TREE.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/FILE_TREE.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/action/ExecuteMotionPrimitive.action b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/action/ExecuteMotionPrimitive.action
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/action/ExecuteMotionPrimitive.action
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/action/ExecuteMotionPrimitive.action
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AckermannCalibrationParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AckermannCalibrationParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AckermannCalibrationParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AckermannCalibrationParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AppliedChassisCalibrationParametersResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AppliedChassisCalibrationParametersResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AppliedChassisCalibrationParametersResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/AppliedChassisCalibrationParametersResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ArcCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ArcCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ArcCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ArcCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCalibrationParameterSet.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCalibrationParameterSet.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCalibrationParameterSet.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCalibrationParameterSet.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisCapabilityResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisJobResult.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisJobResult.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisJobResult.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisJobResult.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisMotionPrimitiveType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisMotionPrimitiveType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisMotionPrimitiveType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisMotionPrimitiveType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisReadinessResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisReadinessResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisReadinessResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisReadinessResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisSpecificParamsType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisSpecificParamsType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisSpecificParamsType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisSpecificParamsType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisTelemetry.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisTelemetry.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisTelemetry.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisTelemetry.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisValidationSummary.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisValidationSummary.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisValidationSummary.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisValidationSummary.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkMode.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkMode.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkMode.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkMode.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkModeRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkModeRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkModeRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ChassisWorkModeRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommitChassisCalibrationParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommitChassisCalibrationParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommitChassisCalibrationParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommitChassisCalibrationParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommonChassisCalibrationParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommonChassisCalibrationParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommonChassisCalibrationParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CommonChassisCalibrationParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CoordinatedSteeringCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CoordinatedSteeringCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CoordinatedSteeringCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/CoordinatedSteeringCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DiagonalMotionCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DiagonalMotionCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DiagonalMotionCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DiagonalMotionCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DifferentialCalibrationParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DifferentialCalibrationParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DifferentialCalibrationParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/DifferentialCalibrationParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/GetAppliedChassisCalibrationParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/GetAppliedChassisCalibrationParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/GetAppliedChassisCalibrationParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/GetAppliedChassisCalibrationParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/InPlaceRotationCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/InPlaceRotationCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/InPlaceRotationCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/InPlaceRotationCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/LateralTranslationCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/LateralTranslationCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/LateralTranslationCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/LateralTranslationCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ModuleAlignmentCheckCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ModuleAlignmentCheckCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ModuleAlignmentCheckCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/ModuleAlignmentCheckCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveTaskPurpose.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveTaskPurpose.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveTaskPurpose.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MotionPrimitiveTaskPurpose.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MultiSteerWheelCalibrationParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MultiSteerWheelCalibrationParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MultiSteerWheelCalibrationParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/MultiSteerWheelCalibrationParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SingleSteerWheelCalibrationParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SingleSteerWheelCalibrationParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SingleSteerWheelCalibrationParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SingleSteerWheelCalibrationParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringModuleCalibrationParam.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringModuleCalibrationParam.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringModuleCalibrationParam.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringModuleCalibrationParam.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringSweepCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringSweepCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringSweepCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/SteeringSweepCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StraightLineCommand.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StraightLineCommand.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StraightLineCommand.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StraightLineCommand.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StreamChassisTelemetryRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StreamChassisTelemetryRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StreamChassisTelemetryRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/StreamChassisTelemetryRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/WheelModuleState.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/WheelModuleState.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/msg/WheelModuleState.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/msg/WheelModuleState.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/proto/chassis_calibration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/proto/chassis_calibration.proto
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/proto/chassis_calibration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/proto/chassis_calibration.proto
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CancelChassisJob.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CancelChassisJob.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CancelChassisJob.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CancelChassisJob.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CommitChassisCalibrationParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CommitChassisCalibrationParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CommitChassisCalibrationParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/CommitChassisCalibrationParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/EmergencyBrake.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/EmergencyBrake.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/EmergencyBrake.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/EmergencyBrake.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetAppliedChassisCalibrationParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetAppliedChassisCalibrationParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetAppliedChassisCalibrationParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetAppliedChassisCalibrationParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisCapability.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisCapability.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisCapability.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisCapability.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobStatus.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobStatus.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobStatus.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisJobStatus.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisReadiness.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisReadiness.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisReadiness.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/GetChassisReadiness.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/Heartbeat.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/Heartbeat.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/Heartbeat.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/Heartbeat.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/SetChassisWorkMode.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/SetChassisWorkMode.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/SetChassisWorkMode.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/SetChassisWorkMode.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StartMotionPrimitive.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StartMotionPrimitive.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StartMotionPrimitive.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StartMotionPrimitive.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StreamChassisTelemetry.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StreamChassisTelemetry.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StreamChassisTelemetry.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_chassis_interfaces/srv/StreamChassisTelemetry.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/action/MonitorJob.action b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/action/MonitorJob.action
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/action/MonitorJob.action
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/action/MonitorJob.action
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/AgentReadinessRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/AgentReadinessRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/AgentReadinessRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/AgentReadinessRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/ErrorCode.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/ErrorCode.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/ErrorCode.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/ErrorCode.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/FileDigest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/FileDigest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/FileDigest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/FileDigest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/FileReference.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/FileReference.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/FileReference.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/FileReference.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/HeartbeatResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobAccepted.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobAccepted.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobAccepted.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobAccepted.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobQuery.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobQuery.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobQuery.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobQuery.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobState.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobState.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobState.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobState.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobStatus.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobStatus.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/JobStatus.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/JobStatus.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/KeyValuePair.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/KeyValuePair.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/KeyValuePair.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/KeyValuePair.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/Pose3D.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/Pose3D.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/Pose3D.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/Pose3D.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/ReadinessIssue.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/ReadinessIssue.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/ReadinessIssue.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/ReadinessIssue.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/RequestHeader.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/RequestHeader.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/RequestHeader.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/RequestHeader.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/StandardResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/StandardResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/StandardResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/StandardResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/Vector3D.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/Vector3D.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/msg/Vector3D.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/msg/Vector3D.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/proto/calibration_common.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/proto/calibration_common.proto
similarity index 99%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/proto/calibration_common.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/proto/calibration_common.proto
index 4d44308..0013f90 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/proto/calibration_common.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/proto/calibration_common.proto
@@ -3,8 +3,8 @@ syntax = "proto3";
package agv.calibration.common;
// ├── msg/
-// │ ├── Vector3d.msg
-// │ ├── Pose3dEuler.msg
+// │ ├── Vector3D.msg
+// │ ├── Pose3D.msg
// │ ├── RequestHeader.msg
// │ ├── ErrorCode.msg
// │ ├── StandardResponse.msg
@@ -263,4 +263,4 @@ message FileReference {
message KeyValuePair {
string key = 1; // 键
string value = 2; // 值
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/proto/transport_contract.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/proto/transport_contract.proto
new file mode 100644
index 0000000..8cb6376
--- /dev/null
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/proto/transport_contract.proto
@@ -0,0 +1,146 @@
+syntax = "proto3";
+
+package agv.calibration.transport;
+
+// =========================================================
+// 文件作用:WiFi6/TCP 传输契约
+// 使用范围:
+// 1) Ubuntu 车间工控机与 Windows 车端代理之间的网络边界
+// 2) 仿真车端 agent 与真实车端 agent 需要共同遵守的帧号和通道约定
+// 3) 业务消息仍由 chassis/control/sensor/external_localization proto 定义
+// 说明:
+// 1) WiFi6 是承载网络,当前工程传输层使用 TCP 长/短连接
+// 2) 当前仿真实现 payload 使用 proto 字段名风格的 JSON
+// 3) 现场可切换为 protobuf binary,但必须保持本文件中的通道和帧号不变
+// =========================================================
+
+// =========================================================
+// WiFi6 逻辑通道
+// =========================================================
+enum Wifi6Channel {
+ WIFI6_CHANNEL_UNSPECIFIED = 0;
+ WIFI6_CHANNEL_CHASSIS = 1; // 底盘标定动作和急停
+ WIFI6_CHANNEL_CONTROL = 2; // 运控参数评估、轨迹跟踪
+ WIFI6_CHANNEL_SENSOR = 3; // 车端传感器原始数据
+ WIFI6_CHANNEL_EXTERNAL_POSE = 4; // 外部真值位姿输入到车端
+}
+
+// =========================================================
+// 默认端口
+// 说明:
+// 1) WiFi6 边界默认只暴露一个车端 gateway 端口
+// 2) channel 只是协议里的逻辑通道,不应该被理解成“一类功能一个物理端口”
+// 3) 9001-9004 仅保留给仿真 router 背后的内部域服务或旧版兼容使用
+// =========================================================
+enum Wifi6DefaultPort {
+ WIFI6_DEFAULT_PORT_UNSPECIFIED = 0;
+ WIFI6_DEFAULT_PORT_VEHICLE_GATEWAY = 9000;
+ WIFI6_LEGACY_INTERNAL_PORT_CHASSIS = 9001;
+ WIFI6_LEGACY_INTERNAL_PORT_CONTROL = 9002;
+ WIFI6_LEGACY_INTERNAL_PORT_SENSOR = 9003;
+ WIFI6_LEGACY_INTERNAL_PORT_EXTERNAL_POSE = 9004;
+}
+
+// =========================================================
+// TCP 载荷编码方式
+// =========================================================
+enum Wifi6PayloadEncoding {
+ WIFI6_PAYLOAD_ENCODING_UNSPECIFIED = 0;
+ WIFI6_PAYLOAD_ENCODING_JSON_PROTO_FIELD_NAMES = 1; // 当前仿真实现:JSON key 使用 proto 字段名
+ WIFI6_PAYLOAD_ENCODING_PROTOBUF_BINARY = 2; // 现场高性能实现可选
+}
+
+// =========================================================
+// TCP 连接方向
+// =========================================================
+enum Wifi6FrameDirection {
+ WIFI6_FRAME_DIRECTION_UNSPECIFIED = 0;
+ WIFI6_FRAME_DIRECTION_WORKSHOP_TO_VEHICLE = 1;
+ WIFI6_FRAME_DIRECTION_VEHICLE_TO_WORKSHOP = 2;
+}
+
+// =========================================================
+// TCP 帧号
+// 帧头格式固定为:
+// uint32 little-endian msg_type
+// uint32 little-endian payload_len
+// payload_len bytes payload
+// 注意:
+// 1) 这个 8 字节帧头不是 protobuf 序列化结果,而是传输层二进制头
+// 2) payload 的业务结构由本字段注释中对应的 proto 消息定义
+// 3) 逻辑 channel 由 msg_type 映射得到;同一个 gateway 端口根据 msg_type 做路由
+// =========================================================
+enum Wifi6FrameType {
+ WIFI6_FRAME_TYPE_UNSPECIFIED = 0;
+
+ // 底盘域:chassis_calibration.proto / AgvCalibChassisService
+ WIFI6_FRAME_CHASSIS_GET_READINESS_REQ = 1; // AgentReadinessRequest
+ WIFI6_FRAME_CHASSIS_GET_READINESS_RSP = 2; // ChassisReadinessResponse
+ WIFI6_FRAME_CHASSIS_MOTION_PRIMITIVE_REQ = 3; // MotionPrimitiveRequest
+ WIFI6_FRAME_CHASSIS_MOTION_PRIMITIVE_RSP = 4; // ChassisJobResult
+ WIFI6_FRAME_CHASSIS_EMERGENCY_BRAKE_REQ = 5; // Empty 或 EmergencyBrake 请求
+ WIFI6_FRAME_CHASSIS_EMERGENCY_BRAKE_RSP = 6; // StandardResponse
+
+ // 运控域:control_calibration.proto / AgvCalibControlService
+ WIFI6_FRAME_CONTROL_GET_READINESS_REQ = 11; // AgentReadinessRequest
+ WIFI6_FRAME_CONTROL_GET_READINESS_RSP = 12; // ControlReadinessResponse
+ WIFI6_FRAME_CONTROL_EVALUATION_REQ = 13; // ControllerEvaluationRequest
+ WIFI6_FRAME_CONTROL_EVALUATION_RSP = 14; // ControlJobResult
+
+ // 传感器域:sensor_calibration.proto / AgvCalibSensorService
+ WIFI6_FRAME_SENSOR_GET_READINESS_REQ = 21; // AgentReadinessRequest
+ WIFI6_FRAME_SENSOR_GET_READINESS_RSP = 22; // SensorReadinessResponse
+ WIFI6_FRAME_SENSOR_GET_LATEST_FRAME_REQ = 23; // StreamVehicleSensorDataRequest 的轻量轮询形态
+ WIFI6_FRAME_SENSOR_GET_LATEST_FRAME_RSP = 24; // VehicleSensorFrame
+ WIFI6_FRAME_SENSOR_LIST_SENSORS_REQ = 25; // Empty 或能力查询请求
+ WIFI6_FRAME_SENSOR_LIST_SENSORS_RSP = 26; // Sensor 列表响应
+
+ // 外部真值位姿域:external_localization.proto / AgvCalibExternalPoseFeedService
+ WIFI6_FRAME_EXTERNAL_POSE_PUSH_REQ = 31; // ExternalLocalizationTelemetry
+ WIFI6_FRAME_EXTERNAL_POSE_PUSH_RSP = 32; // StandardResponse
+}
+
+// =========================================================
+// TCP 帧头的 protobuf 表达
+// 说明:
+// 1) 这个 message 仅用于文档、测试、代码生成时表达契约
+// 2) 实际线上帧头仍是上面注释中定义的 8 字节小端二进制结构
+// =========================================================
+message Wifi6TcpFrameHeader {
+ Wifi6FrameType msg_type = 1; // 对应 8 字节帧头中的 uint32 msg_type
+ uint32 payload_len = 2; // 对应 8 字节帧头中的 uint32 payload_len
+}
+
+// =========================================================
+// 逻辑通道端点
+// =========================================================
+message Wifi6ChannelEndpoint {
+ Wifi6Channel channel = 1;
+ Wifi6DefaultPort default_port = 2;
+ Wifi6FrameDirection request_direction = 3;
+ string canonical_proto_file = 4; // 例如 chassis_calibration.proto
+ string canonical_service = 5; // 例如 AgvCalibChassisService
+}
+
+// =========================================================
+// 请求 / 响应帧映射
+// =========================================================
+message Wifi6FrameMapping {
+ Wifi6Channel channel = 1;
+ Wifi6FrameType request_type = 2;
+ Wifi6FrameType response_type = 3;
+ Wifi6PayloadEncoding payload_encoding = 4;
+ string request_message = 5; // proto 消息名
+ string response_message = 6; // proto 消息名
+ string rpc_name = 7; // 对齐的 RPC 名称;轻量轮询可为空
+}
+
+// =========================================================
+// 当前工程默认契约版本
+// =========================================================
+message Wifi6TransportContract {
+ string contract_version = 1; // 当前为 "wifi6_tcp_v1"
+ Wifi6PayloadEncoding default_payload_encoding = 2;
+ repeated Wifi6ChannelEndpoint endpoints = 3;
+ repeated Wifi6FrameMapping frame_mappings = 4;
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/srv/GetAgentReadiness.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/srv/GetAgentReadiness.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/srv/GetAgentReadiness.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/srv/GetAgentReadiness.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/srv/Heartbeat.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/srv/Heartbeat.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/srv/Heartbeat.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/srv/Heartbeat.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/srv/QueryJobStatus.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/srv/QueryJobStatus.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_common_interfaces/srv/QueryJobStatus.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_common_interfaces/srv/QueryJobStatus.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/FILE_TREE.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/FILE_TREE.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/FILE_TREE.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/FILE_TREE.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/action/ExecuteControllerEvaluation.action b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/action/ExecuteControllerEvaluation.action
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/action/ExecuteControllerEvaluation.action
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/action/ExecuteControllerEvaluation.action
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/AccelerationDecelerationTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/AccelerationDecelerationTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/AccelerationDecelerationTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/AccelerationDecelerationTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ActiveControllerParametersResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ActiveControllerParametersResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ActiveControllerParametersResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ActiveControllerParametersResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/CommitControllerParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/CommitControllerParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/CommitControllerParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/CommitControllerParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlJobResult.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlJobResult.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlJobResult.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlJobResult.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlReadinessResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlReadinessResponse.msg
similarity index 68%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlReadinessResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlReadinessResponse.msg
index 87dfd3c..60ad539 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlReadinessResponse.msg
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlReadinessResponse.msg
@@ -26,3 +26,14 @@ bool vehicle_safe_to_move
calibration_common_interfaces/ReadinessIssue[] issues
# 检查时间
int64 checked_timestamp_us
+
+# 外部真值 / 定位位姿输入是否就绪
+bool external_pose_feedback_ready
+# 当前外部位姿源名称
+string external_pose_source_name
+# 最近一帧外部位姿年龄
+float64 external_pose_age_ms
+# 最近一帧外部位姿质量分数
+float64 external_pose_quality_score
+# 外部位姿传输方式,例如 wifi6
+string external_pose_transport
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlTelemetry.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlTelemetry.msg
similarity index 87%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlTelemetry.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlTelemetry.msg
index cbc74ee..fe477c2 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlTelemetry.msg
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlTelemetry.msg
@@ -43,3 +43,8 @@ string parameter_version
calibration_vehicle_profile_interfaces/ControllerAlgorithmType active_lateral_algorithm
# 当前纵向算法
calibration_vehicle_profile_interfaces/ControllerAlgorithmType active_longitudinal_algorithm
+
+# 本帧控制使用的位姿源名称
+string pose_source_name
+# 本帧位姿是否来自外部真值 / 外部定位
+bool pose_from_external_truth
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlValidationSummary.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlValidationSummary.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlValidationSummary.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlValidationSummary.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkMode.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkMode.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkMode.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkMode.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkModeRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkModeRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkModeRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControlWorkModeRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskPurpose.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskPurpose.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskPurpose.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskPurpose.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerEvaluationTaskType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterKind.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterKind.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterKind.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterKind.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterPack.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterPack.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterPack.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterPack.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterSet.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterSet.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterSet.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/ControllerParameterSet.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/GetActiveControllerParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/GetActiveControllerParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/GetActiveControllerParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/GetActiveControllerParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/InjectControllerParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/InjectControllerParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/InjectControllerParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/InjectControllerParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/LQRParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/LQRParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/LQRParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/LQRParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/LateralMPCParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/LateralMPCParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/LateralMPCParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/LateralMPCParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/LongitudinalMPCParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/LongitudinalMPCParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/LongitudinalMPCParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/LongitudinalMPCParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/PIDParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/PIDParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/PIDParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/PIDParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/PurePursuitParams.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/PurePursuitParams.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/PurePursuitParams.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/PurePursuitParams.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/StopAccuracyTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/StopAccuracyTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/StopAccuracyTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/StopAccuracyTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/StreamControlTelemetryRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/StreamControlTelemetryRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/StreamControlTelemetryRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/StreamControlTelemetryRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/TrajectoryPoint.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/TrajectoryPoint.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/TrajectoryPoint.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/TrajectoryPoint.msg
diff --git a/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/TrajectoryTrackingTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/TrajectoryTrackingTask.msg
new file mode 100644
index 0000000..353ff30
--- /dev/null
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/TrajectoryTrackingTask.msg
@@ -0,0 +1,25 @@
+# =========================================================
+# 轨迹跟踪评估任务
+# 作用:让车端按当前控制参数跑一条测试轨迹
+# =========================================================
+
+# 轨迹点序列
+calibration_control_interfaces/TrajectoryPoint[] path
+# 结束后是否停车
+bool stop_at_end
+# 超时时间
+float64 timeout_sec
+# 要求使用的外部位姿源 ID
+string required_external_pose_source_id
+# 允许最大外部位姿延迟,0 表示使用车端默认值
+float64 max_external_pose_age_ms
+# 允许最小外部位姿质量分数,0 表示使用车端默认值
+float64 min_external_pose_quality_score
+# 轨迹 ID,用于分段下发时关联多段轨迹
+string trajectory_id
+# 当前轨迹段序号,从 0 开始
+uint32 segment_index
+# 总段数;0 或 1 表示本请求携带完整轨迹
+uint32 total_segments
+# 当前段是否为最后一段,作为 total_segments 的冗余校验
+bool is_final_segment
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/VelocityStepTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/VelocityStepTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/msg/VelocityStepTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/msg/VelocityStepTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/control_calibration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/proto/control_calibration.proto
similarity index 93%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/control_calibration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/proto/control_calibration.proto
index 61a04c4..307e21b 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/control_calibration.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/proto/control_calibration.proto
@@ -115,6 +115,12 @@ message ControlReadinessResponse {
bool vehicle_safe_to_move = 9; // 当前车辆是否允许移动
repeated .agv.calibration.common.ReadinessIssue issues = 10; // 不满足项
int64 checked_timestamp_us = 11; // 检查时间
+
+ bool external_pose_feedback_ready = 12; // 外部真值 / 定位位姿输入是否就绪
+ string external_pose_source_name = 13; // 当前外部位姿源名称
+ double external_pose_age_ms = 14; // 最近一帧外部位姿年龄
+ double external_pose_quality_score = 15; // 最近一帧外部位姿质量分数
+ string external_pose_transport = 16; // 外部位姿传输方式,例如 wifi6
}
// =========================================================
@@ -249,6 +255,13 @@ message TrajectoryTrackingTask {
repeated TrajectoryPoint path = 1; // 轨迹点序列
bool stop_at_end = 2; // 结束后是否停车
double timeout_sec = 3; // 超时时间
+ string required_external_pose_source_id = 4; // 要求使用的外部位姿源 ID
+ double max_external_pose_age_ms = 5; // 允许最大外部位姿延迟
+ double min_external_pose_quality_score = 6; // 允许最小外部位姿质量分数
+ string trajectory_id = 7; // 轨迹 ID,用于分段下发时关联多段轨迹
+ uint32 segment_index = 8; // 当前轨迹段序号,从 0 开始
+ uint32 total_segments = 9; // 总段数;0 或 1 表示本请求携带完整轨迹
+ bool is_final_segment = 10; // 当前段是否为最后一段,作为 total_segments 的冗余校验
}
// =========================================================
@@ -353,6 +366,9 @@ message ControlTelemetry {
string parameter_version = 15; // 当前生效参数版本
.agv.calibration.vehicle.profile.ControllerAlgorithmType active_lateral_algorithm = 16; // 当前横向算法
.agv.calibration.vehicle.profile.ControllerAlgorithmType active_longitudinal_algorithm = 17; // 当前纵向算法
+
+ string pose_source_name = 18; // 本帧控制使用的位姿源名称
+ bool pose_from_external_truth = 19; // 本帧位姿是否来自外部真值 / 外部定位
}
// =========================================================
@@ -420,4 +436,4 @@ message ControlJobResult {
ControlValidationSummary validation_summary = 8; // 验证摘要
ControllerParameterSet estimated_parameter_set = 9; // 本轮估计参数集
repeated .agv.calibration.common.FileReference artifacts = 10; // 关联产物
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/CancelControlJob.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/CancelControlJob.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/CancelControlJob.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/CancelControlJob.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/CommitControllerParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/CommitControllerParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/CommitControllerParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/CommitControllerParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/EmergencyStop.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/EmergencyStop.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/EmergencyStop.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/EmergencyStop.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetActiveControllerParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetActiveControllerParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetActiveControllerParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetActiveControllerParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobStatus.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobStatus.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobStatus.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlJobStatus.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlReadiness.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlReadiness.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlReadiness.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/GetControlReadiness.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/Heartbeat.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/Heartbeat.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/Heartbeat.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/Heartbeat.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/InjectControllerParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/InjectControllerParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/InjectControllerParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/InjectControllerParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/SetControlWorkMode.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/SetControlWorkMode.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/SetControlWorkMode.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/SetControlWorkMode.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/StartControllerEvaluation.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/StartControllerEvaluation.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/StartControllerEvaluation.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/StartControllerEvaluation.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/StreamControlTelemetry.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/StreamControlTelemetry.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/srv/StreamControlTelemetry.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_control_interfaces/srv/StreamControlTelemetry.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/FILE_TREE.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/FILE_TREE.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/FILE_TREE.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/FILE_TREE.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/action/ExecuteExternalLocalizationTask.action b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/action/ExecuteExternalLocalizationTask.action
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/action/ExecuteExternalLocalizationTask.action
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/action/ExecuteExternalLocalizationTask.action
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/AppliedExternalLocalizationResultResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/AppliedExternalLocalizationResultResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/AppliedExternalLocalizationResultResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/AppliedExternalLocalizationResultResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/CommitExternalLocalizationResultRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/CommitExternalLocalizationResultRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/CommitExternalLocalizationResultRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/CommitExternalLocalizationResultRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCalibrationResult.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCalibrationResult.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCalibrationResult.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCalibrationResult.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationCapabilityResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationJobResult.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationJobResult.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationJobResult.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationJobResult.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationReadinessResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationReadinessResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationReadinessResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationReadinessResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPayloadType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPayloadType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPayloadType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPayloadType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPurpose.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPurpose.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPurpose.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskPurpose.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTaskRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTelemetry.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTelemetry.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTelemetry.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationTelemetry.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationValidationSummary.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationValidationSummary.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationValidationSummary.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationValidationSummary.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkMode.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkMode.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkMode.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkMode.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkModeRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkModeRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkModeRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ExternalLocalizationWorkModeRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/GetAppliedExternalLocalizationResultRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/GetAppliedExternalLocalizationResultRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/GetAppliedExternalLocalizationResultRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/GetAppliedExternalLocalizationResultRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/MarkerAlignmentTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/MarkerAlignmentTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/MarkerAlignmentTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/MarkerAlignmentTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ReferencePoseCollectionTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ReferencePoseCollectionTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ReferencePoseCollectionTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/ReferencePoseCollectionTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/StreamExternalLocalizationTelemetryRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/StreamExternalLocalizationTelemetryRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/StreamExternalLocalizationTelemetryRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/StreamExternalLocalizationTelemetryRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/TruthSourceValidationTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/TruthSourceValidationTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/TruthSourceValidationTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/msg/TruthSourceValidationTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/external_localization.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/proto/external_localization.proto
similarity index 87%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/external_localization.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/proto/external_localization.proto
index 35749b7..069bb81 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/external_localization.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/proto/external_localization.proto
@@ -69,6 +69,30 @@ service AgvCalibExternalLocalizationService {
returns (.agv.calibration.common.StandardResponse);
}
+// =========================================================
+// 服务:外部真值位姿下发服务
+// 运行位置:Ubuntu 车间电脑 / 外部真值系统桥接进程
+// 调用方:Windows 车端代理
+// 传输介质:现场通过 WiFi 6 网络承载
+// 作用:
+// 1) 让车端在执行轨迹跟踪时获得车间坐标系下的实时位姿
+// 2) 与 StreamExternalLocalizationTelemetry 使用同一位姿消息结构
+// 3) 车端不得把底盘里程计当成默认全局位姿源,只可作为降级输入
+// =========================================================
+service AgvCalibExternalPoseFeedService {
+ // 心跳保活,用于车端确认外部真值链路在线
+ rpc Heartbeat(.agv.calibration.common.HeartbeatRequest)
+ returns (.agv.calibration.common.HeartbeatResponse);
+
+ // 车端订阅外部真值位姿流
+ rpc StreamExternalPoseToVehicle(ExternalPoseFeedRequest)
+ returns (stream ExternalLocalizationTelemetry);
+
+ // 可选:外部真值系统主动推送单帧位姿到车端
+ rpc PushExternalPoseToVehicle(ExternalLocalizationTelemetry)
+ returns (.agv.calibration.common.StandardResponse);
+}
+
// =========================================================
// 外部定位工作模式请求
// 作用:切换外部定位桥接服务到不同模式
@@ -238,6 +262,20 @@ message StreamExternalLocalizationTelemetryRequest {
bool include_tracking_state = 6; // 是否包含跟踪状态
}
+// =========================================================
+// 外部真值位姿下发请求
+// 作用:车端通过 WiFi 6 请求工控机 / 外部真值桥接进程提供实时位姿流
+// =========================================================
+message ExternalPoseFeedRequest {
+ .agv.calibration.common.RequestHeader header = 1; // 请求头
+ string vehicle_id = 2; // 目标车辆 ID
+ string localization_source_id = 3; // 外部真值源 ID
+ string workcell_zone_id = 4; // 工位 / 区域 ID
+ uint32 expected_hz = 5; // 期望下发频率
+ double max_pose_age_ms = 6; // 允许最大位姿延迟
+ bool require_quality_metrics = 7; // 是否要求质量指标
+}
+
// =========================================================
// 外部定位遥测
// 作用:回传外部定位实时观测结果
@@ -248,7 +286,7 @@ message ExternalLocalizationTelemetry {
int64 hardware_timestamp_us = 1; // 硬件时间戳
bool pose_valid = 2; // 位姿是否有效
- .agv.calibration.common.Pose3dEuler workshop_pose = 3; // 在车间参考系下的位姿
+ .agv.calibration.common.Pose3D workshop_pose = 3; // 在车间参考系下的位姿
double position_stddev_m = 4; // 位置标准差
double yaw_stddev_rad = 5; // 航向标准差
@@ -269,7 +307,7 @@ message ExternalLocalizationCalibrationResult {
string workshop_frame_id = 1; // 车间参考坐标系 ID
string localization_frame_id = 2; // 外部定位坐标系 ID
- .agv.calibration.common.Pose3dEuler workshop_to_localization = 3; // 车间系到定位系的位姿
+ .agv.calibration.common.Pose3D workshop_to_localization = 3; // 车间系到定位系的位姿
double position_repeatability_m = 4; // 位置重复性
double yaw_repeatability_rad = 5; // 航向重复性
@@ -334,4 +372,4 @@ message ExternalLocalizationJobResult {
ExternalLocalizationValidationSummary validation_summary = 9; // 真值参考验证摘要
ExternalLocalizationCalibrationResult result = 10; // 结果内容
repeated .agv.calibration.common.FileReference artifacts = 11; // 关联产物
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CancelExternalLocalizationJob.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CancelExternalLocalizationJob.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CancelExternalLocalizationJob.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CancelExternalLocalizationJob.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CommitExternalLocalizationResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CommitExternalLocalizationResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CommitExternalLocalizationResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/CommitExternalLocalizationResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/EmergencyStop.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/EmergencyStop.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/EmergencyStop.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/EmergencyStop.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetAppliedExternalLocalizationResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetAppliedExternalLocalizationResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetAppliedExternalLocalizationResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetAppliedExternalLocalizationResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationCapability.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationCapability.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationCapability.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationCapability.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobStatus.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobStatus.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobStatus.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationJobStatus.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationReadiness.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationReadiness.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationReadiness.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/GetExternalLocalizationReadiness.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/Heartbeat.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/Heartbeat.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/Heartbeat.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/Heartbeat.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/SetExternalLocalizationWorkMode.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/SetExternalLocalizationWorkMode.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/SetExternalLocalizationWorkMode.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/SetExternalLocalizationWorkMode.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StartExternalLocalizationTask.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StartExternalLocalizationTask.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StartExternalLocalizationTask.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StartExternalLocalizationTask.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StreamExternalLocalizationTelemetry.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StreamExternalLocalizationTelemetry.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StreamExternalLocalizationTelemetry.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_external_localization_interfaces/srv/StreamExternalLocalizationTelemetry.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/FILE_TREE.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/FILE_TREE.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/FILE_TREE.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/FILE_TREE.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/action/ExecuteSensorCalibrationTask.action b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/action/ExecuteSensorCalibrationTask.action
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/action/ExecuteSensorCalibrationTask.action
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/action/ExecuteSensorCalibrationTask.action
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/AppliedSensorCalibrationParametersResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/AppliedSensorCalibrationParametersResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/AppliedSensorCalibrationParametersResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/AppliedSensorCalibrationParametersResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/ArtifactType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/ArtifactType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/ArtifactType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/ArtifactType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationArtifact.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationArtifact.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationArtifact.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationArtifact.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationReferenceTarget.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationReferenceTarget.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationReferenceTarget.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CalibrationReferenceTarget.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsicCalibrationTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsicCalibrationTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsicCalibrationTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsicCalibrationTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsics.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsics.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsics.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraIntrinsics.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraModelType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraModelType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraModelType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CameraModelType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CaptureIntentType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CaptureIntentType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CaptureIntentType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CaptureIntentType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CommitSensorCalibrationParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CommitSensorCalibrationParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CommitSensorCalibrationParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/CommitSensorCalibrationParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/GetAppliedSensorCalibrationParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/GetAppliedSensorCalibrationParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/GetAppliedSensorCalibrationParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/GetAppliedSensorCalibrationParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationMode.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationMode.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationMode.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationMode.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/HandEyeCalibrationTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsicCalibrationTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsicCalibrationTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsicCalibrationTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsicCalibrationTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsics.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsics.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsics.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/IMUIntrinsics.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationCapabilityResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationJobResult.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationJobResult.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationJobResult.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationJobResult.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameter.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameter.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameter.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameter.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameterSet.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameterSet.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameterSet.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationParameterSet.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskPurpose.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskPurpose.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskPurpose.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskPurpose.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskSubtype.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskSubtype.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskSubtype.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskSubtype.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTaskType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTelemetry.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTelemetry.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTelemetry.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationTelemetry.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkMode.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkMode.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkMode.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkMode.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkModeRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkModeRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkModeRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorCalibrationWorkModeRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorExtrinsics.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorExtrinsics.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorExtrinsics.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorExtrinsics.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorReadinessResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorReadinessResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorReadinessResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorReadinessResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorToBaseExtrinsicCalibrationTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorToBaseExtrinsicCalibrationTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorToBaseExtrinsicCalibrationTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorToBaseExtrinsicCalibrationTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorValidationSummary.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorValidationSummary.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorValidationSummary.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/SensorValidationSummary.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/StreamSensorCalibrationTelemetryRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/StreamSensorCalibrationTelemetryRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/msg/StreamSensorCalibrationTelemetryRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/msg/StreamSensorCalibrationTelemetryRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/sensor_calibration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/proto/sensor_calibration.proto
similarity index 70%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/sensor_calibration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/proto/sensor_calibration.proto
index 38d0096..a121b55 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/sensor_calibration.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/proto/sensor_calibration.proto
@@ -11,7 +11,7 @@ import "vehicle_profile.proto";
// Ubuntu 车间电脑(Linux) -> Windows 车端代理 / 采集服务
// 说明:
// 1) Linux 负责图像 / 点云 / 激光扫描 / IMU 数据分析与参数求解
-// 2) 车端 / 采集服务只负责组织采集、回传观测状态、写入结果
+// 2) 车端 / 采集服务负责订阅车端传感器、组织采集、回传原始数据和观测状态、写入结果
// 3) 支持相机内参、IMU 内参、传感器外参、手眼标定
// 4) 支持相机“只做内参 / 只做外参 / 内外参都做”
// =========================================================
@@ -58,6 +58,10 @@ service AgvCalibSensorService {
rpc StreamSensorCalibrationTelemetry(StreamSensorCalibrationTelemetryRequest)
returns (stream SensorCalibrationTelemetry);
+ // 打开车端传感器原始数据流;用于 WiFi6 把车载相机、雷达、IMU 数据传给车间电脑
+ rpc StreamVehicleSensorData(StreamVehicleSensorDataRequest)
+ returns (stream VehicleSensorFrame);
+
// 写入传感器标定参数
rpc CommitSensorCalibrationParameters(CommitSensorCalibrationParametersRequest)
returns (.agv.calibration.common.StandardResponse);
@@ -71,6 +75,22 @@ service AgvCalibSensorService {
returns (.agv.calibration.common.StandardResponse);
}
+// =========================================================
+// 服务:车间电脑传感器数据接收服务
+// 运行位置:Ubuntu 车间电脑
+// 调用方:Windows 车端代理 / 仿真车端代理
+// 说明:
+// 1) 当现场网络策略采用车端主动上报时使用
+// 2) 与 StreamVehicleSensorData 使用同一帧结构
+// =========================================================
+service AgvCalibWorkshopSensorIngestService {
+ rpc Heartbeat(.agv.calibration.common.HeartbeatRequest)
+ returns (.agv.calibration.common.HeartbeatResponse);
+
+ rpc PushVehicleSensorFrame(VehicleSensorFrame)
+ returns (.agv.calibration.common.StandardResponse);
+}
+
// =========================================================
// 传感器标定工作模式
// 作用:切换采集服务到不同模式
@@ -109,6 +129,10 @@ message SensorReadinessResponse {
repeated string ready_sensor_ids = 10; // 已就绪的传感器 ID
repeated .agv.calibration.common.ReadinessIssue issues = 11; // 不满足项
int64 checked_timestamp_us = 12; // 检查时间
+
+ bool sensor_data_stream_ready = 13; // 车端原始传感器数据流是否就绪
+ repeated string streaming_sensor_ids = 14; // 当前可被转发到车间电脑的传感器 ID
+ string sensor_data_transport = 15; // 传输方式,例如 wifi6 / wifi6_sim_tcp
}
// =========================================================
@@ -137,6 +161,9 @@ message SensorCalibrationCapabilityResponse {
bool supports_2d_lidar_extrinsic = 9; // 是否支持 2D 激光雷达外参
bool supports_camera_only_intrinsic = 10; // 是否支持仅做相机内参
bool supports_camera_only_extrinsic = 11; // 是否支持仅做相机外参
+ bool supports_vehicle_sensor_data_stream = 12; // 是否支持车端原始传感器数据流
+ bool supports_sensor_frame_chunking = 13; // 是否支持大帧分片传输
+ bool supports_compressed_image_stream = 14; // 是否支持压缩图像流
}
// =========================================================
@@ -238,8 +265,8 @@ enum SensorCalibrationTaskSubtype {
IMU_EXTRINSIC = 6;
LIDAR_2D_EXTRINSIC = 7;
LIDAR_3D_EXTRINSIC = 8;
- EYE_IN_HAND = 9;
- EYE_TO_HAND = 10;
+ HAND_EYE_IN_HAND = 9;
+ HAND_EYE_TO_HAND = 10;
}
// =========================================================
@@ -300,6 +327,161 @@ message SensorCalibrationTelemetry {
CaptureIntentType capture_intent = 9; // 当前采集意图
}
+// =========================================================
+// 车端传感器原始数据流请求
+// 作用:车间电脑指定要接收哪些车端传感器数据
+// =========================================================
+message StreamVehicleSensorDataRequest {
+ .agv.calibration.common.RequestHeader header = 1; // 请求头
+ repeated string sensor_ids = 2; // 要接收的传感器 ID;为空表示由任务决定
+ repeated .agv.calibration.vehicle.profile.SensorType sensor_types = 3; // 要接收的传感器类型
+ uint32 expected_hz = 4; // 期望上报频率,0 表示车端默认
+ uint32 max_frame_payload_bytes = 5; // 单个分片最大 payload,0 表示车端默认
+ bool allow_compressed = 6; // 是否允许压缩图像 / 点云
+ bool include_camera_info = 7; // 是否随图像携带相机内参初值
+ CaptureIntentType capture_intent = 8; // 数据采集意图
+ string active_job_id = 9; // 关联的标定任务 ID
+}
+
+// =========================================================
+// 传感器原始帧负载类型
+// =========================================================
+enum SensorFramePayloadType {
+ SENSOR_FRAME_PAYLOAD_TYPE_UNSPECIFIED = 0;
+ IMAGE_FRAME = 1; // 相机图像
+ POINT_CLOUD_FRAME = 2; // 3D 激光雷达点云
+ LASER_SCAN_FRAME = 3; // 2D 激光雷达扫描
+ IMU_FRAME = 4; // IMU 数据
+ CAMERA_INFO_FRAME = 5; // 相机内参 / camera_info
+ RAW_BYTES_FRAME = 6; // 预留给厂商私有二进制格式
+}
+
+// =========================================================
+// 传感器原始帧公共头
+// =========================================================
+message VehicleSensorFrameHeader {
+ string sensor_id = 1; // 传感器 ID,例如 demo_front_camera
+ .agv.calibration.vehicle.profile.SensorType sensor_type = 2; // 传感器类型
+ string frame_id = 3; // ROS / 车端坐标系 frame_id
+ int64 hardware_timestamp_us = 4; // 硬件时间戳
+ uint64 sequence_id = 5; // 单传感器递增帧号
+ string active_job_id = 6; // 关联任务 ID
+ CaptureIntentType capture_intent = 7; // 采集意图
+}
+
+// =========================================================
+// 图像帧
+// 对齐 ROS sensor_msgs/Image 的核心字段
+// =========================================================
+message VehicleImageFrame {
+ uint32 width = 1; // 图像宽度
+ uint32 height = 2; // 图像高度
+ string encoding = 3; // 例如 rgb8 / bgr8 / mono8 / jpeg / png
+ bool is_bigendian = 4; // 字节序
+ uint32 step = 5; // 每行字节数
+ bytes data = 6; // 图像数据或分片数据
+ string compression = 7; // none / jpeg / png
+ CameraIntrinsics camera_intrinsics_hint = 8; // 可选内参初值或当前参数
+}
+
+// =========================================================
+// PointCloud2 字段描述
+// =========================================================
+enum PointCloudFieldDataType {
+ POINT_CLOUD_FIELD_DATA_TYPE_UNSPECIFIED = 0;
+ POINT_CLOUD_FIELD_INT8 = 1;
+ POINT_CLOUD_FIELD_UINT8 = 2;
+ POINT_CLOUD_FIELD_INT16 = 3;
+ POINT_CLOUD_FIELD_UINT16 = 4;
+ POINT_CLOUD_FIELD_INT32 = 5;
+ POINT_CLOUD_FIELD_UINT32 = 6;
+ POINT_CLOUD_FIELD_FLOAT32 = 7;
+ POINT_CLOUD_FIELD_FLOAT64 = 8;
+}
+
+message PointCloudField {
+ string name = 1; // 字段名,例如 x / y / z / intensity
+ uint32 offset = 2; // 字节偏移
+ PointCloudFieldDataType datatype = 3; // 数据类型
+ uint32 count = 4; // 元素数量
+}
+
+// =========================================================
+// 3D 点云帧
+// 对齐 ROS sensor_msgs/PointCloud2 的核心字段
+// =========================================================
+message VehiclePointCloudFrame {
+ uint32 height = 1;
+ uint32 width = 2;
+ repeated PointCloudField fields = 3;
+ bool is_bigendian = 4;
+ uint32 point_step = 5;
+ uint32 row_step = 6;
+ bytes data = 7; // 点云数据或分片数据
+ bool is_dense = 8;
+ string compression = 9; // none / zstd / lz4 / vendor
+}
+
+// =========================================================
+// 2D 激光雷达扫描帧
+// 对齐 ROS sensor_msgs/LaserScan 的核心字段
+// =========================================================
+message VehicleLaserScanFrame {
+ double angle_min_rad = 1;
+ double angle_max_rad = 2;
+ double angle_increment_rad = 3;
+ double time_increment_sec = 4;
+ double scan_time_sec = 5;
+ double range_min_m = 6;
+ double range_max_m = 7;
+ repeated float ranges_m = 8;
+ repeated float intensities = 9;
+}
+
+// =========================================================
+// IMU 帧
+// 对齐 ROS sensor_msgs/Imu 的核心字段
+// =========================================================
+message VehicleImuFrame {
+ double orientation_x = 1;
+ double orientation_y = 2;
+ double orientation_z = 3;
+ double orientation_w = 4;
+ repeated double orientation_covariance = 5;
+ .agv.calibration.common.Vector3D angular_velocity = 6;
+ repeated double angular_velocity_covariance = 7;
+ .agv.calibration.common.Vector3D linear_acceleration = 8;
+ repeated double linear_acceleration_covariance = 9;
+}
+
+// =========================================================
+// 车端传感器原始帧
+// 作用:通过 WiFi6 在车端和车间电脑之间传输相机 / 雷达 / IMU 数据
+// 说明:
+// 1) fragment_index / total_fragments 用于大图像或点云分片
+// 2) total_fragments 为 0 或 1 表示本消息携带完整帧
+// 3) oneof 中的数据字段可携带完整数据,也可携带当前分片数据
+// =========================================================
+message VehicleSensorFrame {
+ VehicleSensorFrameHeader header = 1; // 公共帧头
+ SensorFramePayloadType payload_type = 2; // 负载类型
+ string stream_id = 3; // 数据流 ID
+ uint32 fragment_index = 4; // 当前分片序号,从 0 开始
+ uint32 total_fragments = 5; // 总分片数;0 或 1 表示完整帧
+ bool is_final_fragment = 6; // 当前是否最后一个分片
+ uint32 uncompressed_size_bytes = 7; // 解压后总大小,用于校验
+ string payload_digest = 8; // 完整帧摘要,例如 sha256:...
+
+ oneof payload {
+ VehicleImageFrame image = 20;
+ VehiclePointCloudFrame point_cloud = 21;
+ VehicleLaserScanFrame laser_scan = 22;
+ VehicleImuFrame imu = 23;
+ CameraIntrinsics camera_info = 24;
+ bytes raw_payload = 25;
+ }
+}
+
// =========================================================
// 相机模型类型
// 作用:表达相机内参使用的模型
@@ -335,8 +517,8 @@ message CameraIntrinsics {
// 3) 采用强约束三维向量,不再使用 repeated double
// =========================================================
message IMUIntrinsics {
- .agv.calibration.common.Vector3d accel_bias = 1; // 加速度计偏置
- .agv.calibration.common.Vector3d gyro_bias = 2; // 陀螺仪偏置
+ .agv.calibration.common.Vector3D accel_bias = 1; // 加速度计偏置
+ .agv.calibration.common.Vector3D gyro_bias = 2; // 陀螺仪偏置
}
// =========================================================
@@ -347,7 +529,7 @@ message IMUIntrinsics {
message SensorExtrinsics {
string parent_frame_id = 1; // 父坐标系,一般为 base_link
string child_frame_id = 2; // 子坐标系,一般为 sensor frame
- .agv.calibration.common.Pose3dEuler parent_to_child = 3; // 父到子的位姿
+ .agv.calibration.common.Pose3D parent_to_child = 3; // 父到子的位姿
}
// =========================================================
@@ -461,4 +643,4 @@ message SensorCalibrationJobResult {
SensorValidationSummary validation_summary = 8; // 验证摘要
SensorCalibrationParameterSet estimated_params = 9; // 本轮估计参数
repeated CalibrationArtifact artifacts = 10; // 关联产物
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CancelSensorCalibrationJob.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CancelSensorCalibrationJob.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CancelSensorCalibrationJob.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CancelSensorCalibrationJob.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CommitSensorCalibrationParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CommitSensorCalibrationParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CommitSensorCalibrationParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/CommitSensorCalibrationParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/EmergencyStop.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/EmergencyStop.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/EmergencyStop.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/EmergencyStop.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetAppliedSensorCalibrationParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetAppliedSensorCalibrationParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetAppliedSensorCalibrationParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetAppliedSensorCalibrationParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationCapability.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationCapability.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationCapability.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationCapability.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobStatus.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobStatus.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobStatus.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorCalibrationJobStatus.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorReadiness.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorReadiness.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorReadiness.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/GetSensorReadiness.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/Heartbeat.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/Heartbeat.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/Heartbeat.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/Heartbeat.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/SetSensorCalibrationWorkMode.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/SetSensorCalibrationWorkMode.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/SetSensorCalibrationWorkMode.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/SetSensorCalibrationWorkMode.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StartSensorCalibrationTask.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StartSensorCalibrationTask.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StartSensorCalibrationTask.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StartSensorCalibrationTask.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StreamSensorCalibrationTelemetry.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StreamSensorCalibrationTelemetry.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StreamSensorCalibrationTelemetry.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_sensor_interfaces/srv/StreamSensorCalibrationTelemetry.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/FILE_TREE.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/FILE_TREE.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/FILE_TREE.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/FILE_TREE.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ApplicabilityIssue.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ApplicabilityIssue.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ApplicabilityIssue.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ApplicabilityIssue.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationAbilityType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationAbilityType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationAbilityType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationAbilityType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationCapability.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationCapability.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationCapability.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationCapability.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationModuleType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationModuleType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationModuleType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CalibrationModuleType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CameraMountType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CameraMountType.msg
similarity index 97%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CameraMountType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CameraMountType.msg
index fdf7125..c8cfd45 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CameraMountType.msg
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/CameraMountType.msg
@@ -11,4 +11,4 @@ uint8 EYE_IN_HAND=4 # 眼在手上
uint8 EYE_TO_HAND=5 # 眼在手外
# 当前枚举取值
-uint8 value
\ No newline at end of file
+uint8 value
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ChassisType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ChassisType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ChassisType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ChassisType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControlAxisType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControlAxisType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControlAxisType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControlAxisType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerAlgorithmType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerAlgorithmType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerAlgorithmType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerAlgorithmType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerProfile.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerProfile.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerProfile.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerProfile.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerSelection.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerSelection.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerSelection.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/ControllerSelection.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/EvaluateVehicleCalibrationApplicabilityRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/EvaluateVehicleCalibrationApplicabilityRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/EvaluateVehicleCalibrationApplicabilityRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/EvaluateVehicleCalibrationApplicabilityRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/MechanicalArmProfile.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/MechanicalArmProfile.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/MechanicalArmProfile.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/MechanicalArmProfile.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/RegisterOrUpdateVehicleProfileRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/RegisterOrUpdateVehicleProfileRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/RegisterOrUpdateVehicleProfileRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/RegisterOrUpdateVehicleProfileRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorProfile.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorProfile.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorProfile.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorProfile.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorType.msg
similarity index 97%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorType.msg
index 22ad7d9..b8d08aa 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorType.msg
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/SensorType.msg
@@ -12,4 +12,4 @@ uint8 LIDAR_2D=5 # 2D 激光雷达
uint8 IMU=6 # IMU
# 当前枚举取值
-uint8 value
\ No newline at end of file
+uint8 value
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleBaseInfo.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleBaseInfo.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleBaseInfo.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleBaseInfo.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleCalibrationApplicabilityResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleCalibrationApplicabilityResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleCalibrationApplicabilityResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleCalibrationApplicabilityResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfile.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfile.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfile.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfile.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileQuery.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileQuery.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileQuery.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileQuery.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/VehicleProfileResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/WorkflowStageType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/WorkflowStageType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/WorkflowStageType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/msg/WorkflowStageType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/vehicle_profile.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/proto/vehicle_profile.proto
similarity index 99%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/vehicle_profile.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/proto/vehicle_profile.proto
index 678fccd..a396702 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/vehicle_profile.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/proto/vehicle_profile.proto
@@ -352,4 +352,4 @@ message VehicleCalibrationApplicabilityResponse {
repeated ApplicabilityIssue issues = 5; // 问题列表
bool overall_supported = 6; // 是否总体可开展标定
repeated WorkflowStageType recommended_workflow_stages = 7; // 推荐执行阶段
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/EvaluateVehicleCalibrationApplicability.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/EvaluateVehicleCalibrationApplicability.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/EvaluateVehicleCalibrationApplicability.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/EvaluateVehicleCalibrationApplicability.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/GetVehicleProfile.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/GetVehicleProfile.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/GetVehicleProfile.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/GetVehicleProfile.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/Heartbeat.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/Heartbeat.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/Heartbeat.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/Heartbeat.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/RegisterOrUpdateVehicleProfile.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/RegisterOrUpdateVehicleProfile.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/RegisterOrUpdateVehicleProfile.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/srv/RegisterOrUpdateVehicleProfile.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/FILE_TREE.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/FILE_TREE.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/FILE_TREE.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/FILE_TREE.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/ExecuteWorkshopSession.action b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/ExecuteWorkshopSession.action
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/ExecuteWorkshopSession.action
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/ExecuteWorkshopSession.action
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/RunWorkshopPrecheck.action b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/RunWorkshopPrecheck.action
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/RunWorkshopPrecheck.action
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/action/RunWorkshopPrecheck.action
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApprovalState.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApprovalState.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApprovalState.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApprovalState.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApproveStageResultRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApproveStageResultRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApproveStageResultRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ApproveStageResultRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/BuildExecutionPlanResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CancelWorkshopSessionRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CancelWorkshopSessionRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CancelWorkshopSessionRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CancelWorkshopSessionRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/CreateWorkshopSessionResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ExecutionPlanValidationIssue.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ExecutionPlanValidationIssue.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ExecutionPlanValidationIssue.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ExecutionPlanValidationIssue.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualActionType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualActionType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualActionType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualActionType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualStepAckRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualStepAckRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualStepAckRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ManualStepAckRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PauseWorkshopSessionRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PauseWorkshopSessionRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PauseWorkshopSessionRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PauseWorkshopSessionRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PrecheckItem.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PrecheckItem.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PrecheckItem.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/PrecheckItem.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RebuildExecutionPlanRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RebuildExecutionPlanRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RebuildExecutionPlanRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RebuildExecutionPlanRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RequestedCalibrationTask.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RequestedCalibrationTask.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RequestedCalibrationTask.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RequestedCalibrationTask.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ResumeWorkshopSessionRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ResumeWorkshopSessionRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ResumeWorkshopSessionRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ResumeWorkshopSessionRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RollbackStageParametersRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RollbackStageParametersRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RollbackStageParametersRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RollbackStageParametersRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RunWorkshopPrecheckRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RunWorkshopPrecheckRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RunWorkshopPrecheckRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/RunWorkshopPrecheckRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageExecutionPolicy.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageExecutionPolicy.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageExecutionPolicy.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageExecutionPolicy.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StagePlan.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StagePlan.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StagePlan.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StagePlan.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageResultSummary.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageResultSummary.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageResultSummary.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StageResultSummary.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StartWorkshopSessionRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StartWorkshopSessionRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StartWorkshopSessionRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/StartWorkshopSessionRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanRequest.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanRequest.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanRequest.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanRequest.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/ValidateExecutionPlanResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEvent.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEvent.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEvent.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEvent.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEventType.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEventType.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEventType.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopEventType.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopOperatorInfo.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopOperatorInfo.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopOperatorInfo.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopOperatorInfo.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopPrecheckResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopPrecheckResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopPrecheckResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopPrecheckResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReport.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReport.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReport.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReport.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReportResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReportResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReportResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopReportResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSession.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSession.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSession.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSession.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionConfig.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionConfig.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionConfig.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionConfig.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionQuery.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionQuery.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionQuery.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionQuery.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionResponse.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionResponse.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionResponse.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionResponse.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionState.msg b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionState.msg
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionState.msg
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/msg/WorkshopSessionState.msg
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/proto/workshop_orchestration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/proto/workshop_orchestration.proto
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/proto/workshop_orchestration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/proto/workshop_orchestration.proto
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/AcknowledgeManualStep.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/AcknowledgeManualStep.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/AcknowledgeManualStep.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/AcknowledgeManualStep.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ApproveStageResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ApproveStageResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ApproveStageResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ApproveStageResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/BuildExecutionPlan.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/BuildExecutionPlan.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/BuildExecutionPlan.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/BuildExecutionPlan.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CancelWorkshopSession.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CancelWorkshopSession.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CancelWorkshopSession.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CancelWorkshopSession.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CreateWorkshopSession.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CreateWorkshopSession.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CreateWorkshopSession.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/CreateWorkshopSession.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetLastWorkshopPrecheckResult.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetLastWorkshopPrecheckResult.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetLastWorkshopPrecheckResult.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetLastWorkshopPrecheckResult.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopJobStatus.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopJobStatus.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopJobStatus.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopJobStatus.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopReport.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopReport.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopReport.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopReport.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopSession.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopSession.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopSession.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/GetWorkshopSession.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/Heartbeat.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/Heartbeat.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/Heartbeat.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/Heartbeat.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/PauseWorkshopSession.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/PauseWorkshopSession.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/PauseWorkshopSession.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/PauseWorkshopSession.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RebuildExecutionPlan.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RebuildExecutionPlan.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RebuildExecutionPlan.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RebuildExecutionPlan.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ResumeWorkshopSession.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ResumeWorkshopSession.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ResumeWorkshopSession.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ResumeWorkshopSession.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RollbackStageParameters.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RollbackStageParameters.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RollbackStageParameters.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RollbackStageParameters.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RunWorkshopPrecheck.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RunWorkshopPrecheck.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RunWorkshopPrecheck.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/RunWorkshopPrecheck.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StartWorkshopSession.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StartWorkshopSession.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StartWorkshopSession.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StartWorkshopSession.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StreamWorkshopEvent.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StreamWorkshopEvent.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StreamWorkshopEvent.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/StreamWorkshopEvent.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ValidateExecutionPlan.srv b/agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ValidateExecutionPlan.srv
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ValidateExecutionPlan.srv
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/calibration_workshop_orchestration_interfaces/srv/ValidateExecutionPlan.srv
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/chassis_bridge_node.hpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/chassis_bridge_node.hpp
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/chassis_bridge_node.hpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/chassis_bridge_node.hpp
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/control_bridge_node.hpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/control_bridge_node.hpp
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/control_bridge_node.hpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/control_bridge_node.hpp
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/gateway_codec.hpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/gateway_codec.hpp
similarity index 94%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/gateway_codec.hpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/gateway_codec.hpp
index 7d9feb1..64e438a 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/gateway_codec.hpp
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/gateway_codec.hpp
@@ -281,7 +281,14 @@ inline std::string encode_controller_evaluation_request(
j["trajectory_tracking"] = {
{"path", path_arr},
{"stop_at_end", req.trajectory_tracking.stop_at_end},
- {"timeout_sec", req.trajectory_tracking.timeout_sec}
+ {"timeout_sec", req.trajectory_tracking.timeout_sec},
+ {"required_external_pose_source_id", req.trajectory_tracking.required_external_pose_source_id},
+ {"max_external_pose_age_ms", req.trajectory_tracking.max_external_pose_age_ms},
+ {"min_external_pose_quality_score", req.trajectory_tracking.min_external_pose_quality_score},
+ {"trajectory_id", req.trajectory_tracking.trajectory_id},
+ {"segment_index", req.trajectory_tracking.segment_index},
+ {"total_segments", req.trajectory_tracking.total_segments},
+ {"is_final_segment", req.trajectory_tracking.is_final_segment}
};
break;
}
@@ -334,6 +341,11 @@ inline void decode_control_readiness_response(
rsp.estop_released = j.value("estop_released", false);
rsp.vehicle_safe_to_move = j.value("vehicle_safe_to_move", false);
rsp.checked_timestamp_us = j.value("checked_timestamp_us", int64_t{0});
+ rsp.external_pose_feedback_ready = j.value("external_pose_feedback_ready", false);
+ rsp.external_pose_source_name = j.value("external_pose_source_name", std::string{});
+ rsp.external_pose_age_ms = j.value("external_pose_age_ms", 0.0);
+ rsp.external_pose_quality_score = j.value("external_pose_quality_score", 0.0);
+ rsp.external_pose_transport = j.value("external_pose_transport", std::string{});
if (j.contains("error_code")) {
decode_error_code(j["error_code"], rsp.error_code);
}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/proto_frame.hpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/proto_frame.hpp
similarity index 70%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/proto_frame.hpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/proto_frame.hpp
index d2c20d0..d9acc4b 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/proto_frame.hpp
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/proto_frame.hpp
@@ -7,6 +7,7 @@ namespace vehicle_agent_gateway
{
// 消息帧类型枚举
+// 必须与 proto/transport_contract.proto 中的 Wifi6FrameType 保持一致。
// 帧格式:[4字节LE: msg_type][4字节LE: payload_len][payload_len字节: payload]
enum class MsgType : uint32_t
{
@@ -23,6 +24,18 @@ enum class MsgType : uint32_t
CONTROL_GET_READINESS_RSP = 12,
CONTROL_EVALUATION_REQ = 13,
CONTROL_EVALUATION_RSP = 14,
+
+ // 传感器域
+ SENSOR_GET_READINESS_REQ = 21,
+ SENSOR_GET_READINESS_RSP = 22,
+ SENSOR_GET_LATEST_FRAME_REQ = 23,
+ SENSOR_GET_LATEST_FRAME_RSP = 24,
+ SENSOR_LIST_SENSORS_REQ = 25,
+ SENSOR_LIST_SENSORS_RSP = 26,
+
+ // 外部真值位姿域:车间工控机/真值系统通过 WiFi6 推给车端
+ EXTERNAL_POSE_PUSH_REQ = 31,
+ EXTERNAL_POSE_PUSH_RSP = 32,
};
// 向 fd 发送一帧。payload 可以为空(长度字段写 0)。
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/tcp_client.hpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/tcp_client.hpp
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/tcp_client.hpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/include/vehicle_agent_gateway/tcp_client.hpp
diff --git a/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/launch/vehicle_agent_gateway.launch.py b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/launch/vehicle_agent_gateway.launch.py
new file mode 100644
index 0000000..b9cadd6
--- /dev/null
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/launch/vehicle_agent_gateway.launch.py
@@ -0,0 +1,30 @@
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+from launch_ros.parameter_descriptions import ParameterValue
+
+
+def generate_launch_description():
+ return LaunchDescription([
+ DeclareLaunchArgument("chassis_host", default_value="192.168.1.100"),
+ DeclareLaunchArgument("chassis_port", default_value="9000"),
+ DeclareLaunchArgument("chassis_timeout_ms", default_value="5000"),
+ DeclareLaunchArgument("control_host", default_value="192.168.1.100"),
+ DeclareLaunchArgument("control_port", default_value="9000"),
+ DeclareLaunchArgument("control_timeout_ms", default_value="5000"),
+ Node(
+ package="vehicle_agent_gateway",
+ executable="vehicle_agent_gateway_node",
+ name="vehicle_agent_gateway",
+ output="screen",
+ parameters=[{
+ "chassis_host": LaunchConfiguration("chassis_host"),
+ "chassis_port": ParameterValue(LaunchConfiguration("chassis_port"), value_type=int),
+ "chassis_timeout_ms": ParameterValue(LaunchConfiguration("chassis_timeout_ms"), value_type=int),
+ "control_host": LaunchConfiguration("control_host"),
+ "control_port": ParameterValue(LaunchConfiguration("control_port"), value_type=int),
+ "control_timeout_ms": ParameterValue(LaunchConfiguration("control_timeout_ms"), value_type=int),
+ }],
+ ),
+ ])
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/scripts/windows_stub_server.py b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/scripts/windows_stub_server.py
similarity index 59%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/scripts/windows_stub_server.py
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/scripts/windows_stub_server.py
index c29db14..99458a6 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/scripts/windows_stub_server.py
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/scripts/windows_stub_server.py
@@ -5,6 +5,8 @@
# 默认监听:
# 9001 端口 —— 底盘域
# 9002 端口 —— 运控域
+# 9003 端口 —— 传感器域
+# 9004 端口 —— 外部真值位姿输入
import json
import socket
@@ -15,7 +17,7 @@ import logging
logging.basicConfig(level=logging.INFO, format="[%(threadName)s] %(message)s")
-# 帧类型(与 proto_frame.hpp 保持一致)
+# 帧类型(与 proto_frame.hpp 和 proto/transport_contract.proto 保持一致)
CHASSIS_GET_READINESS_REQ = 1
CHASSIS_GET_READINESS_RSP = 2
CHASSIS_MOTION_PRIMITIVE_REQ = 3
@@ -26,6 +28,14 @@ CONTROL_GET_READINESS_REQ = 11
CONTROL_GET_READINESS_RSP = 12
CONTROL_EVALUATION_REQ = 13
CONTROL_EVALUATION_RSP = 14
+SENSOR_GET_READINESS_REQ = 21
+SENSOR_GET_READINESS_RSP = 22
+SENSOR_GET_LATEST_FRAME_REQ = 23
+SENSOR_GET_LATEST_FRAME_RSP = 24
+SENSOR_LIST_SENSORS_REQ = 25
+SENSOR_LIST_SENSORS_RSP = 26
+EXTERNAL_POSE_PUSH_REQ = 31
+EXTERNAL_POSE_PUSH_RSP = 32
# REQ → RSP 类型映射
REQ_TO_RSP = {
@@ -34,6 +44,10 @@ REQ_TO_RSP = {
CHASSIS_EMERGENCY_BRAKE_REQ: CHASSIS_EMERGENCY_BRAKE_RSP,
CONTROL_GET_READINESS_REQ: CONTROL_GET_READINESS_RSP,
CONTROL_EVALUATION_REQ: CONTROL_EVALUATION_RSP,
+ SENSOR_GET_READINESS_REQ: SENSOR_GET_READINESS_RSP,
+ SENSOR_GET_LATEST_FRAME_REQ: SENSOR_GET_LATEST_FRAME_RSP,
+ SENSOR_LIST_SENSORS_REQ: SENSOR_LIST_SENSORS_RSP,
+ EXTERNAL_POSE_PUSH_REQ: EXTERNAL_POSE_PUSH_RSP,
}
@@ -97,6 +111,11 @@ def _make_payload(req_type: int, req_payload: dict) -> dict:
"estop_released": True,
"vehicle_safe_to_move": True,
"checked_timestamp_us": _ts_us(),
+ "external_pose_feedback_ready": True,
+ "external_pose_source_name": "stub_external_truth",
+ "external_pose_age_ms": 10.0,
+ "external_pose_quality_score": 1.0,
+ "external_pose_transport": "wifi6_stub_tcp",
}
elif req_type == CONTROL_EVALUATION_REQ:
job_id = req_payload.get("header", {}).get("request_id", "stub_job")
@@ -121,6 +140,71 @@ def _make_payload(req_type: int, req_payload: dict) -> dict:
},
"artifacts": [],
}
+ elif req_type == SENSOR_GET_READINESS_REQ:
+ return {
+ "success": True,
+ "error_code": {"code": 1},
+ "message": "Stub: 传感器数据流就绪。",
+ "agent_ready": True,
+ "capture_pipeline_ready": True,
+ "storage_ready": True,
+ "telemetry_ready": True,
+ "vehicle_safe_to_move": True,
+ "arm_ready": True,
+ "ready_sensor_ids": ["demo_front_camera", "demo_down_camera", "demo_lidar_3d", "demo_lidar_2d", "demo_imu"],
+ "issues": [],
+ "checked_timestamp_us": _ts_us(),
+ "sensor_data_stream_ready": True,
+ "streaming_sensor_ids": ["demo_front_camera", "demo_down_camera", "demo_lidar_3d", "demo_lidar_2d", "demo_imu"],
+ "sensor_data_transport": "wifi6_stub_tcp",
+ }
+ elif req_type == SENSOR_LIST_SENSORS_REQ:
+ return {
+ "success": True,
+ "error_code": {"code": 1},
+ "message": "Stub: 传感器列表。",
+ "sensors": [
+ {"sensor_id": "demo_front_camera", "sensor_type": 2, "payload_type": 1, "topic": "/sensor/front_camera/image_raw", "frame_id": "front_camera_link"},
+ {"sensor_id": "demo_down_camera", "sensor_type": 1, "payload_type": 1, "topic": "/sensor/down_camera/image_raw", "frame_id": "down_camera_link"},
+ {"sensor_id": "demo_lidar_3d", "sensor_type": 4, "payload_type": 2, "topic": "/sensor/lidar_3d/pointcloud", "frame_id": "lidar_3d_link"},
+ {"sensor_id": "demo_lidar_2d", "sensor_type": 5, "payload_type": 3, "topic": "/sensor/lidar_2d/scan", "frame_id": "lidar_2d_link"},
+ {"sensor_id": "demo_imu", "sensor_type": 6, "payload_type": 4, "topic": "/sensor/imu/data", "frame_id": "imu_link"},
+ ],
+ }
+ elif req_type == SENSOR_GET_LATEST_FRAME_REQ:
+ sensor_id = req_payload.get("sensor_id", "demo_front_camera")
+ return {
+ "success": True,
+ "error_code": {"code": 1},
+ "message": "Stub: 最新传感器帧。",
+ "sensor_frame": {
+ "header": {
+ "sensor_id": sensor_id,
+ "sensor_type": 2,
+ "frame_id": "front_camera_link",
+ "hardware_timestamp_us": _ts_us(),
+ "sequence_id": 1,
+ "active_job_id": "",
+ "capture_intent": 0,
+ },
+ "payload_type": 1,
+ "stream_id": f"{sensor_id}:1",
+ "fragment_index": 0,
+ "total_fragments": 1,
+ "is_final_fragment": True,
+ "uncompressed_size_bytes": 0,
+ "payload_digest": "",
+ "image": {"width": 0, "height": 0, "encoding": "stub", "is_bigendian": False, "step": 0, "data": "", "compression": "none"},
+ },
+ }
+ elif req_type == EXTERNAL_POSE_PUSH_REQ:
+ return {
+ "success": True,
+ "error_code": {"code": 1},
+ "message": "Stub: 外部真值位姿已接收。",
+ "accepted_timestamp_us": _ts_us(),
+ "reference_source_name": req_payload.get("reference_source_name", "stub_external_truth"),
+ }
return {}
@@ -182,8 +266,16 @@ if __name__ == "__main__":
t_control = threading.Thread(
target=start_server, args=(9002, "control"), name="control-srv", daemon=True
)
+ t_sensor = threading.Thread(
+ target=start_server, args=(9003, "sensor"), name="sensor-srv", daemon=True
+ )
+ t_external_pose = threading.Thread(
+ target=start_server, args=(9004, "external-pose"), name="external-pose-srv", daemon=True
+ )
t_chassis.start()
t_control.start()
+ t_sensor.start()
+ t_external_pose.start()
logging.info("Windows stub server 已启动,按 Ctrl+C 退出。")
try:
t_chassis.join()
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/chassis_bridge_node.cpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/chassis_bridge_node.cpp
similarity index 97%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/chassis_bridge_node.cpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/chassis_bridge_node.cpp
index 3160311..b792f8a 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/chassis_bridge_node.cpp
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/chassis_bridge_node.cpp
@@ -16,9 +16,9 @@ using calibration_common_interfaces::msg::JobState;
ChassisBridgeNode::ChassisBridgeNode(const rclcpp::NodeOptions & options)
: Node("chassis_bridge_node", options)
{
- // 节点参数:Windows 车端 IP 与端口,方便通过 launch 文件或命令行覆盖。
+ // 节点参数:Windows 车端统一 WiFi6 gateway IP 与端口,方便通过 launch 文件或命令行覆盖。
chassis_host_ = declare_parameter("chassis_host", "192.168.1.100");
- chassis_port_ = static_cast(declare_parameter("chassis_port", 9001));
+ chassis_port_ = static_cast(declare_parameter("chassis_port", 9000));
timeout_ms_ = declare_parameter("chassis_timeout_ms", 5000);
readiness_service_ = create_service(
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/control_bridge_node.cpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/control_bridge_node.cpp
similarity index 97%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/control_bridge_node.cpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/control_bridge_node.cpp
index 450e8f8..e399d2c 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/control_bridge_node.cpp
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/control_bridge_node.cpp
@@ -17,9 +17,9 @@ using calibration_common_interfaces::msg::JobState;
ControlBridgeNode::ControlBridgeNode(const rclcpp::NodeOptions & options)
: Node("control_bridge_node", options)
{
- // 节点参数:Windows 车端 IP 与端口,方便通过 launch 文件或命令行覆盖。
+ // 节点参数:Windows 车端统一 WiFi6 gateway IP 与端口,方便通过 launch 文件或命令行覆盖。
control_host_ = declare_parameter("control_host", "192.168.1.100");
- control_port_ = static_cast(declare_parameter("control_port", 9002));
+ control_port_ = static_cast(declare_parameter("control_port", 9000));
timeout_ms_ = declare_parameter("control_timeout_ms", 5000);
readiness_service_ = create_service(
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/main.cpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/main.cpp
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/main.cpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/main.cpp
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/proto_frame.cpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/proto_frame.cpp
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/proto_frame.cpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/proto_frame.cpp
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/tcp_client.cpp b/agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/tcp_client.cpp
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/vehicle_agent_gateway/src/tcp_client.cpp
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/vehicle_agent_gateway/src/tcp_client.cpp
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/CMakeLists.txt b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/CMakeLists.txt
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/CMakeLists.txt
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/images/sequence_diagram.png b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/images/sequence_diagram.png
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/images/sequence_diagram.png
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/images/sequence_diagram.png
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/proto 驱动任务选择图.png b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/proto 驱动任务选择图.png
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/proto 驱动任务选择图.png
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/proto 驱动任务选择图.png
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/传感器标定详细流程图.png b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/传感器标定详细流程图.png
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/传感器标定详细流程图.png
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/传感器标定详细流程图.png
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/底盘标定详细流程图.png b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/底盘标定详细流程图.png
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/底盘标定详细流程图.png
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/底盘标定详细流程图.png
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/自动化标定车间总控完整流程图.png b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/自动化标定车间总控完整流程图.png
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/自动化标定车间总控完整流程图.png
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/自动化标定车间总控完整流程图.png
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/运控参数调优详细流程图.png b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/运控参数调优详细流程图.png
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/docs/运控参数调优详细流程图.png
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/docs/运控参数调优详细流程图.png
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/launch/minimal_workshop_demo.launch.py b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/launch/minimal_workshop_demo.launch.py
similarity index 54%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/launch/minimal_workshop_demo.launch.py
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/launch/minimal_workshop_demo.launch.py
index 5efa949..b01f61f 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/launch/minimal_workshop_demo.launch.py
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/launch/minimal_workshop_demo.launch.py
@@ -8,6 +8,9 @@ from launch_ros.actions import Node
# 参数:
# use_gateway (bool, 默认 false):true 时用 vehicle_agent_gateway 替换本地底盘/运控 stub 节点。
# chassis_host / control_host:Windows 车端 IP(仅 use_gateway=true 时生效)。
+# profile_storage_path:vehicle_profile_manager 的画像持久化文件。
+# sensor_storage_root / sensor_registry / capture_pipeline_name / telemetry_topics:
+# 传感器 readiness 的最小真实配置入口。
def generate_launch_description():
use_gateway_arg = DeclareLaunchArgument(
"use_gateway",
@@ -22,11 +25,53 @@ def generate_launch_description():
"control_host", default_value="192.168.1.100",
description="Windows 车端 IP(use_gateway=true 时生效)",
)
+ profile_storage_path_arg = DeclareLaunchArgument(
+ "profile_storage_path",
+ default_value="/tmp/agv_calib_vehicle_profiles.db",
+ description="vehicle_profile_manager 的画像持久化文件路径",
+ )
+ sensor_storage_root_arg = DeclareLaunchArgument(
+ "sensor_storage_root",
+ default_value="/tmp/agv_sensor_calibration",
+ description="sensor_calibration_service 的产物目录",
+ )
+ sensor_registry_arg = DeclareLaunchArgument(
+ "sensor_registry",
+ default_value="demo_front_camera",
+ description="逗号分隔的可用传感器 ID 列表",
+ )
+ capture_pipeline_name_arg = DeclareLaunchArgument(
+ "capture_pipeline_name",
+ default_value="sensor_capture_pipeline",
+ description="传感器采集链路名称",
+ )
+ telemetry_topics_arg = DeclareLaunchArgument(
+ "telemetry_topics",
+ default_value="/sensor_calibration/telemetry",
+ description="逗号分隔的传感器遥测 topic 列表",
+ )
+ vehicle_safe_to_move_arg = DeclareLaunchArgument(
+ "vehicle_safe_to_move",
+ default_value="true",
+ description="传感器任务若需要移动车辆时,当前是否允许移动",
+ )
+ arm_ready_arg = DeclareLaunchArgument(
+ "arm_ready",
+ default_value="true",
+ description="当前机械臂是否就绪",
+ )
def make_nodes(context):
use_gateway = LaunchConfiguration("use_gateway").perform(context).lower() == "true"
chassis_host = LaunchConfiguration("chassis_host").perform(context)
control_host = LaunchConfiguration("control_host").perform(context)
+ profile_storage_path = LaunchConfiguration("profile_storage_path").perform(context)
+ sensor_storage_root = LaunchConfiguration("sensor_storage_root").perform(context)
+ sensor_registry = LaunchConfiguration("sensor_registry").perform(context)
+ capture_pipeline_name = LaunchConfiguration("capture_pipeline_name").perform(context)
+ telemetry_topics = LaunchConfiguration("telemetry_topics").perform(context)
+ vehicle_safe_to_move = LaunchConfiguration("vehicle_safe_to_move").perform(context).lower() == "true"
+ arm_ready = LaunchConfiguration("arm_ready").perform(context).lower() == "true"
common_nodes = [
Node(
@@ -34,6 +79,9 @@ def generate_launch_description():
executable="vehicle_profile_manager_node",
name="vehicle_profile_manager",
output="screen",
+ parameters=[{
+ "profile_storage_path": profile_storage_path,
+ }],
),
Node(
package="external_localization_service",
@@ -46,6 +94,14 @@ def generate_launch_description():
executable="sensor_calibration_service_node",
name="sensor_calibration_service",
output="screen",
+ parameters=[{
+ "sensor_storage_root": sensor_storage_root,
+ "sensor_registry": sensor_registry,
+ "capture_pipeline_name": capture_pipeline_name,
+ "telemetry_topics": telemetry_topics,
+ "vehicle_safe_to_move": vehicle_safe_to_move,
+ "arm_ready": arm_ready,
+ }],
),
Node(
package="workshop_orchestrator_v2",
@@ -56,7 +112,7 @@ def generate_launch_description():
]
if use_gateway:
- # WiFi 网关模式:底盘和运控通过 TCP 转发到 Windows 车端。
+ # WiFi 网关模式:底盘和运控通过统一 TCP 端口转发到 Windows 车端。
chassis_control_nodes = [
Node(
package="vehicle_agent_gateway",
@@ -65,10 +121,10 @@ def generate_launch_description():
output="screen",
parameters=[{
"chassis_host": chassis_host,
- "chassis_port": 9001,
+ "chassis_port": 9000,
"chassis_timeout_ms": 5000,
"control_host": control_host,
- "control_port": 9002,
+ "control_port": 9000,
"control_timeout_ms": 5000,
}],
),
@@ -96,5 +152,12 @@ def generate_launch_description():
use_gateway_arg,
chassis_host_arg,
control_host_arg,
+ profile_storage_path_arg,
+ sensor_storage_root_arg,
+ sensor_registry_arg,
+ capture_pipeline_name_arg,
+ telemetry_topics_arg,
+ vehicle_safe_to_move_arg,
+ arm_ready_arg,
OpaqueFunction(function=make_nodes),
])
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/package.xml b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/package.xml
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/package.xml
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/package.xml
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/README.md b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/README.md
similarity index 87%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/README.md
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/README.md
index 0999a49..075ad26 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/README.md
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/README.md
@@ -1,10 +1,10 @@
-# 自动化标定车间 Proto 协同工作说明
+# 自动化标定车间协议协同工作说明
-[](https://developers.google.com/protocol-buffers)
-[](https://ubuntu.com)
-[](./)
+> **核心定位**:面向自动化标定车间的分层协议设计,用 8 个 `.proto` 把“车间总控、车辆画像、真值参考、底盘标定、传感器标定、运控调优、参数归档、WiFi6 传输契约”串成一条可执行、可追溯、可扩展的自动化流程。
-> **核心定位**:面向自动化标定车间的分层协议设计,用 7 个 `.proto` 把“车间总控、车辆画像、真值参考、底盘标定、传感器标定、运控调优、参数归档”串成一条可执行、可追溯、可扩展的自动化流程。
+协议格式:Protocol Buffers
+目标平台:Ubuntu / Linux / Windows
+当前状态:Proto 冻结候选版
---
@@ -12,10 +12,10 @@
- [1. 文档目的](#1-文档目的)
- [2. 系统边界与角色分工](#2-系统边界与角色分工)
-- [3. 七个 Proto 文件的职责划分](#3-七个-proto-文件的职责划分)
-- [4. 七个 Proto 的依赖关系](#4-七个-proto-的依赖关系)
+- [3. 八个 Proto 文件的职责划分](#3-八个-proto-文件的职责划分)
+- [4. 八个 Proto 的依赖关系](#4-八个-proto-的依赖关系)
- [5. 自动化标定车间完整流程](#5-自动化标定车间完整流程)
-- [6. 七个 Proto 在主流程中的协同方式](#6-七个-proto-在主流程中的协同方式)
+- [6. 八个 Proto 在主流程中的协同方式](#6-八个-proto-在主流程中的协同方式)
- [7. 当前协议设计已经明确的关键原则](#7-当前协议设计已经明确的关键原则)
- [8. 冻结前建议补齐的小修补项](#8-冻结前建议补齐的小修补项)
- [9. 从 Proto 到 ROS2 的映射建议](#9-从-proto-到-ros2-的映射建议)
@@ -26,13 +26,13 @@
## 1. 文档目的
-本文档用于说明当前自动化标定车间中 **7 个核心 `.proto` 文件** 的职责边界、依赖关系、协同流程和工程落地方式。
+本文档用于说明当前自动化标定车间中 **8 个核心 `.proto` 文件** 的职责边界、依赖关系、协同流程和工程落地方式。
这套协议不是为了把所有逻辑堆到一个服务里,而是为了把整个系统拆成清晰的几层:
- **车间总控层**:只负责编排、状态推进、审批、回滚、归档
- **专业域服务层**:分别处理真值参考、底盘、传感器、运控调优
-- **车端代理层**:只负责动作执行、数据采集、参数写入、状态回传
+- **车端代理层**:只负责动作执行、传感器订阅与数据采集、参数写入、状态回传
- **公共协议层**:统一请求头、错误码、心跳、长任务状态、文件引用、位姿/向量类型
这份 README 的目标是让后续做 ROS2 映射、节点架构设计、C++ 服务实现时,所有人对协议语义有同一个理解。
@@ -74,12 +74,13 @@
- **Linux 负责求解和编排,不负责直接驱动硬件细节**
- **Windows 负责执行和采集,不负责复杂求解与全局决策**
+- **车端传感器属于车辆侧,图像、点云、LaserScan、IMU 原始帧经 WiFi6 从车端转发到车间电脑**
- **所有阶段都围绕同一个 `session_id`、`vehicle_id`、`job_id` 协同**
- **所有长任务都统一使用 `JobAccepted / JobStatus / JobResult` 语义**
---
-## 3. 七个 Proto 文件的职责划分
+## 3. 八个 Proto 文件的职责划分
### 3.1 calibration_common.proto
@@ -96,7 +97,7 @@
- `HeartbeatRequest / HeartbeatResponse`:统一保活机制
- `AgentReadinessRequest / ReadinessIssue`:统一 readiness 检查模式
- `FileDigest / FileReference`:统一文件摘要与文件引用
-- `Vector3D / Vector3d / Pose3D / Pose3dEuler`:统一三维向量与位姿表达
+- `Vector3D / Pose3D`:统一三维向量与位姿表达
- `KeyValuePair`:为后续扩展保留元数据入口
**一句话理解**:它不描述任何专项算法,但所有专项服务都要先站在这块地基上。
@@ -272,6 +273,8 @@
- 传感器到 `base_link` 外参任务
- 手眼标定任务
- 遥测流
+- 车端传感器原始数据流 `StreamVehicleSensorData`
+- 车间电脑传感器数据接收服务 `AgvCalibWorkshopSensorIngestService`
- 参数写入与查询
- 任务结果与验证摘要
@@ -279,13 +282,14 @@
- 已支持相机 **只做内参 / 只做外参 / 内外参都做**
- 已将 IMU 内参改为三轴强约束:
- - `Vector3d accel_bias`
- - `Vector3d gyro_bias`
+ - `Vector3D accel_bias`
+ - `Vector3D gyro_bias`
- 已增加 `LASER_SCAN_FILE`,单独表达 2D 激光雷达产物
+- 已增加 `VehicleSensorFrame`,用于承载相机图像、3D 点云、2D LaserScan、IMU 原始帧,并支持大图像 / 点云分片传输
- 已增加 `SensorValidationSummary`
- 已增加 `SensorCalibrationJobResult`
-**一句话理解**:它负责把“采什么、怎么采、产出什么参数、怎么判断是否通过”描述完整。
+**一句话理解**:它负责把“采什么、怎么采、原始数据怎么从车端到车间电脑、产出什么参数、怎么判断是否通过”描述完整。
---
@@ -320,7 +324,23 @@
---
-## 4. 七个 Proto 的依赖关系
+### 3.8 transport_contract.proto
+
+**作用:车间工控机与车端电脑之间的 WiFi6/TCP 传输契约。**
+
+它不替代底盘、运控、传感器、外部真值的业务消息,而是固定网络边界上的通道和帧规则:
+
+- `Wifi6Channel`:底盘、运控、传感器、外部真值位姿四个逻辑通道
+- `Wifi6DefaultPort`:WiFi6 边界默认使用统一车端 gateway 端口 9000,9001-9004 只作为仿真内部域端口或旧版兼容
+- `Wifi6FrameType`:当前 TCP 帧号 1-32
+- `Wifi6TcpFrameHeader`:8 字节小端帧头的契约表达
+- `Wifi6PayloadEncoding`:当前 JSON 字段名编码与后续 protobuf binary 编码预留
+
+**一句话理解**:它把“哪些数据通过 WiFi6 怎么走”固定下来,避免 Windows 车端和 Ubuntu 工控机只靠代码常量私下约定。
+
+---
+
+## 4. 八个 Proto 的依赖关系
依赖关系可以概括如下:
@@ -333,6 +353,7 @@
| `control_calibration.proto` | `calibration_common.proto`、`vehicle_profile.proto` | 运控调优执行、遥测、验证、参数写入 |
| `sensor_calibration.proto` | `calibration_common.proto`、`vehicle_profile.proto` | 传感器任务、采集、参数、验证 |
| `workshop_orchestration.proto` | `calibration_common.proto`、`vehicle_profile.proto` | 整场会话编排、计划、审批、回滚、报告 |
+| `transport_contract.proto` | 无 | WiFi6/TCP 通道、端口、帧头、帧号、payload 编码 |
总体依赖方向是:
@@ -344,6 +365,7 @@ flowchart LR
A --> E[control_calibration.proto]
A --> F[sensor_calibration.proto]
A --> G[workshop_orchestration.proto]
+ H[transport_contract.proto]
B --> D
B --> E
B --> F
@@ -458,7 +480,7 @@ flowchart TB
---
-## 6. 七个 Proto 在主流程中的协同方式
+## 6. 八个 Proto 在主流程中的协同方式
### 6.1 协同主图
@@ -555,7 +577,7 @@ Windows 代理只负责:
## 8. 冻结前建议补齐的小修补项
-当前 7 个 proto 的主结构已经可以冻结,但为了减少后续返工,建议在冻结前补 4 类小修补。
+当前 8 个 proto 的主结构已经可以冻结,但为了减少后续返工,建议在冻结前补 4 类小修补。
### 8.1 给计划 / 结果 / 报告补统一 `metadata`
@@ -620,10 +642,11 @@ message CalibrationReferenceTarget {
- `RequestHeader`
- `JobStatus`
-- `Pose3dEuler`
+- `Pose3D`
- `ChassisTelemetry`
- `ControlTelemetry`
- `SensorCalibrationTelemetry`
+- `VehicleSensorFrame`
### 9.2 srv
@@ -682,7 +705,8 @@ proto/
├── chassis_calibration.proto
├── control_calibration.proto
├── sensor_calibration.proto
-└── workshop_orchestration.proto
+├── workshop_orchestration.proto
+└── transport_contract.proto
services/
├── workshop_orchestrator/
@@ -708,7 +732,7 @@ logs/
建议按下面顺序推进:
-1. 先冻结 7 个 proto
+1. 先冻结 8 个 proto
2. 再设计 ROS2 的 msg / srv / action 对应关系
3. 再画节点架构图和 topic / service / action 拓扑
4. 再实现总控状态机
@@ -728,7 +752,7 @@ logs/
## 11. 总结
-当前这套 7 个 proto 已经不再是“概念方案”,而是一套接近可冻结的自动化标定车间协议主干。
+当前这套 8 个 proto 已经不再是“概念方案”,而是一套接近可冻结的自动化标定车间协议主干。
它们共同支撑的不是单个算法模块,而是完整的一条自动化流程:
@@ -743,7 +767,8 @@ logs/
- `control_calibration.proto` 负责横纵向控制器调优执行
- `sensor_calibration.proto` 负责多传感器采集、求解与参数表达
- `workshop_orchestration.proto` 负责总流程编排、审批、回滚与归档
+- `transport_contract.proto` 固定 WiFi6/TCP 通道、端口、帧头、帧号和 payload 编码
只要把冻结前的小修补项补齐,这套协议就可以正式进入下一阶段:
-**ROS2 接口映射、节点架构设计、C++ 服务实现。**
\ No newline at end of file
+**ROS2 接口映射、节点架构设计、C++ 服务实现。**
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/calibration_common.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/calibration_common.proto
similarity index 99%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/calibration_common.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/calibration_common.proto
index 4d44308..0013f90 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/calibration_common.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/calibration_common.proto
@@ -3,8 +3,8 @@ syntax = "proto3";
package agv.calibration.common;
// ├── msg/
-// │ ├── Vector3d.msg
-// │ ├── Pose3dEuler.msg
+// │ ├── Vector3D.msg
+// │ ├── Pose3D.msg
// │ ├── RequestHeader.msg
// │ ├── ErrorCode.msg
// │ ├── StandardResponse.msg
@@ -263,4 +263,4 @@ message FileReference {
message KeyValuePair {
string key = 1; // 键
string value = 2; // 值
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/chassis_calibration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/chassis_calibration.proto
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/chassis_calibration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/chassis_calibration.proto
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/proto/control_calibration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/control_calibration.proto
similarity index 93%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/proto/control_calibration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/control_calibration.proto
index 61a04c4..307e21b 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_control_interfaces/proto/control_calibration.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/control_calibration.proto
@@ -115,6 +115,12 @@ message ControlReadinessResponse {
bool vehicle_safe_to_move = 9; // 当前车辆是否允许移动
repeated .agv.calibration.common.ReadinessIssue issues = 10; // 不满足项
int64 checked_timestamp_us = 11; // 检查时间
+
+ bool external_pose_feedback_ready = 12; // 外部真值 / 定位位姿输入是否就绪
+ string external_pose_source_name = 13; // 当前外部位姿源名称
+ double external_pose_age_ms = 14; // 最近一帧外部位姿年龄
+ double external_pose_quality_score = 15; // 最近一帧外部位姿质量分数
+ string external_pose_transport = 16; // 外部位姿传输方式,例如 wifi6
}
// =========================================================
@@ -249,6 +255,13 @@ message TrajectoryTrackingTask {
repeated TrajectoryPoint path = 1; // 轨迹点序列
bool stop_at_end = 2; // 结束后是否停车
double timeout_sec = 3; // 超时时间
+ string required_external_pose_source_id = 4; // 要求使用的外部位姿源 ID
+ double max_external_pose_age_ms = 5; // 允许最大外部位姿延迟
+ double min_external_pose_quality_score = 6; // 允许最小外部位姿质量分数
+ string trajectory_id = 7; // 轨迹 ID,用于分段下发时关联多段轨迹
+ uint32 segment_index = 8; // 当前轨迹段序号,从 0 开始
+ uint32 total_segments = 9; // 总段数;0 或 1 表示本请求携带完整轨迹
+ bool is_final_segment = 10; // 当前段是否为最后一段,作为 total_segments 的冗余校验
}
// =========================================================
@@ -353,6 +366,9 @@ message ControlTelemetry {
string parameter_version = 15; // 当前生效参数版本
.agv.calibration.vehicle.profile.ControllerAlgorithmType active_lateral_algorithm = 16; // 当前横向算法
.agv.calibration.vehicle.profile.ControllerAlgorithmType active_longitudinal_algorithm = 17; // 当前纵向算法
+
+ string pose_source_name = 18; // 本帧控制使用的位姿源名称
+ bool pose_from_external_truth = 19; // 本帧位姿是否来自外部真值 / 外部定位
}
// =========================================================
@@ -420,4 +436,4 @@ message ControlJobResult {
ControlValidationSummary validation_summary = 8; // 验证摘要
ControllerParameterSet estimated_parameter_set = 9; // 本轮估计参数集
repeated .agv.calibration.common.FileReference artifacts = 10; // 关联产物
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/proto/external_localization.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/external_localization.proto
similarity index 87%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/proto/external_localization.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/external_localization.proto
index 35749b7..069bb81 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_external_localization_interfaces/proto/external_localization.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/external_localization.proto
@@ -69,6 +69,30 @@ service AgvCalibExternalLocalizationService {
returns (.agv.calibration.common.StandardResponse);
}
+// =========================================================
+// 服务:外部真值位姿下发服务
+// 运行位置:Ubuntu 车间电脑 / 外部真值系统桥接进程
+// 调用方:Windows 车端代理
+// 传输介质:现场通过 WiFi 6 网络承载
+// 作用:
+// 1) 让车端在执行轨迹跟踪时获得车间坐标系下的实时位姿
+// 2) 与 StreamExternalLocalizationTelemetry 使用同一位姿消息结构
+// 3) 车端不得把底盘里程计当成默认全局位姿源,只可作为降级输入
+// =========================================================
+service AgvCalibExternalPoseFeedService {
+ // 心跳保活,用于车端确认外部真值链路在线
+ rpc Heartbeat(.agv.calibration.common.HeartbeatRequest)
+ returns (.agv.calibration.common.HeartbeatResponse);
+
+ // 车端订阅外部真值位姿流
+ rpc StreamExternalPoseToVehicle(ExternalPoseFeedRequest)
+ returns (stream ExternalLocalizationTelemetry);
+
+ // 可选:外部真值系统主动推送单帧位姿到车端
+ rpc PushExternalPoseToVehicle(ExternalLocalizationTelemetry)
+ returns (.agv.calibration.common.StandardResponse);
+}
+
// =========================================================
// 外部定位工作模式请求
// 作用:切换外部定位桥接服务到不同模式
@@ -238,6 +262,20 @@ message StreamExternalLocalizationTelemetryRequest {
bool include_tracking_state = 6; // 是否包含跟踪状态
}
+// =========================================================
+// 外部真值位姿下发请求
+// 作用:车端通过 WiFi 6 请求工控机 / 外部真值桥接进程提供实时位姿流
+// =========================================================
+message ExternalPoseFeedRequest {
+ .agv.calibration.common.RequestHeader header = 1; // 请求头
+ string vehicle_id = 2; // 目标车辆 ID
+ string localization_source_id = 3; // 外部真值源 ID
+ string workcell_zone_id = 4; // 工位 / 区域 ID
+ uint32 expected_hz = 5; // 期望下发频率
+ double max_pose_age_ms = 6; // 允许最大位姿延迟
+ bool require_quality_metrics = 7; // 是否要求质量指标
+}
+
// =========================================================
// 外部定位遥测
// 作用:回传外部定位实时观测结果
@@ -248,7 +286,7 @@ message ExternalLocalizationTelemetry {
int64 hardware_timestamp_us = 1; // 硬件时间戳
bool pose_valid = 2; // 位姿是否有效
- .agv.calibration.common.Pose3dEuler workshop_pose = 3; // 在车间参考系下的位姿
+ .agv.calibration.common.Pose3D workshop_pose = 3; // 在车间参考系下的位姿
double position_stddev_m = 4; // 位置标准差
double yaw_stddev_rad = 5; // 航向标准差
@@ -269,7 +307,7 @@ message ExternalLocalizationCalibrationResult {
string workshop_frame_id = 1; // 车间参考坐标系 ID
string localization_frame_id = 2; // 外部定位坐标系 ID
- .agv.calibration.common.Pose3dEuler workshop_to_localization = 3; // 车间系到定位系的位姿
+ .agv.calibration.common.Pose3D workshop_to_localization = 3; // 车间系到定位系的位姿
double position_repeatability_m = 4; // 位置重复性
double yaw_repeatability_rad = 5; // 航向重复性
@@ -334,4 +372,4 @@ message ExternalLocalizationJobResult {
ExternalLocalizationValidationSummary validation_summary = 9; // 真值参考验证摘要
ExternalLocalizationCalibrationResult result = 10; // 结果内容
repeated .agv.calibration.common.FileReference artifacts = 11; // 关联产物
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/proto/sensor_calibration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/sensor_calibration.proto
similarity index 70%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/proto/sensor_calibration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/sensor_calibration.proto
index 38d0096..a121b55 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_sensor_interfaces/proto/sensor_calibration.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/sensor_calibration.proto
@@ -11,7 +11,7 @@ import "vehicle_profile.proto";
// Ubuntu 车间电脑(Linux) -> Windows 车端代理 / 采集服务
// 说明:
// 1) Linux 负责图像 / 点云 / 激光扫描 / IMU 数据分析与参数求解
-// 2) 车端 / 采集服务只负责组织采集、回传观测状态、写入结果
+// 2) 车端 / 采集服务负责订阅车端传感器、组织采集、回传原始数据和观测状态、写入结果
// 3) 支持相机内参、IMU 内参、传感器外参、手眼标定
// 4) 支持相机“只做内参 / 只做外参 / 内外参都做”
// =========================================================
@@ -58,6 +58,10 @@ service AgvCalibSensorService {
rpc StreamSensorCalibrationTelemetry(StreamSensorCalibrationTelemetryRequest)
returns (stream SensorCalibrationTelemetry);
+ // 打开车端传感器原始数据流;用于 WiFi6 把车载相机、雷达、IMU 数据传给车间电脑
+ rpc StreamVehicleSensorData(StreamVehicleSensorDataRequest)
+ returns (stream VehicleSensorFrame);
+
// 写入传感器标定参数
rpc CommitSensorCalibrationParameters(CommitSensorCalibrationParametersRequest)
returns (.agv.calibration.common.StandardResponse);
@@ -71,6 +75,22 @@ service AgvCalibSensorService {
returns (.agv.calibration.common.StandardResponse);
}
+// =========================================================
+// 服务:车间电脑传感器数据接收服务
+// 运行位置:Ubuntu 车间电脑
+// 调用方:Windows 车端代理 / 仿真车端代理
+// 说明:
+// 1) 当现场网络策略采用车端主动上报时使用
+// 2) 与 StreamVehicleSensorData 使用同一帧结构
+// =========================================================
+service AgvCalibWorkshopSensorIngestService {
+ rpc Heartbeat(.agv.calibration.common.HeartbeatRequest)
+ returns (.agv.calibration.common.HeartbeatResponse);
+
+ rpc PushVehicleSensorFrame(VehicleSensorFrame)
+ returns (.agv.calibration.common.StandardResponse);
+}
+
// =========================================================
// 传感器标定工作模式
// 作用:切换采集服务到不同模式
@@ -109,6 +129,10 @@ message SensorReadinessResponse {
repeated string ready_sensor_ids = 10; // 已就绪的传感器 ID
repeated .agv.calibration.common.ReadinessIssue issues = 11; // 不满足项
int64 checked_timestamp_us = 12; // 检查时间
+
+ bool sensor_data_stream_ready = 13; // 车端原始传感器数据流是否就绪
+ repeated string streaming_sensor_ids = 14; // 当前可被转发到车间电脑的传感器 ID
+ string sensor_data_transport = 15; // 传输方式,例如 wifi6 / wifi6_sim_tcp
}
// =========================================================
@@ -137,6 +161,9 @@ message SensorCalibrationCapabilityResponse {
bool supports_2d_lidar_extrinsic = 9; // 是否支持 2D 激光雷达外参
bool supports_camera_only_intrinsic = 10; // 是否支持仅做相机内参
bool supports_camera_only_extrinsic = 11; // 是否支持仅做相机外参
+ bool supports_vehicle_sensor_data_stream = 12; // 是否支持车端原始传感器数据流
+ bool supports_sensor_frame_chunking = 13; // 是否支持大帧分片传输
+ bool supports_compressed_image_stream = 14; // 是否支持压缩图像流
}
// =========================================================
@@ -238,8 +265,8 @@ enum SensorCalibrationTaskSubtype {
IMU_EXTRINSIC = 6;
LIDAR_2D_EXTRINSIC = 7;
LIDAR_3D_EXTRINSIC = 8;
- EYE_IN_HAND = 9;
- EYE_TO_HAND = 10;
+ HAND_EYE_IN_HAND = 9;
+ HAND_EYE_TO_HAND = 10;
}
// =========================================================
@@ -300,6 +327,161 @@ message SensorCalibrationTelemetry {
CaptureIntentType capture_intent = 9; // 当前采集意图
}
+// =========================================================
+// 车端传感器原始数据流请求
+// 作用:车间电脑指定要接收哪些车端传感器数据
+// =========================================================
+message StreamVehicleSensorDataRequest {
+ .agv.calibration.common.RequestHeader header = 1; // 请求头
+ repeated string sensor_ids = 2; // 要接收的传感器 ID;为空表示由任务决定
+ repeated .agv.calibration.vehicle.profile.SensorType sensor_types = 3; // 要接收的传感器类型
+ uint32 expected_hz = 4; // 期望上报频率,0 表示车端默认
+ uint32 max_frame_payload_bytes = 5; // 单个分片最大 payload,0 表示车端默认
+ bool allow_compressed = 6; // 是否允许压缩图像 / 点云
+ bool include_camera_info = 7; // 是否随图像携带相机内参初值
+ CaptureIntentType capture_intent = 8; // 数据采集意图
+ string active_job_id = 9; // 关联的标定任务 ID
+}
+
+// =========================================================
+// 传感器原始帧负载类型
+// =========================================================
+enum SensorFramePayloadType {
+ SENSOR_FRAME_PAYLOAD_TYPE_UNSPECIFIED = 0;
+ IMAGE_FRAME = 1; // 相机图像
+ POINT_CLOUD_FRAME = 2; // 3D 激光雷达点云
+ LASER_SCAN_FRAME = 3; // 2D 激光雷达扫描
+ IMU_FRAME = 4; // IMU 数据
+ CAMERA_INFO_FRAME = 5; // 相机内参 / camera_info
+ RAW_BYTES_FRAME = 6; // 预留给厂商私有二进制格式
+}
+
+// =========================================================
+// 传感器原始帧公共头
+// =========================================================
+message VehicleSensorFrameHeader {
+ string sensor_id = 1; // 传感器 ID,例如 demo_front_camera
+ .agv.calibration.vehicle.profile.SensorType sensor_type = 2; // 传感器类型
+ string frame_id = 3; // ROS / 车端坐标系 frame_id
+ int64 hardware_timestamp_us = 4; // 硬件时间戳
+ uint64 sequence_id = 5; // 单传感器递增帧号
+ string active_job_id = 6; // 关联任务 ID
+ CaptureIntentType capture_intent = 7; // 采集意图
+}
+
+// =========================================================
+// 图像帧
+// 对齐 ROS sensor_msgs/Image 的核心字段
+// =========================================================
+message VehicleImageFrame {
+ uint32 width = 1; // 图像宽度
+ uint32 height = 2; // 图像高度
+ string encoding = 3; // 例如 rgb8 / bgr8 / mono8 / jpeg / png
+ bool is_bigendian = 4; // 字节序
+ uint32 step = 5; // 每行字节数
+ bytes data = 6; // 图像数据或分片数据
+ string compression = 7; // none / jpeg / png
+ CameraIntrinsics camera_intrinsics_hint = 8; // 可选内参初值或当前参数
+}
+
+// =========================================================
+// PointCloud2 字段描述
+// =========================================================
+enum PointCloudFieldDataType {
+ POINT_CLOUD_FIELD_DATA_TYPE_UNSPECIFIED = 0;
+ POINT_CLOUD_FIELD_INT8 = 1;
+ POINT_CLOUD_FIELD_UINT8 = 2;
+ POINT_CLOUD_FIELD_INT16 = 3;
+ POINT_CLOUD_FIELD_UINT16 = 4;
+ POINT_CLOUD_FIELD_INT32 = 5;
+ POINT_CLOUD_FIELD_UINT32 = 6;
+ POINT_CLOUD_FIELD_FLOAT32 = 7;
+ POINT_CLOUD_FIELD_FLOAT64 = 8;
+}
+
+message PointCloudField {
+ string name = 1; // 字段名,例如 x / y / z / intensity
+ uint32 offset = 2; // 字节偏移
+ PointCloudFieldDataType datatype = 3; // 数据类型
+ uint32 count = 4; // 元素数量
+}
+
+// =========================================================
+// 3D 点云帧
+// 对齐 ROS sensor_msgs/PointCloud2 的核心字段
+// =========================================================
+message VehiclePointCloudFrame {
+ uint32 height = 1;
+ uint32 width = 2;
+ repeated PointCloudField fields = 3;
+ bool is_bigendian = 4;
+ uint32 point_step = 5;
+ uint32 row_step = 6;
+ bytes data = 7; // 点云数据或分片数据
+ bool is_dense = 8;
+ string compression = 9; // none / zstd / lz4 / vendor
+}
+
+// =========================================================
+// 2D 激光雷达扫描帧
+// 对齐 ROS sensor_msgs/LaserScan 的核心字段
+// =========================================================
+message VehicleLaserScanFrame {
+ double angle_min_rad = 1;
+ double angle_max_rad = 2;
+ double angle_increment_rad = 3;
+ double time_increment_sec = 4;
+ double scan_time_sec = 5;
+ double range_min_m = 6;
+ double range_max_m = 7;
+ repeated float ranges_m = 8;
+ repeated float intensities = 9;
+}
+
+// =========================================================
+// IMU 帧
+// 对齐 ROS sensor_msgs/Imu 的核心字段
+// =========================================================
+message VehicleImuFrame {
+ double orientation_x = 1;
+ double orientation_y = 2;
+ double orientation_z = 3;
+ double orientation_w = 4;
+ repeated double orientation_covariance = 5;
+ .agv.calibration.common.Vector3D angular_velocity = 6;
+ repeated double angular_velocity_covariance = 7;
+ .agv.calibration.common.Vector3D linear_acceleration = 8;
+ repeated double linear_acceleration_covariance = 9;
+}
+
+// =========================================================
+// 车端传感器原始帧
+// 作用:通过 WiFi6 在车端和车间电脑之间传输相机 / 雷达 / IMU 数据
+// 说明:
+// 1) fragment_index / total_fragments 用于大图像或点云分片
+// 2) total_fragments 为 0 或 1 表示本消息携带完整帧
+// 3) oneof 中的数据字段可携带完整数据,也可携带当前分片数据
+// =========================================================
+message VehicleSensorFrame {
+ VehicleSensorFrameHeader header = 1; // 公共帧头
+ SensorFramePayloadType payload_type = 2; // 负载类型
+ string stream_id = 3; // 数据流 ID
+ uint32 fragment_index = 4; // 当前分片序号,从 0 开始
+ uint32 total_fragments = 5; // 总分片数;0 或 1 表示完整帧
+ bool is_final_fragment = 6; // 当前是否最后一个分片
+ uint32 uncompressed_size_bytes = 7; // 解压后总大小,用于校验
+ string payload_digest = 8; // 完整帧摘要,例如 sha256:...
+
+ oneof payload {
+ VehicleImageFrame image = 20;
+ VehiclePointCloudFrame point_cloud = 21;
+ VehicleLaserScanFrame laser_scan = 22;
+ VehicleImuFrame imu = 23;
+ CameraIntrinsics camera_info = 24;
+ bytes raw_payload = 25;
+ }
+}
+
// =========================================================
// 相机模型类型
// 作用:表达相机内参使用的模型
@@ -335,8 +517,8 @@ message CameraIntrinsics {
// 3) 采用强约束三维向量,不再使用 repeated double
// =========================================================
message IMUIntrinsics {
- .agv.calibration.common.Vector3d accel_bias = 1; // 加速度计偏置
- .agv.calibration.common.Vector3d gyro_bias = 2; // 陀螺仪偏置
+ .agv.calibration.common.Vector3D accel_bias = 1; // 加速度计偏置
+ .agv.calibration.common.Vector3D gyro_bias = 2; // 陀螺仪偏置
}
// =========================================================
@@ -347,7 +529,7 @@ message IMUIntrinsics {
message SensorExtrinsics {
string parent_frame_id = 1; // 父坐标系,一般为 base_link
string child_frame_id = 2; // 子坐标系,一般为 sensor frame
- .agv.calibration.common.Pose3dEuler parent_to_child = 3; // 父到子的位姿
+ .agv.calibration.common.Pose3D parent_to_child = 3; // 父到子的位姿
}
// =========================================================
@@ -461,4 +643,4 @@ message SensorCalibrationJobResult {
SensorValidationSummary validation_summary = 8; // 验证摘要
SensorCalibrationParameterSet estimated_params = 9; // 本轮估计参数
repeated CalibrationArtifact artifacts = 10; // 关联产物
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/transport_contract.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/transport_contract.proto
new file mode 100644
index 0000000..8cb6376
--- /dev/null
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/transport_contract.proto
@@ -0,0 +1,146 @@
+syntax = "proto3";
+
+package agv.calibration.transport;
+
+// =========================================================
+// 文件作用:WiFi6/TCP 传输契约
+// 使用范围:
+// 1) Ubuntu 车间工控机与 Windows 车端代理之间的网络边界
+// 2) 仿真车端 agent 与真实车端 agent 需要共同遵守的帧号和通道约定
+// 3) 业务消息仍由 chassis/control/sensor/external_localization proto 定义
+// 说明:
+// 1) WiFi6 是承载网络,当前工程传输层使用 TCP 长/短连接
+// 2) 当前仿真实现 payload 使用 proto 字段名风格的 JSON
+// 3) 现场可切换为 protobuf binary,但必须保持本文件中的通道和帧号不变
+// =========================================================
+
+// =========================================================
+// WiFi6 逻辑通道
+// =========================================================
+enum Wifi6Channel {
+ WIFI6_CHANNEL_UNSPECIFIED = 0;
+ WIFI6_CHANNEL_CHASSIS = 1; // 底盘标定动作和急停
+ WIFI6_CHANNEL_CONTROL = 2; // 运控参数评估、轨迹跟踪
+ WIFI6_CHANNEL_SENSOR = 3; // 车端传感器原始数据
+ WIFI6_CHANNEL_EXTERNAL_POSE = 4; // 外部真值位姿输入到车端
+}
+
+// =========================================================
+// 默认端口
+// 说明:
+// 1) WiFi6 边界默认只暴露一个车端 gateway 端口
+// 2) channel 只是协议里的逻辑通道,不应该被理解成“一类功能一个物理端口”
+// 3) 9001-9004 仅保留给仿真 router 背后的内部域服务或旧版兼容使用
+// =========================================================
+enum Wifi6DefaultPort {
+ WIFI6_DEFAULT_PORT_UNSPECIFIED = 0;
+ WIFI6_DEFAULT_PORT_VEHICLE_GATEWAY = 9000;
+ WIFI6_LEGACY_INTERNAL_PORT_CHASSIS = 9001;
+ WIFI6_LEGACY_INTERNAL_PORT_CONTROL = 9002;
+ WIFI6_LEGACY_INTERNAL_PORT_SENSOR = 9003;
+ WIFI6_LEGACY_INTERNAL_PORT_EXTERNAL_POSE = 9004;
+}
+
+// =========================================================
+// TCP 载荷编码方式
+// =========================================================
+enum Wifi6PayloadEncoding {
+ WIFI6_PAYLOAD_ENCODING_UNSPECIFIED = 0;
+ WIFI6_PAYLOAD_ENCODING_JSON_PROTO_FIELD_NAMES = 1; // 当前仿真实现:JSON key 使用 proto 字段名
+ WIFI6_PAYLOAD_ENCODING_PROTOBUF_BINARY = 2; // 现场高性能实现可选
+}
+
+// =========================================================
+// TCP 连接方向
+// =========================================================
+enum Wifi6FrameDirection {
+ WIFI6_FRAME_DIRECTION_UNSPECIFIED = 0;
+ WIFI6_FRAME_DIRECTION_WORKSHOP_TO_VEHICLE = 1;
+ WIFI6_FRAME_DIRECTION_VEHICLE_TO_WORKSHOP = 2;
+}
+
+// =========================================================
+// TCP 帧号
+// 帧头格式固定为:
+// uint32 little-endian msg_type
+// uint32 little-endian payload_len
+// payload_len bytes payload
+// 注意:
+// 1) 这个 8 字节帧头不是 protobuf 序列化结果,而是传输层二进制头
+// 2) payload 的业务结构由本字段注释中对应的 proto 消息定义
+// 3) 逻辑 channel 由 msg_type 映射得到;同一个 gateway 端口根据 msg_type 做路由
+// =========================================================
+enum Wifi6FrameType {
+ WIFI6_FRAME_TYPE_UNSPECIFIED = 0;
+
+ // 底盘域:chassis_calibration.proto / AgvCalibChassisService
+ WIFI6_FRAME_CHASSIS_GET_READINESS_REQ = 1; // AgentReadinessRequest
+ WIFI6_FRAME_CHASSIS_GET_READINESS_RSP = 2; // ChassisReadinessResponse
+ WIFI6_FRAME_CHASSIS_MOTION_PRIMITIVE_REQ = 3; // MotionPrimitiveRequest
+ WIFI6_FRAME_CHASSIS_MOTION_PRIMITIVE_RSP = 4; // ChassisJobResult
+ WIFI6_FRAME_CHASSIS_EMERGENCY_BRAKE_REQ = 5; // Empty 或 EmergencyBrake 请求
+ WIFI6_FRAME_CHASSIS_EMERGENCY_BRAKE_RSP = 6; // StandardResponse
+
+ // 运控域:control_calibration.proto / AgvCalibControlService
+ WIFI6_FRAME_CONTROL_GET_READINESS_REQ = 11; // AgentReadinessRequest
+ WIFI6_FRAME_CONTROL_GET_READINESS_RSP = 12; // ControlReadinessResponse
+ WIFI6_FRAME_CONTROL_EVALUATION_REQ = 13; // ControllerEvaluationRequest
+ WIFI6_FRAME_CONTROL_EVALUATION_RSP = 14; // ControlJobResult
+
+ // 传感器域:sensor_calibration.proto / AgvCalibSensorService
+ WIFI6_FRAME_SENSOR_GET_READINESS_REQ = 21; // AgentReadinessRequest
+ WIFI6_FRAME_SENSOR_GET_READINESS_RSP = 22; // SensorReadinessResponse
+ WIFI6_FRAME_SENSOR_GET_LATEST_FRAME_REQ = 23; // StreamVehicleSensorDataRequest 的轻量轮询形态
+ WIFI6_FRAME_SENSOR_GET_LATEST_FRAME_RSP = 24; // VehicleSensorFrame
+ WIFI6_FRAME_SENSOR_LIST_SENSORS_REQ = 25; // Empty 或能力查询请求
+ WIFI6_FRAME_SENSOR_LIST_SENSORS_RSP = 26; // Sensor 列表响应
+
+ // 外部真值位姿域:external_localization.proto / AgvCalibExternalPoseFeedService
+ WIFI6_FRAME_EXTERNAL_POSE_PUSH_REQ = 31; // ExternalLocalizationTelemetry
+ WIFI6_FRAME_EXTERNAL_POSE_PUSH_RSP = 32; // StandardResponse
+}
+
+// =========================================================
+// TCP 帧头的 protobuf 表达
+// 说明:
+// 1) 这个 message 仅用于文档、测试、代码生成时表达契约
+// 2) 实际线上帧头仍是上面注释中定义的 8 字节小端二进制结构
+// =========================================================
+message Wifi6TcpFrameHeader {
+ Wifi6FrameType msg_type = 1; // 对应 8 字节帧头中的 uint32 msg_type
+ uint32 payload_len = 2; // 对应 8 字节帧头中的 uint32 payload_len
+}
+
+// =========================================================
+// 逻辑通道端点
+// =========================================================
+message Wifi6ChannelEndpoint {
+ Wifi6Channel channel = 1;
+ Wifi6DefaultPort default_port = 2;
+ Wifi6FrameDirection request_direction = 3;
+ string canonical_proto_file = 4; // 例如 chassis_calibration.proto
+ string canonical_service = 5; // 例如 AgvCalibChassisService
+}
+
+// =========================================================
+// 请求 / 响应帧映射
+// =========================================================
+message Wifi6FrameMapping {
+ Wifi6Channel channel = 1;
+ Wifi6FrameType request_type = 2;
+ Wifi6FrameType response_type = 3;
+ Wifi6PayloadEncoding payload_encoding = 4;
+ string request_message = 5; // proto 消息名
+ string response_message = 6; // proto 消息名
+ string rpc_name = 7; // 对齐的 RPC 名称;轻量轮询可为空
+}
+
+// =========================================================
+// 当前工程默认契约版本
+// =========================================================
+message Wifi6TransportContract {
+ string contract_version = 1; // 当前为 "wifi6_tcp_v1"
+ Wifi6PayloadEncoding default_payload_encoding = 2;
+ repeated Wifi6ChannelEndpoint endpoints = 3;
+ repeated Wifi6FrameMapping frame_mappings = 4;
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/proto/vehicle_profile.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/vehicle_profile.proto
similarity index 99%
rename from agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/proto/vehicle_profile.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/vehicle_profile.proto
index 678fccd..a396702 100644
--- a/agv_calib_brain/src/win_ubuntu_bridge/calibration_vehicle_profile_interfaces/proto/vehicle_profile.proto
+++ b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/vehicle_profile.proto
@@ -352,4 +352,4 @@ message VehicleCalibrationApplicabilityResponse {
repeated ApplicabilityIssue issues = 5; // 问题列表
bool overall_supported = 6; // 是否总体可开展标定
repeated WorkflowStageType recommended_workflow_stages = 7; // 推荐执行阶段
-}
\ No newline at end of file
+}
diff --git a/agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/workshop_orchestration.proto b/agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/workshop_orchestration.proto
similarity index 100%
rename from agv_calib_brain/src/win_ubuntu_bridge/win_ubuntu_bridge/proto/workshop_orchestration.proto
rename to agv_calib_brain/src/communication/win_ubuntu_bridge/win_ubuntu_bridge/proto/workshop_orchestration.proto
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/CMakeLists.txt b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/CMakeLists.txt
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/CMakeLists.txt
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithm_template.hpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithm_template.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithm_template.hpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithm_template.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithms.hpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithms.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithms.hpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_algorithms.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_common.hpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_common.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_common.hpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_common.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_service_node.hpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_service_node.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_service_node.hpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/include/chassis_calibration_service/chassis_calibration_service_node.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/launch/chassis_calibration_service_component.launch.py b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/launch/chassis_calibration_service_component.launch.py
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/launch/chassis_calibration_service_component.launch.py
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/launch/chassis_calibration_service_component.launch.py
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/package.xml b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/package.xml
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/package.xml
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/package.xml
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/ackermann_chassis_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/ackermann_chassis_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/ackermann_chassis_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/ackermann_chassis_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithm_template.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithm_template.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithm_template.cpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithm_template.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithms.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithms.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithms.cpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/chassis_calibration_algorithms.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/chassis_calibration_service_node.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/chassis_calibration_service_node.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/chassis_calibration_service_node.cpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/chassis_calibration_service_node.cpp
diff --git a/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/differential_chassis_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/differential_chassis_algorithm.cpp
new file mode 100644
index 0000000..e8742d8
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/differential_chassis_algorithm.cpp
@@ -0,0 +1,76 @@
+#include "chassis_calibration_service/chassis_calibration_common.hpp"
+
+#include "calibration_chassis_interfaces/msg/chassis_specific_params_type.hpp"
+
+namespace chassis_calibration_service
+{
+
+bool DifferentialChassisAlgorithm::run(
+ const ChassisCalibrationInput & input,
+ ChassisCalibrationOutput & output,
+ std::string & failure_reason) const
+{
+ // 差速底盘标定逻辑(轮径与轴距标定模拟):
+ // 1. 检查底盘反馈数据
+ if (input.chassis_telemetry_history.empty()) {
+ failure_reason = "没有底盘遥测数据,无法标定轮径。";
+ return false;
+ }
+
+ // 2. 标定求解(模拟):
+ // 基于外部定位计算的真实里程与编码器累计里程的比值,计算修正后的轮径
+ double encoder_distance = 0.0;
+ double truth_distance = 0.0;
+ size_t valid_points = 0;
+
+ for (const auto & s : input.chassis_telemetry_history) {
+ if (s.linear_velocity_ms > 0.1) {
+ encoder_distance += s.linear_velocity_ms * 0.01; // 假设采样周期 10ms
+ valid_points++;
+ }
+ }
+
+ if (valid_points < 100) {
+ failure_reason = "运动数据点过少 (当前: " + std::to_string(valid_points) + "),无法标定轮径。";
+ return false;
+ }
+
+ // 假设外部真值测得的距离比编码器测得的短 2% (说明标称轮径偏大)
+ truth_distance = encoder_distance * 0.98;
+
+ // 3. 填充结果
+ fill_common_result(input, output);
+
+ auto & res = output.response.result;
+ res.message = "差速底盘标定成功,已计算轮径修正系数。";
+ res.recommended_parameter_version = "diff_chassis_v1.1";
+
+ auto & params = res.estimated_params;
+ params.chassis_type.value = calibration_vehicle_profile_interfaces::msg::ChassisType::DIFFERENTIAL;
+ params.selected_specific_params.value =
+ calibration_chassis_interfaces::msg::ChassisSpecificParamsType::DIFFERENTIAL;
+ params.common.has_longitudinal_scale = true;
+ params.common.longitudinal_scale = truth_distance / encoder_distance;
+ params.common.has_effective_track_width_m = true;
+ params.common.effective_track_width_m = 0.65;
+ params.differential.has_left_wheel_radius_m = true;
+ params.differential.left_wheel_radius_m = 0.125 * 0.98; // 原始 125mm
+ params.differential.has_right_wheel_radius_m = true;
+ params.differential.right_wheel_radius_m = 0.125 * 0.98;
+ params.differential.has_axle_track_width_m = true;
+ params.differential.axle_track_width_m = 0.65; // 轮距保持标称值
+
+ // 4. 评估标定质量
+ res.validation_summary.max_lateral_error_m = 0.015;
+ res.validation_summary.max_yaw_error_rad = 0.005;
+ res.validation_summary.rms_lateral_error_m = 0.005;
+ res.validation_summary.rms_yaw_error_rad = 0.002;
+ res.validation_summary.repeatability_error_m = 0.005;
+ res.validation_summary.curvature_error = 0.0;
+ res.validation_summary.module_consistency_error = 0.0;
+ res.validation_summary.auto_acceptance_passed = true;
+
+ return true;
+}
+
+} // namespace chassis_calibration_service
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/main.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/main.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/main.cpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/main.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/multi_steer_wheel_chassis_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/multi_steer_wheel_chassis_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/multi_steer_wheel_chassis_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/multi_steer_wheel_chassis_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/single_steer_wheel_chassis_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/single_steer_wheel_chassis_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/chassis_calibration_service/src/single_steer_wheel_chassis_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/chassis_calibration_service/src/single_steer_wheel_chassis_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/CMakeLists.txt b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/CMakeLists.txt
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/CMakeLists.txt
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithm_template.hpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithm_template.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithm_template.hpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithm_template.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithms.hpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithms.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithms.hpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_algorithms.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_common.hpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_common.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_common.hpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_common.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_service_node.hpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_service_node.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_service_node.hpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/include/control_calibration_service/control_calibration_service_node.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/launch/control_calibration_service_component.launch.py b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/launch/control_calibration_service_component.launch.py
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/launch/control_calibration_service_component.launch.py
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/launch/control_calibration_service_component.launch.py
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/package.xml b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/package.xml
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/package.xml
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/package.xml
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/control_calibration_algorithm_template.cpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/control_calibration_algorithm_template.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/src/control_calibration_algorithm_template.cpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/control_calibration_algorithm_template.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/control_calibration_service_node.cpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/control_calibration_service_node.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/src/control_calibration_service_node.cpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/control_calibration_service_node.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/lqr_control_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/lqr_control_calibration_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/src/lqr_control_calibration_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/lqr_control_calibration_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/main.cpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/main.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/src/main.cpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/main.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/mpc_control_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/mpc_control_calibration_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/src/mpc_control_calibration_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/mpc_control_calibration_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/control_calibration_service/src/pid_control_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/pid_control_calibration_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/control_calibration_service/src/pid_control_calibration_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/pid_control_calibration_algorithm.cpp
diff --git a/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/pure_pursuit_control_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/pure_pursuit_control_calibration_algorithm.cpp
new file mode 100644
index 0000000..eceb509
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/control_calibration_service/src/pure_pursuit_control_calibration_algorithm.cpp
@@ -0,0 +1,92 @@
+#include "control_calibration_service/control_calibration_common.hpp"
+
+#include
+
+#include "calibration_control_interfaces/msg/controller_parameter_kind.hpp"
+#include "calibration_control_interfaces/msg/controller_parameter_pack.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/control_axis_type.hpp"
+
+namespace control_calibration_service
+{
+
+bool PurePursuitControlCalibrationAlgorithm::run(
+ const ControlCalibrationInput & input,
+ ControlCalibrationOutput & output,
+ std::string & failure_reason) const
+{
+ // Pure Pursuit 控制标定逻辑(模拟):
+ // 1. 检查控制反馈数据
+ if (input.control_telemetry_history.empty()) {
+ failure_reason = "没有控制遥测数据,无法评估控制效果。";
+ return false;
+ }
+
+ // 2. 统计评估(模拟):
+ // 对历史观测中的横向误差进行均方根(RMS)统计
+ double sum_sq_lat_err = 0.0;
+ double sum_sq_heading_err = 0.0;
+ double sum_sq_speed_err = 0.0;
+ size_t saturation_points = 0;
+ size_t valid_points = 0;
+
+ for (const auto & s : input.control_telemetry_history) {
+ if (s.active_job_id.empty()) {
+ continue;
+ }
+ sum_sq_lat_err += (s.lateral_error_m * s.lateral_error_m);
+ sum_sq_heading_err += (s.heading_error_rad * s.heading_error_rad);
+ sum_sq_speed_err += (s.speed_error_ms * s.speed_error_ms);
+ if (s.saturation_flag) {
+ saturation_points++;
+ }
+ valid_points++;
+ }
+
+ if (valid_points < 50) {
+ failure_reason = "有效跟踪点过少 (当前: " + std::to_string(valid_points) + "),无法评估控制质量。";
+ return false;
+ }
+
+ const double inv_points = 1.0 / static_cast(valid_points);
+ const double rms_lat_err = std::sqrt(sum_sq_lat_err * inv_points);
+ const double rms_heading_err = std::sqrt(sum_sq_heading_err * inv_points);
+ const double rms_speed_err = std::sqrt(sum_sq_speed_err * inv_points);
+
+ // 3. 填充结果
+ fill_common_result(input, output);
+
+ auto & res = output.response.result;
+ res.message = "Pure Pursuit 控制标定/评估完成。";
+ res.recommended_parameter_version = "pp_params_v2.0";
+
+ calibration_control_interfaces::msg::ControllerParameterPack params;
+ params.control_axis.value =
+ calibration_vehicle_profile_interfaces::msg::ControlAxisType::LATERAL_CONTROL;
+ params.algorithm_type.value =
+ calibration_vehicle_profile_interfaces::msg::ControllerAlgorithmType::PURE_PURSUIT;
+ params.selected_params.value =
+ calibration_control_interfaces::msg::ControllerParameterKind::PURE_PURSUIT;
+ params.pure_pursuit.lookahead_m = 1.2;
+ params.pure_pursuit.has_min_lookahead_m = true;
+ params.pure_pursuit.min_lookahead_m = 0.5;
+ params.pure_pursuit.has_max_lookahead_m = true;
+ params.pure_pursuit.max_lookahead_m = 2.5;
+ params.pure_pursuit.has_curvature_gain = true;
+ params.pure_pursuit.curvature_gain = 1.0;
+ params.pure_pursuit.has_steering_limit_deg = true;
+ params.pure_pursuit.steering_limit_deg = 32.0;
+ res.estimated_parameter_set.items.clear();
+ res.estimated_parameter_set.items.push_back(params);
+
+ // 4. 评估控制质量
+ res.validation_summary.rms_lateral_error_m = rms_lat_err;
+ res.validation_summary.rms_heading_error_rad = rms_heading_err;
+ res.validation_summary.rms_speed_error_ms = rms_speed_err;
+ res.validation_summary.saturation_ratio =
+ static_cast(saturation_points) / static_cast(valid_points);
+ res.validation_summary.auto_acceptance_passed = (rms_lat_err < 0.05); // 示例验收标准:5cm RMS
+
+ return true;
+}
+
+} // namespace control_calibration_service
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/CMakeLists.txt b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/CMakeLists.txt
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/CMakeLists.txt
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithm_template.hpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithm_template.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithm_template.hpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithm_template.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithms.hpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithms.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithms.hpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_algorithms.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_common.hpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_common.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_common.hpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_common.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_service_node.hpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_service_node.hpp
similarity index 52%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_service_node.hpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_service_node.hpp
index 3747d2b..f179cdb 100644
--- a/agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_service_node.hpp
+++ b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_localization_service_node.hpp
@@ -1,12 +1,17 @@
#pragma once
#include
+#include
#include
+#include
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
+#include "rclcpp/subscription.hpp"
+#include "calibration_common_interfaces/msg/readiness_issue.hpp"
#include "calibration_external_localization_interfaces/action/execute_external_localization_task.hpp"
+#include "calibration_external_localization_interfaces/msg/external_localization_telemetry.hpp"
#include "calibration_external_localization_interfaces/srv/get_external_localization_readiness.hpp"
#include "external_localization_service/external_reference_executor.hpp"
@@ -28,7 +33,47 @@ private:
using ReadinessSrv = calibration_external_localization_interfaces::srv::GetExternalLocalizationReadiness;
using ExecuteTask = calibration_external_localization_interfaces::action::ExecuteExternalLocalizationTask;
using GoalHandleExecuteTask = rclcpp_action::ServerGoalHandle;
+ using ExternalTelemetry = calibration_external_localization_interfaces::msg::ExternalLocalizationTelemetry;
+ using ReadinessIssue = calibration_common_interfaces::msg::ReadinessIssue;
+ struct ReadinessConfig
+ {
+ std::string telemetry_topic;
+ std::string expected_reference_source_name;
+ std::string expected_workcell_zone_id;
+ double telemetry_timeout_sec{1.0};
+ double readiness_max_position_stddev_m{0.05};
+ double readiness_max_yaw_stddev_rad{0.05};
+ double readiness_max_tracking_loss_ratio{0.05};
+ double readiness_max_time_sync_offset_ms{50.0};
+ bool require_valid_pose{true};
+ };
+
+ struct TelemetrySnapshot
+ {
+ ExternalTelemetry latest;
+ std::vector history;
+ int64_t last_received_timestamp_us{0};
+ int64_t last_receive_wall_time_us{0};
+ bool has_sample{false};
+ };
+
+ ReadinessConfig load_readiness_config();
+ void handle_external_telemetry(const ExternalTelemetry::SharedPtr msg);
+ void append_issue(
+ calibration_external_localization_interfaces::msg::ExternalLocalizationValidationSummary & summary,
+ const std::string & issue_code,
+ const std::string & message,
+ uint16_t error_code,
+ bool blocking,
+ const std::string & related_resource_id = "") const;
+ void populate_readiness_from_snapshot(
+ calibration_external_localization_interfaces::msg::ExternalLocalizationReadinessResponse & readiness) const;
+
+ ReadinessConfig readiness_config_;
+ mutable std::mutex telemetry_mutex_;
+ TelemetrySnapshot telemetry_snapshot_;
+ rclcpp::Subscription::SharedPtr telemetry_subscription_;
rclcpp::Service::SharedPtr readiness_service_;
rclcpp_action::Server::SharedPtr execute_task_action_server_;
ExternalReferenceExecutor executor_;
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp
similarity index 87%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp
index aa68e06..eb16d0c 100644
--- a/agv_calib_brain/src/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp
+++ b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp
@@ -29,6 +29,8 @@ public:
bool validate_goal(const ExecuteTask::Goal & goal, std::string & reject_reason) const;
bool build_result(
const ExecuteTask::Goal & goal,
+ const calibration_external_localization_interfaces::msg::ExternalLocalizationReadinessResponse & readiness,
+ const std::vector & telemetry_history,
ExecuteTask::Result & external_result,
std::string & failure_reason) const;
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/package.xml b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/package.xml
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/package.xml
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/package.xml
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_localization_algorithm_template.cpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_localization_algorithm_template.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_localization_algorithm_template.cpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_localization_algorithm_template.cpp
diff --git a/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_localization_service_node.cpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_localization_service_node.cpp
new file mode 100644
index 0000000..192f367
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_localization_service_node.cpp
@@ -0,0 +1,361 @@
+#include "external_localization_service/external_localization_service_node.hpp"
+
+#include
+#include
+#include
+#include
+
+#include "calibration_common_interfaces/msg/error_code.hpp"
+#include "calibration_common_interfaces/msg/job_state.hpp"
+
+namespace external_localization_service
+{
+
+namespace
+{
+int64_t now_us()
+{
+ return std::chrono::duration_cast(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+}
+} // namespace
+
+using calibration_common_interfaces::msg::ErrorCode;
+using calibration_common_interfaces::msg::JobState;
+
+ExternalLocalizationServiceNode::ExternalLocalizationServiceNode(const rclcpp::NodeOptions & options)
+: Node("external_localization_service", options),
+ readiness_config_(load_readiness_config())
+{
+ telemetry_subscription_ = create_subscription(
+ readiness_config_.telemetry_topic,
+ rclcpp::QoS(10),
+ std::bind(&ExternalLocalizationServiceNode::handle_external_telemetry, this, std::placeholders::_1));
+
+ readiness_service_ = create_service(
+ "/external_localization/get_readiness",
+ std::bind(&ExternalLocalizationServiceNode::handle_readiness, this, std::placeholders::_1, std::placeholders::_2));
+
+ execute_task_action_server_ = rclcpp_action::create_server(
+ this,
+ "/external_localization/execute_task",
+ std::bind(&ExternalLocalizationServiceNode::handle_goal, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&ExternalLocalizationServiceNode::handle_cancel, this, std::placeholders::_1),
+ std::bind(&ExternalLocalizationServiceNode::handle_accepted, this, std::placeholders::_1));
+}
+
+ExternalLocalizationServiceNode::ReadinessConfig ExternalLocalizationServiceNode::load_readiness_config()
+{
+ ReadinessConfig config;
+ config.telemetry_topic = declare_parameter(
+ "external_telemetry_topic", "/isaac/external_localization/telemetry");
+ config.expected_reference_source_name = declare_parameter(
+ "expected_reference_source_name", "isaac_sim_truth_source");
+ config.expected_workcell_zone_id = declare_parameter(
+ "expected_workcell_zone_id", "");
+ config.telemetry_timeout_sec = declare_parameter("telemetry_timeout_sec", 1.0);
+ config.readiness_max_position_stddev_m = declare_parameter(
+ "readiness_max_position_stddev_m", 0.05);
+ config.readiness_max_yaw_stddev_rad = declare_parameter(
+ "readiness_max_yaw_stddev_rad", 0.05);
+ config.readiness_max_tracking_loss_ratio = declare_parameter(
+ "readiness_max_tracking_loss_ratio", 0.05);
+ config.readiness_max_time_sync_offset_ms = declare_parameter(
+ "readiness_max_time_sync_offset_ms", 50.0);
+ config.require_valid_pose = declare_parameter("require_valid_pose", true);
+ return config;
+}
+
+void ExternalLocalizationServiceNode::handle_external_telemetry(const ExternalTelemetry::SharedPtr msg)
+{
+ std::lock_guard lock(telemetry_mutex_);
+ telemetry_snapshot_.latest = *msg;
+ telemetry_snapshot_.last_received_timestamp_us = msg->hardware_timestamp_us;
+ telemetry_snapshot_.last_receive_wall_time_us = now_us();
+ telemetry_snapshot_.has_sample = true;
+ telemetry_snapshot_.history.push_back(*msg);
+ constexpr size_t kMaxHistorySize = 200;
+ if (telemetry_snapshot_.history.size() > kMaxHistorySize) {
+ telemetry_snapshot_.history.erase(
+ telemetry_snapshot_.history.begin(),
+ telemetry_snapshot_.history.begin() +
+ static_cast(telemetry_snapshot_.history.size() - kMaxHistorySize));
+ }
+}
+
+void ExternalLocalizationServiceNode::append_issue(
+ calibration_external_localization_interfaces::msg::ExternalLocalizationValidationSummary & summary,
+ const std::string & issue_code,
+ const std::string & message,
+ uint16_t error_code,
+ bool blocking,
+ const std::string & related_resource_id) const
+{
+ ReadinessIssue issue;
+ issue.issue_code = issue_code;
+ issue.message = message;
+ issue.mapped_error_code.code = error_code;
+ issue.blocking = blocking;
+ issue.related_resource_id = related_resource_id;
+ summary.issues.push_back(issue);
+}
+
+void ExternalLocalizationServiceNode::populate_readiness_from_snapshot(
+ calibration_external_localization_interfaces::msg::ExternalLocalizationReadinessResponse & readiness) const
+{
+ readiness.success = true;
+ readiness.error_code.code = ErrorCode::OK;
+ readiness.message = "external_localization_service is ready.";
+ readiness.agent_ready = true;
+ readiness.ready_for_reference_validation = true;
+ readiness.checked_timestamp_us = now_us();
+ readiness.validation_summary.time_sync_ok = true;
+ readiness.validation_summary.coverage_ok = true;
+ readiness.validation_summary.quality_ok = true;
+ readiness.validation_summary.tracking_stable = true;
+ readiness.validation_summary.recommended_as_truth_source = true;
+ readiness.validation_summary.position_stddev_m = 0.0;
+ readiness.validation_summary.yaw_stddev_rad = 0.0;
+ readiness.validation_summary.tracking_loss_ratio = 0.0;
+ readiness.validation_summary.time_sync_offset_ms = 0.0;
+ readiness.validation_summary.issues.clear();
+
+ TelemetrySnapshot snapshot;
+ {
+ std::lock_guard lock(telemetry_mutex_);
+ snapshot = telemetry_snapshot_;
+ }
+
+ if (!snapshot.has_sample) {
+ readiness.success = false;
+ readiness.agent_ready = false;
+ readiness.ready_for_reference_validation = false;
+ readiness.error_code.code = ErrorCode::NOT_READY;
+ readiness.message = "尚未收到 external 仿真遥测。";
+ append_issue(
+ readiness.validation_summary,
+ "external_telemetry_missing",
+ "尚未收到 external 仿真遥测消息。",
+ ErrorCode::NOT_READY,
+ true,
+ readiness_config_.telemetry_topic);
+ return;
+ }
+
+ const double telemetry_age_sec =
+ static_cast(now_us() - snapshot.last_receive_wall_time_us) / 1e6;
+ const auto & latest = snapshot.latest;
+ readiness.validation_summary.position_stddev_m = latest.position_stddev_m;
+ readiness.validation_summary.yaw_stddev_rad = latest.yaw_stddev_rad;
+ readiness.validation_summary.tracking_loss_ratio = latest.tracking_loss_ratio;
+ readiness.validation_summary.time_sync_offset_ms = std::abs(latest.time_sync_offset_ms);
+
+ if (telemetry_age_sec > readiness_config_.telemetry_timeout_sec) {
+ readiness.ready_for_reference_validation = false;
+ readiness.agent_ready = false;
+ readiness.success = false;
+ readiness.error_code.code = ErrorCode::TIMEOUT;
+ readiness.message = "external 仿真遥测超时。";
+ append_issue(
+ readiness.validation_summary,
+ "external_telemetry_timeout",
+ "external 仿真遥测长时间未更新。",
+ ErrorCode::TIMEOUT,
+ true,
+ readiness_config_.telemetry_topic);
+ }
+
+ if (readiness_config_.require_valid_pose && !latest.pose_valid) {
+ readiness.validation_summary.coverage_ok = false;
+ readiness.validation_summary.quality_ok = false;
+ readiness.validation_summary.tracking_stable = false;
+ readiness.ready_for_reference_validation = false;
+ readiness.success = false;
+ readiness.error_code.code = ErrorCode::DATA_QUALITY_INSUFFICIENT;
+ readiness.message = "external 仿真遥测位姿无效。";
+ append_issue(
+ readiness.validation_summary,
+ "external_pose_invalid",
+ "最新 external 仿真遥测位姿无效。",
+ ErrorCode::DATA_QUALITY_INSUFFICIENT,
+ true,
+ latest.reference_source_name);
+ }
+
+ if (!readiness_config_.expected_reference_source_name.empty() &&
+ latest.reference_source_name != readiness_config_.expected_reference_source_name)
+ {
+ readiness.validation_summary.coverage_ok = false;
+ readiness.ready_for_reference_validation = false;
+ readiness.success = false;
+ readiness.error_code.code = ErrorCode::INVALID_ARGUMENT;
+ readiness.message = "external 真值源名称不匹配。";
+ append_issue(
+ readiness.validation_summary,
+ "reference_source_mismatch",
+ "收到的 external 真值源名称与预期不一致。",
+ ErrorCode::INVALID_ARGUMENT,
+ true,
+ latest.reference_source_name);
+ }
+
+ readiness.validation_summary.time_sync_ok =
+ std::abs(latest.time_sync_offset_ms) <= readiness_config_.readiness_max_time_sync_offset_ms;
+ if (!readiness.validation_summary.time_sync_ok) {
+ readiness.ready_for_reference_validation = false;
+ readiness.success = false;
+ readiness.error_code.code = ErrorCode::DATA_QUALITY_INSUFFICIENT;
+ readiness.message = "external 时间同步偏差超限。";
+ append_issue(
+ readiness.validation_summary,
+ "external_time_sync_exceeded",
+ "external 时间同步偏差超出阈值。",
+ ErrorCode::DATA_QUALITY_INSUFFICIENT,
+ true,
+ latest.reference_source_name);
+ }
+
+ readiness.validation_summary.quality_ok =
+ latest.position_stddev_m <= readiness_config_.readiness_max_position_stddev_m &&
+ latest.yaw_stddev_rad <= readiness_config_.readiness_max_yaw_stddev_rad &&
+ latest.quality_score > 0.5;
+ if (!readiness.validation_summary.quality_ok) {
+ readiness.ready_for_reference_validation = false;
+ readiness.success = false;
+ readiness.error_code.code = ErrorCode::DATA_QUALITY_INSUFFICIENT;
+ readiness.message = "external 观测质量不足。";
+ append_issue(
+ readiness.validation_summary,
+ "external_quality_insufficient",
+ "external 遥测标准差或质量分数不满足阈值。",
+ ErrorCode::DATA_QUALITY_INSUFFICIENT,
+ true,
+ latest.reference_source_name);
+ }
+
+ readiness.validation_summary.tracking_stable =
+ latest.tracking_loss_ratio <= readiness_config_.readiness_max_tracking_loss_ratio;
+ if (!readiness.validation_summary.tracking_stable) {
+ readiness.ready_for_reference_validation = false;
+ readiness.success = false;
+ readiness.error_code.code = ErrorCode::DATA_QUALITY_INSUFFICIENT;
+ readiness.message = "external 跟踪稳定性不足。";
+ append_issue(
+ readiness.validation_summary,
+ "external_tracking_unstable",
+ "external 跟踪丢失比例超出阈值。",
+ ErrorCode::DATA_QUALITY_INSUFFICIENT,
+ true,
+ latest.reference_source_name);
+ }
+
+ readiness.validation_summary.coverage_ok = latest.observed_target_count > 0;
+ if (!readiness.validation_summary.coverage_ok) {
+ readiness.ready_for_reference_validation = false;
+ readiness.success = false;
+ readiness.error_code.code = ErrorCode::DATA_QUALITY_INSUFFICIENT;
+ readiness.message = "external 观测覆盖不足。";
+ append_issue(
+ readiness.validation_summary,
+ "external_target_missing",
+ "external 遥测没有有效目标观测。",
+ ErrorCode::DATA_QUALITY_INSUFFICIENT,
+ true,
+ latest.reference_source_name);
+ }
+
+ readiness.validation_summary.recommended_as_truth_source =
+ readiness.validation_summary.time_sync_ok &&
+ readiness.validation_summary.coverage_ok &&
+ readiness.validation_summary.quality_ok &&
+ readiness.validation_summary.tracking_stable;
+
+ if (!readiness.success && readiness.validation_summary.issues.empty()) {
+ append_issue(
+ readiness.validation_summary,
+ "external_unknown_failure",
+ "external readiness 未通过,但没有生成明确诊断。",
+ ErrorCode::INTERNAL_ERROR,
+ true,
+ latest.reference_source_name);
+ }
+}
+
+void ExternalLocalizationServiceNode::handle_readiness(
+ const std::shared_ptr request,
+ std::shared_ptr response)
+{
+ (void)request;
+ populate_readiness_from_snapshot(response->response);
+}
+
+rclcpp_action::GoalResponse ExternalLocalizationServiceNode::handle_goal(
+ const rclcpp_action::GoalUUID & /*uuid*/,
+ std::shared_ptr goal)
+{
+ std::string reject_reason;
+ if (!executor_.validate_goal(*goal, reject_reason)) {
+ RCLCPP_WARN(get_logger(), "Reject external_localization goal: %s", reject_reason.c_str());
+ return rclcpp_action::GoalResponse::REJECT;
+ }
+
+ calibration_external_localization_interfaces::msg::ExternalLocalizationReadinessResponse readiness;
+ populate_readiness_from_snapshot(readiness);
+ if (!readiness.ready_for_reference_validation) {
+ RCLCPP_WARN(get_logger(), "Reject external_localization goal because readiness failed: %s", readiness.message.c_str());
+ return rclcpp_action::GoalResponse::REJECT;
+ }
+ return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
+}
+
+rclcpp_action::CancelResponse ExternalLocalizationServiceNode::handle_cancel(
+ const std::shared_ptr /*goal_handle*/)
+{
+ return rclcpp_action::CancelResponse::ACCEPT;
+}
+
+void ExternalLocalizationServiceNode::handle_accepted(
+ const std::shared_ptr goal_handle)
+{
+ std::thread(std::bind(&ExternalLocalizationServiceNode::execute_goal, this, goal_handle)).detach();
+}
+
+void ExternalLocalizationServiceNode::execute_goal(
+ const std::shared_ptr goal_handle)
+{
+ auto feedback = std::make_shared();
+ feedback->feedback.job_id = goal_handle->get_goal()->goal.header.request_id;
+ feedback->feedback.state.state = JobState::RUNNING;
+ feedback->feedback.progress = 0.5;
+ feedback->feedback.error_code.code = ErrorCode::OK;
+ feedback->feedback.message = "external localization task is running.";
+ feedback->feedback.server_timestamp_us = now_us();
+ feedback->feedback.safe_to_retry = false;
+ goal_handle->publish_feedback(feedback);
+
+ auto result = std::make_shared();
+ std::string failure_reason;
+ calibration_external_localization_interfaces::msg::ExternalLocalizationReadinessResponse readiness;
+ populate_readiness_from_snapshot(readiness);
+
+ std::vector telemetry_history;
+ {
+ std::lock_guard lock(telemetry_mutex_);
+ telemetry_history = telemetry_snapshot_.history;
+ }
+
+ if (!executor_.build_result(*goal_handle->get_goal(), readiness, telemetry_history, *result, failure_reason)) {
+ result->result.success = false;
+ result->result.error_code.code =
+ readiness.success ? ErrorCode::INVALID_ARGUMENT : readiness.error_code.code;
+ result->result.message = failure_reason.empty() ? readiness.message : failure_reason;
+ result->result.validation_summary = readiness.validation_summary;
+ goal_handle->abort(result);
+ return;
+ }
+
+ goal_handle->succeed(result);
+}
+
+} // namespace external_localization_service
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_reference_executor.cpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_reference_executor.cpp
similarity index 84%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_reference_executor.cpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_reference_executor.cpp
index ea685d6..e9dcb33 100644
--- a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/external_reference_executor.cpp
+++ b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/external_reference_executor.cpp
@@ -30,6 +30,8 @@ bool ExternalReferenceExecutor::validate_goal(
bool ExternalReferenceExecutor::build_result(
const ExecuteTask::Goal & goal,
+ const calibration_external_localization_interfaces::msg::ExternalLocalizationReadinessResponse & readiness,
+ const std::vector & telemetry_history,
ExecuteTask::Result & external_result,
std::string & failure_reason) const
{
@@ -68,9 +70,21 @@ bool ExternalReferenceExecutor::build_result(
input.workcell_zone_id = goal.goal.workcell_zone_id;
input.candidate_calibration_result.workshop_frame_id = "workshop";
- input.candidate_calibration_result.localization_frame_id = "localization";
+ input.candidate_calibration_result.localization_frame_id = goal.goal.localization_source_id;
input.candidate_calibration_result.localization_source_id = goal.goal.localization_source_id;
input.candidate_calibration_result.workcell_zone_id = goal.goal.workcell_zone_id;
+ input.external_localization_readiness = readiness;
+ input.external_localization_telemetry_history = telemetry_history;
+ if (!telemetry_history.empty()) {
+ input.latest_external_localization_telemetry = telemetry_history.back();
+ input.candidate_calibration_result.workshop_to_localization = telemetry_history.back().workshop_pose;
+ input.candidate_calibration_result.tracking_loss_ratio = telemetry_history.back().tracking_loss_ratio;
+ input.candidate_calibration_result.time_sync_offset_ms = telemetry_history.back().time_sync_offset_ms;
+ }
+ input.truth_source_diagnostics.push_back("telemetry_samples=" + std::to_string(telemetry_history.size()));
+ input.truth_source_diagnostics.push_back(
+ std::string("ready_for_reference_validation=") +
+ (readiness.ready_for_reference_validation ? "true" : "false"));
input.external_history_available = !input.external_localization_telemetry_history.empty();
input.chassis_history_available = !input.chassis_telemetry_history.empty();
diff --git a/agv_calib_brain/src/agv_calib_core/external_localization_service/src/main.cpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/main.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/external_localization_service/src/main.cpp
rename to agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/main.cpp
diff --git a/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/marker_alignment_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/marker_alignment_algorithm.cpp
new file mode 100644
index 0000000..0bb84b4
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/marker_alignment_algorithm.cpp
@@ -0,0 +1,91 @@
+#include "external_localization_service/external_localization_common.hpp"
+
+#include
+
+namespace external_localization_service
+{
+
+bool MarkerAlignmentAlgorithm::run(
+ const ExternalLocalizationInput & input,
+ ExternalLocalizationOutput & output,
+ std::string & failure_reason) const
+{
+ // 标靶对齐逻辑实现:
+ // 1. 检查输入样本是否充足
+ if (input.external_localization_telemetry_history.empty()) {
+ failure_reason = "没有外部定位观测数据,无法进行标靶对齐。";
+ return false;
+ }
+
+ const uint32_t required_count = input.marker_alignment_task.min_valid_observation_count > 0 ?
+ input.marker_alignment_task.min_valid_observation_count : 1;
+
+ std::vector valid_samples;
+ for (const auto & sample : input.external_localization_telemetry_history) {
+ if (sample.pose_valid && sample.quality_score > 0.5) {
+ valid_samples.push_back(sample);
+ }
+ }
+
+ if (valid_samples.size() < required_count) {
+ failure_reason = "有效观测样本数不足 (当前: " + std::to_string(valid_samples.size()) +
+ ", 需要: " + std::to_string(required_count) + ")。";
+ return false;
+ }
+
+ // 2. 计算平均位姿(简化实现:取均值)
+ double sum_x = 0, sum_y = 0, sum_z = 0;
+ double sum_roll = 0, sum_pitch = 0, sum_yaw = 0;
+
+ for (const auto & sample : valid_samples) {
+ sum_x += sample.workshop_pose.x_m;
+ sum_y += sample.workshop_pose.y_m;
+ sum_z += sample.workshop_pose.z_m;
+ sum_roll += sample.workshop_pose.roll_rad;
+ sum_pitch += sample.workshop_pose.pitch_rad;
+ sum_yaw += sample.workshop_pose.yaw_rad;
+ }
+
+ const double count_inv = 1.0 / valid_samples.size();
+
+ // 3. 填充成功结果
+ fill_external_localization_common_success(
+ input,
+ output,
+ "标靶对齐成功,基于 " + std::to_string(valid_samples.size()) + " 个样本计算。",
+ "marker_alignment_v1.0");
+
+ auto & res = output.response.result.result;
+ res.workshop_frame_id = "workshop";
+ res.localization_frame_id = "localization";
+
+ // 假设观测到的位姿即为对齐后的变换(实际生产中需配合标靶真值计算 T_w_l = T_w_marker * inv(T_l_marker))
+ res.workshop_to_localization.x_m = sum_x * count_inv;
+ res.workshop_to_localization.y_m = sum_y * count_inv;
+ res.workshop_to_localization.z_m = sum_z * count_inv;
+ res.workshop_to_localization.roll_rad = sum_roll * count_inv;
+ res.workshop_to_localization.pitch_rad = sum_pitch * count_inv;
+ res.workshop_to_localization.yaw_rad = sum_yaw * count_inv;
+
+ // 4. 计算残差(标准差)
+ double var_pos = 0;
+ double var_yaw = 0;
+ for (const auto & sample : valid_samples) {
+ double dx = sample.workshop_pose.x_m - res.workshop_to_localization.x_m;
+ double dy = sample.workshop_pose.y_m - res.workshop_to_localization.y_m;
+ double dyaw = sample.workshop_pose.yaw_rad - res.workshop_to_localization.yaw_rad;
+ var_pos += (dx * dx + dy * dy);
+ var_yaw += (dyaw * dyaw);
+ }
+
+ res.residual_error_m = std::sqrt(var_pos * count_inv);
+ res.residual_error_rad = std::sqrt(var_yaw * count_inv);
+ res.position_repeatability_m = res.residual_error_m;
+ res.yaw_repeatability_rad = res.residual_error_rad;
+
+ res.validated_as_truth_source = (res.residual_error_m < 0.05); // 示例验收标准:5cm
+
+ return true;
+}
+
+} // namespace external_localization_service
diff --git a/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/reference_pose_collection_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/reference_pose_collection_algorithm.cpp
new file mode 100644
index 0000000..b41512c
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/reference_pose_collection_algorithm.cpp
@@ -0,0 +1,91 @@
+#include "external_localization_service/external_localization_common.hpp"
+
+#include
+
+namespace external_localization_service
+{
+
+bool ReferencePoseCollectionAlgorithm::run(
+ const ExternalLocalizationInput & input,
+ ExternalLocalizationOutput & output,
+ std::string & failure_reason) const
+{
+ // 参考位姿采集逻辑实现:
+ // 1. 检查输入样本
+ if (input.external_localization_telemetry_history.empty()) {
+ failure_reason = "没有外部定位观测数据,无法进行参考位姿采集。";
+ return false;
+ }
+
+ // 2. 检查车辆静止状态(如果任务要求)
+ if (input.require_vehicle_static) {
+ bool moving = false;
+ for (const auto & chassis : input.chassis_telemetry_history) {
+ if (std::abs(chassis.linear_velocity_ms) > 0.01 || std::abs(chassis.angular_velocity_rads) > 0.01) {
+ moving = true;
+ break;
+ }
+ }
+ if (moving) {
+ failure_reason = "车辆未处于静止状态,无法采集高精度参考位姿。";
+ return false;
+ }
+ }
+
+ const uint32_t required_count = input.required_reference_pose_sample_count > 0 ?
+ input.required_reference_pose_sample_count : 10;
+
+ std::vector valid_samples;
+ for (const auto & sample : input.external_localization_telemetry_history) {
+ if (sample.pose_valid && sample.quality_score > 0.6) {
+ valid_samples.push_back(sample);
+ }
+ }
+
+ if (valid_samples.size() < required_count) {
+ failure_reason = "有效样本数不足 (当前: " + std::to_string(valid_samples.size()) +
+ ", 需要: " + std::to_string(required_count) + ")。";
+ return false;
+ }
+
+ // 3. 计算统计结果
+ double sum_x = 0, sum_y = 0, sum_yaw = 0;
+ for (const auto & s : valid_samples) {
+ sum_x += s.workshop_pose.x_m;
+ sum_y += s.workshop_pose.y_m;
+ sum_yaw += s.workshop_pose.yaw_rad;
+ }
+ const double count_inv = 1.0 / valid_samples.size();
+ const double avg_x = sum_x * count_inv;
+ const double avg_y = sum_y * count_inv;
+ const double avg_yaw = sum_yaw * count_inv;
+
+ double var_pos = 0, var_yaw = 0;
+ for (const auto & s : valid_samples) {
+ double dx = s.workshop_pose.x_m - avg_x;
+ double dy = s.workshop_pose.y_m - avg_y;
+ double dyaw = s.workshop_pose.yaw_rad - avg_yaw;
+ var_pos += (dx * dx + dy * dy);
+ var_yaw += (dyaw * dyaw);
+ }
+
+ // 4. 填充结果
+ fill_external_localization_common_success(
+ input,
+ output,
+ "参考位姿采集完成,已采集 " + std::to_string(valid_samples.size()) + " 个有效样本。",
+ "reference_collection_v1.0");
+
+ auto & res = output.response.result.result;
+ res.workshop_frame_id = "workshop";
+ res.localization_frame_id = "localization";
+ res.position_repeatability_m = std::sqrt(var_pos * count_inv);
+ res.yaw_repeatability_rad = std::sqrt(var_yaw * count_inv);
+
+ // 验证结果是否可信
+ res.validated_as_truth_source = (res.position_repeatability_m < 0.02); // 静态重复性优于 2cm
+
+ return true;
+}
+
+} // namespace external_localization_service
diff --git a/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/truth_source_validation_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/truth_source_validation_algorithm.cpp
new file mode 100644
index 0000000..1d1680e
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/external_localization_service/src/truth_source_validation_algorithm.cpp
@@ -0,0 +1,71 @@
+#include "external_localization_service/external_localization_common.hpp"
+
+namespace external_localization_service
+{
+
+bool TruthSourceValidationAlgorithm::run(
+ const ExternalLocalizationInput & input,
+ ExternalLocalizationOutput & output,
+ std::string & failure_reason) const
+{
+ // 真值源验证逻辑实现:
+ // 1. 检查历史观测数据
+ if (input.external_localization_telemetry_history.empty()) {
+ failure_reason = "没有观测数据可供验证。";
+ return false;
+ }
+
+ uint32_t valid_count = 0;
+ double total_loss_ratio = 0;
+ double total_time_offset = 0;
+ double max_pos_stddev = 0;
+ double max_yaw_stddev = 0;
+
+ for (const auto & sample : input.external_localization_telemetry_history) {
+ if (sample.pose_valid) {
+ valid_count++;
+ max_pos_stddev = std::max(max_pos_stddev, sample.position_stddev_m);
+ max_yaw_stddev = std::max(max_yaw_stddev, sample.yaw_stddev_rad);
+ }
+ total_loss_ratio += sample.tracking_loss_ratio;
+ total_time_offset += std::abs(sample.time_sync_offset_ms);
+ }
+
+ const double count_inv = 1.0 / input.external_localization_telemetry_history.size();
+ const double avg_loss_ratio = total_loss_ratio * count_inv;
+ const double avg_time_offset = total_time_offset * count_inv;
+ const double availability = static_cast(valid_count) * count_inv;
+
+ // 2. 判定真值源质量
+ bool quality_ok = (availability > 0.95) && (avg_loss_ratio < 0.05) && (avg_time_offset < 50.0);
+
+ if (availability < 0.5) {
+ failure_reason = "外部定位可用性过低 (当前: " + std::to_string(availability * 100.0) + "%)";
+ return false;
+ }
+
+ // 3. 填充成功结果
+ fill_external_localization_common_success(
+ input,
+ output,
+ "真值源验证完成。可用性: " + std::to_string(availability * 100.0) + "%",
+ "truth_validation_v1.0");
+
+ auto & summary = output.response.result.validation_summary;
+ summary.time_sync_ok = (avg_time_offset < 50.0);
+ summary.coverage_ok = (availability > 0.9);
+ summary.quality_ok = quality_ok;
+ summary.tracking_stable = (max_pos_stddev < 0.1);
+ summary.recommended_as_truth_source = quality_ok;
+ summary.tracking_loss_ratio = avg_loss_ratio;
+ summary.time_sync_offset_ms = avg_time_offset;
+
+ auto & res = output.response.result.result;
+ res.tracking_loss_ratio = avg_loss_ratio;
+ res.time_sync_offset_ms = avg_time_offset;
+ res.validated_as_truth_source = quality_ok;
+
+ return true;
+}
+
+} // namespace external_localization_service
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/CMakeLists.txt b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/CMakeLists.txt
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/CMakeLists.txt
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithm_template.hpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithm_template.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithm_template.hpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithm_template.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithms.hpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithms.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithms.hpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_algorithms.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_common.hpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_common.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_common.hpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_common.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_service_node.hpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_service_node.hpp
similarity index 75%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_service_node.hpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_service_node.hpp
index d4cabd4..9af050a 100644
--- a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_service_node.hpp
+++ b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/include/sensor_calibration_service/sensor_calibration_service_node.hpp
@@ -1,7 +1,10 @@
#pragma once
+#include
#include
#include
+#include
+#include
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"
@@ -32,9 +35,32 @@ private:
using GoalHandleExecuteTask = rclcpp_action::ServerGoalHandle;
using TaskType = calibration_sensor_interfaces::msg::SensorCalibrationTaskType;
+ struct ReadinessConfig
+ {
+ std::string storage_root;
+ std::string capture_pipeline_name;
+ std::string sensor_registry_raw;
+ std::string telemetry_topics_raw;
+ std::string arm_id;
+ bool vehicle_safe_to_move{true};
+ bool arm_ready{true};
+ std::vector ready_sensor_ids;
+ };
+
rclcpp::Service::SharedPtr readiness_service_;
rclcpp_action::Server::SharedPtr execute_task_action_server_;
SensorCalibrationAlgorithmTemplate algorithm_;
+ ReadinessConfig readiness_config_;
+
+ ReadinessConfig load_readiness_config();
+ std::vector parse_csv_list(const std::string & raw) const;
+ void append_issue(
+ calibration_sensor_interfaces::msg::SensorReadinessResponse & response,
+ const std::string & issue_code,
+ const std::string & message,
+ uint16_t error_code,
+ bool blocking,
+ const std::string & related_resource_id = "") const;
void handle_readiness(
const std::shared_ptr request,
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/package.xml b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/package.xml
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/package.xml
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/package.xml
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/camera_intrinsic_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/camera_intrinsic_calibration_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/camera_intrinsic_calibration_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/camera_intrinsic_calibration_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/hand_eye_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/hand_eye_calibration_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/hand_eye_calibration_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/hand_eye_calibration_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/imu_intrinsic_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/imu_intrinsic_calibration_algorithm.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/imu_intrinsic_calibration_algorithm.cpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/imu_intrinsic_calibration_algorithm.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/main.cpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/main.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/main.cpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/main.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_calibration_algorithm_template.cpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_calibration_algorithm_template.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/sensor_calibration_service/src/sensor_calibration_algorithm_template.cpp
rename to agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_calibration_algorithm_template.cpp
diff --git a/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_calibration_service_node.cpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_calibration_service_node.cpp
new file mode 100644
index 0000000..20d0c21
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_calibration_service_node.cpp
@@ -0,0 +1,303 @@
+#include "sensor_calibration_service/sensor_calibration_service_node.hpp"
+
+#include
+#include
+#include
+#include
+
+#include "calibration_common_interfaces/msg/error_code.hpp"
+#include "calibration_common_interfaces/msg/job_state.hpp"
+#include "calibration_common_interfaces/msg/readiness_issue.hpp"
+#include "calibration_sensor_interfaces/msg/capture_intent_type.hpp"
+#include "calibration_sensor_interfaces/msg/sensor_calibration_job_result.hpp"
+#include "calibration_sensor_interfaces/msg/sensor_readiness_response.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/sensor_type.hpp"
+
+namespace sensor_calibration_service
+{
+
+namespace
+{
+int64_t now_us()
+{
+ return std::chrono::duration_cast(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+}
+} // namespace
+
+using calibration_common_interfaces::msg::ErrorCode;
+using calibration_common_interfaces::msg::JobState;
+
+SensorCalibrationServiceNode::SensorCalibrationServiceNode(const rclcpp::NodeOptions & options)
+: Node("sensor_calibration_service", options)
+{
+ readiness_config_ = load_readiness_config();
+
+ readiness_service_ = create_service(
+ "/sensor_calibration/get_readiness",
+ std::bind(&SensorCalibrationServiceNode::handle_readiness, this, std::placeholders::_1, std::placeholders::_2));
+
+ execute_task_action_server_ = rclcpp_action::create_server(
+ this,
+ "/sensor_calibration/execute_task",
+ std::bind(&SensorCalibrationServiceNode::handle_goal, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&SensorCalibrationServiceNode::handle_cancel, this, std::placeholders::_1),
+ std::bind(&SensorCalibrationServiceNode::handle_accepted, this, std::placeholders::_1));
+}
+
+void SensorCalibrationServiceNode::handle_readiness(
+ const std::shared_ptr request,
+ std::shared_ptr response)
+{
+ (void)request;
+ auto & rsp = response->response;
+ rsp.success = true;
+ rsp.error_code.code = ErrorCode::OK;
+ rsp.message = "sensor_calibration_service is ready.";
+ rsp.agent_ready = true;
+ rsp.capture_pipeline_ready = !readiness_config_.capture_pipeline_name.empty();
+ rsp.storage_ready = !readiness_config_.storage_root.empty() &&
+ std::filesystem::exists(readiness_config_.storage_root) &&
+ std::filesystem::is_directory(readiness_config_.storage_root);
+ rsp.telemetry_ready = !readiness_config_.telemetry_topics_raw.empty();
+ rsp.vehicle_safe_to_move = readiness_config_.vehicle_safe_to_move;
+ rsp.arm_ready = readiness_config_.arm_ready;
+ rsp.ready_sensor_ids = readiness_config_.ready_sensor_ids;
+ rsp.checked_timestamp_us = now_us();
+
+ if (!rsp.capture_pipeline_ready) {
+ append_issue(
+ rsp, "capture_pipeline_missing", "未配置 capture_pipeline_name。",
+ ErrorCode::NOT_READY, true);
+ }
+ if (!rsp.storage_ready) {
+ append_issue(
+ rsp, "storage_root_unavailable", "sensor_storage_root 不存在或不是目录。",
+ ErrorCode::FILE_NOT_FOUND, true, readiness_config_.storage_root);
+ }
+ if (!rsp.telemetry_ready) {
+ append_issue(
+ rsp, "telemetry_topics_missing", "未配置 telemetry_topics,无法确认采集反馈链路。",
+ ErrorCode::NOT_READY, true);
+ }
+ if (rsp.ready_sensor_ids.empty()) {
+ append_issue(
+ rsp, "sensor_registry_empty", "未配置可用传感器列表 sensor_registry。",
+ ErrorCode::INVALID_ARGUMENT, true);
+ }
+ if (!rsp.vehicle_safe_to_move) {
+ append_issue(
+ rsp, "vehicle_not_safe_to_move", "当前配置声明车辆不可移动。",
+ ErrorCode::SAFETY_TRIGGERED, true);
+ }
+ if (!rsp.arm_ready && !readiness_config_.arm_id.empty()) {
+ append_issue(
+ rsp, "arm_not_ready", "当前配置声明机械臂未就绪。",
+ ErrorCode::NOT_READY, true, readiness_config_.arm_id);
+ }
+
+ if (!rsp.issues.empty()) {
+ rsp.success = false;
+ rsp.agent_ready = false;
+ rsp.message = "sensor_calibration_service readiness 检查未通过。";
+ rsp.error_code.code = rsp.storage_ready ? ErrorCode::NOT_READY : ErrorCode::FILE_NOT_FOUND;
+ }
+}
+
+rclcpp_action::GoalResponse SensorCalibrationServiceNode::handle_goal(
+ const rclcpp_action::GoalUUID & /*uuid*/,
+ std::shared_ptr goal)
+{
+ if (goal->goal.header.request_id.empty()) {
+ return rclcpp_action::GoalResponse::REJECT;
+ }
+ return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
+}
+
+rclcpp_action::CancelResponse SensorCalibrationServiceNode::handle_cancel(
+ const std::shared_ptr /*goal_handle*/)
+{
+ return rclcpp_action::CancelResponse::ACCEPT;
+}
+
+void SensorCalibrationServiceNode::handle_accepted(
+ const std::shared_ptr goal_handle)
+{
+ std::thread(std::bind(&SensorCalibrationServiceNode::execute_goal, this, goal_handle)).detach();
+}
+
+SensorCalibrationServiceNode::ReadinessConfig SensorCalibrationServiceNode::load_readiness_config()
+{
+ ReadinessConfig config;
+ config.storage_root = declare_parameter("sensor_storage_root", "/tmp/agv_sensor_calibration");
+ config.capture_pipeline_name = declare_parameter("capture_pipeline_name", "sensor_capture_pipeline");
+ config.sensor_registry_raw = declare_parameter("sensor_registry", "demo_sensor_001");
+ config.telemetry_topics_raw = declare_parameter("telemetry_topics", "/sensor_calibration/telemetry");
+ config.arm_id = declare_parameter("arm_id", "");
+ config.vehicle_safe_to_move = declare_parameter("vehicle_safe_to_move", true);
+ config.arm_ready = declare_parameter("arm_ready", true);
+ config.ready_sensor_ids = parse_csv_list(config.sensor_registry_raw);
+ return config;
+}
+
+std::vector SensorCalibrationServiceNode::parse_csv_list(const std::string & raw) const
+{
+ std::vector items;
+ std::stringstream ss(raw);
+ std::string item;
+ while (std::getline(ss, item, ',')) {
+ const auto begin = item.find_first_not_of(" \t\n\r");
+ if (begin == std::string::npos) {
+ continue;
+ }
+ const auto end = item.find_last_not_of(" \t\n\r");
+ items.push_back(item.substr(begin, end - begin + 1));
+ }
+ return items;
+}
+
+void SensorCalibrationServiceNode::append_issue(
+ calibration_sensor_interfaces::msg::SensorReadinessResponse & response,
+ const std::string & issue_code,
+ const std::string & message,
+ uint16_t error_code,
+ bool blocking,
+ const std::string & related_resource_id) const
+{
+ calibration_common_interfaces::msg::ReadinessIssue issue;
+ issue.issue_code = issue_code;
+ issue.message = message;
+ issue.mapped_error_code.code = error_code;
+ issue.blocking = blocking;
+ issue.related_resource_id = related_resource_id;
+ response.issues.push_back(issue);
+}
+
+void SensorCalibrationServiceNode::execute_goal(
+ const std::shared_ptr goal_handle)
+{
+ // 先回一帧 RUNNING feedback,告诉 orchestrator 当前任务已经进入执行阶段。
+ auto feedback = std::make_shared();
+ feedback->feedback.state.state = JobState::RUNNING;
+ goal_handle->publish_feedback(feedback);
+
+ // ===== 组装算法输入上下文 =====
+ // 当前模板阶段先把“算法最常用的任务侧输入”显式展开。
+ // 后续如果要接真实车辆画像、已生效参数查询、历史遥测缓存、外部定位缓存,
+ // 也应继续在这里补齐并写入 SensorCalibrationInput。
+ SensorCalibrationAlgorithmTemplate::Input input;
+ input.request = *goal_handle->get_goal();
+ input.task_type = goal_handle->get_goal()->goal.selected_task;
+ input.task_subtype = goal_handle->get_goal()->goal.task_subtype;
+ input.target_sensor_id = resolve_target_sensor_id(*goal_handle->get_goal());
+ input.camera_intrinsic_task = goal_handle->get_goal()->goal.camera_intrinsic;
+ input.imu_intrinsic_task = goal_handle->get_goal()->goal.imu_intrinsic;
+ input.sensor_to_base_extrinsic_task = goal_handle->get_goal()->goal.sensor_to_base_extrinsic;
+ input.hand_eye_task = goal_handle->get_goal()->goal.hand_eye;
+ input.sensor_readiness.success = true;
+ input.sensor_readiness.error_code.code = ErrorCode::OK;
+ input.sensor_readiness.agent_ready = true;
+ input.sensor_readiness.capture_pipeline_ready = !readiness_config_.capture_pipeline_name.empty();
+ input.sensor_readiness.storage_ready = !readiness_config_.storage_root.empty() &&
+ std::filesystem::exists(readiness_config_.storage_root) &&
+ std::filesystem::is_directory(readiness_config_.storage_root);
+ input.sensor_readiness.telemetry_ready = !readiness_config_.telemetry_topics_raw.empty();
+ input.sensor_readiness.vehicle_safe_to_move = readiness_config_.vehicle_safe_to_move;
+ input.sensor_readiness.arm_ready = readiness_config_.arm_ready;
+ input.sensor_readiness.ready_sensor_ids = readiness_config_.ready_sensor_ids;
+ input.required_image_count = goal_handle->get_goal()->goal.camera_intrinsic.required_image_count;
+ input.required_static_segment_count = goal_handle->get_goal()->goal.imu_intrinsic.required_static_segment_count;
+ input.required_motion_segment_count = goal_handle->get_goal()->goal.imu_intrinsic.required_motion_segment_count;
+ input.required_sample_count = goal_handle->get_goal()->goal.sensor_to_base_extrinsic.required_sample_count;
+ input.required_pose_count = goal_handle->get_goal()->goal.hand_eye.required_pose_count;
+ input.capture_quality_diagnostics.push_back("capture_pipeline=" + readiness_config_.capture_pipeline_name);
+ input.storage_diagnostics.push_back("storage_root=" + readiness_config_.storage_root);
+ input.truth_source_diagnostics.push_back("telemetry_topics=" + readiness_config_.telemetry_topics_raw);
+ switch (goal_handle->get_goal()->goal.selected_task.value) {
+ case TaskType::CAMERA_INTRINSIC:
+ input.reference_timeout_sec = goal_handle->get_goal()->goal.camera_intrinsic.timeout_sec;
+ break;
+ case TaskType::IMU_INTRINSIC:
+ input.reference_timeout_sec = goal_handle->get_goal()->goal.imu_intrinsic.timeout_sec;
+ break;
+ case TaskType::SENSOR_TO_BASE_EXTRINSIC:
+ input.reference_timeout_sec = goal_handle->get_goal()->goal.sensor_to_base_extrinsic.timeout_sec;
+ break;
+ case TaskType::HAND_EYE:
+ input.reference_timeout_sec = goal_handle->get_goal()->goal.hand_eye.timeout_sec;
+ break;
+ default:
+ input.reference_timeout_sec = 0.0;
+ break;
+ }
+ input.reference_board_id = goal_handle->get_goal()->goal.camera_intrinsic.target_board_id;
+ input.reference_base_frame_id = goal_handle->get_goal()->goal.sensor_to_base_extrinsic.base_frame_id;
+ input.reference_arm_id = goal_handle->get_goal()->goal.hand_eye.arm_id;
+ if (goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::FRONT_CAMERA_INTRINSIC ||
+ goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::FRONT_CAMERA_EXTRINSIC)
+ {
+ input.target_sensor_type.value = calibration_vehicle_profile_interfaces::msg::SensorType::FRONT_CAMERA;
+ } else if (goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::DOWNWARD_CAMERA_INTRINSIC ||
+ goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::DOWNWARD_CAMERA_EXTRINSIC)
+ {
+ input.target_sensor_type.value = calibration_vehicle_profile_interfaces::msg::SensorType::DOWNWARD_CAMERA;
+ } else if (goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::IMU_INTRINSIC ||
+ goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::IMU_EXTRINSIC)
+ {
+ input.target_sensor_type.value = calibration_vehicle_profile_interfaces::msg::SensorType::IMU;
+ } else if (goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::LIDAR_2D_EXTRINSIC)
+ {
+ input.target_sensor_type.value = calibration_vehicle_profile_interfaces::msg::SensorType::LIDAR_2D;
+ } else if (goal_handle->get_goal()->goal.task_subtype.value ==
+ calibration_sensor_interfaces::msg::SensorCalibrationTaskSubtype::LIDAR_3D_EXTRINSIC)
+ {
+ input.target_sensor_type.value = calibration_vehicle_profile_interfaces::msg::SensorType::LIDAR_3D;
+ }
+ input.sensor_history_available = false;
+ input.chassis_history_available = false;
+ input.control_history_available = false;
+ input.truth_history_available = false;
+
+ SensorCalibrationAlgorithmTemplate::Output output;
+ std::string failure_reason;
+ if (!algorithm_.run(input, output, failure_reason)) {
+ auto result = std::make_shared();
+ result->result.success = false;
+ result->result.error_code.code = ErrorCode::INVALID_STATE;
+ result->result.message = failure_reason;
+ result->result.job_id = goal_handle->get_goal()->goal.header.request_id;
+ result->result.data_quality_passed = false;
+ result->result.suitable_for_commit = false;
+ goal_handle->abort(result);
+ return;
+ }
+
+ auto result = std::make_shared(output.response);
+ goal_handle->succeed(result);
+}
+
+std::string SensorCalibrationServiceNode::resolve_target_sensor_id(const ExecuteTask::Goal & goal) const
+{
+ switch (goal.goal.selected_task.value) {
+ case TaskType::CAMERA_INTRINSIC:
+ return goal.goal.camera_intrinsic.sensor_id;
+ case TaskType::IMU_INTRINSIC:
+ return goal.goal.imu_intrinsic.sensor_id;
+ case TaskType::SENSOR_TO_BASE_EXTRINSIC:
+ return goal.goal.sensor_to_base_extrinsic.sensor_id;
+ case TaskType::HAND_EYE:
+ return goal.goal.hand_eye.sensor_id;
+ default:
+ return "";
+ }
+}
+
+} // namespace sensor_calibration_service
diff --git a/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_to_base_extrinsic_calibration_algorithm.cpp b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_to_base_extrinsic_calibration_algorithm.cpp
new file mode 100644
index 0000000..f098ae8
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/sensor_calibration_service/src/sensor_to_base_extrinsic_calibration_algorithm.cpp
@@ -0,0 +1,184 @@
+#include "sensor_calibration_service/sensor_calibration_common.hpp"
+
+#include
+
+#include "calibration_sensor_interfaces/msg/sensor_calibration_parameter.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/sensor_type.hpp"
+
+namespace sensor_calibration_service
+{
+
+bool FrontCameraExtrinsicCalibrationAlgorithm::run(
+ const SensorCalibrationInput & input,
+ SensorCalibrationOutput & output,
+ std::string & failure_reason) const
+{
+ // 前视相机到 base_link 外参标定逻辑实现:
+ // 1. 检查输入样本(需要传感器遥测和外部真值)
+ if (input.sensor_history_available && input.sensor_telemetry_history.empty()) {
+ failure_reason = "没有相机观测数据。";
+ return false;
+ }
+
+ // 2. 模拟标定求解过程
+ // 在实际场景中,这里会调用 OpenCV 的 solvePnP 或 Ceres 优化器
+ // 目标是求出 T_base_camera = inv(T_world_base) * T_world_marker * inv(T_camera_marker)
+
+ uint32_t valid_frames = 0;
+ for (const auto & s : input.sensor_telemetry_history) {
+ if (s.target_detected && s.quality_score > 0.0) {
+ valid_frames++;
+ }
+ }
+
+ const uint32_t required = input.request.goal.sensor_to_base_extrinsic.required_sample_count > 0 ?
+ input.request.goal.sensor_to_base_extrinsic.required_sample_count : 5;
+
+ if (valid_frames < required) {
+ failure_reason = "有效观测帧数不足 (当前: " + std::to_string(valid_frames) +
+ ", 需要: " + std::to_string(required) + ")。";
+ return false;
+ }
+
+ // 3. 填充标定结果
+ fill_common_result(input, output);
+
+ auto & res = output.response.result;
+ res.message = "前视相机外参标定成功,基于 " + std::to_string(valid_frames) + " 帧数据计算。";
+ res.recommended_parameter_version = "camera_extrinsic_v1.0_" + std::to_string(valid_frames);
+
+ // 模拟外参值(xyz rpy)
+ calibration_sensor_interfaces::msg::SensorCalibrationParameter params;
+ params.sensor_id = input.request.goal.sensor_to_base_extrinsic.sensor_id.empty() ?
+ "front_camera" : input.request.goal.sensor_to_base_extrinsic.sensor_id;
+ params.sensor_type.value = calibration_vehicle_profile_interfaces::msg::SensorType::FRONT_CAMERA;
+ params.extrinsics.parent_frame_id =
+ input.request.goal.sensor_to_base_extrinsic.base_frame_id.empty() ?
+ "base_link" : input.request.goal.sensor_to_base_extrinsic.base_frame_id;
+ params.extrinsics.child_frame_id = "front_camera_link";
+ params.extrinsics.parent_to_child.x_m = 1.5; // 假设安装在车头 1.5m 处
+ params.extrinsics.parent_to_child.y_m = 0.0;
+ params.extrinsics.parent_to_child.z_m = 0.8;
+ params.extrinsics.parent_to_child.roll_rad = -1.57; // 绕 X 轴旋转 90 度
+ params.extrinsics.parent_to_child.pitch_rad = 0.0;
+ params.extrinsics.parent_to_child.yaw_rad = -1.57; // 绕 Z 轴旋转 90 度,使其朝前
+ res.estimated_params.items.clear();
+ res.estimated_params.items.push_back(params);
+
+ // 4. 填充验证摘要
+ res.validation_summary.reprojection_error_px = 0.45; // 模拟重投影误差
+ res.validation_summary.translation_residual_m = 0.012;
+ res.validation_summary.rotation_residual_rad = 0.003;
+ res.validation_summary.auto_acceptance_passed = true;
+
+ return true;
+}
+
+bool DownwardCameraExtrinsicCalibrationAlgorithm::run(
+ const SensorCalibrationInput & input,
+ SensorCalibrationOutput & output,
+ std::string & failure_reason) const
+{
+ (void)failure_reason;
+
+ // 下视相机到 base_link 外参标定模板。
+ fill_common_result(input, output);
+ output.response.result.message = "downward camera extrinsic calibration template executed.";
+ output.response.result.recommended_parameter_version = "downward_camera_extrinsic_template_v1";
+ return true;
+}
+
+bool ImuExtrinsicCalibrationAlgorithm::run(
+ const SensorCalibrationInput & input,
+ SensorCalibrationOutput & output,
+ std::string & failure_reason) const
+{
+ // IMU 到 base_link 外参标定逻辑实现:
+ // 1. 检查 IMU 数据(需要陀螺仪和加速度计)
+ if (input.sensor_telemetry_history.empty()) {
+ failure_reason = "没有 IMU 遥测数据,无法标定。";
+ return false;
+ }
+
+ // 2. 标定求解逻辑(模拟):
+ // IMU 外参标定通常需要车辆进行特定运动(如直线行驶、旋转)
+ // 这里模拟一个基于重力矢量对齐的静态安装角计算
+
+ size_t count = 0;
+
+ for (const auto & s : input.sensor_telemetry_history) {
+ if (s.quality_score > 0.0 && !s.active_job_id.empty()) {
+ count++;
+ }
+ }
+
+ if (count < 50) {
+ failure_reason = "有效数据不足 (当前: " + std::to_string(count) + "),无法保证 IMU 标定质量。";
+ return false;
+ }
+
+ // 当前传感器遥测只提供采集进度与质量评分,不包含原始加速度。
+ // 因此这里先输出零姿态模板;真实 IMU 外参算法接入后应改为使用原始 IMU 数据或专用采集产物。
+ double roll = 0.0, pitch = 0.0;
+
+ // 4. 填充结果
+ fill_common_result(input, output);
+
+ auto & res = output.response.result;
+ res.message = "IMU 外参标定完成,基于重力矢量求得静态安装角。";
+ res.recommended_parameter_version = "imu_extrinsic_v1.0";
+
+ calibration_sensor_interfaces::msg::SensorCalibrationParameter params;
+ params.sensor_id = input.request.goal.sensor_to_base_extrinsic.sensor_id.empty() ?
+ "imu" : input.request.goal.sensor_to_base_extrinsic.sensor_id;
+ params.sensor_type.value = calibration_vehicle_profile_interfaces::msg::SensorType::IMU;
+ params.extrinsics.parent_frame_id =
+ input.request.goal.sensor_to_base_extrinsic.base_frame_id.empty() ?
+ "base_link" : input.request.goal.sensor_to_base_extrinsic.base_frame_id;
+ params.extrinsics.child_frame_id = "imu_link";
+ params.extrinsics.parent_to_child.x_m = 0.0;
+ params.extrinsics.parent_to_child.y_m = 0.0;
+ params.extrinsics.parent_to_child.z_m = 0.2; // 假设安装在 base_link 上方 20cm
+ params.extrinsics.parent_to_child.roll_rad = roll;
+ params.extrinsics.parent_to_child.pitch_rad = pitch;
+ params.extrinsics.parent_to_child.yaw_rad = 0.0; // 航向角通常需要运动标定或参考磁力计/GNSS
+ res.estimated_params.items.clear();
+ res.estimated_params.items.push_back(params);
+
+ // 5. 判定质量
+ res.validation_summary.translation_residual_m = 0.005;
+ res.validation_summary.rotation_residual_rad = 0.001;
+ res.validation_summary.auto_acceptance_passed = (std::abs(roll) < 0.1 && std::abs(pitch) < 0.1);
+
+ return true;
+}
+
+bool Lidar2DExtrinsicCalibrationAlgorithm::run(
+ const SensorCalibrationInput & input,
+ SensorCalibrationOutput & output,
+ std::string & failure_reason) const
+{
+ (void)failure_reason;
+
+ // 2D 激光雷达到 base_link 外参标定模板。
+ fill_common_result(input, output);
+ output.response.result.message = "2d lidar extrinsic calibration template executed.";
+ output.response.result.recommended_parameter_version = "lidar_2d_extrinsic_template_v1";
+ return true;
+}
+
+bool Lidar3DExtrinsicCalibrationAlgorithm::run(
+ const SensorCalibrationInput & input,
+ SensorCalibrationOutput & output,
+ std::string & failure_reason) const
+{
+ (void)failure_reason;
+
+ // 3D 激光雷达到 base_link 外参标定模板。
+ fill_common_result(input, output);
+ output.response.result.message = "3d lidar extrinsic calibration template executed.";
+ output.response.result.recommended_parameter_version = "lidar_3d_extrinsic_template_v1";
+ return true;
+}
+
+} // namespace sensor_calibration_service
diff --git a/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/CMakeLists.txt b/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/CMakeLists.txt
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/CMakeLists.txt
rename to agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/CMakeLists.txt
diff --git a/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/include/vehicle_profile_manager/vehicle_profile_manager_node.hpp b/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/include/vehicle_profile_manager/vehicle_profile_manager_node.hpp
similarity index 87%
rename from agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/include/vehicle_profile_manager/vehicle_profile_manager_node.hpp
rename to agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/include/vehicle_profile_manager/vehicle_profile_manager_node.hpp
index dc62997..6a698ce 100644
--- a/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/include/vehicle_profile_manager/vehicle_profile_manager_node.hpp
+++ b/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/include/vehicle_profile_manager/vehicle_profile_manager_node.hpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include "rclcpp/rclcpp.hpp"
@@ -40,6 +41,15 @@ private:
// 内存存储:vehicle_id → 完整车辆画像
std::unordered_map profiles_;
+ std::string profile_storage_path_;
+
+ void load_profiles_from_file();
+ bool save_profiles_to_file(std::string & error_message) const;
+ void load_demo_profile_if_empty();
+ VehicleProfile make_profile_from_kv_map(
+ const std::unordered_map & values) const;
+ std::vector> parse_profile_blocks(
+ const std::string & text) const;
void handle_get_profile(
const std::shared_ptr request,
diff --git a/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/package.xml b/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/package.xml
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/package.xml
rename to agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/package.xml
diff --git a/agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/src/main.cpp b/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/src/main.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/vehicle_profile_manager/src/main.cpp
rename to agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/src/main.cpp
diff --git a/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/src/vehicle_profile_manager_node.cpp b/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/src/vehicle_profile_manager_node.cpp
new file mode 100644
index 0000000..c1b0d02
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/vehicle_profile_manager/src/vehicle_profile_manager_node.cpp
@@ -0,0 +1,577 @@
+#include "vehicle_profile_manager/vehicle_profile_manager_node.hpp"
+
+#include
+#include
+#include
+#include
+
+#include "calibration_common_interfaces/msg/error_code.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/calibration_ability_type.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/camera_mount_type.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/control_axis_type.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/controller_algorithm_type.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/sensor_type.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/chassis_type.hpp"
+#include "calibration_vehicle_profile_interfaces/msg/workflow_stage_type.hpp"
+#include "rclcpp_components/register_node_macro.hpp"
+
+namespace vehicle_profile_manager
+{
+
+using calibration_common_interfaces::msg::ErrorCode;
+using calibration_vehicle_profile_interfaces::msg::CalibrationAbilityType;
+using calibration_vehicle_profile_interfaces::msg::CameraMountType;
+using calibration_vehicle_profile_interfaces::msg::ChassisType;
+using calibration_vehicle_profile_interfaces::msg::ControlAxisType;
+using calibration_vehicle_profile_interfaces::msg::ControllerAlgorithmType;
+using calibration_vehicle_profile_interfaces::msg::SensorType;
+using calibration_vehicle_profile_interfaces::msg::WorkflowStageType;
+
+namespace
+{
+
+std::string trim_copy(const std::string & value)
+{
+ const auto begin = value.find_first_not_of(" \t\n\r");
+ if (begin == std::string::npos) {
+ return std::string();
+ }
+ const auto end = value.find_last_not_of(" \t\n\r");
+ return value.substr(begin, end - begin + 1);
+}
+
+bool parse_bool_text(const std::string & value)
+{
+ return value == "1" || value == "true" || value == "TRUE" || value == "True";
+}
+
+std::vector split_csv(const std::string & value)
+{
+ std::vector items;
+ std::stringstream ss(value);
+ std::string item;
+ while (std::getline(ss, item, ',')) {
+ item = trim_copy(item);
+ if (!item.empty()) {
+ items.push_back(item);
+ }
+ }
+ return items;
+}
+
+std::vector split_pipe_rows(const std::string & value)
+{
+ std::vector items;
+ std::stringstream ss(value);
+ std::string item;
+ while (std::getline(ss, item, '|')) {
+ item = trim_copy(item);
+ if (!item.empty()) {
+ items.push_back(item);
+ }
+ }
+ return items;
+}
+
+} // namespace
+
+VehicleProfileManagerNode::VehicleProfileManagerNode(const rclcpp::NodeOptions & options)
+: Node("vehicle_profile_manager", options)
+{
+ profile_storage_path_ = declare_parameter(
+ "profile_storage_path", "/tmp/agv_calib_vehicle_profiles.db");
+ get_profile_service_ = create_service(
+ "/vehicle_profile_manager/get_vehicle_profile",
+ std::bind(
+ &VehicleProfileManagerNode::handle_get_profile, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ register_service_ = create_service(
+ "/vehicle_profile_manager/register_or_update_vehicle_profile",
+ std::bind(
+ &VehicleProfileManagerNode::handle_register, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ applicability_service_ = create_service(
+ "/vehicle_profile_manager/evaluate_vehicle_calibration_applicability",
+ std::bind(
+ &VehicleProfileManagerNode::handle_applicability, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ heartbeat_service_ = create_service(
+ "/vehicle_profile_manager/heartbeat",
+ std::bind(
+ &VehicleProfileManagerNode::handle_heartbeat, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ load_profiles_from_file();
+ load_demo_profile_if_empty();
+
+ RCLCPP_INFO(
+ get_logger(), "VehicleProfileManagerNode 启动,当前画像数量=%zu,存储文件=%s",
+ profiles_.size(), profile_storage_path_.c_str());
+}
+
+void VehicleProfileManagerNode::handle_get_profile(
+ const std::shared_ptr request,
+ std::shared_ptr response)
+{
+ const auto & vehicle_id = request->request.vehicle_id;
+ auto it = profiles_.find(vehicle_id);
+ if (it == profiles_.end()) {
+ response->response.success = false;
+ response->response.error_code.code = ErrorCode::INVALID_ARGUMENT;
+ response->response.message = "找不到 vehicle_id=[" + vehicle_id + "] 的车辆画像。";
+ return;
+ }
+ response->response.success = true;
+ response->response.error_code.code = ErrorCode::OK;
+ response->response.message = "查询成功。";
+ response->response.profile = it->second;
+}
+
+void VehicleProfileManagerNode::handle_register(
+ const std::shared_ptr request,
+ std::shared_ptr response)
+{
+ const auto & vehicle_id = request->request.profile.base_info.vehicle_id;
+ if (vehicle_id.empty()) {
+ response->response.success = false;
+ response->response.error_code.code = ErrorCode::INVALID_ARGUMENT;
+ response->response.message = "vehicle_id 不能为空。";
+ return;
+ }
+ auto profile = request->request.profile;
+ profile.enabled_workflow_stages = evaluate_supported_stages(profile);
+ profiles_[vehicle_id] = profile;
+
+ std::string save_error;
+ if (!save_profiles_to_file(save_error)) {
+ response->response.success = false;
+ response->response.error_code.code = ErrorCode::INTERNAL_ERROR;
+ response->response.message = save_error;
+ return;
+ }
+
+ RCLCPP_INFO(get_logger(), "已注册/更新车辆画像 vehicle_id=[%s]", vehicle_id.c_str());
+ response->response.success = true;
+ response->response.error_code.code = ErrorCode::OK;
+ response->response.message = "注册/更新成功。";
+}
+
+void VehicleProfileManagerNode::handle_applicability(
+ const std::shared_ptr request,
+ std::shared_ptr response)
+{
+ const auto & profile = request->request.profile_snapshot;
+ auto stages = evaluate_supported_stages(profile);
+
+ response->response.success = true;
+ response->response.error_code.code = ErrorCode::OK;
+ response->response.message = "适用性评估完成。";
+ response->response.overall_supported = !stages.empty();
+ response->response.recommended_workflow_stages = stages;
+}
+
+void VehicleProfileManagerNode::handle_heartbeat(
+ const std::shared_ptr /*request*/,
+ std::shared_ptr response)
+{
+ const auto now_us = std::chrono::duration_cast(
+ std::chrono::system_clock::now().time_since_epoch()).count();
+ response->response.success = true;
+ response->response.error_code.code = ErrorCode::OK;
+ response->response.message = "vehicle_profile_manager 在线。";
+ response->response.server_timestamp_us = now_us;
+ response->response.vehicle_ready = true;
+}
+
+std::vector
+VehicleProfileManagerNode::evaluate_supported_stages(const VehicleProfile & profile) const
+{
+ std::vector stages;
+
+ auto make_stage = [](uint8_t v) {
+ WorkflowStageType s;
+ s.value = v;
+ return s;
+ };
+
+ // 预检和画像校验始终支持。
+ stages.push_back(make_stage(WorkflowStageType::PROFILE_VALIDATION_STAGE));
+ stages.push_back(make_stage(WorkflowStageType::WORKSHOP_PRECHECK_STAGE));
+
+ // 底盘标定:底盘类型已指定时支持。
+ if (profile.chassis_type.value != ChassisType::CHASSIS_TYPE_UNSPECIFIED) {
+ stages.push_back(make_stage(WorkflowStageType::CHASSIS_CALIBRATION_STAGE));
+ stages.push_back(make_stage(WorkflowStageType::CONTROL_CALIBRATION_STAGE));
+ }
+
+ // 传感器标定:有传感器配置时支持。
+ if (!profile.sensors.empty()) {
+ stages.push_back(make_stage(WorkflowStageType::SENSOR_INTRINSIC_CALIBRATION_STAGE));
+ stages.push_back(make_stage(WorkflowStageType::SENSOR_EXTRINSIC_CALIBRATION_STAGE));
+ }
+
+ // 手眼标定:有机械臂且有传感器时支持。
+ if (profile.arm_profile.has_mechanical_arm && !profile.sensors.empty()) {
+ stages.push_back(make_stage(WorkflowStageType::HAND_EYE_CALIBRATION_STAGE));
+ }
+
+ // 最终阶段始终加入。
+ stages.push_back(make_stage(WorkflowStageType::PARAMETER_COMMIT_STAGE));
+ stages.push_back(make_stage(WorkflowStageType::REPORT_ARCHIVE_STAGE));
+
+ return stages;
+}
+
+void VehicleProfileManagerNode::load_profiles_from_file()
+{
+ profiles_.clear();
+ if (profile_storage_path_.empty()) {
+ RCLCPP_WARN(get_logger(), "profile_storage_path 为空,跳过画像文件加载。");
+ return;
+ }
+ if (!std::filesystem::exists(profile_storage_path_)) {
+ RCLCPP_WARN(get_logger(), "画像存储文件不存在:%s,后续将回退到 demo 画像。", profile_storage_path_.c_str());
+ return;
+ }
+
+ std::ifstream ifs(profile_storage_path_);
+ if (!ifs.is_open()) {
+ RCLCPP_WARN(get_logger(), "无法打开画像存储文件:%s", profile_storage_path_.c_str());
+ return;
+ }
+
+ std::stringstream buffer;
+ buffer << ifs.rdbuf();
+ for (const auto & block : parse_profile_blocks(buffer.str())) {
+ auto profile = make_profile_from_kv_map(block);
+ if (!profile.base_info.vehicle_id.empty()) {
+ profile.enabled_workflow_stages = evaluate_supported_stages(profile);
+ profiles_[profile.base_info.vehicle_id] = profile;
+ }
+ }
+}
+
+bool VehicleProfileManagerNode::save_profiles_to_file(std::string & error_message) const
+{
+ if (profile_storage_path_.empty()) {
+ error_message = "profile_storage_path 为空,无法保存车辆画像。";
+ return false;
+ }
+
+ const auto parent = std::filesystem::path(profile_storage_path_).parent_path();
+ if (!parent.empty()) {
+ std::error_code ec;
+ std::filesystem::create_directories(parent, ec);
+ if (ec) {
+ error_message = "创建画像存储目录失败:" + ec.message();
+ return false;
+ }
+ }
+
+ std::ofstream ofs(profile_storage_path_, std::ios::trunc);
+ if (!ofs.is_open()) {
+ error_message = "无法打开画像存储文件进行写入:" + profile_storage_path_;
+ return false;
+ }
+
+ for (const auto & [vehicle_id, profile] : profiles_) {
+ ofs << "[profile]\n";
+ ofs << "vehicle_id=" << vehicle_id << "\n";
+ ofs << "vehicle_name=" << profile.base_info.vehicle_name << "\n";
+ ofs << "model_name=" << profile.base_info.model_name << "\n";
+ ofs << "serial_number=" << profile.base_info.serial_number << "\n";
+ ofs << "manufacturer=" << profile.base_info.manufacturer << "\n";
+ ofs << "description=" << profile.base_info.description << "\n";
+ ofs << "profile_version=" << profile.profile_version << "\n";
+ ofs << "base_link_frame=" << profile.base_link_frame << "\n";
+ ofs << "chassis_type=" << static_cast(profile.chassis_type.value) << "\n";
+ ofs << "has_mechanical_arm=" << (profile.arm_profile.has_mechanical_arm ? "true" : "false") << "\n";
+ ofs << "arm_id=" << profile.arm_profile.arm_id << "\n";
+ ofs << "arm_model=" << profile.arm_profile.arm_model << "\n";
+ ofs << "arm_dof=" << profile.arm_profile.dof << "\n";
+ ofs << "arm_base_frame=" << profile.arm_profile.arm_base_frame << "\n";
+ ofs << "tool_frame=" << profile.arm_profile.tool_frame << "\n";
+
+ for (const auto & sensor : profile.sensors) {
+ ofs << "sensor="
+ << sensor.sensor_id << ","
+ << static_cast(sensor.sensor_type.value) << ","
+ << sensor.sensor_name << ","
+ << sensor.frame_id << ","
+ << static_cast(sensor.camera_mount_type.value) << ","
+ << (sensor.enabled ? "true" : "false") << ","
+ << (sensor.needs_intrinsic_calibration ? "true" : "false") << ","
+ << (sensor.needs_extrinsic_calibration ? "true" : "false") << ","
+ << sensor.device_hint << ","
+ << (sensor.selected_for_this_session ? "true" : "false") << ","
+ << (sensor.supports_intrinsic_calibration ? "true" : "false") << ","
+ << (sensor.supports_extrinsic_calibration ? "true" : "false") << "\n";
+ }
+
+ for (const auto & cap : profile.capabilities) {
+ ofs << "capability="
+ << static_cast(cap.ability_type.value) << ","
+ << (cap.supported ? "true" : "false") << ","
+ << cap.message << "\n";
+ }
+
+ for (const auto & controller : profile.controllers) {
+ ofs << "controller="
+ << static_cast(controller.control_axis.value) << ","
+ << static_cast(controller.default_algorithm.value) << "\n";
+ }
+
+ ofs << "\n";
+ }
+
+ return true;
+}
+
+void VehicleProfileManagerNode::load_demo_profile_if_empty()
+{
+ if (!profiles_.empty()) {
+ return;
+ }
+ load_demo_profile();
+ std::string save_error;
+ if (!save_profiles_to_file(save_error)) {
+ RCLCPP_WARN(get_logger(), "写入 demo 画像到存储文件失败:%s", save_error.c_str());
+ }
+}
+
+VehicleProfileManagerNode::VehicleProfile VehicleProfileManagerNode::make_profile_from_kv_map(
+ const std::unordered_map & values) const
+{
+ VehicleProfile profile;
+ auto get = [&](const std::string & key) -> std::string {
+ const auto it = values.find(key);
+ return it == values.end() ? std::string() : it->second;
+ };
+
+ profile.base_info.vehicle_id = get("vehicle_id");
+ profile.base_info.vehicle_name = get("vehicle_name");
+ profile.base_info.model_name = get("model_name");
+ profile.base_info.serial_number = get("serial_number");
+ profile.base_info.manufacturer = get("manufacturer");
+ profile.base_info.description = get("description");
+ profile.profile_version = get("profile_version");
+ profile.base_link_frame = get("base_link_frame");
+
+ try {
+ if (!get("chassis_type").empty()) {
+ profile.chassis_type.value = static_cast(std::stoul(get("chassis_type")));
+ }
+ if (!get("arm_dof").empty()) {
+ profile.arm_profile.dof = static_cast(std::stoul(get("arm_dof")));
+ }
+ } catch (...) {
+ }
+
+ profile.arm_profile.has_mechanical_arm = parse_bool_text(get("has_mechanical_arm"));
+ profile.arm_profile.arm_id = get("arm_id");
+ profile.arm_profile.arm_model = get("arm_model");
+ profile.arm_profile.arm_base_frame = get("arm_base_frame");
+ profile.arm_profile.tool_frame = get("tool_frame");
+
+ const auto sensor_rows = split_pipe_rows(get("sensor_rows"));
+ for (const auto & row : sensor_rows) {
+ auto parts = split_csv(row);
+ if (parts.size() < 12) {
+ continue;
+ }
+ calibration_vehicle_profile_interfaces::msg::SensorProfile sensor;
+ sensor.sensor_id = parts[0];
+ sensor.sensor_type.value = static_cast(std::stoul(parts[1]));
+ sensor.sensor_name = parts[2];
+ sensor.frame_id = parts[3];
+ sensor.camera_mount_type.value = static_cast(std::stoul(parts[4]));
+ sensor.enabled = parse_bool_text(parts[5]);
+ sensor.needs_intrinsic_calibration = parse_bool_text(parts[6]);
+ sensor.needs_extrinsic_calibration = parse_bool_text(parts[7]);
+ sensor.device_hint = parts[8];
+ sensor.selected_for_this_session = parse_bool_text(parts[9]);
+ sensor.supports_intrinsic_calibration = parse_bool_text(parts[10]);
+ sensor.supports_extrinsic_calibration = parse_bool_text(parts[11]);
+ profile.sensors.push_back(sensor);
+ }
+
+ const auto capability_rows = split_pipe_rows(get("capability_rows"));
+ for (const auto & row : capability_rows) {
+ auto parts = split_csv(row);
+ if (parts.size() < 3) {
+ continue;
+ }
+ calibration_vehicle_profile_interfaces::msg::CalibrationCapability capability;
+ capability.ability_type.value = static_cast(std::stoul(parts[0]));
+ capability.supported = parse_bool_text(parts[1]);
+ capability.message = parts[2];
+ profile.capabilities.push_back(capability);
+ }
+
+ const auto controller_rows = split_pipe_rows(get("controller_rows"));
+ for (const auto & row : controller_rows) {
+ auto parts = split_csv(row);
+ if (parts.size() < 2) {
+ continue;
+ }
+ calibration_vehicle_profile_interfaces::msg::ControllerProfile controller;
+ controller.control_axis.value = static_cast(std::stoul(parts[0]));
+ controller.default_algorithm.value = static_cast(std::stoul(parts[1]));
+ profile.controllers.push_back(controller);
+ }
+
+ return profile;
+}
+
+std::vector> VehicleProfileManagerNode::parse_profile_blocks(
+ const std::string & text) const
+{
+ std::vector> blocks;
+ std::unordered_map current;
+ std::stringstream ss(text);
+ std::string line;
+ std::vector sensor_rows;
+ std::vector capability_rows;
+ std::vector controller_rows;
+
+ auto flush_current = [&]() {
+ if (!current.empty()) {
+ std::string sensor_rows_joined;
+ for (size_t i = 0; i < sensor_rows.size(); ++i) {
+ if (i != 0) {
+ sensor_rows_joined += "|";
+ }
+ sensor_rows_joined += sensor_rows[i];
+ }
+ std::string capability_rows_joined;
+ for (size_t i = 0; i < capability_rows.size(); ++i) {
+ if (i != 0) {
+ capability_rows_joined += "|";
+ }
+ capability_rows_joined += capability_rows[i];
+ }
+ std::string controller_rows_joined;
+ for (size_t i = 0; i < controller_rows.size(); ++i) {
+ if (i != 0) {
+ controller_rows_joined += "|";
+ }
+ controller_rows_joined += controller_rows[i];
+ }
+ current["sensor_rows"] = sensor_rows_joined;
+ current["capability_rows"] = capability_rows_joined;
+ current["controller_rows"] = controller_rows_joined;
+ blocks.push_back(current);
+ }
+ current.clear();
+ sensor_rows.clear();
+ capability_rows.clear();
+ controller_rows.clear();
+ };
+
+ while (std::getline(ss, line)) {
+ line = trim_copy(line);
+ if (line.empty()) {
+ flush_current();
+ continue;
+ }
+ if (line == "[profile]") {
+ flush_current();
+ continue;
+ }
+ const auto sep = line.find('=');
+ if (sep == std::string::npos) {
+ continue;
+ }
+ const auto key = trim_copy(line.substr(0, sep));
+ const auto value = trim_copy(line.substr(sep + 1));
+ if (key == "sensor") {
+ sensor_rows.push_back(value);
+ } else if (key == "capability") {
+ capability_rows.push_back(value);
+ } else if (key == "controller") {
+ controller_rows.push_back(value);
+ } else {
+ current[key] = value;
+ }
+ }
+ flush_current();
+ return blocks;
+}
+
+void VehicleProfileManagerNode::load_demo_profile()
+{
+ VehicleProfile demo;
+
+ // 基础信息
+ demo.base_info.vehicle_id = "demo_agv_001";
+ demo.base_info.vehicle_name = "Demo AGV";
+ demo.base_info.model_name = "DemoModel-X1";
+ demo.base_info.manufacturer = "Demo Manufacturer";
+
+ // 底盘类型:差速
+ demo.chassis_type.value = ChassisType::DIFFERENTIAL;
+
+ // base_link
+ demo.base_link_frame = "base_link";
+
+ // 画像版本
+ demo.profile_version = "demo_v1";
+
+ calibration_vehicle_profile_interfaces::msg::SensorProfile front_camera;
+ front_camera.sensor_id = "demo_front_camera";
+ front_camera.sensor_type.value = SensorType::FRONT_CAMERA;
+ front_camera.sensor_name = "Demo Front Camera";
+ front_camera.frame_id = "front_camera_link";
+ front_camera.camera_mount_type.value = CameraMountType::FRONT_MOUNTED;
+ front_camera.enabled = true;
+ front_camera.needs_intrinsic_calibration = true;
+ front_camera.needs_extrinsic_calibration = true;
+ front_camera.device_hint = "/dev/video0";
+ front_camera.selected_for_this_session = true;
+ front_camera.supports_intrinsic_calibration = true;
+ front_camera.supports_extrinsic_calibration = true;
+ demo.sensors.push_back(front_camera);
+
+ calibration_vehicle_profile_interfaces::msg::CalibrationCapability external_cap;
+ external_cap.ability_type.value = CalibrationAbilityType::EXTERNAL_LOCALIZATION_CALIBRATION;
+ external_cap.supported = true;
+ external_cap.message = "demo external localization supported";
+ demo.capabilities.push_back(external_cap);
+
+ calibration_vehicle_profile_interfaces::msg::CalibrationCapability chassis_cap;
+ chassis_cap.ability_type.value = CalibrationAbilityType::CHASSIS_CALIBRATION;
+ chassis_cap.supported = true;
+ chassis_cap.message = "demo chassis calibration supported";
+ demo.capabilities.push_back(chassis_cap);
+
+ calibration_vehicle_profile_interfaces::msg::CalibrationCapability control_cap;
+ control_cap.ability_type.value = CalibrationAbilityType::CONTROL_CALIBRATION;
+ control_cap.supported = true;
+ control_cap.message = "demo control calibration supported";
+ demo.capabilities.push_back(control_cap);
+
+ calibration_vehicle_profile_interfaces::msg::CalibrationCapability sensor_cap;
+ sensor_cap.ability_type.value = CalibrationAbilityType::SENSOR_CALIBRATION;
+ sensor_cap.supported = true;
+ sensor_cap.message = "demo sensor calibration supported";
+ demo.capabilities.push_back(sensor_cap);
+
+ calibration_vehicle_profile_interfaces::msg::ControllerProfile controller;
+ controller.control_axis.value = ControlAxisType::LATERAL_CONTROL;
+ controller.default_algorithm.value = ControllerAlgorithmType::PURE_PURSUIT;
+ demo.controllers.push_back(controller);
+
+ // 启用的工作流阶段
+ demo.enabled_workflow_stages = evaluate_supported_stages(demo);
+
+ profiles_[demo.base_info.vehicle_id] = demo;
+ RCLCPP_INFO(get_logger(), "已预载 demo 车辆画像 vehicle_id=[%s]",
+ demo.base_info.vehicle_id.c_str());
+}
+
+} // namespace vehicle_profile_manager
+
+RCLCPP_COMPONENTS_REGISTER_NODE(vehicle_profile_manager::VehicleProfileManagerNode)
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/ANNOTATION_NOTES.md b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/ANNOTATION_NOTES.md
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/ANNOTATION_NOTES.md
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/ANNOTATION_NOTES.md
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/CMakeLists.txt b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/CMakeLists.txt
similarity index 92%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/CMakeLists.txt
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/CMakeLists.txt
index 7cc5eb4..fd9c460 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/CMakeLists.txt
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/CMakeLists.txt
@@ -19,6 +19,7 @@ find_package(calibration_external_localization_interfaces REQUIRED)
find_package(calibration_chassis_interfaces REQUIRED)
find_package(calibration_control_interfaces REQUIRED)
find_package(calibration_sensor_interfaces REQUIRED)
+find_package(nlohmann_json REQUIRED)
include_directories(include)
@@ -31,6 +32,7 @@ add_executable(workshop_orchestrator_v2_node
src/chassis_gateway_client.cpp
src/control_gateway_client.cpp
src/sensor_gateway_client.cpp
+ src/wifi6_link_client.cpp
src/workshop_orchestrator_v2_node.cpp
)
@@ -47,6 +49,10 @@ ament_target_dependencies(workshop_orchestrator_v2_node
calibration_sensor_interfaces
)
+target_link_libraries(workshop_orchestrator_v2_node
+ nlohmann_json::nlohmann_json
+)
+
install(TARGETS workshop_orchestrator_v2_node
DESTINATION lib/${PROJECT_NAME}
)
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/INTEGRATION_NOTES.md b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/INTEGRATION_NOTES.md
similarity index 85%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/INTEGRATION_NOTES.md
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/INTEGRATION_NOTES.md
index 484c60e..9c36cd8 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/INTEGRATION_NOTES.md
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/INTEGRATION_NOTES.md
@@ -1,6 +1,6 @@
把这个包接入你现在的仓库时,建议放到:
-`src/win_ubuntu_bridge/service/workshop_orchestrator_v2`
+`src/communication/win_ubuntu_bridge/service/workshop_orchestrator_v2`
如果你已经创建了同名包,可以直接把 `include/`、`src/`、`launch/` 里的对应文件合并进去。
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/MIGRATION_NOTES.md b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/MIGRATION_NOTES.md
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/MIGRATION_NOTES.md
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/MIGRATION_NOTES.md
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/README.md b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/README.md
similarity index 57%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/README.md
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/README.md
index 870dc19..00a1f8e 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/README.md
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/README.md
@@ -1,4 +1,4 @@
-# workshop_orchestrator
+# 车间总控编排模块
这是自动化标定车间的总编排说明文档。这个 README 需要跟着代码一起更新,用来保留当前流程设计、任务粒度和模块职责。
@@ -27,7 +27,27 @@
- 阶段审批
- 报告生成与查询
-### 2. 任务选择方式
+### 2. WiFi6 链路调度
+
+车间工控机到车端电脑只使用一个统一 WiFi6/TCP 入口,默认是:
+
+```text
+wifi6_vehicle_host: 127.0.0.1
+wifi6_vehicle_port: 9000
+```
+
+总控预检时会在同一个 TCP endpoint 上依次检查四个逻辑通道:
+
+| 逻辑通道 | 帧类型 | 作用 |
+|---|---|---|
+| 底盘 `CHASSIS` | `1 -> 2` | 检查底盘 agent、急停、运动安全状态 |
+| 运控 `CONTROL` | `11 -> 12` | 检查轨迹执行器、车辆反馈、控制输出 |
+| 传感器 `SENSOR` | `21 -> 22` | 检查车端传感器采集和数据流状态 |
+| 外部真值 `EXTERNAL_POSE` | `31 -> 32` | 检查外部真值位姿能否通过 WiFi6 推入车端 |
+
+这里的“四条链路”是协议里的逻辑通道,不是四个物理端口。仿真环境中如果底盘、运控、传感器、外部真值仍由不同脚本承载,可以启动 `vehicle_wifi6_gateway_sim.py`,由它监听 `9000` 并转发到内部后端端口。
+
+### 3. 任务选择方式
当前设计是“**由 UI 或上层显式选择要执行的阶段**”。
@@ -36,7 +56,7 @@
## 当前执行主线
-`CreateSession -> BuildPlan -> Precheck -> Stage Execution -> Commit/Validation -> Report`
+当前主线为:创建会话 -> 生成计划 -> 执行预检 -> 阶段执行 -> 提交/验收 -> 生成报告。
其中阶段执行会按会话配置和车辆画像决定是否加入:
@@ -71,12 +91,12 @@
| 模块 | 职责 | 输入 | 输出 | 实现位置 |
|---|---|---|---|---|
-| 车间总控 `workshop_orchestrator_v2` | 管会话、生成计划、调度执行、处理人工确认/审批、生成报告 | `VehicleProfile`、`WorkshopSessionConfig`、`RequestedCalibrationTask`、`StagePlan`、`StageResultSummary` | `WorkshopSession`、`WorkshopPrecheckResponse`、`WorkshopReport`、`WorkshopEvent` | `src/agv_calib_core/workshop_orchestrator/src/main.cpp`
`src/agv_calib_core/workshop_orchestrator/src/workshop_orchestrator_v2_node.cpp`
`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp`
`src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp` / `include/workshop_orchestrator_v2/plan_builder.hpp`
`src/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp` / `include/workshop_orchestrator_v2/precheck_runner.hpp`
`src/agv_calib_core/workshop_orchestrator/src/report_builder.cpp` / `include/workshop_orchestrator_v2/report_builder.hpp`
`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp` |
-| 外部定位 / 真值接入 `external_localization_service` | goal 校验、外部参考接入、真值校核、结果回填 | `ExecuteExternalLocalizationTask::Goal`、`WorkshopSession`、`StagePlan` | `StageResultSummary`、`ExecuteExternalLocalizationTask::Result` | `src/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp`
`src/agv_calib_core/external_localization_service/src/external_reference_executor.cpp` |
-| 底盘标定客户端 | readiness 检查、底盘动作原语任务下发、结果翻译 | `WorkshopSession`、`StagePlan` | `StageResultSummary`、底盘专项 goal / result | `src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp`
`src/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp` |
-| 运控参数标定客户端 | readiness 检查、控制评估任务下发、轨迹组装、结果翻译 | `WorkshopSession`、`StagePlan`、`stage.metadata` 中的轨迹与参数 | `StageResultSummary`、运控专项 goal / result | `src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp`
`src/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp` |
-| 传感器标定客户端 | readiness 检查、传感器任务路由、结果翻译 | `WorkshopSession`、`StagePlan`、`stage.metadata` 中的传感器信息 | `StageResultSummary`、传感器专项 goal / result | `src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp`
`src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp` |
-| 外部定位客户端 | readiness 检查、外部参考接入任务下发、结果接入总控 | `WorkshopSession`、`StagePlan` | `StageResultSummary`、外部定位专项 goal / result | `src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp`
`src/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp` |
+| 车间总控 `workshop_orchestrator_v2` | 管会话、生成计划、调度执行、处理人工确认/审批、生成报告 | `VehicleProfile`、`WorkshopSessionConfig`、`RequestedCalibrationTask`、`StagePlan`、`StageResultSummary` | `WorkshopSession`、`WorkshopPrecheckResponse`、`WorkshopReport`、`WorkshopEvent` | `src/core/agv_calib_core/workshop_orchestrator/src/main.cpp`
`src/core/agv_calib_core/workshop_orchestrator/src/workshop_orchestrator_v2_node.cpp`
`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp`
`src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp` / `include/workshop_orchestrator_v2/plan_builder.hpp`
`src/core/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp` / `include/workshop_orchestrator_v2/precheck_runner.hpp`
`src/core/agv_calib_core/workshop_orchestrator/src/report_builder.cpp` / `include/workshop_orchestrator_v2/report_builder.hpp`
`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp` |
+| 外部定位 / 真值接入 `external_localization_service` | goal 校验、外部参考接入、真值校核、结果回填 | `ExecuteExternalLocalizationTask::Goal`、`WorkshopSession`、`StagePlan` | `StageResultSummary`、`ExecuteExternalLocalizationTask::Result` | `src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp`
`src/core/agv_calib_core/external_localization_service/src/external_reference_executor.cpp` |
+| 底盘标定客户端 | readiness 检查、底盘动作原语任务下发、结果翻译 | `WorkshopSession`、`StagePlan` | `StageResultSummary`、底盘专项 goal / result | `src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp`
`src/core/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp` |
+| 运控参数标定客户端 | readiness 检查、控制评估任务下发、轨迹组装、结果翻译 | `WorkshopSession`、`StagePlan`、`stage.metadata` 中的轨迹与参数 | `StageResultSummary`、运控专项 goal / result | `src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp`
`src/core/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp` |
+| 传感器标定客户端 | readiness 检查、传感器任务路由、结果翻译 | `WorkshopSession`、`StagePlan`、`stage.metadata` 中的传感器信息 | `StageResultSummary`、传感器专项 goal / result | `src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp`
`src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp` |
+| 外部定位客户端 | readiness 检查、外部参考接入任务下发、结果接入总控 | `WorkshopSession`、`StagePlan` | `StageResultSummary`、外部定位专项 goal / result | `src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp`
`src/core/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp` |
### 1. 车间总控模块 `workshop_orchestrator_v2`
@@ -100,13 +120,13 @@
- `WorkshopEvent`
**实现位置**
-- 节点入口:`src/agv_calib_core/workshop_orchestrator/src/main.cpp`
-- 总控节点:`src/agv_calib_core/workshop_orchestrator/src/workshop_orchestrator_v2_node.cpp`
-- 总控头文件:`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp`
-- 阶段规划:`src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp` / `include/workshop_orchestrator_v2/plan_builder.hpp`
-- 预检逻辑:`src/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp` / `include/workshop_orchestrator_v2/precheck_runner.hpp`
-- 报告生成:`src/agv_calib_core/workshop_orchestrator/src/report_builder.cpp` / `include/workshop_orchestrator_v2/report_builder.hpp`
-- 共享类型:`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp`
+- 节点入口:`src/core/agv_calib_core/workshop_orchestrator/src/main.cpp`
+- 总控节点:`src/core/agv_calib_core/workshop_orchestrator/src/workshop_orchestrator_v2_node.cpp`
+- 总控头文件:`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp`
+- 阶段规划:`src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp` / `include/workshop_orchestrator_v2/plan_builder.hpp`
+- 预检逻辑:`src/core/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp` / `include/workshop_orchestrator_v2/precheck_runner.hpp`
+- 报告生成:`src/core/agv_calib_core/workshop_orchestrator/src/report_builder.cpp` / `include/workshop_orchestrator_v2/report_builder.hpp`
+- 共享类型:`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp`
### 2. 外部定位 / 真值接入模块 `external_localization_service`
@@ -125,8 +145,8 @@
- `ExecuteExternalLocalizationTask::Result`
**实现位置**
-- 执行器头文件:`src/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp`
-- 执行器实现:`src/agv_calib_core/external_localization_service/src/external_reference_executor.cpp`
+- 执行器头文件:`src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp`
+- 执行器实现:`src/core/agv_calib_core/external_localization_service/src/external_reference_executor.cpp`
### 3. 底盘标定客户端
@@ -144,8 +164,8 @@
- 底盘专项 goal / result
**实现位置**
-- 头文件:`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp`
-- 实现:`src/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp`
+- 头文件:`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp`
+- 实现:`src/core/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp`
### 4. 运控参数标定客户端
@@ -165,8 +185,8 @@
- 运控专项 goal / result
**实现位置**
-- 头文件:`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp`
-- 实现:`src/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp`
+- 头文件:`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp`
+- 实现:`src/core/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp`
### 5. 传感器标定客户端
@@ -186,8 +206,8 @@
- 传感器专项 goal / result
**实现位置**
-- 头文件:`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp`
-- 实现:`src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
+- 头文件:`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp`
+- 实现:`src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
### 6. 外部定位客户端
@@ -205,8 +225,8 @@
- 外部定位专项 goal / result
**实现位置**
-- 头文件:`src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp`
-- 实现:`src/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp`
+- 头文件:`src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp`
+- 实现:`src/core/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp`
### 7. 外部定位专项执行骨架
@@ -223,8 +243,8 @@
- `StageResultSummary`
**实现位置**
-- 头文件:`src/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp`
-- 实现:`src/agv_calib_core/external_localization_service/src/external_reference_executor.cpp`
+- 头文件:`src/core/agv_calib_core/external_localization_service/include/external_localization_service/external_reference_executor.hpp`
+- 实现:`src/core/agv_calib_core/external_localization_service/src/external_reference_executor.cpp`
## 专项任务清单
@@ -233,9 +253,9 @@
### 1. 外部定位 / 真值接入
**对应代码**
-- `src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
-- `src/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp`
-- `src/agv_calib_core/external_localization_service/src/external_reference_executor.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp`
+- `src/core/agv_calib_core/external_localization_service/src/external_reference_executor.cpp`
**当前任务**
- 外部真值参考接入
@@ -251,8 +271,8 @@
### 2. 底盘标定
**对应代码**
-- `src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
-- `src/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp`
**当前任务**
- 底盘 readiness 检查
@@ -267,8 +287,8 @@
### 3. 运控参数标定
**对应代码**
-- `src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
-- `src/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp`
**当前任务**
- 运控 readiness 检查
@@ -284,8 +304,8 @@
### 4. 传感器内参标定
**对应代码**
-- `src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
-- `src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
**当前任务**
- 相机内参标定
@@ -302,8 +322,8 @@
### 5. 传感器外参标定
**对应代码**
-- `src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
-- `src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
**当前任务**
- 相机外参标定
@@ -321,8 +341,8 @@
### 6. 手眼标定
**对应代码**
-- `src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
-- `src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp`
+- `src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp`
**当前任务**
- 眼在手上(EYE_IN_HAND)
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/chassis_gateway_client.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/control_gateway_client.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/external_localization_client.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/plan_builder.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/plan_builder.hpp
similarity index 70%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/plan_builder.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/plan_builder.hpp
index e407663..cf7c8f4 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/plan_builder.hpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/plan_builder.hpp
@@ -49,13 +49,34 @@ private:
uint8_t ability_type) const;
// 各阶段的构造方法。
- StagePlan make_external_reference_stage(int order_index, const RequestedCalibrationTask * task_cfg) const;
- StagePlan make_chassis_stage(int order_index, const RequestedCalibrationTask * task_cfg) const;
- StagePlan make_control_stage(int order_index, const RequestedCalibrationTask * task_cfg) const;
- StagePlan make_sensor_intrinsic_stage(int order_index, const RequestedCalibrationTask * task_cfg) const;
- StagePlan make_sensor_extrinsic_stage(int order_index, const RequestedCalibrationTask * task_cfg) const;
- StagePlan make_hand_eye_stage(int order_index, const RequestedCalibrationTask * task_cfg) const;
- StagePlan make_stage_for_task(int order_index, const RequestedCalibrationTask & task) const;
+ StagePlan make_external_reference_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const;
+ StagePlan make_chassis_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const;
+ StagePlan make_control_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const;
+ StagePlan make_sensor_intrinsic_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const;
+ StagePlan make_sensor_extrinsic_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const;
+ StagePlan make_hand_eye_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const;
+ StagePlan make_stage_for_task(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask & task) const;
// 把 RequestedCalibrationTask 中的策略和配置应用到 StagePlan 上。
void apply_task_config(StagePlan & stage, const RequestedCalibrationTask * task_cfg) const;
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/precheck_runner.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/precheck_runner.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/precheck_runner.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/precheck_runner.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/report_builder.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/report_builder.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/report_builder.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/report_builder.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/sensor_gateway_client.hpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp
similarity index 69%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp
index 8e37f9b..327ca18 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/types.hpp
@@ -94,12 +94,46 @@ inline constexpr const char * CHASSIS_PRIMITIVE_TYPE = "primitive_type";
inline constexpr const char * CHASSIS_STRAIGHT_LINE_DISTANCE_M = "straight_line.target_distance_m";
inline constexpr const char * CHASSIS_STRAIGHT_LINE_SPEED_MS = "straight_line.target_speed_ms";
inline constexpr const char * CHASSIS_STRAIGHT_LINE_REVERSE = "straight_line.reverse";
+inline constexpr const char * CHASSIS_ARC_SPEED_MS = "arc.target_speed_ms";
+inline constexpr const char * CHASSIS_ARC_RADIUS_M = "arc.radius_m";
+inline constexpr const char * CHASSIS_ARC_SWEEP_ANGLE_DEG = "arc.sweep_angle_deg";
+inline constexpr const char * CHASSIS_ARC_CLOCKWISE = "arc.clockwise";
+inline constexpr const char * CHASSIS_ROTATION_TARGET_YAW_DEG = "in_place_rotation.target_yaw_deg";
+inline constexpr const char * CHASSIS_ROTATION_TARGET_ANGULAR_VEL_DEG_S = "in_place_rotation.target_angular_vel_deg_s";
+inline constexpr const char * CHASSIS_STEERING_SWEEP_TARGET_ANGLE_DEG = "steering_sweep.target_angle_deg";
+inline constexpr const char * CHASSIS_STEERING_SWEEP_AMPLITUDE_DEG = "steering_sweep.sweep_amplitude_deg";
+inline constexpr const char * CHASSIS_STEERING_SWEEP_FREQUENCY_HZ = "steering_sweep.sweep_frequency_hz";
+inline constexpr const char * CHASSIS_STEERING_SWEEP_DURATION_SEC = "steering_sweep.duration_sec";
+inline constexpr const char * CHASSIS_LATERAL_SPEED_MS = "lateral_translation.target_speed_ms";
+inline constexpr const char * CHASSIS_LATERAL_DISTANCE_M = "lateral_translation.target_distance_m";
+inline constexpr const char * CHASSIS_LATERAL_MOVE_LEFT = "lateral_translation.move_left";
+inline constexpr const char * CHASSIS_DIAGONAL_SPEED_MS = "diagonal_motion.target_speed_ms";
+inline constexpr const char * CHASSIS_DIAGONAL_DISTANCE_M = "diagonal_motion.target_distance_m";
+inline constexpr const char * CHASSIS_DIAGONAL_HEADING_DEG = "diagonal_motion.heading_deg";
+inline constexpr const char * CHASSIS_MODULE_ALIGNMENT_IDS = "module_alignment.module_ids";
+inline constexpr const char * CHASSIS_MODULE_ALIGNMENT_ZERO_DEG = "module_alignment.target_zero_deg";
+inline constexpr const char * CHASSIS_MODULE_ALIGNMENT_TOLERANCE_DEG = "module_alignment.tolerance_deg";
+inline constexpr const char * CHASSIS_COORDINATED_STEERING_IDS = "coordinated_steering.module_ids";
+inline constexpr const char * CHASSIS_COORDINATED_STEERING_TARGET_ANGLE_DEG = "coordinated_steering.target_angle_deg";
+inline constexpr const char * CHASSIS_COORDINATED_STEERING_HOLD_TIME_SEC = "coordinated_steering.hold_time_sec";
inline constexpr const char * COMMON_BRAKE_WHEN_FINISHED = "brake_when_finished";
inline constexpr const char * COMMON_TIMEOUT_SEC = "timeout_sec";
// control
inline constexpr const char * CONTROL_TASK_TYPE = "control.task_type";
inline constexpr const char * CONTROL_TRAJECTORY_PREFIX = "traj_pt_";
+inline constexpr const char * CONTROL_STOP_AT_END = "control.stop_at_end";
+inline constexpr const char * CONTROL_TIMEOUT_SEC = "control.timeout_sec";
+inline constexpr const char * CONTROL_VELOCITY_STEP_TARGET_VELOCITY_MS = "velocity_step.target_velocity_ms";
+inline constexpr const char * CONTROL_VELOCITY_STEP_HOLD_TIME_SEC = "velocity_step.hold_time_sec";
+inline constexpr const char * CONTROL_VELOCITY_STEP_SETTLE_BEFORE_STEP_SEC = "velocity_step.settle_before_step_sec";
+inline constexpr const char * CONTROL_ACCEL_DECEL_START_VELOCITY_MS = "accel_decel.start_velocity_ms";
+inline constexpr const char * CONTROL_ACCEL_DECEL_TARGET_VELOCITY_MS = "accel_decel.target_velocity_ms";
+inline constexpr const char * CONTROL_ACCEL_DECEL_TARGET_ACCEL_MS2 = "accel_decel.target_accel_ms2";
+inline constexpr const char * CONTROL_ACCEL_DECEL_HOLD_TIME_SEC = "accel_decel.hold_time_sec";
+inline constexpr const char * CONTROL_STOP_ACCURACY_X_M = "stop_accuracy.target_stop_x_m";
+inline constexpr const char * CONTROL_STOP_ACCURACY_Y_M = "stop_accuracy.target_stop_y_m";
+inline constexpr const char * CONTROL_STOP_ACCURACY_YAW_RAD = "stop_accuracy.target_stop_yaw_rad";
// sensor
inline constexpr const char * SENSOR_ID = "sensor.sensor_id";
@@ -107,6 +141,9 @@ inline constexpr const char * SENSOR_TASK_SUBTYPE = "sensor.task_subtype";
inline constexpr const char * CAMERA_INTRINSIC_REQUIRED_IMAGE_COUNT = "camera_intrinsic.required_image_count";
inline constexpr const char * CAMERA_INTRINSIC_TARGET_BOARD_ID = "camera_intrinsic.target_board_id";
inline constexpr const char * CAMERA_INTRINSIC_TIMEOUT_SEC = "camera_intrinsic.timeout_sec";
+inline constexpr const char * IMU_INTRINSIC_REQUIRED_STATIC_SEGMENT_COUNT = "imu_intrinsic.required_static_segment_count";
+inline constexpr const char * IMU_INTRINSIC_REQUIRED_MOTION_SEGMENT_COUNT = "imu_intrinsic.required_motion_segment_count";
+inline constexpr const char * IMU_INTRINSIC_TIMEOUT_SEC = "imu_intrinsic.timeout_sec";
inline constexpr const char * SENSOR_EXTRINSIC_BASE_FRAME_ID = "sensor_extrinsic.base_frame_id";
inline constexpr const char * SENSOR_EXTRINSIC_REQUIRED_SAMPLE_COUNT = "sensor_extrinsic.required_sample_count";
inline constexpr const char * SENSOR_EXTRINSIC_TIMEOUT_SEC = "sensor_extrinsic.timeout_sec";
diff --git a/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/wifi6_link_client.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/wifi6_link_client.hpp
new file mode 100644
index 0000000..450323f
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/wifi6_link_client.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include
+#include
+
+namespace workshop_orchestrator_v2
+{
+
+// 对齐 src/communication/win_ubuntu_bridge/*/proto/transport_contract.proto。
+// 这个 client 只用于 orchestrator 预检四条 WiFi6/TCP 链路,不承载专项算法逻辑。
+class Wifi6LinkClient
+{
+public:
+ struct Config
+ {
+ std::string vehicle_host{"127.0.0.1"};
+ uint16_t vehicle_port{9000};
+ int timeout_ms{5000};
+ };
+
+ struct CheckResult
+ {
+ bool passed{false};
+ std::string message;
+ };
+
+ explicit Wifi6LinkClient(Config config);
+
+ CheckResult check_chassis() const;
+ CheckResult check_control() const;
+ CheckResult check_sensor() const;
+ CheckResult check_external_pose() const;
+
+private:
+ enum class FrameType : uint32_t
+ {
+ CHASSIS_GET_READINESS_REQ = 1,
+ CHASSIS_GET_READINESS_RSP = 2,
+ CONTROL_GET_READINESS_REQ = 11,
+ CONTROL_GET_READINESS_RSP = 12,
+ SENSOR_GET_READINESS_REQ = 21,
+ SENSOR_GET_READINESS_RSP = 22,
+ EXTERNAL_POSE_PUSH_REQ = 31,
+ EXTERNAL_POSE_PUSH_RSP = 32,
+ };
+
+ CheckResult send_json_request(
+ FrameType request_type,
+ FrameType response_type,
+ const std::string & request_payload,
+ const std::string & link_name) const;
+
+ Config config_;
+};
+
+} // namespace workshop_orchestrator_v2
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp
similarity index 94%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp
index fa28bfc..ba0049a 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/include/workshop_orchestrator_v2/workshop_orchestrator_v2_node.hpp
@@ -9,6 +9,8 @@
#include "rclcpp/rclcpp.hpp" // ROS 2 普通节点基础能力。
#include "rclcpp_action/rclcpp_action.hpp" // ROS 2 action 能力,适合承载"整场任务执行"这种长操作。
+#include "rcl_interfaces/msg/set_parameters_result.hpp"
+
#include "calibration_workshop_orchestration_interfaces/action/execute_workshop_session.hpp" // 外部要求主控开始跑某次标定任务的 action。
#include "calibration_workshop_orchestration_interfaces/msg/workshop_event.hpp" // 发给界面/日志/上位机的进度通知消息。
#include "calibration_workshop_orchestration_interfaces/msg/workshop_event_type.hpp" // 进度通知里的事件类型枚举。
@@ -28,6 +30,7 @@
#include "workshop_orchestrator_v2/chassis_gateway_client.hpp" // 底盘模块薄 client。
#include "workshop_orchestrator_v2/control_gateway_client.hpp" // 运控模块薄 client。
#include "workshop_orchestrator_v2/sensor_gateway_client.hpp" // 传感器模块薄 client。
+#include "workshop_orchestrator_v2/wifi6_link_client.hpp" // 四条 WiFi6/TCP 链路预检。
namespace workshop_orchestrator_v2
{
@@ -91,6 +94,15 @@ private:
void execute_session(const std::shared_ptr goal_handle);
SessionExecutionContext prepare_session_for_run(const std::string & session_id);
WorkshopPrecheckResponse run_precheck_step(const std::string & session_id);
+ void run_wifi6_link_precheck(const WorkshopSession & session, WorkshopPrecheckResponse & precheck);
+ void append_precheck_item(
+ WorkshopPrecheckResponse & precheck,
+ const std::string & item_code,
+ const std::string & display_name,
+ bool passed,
+ const std::string & message,
+ uint8_t stage_type,
+ uint8_t module_type);
void mark_session_running(const std::string & session_id);
bool handle_cancel_if_requested(
const std::shared_ptr goal_handle,
@@ -208,6 +220,10 @@ private:
std::unique_ptr chassis_gateway_client_;
std::unique_ptr control_gateway_client_;
std::unique_ptr sensor_gateway_client_;
+ std::unique_ptr wifi6_link_client_;
+ bool wifi6_precheck_enabled_{true};
+ bool wifi6_precheck_require_all_links_{true};
+ rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr parameter_callback_handle_;
// ─── ROS 接口 ───
rclcpp::Service::SharedPtr create_session_service_;
diff --git a/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/launch/workshop_orchestrator_v2.launch.py b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/launch/workshop_orchestrator_v2.launch.py
new file mode 100644
index 0000000..02febe8
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/launch/workshop_orchestrator_v2.launch.py
@@ -0,0 +1,30 @@
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+from launch_ros.parameter_descriptions import ParameterValue
+
+
+def generate_launch_description():
+ return LaunchDescription([
+ DeclareLaunchArgument("wifi6_vehicle_host", default_value="127.0.0.1"),
+ DeclareLaunchArgument("wifi6_vehicle_port", default_value="9000"),
+ DeclareLaunchArgument("wifi6_timeout_ms", default_value="5000"),
+ DeclareLaunchArgument("wifi6_precheck_enabled", default_value="true"),
+ DeclareLaunchArgument("wifi6_precheck_require_all_links", default_value="true"),
+ Node(
+ package="workshop_orchestrator_v2",
+ executable="workshop_orchestrator_v2_node",
+ name="workshop_orchestrator_v2",
+ output="screen",
+ parameters=[{
+ "wifi6_vehicle_host": LaunchConfiguration("wifi6_vehicle_host"),
+ "wifi6_vehicle_port": ParameterValue(LaunchConfiguration("wifi6_vehicle_port"), value_type=int),
+ "wifi6_timeout_ms": ParameterValue(LaunchConfiguration("wifi6_timeout_ms"), value_type=int),
+ "wifi6_precheck_enabled": ParameterValue(
+ LaunchConfiguration("wifi6_precheck_enabled"), value_type=bool),
+ "wifi6_precheck_require_all_links": ParameterValue(
+ LaunchConfiguration("wifi6_precheck_require_all_links"), value_type=bool),
+ }],
+ )
+ ])
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/package.xml b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/package.xml
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/package.xml
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/package.xml
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp
similarity index 50%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp
index b4c0e99..84b0fda 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/chassis_gateway_client.cpp
@@ -1,9 +1,11 @@
#include "workshop_orchestrator_v2/chassis_gateway_client.hpp"
#include
+#include
#include
#include
#include
+#include
#include "workshop_orchestrator_v2/types.hpp"
@@ -17,6 +19,61 @@ using calibration_workshop_orchestration_interfaces::msg::StagePlan;
using calibration_workshop_orchestration_interfaces::msg::StageResultSummary;
using calibration_workshop_orchestration_interfaces::msg::WorkshopSession;
+namespace
+{
+
+bool parse_bool_value(const std::string & value)
+{
+ return value == "true" || value == "1" || value == "TRUE" || value == "True";
+}
+
+bool parse_double_metadata(
+ const std::unordered_map & metadata_map,
+ const std::string & key,
+ double & output)
+{
+ const auto it = metadata_map.find(key);
+ if (it == metadata_map.end()) {
+ return false;
+ }
+ try {
+ output = std::stod(it->second);
+ return true;
+ } catch (...) {
+ return false;
+ }
+}
+
+bool parse_string_list_metadata(
+ const std::unordered_map & metadata_map,
+ const std::string & key,
+ std::vector & output)
+{
+ const auto it = metadata_map.find(key);
+ if (it == metadata_map.end()) {
+ return false;
+ }
+
+ output.clear();
+ std::string token;
+ for (char ch : it->second) {
+ if (ch == ',' || ch == ';' || std::isspace(static_cast(ch))) {
+ if (!token.empty()) {
+ output.push_back(token);
+ token.clear();
+ }
+ continue;
+ }
+ token.push_back(ch);
+ }
+ if (!token.empty()) {
+ output.push_back(token);
+ }
+ return !output.empty();
+}
+
+} // namespace
+
ChassisGatewayClient::ChassisGatewayClient(rclcpp::Node * node)
: node_(node)
{
@@ -115,35 +172,170 @@ bool ChassisGatewayClient::build_goal(
return false;
}
- if (primitive_it->second != "straight_line") {
- failure_reason = "当前最小流仅支持 straight_line 底盘动作原语。";
+ if (primitive_it->second == "straight_line") {
+ double target_distance_m = 0.0;
+ double target_speed_ms = 0.0;
+ if (!parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_STRAIGHT_LINE_DISTANCE_M, target_distance_m) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_STRAIGHT_LINE_SPEED_MS, target_speed_ms))
+ {
+ failure_reason = "straight_line 缺少 target_distance_m 或 target_speed_ms,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::STRAIGHT_LINE;
+ goal.goal.straight_line.target_distance_m = target_distance_m;
+ goal.goal.straight_line.target_speed_ms = target_speed_ms;
+ const auto reverse_it = metadata_map.find(metadata_keys::CHASSIS_STRAIGHT_LINE_REVERSE);
+ goal.goal.straight_line.reverse =
+ reverse_it != metadata_map.end() && parse_bool_value(reverse_it->second);
+ } else if (primitive_it->second == "arc") {
+ double target_speed_ms = 0.0;
+ double radius_m = 0.0;
+ double sweep_angle_deg = 0.0;
+ if (!parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_ARC_SPEED_MS, target_speed_ms) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_ARC_RADIUS_M, radius_m) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_ARC_SWEEP_ANGLE_DEG, sweep_angle_deg))
+ {
+ failure_reason = "arc 缺少 target_speed_ms、radius_m 或 sweep_angle_deg,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::ARC;
+ goal.goal.arc.target_speed_ms = target_speed_ms;
+ goal.goal.arc.radius_m = radius_m;
+ goal.goal.arc.sweep_angle_deg = sweep_angle_deg;
+ const auto clockwise_it = metadata_map.find(metadata_keys::CHASSIS_ARC_CLOCKWISE);
+ goal.goal.arc.clockwise =
+ clockwise_it != metadata_map.end() && parse_bool_value(clockwise_it->second);
+ } else if (primitive_it->second == "in_place_rotation") {
+ double target_yaw_deg = 0.0;
+ double target_angular_vel_deg_s = 0.0;
+ if (!parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_ROTATION_TARGET_YAW_DEG, target_yaw_deg) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_ROTATION_TARGET_ANGULAR_VEL_DEG_S,
+ target_angular_vel_deg_s))
+ {
+ failure_reason = "in_place_rotation 缺少 target_yaw_deg 或 target_angular_vel_deg_s,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::IN_PLACE_ROTATION;
+ goal.goal.in_place_rotation.target_yaw_deg = target_yaw_deg;
+ goal.goal.in_place_rotation.target_angular_vel_deg_s = target_angular_vel_deg_s;
+ } else if (primitive_it->second == "steering_sweep") {
+ double target_angle_deg = 0.0;
+ double sweep_amplitude_deg = 0.0;
+ double sweep_frequency_hz = 0.0;
+ double duration_sec = 0.0;
+ if (!parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_STEERING_SWEEP_TARGET_ANGLE_DEG, target_angle_deg) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_STEERING_SWEEP_AMPLITUDE_DEG, sweep_amplitude_deg) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_STEERING_SWEEP_FREQUENCY_HZ, sweep_frequency_hz) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_STEERING_SWEEP_DURATION_SEC, duration_sec))
+ {
+ failure_reason = "steering_sweep 缺少目标角、幅值、频率或持续时间,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::STEERING_SWEEP;
+ goal.goal.steering_sweep.target_angle_deg = target_angle_deg;
+ goal.goal.steering_sweep.sweep_amplitude_deg = sweep_amplitude_deg;
+ goal.goal.steering_sweep.sweep_frequency_hz = sweep_frequency_hz;
+ goal.goal.steering_sweep.duration_sec = duration_sec;
+ } else if (primitive_it->second == "lateral_translation") {
+ double target_speed_ms = 0.0;
+ double target_distance_m = 0.0;
+ if (!parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_LATERAL_SPEED_MS, target_speed_ms) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_LATERAL_DISTANCE_M, target_distance_m))
+ {
+ failure_reason = "lateral_translation 缺少 target_speed_ms 或 target_distance_m,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::LATERAL_TRANSLATION;
+ goal.goal.lateral_translation.target_speed_ms = target_speed_ms;
+ goal.goal.lateral_translation.target_distance_m = target_distance_m;
+ const auto move_left_it = metadata_map.find(metadata_keys::CHASSIS_LATERAL_MOVE_LEFT);
+ goal.goal.lateral_translation.move_left =
+ move_left_it != metadata_map.end() && parse_bool_value(move_left_it->second);
+ } else if (primitive_it->second == "diagonal_motion") {
+ double target_speed_ms = 0.0;
+ double target_distance_m = 0.0;
+ double heading_deg = 0.0;
+ if (!parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_DIAGONAL_SPEED_MS, target_speed_ms) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_DIAGONAL_DISTANCE_M, target_distance_m) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_DIAGONAL_HEADING_DEG, heading_deg))
+ {
+ failure_reason = "diagonal_motion 缺少 target_speed_ms、target_distance_m 或 heading_deg,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::DIAGONAL_MOTION;
+ goal.goal.diagonal_motion.target_speed_ms = target_speed_ms;
+ goal.goal.diagonal_motion.target_distance_m = target_distance_m;
+ goal.goal.diagonal_motion.heading_deg = heading_deg;
+ } else if (primitive_it->second == "module_alignment") {
+ std::vector module_ids;
+ double target_zero_deg = 0.0;
+ double tolerance_deg = 0.0;
+ if (!parse_string_list_metadata(
+ metadata_map, metadata_keys::CHASSIS_MODULE_ALIGNMENT_IDS, module_ids) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_MODULE_ALIGNMENT_ZERO_DEG, target_zero_deg) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_MODULE_ALIGNMENT_TOLERANCE_DEG, tolerance_deg))
+ {
+ failure_reason = "module_alignment 缺少 module_ids、target_zero_deg 或 tolerance_deg,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::MODULE_ALIGNMENT;
+ goal.goal.module_alignment.module_ids = module_ids;
+ goal.goal.module_alignment.target_zero_deg = target_zero_deg;
+ goal.goal.module_alignment.tolerance_deg = tolerance_deg;
+ } else if (primitive_it->second == "coordinated_steering") {
+ std::vector module_ids;
+ double target_angle_deg = 0.0;
+ double hold_time_sec = 0.0;
+ if (!parse_string_list_metadata(
+ metadata_map, metadata_keys::CHASSIS_COORDINATED_STEERING_IDS, module_ids) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_COORDINATED_STEERING_TARGET_ANGLE_DEG,
+ target_angle_deg) ||
+ !parse_double_metadata(
+ metadata_map, metadata_keys::CHASSIS_COORDINATED_STEERING_HOLD_TIME_SEC, hold_time_sec))
+ {
+ failure_reason = "coordinated_steering 缺少 module_ids、target_angle_deg 或 hold_time_sec,或参数格式错误。";
+ return false;
+ }
+
+ goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::COORDINATED_STEERING;
+ goal.goal.coordinated_steering.module_ids = module_ids;
+ goal.goal.coordinated_steering.target_angle_deg = target_angle_deg;
+ goal.goal.coordinated_steering.hold_time_sec = hold_time_sec;
+ } else {
+ failure_reason = "不支持的底盘动作原语类型:" + primitive_it->second;
return false;
}
- const auto distance_it = metadata_map.find(metadata_keys::CHASSIS_STRAIGHT_LINE_DISTANCE_M);
- const auto speed_it = metadata_map.find(metadata_keys::CHASSIS_STRAIGHT_LINE_SPEED_MS);
- if (distance_it == metadata_map.end() || speed_it == metadata_map.end()) {
- failure_reason = "straight_line 缺少 target_distance_m 或 target_speed_ms。";
- return false;
- }
-
- goal.goal.selected_primitive.value = ChassisMotionPrimitiveType::STRAIGHT_LINE;
- try {
- goal.goal.straight_line.target_distance_m = std::stod(distance_it->second);
- goal.goal.straight_line.target_speed_ms = std::stod(speed_it->second);
- } catch (...) {
- failure_reason = "straight_line 参数格式错误,无法解析为数字。";
- return false;
- }
-
- const auto reverse_it = metadata_map.find(metadata_keys::CHASSIS_STRAIGHT_LINE_REVERSE);
- goal.goal.straight_line.reverse =
- reverse_it != metadata_map.end() && (reverse_it->second == "true" || reverse_it->second == "1");
-
goal.goal.brake_when_finished = true;
const auto brake_it = metadata_map.find(metadata_keys::COMMON_BRAKE_WHEN_FINISHED);
if (brake_it != metadata_map.end()) {
- goal.goal.brake_when_finished = brake_it->second == "true" || brake_it->second == "1";
+ goal.goal.brake_when_finished = parse_bool_value(brake_it->second);
}
goal.goal.timeout_sec = 60.0;
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp
similarity index 68%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp
index 06b22ae..f44a115 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/control_gateway_client.cpp
@@ -108,8 +108,17 @@ uint8_t ControlGatewayClient::resolve_task_type(
if (task_type_it->second == "trajectory_tracking") {
return ControllerEvaluationTaskType::TRAJECTORY_TRACKING;
}
+ if (task_type_it->second == "velocity_step") {
+ return ControllerEvaluationTaskType::VELOCITY_STEP;
+ }
+ if (task_type_it->second == "accel_decel") {
+ return ControllerEvaluationTaskType::ACCELERATION_DECELERATION;
+ }
+ if (task_type_it->second == "stop_accuracy") {
+ return ControllerEvaluationTaskType::STOP_ACCURACY;
+ }
- failure_reason = "当前最小流仅支持 trajectory_tracking 运控任务。";
+ failure_reason = "不支持的运控任务类型:" + task_type_it->second;
return ControllerEvaluationTaskType::CONTROL_EVALUATION_TASK_UNSPECIFIED;
}
@@ -140,16 +149,95 @@ bool ControlGatewayClient::build_goal(
}
goal.goal.selected_task.value = selected_task_type;
- goal.goal.trajectory_tracking.stop_at_end = true; // 执行完后停车,保证安全。
- goal.goal.trajectory_tracking.timeout_sec = 60.0;
+ std::unordered_map metadata_map;
+ for (const auto & kv : stage.metadata) {
+ metadata_map[kv.key] = kv.value;
+ }
- // 轨迹必须由流程配置显式提供;编排器不再隐式生成默认轨迹。
- goal.goal.trajectory_tracking.path = build_trajectory_from_metadata(stage, failure_reason);
- if (goal.goal.trajectory_tracking.path.empty()) {
- if (failure_reason.empty()) {
- failure_reason = "运控阶段缺少轨迹输入,无法启动评估任务。";
+ if (selected_task_type == ControllerEvaluationTaskType::TRAJECTORY_TRACKING) {
+ goal.goal.trajectory_tracking.stop_at_end = true; // 执行完后停车,保证安全。
+ goal.goal.trajectory_tracking.timeout_sec = 60.0;
+
+ const auto stop_it = metadata_map.find(metadata_keys::CONTROL_STOP_AT_END);
+ if (stop_it != metadata_map.end()) {
+ goal.goal.trajectory_tracking.stop_at_end =
+ stop_it->second == "true" || stop_it->second == "1" || stop_it->second == "TRUE";
+ }
+
+ const auto timeout_it = metadata_map.find(metadata_keys::CONTROL_TIMEOUT_SEC);
+ if (timeout_it != metadata_map.end()) {
+ try {
+ goal.goal.trajectory_tracking.timeout_sec = std::stod(timeout_it->second);
+ } catch (...) {
+ failure_reason = "control.timeout_sec 格式错误。";
+ return false;
+ }
+ }
+
+ // 轨迹必须由流程配置显式提供;编排器不再隐式生成默认轨迹。
+ goal.goal.trajectory_tracking.path = build_trajectory_from_metadata(stage, failure_reason);
+ if (goal.goal.trajectory_tracking.path.empty()) {
+ if (failure_reason.empty()) {
+ failure_reason = "运控阶段缺少轨迹输入,无法启动评估任务。";
+ }
+ return false;
+ }
+ } else if (selected_task_type == ControllerEvaluationTaskType::VELOCITY_STEP) {
+ const auto velocity_it = metadata_map.find(metadata_keys::CONTROL_VELOCITY_STEP_TARGET_VELOCITY_MS);
+ const auto hold_it = metadata_map.find(metadata_keys::CONTROL_VELOCITY_STEP_HOLD_TIME_SEC);
+ const auto settle_it = metadata_map.find(metadata_keys::CONTROL_VELOCITY_STEP_SETTLE_BEFORE_STEP_SEC);
+ if (velocity_it == metadata_map.end() || hold_it == metadata_map.end() || settle_it == metadata_map.end()) {
+ failure_reason = "velocity_step 缺少 target_velocity_ms、hold_time_sec 或 settle_before_step_sec。";
+ return false;
+ }
+ try {
+ goal.goal.velocity_step.target_velocity_ms = std::stod(velocity_it->second);
+ goal.goal.velocity_step.hold_time_sec = std::stod(hold_it->second);
+ goal.goal.velocity_step.settle_before_step_sec = std::stod(settle_it->second);
+ } catch (...) {
+ failure_reason = "velocity_step 参数格式错误。";
+ return false;
+ }
+ } else if (selected_task_type == ControllerEvaluationTaskType::ACCELERATION_DECELERATION) {
+ const auto start_it = metadata_map.find(metadata_keys::CONTROL_ACCEL_DECEL_START_VELOCITY_MS);
+ const auto target_it = metadata_map.find(metadata_keys::CONTROL_ACCEL_DECEL_TARGET_VELOCITY_MS);
+ const auto accel_it = metadata_map.find(metadata_keys::CONTROL_ACCEL_DECEL_TARGET_ACCEL_MS2);
+ const auto hold_it = metadata_map.find(metadata_keys::CONTROL_ACCEL_DECEL_HOLD_TIME_SEC);
+ if (start_it == metadata_map.end() || target_it == metadata_map.end() ||
+ accel_it == metadata_map.end() || hold_it == metadata_map.end())
+ {
+ failure_reason = "accel_decel 缺少 start_velocity_ms、target_velocity_ms、target_accel_ms2 或 hold_time_sec。";
+ return false;
+ }
+ try {
+ goal.goal.accel_decel.start_velocity_ms = std::stod(start_it->second);
+ goal.goal.accel_decel.target_velocity_ms = std::stod(target_it->second);
+ goal.goal.accel_decel.target_accel_ms2 = std::stod(accel_it->second);
+ goal.goal.accel_decel.hold_time_sec = std::stod(hold_it->second);
+ } catch (...) {
+ failure_reason = "accel_decel 参数格式错误。";
+ return false;
+ }
+ } else if (selected_task_type == ControllerEvaluationTaskType::STOP_ACCURACY) {
+ const auto x_it = metadata_map.find(metadata_keys::CONTROL_STOP_ACCURACY_X_M);
+ const auto y_it = metadata_map.find(metadata_keys::CONTROL_STOP_ACCURACY_Y_M);
+ const auto yaw_it = metadata_map.find(metadata_keys::CONTROL_STOP_ACCURACY_YAW_RAD);
+ const auto timeout_it = metadata_map.find(metadata_keys::CONTROL_TIMEOUT_SEC);
+ if (x_it == metadata_map.end() || y_it == metadata_map.end() ||
+ yaw_it == metadata_map.end() || timeout_it == metadata_map.end())
+ {
+ failure_reason = "stop_accuracy 缺少 target_stop_x_m、target_stop_y_m、target_stop_yaw_rad 或 control.timeout_sec。";
+ return false;
+ }
+ try {
+ goal.goal.stop_accuracy.target_stop_x_m = std::stod(x_it->second);
+ goal.goal.stop_accuracy.target_stop_y_m = std::stod(y_it->second);
+ goal.goal.stop_accuracy.target_stop_yaw_rad = std::stod(yaw_it->second);
+ goal.goal.stop_accuracy.timeout_sec = std::stod(timeout_it->second);
+ } catch (...) {
+ failure_reason = "stop_accuracy 参数格式错误。";
+ return false;
}
- return false;
}
goal.goal.source_iteration_id = session.session_id;
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/external_localization_client.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/main.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/main.cpp
similarity index 100%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/main.cpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/main.cpp
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp
similarity index 54%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp
index f2c4c6e..5e6c019 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/plan_builder.cpp
@@ -4,8 +4,198 @@ namespace workshop_orchestrator_v2
{
using calibration_vehicle_profile_interfaces::msg::CalibrationAbilityType;
+using calibration_vehicle_profile_interfaces::msg::CameraMountType;
+using calibration_vehicle_profile_interfaces::msg::SensorProfile;
+using calibration_vehicle_profile_interfaces::msg::SensorType;
using calibration_workshop_orchestration_interfaces::msg::StageExecutionPolicy;
+namespace
+{
+
+void add_metadata_if_missing(StagePlan & stage, const std::string & key, const std::string & value)
+{
+ for (const auto & kv : stage.metadata) {
+ if (kv.key == key) {
+ return;
+ }
+ }
+ calibration_common_interfaces::msg::KeyValuePair kv;
+ kv.key = key;
+ kv.value = value;
+ stage.metadata.push_back(kv);
+}
+
+const SensorProfile * find_default_sensor(
+ const VehicleProfile & profile,
+ bool require_intrinsic,
+ bool require_extrinsic)
+{
+ for (const auto & sensor : profile.sensors) {
+ if (!sensor.enabled || !sensor.selected_for_this_session) {
+ continue;
+ }
+ if (require_intrinsic &&
+ (!sensor.needs_intrinsic_calibration || !sensor.supports_intrinsic_calibration))
+ {
+ continue;
+ }
+ if (require_extrinsic &&
+ (!sensor.needs_extrinsic_calibration || !sensor.supports_extrinsic_calibration))
+ {
+ continue;
+ }
+ return &sensor;
+ }
+
+ for (const auto & sensor : profile.sensors) {
+ if (!sensor.enabled) {
+ continue;
+ }
+ if (require_intrinsic && !sensor.supports_intrinsic_calibration) {
+ continue;
+ }
+ if (require_extrinsic && !sensor.supports_extrinsic_calibration) {
+ continue;
+ }
+ return &sensor;
+ }
+
+ return nullptr;
+}
+
+std::string resolve_intrinsic_subtype(const SensorProfile & sensor)
+{
+ if (sensor.sensor_type.value == SensorType::IMU) {
+ return "imu_intrinsic";
+ }
+ if (sensor.camera_mount_type.value == CameraMountType::DOWNWARD_MOUNTED ||
+ sensor.sensor_type.value == SensorType::DOWNWARD_CAMERA)
+ {
+ return "downward_camera_intrinsic";
+ }
+ return "front_camera_intrinsic";
+}
+
+std::string resolve_extrinsic_subtype(const SensorProfile & sensor)
+{
+ if (sensor.sensor_type.value == SensorType::IMU) {
+ return "imu_extrinsic";
+ }
+ if (sensor.sensor_type.value == SensorType::LIDAR_2D) {
+ return "lidar_2d_extrinsic";
+ }
+ if (sensor.sensor_type.value == SensorType::LIDAR_3D) {
+ return "lidar_3d_extrinsic";
+ }
+ if (sensor.camera_mount_type.value == CameraMountType::DOWNWARD_MOUNTED ||
+ sensor.sensor_type.value == SensorType::DOWNWARD_CAMERA)
+ {
+ return "downward_camera_extrinsic";
+ }
+ return "front_camera_extrinsic";
+}
+
+std::string resolve_hand_eye_subtype(const SensorProfile & sensor)
+{
+ if (sensor.camera_mount_type.value == CameraMountType::EYE_TO_HAND) {
+ return "eye_to_hand";
+ }
+ return "eye_in_hand";
+}
+
+void apply_default_external_metadata(StagePlan & stage)
+{
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_STATIC_SAMPLE_COUNT, "10");
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_DYNAMIC_SAMPLE_COUNT, "20");
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_REQUIRE_SHORT_MOTION_SEGMENT, "true");
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_MAX_POSITION_STDDEV_M, "0.05");
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_MAX_YAW_STDDEV_RAD, "0.05");
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_MAX_TRACKING_LOSS_RATIO, "0.05");
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_MAX_TIME_SYNC_OFFSET_MS, "50.0");
+ add_metadata_if_missing(stage, metadata_keys::EXTERNAL_TIMEOUT_SEC, "30.0");
+}
+
+void apply_default_chassis_metadata(StagePlan & stage)
+{
+ add_metadata_if_missing(stage, metadata_keys::CHASSIS_PRIMITIVE_TYPE, "straight_line");
+ add_metadata_if_missing(stage, metadata_keys::CHASSIS_STRAIGHT_LINE_DISTANCE_M, "2.0");
+ add_metadata_if_missing(stage, metadata_keys::CHASSIS_STRAIGHT_LINE_SPEED_MS, "0.5");
+ add_metadata_if_missing(stage, metadata_keys::COMMON_BRAKE_WHEN_FINISHED, "true");
+ add_metadata_if_missing(stage, metadata_keys::COMMON_TIMEOUT_SEC, "60.0");
+}
+
+void apply_default_control_metadata(StagePlan & stage)
+{
+ add_metadata_if_missing(stage, metadata_keys::CONTROL_TASK_TYPE, "trajectory_tracking");
+ add_metadata_if_missing(stage, metadata_keys::CONTROL_STOP_AT_END, "true");
+ add_metadata_if_missing(stage, metadata_keys::CONTROL_TIMEOUT_SEC, "60.0");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "0_x_m", "0.0");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "0_y_m", "0.0");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "0_yaw_rad", "0.0");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "0_speed_ms", "0.3");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "1_x_m", "2.0");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "1_y_m", "0.0");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "1_yaw_rad", "0.0");
+ add_metadata_if_missing(stage, std::string(metadata_keys::CONTROL_TRAJECTORY_PREFIX) + "1_speed_ms", "0.3");
+}
+
+void apply_default_sensor_intrinsic_metadata(StagePlan & stage, const VehicleProfile & profile)
+{
+ const auto * sensor = find_default_sensor(profile, true, false);
+ if (!sensor) {
+ return;
+ }
+
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_ID, sensor->sensor_id);
+ const auto subtype = resolve_intrinsic_subtype(*sensor);
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_TASK_SUBTYPE, subtype);
+
+ if (subtype == "imu_intrinsic") {
+ add_metadata_if_missing(stage, metadata_keys::IMU_INTRINSIC_REQUIRED_STATIC_SEGMENT_COUNT, "5");
+ add_metadata_if_missing(stage, metadata_keys::IMU_INTRINSIC_REQUIRED_MOTION_SEGMENT_COUNT, "5");
+ add_metadata_if_missing(stage, metadata_keys::IMU_INTRINSIC_TIMEOUT_SEC, "120.0");
+ return;
+ }
+
+ add_metadata_if_missing(stage, metadata_keys::CAMERA_INTRINSIC_REQUIRED_IMAGE_COUNT, "20");
+ add_metadata_if_missing(stage, metadata_keys::CAMERA_INTRINSIC_TIMEOUT_SEC, "120.0");
+}
+
+void apply_default_sensor_extrinsic_metadata(StagePlan & stage, const VehicleProfile & profile)
+{
+ const auto * sensor = find_default_sensor(profile, false, true);
+ if (!sensor) {
+ return;
+ }
+
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_ID, sensor->sensor_id);
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_TASK_SUBTYPE, resolve_extrinsic_subtype(*sensor));
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_EXTRINSIC_BASE_FRAME_ID,
+ profile.base_link_frame.empty() ? "base_link" : profile.base_link_frame);
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_EXTRINSIC_REQUIRED_SAMPLE_COUNT, "10");
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_EXTRINSIC_TIMEOUT_SEC, "180.0");
+}
+
+void apply_default_hand_eye_metadata(StagePlan & stage, const VehicleProfile & profile)
+{
+ if (!profile.arm_profile.has_mechanical_arm || profile.arm_profile.arm_id.empty()) {
+ return;
+ }
+
+ const auto * sensor = find_default_sensor(profile, false, true);
+ if (!sensor) {
+ return;
+ }
+
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_ID, sensor->sensor_id);
+ add_metadata_if_missing(stage, metadata_keys::SENSOR_TASK_SUBTYPE, resolve_hand_eye_subtype(*sensor));
+ add_metadata_if_missing(stage, metadata_keys::HAND_EYE_ARM_ID, profile.arm_profile.arm_id);
+ add_metadata_if_missing(stage, metadata_keys::HAND_EYE_REQUIRED_POSE_COUNT, "12");
+ add_metadata_if_missing(stage, metadata_keys::HAND_EYE_TIMEOUT_SEC, "180.0");
+}
+
+} // namespace
+
bool PlanBuilder::has_capability(const VehicleProfile & profile, uint8_t ability_type) const
{
for (const auto & cap : profile.capabilities) {
@@ -123,25 +313,28 @@ std::string PlanBuilder::make_task_suffix(const std::string & task_code) const
return suffix;
}
-StagePlan PlanBuilder::make_stage_for_task(int order_index, const RequestedCalibrationTask & task) const
+StagePlan PlanBuilder::make_stage_for_task(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask & task) const
{
if (task.stage_type.value == WorkflowStageType::CHASSIS_CALIBRATION_STAGE) {
- return make_chassis_stage(order_index, &task);
+ return make_chassis_stage(order_index, profile, &task);
}
if (task.stage_type.value == WorkflowStageType::CONTROL_CALIBRATION_STAGE) {
- return make_control_stage(order_index, &task);
+ return make_control_stage(order_index, profile, &task);
}
if (task.stage_type.value == WorkflowStageType::SENSOR_INTRINSIC_CALIBRATION_STAGE) {
- return make_sensor_intrinsic_stage(order_index, &task);
+ return make_sensor_intrinsic_stage(order_index, profile, &task);
}
if (task.stage_type.value == WorkflowStageType::SENSOR_EXTRINSIC_CALIBRATION_STAGE) {
- return make_sensor_extrinsic_stage(order_index, &task);
+ return make_sensor_extrinsic_stage(order_index, profile, &task);
}
if (task.stage_type.value == WorkflowStageType::HAND_EYE_CALIBRATION_STAGE) {
- return make_hand_eye_stage(order_index, &task);
+ return make_hand_eye_stage(order_index, profile, &task);
}
if (task.stage_type.value == WorkflowStageType::EXTERNAL_REFERENCE_READY_CHECK_STAGE) {
- return make_external_reference_stage(order_index, &task);
+ return make_external_reference_stage(order_index, profile, &task);
}
StagePlan stage;
@@ -196,18 +389,19 @@ std::vector PlanBuilder::build_minimal_plan(
continue;
}
}
- stages.push_back(make_stage_for_task(order++, task));
+ stages.push_back(make_stage_for_task(order++, profile, task));
}
}
return stages;
}
- // 外部真值校核:始终加入(除非 requested_tasks 中显式 enabled=false)。
+ // 外部真值校核:默认依赖 external localization 能力;若 requested_tasks 显式要求则仍可纳入。
if (should_include_stage(profile, config,
- WorkflowStageType::EXTERNAL_REFERENCE_READY_CHECK_STAGE, 0)) {
+ WorkflowStageType::EXTERNAL_REFERENCE_READY_CHECK_STAGE,
+ CalibrationAbilityType::EXTERNAL_LOCALIZATION_CALIBRATION)) {
const auto * task_cfg = find_requested_task(config,
WorkflowStageType::EXTERNAL_REFERENCE_READY_CHECK_STAGE);
- stages.push_back(make_external_reference_stage(order++, task_cfg));
+ stages.push_back(make_external_reference_stage(order++, profile, task_cfg));
}
// 底盘标定。
@@ -216,7 +410,7 @@ std::vector PlanBuilder::build_minimal_plan(
CalibrationAbilityType::CHASSIS_CALIBRATION)) {
const auto * task_cfg = find_requested_task(config,
WorkflowStageType::CHASSIS_CALIBRATION_STAGE);
- stages.push_back(make_chassis_stage(order++, task_cfg));
+ stages.push_back(make_chassis_stage(order++, profile, task_cfg));
}
// 运控参数标定。
@@ -225,7 +419,7 @@ std::vector PlanBuilder::build_minimal_plan(
CalibrationAbilityType::CONTROL_CALIBRATION)) {
const auto * task_cfg = find_requested_task(config,
WorkflowStageType::CONTROL_CALIBRATION_STAGE);
- stages.push_back(make_control_stage(order++, task_cfg));
+ stages.push_back(make_control_stage(order++, profile, task_cfg));
}
// 传感器内参标定。
@@ -234,7 +428,7 @@ std::vector PlanBuilder::build_minimal_plan(
CalibrationAbilityType::SENSOR_CALIBRATION)) {
const auto * task_cfg = find_requested_task(config,
WorkflowStageType::SENSOR_INTRINSIC_CALIBRATION_STAGE);
- stages.push_back(make_sensor_intrinsic_stage(order++, task_cfg));
+ stages.push_back(make_sensor_intrinsic_stage(order++, profile, task_cfg));
}
// 传感器外参标定。
@@ -243,7 +437,7 @@ std::vector PlanBuilder::build_minimal_plan(
CalibrationAbilityType::SENSOR_CALIBRATION)) {
const auto * task_cfg = find_requested_task(config,
WorkflowStageType::SENSOR_EXTRINSIC_CALIBRATION_STAGE);
- stages.push_back(make_sensor_extrinsic_stage(order++, task_cfg));
+ stages.push_back(make_sensor_extrinsic_stage(order++, profile, task_cfg));
}
// 手眼标定。
@@ -252,13 +446,16 @@ std::vector PlanBuilder::build_minimal_plan(
CalibrationAbilityType::HAND_EYE_CALIBRATION)) {
const auto * task_cfg = find_requested_task(config,
WorkflowStageType::HAND_EYE_CALIBRATION_STAGE);
- stages.push_back(make_hand_eye_stage(order++, task_cfg));
+ stages.push_back(make_hand_eye_stage(order++, profile, task_cfg));
}
return stages;
}
-StagePlan PlanBuilder::make_external_reference_stage(int order_index, const RequestedCalibrationTask * task_cfg) const
+StagePlan PlanBuilder::make_external_reference_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const
{
StagePlan stage;
stage.stage_id = "stage_external_reference";
@@ -270,11 +467,19 @@ StagePlan PlanBuilder::make_external_reference_stage(int order_index, const Requ
stage.description = "验证并接入车间外部定位真值参考源。需要 session.config 提供 localization_source_id/workcell_zone_id;stage.metadata 需要提供 external.static_sample_count、external.dynamic_sample_count、external.max_position_stddev_m、external.max_yaw_stddev_rad、external.max_tracking_loss_ratio、external.max_time_sync_offset_ms、external.timeout_sec。";
stage.retry_limit = 0;
stage.auto_generated = true;
+ apply_default_external_metadata(stage);
apply_task_config(stage, task_cfg);
+ if (task_cfg) {
+ stage.stage_id += make_task_suffix(task_cfg->task_code);
+ apply_task_identity(stage, *task_cfg);
+ }
return stage;
}
-StagePlan PlanBuilder::make_chassis_stage(int order_index, const RequestedCalibrationTask * task_cfg) const
+StagePlan PlanBuilder::make_chassis_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const
{
StagePlan stage;
stage.stage_id = "stage_chassis_calibration";
@@ -283,9 +488,10 @@ StagePlan PlanBuilder::make_chassis_stage(int order_index, const RequestedCalibr
stage.display_name = "底盘标定";
stage.order_index = order_index;
stage.executor_endpoint_name = "/chassis/execute_motion_primitive";
- stage.description = "调用独立底盘标定包执行动作原语任务。stage.metadata 需要提供 primitive_type;当前最小流支持 straight_line,并要求 straight_line.target_distance_m、straight_line.target_speed_ms;可选 straight_line.reverse、brake_when_finished、timeout_sec。";
+ stage.description = "调用独立底盘标定包执行动作原语任务。stage.metadata 需要提供 primitive_type;支持 straight_line、arc、in_place_rotation、steering_sweep、lateral_translation、diagonal_motion、module_alignment、coordinated_steering。各动作分别消费对应 metadata 参数,并通用支持 brake_when_finished、timeout_sec。";
stage.retry_limit = 1;
stage.auto_generated = true;
+ apply_default_chassis_metadata(stage);
apply_task_config(stage, task_cfg);
if (task_cfg) {
stage.stage_id += make_task_suffix(task_cfg->task_code);
@@ -294,7 +500,10 @@ StagePlan PlanBuilder::make_chassis_stage(int order_index, const RequestedCalibr
return stage;
}
-StagePlan PlanBuilder::make_control_stage(int order_index, const RequestedCalibrationTask * task_cfg) const
+StagePlan PlanBuilder::make_control_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const
{
StagePlan stage;
stage.stage_id = "stage_control_calibration";
@@ -303,9 +512,10 @@ StagePlan PlanBuilder::make_control_stage(int order_index, const RequestedCalibr
stage.display_name = "运控参数调优";
stage.order_index = order_index;
stage.executor_endpoint_name = "/control/execute_controller_evaluation";
- stage.description = "调用独立运控标定包执行控制评估任务。stage.metadata 需要提供 control.task_type;当前最小流支持 trajectory_tracking,并要求至少一组 traj_pt_{i}_{x_m|y_m|yaw_rad|speed_ms} 轨迹点。";
+ stage.description = "调用独立运控标定包执行控制评估任务。stage.metadata 需要提供 control.task_type;支持 trajectory_tracking、velocity_step、accel_decel、stop_accuracy。trajectory_tracking 需提供 traj_pt_{i}_{x_m|y_m|yaw_rad|speed_ms},其余任务需提供各自目标速度、加速度、停车目标与 timeout 等参数。";
stage.retry_limit = 0;
stage.auto_generated = true;
+ apply_default_control_metadata(stage);
apply_task_config(stage, task_cfg);
if (task_cfg) {
stage.stage_id += make_task_suffix(task_cfg->task_code);
@@ -314,7 +524,10 @@ StagePlan PlanBuilder::make_control_stage(int order_index, const RequestedCalibr
return stage;
}
-StagePlan PlanBuilder::make_sensor_intrinsic_stage(int order_index, const RequestedCalibrationTask * task_cfg) const
+StagePlan PlanBuilder::make_sensor_intrinsic_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const
{
StagePlan stage;
stage.stage_id = "stage_sensor_intrinsic_calibration";
@@ -323,9 +536,10 @@ StagePlan PlanBuilder::make_sensor_intrinsic_stage(int order_index, const Reques
stage.display_name = "传感器内参标定";
stage.order_index = order_index;
stage.executor_endpoint_name = "/sensor_calibration/execute_task";
- stage.description = "启动独立传感器标定包执行内参标定任务。stage.metadata 需要提供 sensor.sensor_id、camera_intrinsic.required_image_count;可选 camera_intrinsic.target_board_id、camera_intrinsic.timeout_sec。";
+ stage.description = "启动独立传感器标定包执行内参标定任务。stage.metadata 需要提供 sensor.sensor_id、sensor.task_subtype;相机内参任务需提供 camera_intrinsic.required_image_count,可选 target_board_id/timeout_sec;IMU 内参任务需提供 imu_intrinsic.required_static_segment_count、imu_intrinsic.required_motion_segment_count,可选 imu_intrinsic.timeout_sec。";
stage.retry_limit = 0;
stage.auto_generated = true;
+ apply_default_sensor_intrinsic_metadata(stage, profile);
apply_task_config(stage, task_cfg);
if (task_cfg) {
stage.stage_id += make_task_suffix(task_cfg->task_code);
@@ -334,7 +548,10 @@ StagePlan PlanBuilder::make_sensor_intrinsic_stage(int order_index, const Reques
return stage;
}
-StagePlan PlanBuilder::make_sensor_extrinsic_stage(int order_index, const RequestedCalibrationTask * task_cfg) const
+StagePlan PlanBuilder::make_sensor_extrinsic_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const
{
StagePlan stage;
stage.stage_id = "stage_sensor_extrinsic_calibration";
@@ -346,6 +563,7 @@ StagePlan PlanBuilder::make_sensor_extrinsic_stage(int order_index, const Reques
stage.description = "启动独立传感器标定包执行外参标定任务。stage.metadata 需要提供 sensor.sensor_id、sensor_extrinsic.base_frame_id、sensor_extrinsic.required_sample_count;可选 sensor_extrinsic.timeout_sec。";
stage.retry_limit = 0;
stage.auto_generated = true;
+ apply_default_sensor_extrinsic_metadata(stage, profile);
apply_task_config(stage, task_cfg);
if (task_cfg) {
stage.stage_id += make_task_suffix(task_cfg->task_code);
@@ -354,7 +572,10 @@ StagePlan PlanBuilder::make_sensor_extrinsic_stage(int order_index, const Reques
return stage;
}
-StagePlan PlanBuilder::make_hand_eye_stage(int order_index, const RequestedCalibrationTask * task_cfg) const
+StagePlan PlanBuilder::make_hand_eye_stage(
+ int order_index,
+ const VehicleProfile & profile,
+ const RequestedCalibrationTask * task_cfg) const
{
StagePlan stage;
stage.stage_id = "stage_hand_eye_calibration";
@@ -366,6 +587,7 @@ StagePlan PlanBuilder::make_hand_eye_stage(int order_index, const RequestedCalib
stage.description = "启动独立传感器标定包执行手眼标定任务。stage.metadata 需要提供 sensor.sensor_id、hand_eye.arm_id、hand_eye.required_pose_count;可选 hand_eye.timeout_sec。";
stage.retry_limit = 0;
stage.auto_generated = true;
+ apply_default_hand_eye_metadata(stage, profile);
apply_task_config(stage, task_cfg);
if (task_cfg) {
stage.stage_id += make_task_suffix(task_cfg->task_code);
diff --git a/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp
new file mode 100644
index 0000000..227626e
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/precheck_runner.cpp
@@ -0,0 +1,263 @@
+#include "workshop_orchestrator_v2/precheck_runner.hpp"
+
+#include "calibration_workshop_orchestration_interfaces/msg/precheck_item.hpp"
+
+namespace workshop_orchestrator_v2
+{
+
+bool PrecheckRunner::has_metadata_key(const StagePlan & stage, const std::string & key) const
+{
+ for (const auto & kv : stage.metadata) {
+ if (kv.key == key) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PrecheckRunner::has_metadata_prefix(const StagePlan & stage, const std::string & prefix) const
+{
+ for (const auto & kv : stage.metadata) {
+ if (kv.key.rfind(prefix, 0) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+WorkshopPrecheckResponse PrecheckRunner::run(const WorkshopSession & session) const
+{
+ WorkshopPrecheckResponse response;
+ response.success = true;
+ response.error_code = make_error_code(ErrorCode::OK);
+ response.checked_timestamp_us = now_us();
+
+ auto append_item = [&](const std::string & code,
+ const std::string & name,
+ bool passed,
+ const std::string & message,
+ uint8_t stage_type,
+ uint8_t module_type) {
+ calibration_workshop_orchestration_interfaces::msg::PrecheckItem item;
+ item.item_code = code;
+ item.display_name = name;
+ item.passed = passed;
+ item.blocking = true;
+ item.error_code = make_error_code(passed ? ErrorCode::OK : ErrorCode::INVALID_STATE);
+ item.message = message;
+ item.related_stage_type = make_stage_type(stage_type);
+ item.related_module_type = make_module_type(module_type);
+ response.items.push_back(item);
+ if (!passed) {
+ response.blocking_issue_count += 1;
+ response.all_passed = false;
+ }
+ };
+
+ response.all_passed = true;
+ response.blocking_issue_count = 0;
+
+ append_item(
+ "plan_not_empty",
+ "Execution plan exists",
+ !session.stage_plan.empty(),
+ session.stage_plan.empty() ? "Session has no executable stages." : "Session has executable stages.",
+ WorkflowStageType::WORKFLOW_STAGE_UNSPECIFIED,
+ CalibrationModuleType::CALIBRATION_MODULE_UNSPECIFIED);
+
+ for (const auto & stage : session.stage_plan) {
+ if (stage.module_type.value == CalibrationModuleType::CHASSIS_MODULE) {
+ const bool has_primitive_type = has_metadata_key(stage, metadata_keys::CHASSIS_PRIMITIVE_TYPE);
+ bool passed = false;
+ std::string message = "底盘阶段缺少 primitive_type。";
+
+ if (has_primitive_type) {
+ std::string primitive_type;
+ for (const auto & kv : stage.metadata) {
+ if (kv.key == metadata_keys::CHASSIS_PRIMITIVE_TYPE) {
+ primitive_type = kv.value;
+ break;
+ }
+ }
+
+ if (primitive_type == "straight_line") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_STRAIGHT_LINE_DISTANCE_M) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_STRAIGHT_LINE_SPEED_MS);
+ message = passed ? "底盘直行动作输入完整。" : "straight_line 缺少距离或速度参数。";
+ } else if (primitive_type == "arc") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_ARC_SPEED_MS) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_ARC_RADIUS_M) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_ARC_SWEEP_ANGLE_DEG);
+ message = passed ? "底盘圆弧动作输入完整。" : "arc 缺少速度、半径或扫角参数。";
+ } else if (primitive_type == "in_place_rotation") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_ROTATION_TARGET_YAW_DEG) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_ROTATION_TARGET_ANGULAR_VEL_DEG_S);
+ message = passed ? "原地旋转动作输入完整。" : "in_place_rotation 缺少角度或角速度参数。";
+ } else if (primitive_type == "steering_sweep") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_STEERING_SWEEP_TARGET_ANGLE_DEG) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_STEERING_SWEEP_AMPLITUDE_DEG) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_STEERING_SWEEP_FREQUENCY_HZ) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_STEERING_SWEEP_DURATION_SEC);
+ message = passed ? "舵角扫动动作输入完整。" : "steering_sweep 缺少目标角、幅值、频率或持续时间。";
+ } else if (primitive_type == "lateral_translation") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_LATERAL_SPEED_MS) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_LATERAL_DISTANCE_M);
+ message = passed ? "横移动作输入完整。" : "lateral_translation 缺少速度或距离参数。";
+ } else if (primitive_type == "diagonal_motion") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_DIAGONAL_SPEED_MS) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_DIAGONAL_DISTANCE_M) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_DIAGONAL_HEADING_DEG);
+ message = passed ? "斜移动作输入完整。" : "diagonal_motion 缺少速度、距离或方向角参数。";
+ } else if (primitive_type == "module_alignment") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_MODULE_ALIGNMENT_IDS) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_MODULE_ALIGNMENT_ZERO_DEG) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_MODULE_ALIGNMENT_TOLERANCE_DEG);
+ message = passed ? "模块零位检查输入完整。" : "module_alignment 缺少模块列表、零位或容差参数。";
+ } else if (primitive_type == "coordinated_steering") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CHASSIS_COORDINATED_STEERING_IDS) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_COORDINATED_STEERING_TARGET_ANGLE_DEG) &&
+ has_metadata_key(stage, metadata_keys::CHASSIS_COORDINATED_STEERING_HOLD_TIME_SEC);
+ message = passed ? "协同转向动作输入完整。" : "coordinated_steering 缺少模块列表、目标角或保持时间参数。";
+ } else {
+ message = "底盘阶段 primitive_type 不受支持。";
+ }
+ }
+
+ append_item(
+ stage.stage_id + ".metadata",
+ stage.display_name + " metadata",
+ passed,
+ message,
+ stage.stage_type.value,
+ stage.module_type.value);
+ } else if (stage.module_type.value == CalibrationModuleType::CONTROL_MODULE) {
+ bool has_task_type = has_metadata_key(stage, metadata_keys::CONTROL_TASK_TYPE);
+ bool passed = false;
+ std::string message = "运控阶段缺少 control.task_type。";
+ std::string task_type;
+ if (has_task_type) {
+ for (const auto & kv : stage.metadata) {
+ if (kv.key == metadata_keys::CONTROL_TASK_TYPE) {
+ task_type = kv.value;
+ break;
+ }
+ }
+
+ if (task_type == "trajectory_tracking") {
+ passed = has_metadata_prefix(stage, metadata_keys::CONTROL_TRAJECTORY_PREFIX);
+ message = passed ? "轨迹跟踪任务输入完整。" : "trajectory_tracking 缺少轨迹点输入。";
+ } else if (task_type == "velocity_step") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CONTROL_VELOCITY_STEP_TARGET_VELOCITY_MS) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_VELOCITY_STEP_HOLD_TIME_SEC) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_VELOCITY_STEP_SETTLE_BEFORE_STEP_SEC);
+ message = passed ? "速度阶跃任务输入完整。" : "velocity_step 缺少目标速度、保持时间或阶跃前静稳时间。";
+ } else if (task_type == "accel_decel") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CONTROL_ACCEL_DECEL_START_VELOCITY_MS) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_ACCEL_DECEL_TARGET_VELOCITY_MS) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_ACCEL_DECEL_TARGET_ACCEL_MS2) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_ACCEL_DECEL_HOLD_TIME_SEC);
+ message = passed ? "加减速任务输入完整。" : "accel_decel 缺少起始速度、目标速度、目标加速度或保持时间。";
+ } else if (task_type == "stop_accuracy") {
+ passed =
+ has_metadata_key(stage, metadata_keys::CONTROL_STOP_ACCURACY_X_M) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_STOP_ACCURACY_Y_M) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_STOP_ACCURACY_YAW_RAD) &&
+ has_metadata_key(stage, metadata_keys::CONTROL_TIMEOUT_SEC);
+ message = passed ? "停车精度任务输入完整。" : "stop_accuracy 缺少目标停车位姿或 control.timeout_sec。";
+ } else {
+ message = "运控阶段 control.task_type 不受支持。";
+ }
+ }
+
+ append_item(
+ stage.stage_id + ".metadata",
+ stage.display_name + " metadata",
+ passed,
+ message,
+ stage.stage_type.value,
+ stage.module_type.value);
+ } else if (
+ stage.module_type.value == CalibrationModuleType::SENSOR_INTRINSIC_MODULE ||
+ stage.module_type.value == CalibrationModuleType::SENSOR_EXTRINSIC_MODULE ||
+ stage.module_type.value == CalibrationModuleType::HAND_EYE_MODULE) {
+ bool passed =
+ has_metadata_key(stage, metadata_keys::SENSOR_ID) &&
+ has_metadata_key(stage, metadata_keys::SENSOR_TASK_SUBTYPE);
+ std::string message = passed ? "传感器阶段基础输入完整。" : "传感器阶段缺少 sensor.sensor_id 或 sensor.task_subtype。";
+
+ if (passed && stage.module_type.value == CalibrationModuleType::SENSOR_INTRINSIC_MODULE) {
+ std::string subtype;
+ for (const auto & kv : stage.metadata) {
+ if (kv.key == metadata_keys::SENSOR_TASK_SUBTYPE) {
+ subtype = kv.value;
+ break;
+ }
+ }
+
+ if (subtype == "imu_intrinsic") {
+ passed =
+ has_metadata_key(stage, metadata_keys::IMU_INTRINSIC_REQUIRED_STATIC_SEGMENT_COUNT) &&
+ has_metadata_key(stage, metadata_keys::IMU_INTRINSIC_REQUIRED_MOTION_SEGMENT_COUNT);
+ message = passed ? "IMU 内参阶段输入完整。" : "IMU 内参阶段缺少静止段数或运动段数。";
+ } else {
+ passed = has_metadata_key(stage, metadata_keys::CAMERA_INTRINSIC_REQUIRED_IMAGE_COUNT);
+ message = passed ? "相机内参阶段输入完整。" : "相机内参阶段缺少 required_image_count。";
+ }
+ }
+
+ if (passed && stage.module_type.value == CalibrationModuleType::SENSOR_EXTRINSIC_MODULE) {
+ passed =
+ has_metadata_key(stage, metadata_keys::SENSOR_EXTRINSIC_BASE_FRAME_ID) &&
+ has_metadata_key(stage, metadata_keys::SENSOR_EXTRINSIC_REQUIRED_SAMPLE_COUNT);
+ message = passed ? "传感器外参阶段输入完整。" : "传感器外参阶段缺少 base_frame_id 或 required_sample_count。";
+ }
+
+ if (passed && stage.module_type.value == CalibrationModuleType::HAND_EYE_MODULE) {
+ passed =
+ has_metadata_key(stage, metadata_keys::HAND_EYE_ARM_ID) &&
+ has_metadata_key(stage, metadata_keys::HAND_EYE_REQUIRED_POSE_COUNT);
+ message = passed ? "手眼阶段输入完整。" : "手眼阶段缺少 arm_id 或 required_pose_count。";
+ }
+
+ append_item(
+ stage.stage_id + ".metadata",
+ stage.display_name + " metadata",
+ passed,
+ message,
+ stage.stage_type.value,
+ stage.module_type.value);
+ } else if (stage.module_type.value == CalibrationModuleType::EXTERNAL_LOCALIZATION_MODULE) {
+ const bool passed =
+ has_metadata_key(stage, metadata_keys::EXTERNAL_STATIC_SAMPLE_COUNT) &&
+ has_metadata_key(stage, metadata_keys::EXTERNAL_DYNAMIC_SAMPLE_COUNT) &&
+ has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_POSITION_STDDEV_M) &&
+ has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_YAW_STDDEV_RAD) &&
+ has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_TRACKING_LOSS_RATIO) &&
+ has_metadata_key(stage, metadata_keys::EXTERNAL_MAX_TIME_SYNC_OFFSET_MS) &&
+ has_metadata_key(stage, metadata_keys::EXTERNAL_TIMEOUT_SEC);
+ append_item(
+ stage.stage_id + ".metadata",
+ stage.display_name + " metadata",
+ passed,
+ passed ? "external 阶段输入完整。" : "external 阶段缺少真值校核阈值配置。",
+ stage.stage_type.value,
+ stage.module_type.value);
+ }
+ }
+
+ response.ready_for_start = response.all_passed;
+ response.message = response.ready_for_start ? "Precheck passed." : "Precheck failed.";
+ return response;
+}
+
+} // namespace workshop_orchestrator_v2
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/report_builder.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/report_builder.cpp
similarity index 81%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/report_builder.cpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/report_builder.cpp
index 021d469..a77e063 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/report_builder.cpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/report_builder.cpp
@@ -60,12 +60,30 @@ WorkshopReport ReportBuilder::build(
kv.value = overall_success ? "true" : "false";
report.metadata.push_back(kv);
+ kv.key = "workshop_line_id";
+ kv.value = session.workshop_line_id;
+ report.metadata.push_back(kv);
+
+ kv.key = "vehicle_id";
+ kv.value = session.vehicle_profile_snapshot.base_info.vehicle_id;
+ report.metadata.push_back(kv);
+
+ kv.key = "operator_id";
+ kv.value = session.operator_info.operator_id;
+ report.metadata.push_back(kv);
+
if (!report.active_parameter_bundle_version.empty()) {
kv.key = "active_parameter_bundle_version";
kv.value = report.active_parameter_bundle_version;
report.metadata.push_back(kv);
}
+ if (!stage_results.empty()) {
+ kv.key = "last_stage_id";
+ kv.value = stage_results.back().stage_id;
+ report.metadata.push_back(kv);
+ }
+
return report;
}
diff --git a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp
similarity index 86%
rename from agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp
rename to agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp
index 284c210..5e2b13c 100644
--- a/agv_calib_brain/src/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/sensor_gateway_client.cpp
@@ -86,17 +86,32 @@ uint8_t SensorGatewayClient::resolve_task_type(
const StagePlan & stage,
std::string & failure_reason) const
{
- switch (stage.module_type.value) {
- case CalibrationModuleType::SENSOR_INTRINSIC_MODULE:
- return SensorCalibrationTaskType::CAMERA_INTRINSIC;
- case CalibrationModuleType::SENSOR_EXTRINSIC_MODULE:
- return SensorCalibrationTaskType::SENSOR_TO_BASE_EXTRINSIC;
- case CalibrationModuleType::HAND_EYE_MODULE:
- return SensorCalibrationTaskType::HAND_EYE;
- default:
- failure_reason = "当前传感器阶段未映射到具体标定任务类型。";
+ if (stage.module_type.value == CalibrationModuleType::SENSOR_INTRINSIC_MODULE) {
+ std::unordered_map metadata_map;
+ for (const auto & kv : stage.metadata) {
+ metadata_map[kv.key] = kv.value;
+ }
+
+ const auto subtype_it = metadata_map.find(metadata_keys::SENSOR_TASK_SUBTYPE);
+ if (subtype_it == metadata_map.end()) {
+ failure_reason = "传感器内参阶段缺少 sensor.task_subtype。";
return SensorCalibrationTaskType::SENSOR_CALIBRATION_TASK_TYPE_UNSPECIFIED;
+ }
+
+ if (subtype_it->second == "imu_intrinsic") {
+ return SensorCalibrationTaskType::IMU_INTRINSIC;
+ }
+ return SensorCalibrationTaskType::CAMERA_INTRINSIC;
}
+ if (stage.module_type.value == CalibrationModuleType::SENSOR_EXTRINSIC_MODULE) {
+ return SensorCalibrationTaskType::SENSOR_TO_BASE_EXTRINSIC;
+ }
+ if (stage.module_type.value == CalibrationModuleType::HAND_EYE_MODULE) {
+ return SensorCalibrationTaskType::HAND_EYE;
+ }
+
+ failure_reason = "当前传感器阶段未映射到具体标定任务类型。";
+ return SensorCalibrationTaskType::SENSOR_CALIBRATION_TASK_TYPE_UNSPECIFIED;
}
uint8_t resolve_task_subtype_from_metadata(
@@ -151,8 +166,10 @@ bool task_and_subtype_match(
{
if (task_type == SensorCalibrationTaskType::CAMERA_INTRINSIC) {
return task_subtype == SensorCalibrationTaskSubtype::FRONT_CAMERA_INTRINSIC ||
- task_subtype == SensorCalibrationTaskSubtype::DOWNWARD_CAMERA_INTRINSIC ||
- task_subtype == SensorCalibrationTaskSubtype::IMU_INTRINSIC;
+ task_subtype == SensorCalibrationTaskSubtype::DOWNWARD_CAMERA_INTRINSIC;
+ }
+ if (task_type == SensorCalibrationTaskType::IMU_INTRINSIC) {
+ return task_subtype == SensorCalibrationTaskSubtype::IMU_INTRINSIC;
}
if (task_type == SensorCalibrationTaskType::SENSOR_TO_BASE_EXTRINSIC) {
return task_subtype == SensorCalibrationTaskSubtype::FRONT_CAMERA_EXTRINSIC ||
@@ -238,6 +255,33 @@ bool SensorGatewayClient::build_goal(
return false;
}
}
+ goal.goal.camera_intrinsic.reference_target.reference_target_id = stage.stage_id;
+ } else if (selected_task_type == SensorCalibrationTaskType::IMU_INTRINSIC) {
+ goal.goal.imu_intrinsic.sensor_id = sensor_id_it->second;
+ const auto static_count_it = metadata_map.find(metadata_keys::IMU_INTRINSIC_REQUIRED_STATIC_SEGMENT_COUNT);
+ const auto motion_count_it = metadata_map.find(metadata_keys::IMU_INTRINSIC_REQUIRED_MOTION_SEGMENT_COUNT);
+ if (static_count_it == metadata_map.end() || motion_count_it == metadata_map.end()) {
+ failure_reason = "imu_intrinsic 缺少 required_static_segment_count 或 required_motion_segment_count。";
+ return false;
+ }
+ try {
+ goal.goal.imu_intrinsic.required_static_segment_count =
+ static_cast(std::stoul(static_count_it->second));
+ goal.goal.imu_intrinsic.required_motion_segment_count =
+ static_cast(std::stoul(motion_count_it->second));
+ } catch (...) {
+ failure_reason = "imu_intrinsic 参数格式错误。";
+ return false;
+ }
+ const auto timeout_it = metadata_map.find(metadata_keys::IMU_INTRINSIC_TIMEOUT_SEC);
+ if (timeout_it != metadata_map.end()) {
+ try {
+ goal.goal.imu_intrinsic.timeout_sec = std::stod(timeout_it->second);
+ } catch (...) {
+ failure_reason = "imu_intrinsic.timeout_sec 格式错误。";
+ return false;
+ }
+ }
} else if (selected_task_type == SensorCalibrationTaskType::SENSOR_TO_BASE_EXTRINSIC) {
goal.goal.sensor_to_base_extrinsic.sensor_id = sensor_id_it->second;
const auto base_frame_it = metadata_map.find(metadata_keys::SENSOR_EXTRINSIC_BASE_FRAME_ID);
@@ -266,6 +310,7 @@ bool SensorGatewayClient::build_goal(
return false;
}
}
+ goal.goal.sensor_to_base_extrinsic.reference_target.reference_target_id = stage.stage_id;
if (task_subtype == SensorCalibrationTaskSubtype::FRONT_CAMERA_EXTRINSIC ||
task_subtype == SensorCalibrationTaskSubtype::DOWNWARD_CAMERA_EXTRINSIC)
@@ -310,6 +355,7 @@ bool SensorGatewayClient::build_goal(
return false;
}
}
+ goal.goal.hand_eye.reference_target.reference_target_id = stage.stage_id;
if (task_subtype == SensorCalibrationTaskSubtype::EYE_IN_HAND) {
goal.goal.hand_eye.mode.value = HandEyeCalibrationMode::EYE_IN_HAND;
diff --git a/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/wifi6_link_client.cpp b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/wifi6_link_client.cpp
new file mode 100644
index 0000000..849e6e2
--- /dev/null
+++ b/agv_calib_brain/src/core/agv_calib_core/workshop_orchestrator/src/wifi6_link_client.cpp
@@ -0,0 +1,283 @@
+#include "workshop_orchestrator_v2/wifi6_link_client.hpp"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "nlohmann/json.hpp"
+#include "workshop_orchestrator_v2/types.hpp"
+
+namespace workshop_orchestrator_v2
+{
+
+namespace
+{
+
+void write_le32(uint8_t * buf, uint32_t value)
+{
+ buf[0] = static_cast(value & 0xFF);
+ buf[1] = static_cast((value >> 8) & 0xFF);
+ buf[2] = static_cast((value >> 16) & 0xFF);
+ buf[3] = static_cast((value >> 24) & 0xFF);
+}
+
+uint32_t read_le32(const uint8_t * buf)
+{
+ return static_cast(buf[0]) |
+ (static_cast(buf[1]) << 8) |
+ (static_cast(buf[2]) << 16) |
+ (static_cast(buf[3]) << 24);
+}
+
+bool write_all(int fd, const uint8_t * buf, size_t len)
+{
+ size_t written = 0;
+ while (written < len) {
+ const ssize_t n = ::write(fd, buf + written, len - written);
+ if (n <= 0) {
+ return false;
+ }
+ written += static_cast(n);
+ }
+ return true;
+}
+
+bool read_all(int fd, uint8_t * buf, size_t len)
+{
+ size_t got = 0;
+ while (got < len) {
+ const ssize_t n = ::read(fd, buf + got, len - got);
+ if (n <= 0) {
+ return false;
+ }
+ got += static_cast(n);
+ }
+ return true;
+}
+
+int connect_tcp(const std::string & host, uint16_t port, int timeout_ms)
+{
+ const int fd = ::socket(AF_INET, SOCK_STREAM, 0);
+ if (fd < 0) {
+ return -1;
+ }
+
+ struct timeval tv;
+ tv.tv_sec = timeout_ms / 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
+ ::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ ::setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+
+ struct sockaddr_in addr;
+ std::memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ if (::inet_pton(AF_INET, host.c_str(), &addr.sin_addr) <= 0) {
+ ::close(fd);
+ return -1;
+ }
+ if (::connect(fd, reinterpret_cast(&addr), sizeof(addr)) < 0) {
+ ::close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+std::string endpoint_string(const std::string & host, uint16_t port)
+{
+ std::ostringstream oss;
+ oss << host << ":" << port;
+ return oss.str();
+}
+
+std::string readiness_payload(const std::string & agent_name)
+{
+ nlohmann::json request;
+ request["agent_name"] = agent_name;
+ request["include_details"] = true;
+ request["target_resource_ids"] = nlohmann::json::array();
+ return request.dump();
+}
+
+std::string external_pose_probe_payload()
+{
+ nlohmann::json request;
+ request["hardware_timestamp_us"] = now_us();
+ request["pose_valid"] = false;
+ request["workshop_pose"] = {
+ {"x_m", 0.0},
+ {"y_m", 0.0},
+ {"z_m", 0.0},
+ {"roll_rad", 0.0},
+ {"pitch_rad", 0.0},
+ {"yaw_rad", 0.0},
+ };
+ request["position_stddev_m"] = 0.0;
+ request["yaw_stddev_rad"] = 0.0;
+ request["tracking_loss_ratio"] = 0.0;
+ request["time_sync_offset_ms"] = 0.0;
+ request["quality_score"] = 1.0;
+ request["observed_target_count"] = 0;
+ request["reference_source_name"] = "workshop_orchestrator_precheck";
+ request["active_job_id"] = "wifi6_link_precheck";
+ return request.dump();
+}
+
+bool json_bool(const nlohmann::json & payload, const std::string & key, bool default_value)
+{
+ const auto it = payload.find(key);
+ if (it == payload.end() || !it->is_boolean()) {
+ return default_value;
+ }
+ return it->get();
+}
+
+std::string json_message(const nlohmann::json & payload, const std::string & fallback)
+{
+ const auto it = payload.find("message");
+ if (it == payload.end() || !it->is_string() || it->get().empty()) {
+ return fallback;
+ }
+ return it->get();
+}
+
+bool optional_bool_passed(
+ const nlohmann::json & payload,
+ const std::string & key,
+ std::string & failure_reason)
+{
+ const auto it = payload.find(key);
+ if (it == payload.end() || !it->is_boolean() || it->get()) {
+ return true;
+ }
+ failure_reason = key + "=false";
+ return false;
+}
+
+} // namespace
+
+Wifi6LinkClient::Wifi6LinkClient(Config config)
+: config_(std::move(config))
+{
+}
+
+Wifi6LinkClient::CheckResult Wifi6LinkClient::send_json_request(
+ FrameType request_type,
+ FrameType response_type,
+ const std::string & request_payload,
+ const std::string & link_name) const
+{
+ const int fd = connect_tcp(config_.vehicle_host, config_.vehicle_port, config_.timeout_ms);
+ const auto endpoint = endpoint_string(config_.vehicle_host, config_.vehicle_port);
+ if (fd < 0) {
+ return {false, link_name + " 无法连接 " + endpoint};
+ }
+
+ uint8_t header[8];
+ write_le32(header, static_cast(request_type));
+ write_le32(header + 4, static_cast(request_payload.size()));
+ bool ok = write_all(fd, header, sizeof(header));
+ if (ok && !request_payload.empty()) {
+ ok = write_all(fd, reinterpret_cast(request_payload.data()), request_payload.size());
+ }
+ if (!ok) {
+ ::close(fd);
+ return {false, link_name + " 向 " + endpoint + " 发送请求失败"};
+ }
+
+ uint8_t response_header[8];
+ if (!read_all(fd, response_header, sizeof(response_header))) {
+ ::close(fd);
+ return {false, link_name + " 等待 " + endpoint + " 响应超时或连接断开"};
+ }
+ const auto actual_type = static_cast(read_le32(response_header));
+ const auto payload_len = read_le32(response_header + 4);
+ std::string response_payload(payload_len, '\0');
+ if (payload_len > 0 &&
+ !read_all(fd, reinterpret_cast