From 737ea8274031c0b020b33436b15af5e5940637c5 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Mon, 11 May 2026 00:04:15 +0800 Subject: [PATCH 01/30] feat: add odin_ros_driver submodule --- .gitmodules | 3 +++ rmcs_ws/src/odin_ros_driver | 1 + 2 files changed, 4 insertions(+) create mode 160000 rmcs_ws/src/odin_ros_driver diff --git a/.gitmodules b/.gitmodules index 61e5f08f..20531eff 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "rmcs_ws/src/fast_tf"] path = rmcs_ws/src/fast_tf url = https://github.com/qzhhhi/FastTF.git +[submodule "rmcs_ws/src/odin_ros_driver"] + path = rmcs_ws/src/odin_ros_driver + url = git@github.com:Alliance-Algorithm/odin_ros_driver.git diff --git a/rmcs_ws/src/odin_ros_driver b/rmcs_ws/src/odin_ros_driver new file mode 160000 index 00000000..dbcb0286 --- /dev/null +++ b/rmcs_ws/src/odin_ros_driver @@ -0,0 +1 @@ +Subproject commit dbcb0286b510142e966ac090a37ce5ca238f9e75 From 20575e85947c91d9de67b25ea1220edfb1a5c821 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Mon, 11 May 2026 00:11:19 +0800 Subject: [PATCH 02/30] feat: add hikcamera submodule --- .gitmodules | 3 +++ rmcs_ws/src/hikcamera | 1 + 2 files changed, 4 insertions(+) create mode 160000 rmcs_ws/src/hikcamera diff --git a/.gitmodules b/.gitmodules index 20531eff..4b443c64 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "rmcs_ws/src/odin_ros_driver"] path = rmcs_ws/src/odin_ros_driver url = git@github.com:Alliance-Algorithm/odin_ros_driver.git +[submodule "rmcs_ws/src/hikcamera"] + path = rmcs_ws/src/hikcamera + url = git@github.com:Alliance-Algorithm/ros2-hikcamera.git diff --git a/rmcs_ws/src/hikcamera b/rmcs_ws/src/hikcamera new file mode 160000 index 00000000..f0077f03 --- /dev/null +++ b/rmcs_ws/src/hikcamera @@ -0,0 +1 @@ +Subproject commit f0077f034800bcd0dde4fffeff270b733772a57e From f0761a2024cb6046b5c27eb9ce3f9048447f6402 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Mon, 11 May 2026 00:57:18 +0800 Subject: [PATCH 03/30] feat: add rmcs_auto_aim_v2 submodule --- .gitmodules | 3 +++ rmcs_ws/src/rmcs_auto_aim_v2 | 1 + 2 files changed, 4 insertions(+) create mode 160000 rmcs_ws/src/rmcs_auto_aim_v2 diff --git a/.gitmodules b/.gitmodules index 4b443c64..acf743ec 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "rmcs_ws/src/hikcamera"] path = rmcs_ws/src/hikcamera url = git@github.com:Alliance-Algorithm/ros2-hikcamera.git +[submodule "rmcs_ws/src/rmcs_auto_aim_v2"] + path = rmcs_ws/src/rmcs_auto_aim_v2 + url = git@github.com:Alliance-Algorithm/rmcs_auto_aim_v2.git diff --git a/rmcs_ws/src/rmcs_auto_aim_v2 b/rmcs_ws/src/rmcs_auto_aim_v2 new file mode 160000 index 00000000..d665f7bc --- /dev/null +++ b/rmcs_ws/src/rmcs_auto_aim_v2 @@ -0,0 +1 @@ +Subproject commit d665f7bc35e2f60bbd7b0564ef65c0947f9fa973 From 4df9945dfc0e0d9d9fccbaa60c007de3abd7e9f6 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Mon, 11 May 2026 02:53:20 +0800 Subject: [PATCH 04/30] feat: restructure Aerial gimbal controller and integrate auto-aim module --- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 173 ++++++++++++ rmcs_ws/src/rmcs_core/CMakeLists.txt | 2 +- rmcs_ws/src/rmcs_core/plugins.xml | 4 +- .../gimbal/simple_gimbal_controller.cpp | 16 +- .../bullet_feeder_controller_17mm.cpp | 12 +- .../src/hardware/device/lk_motor.hpp | 15 +- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 260 ++++++++++++++++++ .../rmcs_core/src/hardware/flight_mavros.cpp | 224 +++++++++++++++ 8 files changed, 691 insertions(+), 15 deletions(-) create mode 100644 rmcs_ws/src/rmcs_bringup/config/flight.yaml create mode 100644 rmcs_ws/src/rmcs_core/src/hardware/flight.cpp create mode 100644 rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml new file mode 100644 index 00000000..8c4057cd --- /dev/null +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -0,0 +1,173 @@ +rmcs_executor: + ros__parameters: + update_rate: 1000.0 + components: + - rmcs_core::hardware::Flight -> flight_hardware + # - rmcs_core::hardware::FlightMavros -> flight_mavros_hardware + + - rmcs_core::controller::gimbal::SimpleGimbalController -> gimbal_controller + - rmcs_core::controller::pid::ErrorPidController -> yaw_angle_pid_controller + - rmcs_core::controller::pid::PidController -> yaw_velocity_pid_controller + - rmcs_core::controller::pid::ErrorPidController -> pitch_angle_pid_controller + + - rmcs_core::controller::shooting::FrictionWheelController -> friction_wheel_controller + - rmcs_core::controller::shooting::HeatController -> heat_controller + - rmcs_core::controller::shooting::BulletFeederController17mm -> bullet_feeder_controller + - rmcs_core::controller::pid::PidController -> left_friction_velocity_pid_controller + - rmcs_core::controller::pid::PidController -> right_friction_velocity_pid_controller + - rmcs_core::controller::pid::PidController -> bullet_feeder_velocity_pid_controller + + - rmcs_core::referee::command::Interaction -> referee_interaction + - rmcs_core::referee::Command -> referee_command + - rmcs_core::referee::Status -> referee_status + + - rmcs_core::broadcaster::ValueBroadcaster -> value_broadcaster + - rmcs_core::broadcaster::TfBroadcaster -> tf_broadcaster + + # - rmcs::AutoAimComponent -> auto_aim_component + +mavros: + ros__parameters: + enabled: true + fcu_url: serial:///dev/ttyACM0:921600 + gcs_url: "" + target_system_id: 1 + target_component_id: 1 + fcu_protocol: v2.0 + respawn: true + respawn_delay: 1.0 + +odin_ros_driver: + ros__parameters: + enabled: true + config_file: "/rmcs_install/share/odin_ros_driver/config/control_command.yaml" + node_name: host_sdk_sample + respawn: true + respawn_delay: 1.0 + +value_broadcaster: + ros__parameters: + forward_list: + - /gimbal/pitch/angle + - /gimbal/pitch/velocity + - /gimbal/pitch/torque + - /gimbal/pitch/control_angle_error + - /gimbal/pitch/control_velocity + - /gimbal/pitch/velocity_imu + + - /gimbal/yaw/angle + - /gimbal/yaw/velocity + - /gimbal/yaw/torque + - /gimbal/yaw/control_torque + - /gimbal/yaw/control_angle_error + - /gimbal/yaw/velocity_imu + + +tf_broadcaster: + ros__parameters: + tf: /tf + +flight_hardware: + ros__parameters: + board_serial: "d4-9d44" + yaw_motor_zero_point: 11720 + pitch_motor_zero_point: 18578 + +flight_mavros_hardware: + ros__parameters: + target_frame_id: odom + source_frame_id: odin1_base_link + output_rate: 30.0 + sensor_roll_offset_rad: 3.141592653589793 + sensor_pitch_offset_rad: 1.5707963267948966 + sensor_yaw_offset_rad: 0.0 + mavros_pose_topic: /mavros/vision_pose/pose + mavros_pose_frame_id: odom + +referee_status: + ros__parameters: + path: /dev/tty0 + +gimbal_controller: + ros__parameters: + upper_limit: -0.39518 # -0.39518 rad ≈ -22.6° + lower_limit: 0.7 # 0.7 rad ≈ 40.1° + # TODO: yaw limite + +yaw_angle_pid_controller: + ros__parameters: + measurement: /gimbal/yaw/control_angle_error + control: /gimbal/yaw/control_velocity + kp: 15.0 + ki: 0.0 + kd: 0.0 + +yaw_velocity_pid_controller: + ros__parameters: + measurement: /gimbal/yaw/velocity_imu + setpoint: /gimbal/yaw/control_velocity + control: /gimbal/yaw/control_torque + kp: 8.0 + ki: 0.0 + kd: 0.0 + +pitch_angle_pid_controller: + ros__parameters: + measurement: /gimbal/pitch/control_angle_error + control: /gimbal/pitch/control_velocity + kp: 10.0 + ki: 0.0 + kd: 0.0 + +friction_wheel_controller: + ros__parameters: + friction_wheels: + - /gimbal/left_friction + - /gimbal/right_friction + friction_velocities: + - 740.0 + - 740.0 + friction_soft_start_stop_time: 1.0 + +heat_controller: + ros__parameters: + heat_per_shot: 1 + reserved_heat: 0 + +bullet_feeder_controller: + ros__parameters: + bullets_per_feeder_turn: 8.0 + shot_frequency: 20.0 + safe_shot_frequency: 10.0 + eject_frequency: 10.0 + eject_time: 0.05 + deep_eject_frequency: 5.0 + deep_eject_time: 0.2 + single_shot_max_stop_delay: 2.0 + +left_friction_velocity_pid_controller: + ros__parameters: + measurement: /gimbal/left_friction/velocity + setpoint: /gimbal/left_friction/control_velocity + control: /gimbal/left_friction/control_torque + kp: 0.003436926 + ki: 0.00 + kd: 0.009373434 + +right_friction_velocity_pid_controller: + ros__parameters: + measurement: /gimbal/right_friction/velocity + setpoint: /gimbal/right_friction/control_velocity + control: /gimbal/right_friction/control_torque + kp: 0.003436926 + ki: 0.00 + kd: 0.009373434 + +bullet_feeder_velocity_pid_controller: + ros__parameters: + measurement: /gimbal/bullet_feeder/velocity + setpoint: /gimbal/bullet_feeder/control_velocity + control: /gimbal/bullet_feeder/control_torque + kp: 0.583 + ki: 0.0 + kd: 0.0 diff --git a/rmcs_ws/src/rmcs_core/CMakeLists.txt b/rmcs_ws/src/rmcs_core/CMakeLists.txt index d9504de2..38d75ca7 100644 --- a/rmcs_ws/src/rmcs_core/CMakeLists.txt +++ b/rmcs_ws/src/rmcs_core/CMakeLists.txt @@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-packed-bitfield-compat") if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-O2 -Wall -Wextra -Wpedantic) + add_compile_options(-O2 -Wall -Wextra -Wpedantic) endif() find_package(ament_cmake_auto REQUIRED) diff --git a/rmcs_ws/src/rmcs_core/plugins.xml b/rmcs_ws/src/rmcs_core/plugins.xml index 82ffac1c..58f30161 100644 --- a/rmcs_ws/src/rmcs_core/plugins.xml +++ b/rmcs_ws/src/rmcs_core/plugins.xml @@ -1,5 +1,7 @@ - + + + diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp index d27704d5..e18b0dd9 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp @@ -30,7 +30,8 @@ class SimpleGimbalController register_input("/remote/mouse/velocity", mouse_velocity_); register_input("/remote/mouse", mouse_); - register_input("/gimbal/auto_aim/control_direction", auto_aim_control_direction_, false); + register_input("/auto_aim/should_control", auto_aim_should_control_, false); + register_input("/auto_aim/control_direction", auto_aim_control_direction_, false); register_output("/gimbal/yaw/control_angle_error", yaw_angle_error_, nan_); register_output("/gimbal/pitch/control_angle_error", pitch_angle_error_, nan_); @@ -45,18 +46,20 @@ class SimpleGimbalController TwoAxisGimbalSolver::AngleError calculate_angle_error() { auto switch_right = *switch_right_; auto switch_left = *switch_left_; - auto mouse = *mouse_; - using namespace rmcs_msgs; if ((switch_left == Switch::UNKNOWN || switch_right == Switch::UNKNOWN) || (switch_left == Switch::DOWN && switch_right == Switch::DOWN)) return two_axis_gimbal_solver.update(TwoAxisGimbalSolver::SetDisabled()); - if (auto_aim_control_direction_.ready() && (mouse.right || switch_right == Switch::UP) - && !auto_aim_control_direction_->isZero()) + const auto auto_aim_active = + switch_right == Switch::UP && auto_aim_should_control_.ready() + && *auto_aim_should_control_ && auto_aim_control_direction_.ready() + && auto_aim_control_direction_->allFinite() && !auto_aim_control_direction_->isZero(); + if (auto_aim_active) { return two_axis_gimbal_solver.update( TwoAxisGimbalSolver::SetControlDirection( OdomImu::DirectionVector(*auto_aim_control_direction_))); + } if (!two_axis_gimbal_solver.enabled()) return two_axis_gimbal_solver.update(TwoAxisGimbalSolver::SetToLevel()); @@ -82,6 +85,7 @@ class SimpleGimbalController InputInterface mouse_velocity_; InputInterface mouse_; + InputInterface auto_aim_should_control_; InputInterface auto_aim_control_direction_; TwoAxisGimbalSolver two_axis_gimbal_solver; @@ -94,4 +98,4 @@ class SimpleGimbalController #include PLUGINLIB_EXPORT_CLASS( - rmcs_core::controller::gimbal::SimpleGimbalController, rmcs_executor::Component) \ No newline at end of file + rmcs_core::controller::gimbal::SimpleGimbalController, rmcs_executor::Component) diff --git a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp index 0c97c98a..e90e62cc 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp @@ -53,7 +53,7 @@ class BulletFeederController17mm register_input("/remote/mouse", mouse_); register_input("/remote/keyboard", keyboard_); - register_input("/gimbal/auto_aim/fire_control", fire_control_, false); + register_input("/auto_aim/should_shoot", auto_aim_should_shoot_, false); register_input("/gimbal/bullet_feeder/velocity", bullet_feeder_velocity_); register_output( @@ -63,8 +63,8 @@ class BulletFeederController17mm } void before_updating() override { - if (!fire_control_.ready()) - fire_control_.bind_directly(false); + if (!auto_aim_should_shoot_.ready()) + auto_aim_should_shoot_.bind_directly(false); } void update() override { @@ -103,7 +103,7 @@ class BulletFeederController17mm if (*friction_ready_) { if (shoot_mode == ShootMode::AUTOMATIC) { bool triggered = mouse.left || switch_left == Switch::DOWN - || (switch_right == Switch::UP && *fire_control_); + || (switch_right == Switch::UP && *auto_aim_should_shoot_); bullet_allowance = triggered ? *control_bullet_allowance_limited_by_heat_ : 0; } else { @@ -209,7 +209,7 @@ class BulletFeederController17mm InputInterface mouse_; InputInterface keyboard_; - InputInterface fire_control_; + InputInterface auto_aim_should_shoot_; rmcs_msgs::Switch last_switch_right_ = rmcs_msgs::Switch::UNKNOWN; rmcs_msgs::Switch last_switch_left_ = rmcs_msgs::Switch::UNKNOWN; @@ -232,4 +232,4 @@ class BulletFeederController17mm #include PLUGINLIB_EXPORT_CLASS( - rmcs_core::controller::shooting::BulletFeederController17mm, rmcs_executor::Component) \ No newline at end of file + rmcs_core::controller::shooting::BulletFeederController17mm, rmcs_executor::Component) diff --git a/rmcs_ws/src/rmcs_core/src/hardware/device/lk_motor.hpp b/rmcs_ws/src/rmcs_core/src/hardware/device/lk_motor.hpp index 1bc0ef8a..60348bb6 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/device/lk_motor.hpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/device/lk_motor.hpp @@ -23,7 +23,14 @@ namespace rmcs_core::hardware::device { class LkMotor { public: - enum class Type : uint8_t { kMG5010Ei10, kMG4010Ei10, kMG6012Ei8, kMG4005Ei10, kMG5010Ei36 }; + enum class Type : uint8_t { + kMG5010Ei10, + kMG4010Ei10, + kMG6012Ei8, + kMG4005Ei10, + kMG5010Ei36, + kMHF7015, + }; struct Config { explicit Config(Type type) @@ -110,6 +117,12 @@ class LkMotor { reduction_ratio = 36.0; max_torque_ = 25.0; break; + case Type::kMHF7015: + raw_angle_modulus_ = 1 << 16; + torque_constant = 0.51; + reduction_ratio = 1.0; + max_torque_ = 2.42; + break; default: std::unreachable(); } diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp new file mode 100644 index 00000000..ba0b5439 --- /dev/null +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hardware/device/bmi088.hpp" +#include "hardware/device/can_packet.hpp" +#include "hardware/device/dji_motor.hpp" +#include "hardware/device/dr16.hpp" +#include "hardware/device/lk_motor.hpp" + +namespace rmcs_core::hardware { + +class Flight + : public rmcs_executor::Component + , public rclcpp::Node + , private librmcs::agent::CBoard { +public: + Flight() + : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} + , librmcs::agent::CBoard{get_parameter("board_serial").as_string()} + , logger_(get_logger()) + , command_component_( + create_partner_component(get_component_name() + "_command", *this)) + , gimbal_yaw_motor_(*this, *command_component_, "/gimbal/yaw") + , gimbal_pitch_motor_(*this, *command_component_, "/gimbal/pitch") + , gimbal_left_friction_(*this, *command_component_, "/gimbal/left_friction") + , gimbal_right_friction_(*this, *command_component_, "/gimbal/right_friction") + , gimbal_bullet_feeder_(*this, *command_component_, "/gimbal/bullet_feeder") + , dr16_(*this) + , bmi088_(1000.0, 0.2, 0.00) { + + gimbal_yaw_motor_.configure( + device::LkMotor::Config{device::LkMotor::Type::kMHF7015} + .set_reversed() + .set_encoder_zero_point( + static_cast(get_parameter("yaw_motor_zero_point").as_int()))); + gimbal_pitch_motor_.configure( + device::LkMotor::Config{device::LkMotor::Type::kMG4010Ei10}.set_encoder_zero_point( + static_cast(get_parameter("pitch_motor_zero_point").as_int()))); + gimbal_left_friction_.configure( + device::DjiMotor::Config{device::DjiMotor::Type::kM3508} + .set_reversed() + .set_reduction_ratio(1.0)); + gimbal_right_friction_.configure( + device::DjiMotor::Config{device::DjiMotor::Type::kM3508}.set_reduction_ratio(1.0)); + gimbal_bullet_feeder_.configure( + device::DjiMotor::Config{device::DjiMotor::Type::kM2006} + .set_reversed() + .enable_multi_turn_angle()); + + register_output("/gimbal/yaw/velocity_imu", gimbal_yaw_velocity_imu_); + register_output("/gimbal/pitch/velocity_imu", gimbal_pitch_velocity_imu_); + register_output("/tf", tf_); + + bmi088_.set_coordinate_mapping( + [](double x, double y, double z) { return std::make_tuple(-x, z, y); }); + + using namespace rmcs_description; // NOLINT(google-build-using-namespace) + constexpr double rotor_distance_x = 0.83637; + constexpr double rotor_distance_y = 0.83637; + + tf_->set_transform( + Eigen::Translation3d{rotor_distance_x / 2, rotor_distance_y / 2, 0}); + tf_->set_transform( + Eigen::Translation3d{rotor_distance_x / 2, -rotor_distance_y / 2, 0}); + tf_->set_transform( + Eigen::Translation3d{-rotor_distance_x / 2, rotor_distance_y / 2, 0}); + tf_->set_transform( + Eigen::Translation3d{-rotor_distance_x / 2, -rotor_distance_y / 2, 0}); + + constexpr double gimbal_center_x = 0.0; + constexpr double gimbal_center_y = 0.0; + constexpr double gimbal_center_z = -0.20552; + tf_->set_transform( + Eigen::Translation3d{gimbal_center_x, gimbal_center_y, gimbal_center_z}); + tf_->set_transform(Eigen::Translation3d{0.1572, 0.00675, 0.0528}); + + gimbal_calibrate_subscription_ = create_subscription( + "/gimbal/calibrate", rclcpp::QoS{0}, [this](std_msgs::msg::Int32::UniquePtr&& msg) { + gimbal_calibrate_subscription_callback(std::move(msg)); + }); + + register_output("/referee/serial", referee_serial_); + referee_serial_->read = [this](std::byte* buffer, size_t size) { + return referee_ring_buffer_receive_.pop_front_n( + [&buffer](std::byte byte) noexcept { *buffer++ = byte; }, size); + }; + referee_serial_->write = [this](const std::byte* buffer, size_t size) { + start_transmit().uart1_transmit( + {.uart_data = std::span{buffer, size}}); + return size; + }; + } + + Flight(const Flight&) = delete; + Flight& operator=(const Flight&) = delete; + Flight(Flight&&) = delete; + Flight& operator=(Flight&&) = delete; + + ~Flight() override = default; + + void update() override { + update_motors(); + update_imu(); + dr16_.update_status(); + } + + void command_update() { + auto builder = start_transmit(); + builder + .can2_transmit( + {.can_id = 0x141, + .can_data = gimbal_yaw_motor_.generate_torque_command().as_bytes()}) + .can2_transmit( + {.can_id = 0x142, .can_data = gimbal_pitch_motor_.generate_command().as_bytes()}) + .can1_transmit( + {.can_id = 0x200, + .can_data = + device::CanPacket8{ + gimbal_bullet_feeder_.generate_command(), + device::CanPacket8::PaddingQuarter{}, + gimbal_left_friction_.generate_command(), + gimbal_right_friction_.generate_command()} + .as_bytes()}); + } + +private: + void update_motors() { + using namespace rmcs_description; // NOLINT(google-build-using-namespace) + gimbal_yaw_motor_.update_status(); + tf_->set_state(gimbal_yaw_motor_.angle()); + + gimbal_pitch_motor_.update_status(); + tf_->set_state(gimbal_pitch_motor_.angle()); + + gimbal_bullet_feeder_.update_status(); + gimbal_left_friction_.update_status(); + gimbal_right_friction_.update_status(); + } + + void update_imu() { + bmi088_.update_status(); + Eigen::Quaterniond gimbal_imu_pose{bmi088_.q0(), bmi088_.q1(), bmi088_.q2(), bmi088_.q3()}; + tf_->set_transform( + gimbal_imu_pose.conjugate()); + + *gimbal_yaw_velocity_imu_ = bmi088_.gz(); + *gimbal_pitch_velocity_imu_ = bmi088_.gy(); + } + + void gimbal_calibrate_subscription_callback(std_msgs::msg::Int32::UniquePtr) { + RCLCPP_INFO( + logger_, "[gimbal calibration] New yaw offset: %ld", + gimbal_yaw_motor_.calibrate_zero_point()); + RCLCPP_INFO( + logger_, "[gimbal calibration] New pitch offset: %ld", + gimbal_pitch_motor_.calibrate_zero_point()); + } + + class FlightCommand : public rmcs_executor::Component { + public: + explicit FlightCommand(Flight& flight) + : flight_(flight) {} + + void update() override { flight_.command_update(); } + + private: + Flight& flight_; + }; + +protected: + void can1_receive_callback(const librmcs::data::CanDataView& data) override { + if (data.is_extended_can_id || data.is_remote_transmission || data.can_data.size() < 8) + [[unlikely]] + return; + + if (data.can_id == 0x201) { + gimbal_bullet_feeder_.store_status(data.can_data); + } else if (data.can_id == 0x203) { + gimbal_left_friction_.store_status(data.can_data); + } else if (data.can_id == 0x204) { + gimbal_right_friction_.store_status(data.can_data); + } + } + + void can2_receive_callback(const librmcs::data::CanDataView& data) override { + if (data.is_extended_can_id || data.is_remote_transmission || data.can_data.size() < 8) + [[unlikely]] + return; + + if (data.can_id == 0x142) + gimbal_pitch_motor_.store_status(data.can_data); + else if (data.can_id == 0x141) { + gimbal_yaw_motor_.store_status(data.can_data); + } + } + + void uart1_receive_callback(const librmcs::data::UartDataView& data) override { + const std::byte* ptr = data.uart_data.data(); + referee_ring_buffer_receive_.emplace_back_n( + [&ptr](std::byte* storage) noexcept { new (storage) std::byte{*ptr++}; }, + data.uart_data.size()); + } + + void dbus_receive_callback(const librmcs::data::UartDataView& data) override { + dr16_.store_status(data.uart_data.data(), data.uart_data.size()); + } + + void accelerometer_receive_callback(const librmcs::data::AccelerometerDataView& data) override { + bmi088_.store_accelerometer_status(data.x, data.y, data.z); + } + + void gyroscope_receive_callback(const librmcs::data::GyroscopeDataView& data) override { + bmi088_.store_gyroscope_status(data.x, data.y, data.z); + } + +private: + rclcpp::Logger logger_; + std::shared_ptr command_component_; + rclcpp::Subscription::SharedPtr gimbal_calibrate_subscription_; + + device::LkMotor gimbal_yaw_motor_; + device::LkMotor gimbal_pitch_motor_; + device::DjiMotor gimbal_left_friction_; + device::DjiMotor gimbal_right_friction_; + device::DjiMotor gimbal_bullet_feeder_; + + device::Dr16 dr16_; + device::Bmi088 bmi088_; + + OutputInterface gimbal_yaw_velocity_imu_; + OutputInterface gimbal_pitch_velocity_imu_; + OutputInterface tf_; + OutputInterface referee_serial_; + + rmcs_utility::RingBuffer referee_ring_buffer_receive_{256}; +}; + +} // namespace rmcs_core::hardware + +#include + +PLUGINLIB_EXPORT_CLASS(rmcs_core::hardware::Flight, rmcs_executor::Component) diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp new file mode 100644 index 00000000..54362804 --- /dev/null +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace rmcs_core::hardware { + +class FlightMavros + : public rmcs_executor::Component + , public rclcpp::Node { +public: + FlightMavros() + : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} + , logger_(get_logger()) + , tf_buffer_(get_clock()) + , tf_listener_(tf_buffer_) + , last_pose_received_time_{0, 0, get_clock()->get_clock_type()} { + load_parameters(); + register_input("/predefined/update_rate", update_rate_); + + mavros_pose_publisher_ = create_publisher( + mavros_pose_topic_, rclcpp::QoS{10}.reliable()); + + RCLCPP_INFO( + logger_, + "FlightMavros bridging TF '%s' -> '%s' to '%s' with sensor RPY [%.1f, %.1f, %.1f] " + "deg.", + source_frame_id_.c_str(), target_frame_id_.c_str(), + mavros_pose_publisher_->get_topic_name(), radians_to_degrees(sensor_roll_offset_rad_), + radians_to_degrees(sensor_pitch_offset_rad_), + radians_to_degrees(sensor_yaw_offset_rad_)); + } + + ~FlightMavros() override = default; + + void update() override { + update_pose_from_tf(); + const double update_rate = *update_rate_; + if (!std::isfinite(update_rate) || update_rate <= 0.0) + return; + + publish_credit_ += output_rate_hz_ / update_rate; + while (publish_credit_ >= 1.0) { + publish_credit_ -= 1.0; + publish_pose(); + } + } + +private: + static double radians_to_degrees(double radians) { + return radians * 180.0 / std::numbers::pi_v; + } + + static Eigen::Quaterniond quaternion_from_rpy(double roll, double pitch, double yaw) { + const Eigen::AngleAxisd roll_rotation{roll, Eigen::Vector3d::UnitX()}; + const Eigen::AngleAxisd pitch_rotation{pitch, Eigen::Vector3d::UnitY()}; + const Eigen::AngleAxisd yaw_rotation{yaw, Eigen::Vector3d::UnitZ()}; + return Eigen::Quaterniond{roll_rotation * pitch_rotation * yaw_rotation}; + } + + void load_parameters() { + mavros_pose_topic_ = get_parameter("mavros_pose_topic").as_string(); + mavros_pose_frame_id_ = get_parameter("mavros_pose_frame_id").as_string(); + target_frame_id_ = get_parameter("target_frame_id").as_string(); + source_frame_id_ = get_parameter("source_frame_id").as_string(); + output_rate_hz_ = get_parameter("output_rate").as_double(); + sensor_roll_offset_rad_ = get_parameter("sensor_roll_offset_rad").as_double(); + sensor_pitch_offset_rad_ = get_parameter("sensor_pitch_offset_rad").as_double(); + sensor_yaw_offset_rad_ = get_parameter("sensor_yaw_offset_rad").as_double(); + + output_rate_hz_ = std::max(0.0, output_rate_hz_); + } + + Eigen::Quaterniond sensor_to_body_rotation() const { + auto sensor_to_body = quaternion_from_rpy( + sensor_roll_offset_rad_, sensor_pitch_offset_rad_, sensor_yaw_offset_rad_); + sensor_to_body.normalize(); + return sensor_to_body; + } + + static bool finite_transform(const geometry_msgs::msg::TransformStamped& transform) { + const auto& t = transform.transform.translation; + const auto& r = transform.transform.rotation; + return std::isfinite(t.x) && std::isfinite(t.y) && std::isfinite(t.z) && std::isfinite(r.x) + && std::isfinite(r.y) && std::isfinite(r.z) && std::isfinite(r.w); + } + + Eigen::Vector3d rotate_world_position(const geometry_msgs::msg::Vector3& position) const { + return Eigen::Vector3d{position.x, position.y, position.z}; + } + + Eigen::Quaterniond + rotate_body_orientation(const geometry_msgs::msg::Quaternion& orientation) const { + const Eigen::Quaterniond quat_sensor{ + orientation.w, orientation.x, orientation.y, orientation.z}; + + Eigen::Quaterniond quat_body = quat_sensor * sensor_to_body_rotation(); + quat_body.normalize(); + return quat_body; + } + + void update_pose_from_tf() { + geometry_msgs::msg::TransformStamped transform; + try { + transform = + tf_buffer_.lookupTransform(target_frame_id_, source_frame_id_, tf2::TimePointZero); + } catch (const tf2::TransformException& ex) { + RCLCPP_WARN_THROTTLE( + logger_, *get_clock(), 1000, "TF lookup failed for '%s' -> '%s': %s", + source_frame_id_.c_str(), target_frame_id_.c_str(), ex.what()); + return; + } + + if (!finite_transform(transform)) + return; + + const auto tf_stamp_ns = rclcpp::Time{transform.header.stamp}.nanoseconds(); + + std::lock_guard lock(pose_mutex_); + if (last_tf_stamp_ns_ != 0 && tf_stamp_ns <= last_tf_stamp_ns_) + return; + + const Eigen::Vector3d rotated_position = + rotate_world_position(transform.transform.translation); + const Eigen::Quaterniond rotated_orientation = + rotate_body_orientation(transform.transform.rotation); + + latest_pose_.position.x = rotated_position.x(); + latest_pose_.position.y = rotated_position.y(); + latest_pose_.position.z = rotated_position.z(); + latest_pose_.orientation.x = rotated_orientation.x(); + latest_pose_.orientation.y = rotated_orientation.y(); + latest_pose_.orientation.z = rotated_orientation.z(); + latest_pose_.orientation.w = rotated_orientation.w(); + last_tf_stamp_ns_ = tf_stamp_ns; + last_pose_received_time_ = get_clock()->now(); + pose_ready_ = true; + + RCLCPP_INFO_THROTTLE( + logger_, *get_clock(), 1000, "Received TF '%s' -> '%s'.", source_frame_id_.c_str(), + target_frame_id_.c_str()); + } + + void publish_pose() { + geometry_msgs::msg::Pose pose; + rclcpp::Time pose_received_time{0, 0, get_clock()->get_clock_type()}; + { + std::lock_guard lock(pose_mutex_); + if (!pose_ready_) + return; + pose_received_time = last_pose_received_time_; + pose = latest_pose_; + } + + const rclcpp::Duration max_pose_age = rclcpp::Duration::from_seconds(1.0); + rclcpp::Time publish_stamp = get_clock()->now(); + if ((publish_stamp - pose_received_time) >= max_pose_age) + return; + + { + std::lock_guard lock(pose_mutex_); + if (last_published_stamp_ns_ != 0 + && publish_stamp.nanoseconds() <= last_published_stamp_ns_) { + publish_stamp = + rclcpp::Time{last_published_stamp_ns_ + 1, get_clock()->get_clock_type()}; + } + last_published_stamp_ns_ = publish_stamp.nanoseconds(); + } + + geometry_msgs::msg::PoseStamped pose_msg{}; + pose_msg.header.stamp = publish_stamp; + pose_msg.header.frame_id = mavros_pose_frame_id_; + pose_msg.pose = pose; + mavros_pose_publisher_->publish(pose_msg); + + RCLCPP_INFO_THROTTLE( + logger_, *get_clock(), 1000, "Published MAVROS vision pose at %.1f Hz to '%s'.", + output_rate_hz_, mavros_pose_publisher_->get_topic_name()); + } + + rclcpp::Logger logger_; + std::string mavros_pose_topic_; + std::string mavros_pose_frame_id_; + std::string target_frame_id_; + std::string source_frame_id_; + double output_rate_hz_; + double sensor_roll_offset_rad_; + double sensor_pitch_offset_rad_; + double sensor_yaw_offset_rad_; + tf2_ros::Buffer tf_buffer_; + tf2_ros::TransformListener tf_listener_; + + rclcpp::Publisher::SharedPtr mavros_pose_publisher_; + + InputInterface update_rate_; + + std::mutex pose_mutex_; + geometry_msgs::msg::Pose latest_pose_{}; + std::int64_t last_tf_stamp_ns_{0}; + rclcpp::Time last_pose_received_time_; + std::int64_t last_published_stamp_ns_{0}; + double publish_credit_{0.0}; + bool pose_ready_{false}; +}; + +} // namespace rmcs_core::hardware + +#include +PLUGINLIB_EXPORT_CLASS(rmcs_core::hardware::FlightMavros, rmcs_executor::Component) From 6ef94bbc42394ba61d5e874598cd0c3bca56e487 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Mon, 11 May 2026 14:19:33 +0800 Subject: [PATCH 05/30] feat: launch odin_ros_driver in startup script --- .../src/rmcs_bringup/launch/rmcs.launch.py | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py index 976cb9e7..537aadd8 100644 --- a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py +++ b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py @@ -6,7 +6,8 @@ LaunchDescription, LaunchDescriptionEntity, ) -from launch.actions import LogInfo +from launch.actions import IncludeLaunchDescription, LogInfo +from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import LaunchConfiguration from launch_ros.actions import Node @@ -28,10 +29,7 @@ def visit( robot_name = robot_config entities.append( - LogInfo( - msg=f"Starting RMCS on robot '{robot_config}'{'(automatic)' if is_automatic else ''} -> {robot_name}.yaml" - ) - ) + LogInfo(msg=f"Starting RMCS on robot -> {robot_name}.yaml")) entities.append( Node( @@ -46,13 +44,29 @@ def visit( ], respawn=True, respawn_delay=1.0, - output="log", # stdout and stderr are logged to launch log file and stderr to the screen. + output="log", ) ) if is_automatic: pass + entities.append( + IncludeLaunchDescription( + PythonLaunchDescriptionSource([ + FindPackageShare("odin_ros_driver"), "/launch/odin1_ros2.launch.py" + ]) + ) + ) + + entities.append( + IncludeLaunchDescription( + PythonLaunchDescriptionSource([ + FindPackageShare('rmcs_auto_aim_v2'), '/launch.py' + ]) + ) + ) + return entities From e76872d653517edec5c77d6bb673615d9b72822b Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Mon, 11 May 2026 14:35:12 +0800 Subject: [PATCH 06/30] chore: update rmcs_auto_aim_v2 submodule --- rmcs_ws/src/rmcs_auto_aim_v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rmcs_ws/src/rmcs_auto_aim_v2 b/rmcs_ws/src/rmcs_auto_aim_v2 index d665f7bc..8c16a237 160000 --- a/rmcs_ws/src/rmcs_auto_aim_v2 +++ b/rmcs_ws/src/rmcs_auto_aim_v2 @@ -1 +1 @@ -Subproject commit d665f7bc35e2f60bbd7b0564ef65c0947f9fa973 +Subproject commit 8c16a23745ed4c880f0823f90d37d5fd2362c015 From 62774950771426b0411f8cefed944c9cf940236b Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Wed, 13 May 2026 01:40:01 +0800 Subject: [PATCH 07/30] refactor: restructure flight_mavros module --- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 9 +- rmcs_ws/src/rmcs_core/package.xml | 3 +- .../rmcs_core/src/hardware/flight_mavros.cpp | 212 +++++------------- 3 files changed, 64 insertions(+), 160 deletions(-) diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index 8c4057cd..5d2ee6e8 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -3,7 +3,7 @@ rmcs_executor: update_rate: 1000.0 components: - rmcs_core::hardware::Flight -> flight_hardware - # - rmcs_core::hardware::FlightMavros -> flight_mavros_hardware + - rmcs_core::hardware::FlightMavros -> flight_mavros_hardware - rmcs_core::controller::gimbal::SimpleGimbalController -> gimbal_controller - rmcs_core::controller::pid::ErrorPidController -> yaw_angle_pid_controller @@ -24,7 +24,7 @@ rmcs_executor: - rmcs_core::broadcaster::ValueBroadcaster -> value_broadcaster - rmcs_core::broadcaster::TfBroadcaster -> tf_broadcaster - # - rmcs::AutoAimComponent -> auto_aim_component + - rmcs::AutoAimComponent -> auto_aim_component mavros: ros__parameters: @@ -75,14 +75,11 @@ flight_hardware: flight_mavros_hardware: ros__parameters: - target_frame_id: odom - source_frame_id: odin1_base_link - output_rate: 30.0 + odometry_topic: /odin1/odometry sensor_roll_offset_rad: 3.141592653589793 sensor_pitch_offset_rad: 1.5707963267948966 sensor_yaw_offset_rad: 0.0 mavros_pose_topic: /mavros/vision_pose/pose - mavros_pose_frame_id: odom referee_status: ros__parameters: diff --git a/rmcs_ws/src/rmcs_core/package.xml b/rmcs_ws/src/rmcs_core/package.xml index 4312d334..9eb6b089 100644 --- a/rmcs_ws/src/rmcs_core/package.xml +++ b/rmcs_ws/src/rmcs_core/package.xml @@ -10,11 +10,10 @@ ament_cmake rclcpp + nav_msgs std_msgs std_srvs pluginlib - tf2 - tf2_ros serial rmcs_utility rmcs_msgs diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp index 54362804..6a1dee4c 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp @@ -1,20 +1,16 @@ -#include +#include #include #include -#include #include #include #include #include -#include -#include +#include #include #include -#include -#include -#include +#include #include @@ -26,45 +22,51 @@ class FlightMavros public: FlightMavros() : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} - , logger_(get_logger()) - , tf_buffer_(get_clock()) - , tf_listener_(tf_buffer_) - , last_pose_received_time_{0, 0, get_clock()->get_clock_type()} { - load_parameters(); - register_input("/predefined/update_rate", update_rate_); + , logger_(get_logger()) { + odometry_topic_ = get_parameter("odometry_topic").as_string(); + const auto mavros_pose_topic = get_parameter("mavros_pose_topic").as_string(); + const auto sensor_roll_offset_rad = get_parameter("sensor_roll_offset_rad").as_double(); + const auto sensor_pitch_offset_rad = get_parameter("sensor_pitch_offset_rad").as_double(); + const auto sensor_yaw_offset_rad = get_parameter("sensor_yaw_offset_rad").as_double(); + + sensor_to_body_rotation_ = quaternion_from_rpy( + sensor_roll_offset_rad, sensor_pitch_offset_rad, sensor_yaw_offset_rad); + sensor_to_body_rotation_.normalize(); mavros_pose_publisher_ = create_publisher( - mavros_pose_topic_, rclcpp::QoS{10}.reliable()); + mavros_pose_topic, rclcpp::QoS{10}.reliable()); + odometry_subscription_ = create_subscription( + odometry_topic_, rclcpp::QoS{10}.reliable(), + [this](nav_msgs::msg::Odometry::ConstSharedPtr msg) { odometry_callback(msg); }); + last_odometry_received_time_ns_.store( + get_clock()->now().nanoseconds(), std::memory_order_relaxed); RCLCPP_INFO( logger_, - "FlightMavros bridging TF '%s' -> '%s' to '%s' with sensor RPY [%.1f, %.1f, %.1f] " + "FlightMavros bridging odometry '%s' to '%s' with sensor RPY [%.1f, %.1f, %.1f] " "deg.", - source_frame_id_.c_str(), target_frame_id_.c_str(), - mavros_pose_publisher_->get_topic_name(), radians_to_degrees(sensor_roll_offset_rad_), - radians_to_degrees(sensor_pitch_offset_rad_), - radians_to_degrees(sensor_yaw_offset_rad_)); + odometry_topic_.c_str(), mavros_pose_publisher_->get_topic_name(), + radians_to_degrees(sensor_roll_offset_rad), radians_to_degrees(sensor_pitch_offset_rad), + radians_to_degrees(sensor_yaw_offset_rad)); } ~FlightMavros() override = default; void update() override { - update_pose_from_tf(); - const double update_rate = *update_rate_; - if (!std::isfinite(update_rate) || update_rate <= 0.0) - return; - - publish_credit_ += output_rate_hz_ / update_rate; - while (publish_credit_ >= 1.0) { - publish_credit_ -= 1.0; - publish_pose(); + const auto now_ns = get_clock()->now().nanoseconds(); + const auto last_odometry_received_time_ns = + last_odometry_received_time_ns_.load(std::memory_order_relaxed); + if (now_ns - last_odometry_received_time_ns >= kOdometryTimeoutNs) { + RCLCPP_WARN_THROTTLE( + logger_, *get_clock(), 1000, "No odometry received on '%s' for more than %.1f s.", + odometry_topic_.c_str(), static_cast(kOdometryTimeoutNs) / 1'000'000'000.0); } } private: - static double radians_to_degrees(double radians) { - return radians * 180.0 / std::numbers::pi_v; - } + static constexpr std::int64_t kOdometryTimeoutNs{1'000'000'000}; // 1s + + static double radians_to_degrees(double radians) { return radians * 180.0 / std::numbers::pi; } static Eigen::Quaterniond quaternion_from_rpy(double roll, double pitch, double yaw) { const Eigen::AngleAxisd roll_rotation{roll, Eigen::Vector3d::UnitX()}; @@ -73,149 +75,55 @@ class FlightMavros return Eigen::Quaterniond{roll_rotation * pitch_rotation * yaw_rotation}; } - void load_parameters() { - mavros_pose_topic_ = get_parameter("mavros_pose_topic").as_string(); - mavros_pose_frame_id_ = get_parameter("mavros_pose_frame_id").as_string(); - target_frame_id_ = get_parameter("target_frame_id").as_string(); - source_frame_id_ = get_parameter("source_frame_id").as_string(); - output_rate_hz_ = get_parameter("output_rate").as_double(); - sensor_roll_offset_rad_ = get_parameter("sensor_roll_offset_rad").as_double(); - sensor_pitch_offset_rad_ = get_parameter("sensor_pitch_offset_rad").as_double(); - sensor_yaw_offset_rad_ = get_parameter("sensor_yaw_offset_rad").as_double(); - - output_rate_hz_ = std::max(0.0, output_rate_hz_); - } - - Eigen::Quaterniond sensor_to_body_rotation() const { - auto sensor_to_body = quaternion_from_rpy( - sensor_roll_offset_rad_, sensor_pitch_offset_rad_, sensor_yaw_offset_rad_); - sensor_to_body.normalize(); - return sensor_to_body; - } - - static bool finite_transform(const geometry_msgs::msg::TransformStamped& transform) { - const auto& t = transform.transform.translation; - const auto& r = transform.transform.rotation; - return std::isfinite(t.x) && std::isfinite(t.y) && std::isfinite(t.z) && std::isfinite(r.x) - && std::isfinite(r.y) && std::isfinite(r.z) && std::isfinite(r.w); - } - - Eigen::Vector3d rotate_world_position(const geometry_msgs::msg::Vector3& position) const { - return Eigen::Vector3d{position.x, position.y, position.z}; - } - Eigen::Quaterniond rotate_body_orientation(const geometry_msgs::msg::Quaternion& orientation) const { const Eigen::Quaterniond quat_sensor{ orientation.w, orientation.x, orientation.y, orientation.z}; - Eigen::Quaterniond quat_body = quat_sensor * sensor_to_body_rotation(); + Eigen::Quaterniond quat_body = quat_sensor * sensor_to_body_rotation_; quat_body.normalize(); return quat_body; } - void update_pose_from_tf() { - geometry_msgs::msg::TransformStamped transform; - try { - transform = - tf_buffer_.lookupTransform(target_frame_id_, source_frame_id_, tf2::TimePointZero); - } catch (const tf2::TransformException& ex) { + void odometry_callback(const nav_msgs::msg::Odometry::ConstSharedPtr& msg) { + last_odometry_received_time_ns_.store( + get_clock()->now().nanoseconds(), std::memory_order_relaxed); + + RCLCPP_INFO_ONCE( + logger_, "Received odometry from '%s' with frame '%s' and child frame '%s'.", + odometry_topic_.c_str(), msg->header.frame_id.c_str(), msg->child_frame_id.c_str()); + + if (msg->header.frame_id != "odom" || msg->child_frame_id != "odin1_base_link") { RCLCPP_WARN_THROTTLE( - logger_, *get_clock(), 1000, "TF lookup failed for '%s' -> '%s': %s", - source_frame_id_.c_str(), target_frame_id_.c_str(), ex.what()); - return; + logger_, *get_clock(), 1000, + "Unexpected odometry frames: header='%s', child='%s'. Expected 'odom' and " + "'odin1_base_link'.", + msg->header.frame_id.c_str(), msg->child_frame_id.c_str()); } - if (!finite_transform(transform)) - return; - - const auto tf_stamp_ns = rclcpp::Time{transform.header.stamp}.nanoseconds(); + geometry_msgs::msg::PoseStamped pose_msg{}; + pose_msg.header.stamp = msg->header.stamp; + pose_msg.header.frame_id = msg->header.frame_id; - std::lock_guard lock(pose_mutex_); - if (last_tf_stamp_ns_ != 0 && tf_stamp_ns <= last_tf_stamp_ns_) - return; + pose_msg.pose.position = msg->pose.pose.position; - const Eigen::Vector3d rotated_position = - rotate_world_position(transform.transform.translation); const Eigen::Quaterniond rotated_orientation = - rotate_body_orientation(transform.transform.rotation); - - latest_pose_.position.x = rotated_position.x(); - latest_pose_.position.y = rotated_position.y(); - latest_pose_.position.z = rotated_position.z(); - latest_pose_.orientation.x = rotated_orientation.x(); - latest_pose_.orientation.y = rotated_orientation.y(); - latest_pose_.orientation.z = rotated_orientation.z(); - latest_pose_.orientation.w = rotated_orientation.w(); - last_tf_stamp_ns_ = tf_stamp_ns; - last_pose_received_time_ = get_clock()->now(); - pose_ready_ = true; - - RCLCPP_INFO_THROTTLE( - logger_, *get_clock(), 1000, "Received TF '%s' -> '%s'.", source_frame_id_.c_str(), - target_frame_id_.c_str()); - } - - void publish_pose() { - geometry_msgs::msg::Pose pose; - rclcpp::Time pose_received_time{0, 0, get_clock()->get_clock_type()}; - { - std::lock_guard lock(pose_mutex_); - if (!pose_ready_) - return; - pose_received_time = last_pose_received_time_; - pose = latest_pose_; - } + rotate_body_orientation(msg->pose.pose.orientation); + pose_msg.pose.orientation.x = rotated_orientation.x(); + pose_msg.pose.orientation.y = rotated_orientation.y(); + pose_msg.pose.orientation.z = rotated_orientation.z(); + pose_msg.pose.orientation.w = rotated_orientation.w(); - const rclcpp::Duration max_pose_age = rclcpp::Duration::from_seconds(1.0); - rclcpp::Time publish_stamp = get_clock()->now(); - if ((publish_stamp - pose_received_time) >= max_pose_age) - return; - - { - std::lock_guard lock(pose_mutex_); - if (last_published_stamp_ns_ != 0 - && publish_stamp.nanoseconds() <= last_published_stamp_ns_) { - publish_stamp = - rclcpp::Time{last_published_stamp_ns_ + 1, get_clock()->get_clock_type()}; - } - last_published_stamp_ns_ = publish_stamp.nanoseconds(); - } - - geometry_msgs::msg::PoseStamped pose_msg{}; - pose_msg.header.stamp = publish_stamp; - pose_msg.header.frame_id = mavros_pose_frame_id_; - pose_msg.pose = pose; mavros_pose_publisher_->publish(pose_msg); - - RCLCPP_INFO_THROTTLE( - logger_, *get_clock(), 1000, "Published MAVROS vision pose at %.1f Hz to '%s'.", - output_rate_hz_, mavros_pose_publisher_->get_topic_name()); } rclcpp::Logger logger_; - std::string mavros_pose_topic_; - std::string mavros_pose_frame_id_; - std::string target_frame_id_; - std::string source_frame_id_; - double output_rate_hz_; - double sensor_roll_offset_rad_; - double sensor_pitch_offset_rad_; - double sensor_yaw_offset_rad_; - tf2_ros::Buffer tf_buffer_; - tf2_ros::TransformListener tf_listener_; + std::string odometry_topic_; + Eigen::Quaterniond sensor_to_body_rotation_{Eigen::Quaterniond::Identity()}; + std::atomic last_odometry_received_time_ns_{0}; rclcpp::Publisher::SharedPtr mavros_pose_publisher_; - - InputInterface update_rate_; - - std::mutex pose_mutex_; - geometry_msgs::msg::Pose latest_pose_{}; - std::int64_t last_tf_stamp_ns_{0}; - rclcpp::Time last_pose_received_time_; - std::int64_t last_published_stamp_ns_{0}; - double publish_credit_{0.0}; - bool pose_ready_{false}; + rclcpp::Subscription::SharedPtr odometry_subscription_; }; } // namespace rmcs_core::hardware From 0129fa1667c29ddb1f0249ae90cd91a9389f8916 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Wed, 13 May 2026 01:40:01 +0800 Subject: [PATCH 08/30] refactor: restructure flight_mavros module --- rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp index 6a1dee4c..8536c831 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp @@ -37,7 +37,7 @@ class FlightMavros mavros_pose_topic, rclcpp::QoS{10}.reliable()); odometry_subscription_ = create_subscription( odometry_topic_, rclcpp::QoS{10}.reliable(), - [this](nav_msgs::msg::Odometry::ConstSharedPtr msg) { odometry_callback(msg); }); + [this](const nav_msgs::msg::Odometry::ConstSharedPtr& msg) { odometry_callback(msg); }); last_odometry_received_time_ns_.store( get_clock()->now().nanoseconds(), std::memory_order_relaxed); @@ -64,7 +64,7 @@ class FlightMavros } private: - static constexpr std::int64_t kOdometryTimeoutNs{1'000'000'000}; // 1s + static constexpr std::int64_t kOdometryTimeoutNs{1'000'000'000}; static double radians_to_degrees(double radians) { return radians * 180.0 / std::numbers::pi; } @@ -104,7 +104,6 @@ class FlightMavros geometry_msgs::msg::PoseStamped pose_msg{}; pose_msg.header.stamp = msg->header.stamp; pose_msg.header.frame_id = msg->header.frame_id; - pose_msg.pose.position = msg->pose.pose.position; const Eigen::Quaterniond rotated_orientation = From 2c79e27199ac5fe59a5873701e8d1dca9d9f58db Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Wed, 13 May 2026 23:50:26 +0800 Subject: [PATCH 09/30] refactor: update gimbal coordinate transformation --- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index ba0b5439..d0d15155 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -73,8 +73,8 @@ class Flight [](double x, double y, double z) { return std::make_tuple(-x, z, y); }); using namespace rmcs_description; // NOLINT(google-build-using-namespace) - constexpr double rotor_distance_x = 0.83637; - constexpr double rotor_distance_y = 0.83637; + constexpr double rotor_distance_x = 1.128; + constexpr double rotor_distance_y = 1.128; tf_->set_transform( Eigen::Translation3d{rotor_distance_x / 2, rotor_distance_y / 2, 0}); @@ -85,12 +85,15 @@ class Flight tf_->set_transform( Eigen::Translation3d{-rotor_distance_x / 2, -rotor_distance_y / 2, 0}); - constexpr double gimbal_center_x = 0.0; - constexpr double gimbal_center_y = 0.0; - constexpr double gimbal_center_z = -0.20552; + // GimbalCenterLink 原点等效于 YawLink 和 PitchLink 的交点 + constexpr double gimbal_center_z = -0.27812; tf_->set_transform( - Eigen::Translation3d{gimbal_center_x, gimbal_center_y, gimbal_center_z}); - tf_->set_transform(Eigen::Translation3d{0.1572, 0.00675, 0.0528}); + Eigen::Translation3d{0.0, 0.0, gimbal_center_z}); + constexpr auto camera_postion_x = 0.10238; + constexpr auto camera_postion_z = 0.05286; + + tf_->set_transform( + Eigen::Translation3d{camera_postion_x, 0.0, camera_postion_z}); gimbal_calibrate_subscription_ = create_subscription( "/gimbal/calibrate", rclcpp::QoS{0}, [this](std_msgs::msg::Int32::UniquePtr&& msg) { From 9c22bbd81d224bc4d58d9b35fdeefa3285f1e7cb Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Thu, 14 May 2026 00:42:43 +0800 Subject: [PATCH 10/30] feat(launch): integrate MAVROS node in launch script for FCU communication --- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 1 - .../src/rmcs_bringup/launch/rmcs.launch.py | 24 +++++++++++++++++++ rmcs_ws/src/rmcs_bringup/package.xml | 3 ++- .../gimbal/simple_gimbal_controller.cpp | 12 ++++++---- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index 5d2ee6e8..da23e880 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -62,7 +62,6 @@ value_broadcaster: - /gimbal/yaw/control_angle_error - /gimbal/yaw/velocity_imu - tf_broadcaster: ros__parameters: tf: /tf diff --git a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py index 537aadd8..bd076a3c 100644 --- a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py +++ b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py @@ -59,6 +59,30 @@ def visit( ) ) + mavros_share = FindPackageShare("mavros").perform(context) + entities.append( + Node( + package="mavros", + executable="mavros_node", + namespace="mavros", + parameters=[ + os.path.join(mavros_share, "launch", "px4_pluginlists.yaml"), + os.path.join(mavros_share, "launch", "px4_config.yaml"), + { + "fcu_url": "serial:///dev/ttyACM0:921600", + "gcs_url": "", + "tgt_system": 1, + "tgt_component": 1, + "fcu_protocol": "v2.0", + }, + ], + respawn=True, + respawn_delay=1.0, + output="screen", + emulate_tty=True, + ) + ) + entities.append( IncludeLaunchDescription( PythonLaunchDescriptionSource([ diff --git a/rmcs_ws/src/rmcs_bringup/package.xml b/rmcs_ws/src/rmcs_bringup/package.xml index c64c661f..43835a9b 100644 --- a/rmcs_ws/src/rmcs_bringup/package.xml +++ b/rmcs_ws/src/rmcs_bringup/package.xml @@ -11,6 +11,7 @@ ament_cmake joint_state_broadcaster + mavros robot_state_publisher rviz2 xacro @@ -21,4 +22,4 @@ ament_cmake - \ No newline at end of file + diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp index e18b0dd9..44e26673 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp @@ -46,16 +46,18 @@ class SimpleGimbalController TwoAxisGimbalSolver::AngleError calculate_angle_error() { auto switch_right = *switch_right_; auto switch_left = *switch_left_; + using namespace rmcs_msgs; if ((switch_left == Switch::UNKNOWN || switch_right == Switch::UNKNOWN) || (switch_left == Switch::DOWN && switch_right == Switch::DOWN)) return two_axis_gimbal_solver.update(TwoAxisGimbalSolver::SetDisabled()); - const auto auto_aim_active = - switch_right == Switch::UP && auto_aim_should_control_.ready() - && *auto_aim_should_control_ && auto_aim_control_direction_.ready() - && auto_aim_control_direction_->allFinite() && !auto_aim_control_direction_->isZero(); - if (auto_aim_active) { + const auto manual_active = switch_right == Switch::UP; + const auto should_control = auto_aim_should_control_.ready() && *auto_aim_should_control_; + const auto valid_control = + auto_aim_control_direction_.ready() && auto_aim_control_direction_->allFinite(); + + if (manual_active && should_control && valid_control) { return two_axis_gimbal_solver.update( TwoAxisGimbalSolver::SetControlDirection( OdomImu::DirectionVector(*auto_aim_control_direction_))); From 95df49f3e90851df4032e3352379a32507e19c0f Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Thu, 14 May 2026 21:00:18 +0800 Subject: [PATCH 11/30] refactor: restructure flight_mavros module and optimize odin launch scripts - Refactor flight_mavros to support absolute pose tracking and feedback. - Optimize odin1 launch script by integrating hardware drivers and auto-aim. - Remove default Rviz startup to reduce system overhead in headless mode. - Synchronize coordinate transformations for cross-platform deployment. --- rmcs_ws/src/odin_ros_driver | 2 +- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 13 +- .../src/rmcs_bringup/launch/rmcs.launch.py | 9 +- rmcs_ws/src/rmcs_bringup/package.xml | 1 + .../rmcs_core/src/hardware/flight_mavros.cpp | 131 ------------------ 5 files changed, 9 insertions(+), 147 deletions(-) delete mode 100644 rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp diff --git a/rmcs_ws/src/odin_ros_driver b/rmcs_ws/src/odin_ros_driver index dbcb0286..165a7907 160000 --- a/rmcs_ws/src/odin_ros_driver +++ b/rmcs_ws/src/odin_ros_driver @@ -1 +1 @@ -Subproject commit dbcb0286b510142e966ac090a37ce5ca238f9e75 +Subproject commit 165a79072fc292b73f388765e23a23aa99561f55 diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index da23e880..1f21f85e 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -3,7 +3,6 @@ rmcs_executor: update_rate: 1000.0 components: - rmcs_core::hardware::Flight -> flight_hardware - - rmcs_core::hardware::FlightMavros -> flight_mavros_hardware - rmcs_core::controller::gimbal::SimpleGimbalController -> gimbal_controller - rmcs_core::controller::pid::ErrorPidController -> yaw_angle_pid_controller @@ -72,14 +71,6 @@ flight_hardware: yaw_motor_zero_point: 11720 pitch_motor_zero_point: 18578 -flight_mavros_hardware: - ros__parameters: - odometry_topic: /odin1/odometry - sensor_roll_offset_rad: 3.141592653589793 - sensor_pitch_offset_rad: 1.5707963267948966 - sensor_yaw_offset_rad: 0.0 - mavros_pose_topic: /mavros/vision_pose/pose - referee_status: ros__parameters: path: /dev/tty0 @@ -121,8 +112,8 @@ friction_wheel_controller: - /gimbal/left_friction - /gimbal/right_friction friction_velocities: - - 740.0 - - 740.0 + - 610.0 + - 610.0 friction_soft_start_stop_time: 1.0 heat_controller: diff --git a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py index bd076a3c..b56e910d 100644 --- a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py +++ b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py @@ -52,10 +52,11 @@ def visit( pass entities.append( - IncludeLaunchDescription( - PythonLaunchDescriptionSource([ - FindPackageShare("odin_ros_driver"), "/launch/odin1_ros2.launch.py" - ]) + Node( + package="odin_ros_driver", + executable="tmux-launch.sh", + output="screen", + emulate_tty=True, ) ) diff --git a/rmcs_ws/src/rmcs_bringup/package.xml b/rmcs_ws/src/rmcs_bringup/package.xml index 43835a9b..8642966e 100644 --- a/rmcs_ws/src/rmcs_bringup/package.xml +++ b/rmcs_ws/src/rmcs_bringup/package.xml @@ -12,6 +12,7 @@ joint_state_broadcaster mavros + odin_ros_driver robot_state_publisher rviz2 xacro diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp deleted file mode 100644 index 8536c831..00000000 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight_mavros.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -namespace rmcs_core::hardware { - -class FlightMavros - : public rmcs_executor::Component - , public rclcpp::Node { -public: - FlightMavros() - : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} - , logger_(get_logger()) { - odometry_topic_ = get_parameter("odometry_topic").as_string(); - const auto mavros_pose_topic = get_parameter("mavros_pose_topic").as_string(); - const auto sensor_roll_offset_rad = get_parameter("sensor_roll_offset_rad").as_double(); - const auto sensor_pitch_offset_rad = get_parameter("sensor_pitch_offset_rad").as_double(); - const auto sensor_yaw_offset_rad = get_parameter("sensor_yaw_offset_rad").as_double(); - - sensor_to_body_rotation_ = quaternion_from_rpy( - sensor_roll_offset_rad, sensor_pitch_offset_rad, sensor_yaw_offset_rad); - sensor_to_body_rotation_.normalize(); - - mavros_pose_publisher_ = create_publisher( - mavros_pose_topic, rclcpp::QoS{10}.reliable()); - odometry_subscription_ = create_subscription( - odometry_topic_, rclcpp::QoS{10}.reliable(), - [this](const nav_msgs::msg::Odometry::ConstSharedPtr& msg) { odometry_callback(msg); }); - last_odometry_received_time_ns_.store( - get_clock()->now().nanoseconds(), std::memory_order_relaxed); - - RCLCPP_INFO( - logger_, - "FlightMavros bridging odometry '%s' to '%s' with sensor RPY [%.1f, %.1f, %.1f] " - "deg.", - odometry_topic_.c_str(), mavros_pose_publisher_->get_topic_name(), - radians_to_degrees(sensor_roll_offset_rad), radians_to_degrees(sensor_pitch_offset_rad), - radians_to_degrees(sensor_yaw_offset_rad)); - } - - ~FlightMavros() override = default; - - void update() override { - const auto now_ns = get_clock()->now().nanoseconds(); - const auto last_odometry_received_time_ns = - last_odometry_received_time_ns_.load(std::memory_order_relaxed); - if (now_ns - last_odometry_received_time_ns >= kOdometryTimeoutNs) { - RCLCPP_WARN_THROTTLE( - logger_, *get_clock(), 1000, "No odometry received on '%s' for more than %.1f s.", - odometry_topic_.c_str(), static_cast(kOdometryTimeoutNs) / 1'000'000'000.0); - } - } - -private: - static constexpr std::int64_t kOdometryTimeoutNs{1'000'000'000}; - - static double radians_to_degrees(double radians) { return radians * 180.0 / std::numbers::pi; } - - static Eigen::Quaterniond quaternion_from_rpy(double roll, double pitch, double yaw) { - const Eigen::AngleAxisd roll_rotation{roll, Eigen::Vector3d::UnitX()}; - const Eigen::AngleAxisd pitch_rotation{pitch, Eigen::Vector3d::UnitY()}; - const Eigen::AngleAxisd yaw_rotation{yaw, Eigen::Vector3d::UnitZ()}; - return Eigen::Quaterniond{roll_rotation * pitch_rotation * yaw_rotation}; - } - - Eigen::Quaterniond - rotate_body_orientation(const geometry_msgs::msg::Quaternion& orientation) const { - const Eigen::Quaterniond quat_sensor{ - orientation.w, orientation.x, orientation.y, orientation.z}; - - Eigen::Quaterniond quat_body = quat_sensor * sensor_to_body_rotation_; - quat_body.normalize(); - return quat_body; - } - - void odometry_callback(const nav_msgs::msg::Odometry::ConstSharedPtr& msg) { - last_odometry_received_time_ns_.store( - get_clock()->now().nanoseconds(), std::memory_order_relaxed); - - RCLCPP_INFO_ONCE( - logger_, "Received odometry from '%s' with frame '%s' and child frame '%s'.", - odometry_topic_.c_str(), msg->header.frame_id.c_str(), msg->child_frame_id.c_str()); - - if (msg->header.frame_id != "odom" || msg->child_frame_id != "odin1_base_link") { - RCLCPP_WARN_THROTTLE( - logger_, *get_clock(), 1000, - "Unexpected odometry frames: header='%s', child='%s'. Expected 'odom' and " - "'odin1_base_link'.", - msg->header.frame_id.c_str(), msg->child_frame_id.c_str()); - } - - geometry_msgs::msg::PoseStamped pose_msg{}; - pose_msg.header.stamp = msg->header.stamp; - pose_msg.header.frame_id = msg->header.frame_id; - pose_msg.pose.position = msg->pose.pose.position; - - const Eigen::Quaterniond rotated_orientation = - rotate_body_orientation(msg->pose.pose.orientation); - pose_msg.pose.orientation.x = rotated_orientation.x(); - pose_msg.pose.orientation.y = rotated_orientation.y(); - pose_msg.pose.orientation.z = rotated_orientation.z(); - pose_msg.pose.orientation.w = rotated_orientation.w(); - - mavros_pose_publisher_->publish(pose_msg); - } - - rclcpp::Logger logger_; - std::string odometry_topic_; - Eigen::Quaterniond sensor_to_body_rotation_{Eigen::Quaterniond::Identity()}; - std::atomic last_odometry_received_time_ns_{0}; - - rclcpp::Publisher::SharedPtr mavros_pose_publisher_; - rclcpp::Subscription::SharedPtr odometry_subscription_; -}; - -} // namespace rmcs_core::hardware - -#include -PLUGINLIB_EXPORT_CLASS(rmcs_core::hardware::FlightMavros, rmcs_executor::Component) From b27493560855165537e6186da0b2cb2c8d6786f0 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Sat, 16 May 2026 16:14:42 +0800 Subject: [PATCH 12/30] refactor: optimize odin1 launch script, fix referee serial port, update heat management, and conduct aerial tracking tests --- rmcs_ws/src/odin_ros_driver | 2 +- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 14 +++++------ .../src/rmcs_bringup/launch/rmcs.launch.py | 25 ------------------- .../gimbal/simple_gimbal_controller.cpp | 2 +- .../bullet_feeder_controller_17mm.cpp | 3 ++- .../controller/shooting/heat_controller.cpp | 2 +- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 4 +-- rmcs_ws/src/rmcs_core/src/referee/status.cpp | 4 +-- 8 files changed, 15 insertions(+), 41 deletions(-) diff --git a/rmcs_ws/src/odin_ros_driver b/rmcs_ws/src/odin_ros_driver index 165a7907..81cc4a60 160000 --- a/rmcs_ws/src/odin_ros_driver +++ b/rmcs_ws/src/odin_ros_driver @@ -1 +1 @@ -Subproject commit 165a79072fc292b73f388765e23a23aa99561f55 +Subproject commit 81cc4a604ce0f70d97ffee0ca766e89f43e238e9 diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index 1f21f85e..9a60b920 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -104,7 +104,7 @@ pitch_angle_pid_controller: control: /gimbal/pitch/control_velocity kp: 10.0 ki: 0.0 - kd: 0.0 + kd: 0.0 friction_wheel_controller: ros__parameters: @@ -112,19 +112,19 @@ friction_wheel_controller: - /gimbal/left_friction - /gimbal/right_friction friction_velocities: - - 610.0 - - 610.0 + - 770.0 + - 770.0 friction_soft_start_stop_time: 1.0 heat_controller: ros__parameters: - heat_per_shot: 1 - reserved_heat: 0 + heat_per_shot: 10000 + reserved_heat: 10000 bullet_feeder_controller: ros__parameters: bullets_per_feeder_turn: 8.0 - shot_frequency: 20.0 + shot_frequency: 30.0 safe_shot_frequency: 10.0 eject_frequency: 10.0 eject_time: 0.05 @@ -155,6 +155,6 @@ bullet_feeder_velocity_pid_controller: measurement: /gimbal/bullet_feeder/velocity setpoint: /gimbal/bullet_feeder/control_velocity control: /gimbal/bullet_feeder/control_torque - kp: 0.583 + kp: 1.5 ki: 0.0 kd: 0.0 diff --git a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py index b56e910d..adcafe2a 100644 --- a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py +++ b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py @@ -59,31 +59,6 @@ def visit( emulate_tty=True, ) ) - - mavros_share = FindPackageShare("mavros").perform(context) - entities.append( - Node( - package="mavros", - executable="mavros_node", - namespace="mavros", - parameters=[ - os.path.join(mavros_share, "launch", "px4_pluginlists.yaml"), - os.path.join(mavros_share, "launch", "px4_config.yaml"), - { - "fcu_url": "serial:///dev/ttyACM0:921600", - "gcs_url": "", - "tgt_system": 1, - "tgt_component": 1, - "fcu_protocol": "v2.0", - }, - ], - respawn=True, - respawn_delay=1.0, - output="screen", - emulate_tty=True, - ) - ) - entities.append( IncludeLaunchDescription( PythonLaunchDescriptionSource([ diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp index 44e26673..790f17c0 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp @@ -72,7 +72,7 @@ class SimpleGimbalController double yaw_shift = joystick_sensitivity * joystick_left_->y() + mouse_sensitivity * mouse_velocity_->y(); double pitch_shift = - -joystick_sensitivity * joystick_left_->x() - mouse_sensitivity * mouse_velocity_->x(); + -joystick_sensitivity * joystick_left_->x() + mouse_sensitivity * mouse_velocity_->x(); return two_axis_gimbal_solver.update( TwoAxisGimbalSolver::SetControlShift(yaw_shift, pitch_shift)); diff --git a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp index e90e62cc..4b148cd7 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp @@ -103,7 +103,8 @@ class BulletFeederController17mm if (*friction_ready_) { if (shoot_mode == ShootMode::AUTOMATIC) { bool triggered = mouse.left || switch_left == Switch::DOWN - || (switch_right == Switch::UP && *auto_aim_should_shoot_); + || (mouse.right && switch_right == Switch::UP + && *auto_aim_should_shoot_); bullet_allowance = triggered ? *control_bullet_allowance_limited_by_heat_ : 0; } else { diff --git a/rmcs_ws/src/rmcs_core/src/controller/shooting/heat_controller.cpp b/rmcs_ws/src/rmcs_core/src/controller/shooting/heat_controller.cpp index 3de0960a..c6901fbc 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/shooting/heat_controller.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/shooting/heat_controller.cpp @@ -53,4 +53,4 @@ class HeatController #include -PLUGINLIB_EXPORT_CLASS(rmcs_core::controller::shooting::HeatController, rmcs_executor::Component) \ No newline at end of file +PLUGINLIB_EXPORT_CLASS(rmcs_core::controller::shooting::HeatController, rmcs_executor::Component) diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index d0d15155..bfbedabb 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -106,7 +106,7 @@ class Flight [&buffer](std::byte byte) noexcept { *buffer++ = byte; }, size); }; referee_serial_->write = [this](const std::byte* buffer, size_t size) { - start_transmit().uart1_transmit( + start_transmit().uart2_transmit( {.uart_data = std::span{buffer, size}}); return size; }; @@ -215,7 +215,7 @@ class Flight } } - void uart1_receive_callback(const librmcs::data::UartDataView& data) override { + void uart2_receive_callback(const librmcs::data::UartDataView& data) override { const std::byte* ptr = data.uart_data.data(); referee_ring_buffer_receive_.emplace_back_n( [&ptr](std::byte* storage) noexcept { new (storage) std::byte{*ptr++}; }, diff --git a/rmcs_ws/src/rmcs_core/src/referee/status.cpp b/rmcs_ws/src/rmcs_core/src/referee/status.cpp index c080a355..6cb4e026 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/status.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/status.cpp @@ -21,9 +21,7 @@ class Status , public rclcpp::Node { public: Status() - : Node{ - get_component_name(), - rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} + : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} , logger_(get_logger()) { register_input("/referee/serial", serial_); From b015a98054cc57b97207f2955faab542aac62450 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Tue, 19 May 2026 14:46:20 +0800 Subject: [PATCH 13/30] config: update bullet speed --- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index 9a60b920..dd83cbb6 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -112,14 +112,14 @@ friction_wheel_controller: - /gimbal/left_friction - /gimbal/right_friction friction_velocities: - - 770.0 - - 770.0 + - 610.0 + - 610.0 friction_soft_start_stop_time: 1.0 heat_controller: ros__parameters: heat_per_shot: 10000 - reserved_heat: 10000 + reserved_heat: 15000 bullet_feeder_controller: ros__parameters: From 525d97920431fa434638c26366b961ece6557cd4 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Wed, 20 May 2026 04:45:50 +0800 Subject: [PATCH 14/30] feat: update serial baund, communicate with fcu successfully --- .script/template/entrypoint | 15 ++++++++++++++- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 15 ++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.script/template/entrypoint b/.script/template/entrypoint index e8660e7a..49290c5c 100755 --- a/.script/template/entrypoint +++ b/.script/template/entrypoint @@ -1,5 +1,18 @@ #!/usr/bin/bash +USBFS_MEMORY_MB="${USBFS_MEMORY_MB:-2000}" +USBFS_MEMORY_MB_PATH="/sys/module/usbcore/parameters/usbfs_memory_mb" + +if [ -w "$USBFS_MEMORY_MB_PATH" ]; then + if ! printf '%s\n' "$USBFS_MEMORY_MB" > "$USBFS_MEMORY_MB_PATH"; then + echo "Warning: failed to set $USBFS_MEMORY_MB_PATH to $USBFS_MEMORY_MB" >&2 + fi +elif [ -e "$USBFS_MEMORY_MB_PATH" ]; then + echo "Warning: $USBFS_MEMORY_MB_PATH is not writable, skipping usbfs_memory_mb setup" >&2 +else + echo "Warning: $USBFS_MEMORY_MB_PATH not found, skipping usbfs_memory_mb setup" >&2 +fi + # Remove all files in /tmp rm -rf /tmp/* @@ -14,4 +27,4 @@ if [ -f "/etc/avahi/enabled" ]; then service avahi-daemon start fi -sleep infinity \ No newline at end of file +sleep infinity diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index dd83cbb6..31a2bdd2 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -25,17 +25,6 @@ rmcs_executor: - rmcs::AutoAimComponent -> auto_aim_component -mavros: - ros__parameters: - enabled: true - fcu_url: serial:///dev/ttyACM0:921600 - gcs_url: "" - target_system_id: 1 - target_component_id: 1 - fcu_protocol: v2.0 - respawn: true - respawn_delay: 1.0 - odin_ros_driver: ros__parameters: enabled: true @@ -112,8 +101,8 @@ friction_wheel_controller: - /gimbal/left_friction - /gimbal/right_friction friction_velocities: - - 610.0 - - 610.0 + - 605.0 + - 605.0 friction_soft_start_stop_time: 1.0 heat_controller: From 097c64e45e589bde257cd2d17cd5ade65e20bf84 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Wed, 20 May 2026 04:49:25 +0800 Subject: [PATCH 15/30] feat: update odin ros driver --- rmcs_ws/src/odin_ros_driver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rmcs_ws/src/odin_ros_driver b/rmcs_ws/src/odin_ros_driver index 81cc4a60..5cb37012 160000 --- a/rmcs_ws/src/odin_ros_driver +++ b/rmcs_ws/src/odin_ros_driver @@ -1 +1 @@ -Subproject commit 81cc4a604ce0f70d97ffee0ca766e89f43e238e9 +Subproject commit 5cb37012a12686bb757923244eb0612285012c04 From b5216ace0b863cff33409dd8f8ead54e8bc77ecb Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Thu, 21 May 2026 05:37:54 +0800 Subject: [PATCH 16/30] feat: update ui and gimbal control --- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 11 +-- rmcs_ws/src/rmcs_core/plugins.xml | 1 + .../gimbal/simple_gimbal_controller.cpp | 4 +- .../rmcs_core/src/referee/app/ui/flight.cpp | 71 +++++++++++++++++++ .../src/referee/app/ui/widget/status_ring.hpp | 30 ++++++-- 5 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index 31a2bdd2..a42e0dcb 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -19,6 +19,8 @@ rmcs_executor: - rmcs_core::referee::command::Interaction -> referee_interaction - rmcs_core::referee::Command -> referee_command - rmcs_core::referee::Status -> referee_status + - rmcs_core::referee::command::interaction::Ui -> referee_ui + - rmcs_core::referee::app::ui::Flight -> referee_ui_flight - rmcs_core::broadcaster::ValueBroadcaster -> value_broadcaster - rmcs_core::broadcaster::TfBroadcaster -> tf_broadcaster @@ -49,6 +51,7 @@ value_broadcaster: - /gimbal/yaw/control_torque - /gimbal/yaw/control_angle_error - /gimbal/yaw/velocity_imu + - /gimbal/bullet_feeder/velocity tf_broadcaster: ros__parameters: @@ -101,8 +104,8 @@ friction_wheel_controller: - /gimbal/left_friction - /gimbal/right_friction friction_velocities: - - 605.0 - - 605.0 + - 600.0 + - 600.0 friction_soft_start_stop_time: 1.0 heat_controller: @@ -113,7 +116,7 @@ heat_controller: bullet_feeder_controller: ros__parameters: bullets_per_feeder_turn: 8.0 - shot_frequency: 30.0 + shot_frequency: 25.0 safe_shot_frequency: 10.0 eject_frequency: 10.0 eject_time: 0.05 @@ -144,6 +147,6 @@ bullet_feeder_velocity_pid_controller: measurement: /gimbal/bullet_feeder/velocity setpoint: /gimbal/bullet_feeder/control_velocity control: /gimbal/bullet_feeder/control_torque - kp: 1.5 + kp: 0.583 ki: 0.0 kd: 0.0 diff --git a/rmcs_ws/src/rmcs_core/plugins.xml b/rmcs_ws/src/rmcs_core/plugins.xml index 58f30161..51fb30aa 100644 --- a/rmcs_ws/src/rmcs_core/plugins.xml +++ b/rmcs_ws/src/rmcs_core/plugins.xml @@ -50,6 +50,7 @@ + diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp index 790f17c0..7873188b 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp @@ -52,12 +52,12 @@ class SimpleGimbalController || (switch_left == Switch::DOWN && switch_right == Switch::DOWN)) return two_axis_gimbal_solver.update(TwoAxisGimbalSolver::SetDisabled()); - const auto manual_active = switch_right == Switch::UP; + const auto auto_aim_requested = mouse_->right || switch_right == Switch::UP; const auto should_control = auto_aim_should_control_.ready() && *auto_aim_should_control_; const auto valid_control = auto_aim_control_direction_.ready() && auto_aim_control_direction_->allFinite(); - if (manual_active && should_control && valid_control) { + if (auto_aim_requested && should_control && valid_control) { return two_axis_gimbal_solver.update( TwoAxisGimbalSolver::SetControlDirection( OdomImu::DirectionVector(*auto_aim_control_direction_))); diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp new file mode 100644 index 00000000..9ef80e79 --- /dev/null +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp @@ -0,0 +1,71 @@ +#include +#include + +#include +#include +#include + +#include "referee/app/ui/shape/shape.hpp" +#include "referee/app/ui/widget/crosshair_circle.hpp" +#include "referee/app/ui/widget/status_ring.hpp" + +namespace rmcs_core::referee::app::ui { +using namespace std::chrono_literals; + +class Flight + : public rmcs_executor::Component + , public rclcpp::Node { +public: + Flight() + : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} + , crosshair_circle_(Shape::Color::WHITE, x_center - 2, y_center - 30, 8, 2) + , status_ring_( + 26.5, 26.5, 600, 300, StatusRing::DynamicArcsVisibility{false, false}) + , horizontal_center_guidelines_( + {Shape::Color::WHITE, 2, x_center - 360, y_center, x_center - 110, y_center}, + {Shape::Color::WHITE, 2, x_center + 110, y_center, x_center + 360, y_center}) + , vertical_center_guidelines_( + {Shape::Color::WHITE, 2, x_center, 800, x_center, y_center + 110}, + {Shape::Color::WHITE, 2, x_center, y_center - 110, x_center, 200}) { + + register_input("/referee/shooter/bullet_allowance", robot_bullet_allowance_); + + register_input("/gimbal/left_friction/control_velocity", left_friction_control_velocity_); + register_input("/gimbal/left_friction/velocity", left_friction_velocity_); + register_input("/gimbal/right_friction/velocity", right_friction_velocity_); + + register_input("/remote/mouse", mouse_); + } + + void update() override { + status_ring_.update_bullet_allowance(*robot_bullet_allowance_); + status_ring_.update_friction_wheel_speed( + std::min(*left_friction_velocity_, *right_friction_velocity_), + *left_friction_control_velocity_ > 0); + status_ring_.update_auto_aim_enable(mouse_->right == 1); + } + +private: + static constexpr uint16_t screen_width = 1920, screen_height = 1080; + static constexpr uint16_t x_center = screen_width / 2, y_center = screen_height / 2; + + InputInterface robot_bullet_allowance_; + + InputInterface left_friction_control_velocity_; + InputInterface left_friction_velocity_; + InputInterface right_friction_velocity_; + + InputInterface mouse_; + + CrossHairCircle crosshair_circle_; + StatusRing status_ring_; + + Line horizontal_center_guidelines_[2]; + Line vertical_center_guidelines_[2]; +}; + +} // namespace rmcs_core::referee::app::ui + +#include + +PLUGINLIB_EXPORT_CLASS(rmcs_core::referee::app::ui::Flight, rmcs_executor::Component) diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp index 8af3d993..32d8c614 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp @@ -16,8 +16,20 @@ namespace rmcs_core::referee::app::ui { class StatusRing { public: + struct DynamicArcsVisibility { + bool supercap; + bool battery; + }; + + StatusRing(double supercap_limit, double battery_limit, double friction_limit, int16_t bullet_limit) + : StatusRing( + supercap_limit, battery_limit, friction_limit, bullet_limit, + DynamicArcsVisibility{true, true}) {} + StatusRing( - double supercap_limit, double battery_limit, double friction_limit, int16_t bullet_limit) { + double supercap_limit, double battery_limit, double friction_limit, int16_t bullet_limit, + DynamicArcsVisibility dynamic_arcs_visibility) + : dynamic_arcs_visibility_(dynamic_arcs_visibility) { supercap_status_.set_x(x_center); supercap_status_.set_y(y_center); supercap_status_.set_r(visible_radius - width_ring); @@ -108,12 +120,14 @@ class StatusRing { arc_right_down_.set_visible(true); set_limits(supercap_limit, battery_limit, friction_limit, bullet_limit); + supercap_status_.set_visible(dynamic_arcs_visibility_.supercap); + battery_status_.set_visible(dynamic_arcs_visibility_.battery); } void set_visible(bool value) { // Dynamic - supercap_status_.set_visible(value); - battery_status_.set_visible(value); + supercap_status_.set_visible(value && dynamic_arcs_visibility_.supercap); + battery_status_.set_visible(value && dynamic_arcs_visibility_.battery); friction_wheel_speed_.set_visible(value); bullet_status_.set_visible(value); @@ -246,6 +260,9 @@ class StatusRing { } void update_supercap(double value, bool enable) { + if (!dynamic_arcs_visibility_.supercap) + return; + auto angle = 275 + calculate_angle(value, 10.5, supercap_limit_) + 1; supercap_status_.set_angle_end(static_cast(angle)); @@ -259,6 +276,9 @@ class StatusRing { } void update_battery_power(double value) { + if (!dynamic_arcs_visibility_.battery) + return; + auto angle = 265 - calculate_angle(value, 20, 25.7) - 1; battery_status_.set_angle_start(static_cast(angle)); @@ -353,6 +373,8 @@ class StatusRing { constexpr static uint16_t visible_radius = 400; constexpr static uint16_t visible_angle = 40; + DynamicArcsVisibility dynamic_arcs_visibility_; + double supercap_limit_; double battery_limit_; double friction_limit_; @@ -378,4 +400,4 @@ class StatusRing { Arc bullet_scales_[4]; }; -} // namespace rmcs_core::referee::app::ui \ No newline at end of file +} // namespace rmcs_core::referee::app::ui From af533f1299a5de2d87711073be11c99fb3e923db Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Fri, 22 May 2026 11:02:50 +0800 Subject: [PATCH 17/30] update auto aim shoot logic --- .../src/controller/shooting/bullet_feeder_controller_17mm.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp index 4b148cd7..2b7b0d29 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp @@ -103,8 +103,7 @@ class BulletFeederController17mm if (*friction_ready_) { if (shoot_mode == ShootMode::AUTOMATIC) { bool triggered = mouse.left || switch_left == Switch::DOWN - || (mouse.right && switch_right == Switch::UP - && *auto_aim_should_shoot_); + || (mouse.right && *auto_aim_should_shoot_); bullet_allowance = triggered ? *control_bullet_allowance_limited_by_heat_ : 0; } else { From b05cb5e6b9d0dd2eb4d2c3a3f9c82248e4232145 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Sat, 23 May 2026 16:12:49 +0800 Subject: [PATCH 18/30] feat: add knob-controlled low-frequency firing and remove redundant UI code --- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 4 +- .../bullet_feeder_controller_17mm.cpp | 31 ++++++++-- .../rmcs_core/src/referee/app/ui/flight.cpp | 62 ++++++++++++++++++- .../src/referee/app/ui/shape/shape.hpp | 8 ++- .../src/referee/command/interaction/ui.cpp | 38 +++++++++--- 5 files changed, 123 insertions(+), 20 deletions(-) diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index a42e0dcb..db7bea5b 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -104,8 +104,8 @@ friction_wheel_controller: - /gimbal/left_friction - /gimbal/right_friction friction_velocities: - - 600.0 - - 600.0 + - 620.0 + - 620.0 friction_soft_start_stop_time: 1.0 heat_controller: diff --git a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp index 2b7b0d29..950fcdc7 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp @@ -28,6 +28,9 @@ class BulletFeederController17mm bullet_feeder_working_velocity = bullet_feeder_angle_per_bullet * shot_frequency; double safe_shot_frequency = get_parameter("safe_shot_frequency").as_double(); bullet_feeder_safe_shot_velocity = bullet_feeder_angle_per_bullet * safe_shot_frequency; + constexpr double rotary_knob_shot_frequency = 8.0; + bullet_feeder_rotary_knob_velocity_ = + bullet_feeder_angle_per_bullet * rotary_knob_shot_frequency; double eject_frequency = get_parameter("eject_frequency").as_double(); bullet_feeder_eject_velocity_ = -bullet_feeder_angle_per_bullet * eject_frequency; @@ -52,6 +55,7 @@ class BulletFeederController17mm register_input("/remote/switch/left", switch_left_); register_input("/remote/mouse", mouse_); register_input("/remote/keyboard", keyboard_); + register_input("/remote/rotary_knob_switch", rotary_knob_switch_); register_input("/auto_aim/should_shoot", auto_aim_should_shoot_, false); @@ -74,6 +78,7 @@ class BulletFeederController17mm const auto switch_left = *switch_left_; const auto mouse = *mouse_; const auto keyboard = *keyboard_; + const auto rotary_knob_switch = *rotary_knob_switch_; using namespace rmcs_msgs; if ((switch_left == Switch::UNKNOWN || switch_right == Switch::UNKNOWN) @@ -102,19 +107,29 @@ class BulletFeederController17mm if (*friction_ready_) { if (shoot_mode == ShootMode::AUTOMATIC) { - bool triggered = mouse.left || switch_left == Switch::DOWN - || (mouse.right && *auto_aim_should_shoot_); + bool manual_triggered = mouse.left || switch_left == Switch::DOWN; + bool auto_aim_triggered = mouse.right && *auto_aim_should_shoot_; + bool rotary_knob_triggered = rotary_knob_switch == Switch::DOWN; + bool triggered = + manual_triggered || auto_aim_triggered || rotary_knob_triggered; + bool rotary_knob_low_speed = + rotary_knob_triggered && !manual_triggered && !auto_aim_triggered; bullet_allowance = triggered ? *control_bullet_allowance_limited_by_heat_ : 0; + update_bullet_feeder_velocity(bullet_allowance, rotary_knob_low_speed); } else { bool triggered = single_shot_stop_counter_ > 0; bullet_allowance = triggered && (*control_bullet_allowance_limited_by_heat_ > 0); + update_bullet_feeder_velocity(bullet_allowance, false); } + } else { + update_bullet_feeder_velocity(0, false); } } - update_bullet_feeder_velocity(bullet_allowance); + if (!*friction_ready_ || switch_right == Switch::DOWN) + update_bullet_feeder_velocity(0, false); } last_switch_right_ = switch_right; @@ -130,7 +145,7 @@ class BulletFeederController17mm *bullet_feeder_control_velocity_ = nan_; } - void update_bullet_feeder_velocity(int64_t bullet_allowance) { + void update_bullet_feeder_velocity(int64_t bullet_allowance, bool rotary_knob_low_speed) { if (bullet_allowance <= 0) { bullet_feeder_working_status_ = 0; *bullet_feeder_control_velocity_ = 0.0; @@ -144,8 +159,9 @@ class BulletFeederController17mm return; } - double new_control_velocity = bullet_allowance > 1 ? bullet_feeder_working_velocity - : bullet_feeder_safe_shot_velocity; + double new_control_velocity = rotary_knob_low_speed ? bullet_feeder_rotary_knob_velocity_ + : bullet_allowance > 1 ? bullet_feeder_working_velocity + : bullet_feeder_safe_shot_velocity; if (new_control_velocity > *bullet_feeder_control_velocity_) bullet_feeder_working_status_ = std::min(0, bullet_feeder_working_status_); *bullet_feeder_control_velocity_ = new_control_velocity; @@ -208,6 +224,7 @@ class BulletFeederController17mm InputInterface switch_left_; InputInterface mouse_; InputInterface keyboard_; + InputInterface rotary_knob_switch_; InputInterface auto_aim_should_shoot_; @@ -221,6 +238,8 @@ class BulletFeederController17mm int bullet_feeder_jammed_count_ = 0; int bullet_feeder_cool_down_ = 0; + double bullet_feeder_rotary_knob_velocity_ = 0.0; + int temporary_single_shot_counter_ = 0; OutputInterface shoot_mode_; diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp index 9ef80e79..520f46b9 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp @@ -1,5 +1,8 @@ #include +#include #include +#include +#include #include #include @@ -16,6 +19,9 @@ class Flight : public rmcs_executor::Component , public rclcpp::Node { public: + static constexpr uint8_t kUiModeCombat = 0; + static constexpr uint8_t kUiModeOutpostOnly = 1; + Flight() : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} , crosshair_circle_(Shape::Color::WHITE, x_center - 2, y_center - 30, 8, 2) @@ -26,7 +32,8 @@ class Flight {Shape::Color::WHITE, 2, x_center + 110, y_center, x_center + 360, y_center}) , vertical_center_guidelines_( {Shape::Color::WHITE, 2, x_center, 800, x_center, y_center + 110}, - {Shape::Color::WHITE, 2, x_center, y_center - 110, x_center, 200}) { + {Shape::Color::WHITE, 2, x_center, y_center - 110, x_center, 200}) + , auto_aim_text_(Shape::Color::WHITE, 16, 2, 1320, 60, auto_aim_buffers_[0].data()) { register_input("/referee/shooter/bullet_allowance", robot_bullet_allowance_); @@ -34,7 +41,11 @@ class Flight register_input("/gimbal/left_friction/velocity", left_friction_velocity_); register_input("/gimbal/right_friction/velocity", right_friction_velocity_); + register_input("/auto_aim/ui_mode", auto_aim_mode_, false); + register_input("/remote/mouse", mouse_); + + write_text(auto_aim_buffers_[0], "MODE:COMBAT"); } void update() override { @@ -43,11 +54,53 @@ class Flight std::min(*left_friction_velocity_, *right_friction_velocity_), *left_friction_control_velocity_ > 0); status_ring_.update_auto_aim_enable(mouse_->right == 1); + + update_auto_aim_text(); } private: static constexpr uint16_t screen_width = 1920, screen_height = 1080; static constexpr uint16_t x_center = screen_width / 2, y_center = screen_height / 2; + static constexpr std::size_t text_capacity = 31; + + static auto to_mode_string(uint8_t mode) -> const char* { + switch (mode) { + case kUiModeCombat: return "COMBAT"; + case kUiModeOutpostOnly: return "OUTPOST"; + default: return "UNKNOWN"; + } + } + + static auto write_text( + std::array& buffer, const char* format, const char* mode_value) + -> void { + std::snprintf(buffer.data(), buffer.size(), format, mode_value); + } + + static auto write_text(std::array& buffer, const char* value) -> void { + std::snprintf(buffer.data(), buffer.size(), "%s", value); + } + + auto update_text_shape(Text& text, std::array (&buffers)[2], + uint8_t& active_buffer, const char* format, const char* mode_value) -> void { + auto next_buffer = static_cast(1 - active_buffer); + write_text(buffers[next_buffer], format, mode_value); + if (std::string_view { buffers[next_buffer].data() } + == std::string_view { buffers[active_buffer].data() }) { + return; + } + + active_buffer = next_buffer; + text.set_value(buffers[active_buffer].data()); + } + + auto update_auto_aim_text() -> void { + auto mode_value = auto_aim_mode_.ready() ? *auto_aim_mode_ : kUiModeCombat; + + update_text_shape( + auto_aim_text_, auto_aim_buffers_, active_auto_aim_buffer_, "MODE:%s", + to_mode_string(mode_value)); + } InputInterface robot_bullet_allowance_; @@ -55,6 +108,8 @@ class Flight InputInterface left_friction_velocity_; InputInterface right_friction_velocity_; + InputInterface auto_aim_mode_; + InputInterface mouse_; CrossHairCircle crosshair_circle_; @@ -62,6 +117,11 @@ class Flight Line horizontal_center_guidelines_[2]; Line vertical_center_guidelines_[2]; + + std::array auto_aim_buffers_[2] {}; + uint8_t active_auto_aim_buffer_ { 0 }; + + Text auto_aim_text_; }; } // namespace rmcs_core::referee::app::ui diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp index 37be26ae..ea064f50 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp @@ -192,6 +192,8 @@ class Shape enter_run_queue(); } + void set_text_shape() { is_text_shape_ = true; } + virtual size_t write_description_field(std::byte* buffer) = 0; DescriptionField::Part2 part2_ alignas(4); @@ -722,8 +724,10 @@ class Float : public Integer { class Text : public Shape { public: - Text() - : Shape(true) {} + Text() { + value_ = nullptr; + set_text_shape(); + }; Text( Color color, uint16_t font_size, uint16_t width, uint16_t x, uint16_t y, const char* value, bool visible = true) diff --git a/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp b/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp index cea7953c..4d57f606 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp @@ -87,6 +87,10 @@ class Ui } size_t write_updating_field(std::byte* buffer) const { + if (auto written = write_updating_text_field(buffer); written != 0) { + return written; + } + size_t written = 0; auto& header = *new (buffer + written) Header{}; @@ -98,15 +102,9 @@ class Ui int slot = 0; intptr_t updated[7]; for (auto it = CfsScheduler::get_update_iterator(); it && slot < 7;) { - // Ignore text shape unless it is the first. if (it->is_text_shape()) { - if (slot == 0) { - header.command_id = 0x0110; // Draw text shape - return written + it.update().write(buffer + written); - } else { - it.ignore(); - continue; - } + it.ignore(); + continue; } auto operation = it->predict_update(); @@ -148,6 +146,28 @@ class Ui return written; } + size_t write_updating_text_field(std::byte* buffer) const { + size_t written = 0; + + auto& header = *new (buffer + written) Header{}; + auto full_robot_id = rmcs_msgs::FullRobotId { *robot_id_ }; + header.command_id = 0x0110; // Draw text shape + header.sender_id = full_robot_id; + header.receiver_id = full_robot_id.client(); + written += sizeof(Header); + + for (auto it = CfsScheduler::get_update_iterator(); it;) { + if (!it->is_text_shape()) { + it.ignore(); + continue; + } + + return written + it.update().write(buffer + written); + } + + return 0; + } + InputInterface robot_id_; InputInterface game_stage_; @@ -165,4 +185,4 @@ class Ui #include -PLUGINLIB_EXPORT_CLASS(rmcs_core::referee::command::interaction::Ui, rmcs_executor::Component) \ No newline at end of file +PLUGINLIB_EXPORT_CLASS(rmcs_core::referee::command::interaction::Ui, rmcs_executor::Component) From cfc7bd7d1e1c889ad0935a905b1c562ea6b1238c Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Sat, 23 May 2026 21:32:20 +0800 Subject: [PATCH 19/30] refactor(ui):update flight ui, add mode line --- .../rmcs_core/src/referee/app/ui/flight.cpp | 65 ++++--------------- 1 file changed, 11 insertions(+), 54 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp index 520f46b9..12219d38 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp @@ -1,8 +1,5 @@ #include -#include #include -#include -#include #include #include @@ -13,27 +10,26 @@ #include "referee/app/ui/widget/status_ring.hpp" namespace rmcs_core::referee::app::ui { -using namespace std::chrono_literals; - class Flight : public rmcs_executor::Component , public rclcpp::Node { public: - static constexpr uint8_t kUiModeCombat = 0; + static constexpr uint8_t kUiModeCombat = 0; static constexpr uint8_t kUiModeOutpostOnly = 1; Flight() : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} , crosshair_circle_(Shape::Color::WHITE, x_center - 2, y_center - 30, 8, 2) - , status_ring_( - 26.5, 26.5, 600, 300, StatusRing::DynamicArcsVisibility{false, false}) + , status_ring_(26.5, 26.5, 600, 300, StatusRing::DynamicArcsVisibility{false, false}) , horizontal_center_guidelines_( {Shape::Color::WHITE, 2, x_center - 360, y_center, x_center - 110, y_center}, {Shape::Color::WHITE, 2, x_center + 110, y_center, x_center + 360, y_center}) , vertical_center_guidelines_( {Shape::Color::WHITE, 2, x_center, 800, x_center, y_center + 110}, {Shape::Color::WHITE, 2, x_center, y_center - 110, x_center, 200}) - , auto_aim_text_(Shape::Color::WHITE, 16, 2, 1320, 60, auto_aim_buffers_[0].data()) { + , mode_indicator_( + Shape::Color::YELLOW, 30, x_center + 360, y_center + 220, x_center + 400, + y_center + 220) { register_input("/referee/shooter/bullet_allowance", robot_bullet_allowance_); @@ -44,8 +40,6 @@ class Flight register_input("/auto_aim/ui_mode", auto_aim_mode_, false); register_input("/remote/mouse", mouse_); - - write_text(auto_aim_buffers_[0], "MODE:COMBAT"); } void update() override { @@ -55,51 +49,17 @@ class Flight *left_friction_control_velocity_ > 0); status_ring_.update_auto_aim_enable(mouse_->right == 1); - update_auto_aim_text(); + update_mode_indicator(); } private: static constexpr uint16_t screen_width = 1920, screen_height = 1080; static constexpr uint16_t x_center = screen_width / 2, y_center = screen_height / 2; - static constexpr std::size_t text_capacity = 31; - - static auto to_mode_string(uint8_t mode) -> const char* { - switch (mode) { - case kUiModeCombat: return "COMBAT"; - case kUiModeOutpostOnly: return "OUTPOST"; - default: return "UNKNOWN"; - } - } - static auto write_text( - std::array& buffer, const char* format, const char* mode_value) - -> void { - std::snprintf(buffer.data(), buffer.size(), format, mode_value); - } - - static auto write_text(std::array& buffer, const char* value) -> void { - std::snprintf(buffer.data(), buffer.size(), "%s", value); - } - - auto update_text_shape(Text& text, std::array (&buffers)[2], - uint8_t& active_buffer, const char* format, const char* mode_value) -> void { - auto next_buffer = static_cast(1 - active_buffer); - write_text(buffers[next_buffer], format, mode_value); - if (std::string_view { buffers[next_buffer].data() } - == std::string_view { buffers[active_buffer].data() }) { - return; - } - - active_buffer = next_buffer; - text.set_value(buffers[active_buffer].data()); - } - - auto update_auto_aim_text() -> void { - auto mode_value = auto_aim_mode_.ready() ? *auto_aim_mode_ : kUiModeCombat; - - update_text_shape( - auto_aim_text_, auto_aim_buffers_, active_auto_aim_buffer_, "MODE:%s", - to_mode_string(mode_value)); + auto update_mode_indicator() -> void { + auto mode_value = auto_aim_mode_.ready() ? *auto_aim_mode_ : kUiModeCombat; + mode_indicator_.set_color( + mode_value == kUiModeOutpostOnly ? Shape::Color::GREEN : Shape::Color::YELLOW); } InputInterface robot_bullet_allowance_; @@ -118,10 +78,7 @@ class Flight Line horizontal_center_guidelines_[2]; Line vertical_center_guidelines_[2]; - std::array auto_aim_buffers_[2] {}; - uint8_t active_auto_aim_buffer_ { 0 }; - - Text auto_aim_text_; + Line mode_indicator_; }; } // namespace rmcs_core::referee::app::ui From 6b689f4b98ffc2941102b673fcd4d18b9c461547 Mon Sep 17 00:00:00 2001 From: heyeuu <2829004293@qq.com> Date: Tue, 2 Jun 2026 17:22:34 +0800 Subject: [PATCH 20/30] feat: add engineer UI mode for flight --- rmcs_ws/src/rmcs_auto_aim_v2 | 2 +- .../src/rmcs_core/src/referee/app/ui/flight.cpp | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/rmcs_ws/src/rmcs_auto_aim_v2 b/rmcs_ws/src/rmcs_auto_aim_v2 index 8c16a237..f3bae295 160000 --- a/rmcs_ws/src/rmcs_auto_aim_v2 +++ b/rmcs_ws/src/rmcs_auto_aim_v2 @@ -1 +1 @@ -Subproject commit 8c16a23745ed4c880f0823f90d37d5fd2362c015 +Subproject commit f3bae2952106975478809f6b21fabf7dc36f2668 diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp index 12219d38..b9bbd968 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp @@ -16,6 +16,7 @@ class Flight public: static constexpr uint8_t kUiModeCombat = 0; static constexpr uint8_t kUiModeOutpostOnly = 1; + static constexpr uint8_t kUiModeEngineer = 2; Flight() : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} @@ -58,8 +59,19 @@ class Flight auto update_mode_indicator() -> void { auto mode_value = auto_aim_mode_.ready() ? *auto_aim_mode_ : kUiModeCombat; - mode_indicator_.set_color( - mode_value == kUiModeOutpostOnly ? Shape::Color::GREEN : Shape::Color::YELLOW); + + switch (mode_value) { + case kUiModeOutpostOnly: + mode_indicator_.set_color(Shape::Color::GREEN); + break; + case kUiModeEngineer: + mode_indicator_.set_color(Shape::Color::PINK); + break; + case kUiModeCombat: + default: + mode_indicator_.set_color(Shape::Color::YELLOW); + break; + } } InputInterface robot_bullet_allowance_; From 63c79e81c70d2c68dcf471b4e7bab48a564e9017 Mon Sep 17 00:00:00 2001 From: noskillzheng <3515964992@qq.com> Date: Thu, 18 Jun 2026 17:41:24 +0800 Subject: [PATCH 21/30] feat: 1.add yaw limit 2.permit testing feeder without fricition wheel; fix:reverse the feeder's rotation direction --- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 4 +- .../gimbal/simple_gimbal_controller.cpp | 8 ++++ .../gimbal/two_axis_gimbal_solver.hpp | 38 +++++++++++++++++++ .../bullet_feeder_controller_17mm.cpp | 14 ++++++- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 1 - 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index db7bea5b..aaadd145 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -71,7 +71,8 @@ gimbal_controller: ros__parameters: upper_limit: -0.39518 # -0.39518 rad ≈ -22.6° lower_limit: 0.7 # 0.7 rad ≈ 40.1° - # TODO: yaw limite + yaw_lower_limit: 0.1745 + yaw_upper_limit: 2.5708 yaw_angle_pid_controller: ros__parameters: @@ -115,6 +116,7 @@ heat_controller: bullet_feeder_controller: ros__parameters: + debug_ignore_friction_ready: true # 调试用:不开摩擦轮也允许拨弹,复原时改为 false bullets_per_feeder_turn: 8.0 shot_frequency: 25.0 safe_shot_frequency: 10.0 diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp index 7873188b..0857c178 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp @@ -35,11 +35,19 @@ class SimpleGimbalController register_output("/gimbal/yaw/control_angle_error", yaw_angle_error_, nan_); register_output("/gimbal/pitch/control_angle_error", pitch_angle_error_, nan_); + + rclcpp::Parameter yaw_upper, yaw_lower; + if (get_parameter("yaw_upper_limit", yaw_upper) + && get_parameter("yaw_lower_limit", yaw_lower)) { + two_axis_gimbal_solver.enable_yaw_limit( + *this, yaw_upper.as_double(), yaw_lower.as_double()); + } } void update() override { auto angle_error = calculate_angle_error(); *yaw_angle_error_ = angle_error.yaw_angle_error; + *pitch_angle_error_ = angle_error.pitch_angle_error; } diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp index c1fc772f..711abb21 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp @@ -1,7 +1,10 @@ #pragma once +#include #include #include +#include +#include #include #include @@ -32,6 +35,13 @@ class TwoAxisGimbalSolver { component.register_input("/tf", tf_); } + void enable_yaw_limit( + rmcs_executor::Component& component, double yaw_upper_limit, double yaw_lower_limit) { + yaw_cw_max_ = yaw_upper_limit; + yaw_cw_min_ = yaw_lower_limit; + component.register_input("/gimbal/yaw/angle", gimbal_yaw_angle_); + } + class SetDisabled : public Operation { PitchLink::DirectionVector update(TwoAxisGimbalSolver& super) const override { super.control_enabled_ = false; @@ -113,6 +123,8 @@ class TwoAxisGimbalSolver { if (!control_enabled_) return {nan_, nan_}; + clamp_yaw_limit(control_direction_yaw_link); + control_direction_ = fast_tf::cast(yaw_link_to_pitch_link(control_direction_yaw_link, pitch), *tf_); return calculate_control_errors(control_direction_yaw_link, pitch); @@ -188,6 +200,29 @@ class TwoAxisGimbalSolver { *control_direction << lower_limit_.x() * projection, lower_limit_.y(); } + void clamp_yaw_limit(YawLink::DirectionVector& control_direction) { + if (!yaw_cw_min_.has_value()) + return; + + constexpr double two_pi = 2 * std::numbers::pi; + double cw = std::fmod(two_pi - *gimbal_yaw_angle_, two_pi); + if (cw < 0) + cw += two_pi; + + const auto& [x, y, z] = *control_direction; + const double err = std::atan2(y, x); + + const double target_cw = cw - err; + const double clamped_cw = std::clamp(target_cw, *yaw_cw_min_, *yaw_cw_max_); + if (clamped_cw == target_cw) + return; + + // delta = err_new - err = (cw - clamped_cw) - err + const double delta = (cw - clamped_cw) - err; + const double c = std::cos(delta), s = std::sin(delta); + *control_direction << c * x - s * y, s * x + c * y, z; + } + static AngleError calculate_control_errors( const YawLink::DirectionVector& control_direction, const Eigen::Vector2d& pitch) { const auto& [x, y, z] = *control_direction; @@ -209,6 +244,9 @@ class TwoAxisGimbalSolver { rmcs_executor::Component::InputInterface gimbal_pitch_angle_; rmcs_executor::Component::InputInterface tf_; + std::optional yaw_cw_min_, yaw_cw_max_; + rmcs_executor::Component::InputInterface gimbal_yaw_angle_; + OdomImu::DirectionVector yaw_axis_filtered_{Eigen::Vector3d::UnitZ()}; bool control_enabled_ = false; diff --git a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp index 950fcdc7..69640700 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp @@ -45,6 +45,12 @@ class BulletFeederController17mm single_shot_max_stop_delay_ = static_cast( std::round(1000.0 * get_parameter("single_shot_max_stop_delay").as_double())); + // Debug option: allow bullet feeding without friction wheels spinning. + debug_ignore_friction_ready_ = get_parameter_or("debug_ignore_friction_ready", false); + if (debug_ignore_friction_ready_) + RCLCPP_WARN( + logger_, "Friction-ready check bypassed: feeder will spin without friction wheels!"); + register_input("/gimbal/friction_ready", friction_ready_); register_input("/gimbal/bullet_fired", bullet_fired_); register_input( @@ -105,7 +111,8 @@ class BulletFeederController17mm if (*bullet_fired_) single_shot_stop_counter_ = 0; - if (*friction_ready_) { + const bool friction_ready = *friction_ready_ || debug_ignore_friction_ready_; + if (friction_ready) { if (shoot_mode == ShootMode::AUTOMATIC) { bool manual_triggered = mouse.left || switch_left == Switch::DOWN; bool auto_aim_triggered = mouse.right && *auto_aim_should_shoot_; @@ -128,7 +135,8 @@ class BulletFeederController17mm } } - if (!*friction_ready_ || switch_right == Switch::DOWN) + if ((!*friction_ready_ && !debug_ignore_friction_ready_) + || switch_right == Switch::DOWN) update_bullet_feeder_velocity(0, false); } @@ -216,6 +224,8 @@ class BulletFeederController17mm int single_shot_max_stop_delay_, single_shot_stop_counter_ = 0; + bool debug_ignore_friction_ready_ = false; + InputInterface friction_ready_; InputInterface bullet_fired_; InputInterface control_bullet_allowance_limited_by_heat_; diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index bfbedabb..58b8c5fe 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -62,7 +62,6 @@ class Flight device::DjiMotor::Config{device::DjiMotor::Type::kM3508}.set_reduction_ratio(1.0)); gimbal_bullet_feeder_.configure( device::DjiMotor::Config{device::DjiMotor::Type::kM2006} - .set_reversed() .enable_multi_turn_angle()); register_output("/gimbal/yaw/velocity_imu", gimbal_yaw_velocity_imu_); From 6a1a42f2167edb77443d54088523d83feda68f72 Mon Sep 17 00:00:00 2001 From: Zihan Qin Date: Tue, 9 Jun 2026 22:20:27 +0800 Subject: [PATCH 22/30] feat: Integrate steering-hero support (#80) Add support for steering-hero and steering-hero-little, including hardware drivers, chassis control, gimbal control, shooting control, Hero UI integration, corresponding bringup configs, and plugin registration. Also correct LK motor torque constants: - kMG5010Ei10: 0.90909 -> 0.1 - kMG6012Ei8: 1.09 -> 1.09 / 8.0 To keep mainline vehicle control output unchanged, also retune: - omni-infantry yaw velocity PID parameters - sentry bottom yaw velocity PID / viscous FF parameters Also remove the unmaintained mecanum-hero config. Known issues (not blocking this merge): - The Hero UI shooter condition / state_word path is still leftover debug wiring and is not connected to the current active runtime path - HeroFrictionWheelController still preserves the historical friction-wheel index convention; for now this is only documented with a TODO and should later be replaced by an explicit first-stage mapping - steering-hero-little still has a mismatch between PlayerViewer limit parameters and control logic, which requires follow-up calibration - HeroChassisPowerController inherits the existing ChassisPowerController risk of reading uninitialized members / propagating non-finite values; this is a pre-existing shared issue, not newly introduced by this merge - steering-hero-little uses different vehicle_radius values in steering_wheel_status and steering_wheel_controller - HeroFrictionWheelController does not clear its jam fault counter after recovery, and Ctrl+F currently triggers a double profile toggle - PutterController does not reset putter_timeout_count_ during normal stage transitions - ChassisClimberController repeatedly resets back_climber_recover_count during auto-climb - The Hero UI Ctrl+E bottom-yaw tracking toggle is currently level-triggered, so holding the keys causes repeated flipping Co-authored-by: floatpigeon Co-authored-by: dwx5 <1591215786@qq.com> Co-authored-by: zhzy-star <2807406212@qq.com> --- rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp index ea064f50..1ceae35e 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp @@ -724,10 +724,8 @@ class Float : public Integer { class Text : public Shape { public: - Text() { - value_ = nullptr; - set_text_shape(); - }; + Text() + : Shape(true) {} Text( Color color, uint16_t font_size, uint16_t width, uint16_t x, uint16_t y, const char* value, bool visible = true) From fa868402a21b87e7fe1b6727d34cfca2650a465d Mon Sep 17 00:00:00 2001 From: noskillzheng <3515964992@qq.com> Date: Sun, 5 Jul 2026 08:03:14 +0800 Subject: [PATCH 23/30] fix:migrate can data transmit and receive from Cboard to rmcsboardlite --- rmcs_ws/src/rmcs_auto_aim_v2 | 2 +- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 2 +- .../src/rmcs_bringup/launch/rmcs.launch.py | 7 -- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 71 +++++++++++++------ .../rmcs_core/src/hardware/omni_infantry.cpp | 2 +- 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/rmcs_ws/src/rmcs_auto_aim_v2 b/rmcs_ws/src/rmcs_auto_aim_v2 index f3bae295..02a130b7 160000 --- a/rmcs_ws/src/rmcs_auto_aim_v2 +++ b/rmcs_ws/src/rmcs_auto_aim_v2 @@ -1 +1 @@ -Subproject commit f3bae2952106975478809f6b21fabf7dc36f2668 +Subproject commit 02a130b74692922ea76e6c81ea67f4877ae5434d diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index aaadd145..04235226 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -59,7 +59,7 @@ tf_broadcaster: flight_hardware: ros__parameters: - board_serial: "d4-9d44" + board_serial: "AF-7C58-5458-E731-9F74-1F9C-CAFD-30AF-9C09" yaw_motor_zero_point: 11720 pitch_motor_zero_point: 18578 diff --git a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py index adcafe2a..19fde5f1 100644 --- a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py +++ b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py @@ -59,13 +59,6 @@ def visit( emulate_tty=True, ) ) - entities.append( - IncludeLaunchDescription( - PythonLaunchDescriptionSource([ - FindPackageShare('rmcs_auto_aim_v2'), '/launch.py' - ]) - ) - ) return entities diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index 58b8c5fe..db13fa76 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -20,21 +19,23 @@ #include #include "hardware/device/bmi088.hpp" + #include "hardware/device/can_packet.hpp" #include "hardware/device/dji_motor.hpp" #include "hardware/device/dr16.hpp" #include "hardware/device/lk_motor.hpp" +#include "librmcs/agent/rmcs_board_lite.hpp" namespace rmcs_core::hardware { class Flight : public rmcs_executor::Component , public rclcpp::Node - , private librmcs::agent::CBoard { + , private librmcs::agent::RmcsBoardLite { public: Flight() : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} - , librmcs::agent::CBoard{get_parameter("board_serial").as_string()} + , librmcs::agent::RmcsBoardLite{get_parameter("board_serial").as_string()} , logger_(get_logger()) , command_component_( create_partner_component(get_component_name() + "_command", *this)) @@ -69,7 +70,7 @@ class Flight register_output("/tf", tf_); bmi088_.set_coordinate_mapping( - [](double x, double y, double z) { return std::make_tuple(-x, z, y); }); + [](double x, double y, double z) { return std::make_tuple(y, z, x); }); using namespace rmcs_description; // NOLINT(google-build-using-namespace) constexpr double rotor_distance_x = 1.128; @@ -105,7 +106,7 @@ class Flight [&buffer](std::byte byte) noexcept { *buffer++ = byte; }, size); }; referee_serial_->write = [this](const std::byte* buffer, size_t size) { - start_transmit().uart2_transmit( + start_transmit().uart1_transmit( {.uart_data = std::span{buffer, size}}); return size; }; @@ -127,20 +128,32 @@ class Flight void command_update() { auto builder = start_transmit(); builder - .can2_transmit( - {.can_id = 0x141, - .can_data = gimbal_yaw_motor_.generate_torque_command().as_bytes()}) - .can2_transmit( - {.can_id = 0x142, .can_data = gimbal_pitch_motor_.generate_command().as_bytes()}) + .can0_transmit( + {.can_id = 0x200, + .can_data = + device::CanPacket8{ + device::CanPacket8::PaddingQuarter{}, + device::CanPacket8::PaddingQuarter{}, + gimbal_left_friction_.generate_command(), + gimbal_right_friction_.generate_command(), + } + .as_bytes()}) .can1_transmit( {.can_id = 0x200, .can_data = device::CanPacket8{ gimbal_bullet_feeder_.generate_command(), device::CanPacket8::PaddingQuarter{}, - gimbal_left_friction_.generate_command(), - gimbal_right_friction_.generate_command()} - .as_bytes()}); + device::CanPacket8::PaddingQuarter{}, + device::CanPacket8::PaddingQuarter{}, + } + .as_bytes()}) + .can2_transmit( + {.can_id = 0x141, + .can_data = gimbal_yaw_motor_.generate_torque_command().as_bytes()}) + .can3_transmit( + {.can_id = 0x142, .can_data = gimbal_pitch_motor_.generate_command().as_bytes()}); + } private: @@ -188,33 +201,47 @@ class Flight }; protected: - void can1_receive_callback(const librmcs::data::CanDataView& data) override { + void can0_receive_callback(const librmcs::data::CanDataView& data) override { if (data.is_extended_can_id || data.is_remote_transmission || data.can_data.size() < 8) [[unlikely]] return; - if (data.can_id == 0x201) { - gimbal_bullet_feeder_.store_status(data.can_data); - } else if (data.can_id == 0x203) { + if (data.can_id == 0x203) { gimbal_left_friction_.store_status(data.can_data); - } else if (data.can_id == 0x204) { + }else if(data.can_id == 0x204) { gimbal_right_friction_.store_status(data.can_data); } } + void can1_receive_callback(const librmcs::data::CanDataView& data) override { + if (data.is_extended_can_id || data.is_remote_transmission || data.can_data.size() < 8) + [[unlikely]] + return; + + if (data.can_id == 0x201) { + gimbal_bullet_feeder_.store_status(data.can_data); + } + } void can2_receive_callback(const librmcs::data::CanDataView& data) override { if (data.is_extended_can_id || data.is_remote_transmission || data.can_data.size() < 8) [[unlikely]] return; - if (data.can_id == 0x142) - gimbal_pitch_motor_.store_status(data.can_data); - else if (data.can_id == 0x141) { + if (data.can_id == 0x141){ gimbal_yaw_motor_.store_status(data.can_data); } } + void can3_receive_callback(const librmcs::data::CanDataView& data) override { + if (data.is_extended_can_id || data.is_remote_transmission || data.can_data.size() < 8) + [[unlikely]] + return; + + if (data.can_id == 0x142){ + gimbal_pitch_motor_.store_status(data.can_data); + } + } - void uart2_receive_callback(const librmcs::data::UartDataView& data) override { + void uart1_receive_callback(const librmcs::data::UartDataView& data) override { const std::byte* ptr = data.uart_data.data(); referee_ring_buffer_receive_.emplace_back_n( [&ptr](std::byte* storage) noexcept { new (storage) std::byte{*ptr++}; }, diff --git a/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp b/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp index 84b72077..472b05a3 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp @@ -249,7 +249,7 @@ class OmniInfantry motor.store_status(data.can_data); } else if (can_id == 0x202) { auto& motor = chassis_wheel_motors_[1]; - motor.store_status(data.can_data); + motor.store_status(data.can_data); } else if (can_id == 0x203) { auto& motor = chassis_wheel_motors_[2]; motor.store_status(data.can_data); From bd36817527f49e984678a9e8d8265c54401c2136 Mon Sep 17 00:00:00 2001 From: creeper5820 Date: Sun, 5 Jul 2026 19:42:35 +0800 Subject: [PATCH 24/30] wip: Adapt autoaim v2 --- .gitmodules | 6 ++-- rmcs_ws/src/rmcs_auto_aim_v2 | 2 +- rmcs_ws/src/rmcs_bringup/config/flight.yaml | 18 +++++----- .../src/rmcs_bringup/launch/rmcs.launch.py | 16 ++++----- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 35 +++++++++++++------ 5 files changed, 46 insertions(+), 31 deletions(-) diff --git a/.gitmodules b/.gitmodules index acf743ec..b7cf4791 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,10 +3,10 @@ url = https://github.com/qzhhhi/FastTF.git [submodule "rmcs_ws/src/odin_ros_driver"] path = rmcs_ws/src/odin_ros_driver - url = git@github.com:Alliance-Algorithm/odin_ros_driver.git + url = https://github.com/Alliance-Algorithm/odin_ros_driver.git [submodule "rmcs_ws/src/hikcamera"] path = rmcs_ws/src/hikcamera - url = git@github.com:Alliance-Algorithm/ros2-hikcamera.git + url = https://github.com/Alliance-Algorithm/ros2-hikcamera.git [submodule "rmcs_ws/src/rmcs_auto_aim_v2"] path = rmcs_ws/src/rmcs_auto_aim_v2 - url = git@github.com:Alliance-Algorithm/rmcs_auto_aim_v2.git + url = https://github.com/Alliance-Algorithm/rmcs_auto_aim_v2.git diff --git a/rmcs_ws/src/rmcs_auto_aim_v2 b/rmcs_ws/src/rmcs_auto_aim_v2 index 02a130b7..c2da258f 160000 --- a/rmcs_ws/src/rmcs_auto_aim_v2 +++ b/rmcs_ws/src/rmcs_auto_aim_v2 @@ -1 +1 @@ -Subproject commit 02a130b74692922ea76e6c81ea67f4877ae5434d +Subproject commit c2da258f531e927c3a1f22dd3d2861674bc14e6f diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index 04235226..3d9675f8 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -3,7 +3,7 @@ rmcs_executor: update_rate: 1000.0 components: - rmcs_core::hardware::Flight -> flight_hardware - + - rmcs_core::controller::gimbal::SimpleGimbalController -> gimbal_controller - rmcs_core::controller::pid::ErrorPidController -> yaw_angle_pid_controller - rmcs_core::controller::pid::PidController -> yaw_velocity_pid_controller @@ -22,10 +22,10 @@ rmcs_executor: - rmcs_core::referee::command::interaction::Ui -> referee_ui - rmcs_core::referee::app::ui::Flight -> referee_ui_flight - - rmcs_core::broadcaster::ValueBroadcaster -> value_broadcaster - - rmcs_core::broadcaster::TfBroadcaster -> tf_broadcaster + # - rmcs_core::broadcaster::ValueBroadcaster -> value_broadcaster + # - rmcs_core::broadcaster::TfBroadcaster -> tf_broadcaster - - rmcs::AutoAimComponent -> auto_aim_component + - rmcs::AutoAimComponent odin_ros_driver: ros__parameters: @@ -69,10 +69,10 @@ referee_status: gimbal_controller: ros__parameters: - upper_limit: -0.39518 # -0.39518 rad ≈ -22.6° - lower_limit: 0.7 # 0.7 rad ≈ 40.1° - yaw_lower_limit: 0.1745 - yaw_upper_limit: 2.5708 + upper_limit: -0.39518 # -0.39518 rad ≈ -22.6° + lower_limit: 0.7 # 0.7 rad ≈ 40.1° + yaw_lower_limit: 0.1745 + yaw_upper_limit: 2.5708 yaw_angle_pid_controller: ros__parameters: @@ -116,7 +116,7 @@ heat_controller: bullet_feeder_controller: ros__parameters: - debug_ignore_friction_ready: true # 调试用:不开摩擦轮也允许拨弹,复原时改为 false + debug_ignore_friction_ready: true # 调试用:不开摩擦轮也允许拨弹,复原时改为 false bullets_per_feeder_turn: 8.0 shot_frequency: 25.0 safe_shot_frequency: 10.0 diff --git a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py index 19fde5f1..bc23a13b 100644 --- a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py +++ b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py @@ -51,14 +51,14 @@ def visit( if is_automatic: pass - entities.append( - Node( - package="odin_ros_driver", - executable="tmux-launch.sh", - output="screen", - emulate_tty=True, - ) - ) + # entities.append( + # Node( + # package="odin_ros_driver", + # executable="tmux-launch.sh", + # output="screen", + # emulate_tty=True, + # ) + # ) return entities diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index db13fa76..a8eb2d13 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -34,7 +34,9 @@ class Flight , private librmcs::agent::RmcsBoardLite { public: Flight() - : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} + : Node{ + get_component_name(), + rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} , librmcs::agent::RmcsBoardLite{get_parameter("board_serial").as_string()} , logger_(get_logger()) , command_component_( @@ -62,13 +64,15 @@ class Flight gimbal_right_friction_.configure( device::DjiMotor::Config{device::DjiMotor::Type::kM3508}.set_reduction_ratio(1.0)); gimbal_bullet_feeder_.configure( - device::DjiMotor::Config{device::DjiMotor::Type::kM2006} - .enable_multi_turn_angle()); + device::DjiMotor::Config{device::DjiMotor::Type::kM2006}.enable_multi_turn_angle()); register_output("/gimbal/yaw/velocity_imu", gimbal_yaw_velocity_imu_); register_output("/gimbal/pitch/velocity_imu", gimbal_pitch_velocity_imu_); register_output("/tf", tf_); + register_output("/auto_aim/camera_transform", camera_transform_); + register_output("/auto_aim/barrel_direction", barrel_direction_); + bmi088_.set_coordinate_mapping( [](double x, double y, double z) { return std::make_tuple(y, z, x); }); @@ -123,6 +127,15 @@ class Flight update_motors(); update_imu(); dr16_.update_status(); + + // 从 TF 树中查询相机位姿 + *camera_transform_ = + fast_tf::lookup_transform( + *tf_); + + // 从 TF 树中查询枪口方向 + *barrel_direction_ = *fast_tf::cast( + rmcs_description::PitchLink::DirectionVector{Eigen::Vector3d::UnitX()}, *tf_); } void command_update() { @@ -136,7 +149,7 @@ class Flight device::CanPacket8::PaddingQuarter{}, gimbal_left_friction_.generate_command(), gimbal_right_friction_.generate_command(), - } + } .as_bytes()}) .can1_transmit( {.can_id = 0x200, @@ -146,14 +159,13 @@ class Flight device::CanPacket8::PaddingQuarter{}, device::CanPacket8::PaddingQuarter{}, device::CanPacket8::PaddingQuarter{}, - } + } .as_bytes()}) .can2_transmit( {.can_id = 0x141, .can_data = gimbal_yaw_motor_.generate_torque_command().as_bytes()}) .can3_transmit( {.can_id = 0x142, .can_data = gimbal_pitch_motor_.generate_command().as_bytes()}); - } private: @@ -208,7 +220,7 @@ class Flight if (data.can_id == 0x203) { gimbal_left_friction_.store_status(data.can_data); - }else if(data.can_id == 0x204) { + } else if (data.can_id == 0x204) { gimbal_right_friction_.store_status(data.can_data); } } @@ -219,7 +231,7 @@ class Flight if (data.can_id == 0x201) { gimbal_bullet_feeder_.store_status(data.can_data); - } + } } void can2_receive_callback(const librmcs::data::CanDataView& data) override { @@ -227,7 +239,7 @@ class Flight [[unlikely]] return; - if (data.can_id == 0x141){ + if (data.can_id == 0x141) { gimbal_yaw_motor_.store_status(data.can_data); } } @@ -236,7 +248,7 @@ class Flight [[unlikely]] return; - if (data.can_id == 0x142){ + if (data.can_id == 0x142) { gimbal_pitch_motor_.store_status(data.can_data); } } @@ -279,6 +291,9 @@ class Flight OutputInterface tf_; OutputInterface referee_serial_; + OutputInterface camera_transform_; + OutputInterface barrel_direction_; + rmcs_utility::RingBuffer referee_ring_buffer_receive_{256}; }; From 77492f1ec90bb66af3ded5f0df0b3d873891e6f0 Mon Sep 17 00:00:00 2001 From: creeper5820 Date: Sun, 5 Jul 2026 20:11:19 +0800 Subject: [PATCH 25/30] wip: remove unused transform and clean up code --- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 68 +++++++------------ 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index a8eb2d13..36bc1417 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -6,11 +6,7 @@ #include #include -#include -#include #include -#include -#include #include #include #include @@ -19,7 +15,6 @@ #include #include "hardware/device/bmi088.hpp" - #include "hardware/device/can_packet.hpp" #include "hardware/device/dji_motor.hpp" #include "hardware/device/dr16.hpp" @@ -74,30 +69,7 @@ class Flight register_output("/auto_aim/barrel_direction", barrel_direction_); bmi088_.set_coordinate_mapping( - [](double x, double y, double z) { return std::make_tuple(y, z, x); }); - - using namespace rmcs_description; // NOLINT(google-build-using-namespace) - constexpr double rotor_distance_x = 1.128; - constexpr double rotor_distance_y = 1.128; - - tf_->set_transform( - Eigen::Translation3d{rotor_distance_x / 2, rotor_distance_y / 2, 0}); - tf_->set_transform( - Eigen::Translation3d{rotor_distance_x / 2, -rotor_distance_y / 2, 0}); - tf_->set_transform( - Eigen::Translation3d{-rotor_distance_x / 2, rotor_distance_y / 2, 0}); - tf_->set_transform( - Eigen::Translation3d{-rotor_distance_x / 2, -rotor_distance_y / 2, 0}); - - // GimbalCenterLink 原点等效于 YawLink 和 PitchLink 的交点 - constexpr double gimbal_center_z = -0.27812; - tf_->set_transform( - Eigen::Translation3d{0.0, 0.0, gimbal_center_z}); - constexpr auto camera_postion_x = 0.10238; - constexpr auto camera_postion_z = 0.05286; - - tf_->set_transform( - Eigen::Translation3d{camera_postion_x, 0.0, camera_postion_z}); + [](double x, double y, double z) { return std::tuple{y, z, x}; }); gimbal_calibrate_subscription_ = create_subscription( "/gimbal/calibrate", rclcpp::QoS{0}, [this](std_msgs::msg::Int32::UniquePtr&& msg) { @@ -114,6 +86,13 @@ class Flight {.uart_data = std::span{buffer, size}}); return size; }; + + using namespace rmcs_description; + + constexpr auto kCameraPostionX = 0.10238; + constexpr auto kCameraPostionZ = 0.05286; + tf_->set_transform( + Eigen::Translation3d{kCameraPostionX, 0.0, kCameraPostionZ}); } Flight(const Flight&) = delete; @@ -128,14 +107,10 @@ class Flight update_imu(); dr16_.update_status(); - // 从 TF 树中查询相机位姿 - *camera_transform_ = - fast_tf::lookup_transform( - *tf_); - - // 从 TF 树中查询枪口方向 - *barrel_direction_ = *fast_tf::cast( - rmcs_description::PitchLink::DirectionVector{Eigen::Vector3d::UnitX()}, *tf_); + using namespace rmcs_description; + *camera_transform_ = fast_tf::lookup_transform(*tf_); + *barrel_direction_ = + *fast_tf::cast(PitchLink::DirectionVector{Eigen::Vector3d::UnitX()}, *tf_); } void command_update() { @@ -170,23 +145,26 @@ class Flight private: void update_motors() { - using namespace rmcs_description; // NOLINT(google-build-using-namespace) + gimbal_bullet_feeder_.update_status(); + gimbal_left_friction_.update_status(); + gimbal_right_friction_.update_status(); + + using namespace rmcs_description; + gimbal_yaw_motor_.update_status(); tf_->set_state(gimbal_yaw_motor_.angle()); gimbal_pitch_motor_.update_status(); tf_->set_state(gimbal_pitch_motor_.angle()); - - gimbal_bullet_feeder_.update_status(); - gimbal_left_friction_.update_status(); - gimbal_right_friction_.update_status(); } void update_imu() { + using namespace rmcs_description; + bmi088_.update_status(); - Eigen::Quaterniond gimbal_imu_pose{bmi088_.q0(), bmi088_.q1(), bmi088_.q2(), bmi088_.q3()}; - tf_->set_transform( - gimbal_imu_pose.conjugate()); + const auto gimbal_imu_pose = + Eigen::Quaterniond{bmi088_.q0(), bmi088_.q1(), bmi088_.q2(), bmi088_.q3()}; + tf_->set_transform(gimbal_imu_pose.conjugate()); *gimbal_yaw_velocity_imu_ = bmi088_.gz(); *gimbal_pitch_velocity_imu_ = bmi088_.gy(); From 4e6b2efda500e8a71c9e6813d7c7c4dfc53f0e34 Mon Sep 17 00:00:00 2001 From: creeper5820 Date: Sun, 5 Jul 2026 20:20:17 +0800 Subject: [PATCH 26/30] chore: clean up cmake file --- rmcs_ws/src/rmcs_core/CMakeLists.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/CMakeLists.txt b/rmcs_ws/src/rmcs_core/CMakeLists.txt index 38d75ca7..81bf0b61 100644 --- a/rmcs_ws/src/rmcs_core/CMakeLists.txt +++ b/rmcs_ws/src/rmcs_core/CMakeLists.txt @@ -13,24 +13,25 @@ endif() find_package(ament_cmake_auto REQUIRED) ament_auto_find_build_dependencies() + include(FetchContent) set(BUILD_STATIC_LIBRMCS ON CACHE BOOL "Build static librmcs SDK" FORCE) FetchContent_Declare( - librmcs - URL https://github.com/Alliance-Algorithm/librmcs/releases/download/v3.2.0/librmcs-sdk-src-3.2.0.zip - URL_HASH SHA256=f81c3af7fbcf35727a8a7586200db8e9bf668ee0f448529de4bfd3eb7c36ed6f - DOWNLOAD_EXTRACT_TIMESTAMP TRUE + librmcs + URL https://github.com/Alliance-Algorithm/librmcs/releases/download/v3.2.0/librmcs-sdk-src-3.2.0.zip + URL_HASH SHA256=f81c3af7fbcf35727a8a7586200db8e9bf668ee0f448529de4bfd3eb7c36ed6f + DOWNLOAD_EXTRACT_TIMESTAMP TRUE ) FetchContent_MakeAvailable(librmcs) file(GLOB_RECURSE PROJECT_SOURCE CONFIGURE_DEPENDS - ${PROJECT_SOURCE_DIR}/src/*.cpp - ${PROJECT_SOURCE_DIR}/src/*.c + ${PROJECT_SOURCE_DIR}/src/*.cpp + ${PROJECT_SOURCE_DIR}/src/*.c ) ament_auto_add_library( - ${PROJECT_NAME} SHARED - ${PROJECT_SOURCE} + ${PROJECT_NAME} SHARED + ${PROJECT_SOURCE} ) include_directories(${PROJECT_SOURCE_DIR}/include) From 915c3e4345e6b33994fe1923fd8a597c4ace71e9 Mon Sep 17 00:00:00 2001 From: creeper5820 Date: Sun, 5 Jul 2026 20:38:35 +0800 Subject: [PATCH 27/30] chore: clean up hardware --- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 107 ++++++++---------- 1 file changed, 50 insertions(+), 57 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index 36bc1417..d24ea80e 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include "hardware/device/bmi088.hpp" #include "hardware/device/can_packet.hpp" @@ -32,17 +32,7 @@ class Flight : Node{ get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} - , librmcs::agent::RmcsBoardLite{get_parameter("board_serial").as_string()} - , logger_(get_logger()) - , command_component_( - create_partner_component(get_component_name() + "_command", *this)) - , gimbal_yaw_motor_(*this, *command_component_, "/gimbal/yaw") - , gimbal_pitch_motor_(*this, *command_component_, "/gimbal/pitch") - , gimbal_left_friction_(*this, *command_component_, "/gimbal/left_friction") - , gimbal_right_friction_(*this, *command_component_, "/gimbal/right_friction") - , gimbal_bullet_feeder_(*this, *command_component_, "/gimbal/bullet_feeder") - , dr16_(*this) - , bmi088_(1000.0, 0.2, 0.00) { + , RmcsBoardLite{get_parameter("board_serial").as_string()} { gimbal_yaw_motor_.configure( device::LkMotor::Config{device::LkMotor::Type::kMHF7015} @@ -61,22 +51,17 @@ class Flight gimbal_bullet_feeder_.configure( device::DjiMotor::Config{device::DjiMotor::Type::kM2006}.enable_multi_turn_angle()); - register_output("/gimbal/yaw/velocity_imu", gimbal_yaw_velocity_imu_); - register_output("/gimbal/pitch/velocity_imu", gimbal_pitch_velocity_imu_); - register_output("/tf", tf_); - - register_output("/auto_aim/camera_transform", camera_transform_); - register_output("/auto_aim/barrel_direction", barrel_direction_); - bmi088_.set_coordinate_mapping( [](double x, double y, double z) { return std::tuple{y, z, x}; }); - gimbal_calibrate_subscription_ = create_subscription( - "/gimbal/calibrate", rclcpp::QoS{0}, [this](std_msgs::msg::Int32::UniquePtr&& msg) { - gimbal_calibrate_subscription_callback(std::move(msg)); + status_service_ = create_service( + "/rmcs/service/robot_status", + [this]( + const std_srvs::srv::Trigger::Request::SharedPtr&, + const std_srvs::srv::Trigger::Response::SharedPtr& response) { + status_service_callback(response); }); - register_output("/referee/serial", referee_serial_); referee_serial_->read = [this](std::byte* buffer, size_t size) { return referee_ring_buffer_receive_.pop_front_n( [&buffer](std::byte byte) noexcept { *buffer++ = byte; }, size); @@ -93,14 +78,16 @@ class Flight constexpr auto kCameraPostionZ = 0.05286; tf_->set_transform( Eigen::Translation3d{kCameraPostionX, 0.0, kCameraPostionZ}); - } - Flight(const Flight&) = delete; - Flight& operator=(const Flight&) = delete; - Flight(Flight&&) = delete; - Flight& operator=(Flight&&) = delete; + register_output("/gimbal/yaw/velocity_imu", gimbal_yaw_velocity_imu_); + register_output("/gimbal/pitch/velocity_imu", gimbal_pitch_velocity_imu_); + register_output("/tf", tf_); - ~Flight() override = default; + register_output("/auto_aim/camera_transform", camera_transform_); + register_output("/auto_aim/barrel_direction", barrel_direction_); + + register_output("/referee/serial", referee_serial_); + } void update() override { update_motors(); @@ -170,25 +157,20 @@ class Flight *gimbal_pitch_velocity_imu_ = bmi088_.gy(); } - void gimbal_calibrate_subscription_callback(std_msgs::msg::Int32::UniquePtr) { - RCLCPP_INFO( - logger_, "[gimbal calibration] New yaw offset: %ld", - gimbal_yaw_motor_.calibrate_zero_point()); - RCLCPP_INFO( - logger_, "[gimbal calibration] New pitch offset: %ld", - gimbal_pitch_motor_.calibrate_zero_point()); - } + void + status_service_callback(const std::shared_ptr& response) { + response->success = true; - class FlightCommand : public rmcs_executor::Component { - public: - explicit FlightCommand(Flight& flight) - : flight_(flight) {} + auto feedback_message = std::ostringstream{}; + auto text = [&](std::format_string format, Args&&... args) { + std::println(feedback_message, format, std::forward(args)...); + }; - void update() override { flight_.command_update(); } + text(" yaw_motor_zero_point: {}", gimbal_yaw_motor_.last_raw_angle()); + text(" pitch_motor_zero_point: {}", gimbal_pitch_motor_.last_raw_angle()); - private: - Flight& flight_; - }; + response->message = feedback_message.str(); + } protected: void can0_receive_callback(const librmcs::data::CanDataView& data) override { @@ -251,18 +233,29 @@ class Flight } private: - rclcpp::Logger logger_; - std::shared_ptr command_component_; - rclcpp::Subscription::SharedPtr gimbal_calibrate_subscription_; - - device::LkMotor gimbal_yaw_motor_; - device::LkMotor gimbal_pitch_motor_; - device::DjiMotor gimbal_left_friction_; - device::DjiMotor gimbal_right_friction_; - device::DjiMotor gimbal_bullet_feeder_; - - device::Dr16 dr16_; - device::Bmi088 bmi088_; + class FlightCommand : public rmcs_executor::Component { + public: + explicit FlightCommand(Flight& flight) + : flight_(flight) {} + + void update() override { flight_.command_update(); } + + private: + Flight& flight_; + }; + std::shared_ptr command_component_{ + create_partner_component(get_component_name() + "_command", *this), + }; + std::shared_ptr> status_service_; + + device::LkMotor gimbal_yaw_motor_{*this, *command_component_, "/gimbal/yaw"}; + device::LkMotor gimbal_pitch_motor_{*this, *command_component_, "/gimbal/pitch"}; + device::DjiMotor gimbal_left_friction_{*this, *command_component_, "/gimbal/left_friction"}; + device::DjiMotor gimbal_right_friction_{*this, *command_component_, "/gimbal/right_friction"}; + device::DjiMotor gimbal_bullet_feeder_{*this, *command_component_, "/gimbal/bullet_feeder"}; + + device::Dr16 dr16_{*this}; + device::Bmi088 bmi088_{1000.0, 0.2, 0.00}; OutputInterface gimbal_yaw_velocity_imu_; OutputInterface gimbal_pitch_velocity_imu_; From dfe4f35b6077bf8b5ccd836924c63377ae17ee49 Mon Sep 17 00:00:00 2001 From: zlq040222 <1542498005@qq.com> Date: Mon, 6 Jul 2026 02:27:05 +0800 Subject: [PATCH 28/30] fix(flight): fix initialization order and add tf2_ros dependency --- rmcs_ws/src/rmcs_core/package.xml | 1 + rmcs_ws/src/rmcs_core/src/hardware/flight.cpp | 35 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/rmcs_ws/src/rmcs_core/package.xml b/rmcs_ws/src/rmcs_core/package.xml index 9eb6b089..e42d0669 100644 --- a/rmcs_ws/src/rmcs_core/package.xml +++ b/rmcs_ws/src/rmcs_core/package.xml @@ -19,6 +19,7 @@ rmcs_msgs rmcs_executor rmcs_description + tf2_ros ament_lint_auto ament_lint_common diff --git a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp index d24ea80e..c35bb8df 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/flight.cpp @@ -54,24 +54,6 @@ class Flight bmi088_.set_coordinate_mapping( [](double x, double y, double z) { return std::tuple{y, z, x}; }); - status_service_ = create_service( - "/rmcs/service/robot_status", - [this]( - const std_srvs::srv::Trigger::Request::SharedPtr&, - const std_srvs::srv::Trigger::Response::SharedPtr& response) { - status_service_callback(response); - }); - - referee_serial_->read = [this](std::byte* buffer, size_t size) { - return referee_ring_buffer_receive_.pop_front_n( - [&buffer](std::byte byte) noexcept { *buffer++ = byte; }, size); - }; - referee_serial_->write = [this](const std::byte* buffer, size_t size) { - start_transmit().uart1_transmit( - {.uart_data = std::span{buffer, size}}); - return size; - }; - using namespace rmcs_description; constexpr auto kCameraPostionX = 0.10238; @@ -87,6 +69,23 @@ class Flight register_output("/auto_aim/barrel_direction", barrel_direction_); register_output("/referee/serial", referee_serial_); + referee_serial_->read = [this](std::byte* buffer, size_t size) { + return referee_ring_buffer_receive_.pop_front_n( + [&buffer](std::byte byte) noexcept { *buffer++ = byte; }, size); + }; + referee_serial_->write = [this](const std::byte* buffer, size_t size) { + start_transmit().uart1_transmit( + {.uart_data = std::span{buffer, size}}); + return size; + }; + + status_service_ = create_service( + "/rmcs/service/robot_status", + [this]( + const std_srvs::srv::Trigger::Request::SharedPtr&, + const std_srvs::srv::Trigger::Response::SharedPtr& response) { + status_service_callback(response); + }); } void update() override { From 1820c84ad2d8cb8472679476ba62ec29632bf66e Mon Sep 17 00:00:00 2001 From: creeper5820 Date: Mon, 6 Jul 2026 17:04:25 +0800 Subject: [PATCH 29/30] wip: clean up code and prepared to merge --- .gitmodules | 10 +--- rmcs_ws/src/hikcamera | 1 - rmcs_ws/src/odin_ros_driver | 1 - rmcs_ws/src/rmcs_auto_aim_v2 | 1 - rmcs_ws/src/rmcs_bringup/config/flight.yaml | 3 +- .../src/rmcs_bringup/launch/rmcs.launch.py | 19 ++---- rmcs_ws/src/rmcs_bringup/package.xml | 4 +- rmcs_ws/src/rmcs_core/package.xml | 4 +- rmcs_ws/src/rmcs_core/plugins.xml | 17 +++--- .../gimbal/simple_gimbal_controller.cpp | 18 +++--- .../gimbal/two_axis_gimbal_solver.hpp | 14 ++--- .../bullet_feeder_controller_17mm.cpp | 60 +++++-------------- .../rmcs_core/src/hardware/omni_infantry.cpp | 2 +- .../rmcs_core/src/referee/app/ui/flight.cpp | 18 +++--- .../src/referee/app/ui/shape/shape.hpp | 2 - .../src/referee/app/ui/widget/status_ring.hpp | 40 ++++--------- .../src/referee/command/interaction/ui.cpp | 36 +++-------- rmcs_ws/src/rmcs_core/src/referee/status.cpp | 7 ++- 18 files changed, 83 insertions(+), 174 deletions(-) delete mode 160000 rmcs_ws/src/hikcamera delete mode 160000 rmcs_ws/src/odin_ros_driver delete mode 160000 rmcs_ws/src/rmcs_auto_aim_v2 diff --git a/.gitmodules b/.gitmodules index b7cf4791..68f1d09b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,4 @@ [submodule "rmcs_ws/src/fast_tf"] path = rmcs_ws/src/fast_tf url = https://github.com/qzhhhi/FastTF.git -[submodule "rmcs_ws/src/odin_ros_driver"] - path = rmcs_ws/src/odin_ros_driver - url = https://github.com/Alliance-Algorithm/odin_ros_driver.git -[submodule "rmcs_ws/src/hikcamera"] - path = rmcs_ws/src/hikcamera - url = https://github.com/Alliance-Algorithm/ros2-hikcamera.git -[submodule "rmcs_ws/src/rmcs_auto_aim_v2"] - path = rmcs_ws/src/rmcs_auto_aim_v2 - url = https://github.com/Alliance-Algorithm/rmcs_auto_aim_v2.git + diff --git a/rmcs_ws/src/hikcamera b/rmcs_ws/src/hikcamera deleted file mode 160000 index f0077f03..00000000 --- a/rmcs_ws/src/hikcamera +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f0077f034800bcd0dde4fffeff270b733772a57e diff --git a/rmcs_ws/src/odin_ros_driver b/rmcs_ws/src/odin_ros_driver deleted file mode 160000 index 5cb37012..00000000 --- a/rmcs_ws/src/odin_ros_driver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5cb37012a12686bb757923244eb0612285012c04 diff --git a/rmcs_ws/src/rmcs_auto_aim_v2 b/rmcs_ws/src/rmcs_auto_aim_v2 deleted file mode 160000 index c2da258f..00000000 --- a/rmcs_ws/src/rmcs_auto_aim_v2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c2da258f531e927c3a1f22dd3d2861674bc14e6f diff --git a/rmcs_ws/src/rmcs_bringup/config/flight.yaml b/rmcs_ws/src/rmcs_bringup/config/flight.yaml index 3d9675f8..2291e12a 100644 --- a/rmcs_ws/src/rmcs_bringup/config/flight.yaml +++ b/rmcs_ws/src/rmcs_bringup/config/flight.yaml @@ -116,9 +116,8 @@ heat_controller: bullet_feeder_controller: ros__parameters: - debug_ignore_friction_ready: true # 调试用:不开摩擦轮也允许拨弹,复原时改为 false bullets_per_feeder_turn: 8.0 - shot_frequency: 25.0 + shot_frequency: 20.0 safe_shot_frequency: 10.0 eject_frequency: 10.0 eject_time: 0.05 diff --git a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py index bc23a13b..976cb9e7 100644 --- a/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py +++ b/rmcs_ws/src/rmcs_bringup/launch/rmcs.launch.py @@ -6,8 +6,7 @@ LaunchDescription, LaunchDescriptionEntity, ) -from launch.actions import IncludeLaunchDescription, LogInfo -from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.actions import LogInfo from launch.substitutions import LaunchConfiguration from launch_ros.actions import Node @@ -29,7 +28,10 @@ def visit( robot_name = robot_config entities.append( - LogInfo(msg=f"Starting RMCS on robot -> {robot_name}.yaml")) + LogInfo( + msg=f"Starting RMCS on robot '{robot_config}'{'(automatic)' if is_automatic else ''} -> {robot_name}.yaml" + ) + ) entities.append( Node( @@ -44,22 +46,13 @@ def visit( ], respawn=True, respawn_delay=1.0, - output="log", + output="log", # stdout and stderr are logged to launch log file and stderr to the screen. ) ) if is_automatic: pass - # entities.append( - # Node( - # package="odin_ros_driver", - # executable="tmux-launch.sh", - # output="screen", - # emulate_tty=True, - # ) - # ) - return entities diff --git a/rmcs_ws/src/rmcs_bringup/package.xml b/rmcs_ws/src/rmcs_bringup/package.xml index 8642966e..c64c661f 100644 --- a/rmcs_ws/src/rmcs_bringup/package.xml +++ b/rmcs_ws/src/rmcs_bringup/package.xml @@ -11,8 +11,6 @@ ament_cmake joint_state_broadcaster - mavros - odin_ros_driver robot_state_publisher rviz2 xacro @@ -23,4 +21,4 @@ ament_cmake - + \ No newline at end of file diff --git a/rmcs_ws/src/rmcs_core/package.xml b/rmcs_ws/src/rmcs_core/package.xml index e42d0669..4312d334 100644 --- a/rmcs_ws/src/rmcs_core/package.xml +++ b/rmcs_ws/src/rmcs_core/package.xml @@ -10,16 +10,16 @@ ament_cmake rclcpp - nav_msgs std_msgs std_srvs pluginlib + tf2 + tf2_ros serial rmcs_utility rmcs_msgs rmcs_executor rmcs_description - tf2_ros ament_lint_auto ament_lint_common diff --git a/rmcs_ws/src/rmcs_core/plugins.xml b/rmcs_ws/src/rmcs_core/plugins.xml index 51fb30aa..1f46763e 100644 --- a/rmcs_ws/src/rmcs_core/plugins.xml +++ b/rmcs_ws/src/rmcs_core/plugins.xml @@ -1,7 +1,5 @@ - - - + @@ -9,6 +7,7 @@ + @@ -22,14 +21,14 @@ - + - + @@ -38,19 +37,23 @@ + + + + + + - - diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp index 0857c178..dfd36131 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/simple_gimbal_controller.cpp @@ -20,9 +20,11 @@ class SimpleGimbalController : Node( get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)) - , two_axis_gimbal_solver( - *this, get_parameter("upper_limit").as_double(), - get_parameter("lower_limit").as_double()) { + , two_axis_gimbal_solver{ + *this, + get_parameter("upper_limit").as_double(), + get_parameter("lower_limit").as_double(), + } { register_input("/remote/joystick/left", joystick_left_); register_input("/remote/switch/right", switch_right_); @@ -36,18 +38,14 @@ class SimpleGimbalController register_output("/gimbal/yaw/control_angle_error", yaw_angle_error_, nan_); register_output("/gimbal/pitch/control_angle_error", pitch_angle_error_, nan_); - rclcpp::Parameter yaw_upper, yaw_lower; - if (get_parameter("yaw_upper_limit", yaw_upper) - && get_parameter("yaw_lower_limit", yaw_lower)) { - two_axis_gimbal_solver.enable_yaw_limit( - *this, yaw_upper.as_double(), yaw_lower.as_double()); - } + two_axis_gimbal_solver.enable_yaw_limit( + *this, get_parameter("yaw_upper_limit").as_double(), + get_parameter("yaw_lower_limit").as_double()); } void update() override { auto angle_error = calculate_angle_error(); *yaw_angle_error_ = angle_error.yaw_angle_error; - *pitch_angle_error_ = angle_error.pitch_angle_error; } diff --git a/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp b/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp index 711abb21..03831969 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp +++ b/rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -201,7 +200,7 @@ class TwoAxisGimbalSolver { } void clamp_yaw_limit(YawLink::DirectionVector& control_direction) { - if (!yaw_cw_min_.has_value()) + if (!gimbal_yaw_angle_.ready()) return; constexpr double two_pi = 2 * std::numbers::pi; @@ -210,12 +209,12 @@ class TwoAxisGimbalSolver { cw += two_pi; const auto& [x, y, z] = *control_direction; - const double err = std::atan2(y, x); + const double err = std::atan2(y, x); - const double target_cw = cw - err; - const double clamped_cw = std::clamp(target_cw, *yaw_cw_min_, *yaw_cw_max_); + const double target_cw = cw - err; + const double clamped_cw = std::clamp(target_cw, yaw_cw_min_, yaw_cw_max_); if (clamped_cw == target_cw) - return; + return; // delta = err_new - err = (cw - clamped_cw) - err const double delta = (cw - clamped_cw) - err; @@ -244,7 +243,8 @@ class TwoAxisGimbalSolver { rmcs_executor::Component::InputInterface gimbal_pitch_angle_; rmcs_executor::Component::InputInterface tf_; - std::optional yaw_cw_min_, yaw_cw_max_; + double yaw_cw_min_ = 0.; + double yaw_cw_max_ = 0.; rmcs_executor::Component::InputInterface gimbal_yaw_angle_; OdomImu::DirectionVector yaw_axis_filtered_{Eigen::Vector3d::UnitZ()}; diff --git a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp index 69640700..4b845caa 100644 --- a/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp +++ b/rmcs_ws/src/rmcs_core/src/controller/shooting/bullet_feeder_controller_17mm.cpp @@ -1,7 +1,3 @@ -#include - -#include - #include #include #include @@ -28,9 +24,6 @@ class BulletFeederController17mm bullet_feeder_working_velocity = bullet_feeder_angle_per_bullet * shot_frequency; double safe_shot_frequency = get_parameter("safe_shot_frequency").as_double(); bullet_feeder_safe_shot_velocity = bullet_feeder_angle_per_bullet * safe_shot_frequency; - constexpr double rotary_knob_shot_frequency = 8.0; - bullet_feeder_rotary_knob_velocity_ = - bullet_feeder_angle_per_bullet * rotary_knob_shot_frequency; double eject_frequency = get_parameter("eject_frequency").as_double(); bullet_feeder_eject_velocity_ = -bullet_feeder_angle_per_bullet * eject_frequency; @@ -45,12 +38,6 @@ class BulletFeederController17mm single_shot_max_stop_delay_ = static_cast( std::round(1000.0 * get_parameter("single_shot_max_stop_delay").as_double())); - // Debug option: allow bullet feeding without friction wheels spinning. - debug_ignore_friction_ready_ = get_parameter_or("debug_ignore_friction_ready", false); - if (debug_ignore_friction_ready_) - RCLCPP_WARN( - logger_, "Friction-ready check bypassed: feeder will spin without friction wheels!"); - register_input("/gimbal/friction_ready", friction_ready_); register_input("/gimbal/bullet_fired", bullet_fired_); register_input( @@ -61,9 +48,8 @@ class BulletFeederController17mm register_input("/remote/switch/left", switch_left_); register_input("/remote/mouse", mouse_); register_input("/remote/keyboard", keyboard_); - register_input("/remote/rotary_knob_switch", rotary_knob_switch_); - register_input("/auto_aim/should_shoot", auto_aim_should_shoot_, false); + register_input("/auto_aim/should_shoot", should_shoot_, false); register_input("/gimbal/bullet_feeder/velocity", bullet_feeder_velocity_); register_output( @@ -73,8 +59,8 @@ class BulletFeederController17mm } void before_updating() override { - if (!auto_aim_should_shoot_.ready()) - auto_aim_should_shoot_.bind_directly(false); + if (!should_shoot_.ready()) + should_shoot_.bind_directly(false); } void update() override { @@ -84,14 +70,13 @@ class BulletFeederController17mm const auto switch_left = *switch_left_; const auto mouse = *mouse_; const auto keyboard = *keyboard_; - const auto rotary_knob_switch = *rotary_knob_switch_; using namespace rmcs_msgs; if ((switch_left == Switch::UNKNOWN || switch_right == Switch::UNKNOWN) || (switch_left == Switch::DOWN && switch_right == Switch::DOWN)) { reset_all_controls(); } else { - int64_t bullet_allowance = 0; + std::int64_t bullet_allowance = 0; if (switch_right != Switch::DOWN) { shoot_mode = keyboard.f ? ShootMode::SINGLE : ShootMode::AUTOMATIC; @@ -111,33 +96,22 @@ class BulletFeederController17mm if (*bullet_fired_) single_shot_stop_counter_ = 0; - const bool friction_ready = *friction_ready_ || debug_ignore_friction_ready_; - if (friction_ready) { + if (*friction_ready_) { if (shoot_mode == ShootMode::AUTOMATIC) { - bool manual_triggered = mouse.left || switch_left == Switch::DOWN; - bool auto_aim_triggered = mouse.right && *auto_aim_should_shoot_; - bool rotary_knob_triggered = rotary_knob_switch == Switch::DOWN; - bool triggered = - manual_triggered || auto_aim_triggered || rotary_knob_triggered; - bool rotary_knob_low_speed = - rotary_knob_triggered && !manual_triggered && !auto_aim_triggered; + auto aiming_enable = mouse_->right || (switch_right == Switch::UP); + auto attack_intent = mouse_->left || (switch_left == Switch::DOWN); + auto triggered = aiming_enable ? *should_shoot_ : attack_intent; bullet_allowance = triggered ? *control_bullet_allowance_limited_by_heat_ : 0; - update_bullet_feeder_velocity(bullet_allowance, rotary_knob_low_speed); } else { - bool triggered = single_shot_stop_counter_ > 0; + auto triggered = single_shot_stop_counter_ > 0; bullet_allowance = triggered && (*control_bullet_allowance_limited_by_heat_ > 0); - update_bullet_feeder_velocity(bullet_allowance, false); } - } else { - update_bullet_feeder_velocity(0, false); } } - if ((!*friction_ready_ && !debug_ignore_friction_ready_) - || switch_right == Switch::DOWN) - update_bullet_feeder_velocity(0, false); + update_bullet_feeder_velocity(bullet_allowance); } last_switch_right_ = switch_right; @@ -153,7 +127,7 @@ class BulletFeederController17mm *bullet_feeder_control_velocity_ = nan_; } - void update_bullet_feeder_velocity(int64_t bullet_allowance, bool rotary_knob_low_speed) { + void update_bullet_feeder_velocity(int64_t bullet_allowance) { if (bullet_allowance <= 0) { bullet_feeder_working_status_ = 0; *bullet_feeder_control_velocity_ = 0.0; @@ -167,9 +141,8 @@ class BulletFeederController17mm return; } - double new_control_velocity = rotary_knob_low_speed ? bullet_feeder_rotary_knob_velocity_ - : bullet_allowance > 1 ? bullet_feeder_working_velocity - : bullet_feeder_safe_shot_velocity; + double new_control_velocity = bullet_allowance > 1 ? bullet_feeder_working_velocity + : bullet_feeder_safe_shot_velocity; if (new_control_velocity > *bullet_feeder_control_velocity_) bullet_feeder_working_status_ = std::min(0, bullet_feeder_working_status_); *bullet_feeder_control_velocity_ = new_control_velocity; @@ -224,8 +197,6 @@ class BulletFeederController17mm int single_shot_max_stop_delay_, single_shot_stop_counter_ = 0; - bool debug_ignore_friction_ready_ = false; - InputInterface friction_ready_; InputInterface bullet_fired_; InputInterface control_bullet_allowance_limited_by_heat_; @@ -234,9 +205,8 @@ class BulletFeederController17mm InputInterface switch_left_; InputInterface mouse_; InputInterface keyboard_; - InputInterface rotary_knob_switch_; - InputInterface auto_aim_should_shoot_; + InputInterface should_shoot_; rmcs_msgs::Switch last_switch_right_ = rmcs_msgs::Switch::UNKNOWN; rmcs_msgs::Switch last_switch_left_ = rmcs_msgs::Switch::UNKNOWN; @@ -248,8 +218,6 @@ class BulletFeederController17mm int bullet_feeder_jammed_count_ = 0; int bullet_feeder_cool_down_ = 0; - double bullet_feeder_rotary_knob_velocity_ = 0.0; - int temporary_single_shot_counter_ = 0; OutputInterface shoot_mode_; diff --git a/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp b/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp index 472b05a3..84b72077 100644 --- a/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp +++ b/rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp @@ -249,7 +249,7 @@ class OmniInfantry motor.store_status(data.can_data); } else if (can_id == 0x202) { auto& motor = chassis_wheel_motors_[1]; - motor.store_status(data.can_data); + motor.store_status(data.can_data); } else if (can_id == 0x203) { auto& motor = chassis_wheel_motors_[2]; motor.store_status(data.can_data); diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp index b9bbd968..88367c26 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/flight.cpp @@ -19,9 +19,11 @@ class Flight static constexpr uint8_t kUiModeEngineer = 2; Flight() - : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} + : Node{ + get_component_name(), + rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} , crosshair_circle_(Shape::Color::WHITE, x_center - 2, y_center - 30, 8, 2) - , status_ring_(26.5, 26.5, 600, 300, StatusRing::DynamicArcsVisibility{false, false}) + , status_ring_(26.5, 26.5, 600, 300, false, false) , horizontal_center_guidelines_( {Shape::Color::WHITE, 2, x_center - 360, y_center, x_center - 110, y_center}, {Shape::Color::WHITE, 2, x_center + 110, y_center, x_center + 360, y_center}) @@ -61,16 +63,10 @@ class Flight auto mode_value = auto_aim_mode_.ready() ? *auto_aim_mode_ : kUiModeCombat; switch (mode_value) { - case kUiModeOutpostOnly: - mode_indicator_.set_color(Shape::Color::GREEN); - break; - case kUiModeEngineer: - mode_indicator_.set_color(Shape::Color::PINK); - break; + case kUiModeOutpostOnly: mode_indicator_.set_color(Shape::Color::GREEN); break; + case kUiModeEngineer: mode_indicator_.set_color(Shape::Color::PINK); break; case kUiModeCombat: - default: - mode_indicator_.set_color(Shape::Color::YELLOW); - break; + default: mode_indicator_.set_color(Shape::Color::YELLOW); break; } } diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp index 1ceae35e..37be26ae 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp @@ -192,8 +192,6 @@ class Shape enter_run_queue(); } - void set_text_shape() { is_text_shape_ = true; } - virtual size_t write_description_field(std::byte* buffer) = 0; DescriptionField::Part2 part2_ alignas(4); diff --git a/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp b/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp index 32d8c614..c45eaf93 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp +++ b/rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp @@ -1,11 +1,10 @@ #pragma once #include +#include #include #include #include - -#include #include #include @@ -16,20 +15,12 @@ namespace rmcs_core::referee::app::ui { class StatusRing { public: - struct DynamicArcsVisibility { - bool supercap; - bool battery; - }; - - StatusRing(double supercap_limit, double battery_limit, double friction_limit, int16_t bullet_limit) - : StatusRing( - supercap_limit, battery_limit, friction_limit, bullet_limit, - DynamicArcsVisibility{true, true}) {} - StatusRing( double supercap_limit, double battery_limit, double friction_limit, int16_t bullet_limit, - DynamicArcsVisibility dynamic_arcs_visibility) - : dynamic_arcs_visibility_(dynamic_arcs_visibility) { + bool supercap = true, bool battery = true) + : supercap_ui_{supercap} + , battery_ui_{battery} { + supercap_status_.set_x(x_center); supercap_status_.set_y(y_center); supercap_status_.set_r(visible_radius - width_ring); @@ -37,7 +28,7 @@ class StatusRing { supercap_status_.set_angle_end(275 + visible_angle); supercap_status_.set_width(width_ring); supercap_status_.set_color(Shape::Color::PINK); - supercap_status_.set_visible(true); + supercap_status_.set_visible(supercap); battery_status_.set_x(x_center); battery_status_.set_y(y_center); @@ -46,7 +37,7 @@ class StatusRing { battery_status_.set_angle_end(265); battery_status_.set_width(width_ring); battery_status_.set_color(Shape::Color::PINK); - battery_status_.set_visible(true); + battery_status_.set_visible(battery); friction_wheel_speed_.set_x(x_center); friction_wheel_speed_.set_y(y_center); @@ -120,14 +111,12 @@ class StatusRing { arc_right_down_.set_visible(true); set_limits(supercap_limit, battery_limit, friction_limit, bullet_limit); - supercap_status_.set_visible(dynamic_arcs_visibility_.supercap); - battery_status_.set_visible(dynamic_arcs_visibility_.battery); } void set_visible(bool value) { // Dynamic - supercap_status_.set_visible(value && dynamic_arcs_visibility_.supercap); - battery_status_.set_visible(value && dynamic_arcs_visibility_.battery); + supercap_status_.set_visible(value && supercap_ui_); + battery_status_.set_visible(value && battery_ui_); friction_wheel_speed_.set_visible(value); bullet_status_.set_visible(value); @@ -260,9 +249,6 @@ class StatusRing { } void update_supercap(double value, bool enable) { - if (!dynamic_arcs_visibility_.supercap) - return; - auto angle = 275 + calculate_angle(value, 10.5, supercap_limit_) + 1; supercap_status_.set_angle_end(static_cast(angle)); @@ -276,9 +262,6 @@ class StatusRing { } void update_battery_power(double value) { - if (!dynamic_arcs_visibility_.battery) - return; - auto angle = 265 - calculate_angle(value, 20, 25.7) - 1; battery_status_.set_angle_start(static_cast(angle)); @@ -373,13 +356,14 @@ class StatusRing { constexpr static uint16_t visible_radius = 400; constexpr static uint16_t visible_angle = 40; - DynamicArcsVisibility dynamic_arcs_visibility_; - double supercap_limit_; double battery_limit_; double friction_limit_; int16_t bullet_limit_; + bool supercap_ui_ = true; + bool battery_ui_ = true; + // Dynamic part Arc supercap_status_; diff --git a/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp b/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp index 4d57f606..57167144 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/command/interaction/ui.cpp @@ -87,10 +87,6 @@ class Ui } size_t write_updating_field(std::byte* buffer) const { - if (auto written = write_updating_text_field(buffer); written != 0) { - return written; - } - size_t written = 0; auto& header = *new (buffer + written) Header{}; @@ -102,9 +98,15 @@ class Ui int slot = 0; intptr_t updated[7]; for (auto it = CfsScheduler::get_update_iterator(); it && slot < 7;) { + // Ignore text shape unless it is the first. if (it->is_text_shape()) { - it.ignore(); - continue; + if (slot == 0) { + header.command_id = 0x0110; // Draw text shape + return written + it.update().write(buffer + written); + } else { + it.ignore(); + continue; + } } auto operation = it->predict_update(); @@ -146,28 +148,6 @@ class Ui return written; } - size_t write_updating_text_field(std::byte* buffer) const { - size_t written = 0; - - auto& header = *new (buffer + written) Header{}; - auto full_robot_id = rmcs_msgs::FullRobotId { *robot_id_ }; - header.command_id = 0x0110; // Draw text shape - header.sender_id = full_robot_id; - header.receiver_id = full_robot_id.client(); - written += sizeof(Header); - - for (auto it = CfsScheduler::get_update_iterator(); it;) { - if (!it->is_text_shape()) { - it.ignore(); - continue; - } - - return written + it.update().write(buffer + written); - } - - return 0; - } - InputInterface robot_id_; InputInterface game_stage_; diff --git a/rmcs_ws/src/rmcs_core/src/referee/status.cpp b/rmcs_ws/src/rmcs_core/src/referee/status.cpp index 6cb4e026..c29bc3c2 100644 --- a/rmcs_ws/src/rmcs_core/src/referee/status.cpp +++ b/rmcs_ws/src/rmcs_core/src/referee/status.cpp @@ -21,7 +21,9 @@ class Status , public rclcpp::Node { public: Status() - : Node{get_component_name(), rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} + : Node{ + get_component_name(), + rclcpp::NodeOptions{}.automatically_declare_parameters_from_overrides(true)} , logger_(get_logger()) { register_input("/referee/serial", serial_); @@ -282,7 +284,8 @@ class Status *map_command_received_timestamp_ = std::chrono::duration(now.time_since_epoch()).count(); - if (has_last_map_command_ && std::memcmp(&last_map_command_, &data, sizeof(data)) == 0) { + if (has_last_map_command_ + && std::memcmp(&last_map_command_, &data, sizeof(data)) == 0) { // NOLINT return; } From e100c136ecc91ae3ae1f032915f5ee7be5c62c26 Mon Sep 17 00:00:00 2001 From: creeper5820 Date: Mon, 6 Jul 2026 17:07:28 +0800 Subject: [PATCH 30/30] chore: apply format --- .gitmodules | 1 - .../rmcs_description/sentry_description.hpp | 20 +++++++++---------- .../rmcs_description/tf_description.hpp | 18 ++++++++--------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.gitmodules b/.gitmodules index 68f1d09b..61e5f08f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,3 @@ [submodule "rmcs_ws/src/fast_tf"] path = rmcs_ws/src/fast_tf url = https://github.com/qzhhhi/FastTF.git - diff --git a/rmcs_ws/src/rmcs_description/include/rmcs_description/sentry_description.hpp b/rmcs_ws/src/rmcs_description/include/rmcs_description/sentry_description.hpp index 2fc9d17b..1ac5d4ee 100644 --- a/rmcs_ws/src/rmcs_description/include/rmcs_description/sentry_description.hpp +++ b/rmcs_ws/src/rmcs_description/include/rmcs_description/sentry_description.hpp @@ -66,7 +66,7 @@ struct RightFrontWheelLink : fast_tf::Link { template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Translation3d transform = Eigen::Translation3d::Identity(); }; @@ -114,37 +114,37 @@ struct fast_tf::Joint : fast_tf::ModificationTracka template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Translation3d transform = Eigen::Translation3d::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Translation3d transform = Eigen::Translation3d::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BottomYawLink; + using Parent = rmcs_description::BottomYawLink; Eigen::Quaterniond transform = Eigen::Quaterniond::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Quaterniond transform = Eigen::Quaterniond::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{std::numbers::pi / 4, Eigen::Vector3d::UnitZ()} @@ -155,7 +155,7 @@ struct fast_tf::Joint : fast_tf::Modificat template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{std::numbers::pi / 4 * 3, Eigen::Vector3d::UnitZ()} @@ -166,7 +166,7 @@ struct fast_tf::Joint : fast_tf::Modificati template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{-std::numbers::pi / 4 * 3, Eigen::Vector3d::UnitZ()} @@ -177,7 +177,7 @@ struct fast_tf::Joint : fast_tf::Modificat template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{-std::numbers::pi / 4, Eigen::Vector3d::UnitZ()} diff --git a/rmcs_ws/src/rmcs_description/include/rmcs_description/tf_description.hpp b/rmcs_ws/src/rmcs_description/include/rmcs_description/tf_description.hpp index 650987f5..4a46051c 100644 --- a/rmcs_ws/src/rmcs_description/include/rmcs_description/tf_description.hpp +++ b/rmcs_ws/src/rmcs_description/include/rmcs_description/tf_description.hpp @@ -73,7 +73,7 @@ struct OmniLinkRight : fast_tf::Link { template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Translation3d transform = Eigen::Translation3d::Identity(); }; @@ -101,25 +101,25 @@ struct fast_tf::Joint : fast_tf::ModificationTracka template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Translation3d transform = Eigen::Translation3d::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Translation3d transform = Eigen::Translation3d::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::PitchLink; + using Parent = rmcs_description::PitchLink; Eigen::Quaterniond transform = Eigen::Quaterniond::Identity(); }; @@ -135,7 +135,7 @@ struct fast_tf::Joint : fast_tf::ModificationTrack }; template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{std::numbers::pi / 4, Eigen::Vector3d::UnitZ()} @@ -146,7 +146,7 @@ struct fast_tf::Joint : fast_tf::Modificat template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{std::numbers::pi / 4 * 3, Eigen::Vector3d::UnitZ()} @@ -157,7 +157,7 @@ struct fast_tf::Joint : fast_tf::Modificati template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{-std::numbers::pi / 4 * 3, Eigen::Vector3d::UnitZ()} @@ -168,7 +168,7 @@ struct fast_tf::Joint : fast_tf::Modificat template <> struct fast_tf::Joint : fast_tf::ModificationTrackable { - using Parent = rmcs_description::BaseLink; + using Parent = rmcs_description::BaseLink; Eigen::Isometry3d transform = Eigen::Isometry3d::Identity(); void set_state(double angle) { auto rotation = Eigen::AngleAxisd{-std::numbers::pi / 4, Eigen::Vector3d::UnitZ()}