diff --git a/src/hangar_sim/CMakeLists.txt b/src/hangar_sim/CMakeLists.txt index 0d49770e5..61482d938 100644 --- a/src/hangar_sim/CMakeLists.txt +++ b/src/hangar_sim/CMakeLists.txt @@ -3,6 +3,31 @@ project(hangar_sim) find_package(ament_cmake REQUIRED) find_package(picknik_accessories REQUIRED) +find_package(rclcpp REQUIRED) +find_package(nav_msgs REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_geometry_msgs REQUIRED) +find_package(tf2_ros REQUIRED) + +add_executable(slip_aware_odom src/slip_aware_odom.cpp) +target_include_directories(slip_aware_odom PRIVATE include) +target_compile_features(slip_aware_odom PRIVATE cxx_std_20) +ament_target_dependencies(slip_aware_odom rclcpp nav_msgs tf2 tf2_geometry_msgs) + +add_executable(amcl_odom_gate src/amcl_odom_gate.cpp src/amcl_odom_gate_logic.cpp) +target_include_directories(amcl_odom_gate PRIVATE include) +target_compile_features(amcl_odom_gate PRIVATE cxx_std_20) +ament_target_dependencies(amcl_odom_gate rclcpp geometry_msgs tf2 tf2_geometry_msgs tf2_ros) + +add_executable(odom_world_drift src/odom_world_drift.cpp) +target_include_directories(odom_world_drift PRIVATE include) +target_compile_features(odom_world_drift PRIVATE cxx_std_20) +ament_target_dependencies(odom_world_drift rclcpp nav_msgs sensor_msgs geometry_msgs tf2 tf2_geometry_msgs + tf2_ros) + +install(TARGETS slip_aware_odom amcl_odom_gate odom_world_drift DESTINATION lib/${PROJECT_NAME}) install( DIRECTORY @@ -47,6 +72,22 @@ if(BUILD_TESTING) ENV MOVEIT_CONFIG_PACKAGE=hangar_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR} ROS_LOG_DIR=${CMAKE_CURRENT_BINARY_DIR}/test_results/${PROJECT_NAME}/ros_logs) + + # Unit tests for the pure amcl_odom_gate decision logic (no ROS/TF). + find_package(ament_cmake_gmock REQUIRED) + ament_add_gmock(test_amcl_odom_gate test/test_amcl_odom_gate.cpp src/amcl_odom_gate_logic.cpp) + target_include_directories(test_amcl_odom_gate PRIVATE include) + target_compile_features(test_amcl_odom_gate PRIVATE cxx_std_20) + + # Unit tests for the pure odom_world_drift rail-joint index resolver (no ROS). + ament_add_gmock(test_odom_world_drift test/test_odom_world_drift.cpp) + target_include_directories(test_odom_world_drift PRIVATE include) + target_compile_features(test_odom_world_drift PRIVATE cxx_std_20) + + # Unit tests for the pure slip_aware_odom re-anchor/stitch and covariance-ramp logic (no ROS). + ament_add_gmock(test_slip_aware_odom test/test_slip_aware_odom.cpp) + target_include_directories(test_slip_aware_odom PRIVATE include) + target_compile_features(test_slip_aware_odom PRIVATE cxx_std_20) endif() ament_package() diff --git a/src/hangar_sim/config/control/picknik_ur.ros2_control.yaml b/src/hangar_sim/config/control/picknik_ur.ros2_control.yaml index ab6e0afb3..eea8e6e45 100644 --- a/src/hangar_sim/config/control/picknik_ur.ros2_control.yaml +++ b/src/hangar_sim/config/control/picknik_ur.ros2_control.yaml @@ -160,6 +160,7 @@ platform_velocity_controller_nav2: joint_state_broadcaster: ros__parameters: use_local_topics: false + update_rate: 50 # publish /joint_states at 50 Hz, not the 600 Hz control loop joints: - shoulder_pan_joint - shoulder_lift_joint @@ -211,19 +212,19 @@ joint_trajectory_controller: action_monitor_rate: 20.0 allow_partial_joints_goal: true open_loop_control: false # this is closed loop - # Workaround for PickNikRobotics/moveit_pro#20766: trajectory generation - # leaves sub-epsilon terminal-velocity residuals that Jazzy's JTC rejects - # by default — measured ~1e-4 on `linear_x_joint` from the MTC Cartesian - # approach in "ML Move Boxes to Loading Zone", and ~4e-7 from joint - # interpolation in "Point-to-Point Trajectory" (previously skipped in - # test/objectives_integration_test.py for exactly this rejection). + # Workaround: trajectory generation leaves sub-epsilon terminal-velocity + # residuals that Jazzy's JTC rejects by default — measured ~1e-4 on + # `linear_x_joint` from the MTC Cartesian approach in "ML Move Boxes to + # Loading Zone", and ~4e-7 from joint interpolation in "Point-to-Point + # Trajectory" (previously skipped in test/objectives_integration_test.py + # for exactly this rejection). # CAUTION: this flag is binary and controller-wide — it disables the # endpoint-still-moving check for every magnitude on every joint, # including the mecanum base, where a genuinely nonzero terminal velocity # means the base is still translating at trajectory end and then snaps to # a position hold. Acceptable for this sim config; re-evaluate before - # copying to real hardware. Remove when moveit_pro#20766 clamps the - # residuals at trajectory generation. + # copying to real hardware. Remove once trajectory generation clamps the + # residuals upstream. allow_nonzero_velocity_at_trajectory_end: true gains: shoulder_pan_joint: @@ -297,6 +298,7 @@ force_torque_sensor_broadcaster: imu_sensor_broadcaster: ros__parameters: + update_rate: 100 # 100 Hz IMU is plenty for fuse (optimizes at 10 Hz); was inheriting the 600 Hz control loop sensor_name: imu_site frame_id: ridgeback_base_link # Static covariance values (row-major 3x3 matrices) diff --git a/src/hangar_sim/config/fuse/fuse.yaml b/src/hangar_sim/config/fuse/fuse.yaml index 4ad1039f5..22f5135b6 100644 --- a/src/hangar_sim/config/fuse/fuse.yaml +++ b/src/hangar_sim/config/fuse/fuse.yaml @@ -3,9 +3,9 @@ state_estimator: ros__parameters: # Fixed-lag smoother configuration - optimization_frequency: 20.0 + optimization_frequency: 10.0 # match publish_frequency (10 Hz); optimizing 2x faster than we publish was wasted work transaction_timeout: 0.01 - lag_duration: 0.5 + lag_duration: 0.3 # chosen: median 0.465deg (<0.5 goal), clean transient tail vs 0.25 # Motion model for mobile base (3D omnidirectional) motion_models: @@ -51,7 +51,7 @@ state_estimator: # only the relative change between consecutive messages, preventing # accumulated drift from corrupting the estimate. wheel_odom_sensor: - topic: /platform_velocity_controller_nav2/odom + topic: /odom_slip_aware # slip_aware_odom republishes with spin-aware yaw covariance queue_size: 10 pose_loss: type: fuse_loss::HuberLoss diff --git a/src/hangar_sim/description/picknik_ur_mujoco_ros2_control.xacro b/src/hangar_sim/description/picknik_ur_mujoco_ros2_control.xacro index 42241108e..05ba84c3f 100644 --- a/src/hangar_sim/description/picknik_ur_mujoco_ros2_control.xacro +++ b/src/hangar_sim/description/picknik_ur_mujoco_ros2_control.xacro @@ -31,11 +31,11 @@ ${mujoco_model} hangar_sim 20 - 60 + 30 10 ${publish_odom} ridgeback_base_link - 150 + 50 diff --git a/src/hangar_sim/description/ur5e_ridgeback.xml b/src/hangar_sim/description/ur5e_ridgeback.xml index 2c18a2d13..5fe0538e3 100644 --- a/src/hangar_sim/description/ur5e_ridgeback.xml +++ b/src/hangar_sim/description/ur5e_ridgeback.xml @@ -313,6 +313,10 @@ conaffinity="0" group="2" /> + +