Skip to content

merge(robots): Merge all available robots into one branch - #92

Closed
creeper5820 wants to merge 31 commits into
mainfrom
dev/robots
Closed

merge(robots): Merge all available robots into one branch#92
creeper5820 wants to merge 31 commits into
mainfrom
dev/robots

Conversation

@creeper5820

@creeper5820creeper5820 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

当前队内包含以下可用兵种

  • 六摩擦轮双Yaw舵轮上台阶英雄
  • 自适应悬挂步兵3
  • 自适应悬挂步兵4
  • 舵轮双Yaw哨兵
  • 无人机

同时包含若干特定场景下的测试用 Mock

  • 离线运行自瞄
  • 离线运行导航
  • 单板测试

PR 摘要

将多款机器人硬件/控制能力与离线调试/测试工具整合到同一分支,并完成底层通信与控制组件的大规模重构。新增/更新 Hero(六摩擦轮并支持爬台)、变形步兵(Infantry 3/4 系列)、Sentry(含自动瞄准链路与云台/底盘协同)、以及相关硬件与射控控制流程;同时引入离线自动瞄准调试与识别参数拟合脚本,并补齐自动瞄准/射控 UI 与测试插件支持。

此外,新增 VT13 遥控接入,并在遥控控制输入层完成双控制源仲裁;伴随底盘/云台/射控控制模式与接口语义调整(如 ChassisMode 拆分、功率需求判定、single-shoot 单发触发约束)。

主要变更

机器人配置整合

  • 新增 ROS2 bringup 配置:
    • 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.yamldeformable-infantry-omni-b.yaml(变形步兵/底盘硬件映射与控制器参数重设)
  • 移除旧配置(本次变更未再提供对应内容):
    • rmcs_ws/src/rmcs_bringup/config/steering-hero.yaml
    • rmcs_ws/src/rmcs_bringup/config/steering-infantry.yaml

