Uh oh!
There was an error while loading. Please reload this page.
merge(robots): Merge all available robots into one branch - #92
merge(robots): Merge all available robots into one branch#92creeper5820 wants to merge 31 commits into
Conversation
2、interfere clean 3、six_friction: rename and reset parameter 4、putter return
…for temporary debugging by qzhhhi · Pull Request #55 · Allia)
- Sync both omni and omni-b to BottomBoard/TopBoard/ImuBoard architecture - Update board serial filters and DeformableSuspension config in YAMLs - Remove Vt13/RemoteControl; use Dr16 direct /remote/* outputs - Clean up unrelated changes from feat/deformable-infantry
Walkthrough本次变更迁移硬件板卡通信接口,重构底盘、悬架、云台和射击控制,新增自动瞄准与识别工具,并更新 UI、ROS 配置、插件注册、调试脚本及子模块。 ChangesRMCS 系统整合
Estimated code review effort: 5 (Critical) | ~180 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp (1)
229-248: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win在安全复位中清理完整的射击状态。
当前未复位
shooted、shoot_first、preloaded_ready_、putter_timeout_count_、locked_detect_count_、bullet_feeder_reverse_end_和点击计数。断连发生在射击或反转期间时,恢复后可能立即进入错误分支或沿用旧就绪状态。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp` around lines 229 - 248, 在 reset_all_controls() 中补充完整清理射击状态:重置 shooted、shoot_first、preloaded_ready_、putter_timeout_count_、locked_detect_count_、bullet_feeder_reverse_end_ 以及点击计数,使用各字段现有的默认/初始值。保留现有控制器、PID、扭矩和 shoot_stage_ 的复位逻辑,确保断连恢复后不会沿用旧状态。
🟠 Major comments (30)
rmcs_ws/src/rmcs_core/src/identification/static_torque_test_controller.cpp-176-181 (1)
176-181: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win进入测量模式时重置旧的机械范围。
重新进入
kMeasureRange后,range_initialized_仍保留上次测量结果,新会话只能扩展旧范围而不能缩小它。随后中心点和测试边界可能继续使用失效的机械极限。建议修复
- case RemoteMode::kMeasureRange: handle_measure_range(); break;+ case RemoteMode::kMeasureRange: handle_measure_range(mode_changed); break;- void handle_measure_range() {+ void handle_measure_range(bool mode_changed) { stop_test(true); position_pid_.reset(); velocity_pid_.reset(); + if (mode_changed)+ range_initialized_ = false; update_measured_range(); *control_torque_ = nan_; }Also applies to: 207-225
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/identification/static_torque_test_controller.cpp` around lines 176 - 181, 在 `remote_mode` 切换进入 `RemoteMode::kMeasureRange` 时,利用 `mode_changed` 重置 `range_initialized_` 及其关联的机械范围边界,使新测量会话从空范围开始;保持同一测量模式持续运行时的范围累积行为不变,并确保后续中心点和测试边界使用本次会话数据。.script/identification/fit_sweep_graybox.py-937-959 (1)
937-959: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win将非有限浮点数转换为
null,确保输出为严格 JSON。线性模式的
shooting_window和 ODE 模式的design_condition固定为NaN;json.dumps()会输出裸NaN,不少标准 JSON 解析器会直接拒绝该文件。请先转换为None,并使用allow_nan=False防止回归。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_sweep_graybox.py around lines 937 - 959, Update the JSON payload construction around the shooting_window and design_condition fields so non-finite floating-point values are converted to None before serialization, producing JSON null; preserve finite values unchanged. Include the relevant design_condition value in the payload if it is currently emitted, and serialize with json.dumps(..., allow_nan=False) to reject any remaining NaN or Infinity values..script/identification/fit_sweep_graybox.py-924-935 (1)
924-935: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win不要把失败或非物理解标记为建议参数。
print_warnings()后仍无条件输出Suggested params。优化器失败,或J <= 0、B < 0、Fc < 0时,应拒绝输出建议参数并返回非零状态,避免这些值被复制到机器人配置中。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_sweep_graybox.py around lines 924 - 935, Update the result-reporting flow after print_warnings() so Suggested params and nuisance parameters are printed only when optimization succeeds and the fitted values are physical: J > 0, B >= 0, and Fc >= 0. For optimization failure or any invalid fit, skip those parameter outputs and return a nonzero exit status from the surrounding entry-point function..script/identification/fit_sweep_graybox.py-776-813 (1)
776-813: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win在 unwrap 和滤波前处理非有限样本。
单个
NaN/Inf会污染平滑窗口,并可能让np.unwrap()后续数据全部失效,最终触发未处理的线性代数错误或产生非有限结果。请在预处理前明确拒绝这些行,或按连续有效区间分段拟合。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_sweep_graybox.py around lines 776 - 813, 在执行 savitzky_golay 和 np.unwrap 之前,更新当前数据预处理流程,显式检查 elapsed、angle、velocity、control_torque 和 measured_torque 中的非有限值,并拒绝包含 NaN/Inf 的行;随后仅使用剩余有效样本继续窗口长度、滤波、unwrap 和拟合逻辑,保留现有“样本过少”错误处理。.script/identification/fit_friction_velocity_pid.py-189-196 (1)
189-196: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win两个辨识工具都在未验证采样均匀性的情况下使用固定
dt。 乱序、重复时间戳或丢帧会扭曲导数及最终模型参数。
.script/identification/fit_friction_velocity_pid.py#L189-L196:检查所有时间差为有限正数,并在抖动超限时拒绝或重采样。.script/identification/fit_sweep_graybox.py#L785-L792:在构造 Savitzky-Golay 基和 ODE 分段前应用相同校验。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_friction_velocity_pid.py around lines 189 - 196, Validate sampling uniformity in both sites: .script/identification/fit_friction_velocity_pid.py lines 189-196 and .script/identification/fit_sweep_graybox.py lines 785-792. Before using fixed dt, verify every elapsed-time difference is finite and positive, then reject the data or resample when timing jitter exceeds the accepted threshold. Apply the same validation before constructing the Savitzky-Golay basis and ODE segments in fit_sweep_graybox.py, while preserving the existing valid-dt calculation and downstream processing..script/rmcs-cli-86-102 (1)
86-102: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win使用本次构建的唯一退出标记判断完成状态。
窗格中残留的旧
Summary:/failed会让新构建立刻被误判完成;反之,命令提前退出但未打印这些文本时循环会永久等待。请给命令追加唯一标记和退出码,并设置等待超时。marker=f"__RMCS_BUILD_DONE_{time.time_ns()}__"send_pane( _pane_build, f"cd {RMCS_PATH} && .script/build-rmcs; "f"status=$?; printf '\\n{marker}:%s\\n' \"$status\"", )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/rmcs-cli around lines 86 - 102, 更新 workflow 中的构建等待逻辑,生成每次构建唯一的 marker,并将带退出码的 marker 命令追加到 send_pane(_pane_build, ...);循环仅匹配本次 marker,解析退出码后判断构建成功或失败。为等待循环增加超时,避免命令无标记退出时永久阻塞,并移除对残留 “Summary:”/“failed” 文本的判断。.script/identification/fit_friction_velocity_pid.py-256-262 (1)
256-262: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win校验
fc_hz为有限正数。
--fc-hz nan、无穷值或负数目前会直接生成nan、无穷或负的 PID 增益并输出到 YAML。建议修复
fc_hz = args.fc_hz if args.fc_hz is not None else default_fc_hz(target) + if not math.isfinite(fc_hz) or fc_hz <= 0.0:+ raise ValueError("fc-hz must be finite and positive") wc = 2.0 * math.pi * fc_hz🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_friction_velocity_pid.py around lines 256 - 262, 在计算 wc 和 PID 增益前,于 fc_hz 参数解析后的流程中校验 fc_hz 必须为有限正数,拒绝 NaN、无穷值和小于等于零的值;对无效输入抛出清晰的参数错误,并确保不会继续生成或写入无效增益。使用现有的 fc_hz、default_fc_hz 和参数处理符号完成校验。.script/scan-remote-60-85 (1)
60-85: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win不要在 raw terminal 上下文中调用
os._exit()。
q或 Escape 会绕过RawTerminal.__exit__()、view.stop()和线程池清理,使调用者终端保持无回显、非规范输入状态。请抛出可在顶层处理的取消异常,让上下文正常展开。建议修复
raw = sys.stdin.buffer.raw.read(1) if raw in (b"q", b"Q"): - os._exit(130)+ raise KeyboardInterrupt ... if not RawTerminal.key_ready(0.02): - os._exit(130)+ raise KeyboardInterrupt🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/scan-remote around lines 60 - 85, Replace the os._exit() calls in RawTerminal.read_key and RawTerminal._read_escape with the existing or an appropriate cancellation exception, allowing the top-level caller to handle cancellation. Preserve the current q/Escape cancellation behavior while ensuring RawTerminal.__exit__(), view.stop(), and thread-pool cleanup run during context unwinding..script/identification/fit_gravity_torque.py-483-485 (1)
483-485: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win避免生成不符合 JSON 标准的
NaN和Infinity。
r2和design_condition会被显式设置为非有限值,而json.dumps()默认将其写成NaN/Infinity,严格 JSON 解析器将拒绝该输出。请将非有限值转换为null,并启用allow_nan=False。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_gravity_torque.py around lines 483 - 485, Update the JSON output block for args.json_output so non-finite values in payload, including r2 and design_condition, are recursively converted to null before serialization, and configure json.dumps with allow_nan=False. Preserve the existing indentation, newline, directory creation, and output path behavior..script/identification/fit_gravity_torque.py-183-195 (1)
183-195: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win在拟合前拒绝非有限样本。
angle或value为NaN/Infinity时,Line 198 的奇异性检查也会被绕过,最终仍输出全为NaN的建议参数。请在累加回归量之前验证或过滤样本。建议修复
for angle, value in samples: + if not math.isfinite(angle) or not math.isfinite(value):+ raise ValueError(+ f"Non-finite sample for {signal_name}: angle={angle}, value={value}"+ ) wrapped_angle = wrap_to_pi(angle)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_gravity_torque.py around lines 183 - 195, 在处理 samples 的循环中,使用 math.isfinite 验证 angle 和 value,拒绝或过滤任一非有限的样本;验证必须发生在 wrap_to_pi 及回归量累加之前。确保后续拟合仅使用有限数据,并保留现有奇异性检查和参数输出流程。rmcs_ws/src/rmcs_utility/include/rmcs_utility/rclcpp/node_mixin.hpp-1-3 (1)
1-3: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win补全这个公共头文件的直接依赖。 这里直接使用了
std::convertible_to、std::forward、std::string、std::runtime_error和RCLCPP_*,但只包含了<format>;依赖传递包含会让包含顺序变成隐式前提,容易在别处直接编译失败。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_utility/include/rmcs_utility/rclcpp/node_mixin.hpp` around lines 1 - 3, 补全 node_mixin.hpp 的直接依赖:根据其中使用的 std::convertible_to、std::forward、std::string、std::runtime_error 及 RCLCPP_* 宏,显式加入对应的标准库和 ROS 2 日志头文件;保留现有 <format>,避免依赖其他头文件的传递包含。rmcs_ws/src/rmcs_utility/include/rmcs_utility/csv_writer.hpp-40-60 (1)
40-60: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift不要静默忽略 CSV 写入失败
open()会在打开失败时抛错,但write_row()、flush()和close()都只调用stream_ << .../flush(),没有检查fail()/bad(),也没有启用异常。磁盘满、权限变化或 I/O 故障时,调用方仍会把写入当成成功,最终留下截断 CSV。建议让这些接口在失败时抛出或返回状态,并同步调整调用方的错误处理。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_utility/include/rmcs_utility/csv_writer.hpp` around lines 40 - 60, Update CsvWriter’s write_row, flush, and close methods to detect stream failures after writing, flushing, or closing and propagate them through exceptions or status returns, consistently with open(). Adjust their callers to handle the propagated failure so CSV I/O errors are not treated as successful writes.rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp-608-637 (1)
608-637: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift关节在线状态缺少新鲜度语义。 两个实现都将“曾经收到过反馈”当作“当前反馈有效”,导致断联后继续发布陈旧底盘几何数据。
rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp#L608-L637:记录每个关节的最后接收时间,超时后输出 NaN 并回退默认半径。rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpp#L430-L459:应用相同超时策略,避免断联后永久使用最后一帧。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp` around lines 608 - 637, Update process_chassis_can_receive_ and update_joint_physical_feedback_ in rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp (lines 608-637) to record each joint’s latest feedback timestamp, treat feedback as invalid after the defined timeout, output NaN, and fall back to the default radius. Apply the same freshness and timeout behavior in rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpp (lines 430-459), ensuring disconnected joints no longer use stale feedback.rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp-748-763 (1)
748-763: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win将 supercap 接收标志与有效帧绑定。 两个实现都会在
store_status()拒绝短帧后仍置位接收标志,进而更新陈旧状态。
rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp#L748-L763:仅对有效 8 字节帧保存原始数据、调用store_status()并置位。rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpp#L570-L585:应用相同条件,保证接收标志代表已接受的有效状态。Based on learnings,
store_status()的帧长校验应由设备类负责,但附加状态必须保持相同的接受语义。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp` around lines 748 - 763, 将两个文件中的 supercap 接收处理统一为仅在 8 字节有效帧时保存 latest_supercap_status_、调用 supercap_.store_status() 并置位 supercap_status_received_:更新 deformable-infantry-omni-b.cpp#L748-L763 和 deformable-infantry-omni.cpp#L570-L585 的对应逻辑;保留 CAN ID 0x300 判断,并确保短帧不会更新任何附加状态。Source: Learnings
rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp-412-424 (1)
412-424: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win补上 scope 电机的 CAN 命令和反馈分派。
gimbal_scope_motor_被配置并周期更新,但 CAN2 的第四槽仍是填充值,接收端也未处理其0x204反馈,因此该电机始终无法控制或更新状态。建议修复
device::CanPacket8{ gimbal_friction_wheels_[4].generate_command(), gimbal_friction_wheels_[5].generate_command(), putter_motor_.generate_command(), - device::CanPacket8::PaddingQuarter{},+ gimbal_scope_motor_.generate_command(), }if (can_id == 0x203) { putter_motor_.store_status(data.can_data); + } else if (can_id == 0x204) {+ gimbal_scope_motor_.store_status(data.can_data); } else if (can_id == 0x201) {Also applies to: 470-480
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp` around lines 412 - 424, 在 CAN2 的发送与接收处理路径中补全 gimbal_scope_motor_:将 CAN2 第四槽的 PaddingQuarter 替换为 gimbal_scope_motor_.generate_command(),并在接收分派逻辑中增加对 CAN ID 0x204 的处理,将反馈交给该电机更新状态;保持现有其他电机的命令和反馈处理不变。rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_mode.hpp-61-63 (1)
61-63: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win复位时保留配置的主动悬架基准角。
构造时读取的
active_suspension_base_angle在首次reset()后被覆盖为max_angle_,导致安全复位前后姿态配置不一致。请保存初始配置值并恢复该值,而不是固定恢复最大角。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_mode.hpp` around lines 61 - 63, Update reset handling around active_suspension_base_angle_ to preserve the value loaded during construction instead of assigning max_angle_. Store the initial configured angle and restore it during reset, while keeping current_target_angle_ and joint_current_target_angle_ reset behavior unchanged.rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_controller.cpp-200-211 (1)
200-211: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win使用本周期平移速度计算 ALIGNMENT。
这里读取
chassis_control_velocity_时,Line 142 尚未写入本周期的translational_velocity,因此实际使用上一周期值;复位后的首周期还可能把 NaN 送入 PID。请像 Hero 控制器一样把本周期平移速度作为参数传入。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_controller.cpp` around lines 200 - 211, Update the alignment calculation in the chassis controller to use the current cycle’s translational velocity produced at the earlier control update, rather than reading chassis_control_velocity_->vector directly. Pass that current-cycle velocity into the alignment logic like the Hero controller, and ensure the reset’s first cycle cannot propagate NaN into following_velocity_controller_.update.rmcs_ws/src/rmcs_core/src/controller/chassis/hero_chassis_controller.cpp-195-198 (1)
195-198: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win为 SPIN_SLOW 使用独立的低速比例。
SPIN_SLOW与SPIN_FAST当前都输出0.6 * angular_velocity_max,慢速模式没有任何降速效果。请分别设置比例,例如与通用底盘控制器一致使用 0.3/0.6。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/hero_chassis_controller.cpp` around lines 195 - 198, 为 SPIN_SLOW 和 SPIN_FAST 拆分独立处理,修改底盘控制器中对应的 angular_velocity 计算:SPIN_SLOW 使用 0.3 倍 angular_velocity_max,SPIN_FAST 保持 0.6 倍,并保留 spinning_forward_ 对方向的控制。rmcs_ws/src/rmcs_core/src/controller/chassis/hero_chassis_controller.cpp-192-192 (1)
192-192: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win不要清零 AUTO 跟随控制结果。
该赋值完全覆盖 Line 182-190 计算的跟随角速度,使 AUTO 模式永久不旋转。请删除此行,或用明确配置开关表达禁用需求。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/hero_chassis_controller.cpp` at line 192, Remove the unconditional angular_velocity reset in the AUTO-follow control path after the calculation in the surrounding logic, so the computed follow angular velocity is preserved. If disabling rotation is required, gate it behind an explicit configuration switch rather than overwriting the result unconditionally.rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_power_controller.cpp-137-137 (1)
137-137: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift不要向底盘和攀爬器重复分配完整功率预算。
轮组控制器和前攀爬限功率器都独立获得同一个
power_limit。在 APPROACH/SUPPORT_RETRACT 同时驱动底盘与履带时,两者合计功率可明显超过总预算。请基于攀爬活跃状态和需求估算拆分预算,而不是复制上限。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_power_controller.cpp` at line 137, 在底盘功率控制逻辑中更新 control_power_limit_ 的分配,避免底盘与前攀爬限功率器同时复用完整的 power_limit。基于攀爬活跃状态及其功率需求估算,在 APPROACH/SUPPORT_RETRACT 等并行驱动场景拆分总预算,并确保底盘与攀爬器的分配合计不超过 power_limit;非攀爬场景保持完整预算分配。rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp-120-126 (1)
120-126: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win让
preloaded_ready_始终由当前状态派生。正常进入
PRELOADED时不会置true,离开预装状态时也可能保留旧值。请在状态切换函数或每个更新周期统一设置:
putter_initialized && shoot_stage_ == PRELOADED && bullet_feeder_reverse_end_ == 0。Also applies to: 250-263
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp` around lines 120 - 126, Update the preloaded_ready_ assignment in the shooting controller’s state-update logic, including the corresponding block around the additional reported location, so it is always derived from putter_initialized, shoot_stage_ == ShootStage::PRELOADED, and bullet_feeder_reverse_end_ == 0 on every update or state transition. Remove the existing condition that omits putter_initialized and only updates readiness in the reverse-end case, ensuring the value is reset whenever any required condition is no longer met.rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp-184-203 (1)
184-203: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win恢复正常射击完成检测,不要把机械卡死作为唯一完成条件。
bullet_fired_和推杆行程检测均被注释,现在只有连续低速 50 个周期才设置shooted。正常运动时推杆会持续以目标速度前进直到卡死。请恢复传感器/行程判定,并为推进阶段增加独立超时;卡滞检测只能作为故障回退。Also applies to: 285-303
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp` around lines 184 - 203, 恢复 shooting 控制流程中的正常完成判定:在推进阶段重新启用 bullet_fired_ 传感器和 putter_angle_ 相对 putter_startpoint/putter_stroke_ 的行程检测,满足任一条件即可设置 shooted。为推进阶段增加独立超时保护;保留 update_putter_jam_detection() 仅作为卡滞故障回退,不要让连续低速卡滞检测成为唯一完成条件,并同步修改对应的返回/推进逻辑块。rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_controller.cpp-154-160 (1)
154-160: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win持续同步 TD 状态,避免速度输入失效时目标跳变。
外部
setpoint_velocity有效期间完全跳过td_.update();若该输入随后变为 NaN,TD 会从旧状态恢复,参考角度可能突然回跳。请每周期推进 TD,仅在选择参考速度/角度时决定是否采用 TD 输出。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_controller.cpp` around lines 154 - 160, 在控制周期中始终调用 deformable joint controller 的 td_.update() 推进 TD 状态,不要仅在 setpoint_velocity 非有限时调用。保留有效速度输入时采用 inputs.setpoint_angle 和 inputs.setpoint_velocity;仅当速度无效时改用本周期 td_.update() 返回的 x1、x2 作为 reference_angle 和 reference_velocity,避免 TD 状态滞后导致目标跳变。rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_controller.cpp-117-120 (1)
117-120: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win将导航模式覆盖移出手动模式切换条件。
左开关为
DOWN时,导航平移命令仍在 Line 149 生效,但 Line 117 的行为模式不会更新,可能出现导航平移叠加旧SPIN_FAST/STEP_DOWN角速度控制。导航速度与navigation_chassis_behavior_应原子接管。Also applies to: 149-153
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_controller.cpp` around lines 117 - 120, 将 navigation_chassis_behavior_ 的模式覆盖逻辑移出手动模式切换条件,确保在 navigation_enable_control_ 开启且 navigation_command_velocity_ 有效时,无论左开关状态如何,都与导航速度一起生效。同步调整相关 Line 149-153 的导航速度处理,使导航速度与行为模式原子接管,避免残留 SPIN_FAST/STEP_DOWN 角速度控制。rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_power_controller.cpp-114-115 (1)
114-115: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win避免用无穷大参与超级电容插值。
当电压不高于
supercap_voltage_base_line时,后续表达式会计算(inf - referee) * 0,结果为 NaN;虚拟缓冲比例为零时也存在同样问题。请改用有限的最大 boost 值,或为无限功率模式单独分支。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_power_controller.cpp` around lines 114 - 115, 更新底盘功率控制器中计算 power_limit 的逻辑,避免将 inf_ 传入后续超级电容插值;对 rmcs_msgs::need_power(*mode_) 为真的无限功率模式增加独立分支,或改用有限的最大 boost 值,并确保 supercap_voltage_base_line 以下及虚拟缓冲比例为零时不会产生 NaN。rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_suspension.cpp-75-82 (1)
75-82: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift为主动悬架增加 IMU 失效保护。
缺失 IMU 被伪装成零姿态;运行期出现 NaN 时又只清空目标/PID,之前的
correction_state_rad_仍会叠加到关节目标。请在姿态输入缺失或非有限时禁用主动补偿,并将现有修正安全回零或输出 NaN。Also applies to: 111-120, 458-460
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_suspension.cpp` around lines 75 - 82, 为主动悬架补充 IMU 失效保护:在 chassis_imu_pitch_、chassis_imu_roll_ 及其速率输入缺失或出现非有限值时,禁用主动补偿,不要将缺失输入伪装成有效零姿态。更新现有运行期异常处理逻辑,除清空目标/PID 外,同时将 correction_state_rad_ 安全回零或输出 NaN,确保其不会继续叠加到关节目标。rmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw_solver.hpp-145-149 (1)
145-149: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift无效 TF 不应回退为单位 X 轴继续闭环。
两个位置都会将零范数或非有限变换结果转换为
UnitX,从而把无效姿态伪装为有效零姿态。
rmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw_solver.hpp#L145-L149:让归一化失败返回无效状态,禁止AutoAim设置enabled_。rmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw.cpp#L286-L307:检测无效方向并进入enter_disabled_state(),不要生成零角度控制误差。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw_solver.hpp` around lines 145 - 149, 无效 TF 不应被伪装成 UnitX 继续闭环。更新 eccentric_dual_yaw_solver.hpp 的 normalize,使零范数或非有限输入返回可识别的无效状态,并阻止 AutoAim 设置 enabled_;同时在 eccentric_dual_yaw.cpp 的相关方向处理处检测无效结果,调用 enter_disabled_state(),不要生成零角度控制误差。rmcs_ws/src/rmcs_core/src/controller/gimbal/dual_yaw_controller.cpp-203-218 (1)
203-218: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win为制动接合阶段增加故障退出。
该状态会持续施加
kYawBrakeEngageTorque,只有速度连续低于阈值才退出。若速度为 NaN、传感器离线或制动器卡滞,扭矩将无限期保持;释放阶段已有超时保护,接合阶段也应校验有限性并设置超时。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/gimbal/dual_yaw_controller.cpp` around lines 203 - 218, 在 EncoderState::EngageYawBrake 状态处理中增加故障退出:校验 yaw_brake_velocity_ 为有限值,并为持续施加 kYawBrakeEngageTorque 的接合过程增加超时计数;当速度为 NaN/无穷、传感器无效或超过接合超时时,停止接合扭矩并转入现有安全故障处理路径,同时保留正常的低速确认逻辑。rmcs_ws/src/rmcs_core/src/controller/gimbal/deformable_infantry_gimbal_controller.cpp-220-225 (1)
220-225: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win不要在 ctrl-hold 中禁用重力前馈。
update_ctrl_hold_control()会加入该函数的结果,但ctrl_hold_active_为真时这里固定返回零,导致配置的重力补偿在保持模式下完全失效。建议修复
auto pitch_gravity_feedforward() const -> double { - if (ctrl_hold_active_)- return 0.0; if (!input_.pitch_angle.ready() || !std::isfinite(*input_.pitch_angle)) return 0.0;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/controller/gimbal/deformable_infantry_gimbal_controller.cpp` around lines 220 - 225, 移除 pitch_gravity_feedforward() 中对 ctrl_hold_active_ 的提前返回,确保 update_ctrl_hold_control() 在保持模式下仍使用配置的重力前馈;保留输入未就绪或非有限时返回零的校验逻辑。rmcs_ws/src/rmcs_core/src/referee/app/ui/auto_aim.cpp-66-72 (1)
66-72: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win改用有界格式化,避免缓冲区越界
std::format_to(text.begin(), ...)没有容量边界;distance只要是较大的有限值,就可能把这个 30 字节的缓冲区写穿,导致未定义行为。改成std::format_to_n(text.begin(), text.size() - 1, "{:.1f}m", distance),然后补上'\0'。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/referee/app/ui/auto_aim.cpp` around lines 66 - 72, 在 target_distance_text_ 的格式化逻辑中,将无界的 std::format_to 调整为以 text.size() - 1 为上限的 std::format_to_n,避免写入超过缓冲区;格式字符串移除显式的 "\0",并在格式化后为剩余位置补上 '\0',确保 target_distance_indicator_.set_value(text.data()) 使用有效的空终止字符串。
🟡 Minor comments (4)
rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp-5-10 (1)
5-10: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win补上缺失的标准库头文件
rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp直接包含<string_view>和<ctime>。rmcs_ws/src/rmcs_core/src/identification/swept_frequency_controller.cpp直接包含<string_view>。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp` around lines 5 - 10, 补上缺失的标准库头文件:在 rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp 的包含列表中直接加入 <string_view> 和 <ctime>;在 rmcs_ws/src/rmcs_core/src/identification/swept_frequency_controller.cpp 的包含列表中直接加入 <string_view>,无需修改其他逻辑。.script/identification/fit_friction_velocity_pid.py-137-146 (1)
137-146: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win只要求实际选择的输入信号列。
当前无条件要求
torque和control_torque,因此只有所选输入列的合法 CSV 仍会被拒绝;另一列后续并未读取。建议修复
-def require_columns(fieldnames: list[str], target: str) -> dict[str, str]:+def require_columns(+ fieldnames: list[str], target: str, input_signal: str+) -> dict[str, str]: columns = { ... } - missing = [value for value in columns.values() if value not in fieldnames]+ required = ("elapsed_s", "velocity", input_signal)+ missing = [columns[name] for name in required if columns[name] not in fieldnames]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.script/identification/fit_friction_velocity_pid.py around lines 137 - 146, 修改 require_columns,仅将 elapsed_s 和当前实际选择的输入信号列加入必需列校验;不要无条件要求 torque 与 control_torque。根据现有调用方传入的选择复用对应列映射,并保持返回字典与后续读取逻辑兼容。rmcs_ws/src/rmcs_core/src/hardware/sentry.cpp-383-386 (1)
383-386: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win在调用
asin前夹紧四元数计算结果。浮点误差可能使该值略微超出
[-1, 1],导致/chassis/pitch_imu变为 NaN,并中断攀爬控制判断。建议修复
- *chassis_pitch_imu_ = -std::asin(2.0 * (q.w() * q.y() - q.z() * q.x()));+ const auto sin_pitch =+ std::clamp(2.0 * (q.w() * q.y() - q.z() * q.x()), -1.0, 1.0);+ *chassis_pitch_imu_ = -std::asin(sin_pitch);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/hardware/sentry.cpp` around lines 383 - 386, 在更新 chassis_pitch_imu_ 的逻辑中,先对由四元数 q 计算出的 asin 输入值夹紧到 [-1, 1],再传入 std::asin,避免浮点误差导致 NaN。保持现有负号、姿态计算和 chassis_yaw_velocity_imu_ 更新行为不变。rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp-324-331 (1)
324-331: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win添加边界条件防御,避免
std::clamp未定义行为与除零异常。
std::clamp函数要求其边界参数必须满足min <= max(即cutoff_voltage <= full_voltage)。如果由于配置失误或其他异常导致full_voltage <= cutoff_voltage,不仅会触发std::clamp的未定义行为,还会在后续计算中导致denominator等于或小于 0,引发除零异常(NaN)或反向进度显示。建议添加安全返回以防御此类问题。🛡️ 建议的防御性代码
static constexpr double calculate_energy_angle(double value, double cutoff_voltage, double full_voltage) { + if (full_voltage <= cutoff_voltage)+ return 0.0; const double clamped_value = std::clamp(value, cutoff_voltage, full_voltage); const double numerator = clamped_value * clamped_value - cutoff_voltage * cutoff_voltage; const double denominator = full_voltage * full_voltage - cutoff_voltage * cutoff_voltage; return visible_angle * numerator / denominator; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp` around lines 324 - 331, Update calculate_energy_angle to validate that full_voltage is strictly greater than cutoff_voltage before calling std::clamp or computing the denominator; return the safe zero-angle result for invalid voltage ranges, while preserving the existing calculation for valid ranges.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@rmcs_ws/src/rmcs_core/src/controller/shooting/hero_friction_wheel_controller.cpp`:
- Around line 183-189: 修正 detect_friction_faulty()
的返回逻辑:当任一摩擦轮实际转速绝对值低于对应控制速度绝对值的 50% 时返回 true;遍历完成且未检测到该故障时返回 false。
In `@rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp`:
- Around line 41-43: 在 ValueCollector 的参数初始化流程中校验 write_interval_ 和
flush_interval_ 必须为正数,再进入后续取模逻辑;拒绝或替换 0 及负值,确保相关执行路径不会发生除零。
In `@rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp`:
- Around line 444-480: 在 can_receive_callback 中先校验 CAN ID,再更新 can0_detect 和
friciton_detect,确保仅处理 0x141–0x143 及对应摩擦轮 ID 范围,避免减法索引越界,并将检测数组零初始化;同时在同文件
806-825 行的 check 相关回调中,仅当 CAN ID 属于 check 覆盖的设备集合后再更新索引。
---
Outside diff comments:
In `@rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp`:
- Around line 229-248: 在 reset_all_controls() 中补充完整清理射击状态:重置
shooted、shoot_first、preloaded_ready_、putter_timeout_count_、locked_detect_count_、bullet_feeder_reverse_end_
以及点击计数,使用各字段现有的默认/初始值。保留现有控制器、PID、扭矩和 shoot_stage_ 的复位逻辑,确保断连恢复后不会沿用旧状态。
---
Major comments:
In @.script/identification/fit_friction_velocity_pid.py:
- Around line 189-196: Validate sampling uniformity in both sites:
.script/identification/fit_friction_velocity_pid.py lines 189-196 and
.script/identification/fit_sweep_graybox.py lines 785-792. Before using fixed
dt, verify every elapsed-time difference is finite and positive, then reject the
data or resample when timing jitter exceeds the accepted threshold. Apply the
same validation before constructing the Savitzky-Golay basis and ODE segments in
fit_sweep_graybox.py, while preserving the existing valid-dt calculation and
downstream processing.
- Around line 256-262: 在计算 wc 和 PID 增益前,于 fc_hz 参数解析后的流程中校验 fc_hz 必须为有限正数,拒绝
NaN、无穷值和小于等于零的值;对无效输入抛出清晰的参数错误,并确保不会继续生成或写入无效增益。使用现有的 fc_hz、default_fc_hz
和参数处理符号完成校验。
In @.script/identification/fit_gravity_torque.py:
- Around line 483-485: Update the JSON output block for args.json_output so
non-finite values in payload, including r2 and design_condition, are recursively
converted to null before serialization, and configure json.dumps with
allow_nan=False. Preserve the existing indentation, newline, directory creation,
and output path behavior.
- Around line 183-195: 在处理 samples 的循环中,使用 math.isfinite 验证 angle 和
value,拒绝或过滤任一非有限的样本;验证必须发生在 wrap_to_pi 及回归量累加之前。确保后续拟合仅使用有限数据,并保留现有奇异性检查和参数输出流程。
In @.script/identification/fit_sweep_graybox.py:
- Around line 937-959: Update the JSON payload construction around the
shooting_window and design_condition fields so non-finite floating-point values
are converted to None before serialization, producing JSON null; preserve finite
values unchanged. Include the relevant design_condition value in the payload if
it is currently emitted, and serialize with json.dumps(..., allow_nan=False) to
reject any remaining NaN or Infinity values.
- Around line 924-935: Update the result-reporting flow after print_warnings()
so Suggested params and nuisance parameters are printed only when optimization
succeeds and the fitted values are physical: J > 0, B >= 0, and Fc >= 0. For
optimization failure or any invalid fit, skip those parameter outputs and return
a nonzero exit status from the surrounding entry-point function.
- Around line 776-813: 在执行 savitzky_golay 和 np.unwrap 之前,更新当前数据预处理流程,显式检查
elapsed、angle、velocity、control_torque 和 measured_torque 中的非有限值,并拒绝包含 NaN/Inf
的行;随后仅使用剩余有效样本继续窗口长度、滤波、unwrap 和拟合逻辑,保留现有“样本过少”错误处理。
In @.script/rmcs-cli:
- Around line 86-102: 更新 workflow 中的构建等待逻辑,生成每次构建唯一的 marker,并将带退出码的 marker 命令追加到
send_pane(_pane_build, ...);循环仅匹配本次
marker,解析退出码后判断构建成功或失败。为等待循环增加超时,避免命令无标记退出时永久阻塞,并移除对残留 “Summary:”/“failed”
文本的判断。
In @.script/scan-remote:
- Around line 60-85: Replace the os._exit() calls in RawTerminal.read_key and
RawTerminal._read_escape with the existing or an appropriate cancellation
exception, allowing the top-level caller to handle cancellation. Preserve the
current q/Escape cancellation behavior while ensuring RawTerminal.__exit__(),
view.stop(), and thread-pool cleanup run during context unwinding.
In `@rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_controller.cpp`:
- Around line 200-211: Update the alignment calculation in the chassis
controller to use the current cycle’s translational velocity produced at the
earlier control update, rather than reading chassis_control_velocity_->vector
directly. Pass that current-cycle velocity into the alignment logic like the
Hero controller, and ensure the reset’s first cycle cannot propagate NaN into
following_velocity_controller_.update.
- Around line 117-120: 将 navigation_chassis_behavior_ 的模式覆盖逻辑移出手动模式切换条件,确保在
navigation_enable_control_ 开启且 navigation_command_velocity_
有效时,无论左开关状态如何,都与导航速度一起生效。同步调整相关 Line 149-153 的导航速度处理,使导航速度与行为模式原子接管,避免残留
SPIN_FAST/STEP_DOWN 角速度控制。
In `@rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_power_controller.cpp`:
- Line 137: 在底盘功率控制逻辑中更新 control_power_limit_ 的分配,避免底盘与前攀爬限功率器同时复用完整的
power_limit。基于攀爬活跃状态及其功率需求估算,在 APPROACH/SUPPORT_RETRACT
等并行驱动场景拆分总预算,并确保底盘与攀爬器的分配合计不超过 power_limit;非攀爬场景保持完整预算分配。
- Around line 114-115: 更新底盘功率控制器中计算 power_limit 的逻辑,避免将 inf_ 传入后续超级电容插值;对
rmcs_msgs::need_power(*mode_) 为真的无限功率模式增加独立分支,或改用有限的最大 boost 值,并确保
supercap_voltage_base_line 以下及虚拟缓冲比例为零时不会产生 NaN。
In
`@rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_controller.cpp`:
- Around line 154-160: 在控制周期中始终调用 deformable joint controller 的 td_.update() 推进
TD 状态,不要仅在 setpoint_velocity 非有限时调用。保留有效速度输入时采用 inputs.setpoint_angle 和
inputs.setpoint_velocity;仅当速度无效时改用本周期 td_.update() 返回的 x1、x2 作为 reference_angle
和 reference_velocity,避免 TD 状态滞后导致目标跳变。
In `@rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_mode.hpp`:
- Around line 61-63: Update reset handling around active_suspension_base_angle_
to preserve the value loaded during construction instead of assigning
max_angle_. Store the initial configured angle and restore it during reset,
while keeping current_target_angle_ and joint_current_target_angle_ reset
behavior unchanged.
In `@rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_suspension.cpp`:
- Around line 75-82: 为主动悬架补充 IMU 失效保护:在 chassis_imu_pitch_、chassis_imu_roll_
及其速率输入缺失或出现非有限值时,禁用主动补偿,不要将缺失输入伪装成有效零姿态。更新现有运行期异常处理逻辑,除清空目标/PID 外,同时将
correction_state_rad_ 安全回零或输出 NaN,确保其不会继续叠加到关节目标。
In `@rmcs_ws/src/rmcs_core/src/controller/chassis/hero_chassis_controller.cpp`:
- Around line 195-198: 为 SPIN_SLOW 和 SPIN_FAST 拆分独立处理,修改底盘控制器中对应的
angular_velocity 计算:SPIN_SLOW 使用 0.3 倍 angular_velocity_max,SPIN_FAST 保持 0.6
倍,并保留 spinning_forward_ 对方向的控制。
- Line 192: Remove the unconditional angular_velocity reset in the AUTO-follow
control path after the calculation in the surrounding logic, so the computed
follow angular velocity is preserved. If disabling rotation is required, gate it
behind an explicit configuration switch rather than overwriting the result
unconditionally.
In
`@rmcs_ws/src/rmcs_core/src/controller/gimbal/deformable_infantry_gimbal_controller.cpp`:
- Around line 220-225: 移除 pitch_gravity_feedforward() 中对 ctrl_hold_active_
的提前返回,确保 update_ctrl_hold_control() 在保持模式下仍使用配置的重力前馈;保留输入未就绪或非有限时返回零的校验逻辑。
In `@rmcs_ws/src/rmcs_core/src/controller/gimbal/dual_yaw_controller.cpp`:
- Around line 203-218: 在 EncoderState::EngageYawBrake 状态处理中增加故障退出:校验
yaw_brake_velocity_ 为有限值,并为持续施加 kYawBrakeEngageTorque 的接合过程增加超时计数;当速度为
NaN/无穷、传感器无效或超过接合超时时,停止接合扭矩并转入现有安全故障处理路径,同时保留正常的低速确认逻辑。
In `@rmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw_solver.hpp`:
- Around line 145-149: 无效 TF 不应被伪装成 UnitX 继续闭环。更新 eccentric_dual_yaw_solver.hpp
的 normalize,使零范数或非有限输入返回可识别的无效状态,并阻止 AutoAim 设置 enabled_;同时在
eccentric_dual_yaw.cpp 的相关方向处理处检测无效结果,调用 enter_disabled_state(),不要生成零角度控制误差。
In `@rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp`:
- Around line 120-126: Update the preloaded_ready_ assignment in the shooting
controller’s state-update logic, including the corresponding block around the
additional reported location, so it is always derived from putter_initialized,
shoot_stage_ == ShootStage::PRELOADED, and bullet_feeder_reverse_end_ == 0 on
every update or state transition. Remove the existing condition that omits
putter_initialized and only updates readiness in the reverse-end case, ensuring
the value is reset whenever any required condition is no longer met.
- Around line 184-203: 恢复 shooting 控制流程中的正常完成判定:在推进阶段重新启用 bullet_fired_ 传感器和
putter_angle_ 相对 putter_startpoint/putter_stroke_ 的行程检测,满足任一条件即可设置
shooted。为推进阶段增加独立超时保护;保留 update_putter_jam_detection()
仅作为卡滞故障回退,不要让连续低速卡滞检测成为唯一完成条件,并同步修改对应的返回/推进逻辑块。
In `@rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp`:
- Around line 608-637: Update process_chassis_can_receive_ and
update_joint_physical_feedback_ in
rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp (lines
608-637) to record each joint’s latest feedback timestamp, treat feedback as
invalid after the defined timeout, output NaN, and fall back to the default
radius. Apply the same freshness and timeout behavior in
rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpp (lines 430-459),
ensuring disconnected joints no longer use stale feedback.
- Around line 748-763: 将两个文件中的 supercap 接收处理统一为仅在 8 字节有效帧时保存
latest_supercap_status_、调用 supercap_.store_status() 并置位
supercap_status_received_:更新 deformable-infantry-omni-b.cpp#L748-L763 和
deformable-infantry-omni.cpp#L570-L585 的对应逻辑;保留 CAN ID 0x300 判断,并确保短帧不会更新任何附加状态。
In `@rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp`:
- Around line 412-424: 在 CAN2 的发送与接收处理路径中补全 gimbal_scope_motor_:将 CAN2 第四槽的
PaddingQuarter 替换为 gimbal_scope_motor_.generate_command(),并在接收分派逻辑中增加对 CAN ID
0x204 的处理,将反馈交给该电机更新状态;保持现有其他电机的命令和反馈处理不变。
In `@rmcs_ws/src/rmcs_core/src/identification/static_torque_test_controller.cpp`:
- Around line 176-181: 在 `remote_mode` 切换进入 `RemoteMode::kMeasureRange` 时,利用
`mode_changed` 重置 `range_initialized_`
及其关联的机械范围边界,使新测量会话从空范围开始;保持同一测量模式持续运行时的范围累积行为不变,并确保后续中心点和测试边界使用本次会话数据。
In `@rmcs_ws/src/rmcs_core/src/referee/app/ui/auto_aim.cpp`:
- Around line 66-72: 在 target_distance_text_ 的格式化逻辑中,将无界的 std::format_to 调整为以
text.size() - 1 为上限的 std::format_to_n,避免写入超过缓冲区;格式字符串移除显式的 "\0",并在格式化后为剩余位置补上
'\0',确保 target_distance_indicator_.set_value(text.data()) 使用有效的空终止字符串。
In `@rmcs_ws/src/rmcs_utility/include/rmcs_utility/csv_writer.hpp`:
- Around line 40-60: Update CsvWriter’s write_row, flush, and close methods to
detect stream failures after writing, flushing, or closing and propagate them
through exceptions or status returns, consistently with open(). Adjust their
callers to handle the propagated failure so CSV I/O errors are not treated as
successful writes.
In `@rmcs_ws/src/rmcs_utility/include/rmcs_utility/rclcpp/node_mixin.hpp`:
- Around line 1-3: 补全 node_mixin.hpp 的直接依赖:根据其中使用的
std::convertible_to、std::forward、std::string、std::runtime_error 及 RCLCPP_*
宏,显式加入对应的标准库和 ROS 2 日志头文件;保留现有 <format>,避免依赖其他头文件的传递包含。
---
Minor comments:
In @.script/identification/fit_friction_velocity_pid.py:
- Around line 137-146: 修改 require_columns,仅将 elapsed_s
和当前实际选择的输入信号列加入必需列校验;不要无条件要求 torque 与
control_torque。根据现有调用方传入的选择复用对应列映射,并保持返回字典与后续读取逻辑兼容。
In `@rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp`:
- Around line 5-10: 补上缺失的标准库头文件:在
rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp 的包含列表中直接加入 <string_view> 和
<ctime>;在
rmcs_ws/src/rmcs_core/src/identification/swept_frequency_controller.cpp
的包含列表中直接加入 <string_view>,无需修改其他逻辑。
In `@rmcs_ws/src/rmcs_core/src/hardware/sentry.cpp`:
- Around line 383-386: 在更新 chassis_pitch_imu_ 的逻辑中,先对由四元数 q 计算出的 asin 输入值夹紧到
[-1, 1],再传入 std::asin,避免浮点误差导致 NaN。保持现有负号、姿态计算和 chassis_yaw_velocity_imu_
更新行为不变。
In `@rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp`:
- Around line 324-331: Update calculate_energy_angle to validate that
full_voltage is strictly greater than cutoff_voltage before calling std::clamp
or computing the denominator; return the safe zero-angle result for invalid
voltage ranges, while preserving the existing calculation for valid ranges.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7197d5cc-9145-4f2f-8a5e-f5716e01593f
📒 Files selected for processing (76)
.gitmodules.script/autoaim-debug.script/complete/_local-context.script/complete/_remote-context.script/host/rmcs.script/identification/fit_friction_velocity_pid.py.script/identification/fit_gravity_torque.py.script/identification/fit_sweep_graybox.py.script/local-context.script/remote-context.script/remote-status.script/rmcs-cli.script/scan-remotermcs_ws/src/rmcs_auto_aim_v2rmcs_ws/src/rmcs_bringup/config/auto_aim_test.yamlrmcs_ws/src/rmcs_bringup/config/deformable-infantry-omni-b.yamlrmcs_ws/src/rmcs_bringup/config/deformable-infantry-omni.yamlrmcs_ws/src/rmcs_bringup/config/sentry.yamlrmcs_ws/src/rmcs_bringup/config/steering-hero-little-six-friction.yamlrmcs_ws/src/rmcs_bringup/config/steering-hero-little.yamlrmcs_ws/src/rmcs_bringup/config/steering-hero.yamlrmcs_ws/src/rmcs_bringup/config/steering-infantry.yamlrmcs_ws/src/rmcs_core/CMakeLists.txtrmcs_ws/src/rmcs_core/plugins.xmlrmcs_ws/src/rmcs_core/src/controller/chassis/chassis_climber_controller.cpprmcs_ws/src/rmcs_core/src/controller/chassis/chassis_controller.cpprmcs_ws/src/rmcs_core/src/controller/chassis/chassis_power_controller.cpprmcs_ws/src/rmcs_core/src/controller/chassis/deformable_chassis.cpprmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_controller.cpprmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_layer.hpprmcs_ws/src/rmcs_core/src/controller/chassis/deformable_mode.hpprmcs_ws/src/rmcs_core/src/controller/chassis/deformable_omni_wheel_controller.cpprmcs_ws/src/rmcs_core/src/controller/chassis/deformable_suspension.cpprmcs_ws/src/rmcs_core/src/controller/chassis/deformable_wheel_controller.cpprmcs_ws/src/rmcs_core/src/controller/chassis/hero_chassis_controller.cpprmcs_ws/src/rmcs_core/src/controller/gimbal/deformable_infantry_gimbal_controller.cpprmcs_ws/src/rmcs_core/src/controller/gimbal/dual_yaw_controller.cpprmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw.cpprmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw_solver.hpprmcs_ws/src/rmcs_core/src/controller/gimbal/hero_gimbal_controller.cpprmcs_ws/src/rmcs_core/src/controller/gimbal/player_viewer.cpprmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpprmcs_ws/src/rmcs_core/src/controller/shooting/friction_wheel_controller.cpprmcs_ws/src/rmcs_core/src/controller/shooting/hero_friction_wheel_controller.cpprmcs_ws/src/rmcs_core/src/controller/shooting/hero_heat_controller.cpprmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpprmcs_ws/src/rmcs_core/src/controller/shooting/shooting_recorder.cpprmcs_ws/src/rmcs_core/src/debug/value_collector.cpprmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpprmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpprmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-steering.cpprmcs_ws/src/rmcs_core/src/hardware/device/dji_motor.hpprmcs_ws/src/rmcs_core/src/hardware/device/lk_motor.hpprmcs_ws/src/rmcs_core/src/hardware/flight.cpprmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpprmcs_ws/src/rmcs_core/src/hardware/sentry.cpprmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpprmcs_ws/src/rmcs_core/src/hardware/steering-hero.cpprmcs_ws/src/rmcs_core/src/hardware/steering-infantry.cpprmcs_ws/src/rmcs_core/src/hardware/util/status_monitor.hpprmcs_ws/src/rmcs_core/src/identification/static_torque_test_controller.cpprmcs_ws/src/rmcs_core/src/identification/swept_frequency_controller.cpprmcs_ws/src/rmcs_core/src/referee/app/ui/auto_aim.cpprmcs_ws/src/rmcs_core/src/referee/app/ui/deformable_infantry_ui.cpprmcs_ws/src/rmcs_core/src/referee/app/ui/hero.cpprmcs_ws/src/rmcs_core/src/referee/app/ui/infantry.cpprmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpprmcs_ws/src/rmcs_core/src/referee/app/ui/widget/animated_toggle.hpprmcs_ws/src/rmcs_core/src/referee/app/ui/widget/crosshair_circle.hpprmcs_ws/src/rmcs_core/src/referee/app/ui/widget/deformable_chassis_top_view.hpprmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpprmcs_ws/src/rmcs_msgs/include/rmcs_msgs/chassis_mode.hpprmcs_ws/src/rmcs_msgs/include/rmcs_msgs/rmcs_msgs.hpprmcs_ws/src/rmcs_utility/include/rmcs_utility/csv_writer.hpprmcs_ws/src/rmcs_utility/include/rmcs_utility/rclcpp/node_mixin.hpprmcs_ws/src/rmcs_utility/include/rmcs_utility/ring_buffer.hpp
💤 Files with no reviewable changes (9)
- rmcs_ws/src/rmcs_bringup/config/steering-hero.yaml
- rmcs_ws/src/rmcs_bringup/config/steering-hero-little.yaml
- rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-steering.cpp
- rmcs_ws/src/rmcs_bringup/config/steering-infantry.yaml
- rmcs_ws/src/rmcs_core/src/hardware/steering-infantry.cpp
- rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp
- rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_layer.hpp
- rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_wheel_controller.cpp
- rmcs_ws/src/rmcs_core/src/hardware/steering-hero.cpp
| bool detect_friction_faulty() { | ||
| for (size_t i = 0; i < friction_count_; i++) { | ||
| if (abs(*friction_velocities_[i]) < abs(*friction_control_velocities_[i] * 0.5)) | ||
| return true; | ||
| return false; | ||
| } | ||
| return false; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
修复故障检测逻辑。
当前代码在满足和不满足异常条件时均返回 false,这会导致摩擦轮的卡弹或故障保护机制彻底失效。当检测到实际转速过低(低于控制目标的 50%)时,应返回 true 以标识存在故障。
🐛 建议的修复
bool detect_friction_faulty() {
for (size_t i = 0; i < friction_count_; i++) {
if (abs(*friction_velocities_[i]) < abs(*friction_control_velocities_[i] * 0.5))
- return false;+ return true;
}
return false;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| booldetect_friction_faulty() { | |
| for (size_t i = 0; i < friction_count_; i++) { | |
| if (abs(*friction_velocities_[i]) < abs(*friction_control_velocities_[i] * 0.5)) | |
| returntrue; | |
| returnfalse; | |
| } | |
| returnfalse; | |
| } | |
| booldetect_friction_faulty() { | |
| for (size_t i = 0; i < friction_count_; i++) { | |
| if (abs(*friction_velocities_[i]) < abs(*friction_control_velocities_[i] * 0.5)) | |
| returntrue; | |
| } | |
| returnfalse; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@rmcs_ws/src/rmcs_core/src/controller/shooting/hero_friction_wheel_controller.cpp`
around lines 183 - 189, 修正 detect_friction_faulty()
的返回逻辑:当任一摩擦轮实际转速绝对值低于对应控制速度绝对值的 50% 时返回 true;遍历完成且未检测到该故障时返回 false。
| node::param("signals", signal_names_); | ||
| node::param("write_interval", write_interval_); | ||
| node::param("flush_interval", flush_interval_); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
写入间隔必须在执行取模前验证为正数。
write_interval_ == 0 或 flush_interval_ == 0 会分别在 Line 87、Line 95 触发除零未定义行为并可能终止进程。
建议修复
+#include <stdexcept>+
node::param("write_interval", write_interval_);
node::param("flush_interval", flush_interval_);
++ if (write_interval_ <= 0)+ throw std::runtime_error("write_interval must be positive");+ if (flush_interval_ <= 0)+ throw std::runtime_error("flush_interval must be positive");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| node::param("signals", signal_names_); | |
| node::param("write_interval", write_interval_); | |
| node::param("flush_interval", flush_interval_); | |
| node::param("signals", signal_names_); | |
| node::param("write_interval", write_interval_); | |
| node::param("flush_interval", flush_interval_); | |
| if (write_interval_ <= 0) | |
| throwstd::runtime_error("write_interval must be positive"); | |
| if (flush_interval_ <= 0) | |
| throwstd::runtime_error("flush_interval must be positive"); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp` around lines 41 - 43, 在
ValueCollector 的参数初始化流程中校验 write_interval_ 和 flush_interval_
必须为正数,再进入后续取模逻辑;拒绝或替换 0 及负值,确保相关执行路径不会发生除零。
| void can_receive_callback(const Spec::Can& can, const View::Can& data) override { | ||
| if (data.is_extended_can_id || data.is_remote_transmission) [[unlikely]] | ||
| return; | ||
| auto can_id = data.can_id; | ||
| // can1_receive_rate_counter_.record(can_id); | ||
| if (can_id == 0x201) { | ||
| gimbal_friction_wheels_[0].store_status(data.can_data); | ||
| } else if (can_id == 0x202) { | ||
| gimbal_friction_wheels_[1].store_status(data.can_data); | ||
| } else if (can_id == 0x203) { | ||
| gimbal_friction_wheels_[2].store_status(data.can_data); | ||
| } else if (can_id == 0x204) { | ||
| gimbal_friction_wheels_[3].store_status(data.can_data); | ||
| } else if (can_id == 0x205) { | ||
| putter_motor_.store_status(data.can_data); | ||
| } else if (can_id == 0x206) { | ||
| gimbal_scope_motor_.store_status(data.can_data); | ||
| if (can == Spec::kCans.kCan0) { | ||
| // can0_receive_rate_counter_.record(can_id); | ||
| can0_detect[can_id - 0x141] = 1; | ||
| if (can_id == 0x141) { | ||
| gimbal_top_yaw_motor_.store_status(data.can_data); | ||
| } else if (can_id == 0x143) { | ||
| gimbal_pitch_motor_.store_status(data.can_data); | ||
| } else if (can_id == 0x142) { | ||
| gimbal_bullet_feeder_.store_status(data.can_data); | ||
| } | ||
| } else if (can == Spec::kCans.kCan1) { | ||
| // can1_receive_rate_counter_.record(can_id); | ||
| friciton_detect[can_id - 0x201] = 1; | ||
| if (can_id == 0x201) { | ||
| gimbal_friction_wheels_[0].store_status(data.can_data); | ||
| } else if (can_id == 0x202) { | ||
| gimbal_friction_wheels_[1].store_status(data.can_data); | ||
| } else if (can_id == 0x203) { | ||
| gimbal_friction_wheels_[2].store_status(data.can_data); | ||
| } else if (can_id == 0x204) { | ||
| gimbal_friction_wheels_[3].store_status(data.can_data); | ||
| } | ||
| } else if (can == Spec::kCans.kCan2) { | ||
| // can2_receive_rate_counter_.record(can_id); | ||
| if (can_id == 0x203) { | ||
| putter_motor_.store_status(data.can_data); | ||
| } else if (can_id == 0x201) { | ||
| gimbal_friction_wheels_[4].store_status(data.can_data); | ||
| friciton_detect[4] = 1; | ||
| } else if (can_id == 0x202) { | ||
| gimbal_friction_wheels_[5].store_status(data.can_data); | ||
| friciton_detect[5] = 1; | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
先验证 CAN ID,再更新接收检测数组。 当前两个回调都在设备分派前用未经约束的 CAN ID 做减法索引,非预期标准帧可导致越界写。
rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp#L444-L480:仅在0x141..0x143或对应摩擦轮 ID 范围内更新数组,并将检测数组零初始化。rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp#L806-L825:仅在确认 ID 属于check所覆盖的设备集合后更新索引。
📍 Affects 1 file
rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp#L444-L480(this comment)rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp#L806-L825
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp`
around lines 444 - 480, 在 can_receive_callback 中先校验 CAN ID,再更新 can0_detect 和
friciton_detect,确保仅处理 0x141–0x143 及对应摩擦轮 ID 范围,避免减法索引越界,并将检测数组零初始化;同时在同文件
806-825 行的 check 相关回调中,仅当 CAN ID 属于 check 覆盖的设备集合后再更新索引。
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
rmcs_ws/src/rmcs_core/src/hardware/device/vt13.hpp (1)
127-156: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win建议为
RemoteControlData增加static_assert(sizeof(...))。
read_remote_control_data依赖sizeof(RemoteControlData)判断帧完整性并决定拷贝长度,而Dr16的各数据段(Dr16DataPart1/2/3)都带有static_assert校验大小。为该结构补充一个尺寸断言可防止位域/[[gnu::packed]]布局静默漂移导致的解析错位。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rmcs_ws/src/rmcs_core/src/hardware/device/vt13.hpp` around lines 127 - 156, 在 RemoteControlData 结构定义附近增加 static_assert(sizeof(RemoteControlData) == 预期帧大小),校验其位域与 [[gnu::packed]] 布局符合 read_remote_control_data 使用的协议尺寸;参照 Dr16DataPart1、Dr16DataPart2 和 Dr16DataPart3 的尺寸断言风格,避免布局变化被静默接受。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rmcs_ws/src/rmcs_core/src/hardware/device/dr16.hpp`:
- Around line 49-58: 在 `store_status()`、`update_status()` 和 `refresh_validity()`
中消除 `valid_` 与时间戳的并发数据竞争:将 `last_remote_control_received_at_`
改为适合原子发布的表示,并在接收回调中原子写入、周期更新中原子读取;移除 `store_status()` 对 `valid_` 的写入,使 `valid_`
仅由更新线程通过 `refresh_validity()` 推导和修改。
---
Nitpick comments:
In `@rmcs_ws/src/rmcs_core/src/hardware/device/vt13.hpp`:
- Around line 127-156: 在 RemoteControlData 结构定义附近增加
static_assert(sizeof(RemoteControlData) == 预期帧大小),校验其位域与 [[gnu::packed]] 布局符合
read_remote_control_data 使用的协议尺寸;参照 Dr16DataPart1、Dr16DataPart2 和 Dr16DataPart3
的尺寸断言风格,避免布局变化被静默接受。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 796a1e5f-13c3-45f0-a6b0-d69840f0a4c8
📒 Files selected for processing (10)
rmcs_ws/src/rmcs_bringup/config/steering-hero-little-six-friction.yamlrmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpprmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpprmcs_ws/src/rmcs_core/src/hardware/device/dr16.hpprmcs_ws/src/rmcs_core/src/hardware/device/remote_control.hpprmcs_ws/src/rmcs_core/src/hardware/device/vt13.hpprmcs_ws/src/rmcs_core/src/hardware/flight.cpprmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpprmcs_ws/src/rmcs_core/src/hardware/sentry.cpprmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp
🚧 Files skipped from review as they are similar to previous changes (6)
- rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp
- rmcs_ws/src/rmcs_core/src/hardware/flight.cpp
- rmcs_ws/src/rmcs_core/src/hardware/omni_infantry.cpp
- rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp
- rmcs_ws/src/rmcs_core/src/hardware/sentry.cpp
- rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpp
| last_remote_control_received_at_ = Clock::now(); | ||
| valid_ = true; | ||
| } | ||
| void update_status() { | ||
| const auto now = Clock::now(); | ||
| refresh_validity(now); | ||
| if (!valid_) | ||
| return; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash# 确认 Dr16::store_status 由接收线程(板卡回调)调用,与 update_status 跨线程
rg -nP '\.store_status\s*\(' -C4 rmcs_ws/src/rmcs_core/src/hardware
rg -nP '\bupdate_status\s*\(' -C2 rmcs_ws/src/rmcs_core/src/hardware/device/dr16.hppRepository: Alliance-Algorithm/RMCS
Length of output: 37875
🏁 Script executed:
#!/bin/bashset -euo pipefail
file='rmcs_ws/src/rmcs_core/src/hardware/device/dr16.hpp'
wc -l "$file"
sed -n '1,140p'"$file"| cat -nRepository: Alliance-Algorithm/RMCS
Length of output: 5696
🏁 Script executed:
#!/bin/bashset -euo pipefail
file='rmcs_ws/src/rmcs_core/src/hardware/device/dr16.hpp'
sed -n '140,283p'"$file"| cat -nRepository: Alliance-Algorithm/RMCS
Length of output: 6320
🏁 Script executed:
#!/bin/bashset -euo pipefail
rg -nP '\bdr16_\.update_status\s*\(' rmcs_ws/src/rmcs_core/src/hardware
rg -nP '\.update_status\s*\(' rmcs_ws/src/rmcs_core/src/hardware | sed -n '1,200p'Repository: Alliance-Algorithm/RMCS
Length of output: 8298
valid_ 和 last_remote_control_received_at_ 需要同步保护。store_status() 在接收回调里写这两个普通成员,而 update_status() / refresh_validity() 在周期更新里读写它们;这会形成数据竞争。建议把时间戳改成原子发布,valid_ 只在更新线程内推导。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@rmcs_ws/src/rmcs_core/src/hardware/device/dr16.hpp` around lines 49 - 58, 在
`store_status()`、`update_status()` 和 `refresh_validity()` 中消除 `valid_`
与时间戳的并发数据竞争:将 `last_remote_control_received_at_`
改为适合原子发布的表示,并在接收回调中原子写入、周期更新中原子读取;移除 `store_status()` 对 `valid_` 的写入,使 `valid_`
仅由更新线程通过 `refresh_validity()` 推导和修改。
当前队内包含以下可用兵种
同时包含若干特定场景下的测试用 Mock
PR 摘要
将多款机器人硬件/控制能力与离线调试/测试工具整合到同一分支,并完成底层通信与控制组件的大规模重构。新增/更新 Hero(六摩擦轮并支持爬台)、变形步兵(Infantry 3/4 系列)、Sentry(含自动瞄准链路与云台/底盘协同)、以及相关硬件与射控控制流程;同时引入离线自动瞄准调试与识别参数拟合脚本,并补齐自动瞄准/射控 UI 与测试插件支持。
此外,新增 VT13 遥控接入,并在遥控控制输入层完成双控制源仲裁;伴随底盘/云台/射控控制模式与接口语义调整(如 ChassisMode 拆分、功率需求判定、single-shoot 单发触发约束)。
主要变更
机器人配置整合
rmcs_ws/src/rmcs_bringup/config/auto_aim_test.yaml(自动瞄准视频/录制/组件链路与射控参数)rmcs_ws/src/rmcs_bringup/config/steering-hero-little-six-friction.yaml(六摩擦轮 Hero:爬台/云台/底盘/射控/测试与自动瞄准参数装配)rmcs_ws/src/rmcs_bringup/config/sentry.yaml(Sentry:装配、导航参数与射控/云台/攀爬/发射组件)rmcs_ws/src/rmcs_bringup/config/deformable-infantry-omni.yaml、deformable-infantry-omni-b.yaml(变形步兵/底盘硬件映射与控制器参数重设)rmcs_ws/src/rmcs_bringup/config/steering-hero.yamlrmcs_ws/src/rmcs_bringup/config/steering-infantry.yaml子模块与自动瞄准链路
.gitmodules新增子模块rmcs_auto_aim_v2,并将rmcs_ws/src/rmcs_auto_aim_v2指向更新提交。/auto_aim/*相关输出(camera_transform、barrel_direction、yaw_velocity 等)与 TF 计算链路。调试/工作流脚本与离线测试
.script/autoaim-debug:本地/远端 tmux 启动foxglove与streamer,并要求env_setup.bash存在。.script/rmcs-cli:tmux 化的编译/同步/远程挂载与交互控制流程(包含退出清理)。.script/scan-remote:重构远端扫描交互与网络段生成(由固定192.168.*改为基于网卡前两段生成/16前缀下的/24),调整超时与退出语义。.script/host/rmcs:容器启动改为setup_container(),新增recreate选项。.script/local-context/.script/remote-context:向 ROS2 topic 发布/同步固定键值上下文(用于远端上下文一致性)。.script/complete/_local-context、_remote-context:补全脚本增强。参数识别与离线拟合工具链
fit_friction_velocity_pid.py(摩擦轮线性模型→PID)fit_gravity_torque.py(灰盒重力扭矩正弦拟合,支持双向配对)fit_sweep_graybox.py(灰盒扫频模型,支持线性与 ODE 分段拟合)rmcs_utility::CsvWriter、rmcs_utility::NodeMixinrmcs_utility::RingBuffer::peek_front_nrmcs_core::debug::ValueCollector(ROS2 组件插件,周期写 CSV)rmcs_core::hardware::StatusMonitorStaticTorqueTestController、SweptFrequencyController、以及测试输出AngleOutput(注册在插件体系中)底层硬件通信与组件框架重构
librmcs::agent::RmcsBoardLite继承迁移为librmcs::board::RmcsBoardLite::Callback,并统一采用Spec/View体系与board_->start_transmit()链式can_transmit/uart_transmit。Flight、OmniInfantry、Sentry、SteeringHeroLittle、DeformableInfantryOmni/OmniB。rmcs_core::hardware::DeformableInfantryOmniB(新增 TF/自动瞄准输出与/rmcs/service/robot_status服务)DeformableSuspension组件(悬架对称校准、矫正与关节轨迹输出等)控制逻辑与消息体系更新
rmcs_msgs::ChassisMode重构为enum class,拆分SPIN→SPIN_SLOW/SPIN_FAST,新增ALIGNMENT/ALIGNMENT_POWERED,并提供need_power()影响功率限制策略。ChassisController:导航使能优先级与角速度对齐策略调整,引入爬坡速度/导航速度优先通路。DeformableChassis:替换为轻量姿态目标发布 + 速度控制封装,引入DeformableChassisModeManager。DeformableJointController:简化模式/输出限制/ESO 行为。DualYawController:新增 ENCODER 制动状态机与输出 NaN/占位语义调整。EccentricDualYawSolver:策略化求解(AutoAim/Navigation/Disabled)。HeroGimbalController:接入自动瞄准 TF 与输入切换逻辑。ShootingRecorder评估窗口收紧;HeroHeatController仅在 bullet_fired 上升沿递增热量;PutterController将自动触发入口改为/auto_aim/should_shoot;FrictionWheelController增加 working_velocity 输出。VT13 遥控接入与双控制仲裁
Vt13,支持通过串口字节流做帧头识别与 CRC 校验,并维护遥控/键盘/鼠标等有效性与超时重置。Dr16改为无参构造,并强化“有效性超时”判定,同时提供valid()与rotary_knob_switch()读接口。RemoteControl:在vt13存在且有效时依据vt13.mode_switch()与开关状态在 Sport/Cine/Normal 分支选择;否则在dr16有效时直接使用dr16,两者都无效进入安全的默认快照语义。单发(single-shoot)适配
BulletFeederController17mm新增/auto_aim/single_shoot:在单发触发边沿逻辑下强制切换为SINGLE发射模式,并结合should_shoot的就绪状态驱动单发停止计数。