子模块与自动瞄准链路

  • .gitmodules 新增子模块 rmcs_auto_aim_v2,并将 rmcs_ws/src/rmcs_auto_aim_v2 指向更新提交。
  • Sentry、Hero(SteeringHeroLittle)、变形步兵 Omni/OmniB 等硬件侧均扩展了 /auto_aim/* 相关输出(camera_transform、barrel_direction、yaw_velocity 等)与 TF 计算链路。

调试/工作流脚本与离线测试

  • .script/autoaim-debug:本地/远端 tmux 启动 foxglovestreamer,并要求 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:补全脚本增强。

参数识别与离线拟合工具链

  • 新增/引入多套识别脚本(从 CSV 日志拟合模型并输出 PID/控制器参数 YAML):
    • fit_friction_velocity_pid.py(摩擦轮线性模型→PID)
    • fit_gravity_torque.py(灰盒重力扭矩正弦拟合,支持双向配对)
    • fit_sweep_graybox.py(灰盒扫频模型,支持线性与 ODE 分段拟合)
  • 新增通用数据与 ROS2 工具能力:
    • rmcs_utility::CsvWriterrmcs_utility::NodeMixin
    • rmcs_utility::RingBuffer::peek_front_n
    • rmcs_core::debug::ValueCollector(ROS2 组件插件,周期写 CSV)
    • rmcs_core::hardware::StatusMonitor
  • 新增测试/识别组件插件:
    • StaticTorqueTestControllerSweptFrequencyController、以及测试输出 AngleOutput(注册在插件体系中)

底层硬件通信与组件框架重构

  • 多个硬件实现从 librmcs::agent::RmcsBoardLite 继承迁移为 librmcs::board::RmcsBoardLite::Callback,并统一采用 Spec/View 体系与 board_->start_transmit() 链式 can_transmit/uart_transmit
    • 代表性改造:FlightOmniInfantrySentrySteeringHeroLittleDeformableInfantryOmni/OmniB
  • 新增硬件组件/插件:
    • rmcs_core::hardware::DeformableInfantryOmniB(新增 TF/自动瞄准输出与 /rmcs/service/robot_status 服务)
    • 变形底盘控制链路引入 DeformableSuspension 组件(悬架对称校准、矫正与关节轨迹输出等)

控制逻辑与消息体系更新

  • rmcs_msgs::ChassisMode 重构为 enum class,拆分 SPINSPIN_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_shootFrictionWheelController 增加 working_velocity 输出。

VT13 遥控接入与双控制仲裁

  • 引入 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 的就绪状态驱动单发停止计数。

qzhhhiand others added 28 commits July 14, 2026 09:13
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
@coderabbitai

coderabbitaiBot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

本次变更迁移硬件板卡通信接口,重构底盘、悬架、云台和射击控制,新增自动瞄准与识别工具,并更新 UI、ROS 配置、插件注册、调试脚本及子模块。

Changes

RMCS 系统整合

Layer / File(s)Summary
调试、识别与运维工具
.script/*, .script/identification/*
新增自动瞄准调试、上下文发布、tmux 控制、网络扫描及三类 CSV 识别工具。
硬件板卡与设备通信
rmcs_ws/src/rmcs_core/src/hardware/*, rmcs_ws/src/rmcs_core/plugins.xml
迁移板卡回调与传输接口,更新 CAN/UART 收发、电机 ID 映射、状态监控和插件注册。
底盘、云台与射击控制
rmcs_ws/src/rmcs_core/src/controller/*, rmcs_ws/src/rmcs_msgs/*
扩展底盘模式,新增导航与悬架控制,重构偏航、自动瞄准、姿态保持、供弹和 PID 控制流程。
识别基础设施
rmcs_ws/src/rmcs_utility/*, rmcs_ws/src/rmcs_core/src/identification/*
新增 CSV 写入、节点参数工具、环形缓冲窥视、静态扭矩测试和扫频测试组件。
UI 与运行配置
rmcs_ws/src/rmcs_core/src/referee/app/ui/*, rmcs_ws/src/rmcs_bringup/config/*
增加目标距离、控制过渡和摩擦轮状态显示,更新底盘方向、超级电容、悬架显示及多套机器人配置。

Estimated code review effort: 5 (Critical) | ~180 minutes

Possibly related PRs

Poem

小兔抱着新控制器,
在 tmux 里蹦来蹦去;
云台追星,悬架起舞,
CSV 记录每一步;
CAN 风吹,配置闪闪,
RMCS 耳朵竖起来。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passed标题明确概括了将多套机器人分支合并到一个分支的主要变更。
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev/robots

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

在安全复位中清理完整的射击状态。

当前未复位 shootedshoot_firstpreloaded_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 固定为 NaNjson.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 <= 0B < 0Fc < 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 标准的 NaNInfinity

r2design_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

在拟合前拒绝非有限样本。

anglevalueNaN/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_tostd::forwardstd::stringstd::runtime_errorRCLCPP_*,但只包含了 <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_SLOWSPIN_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

只要求实际选择的输入信号列。

当前无条件要求 torquecontrol_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

📥 Commits

Reviewing files that changed from the base of the PR and between 0a494d4 and b868fd3.

📒 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-remote
  • rmcs_ws/src/rmcs_auto_aim_v2
  • rmcs_ws/src/rmcs_bringup/config/auto_aim_test.yaml
  • rmcs_ws/src/rmcs_bringup/config/deformable-infantry-omni-b.yaml
  • rmcs_ws/src/rmcs_bringup/config/deformable-infantry-omni.yaml
  • rmcs_ws/src/rmcs_bringup/config/sentry.yaml
  • rmcs_ws/src/rmcs_bringup/config/steering-hero-little-six-friction.yaml
  • rmcs_ws/src/rmcs_bringup/config/steering-hero-little.yaml
  • rmcs_ws/src/rmcs_bringup/config/steering-hero.yaml
  • rmcs_ws/src/rmcs_bringup/config/steering-infantry.yaml
  • rmcs_ws/src/rmcs_core/CMakeLists.txt
  • rmcs_ws/src/rmcs_core/plugins.xml
  • rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_climber_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/chassis_power_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_chassis.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_joint_layer.hpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_mode.hpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_omni_wheel_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_suspension.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/deformable_wheel_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/chassis/hero_chassis_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/gimbal/deformable_infantry_gimbal_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/gimbal/dual_yaw_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw.cpp
  • rmcs_ws/src/rmcs_core/src/controller/gimbal/eccentric_dual_yaw_solver.hpp
  • rmcs_ws/src/rmcs_core/src/controller/gimbal/hero_gimbal_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/gimbal/player_viewer.cpp
  • rmcs_ws/src/rmcs_core/src/controller/gimbal/two_axis_gimbal_solver.hpp
  • rmcs_ws/src/rmcs_core/src/controller/shooting/friction_wheel_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/shooting/hero_friction_wheel_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/shooting/hero_heat_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/shooting/putter_controller.cpp
  • rmcs_ws/src/rmcs_core/src/controller/shooting/shooting_recorder.cpp
  • rmcs_ws/src/rmcs_core/src/debug/value_collector.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-steering.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/device/dji_motor.hpp
  • rmcs_ws/src/rmcs_core/src/hardware/device/lk_motor.hpp
  • 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/sentry.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/steering-hero-little-six-friction.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/steering-hero.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/steering-infantry.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/util/status_monitor.hpp
  • rmcs_ws/src/rmcs_core/src/identification/static_torque_test_controller.cpp
  • rmcs_ws/src/rmcs_core/src/identification/swept_frequency_controller.cpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/auto_aim.cpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/deformable_infantry_ui.cpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/hero.cpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/infantry.cpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/shape/shape.hpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/animated_toggle.hpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/crosshair_circle.hpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/deformable_chassis_top_view.hpp
  • rmcs_ws/src/rmcs_core/src/referee/app/ui/widget/status_ring.hpp
  • rmcs_ws/src/rmcs_msgs/include/rmcs_msgs/chassis_mode.hpp
  • rmcs_ws/src/rmcs_msgs/include/rmcs_msgs/rmcs_msgs.hpp
  • rmcs_ws/src/rmcs_utility/include/rmcs_utility/csv_writer.hpp
  • rmcs_ws/src/rmcs_utility/include/rmcs_utility/rclcpp/node_mixin.hpp
  • rmcs_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

Comment on lines 183 to 189
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;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.

Suggested change
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。

Comment on lines +41 to +43
node::param("signals", signal_names_);
node::param("write_interval", write_interval_);
node::param("flush_interval", flush_interval_);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

写入间隔必须在执行取模前验证为正数。

write_interval_ == 0flush_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.

Suggested change
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 及负值,确保相关执行路径不会发生除零。

Comment on lines +444 to +480
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;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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 覆盖的设备集合后再更新索引。

@github-project-automationgithub-project-automationBot moved this from Todo to Done in RMCSJul 19, 2026

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between d49071c and ef4ef90.

📒 Files selected for processing (10)
  • rmcs_ws/src/rmcs_bringup/config/steering-hero-little-six-friction.yaml
  • rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni-b.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/deformable-infantry-omni.cpp
  • rmcs_ws/src/rmcs_core/src/hardware/device/dr16.hpp
  • rmcs_ws/src/rmcs_core/src/hardware/device/remote_control.hpp
  • rmcs_ws/src/rmcs_core/src/hardware/device/vt13.hpp
  • 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/sentry.cpp
  • rmcs_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

Comment on lines +49 to +58

last_remote_control_received_at_ = Clock::now();
valid_ = true;
}

void update_status() {
const auto now = Clock::now();
refresh_validity(now);
if (!valid_)
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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.hpp

Repository: 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 -n

Repository: 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 -n

Repository: 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()` 推导和修改。

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants

@creeper5820@qzhhhi@dwx5@ZGZ713912@floatpigeon