Skip to content

refactor: feishu and cleaning namespace, with a agents.md - #40

Merged
creeper5820 merged 7 commits into
mainfrom
refactor/feishu
Apr 26, 2026
Merged

refactor: feishu and cleaning namespace, with a agents.md#40
creeper5820 merged 7 commits into
mainfrom
refactor/feishu

Conversation

@creeper5820

@creeper5820 creeper5820 commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

概述

本 PR 包含三类主要工作:新增代理行为文档(AGENTS.md)、重构 Feishu 共享内存通信抽象,以及将一系列时间/工具类型与共享上下文从 rmcs::util 收拢并清理为顶级 rmcs 命名空间。变更范围广泛,既有架构/API 层面的公开接口调整,也有大量类型别名替换与格式化净化。

主要改动

新增:AGENTS.md

  • 新增仓库代理行为规范,定义指令优先级(System > Developer > 本文档 > User);
  • 规定高风险情形检测条件与结构化响应(识别风险、拒绝直接实现大规模功能、给出单步最小可验证下一步);
  • 明确代理允许/禁止的工作范围与失败快速退出策略,以及对提取辅助函数的注意事项。

Feishu 库重构(重大)

  • 将模板从 Feishu 改为 Feishu<SendT, RecvT>(公有 API/语义变化);
  • 通过 SendT::kLabel / RecvT::kLabel 派生共享内存标识,移除基于 RuntimeRole 的特化/别名;
  • 引入 start() 显式启动、with_write/send 写入接口,替换原有 commit/fetch/updated 流程;
  • 新增 heartbeat() 用于条件读取并维护带时间戳的接收缓冲区,提供 latest() 与 search(...) 等读取 API;
  • 影响到使用者:所有原基于 role 的调用路径需改为基于 Send/Recv 类型的 heartbeat/latest/with_write/send 模式(测试、runtime、组件均已改写)。

时间类型与命名空间统一

  • 将 Clock/Clock::time_point 的本地别名移除,新增并统一使用顶级别名 rmcs::TimePoint / Duration / Timestamp(在 src/utility/clock.hpp 中从 rmcs::util 移至 rmcs);
  • 大量模块接口/实现(Tracker、Decider、RobotState、Snapshot、Predictor 后端、Outpost、Regular、Image、各 SnapshotBackend 等)将方法签名中的 Clock::time_point 替换为 TimePoint,移除各类的 Clock 别名;
  • 相应的工厂/虚拟方法/构造函数签名同步更新。

共享上下文与状态结构重构(高风险、API 改变)

  • 将 shared/context.hpp 从 rmcs::util 移至 rmcs,并新增 context_trait 概念;
  • Transform 增加静态工厂 kNaN();
  • AutoAimState、ControlState:
    • 添加公共共享内存元数据常量 kLabel / kLength;
    • timestamp 使用 TimePoint;
    • 移除行为方法(reset、set_hold_state、set_tracking_state、has_control_direction 等),改为提供静态工厂 kInvalid()(用于表示无效状态);
    • ControlState 重组成员并新增 capture_signals 记录(timestamp/index);odometry->camera transform 默认化为 {},并在 kInvalid() 中使用 Transform::kNaN();
  • 这些改动为共享内存交互提供显式、可检验的无效值语义,但改变了公开结构与布局(需关注 ABI/序列化约束)。

组件与运行时适配

  • AutoAimComponent / runtime.cpp / test 中已将 Feishu 客户端、状态采集/发布逻辑切换为新的 Send/Recv 型接口(Feishu<ControlState, AutoAimState>)和 event 风格(heartbeat()/latest()/with_write/send);
  • AutoAim 相关:状态新无 reset(),有效性判断改为 AutoAimState::kInvalid() 与 kAutoAimTimeout,目标方向计算改为基于 gimbal_takeover 与 yaw/pitch 的有限性检查;
  • runtime 主循环由原来的 fetch/commit(带失败节流分支)改为直接 send(command);日志节流逻辑替换为新增的 LoggingUtil 使用场景。

新增工具与清理

  • 新增 rmcs::util::LoggingUtil(头文件)——按事件键进行次数/速率限制的日志工具(可 reset、info/warn/error 模板接口);
  • 移除或调整若干类型别名与小范围格式问题(大量 {} -> { }、return {} 风格化更改);
  • 删除测试:移除 test/action_throttler.cpp 及其 CMake 测试目标,相关测试被删除或迁移。

对公开 API / 导出实体的影响(要点)

  • 公开 API 发生的显著变化:
    • rmcs::kernel::Feishu → rmcs::kernel::Feishu<SendT, RecvT>(模板/接口与行为变化,新增大量公有方法:start(), with_write, send, heartbeat, latest, search 等;移除 commit/fetch/旧 updated/RuntimeRole 特化);
    • 新增公有概念:timestamp_trait, context_trait 等;
    • 多个类/接口移除或更改了 public type alias Clock,并将方法签名从 Clock::time_point 改为 TimePoint(包括 Snapshot、RobotState 及 predictor 各后端、Tracker/Decider 等);
    • shared/context.hpp 中 AutoAimState/ControlState 的布局和公共常量改变(kLabel/kLength、kInvalid、timestamp 类型),影响共享内存格式与交互;
    • 新增 rmcs::util::LoggingUtil 类(公共 API)。
  • 需要注意的兼容性风险:共享内存结构与标签常量、类型/布局变更以及 Feishu 模板接口更改会影响进程间交互和任何依赖旧 RuntimeRole 专化的代码或外部进程。

其它说明与代码质量

  • 大量为中等规模的签名替换(Clock -> TimePoint)与格式化调整,估计审查工作量集中在 Feishu 重构、shared/context.hpp 的状态布局及影响面(高),以及 runtime/main 逻辑改动(高)。
  • 新增文档(AGENTS.md)有助于后续使用自动化代理时的约束与风险管控。

Move clock/context aliases to rmcs-level TimePoint usage and remove redundant rmcs-prefixed type aliases to make predictor and IPC interfaces cleaner and more consistent.
@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@creeper5820 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 58 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 22 minutes and 58 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1aed267e-6dec-4e3f-a3d9-051f1fd7a50d

📥 Commits

Reviewing files that changed from the base of the PR and between 19ce0eb and bea8adc.

📒 Files selected for processing (3)
  • config/config.yaml
  • test/feishu_test.cpp
  • test/static_tf.cpp

Walkthrough

统一引入顶层时间类型 rmcs::TimePoint、将 Feishu IPC 重构为泛型双向 Feishu<SendT, RecvT>(新增 start/heartbeat/latest/search/with_write/send),并在运行时、组件、预测器、跟踪器及测试中迁移接口;新增 AGENTS.md 文档与 LoggingUtil 日志节流工具。

Changes

Cohort / File(s) Summary
新文档
AGENTS.md
新增智能体行为规范,定义指令优先级、风险检测条件及高风险场景的结构化响应要求。
Feishu IPC 与集成
src/kernel/feishu.hpp, src/component.cpp, src/runtime.cpp, test/feishu_test.cpp
将基于角色的 Feishu<RuntimeRole> 替换为 Feishu<SendT,RecvT>;移除旧的 commit/fetch/updated 流程,引入 start()heartbeat()latest()search()with_write()send() 并更新使用点与消息类型。
全局时间类型迁移
src/utility/clock.hpp, src/utility/shared/context.hpp
把时钟工具移至顶层命名空间 rmcs,新增 TimePoint/Duration/Timestamp 别名;在共享上下文中将 AutoAimState/ControlState/Transform 等切换为 TimePoint,并添加 kLabel/kLengthkInvalid()/kNaN() 工厂。
预测器与快照时间签名更新
src/module/predictor/... (多个文件,如 robot_state.*, snapshot.*, backend/*, outpost/*, regular/*)
将接口与实现中所有 Clock::time_point 替换为统一 TimePoint,移除局部 Clock 别名,更新工厂与成员类型。
跟踪器与解策器时间签名更新
src/module/tracker/decider.*, src/kernel/tracker.*
Decider::updateTracker::decide 及相关字段改用 TimePoint,移除局部 Clock 别名。
图像与捕获时间戳更新
src/utility/image/image.*, src/module/capturer/local_video.cpp
Image 的 timestamp 接口与实现改为 TimePoint;本地视频实现引入 TimePoint 别名替代原 Clock::time_point
共享上下文与类型重构
src/utility/shared/context.hpp
重构 TransformAutoAimStateControlState 布局,新增共享内存元信息与无效工厂,移除若干行为方法并引入 context_trait 概念。
概念/类型约束微调
src/kernel/common.hpp
serialable_config_trait 概念改为直接引用 util::Serializable,移除中间别名。
运行时与组件逻辑调整
src/runtime.cpp, src/component.cpp
调整主循环与 control-state 流程,改用 feishu.latest()/feishu.send() 路径,重构 auto-aim 状态更新与控制发布逻辑。
日志节流工具与测试变更
src/utility/logging_util.hpp, test/*, test/CMakeLists.txt, test/action_throttler.cpp
新增 rmcs::util::LoggingUtil 用于按键限频日志;删除 action_throttler 测试目标与相关测试,更新测试以匹配 Feishu 新接口。
小范围移除/格式化修改
多处文件(如 src/kernel/fire_control.hpp, src/module/identifier/*, src/utility/tf/static_tf.hpp, test/transform_communication.cpp
移除或迁移若干类内 Clock 别名,及多处格式/空格/大括号初始化风格调整,行为无改动。

Sequence Diagram(s)

sequenceDiagram
    participant Comp as AutoAim\nComponent
    participant Feishu as Feishu\nClient
    participant SHM as Shared\nMemory

    Note over Comp,SHM: 类型化 Feishu 双向流程

    Comp->>Feishu: start()
    activate Feishu
    Feishu->>SHM: 打开发送/接收通道 (基于 SendT::kLabel / RecvT::kLabel)
    deactivate Feishu

    loop 每次主循环
        Comp->>Feishu: heartbeat()
        Feishu-->>Comp: boolean (是否有新 recv)
        alt 有新数据
            Comp->>Feishu: latest()
            Feishu->>SHM: 从缓冲读取最近 RecvT
            Feishu-->>Comp: RecvT (ControlState)
            Comp->>Comp: 条件覆盖/更新 AutoAimState
        else 无新数据
            Comp->>Comp: 保持或使用上次状态
        end

        Comp->>Comp: 计算 ControlState(基于追踪/火控/接管逻辑)
        Comp->>Feishu: with_write(lambda -> send SendT)
        Feishu->>SHM: 写入 SendT (ControlState) 且更新发送端状态
        Feishu-->>Comp: 写入完成(无布尔 commit 分支)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 分钟

Possibly related PRs

Suggested labels

enhancement

诗歌

🐰 时刻换名成一体,
通道变型更分明,
日志按键静候声,
小改多处稳步行,
代码轻跳春风迎。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.94% 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 name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确地反映了主要变化:Feishu接口重构、命名空间清理和新增AGENTS.md文档,覆盖了所有核心改动方向。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/feishu

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/module/predictor/regular/snapshot.hpp (1)

1-13: ⚠️ Potential issue | 🟡 Minor

添加显式的 utility/clock.hpp 包含以提高代码健壮性。

虽然 TimePoint 通过 module/predictor/snapshot.hpp 的传递包含可见,但此模块内存在不一致的模式:robot_state.hpp 等文件显式包含 utility/clock.hpp,而同样使用 TimePoint 的快照声明文件(本文件及 outpost/snapshot.hpp)则依赖传递包含。

建议添加 #include "utility/clock.hpp" 来:

  1. 明确依赖关系
  2. 避免 snapshot.hpp 头文件变化导致的编译失败风险
  3. 与同模块其他文件的包含策略保持一致
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/module/predictor/regular/snapshot.hpp` around lines 1 - 13, The header is
relying on a transitive definition of TimePoint; add an explicit include of
utility/clock.hpp at the top of src/module/predictor/regular/snapshot.hpp so
TimePoint is defined without depending on module/predictor/snapshot.hpp
changes—update the file containing the declaration of
make_regular_snapshot(Snapshot::NormalEKF::XVec ekf_x, DeviceId device,
CampColor color, int armor_num, TimePoint stamp) noexcept -> Snapshot to include
"utility/clock.hpp" alongside the existing includes to make the dependency
explicit and consistent with other files like robot_state.hpp.
src/module/predictor/backend/robot_state_backend.cpp (1)

47-47: ⚠️ Potential issue | 🟡 Minor

命名空间结束注释与实际作用域不匹配。

第 9 行打开的是 namespace rmcs::predictor,本文件并未嵌套 detail 子命名空间,结束注释应改为 // namespace rmcs::predictor,以免阅读时产生误导。

✏️ 修复建议
-} // namespace rmcs::predictor::detail
+} // namespace rmcs::predictor
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/module/predictor/backend/robot_state_backend.cpp` at line 47,
结束注释与实际命名空间不匹配:当前文件在第 9 行打开的是 namespace rmcs::predictor 但文件尾部的注释写成了 // namespace
rmcs::predictor::detail,找到文件末尾闭合的右大括号对应的命名空间结束注释并将注释改为 // namespace
rmcs::predictor 以匹配实际作用域(定位参考符号:namespace rmcs::predictor)。
🧹 Nitpick comments (8)
src/module/predictor/outpost/snapshot.hpp (1)

1-10: 建议直接 #include "utility/clock.hpp" 以显式暴露 TimePoint 依赖。

现在签名里直接使用了未限定的 TimePoint,但本头文件并未直接包含 utility/clock.hpp,依赖于 module/predictor/snapshot.hpp 等间接传递。按 IWYU(include-what-you-use)原则,显式包含可避免未来上游头文件精简时本文件编译失败,属于可选但推荐的小重构。

♻️ 建议修改
 `#include` "module/predictor/outpost/armor_layout.hpp"
 `#include` "module/predictor/snapshot.hpp"
+#include "utility/clock.hpp"
 `#include` "utility/robot/color.hpp"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/module/predictor/outpost/snapshot.hpp` around lines 1 - 10, 在头文件中显式包含
utility/clock.hpp 以暴露 TimePoint 的定义:在 src/module/predictor/outpost/snapshot.hpp
顶部新增 `#include` "utility/clock.hpp"(或等价头),这样 make_outpost_snapshot 的签名中使用的
TimePoint 不再依赖间接包含;保持其他 include 顺序不变,确保编译器能直接解析 TimePoint。
src/module/capturer/local_video.cpp (1)

15-21: 可考虑直接复用 rmcs::TimePoint,避免本地再定义。

本 PR 在 src/utility/clock.hpp 中新增了顶层 rmcs::Clockrmcs::TimePoint 统一别名。此处 Impl 内部新加的 Clock/TimePoint 与其完全等价,可直接 #include "utility/clock.hpp" 后使用 rmcs::TimePoint,与仓库内其他模块保持一致。当然,保留本地别名也不影响功能,属于可选重构。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/module/capturer/local_video.cpp` around lines 15 - 21, Replace the
locally defined Clock/TimePoint aliases in Impl with the shared aliases from
utility/clock.hpp: include "utility/clock.hpp" and use rmcs::Clock and
rmcs::TimePoint for the types currently declared as Clock and TimePoint (which
affect symbols like capturer, interval_duration, last_read_time). This keeps
behavior identical but aligns with project-wide typedefs and removes the
duplicate local aliases.
src/utility/clock.hpp (1)

6-9: 建议移除冗余的 Timestamp 别名,仅保留 TimePoint

当前定义中 using Timestamp = TimePoint;using TimePoint = Clock::time_point; 完全重复。整个代码库中广泛使用 TimePoint(tracker、predictor、image 等模块均采用),而 Timestamp 全局别名未被任何其他文件导入或使用(feishu.hpp 中的 Timestamp 是本地重定义,不依赖该全局别名)。保留两个相同的别名会增加命名空间噪声,易引发后续维护时的混用。建议删除 Timestamp 这一行,统一使用 TimePoint

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utility/clock.hpp` around lines 6 - 9, Remove the redundant alias by
deleting the line "using Timestamp = TimePoint;" from src/utility/clock.hpp so
only Clock, TimePoint and Duration remain; search the repo for any uses of the
global Timestamp alias and, if any are found, replace them with TimePoint (note
feishu.hpp already has its own local Timestamp and does not depend on the
removed alias) to avoid namespace noise and keep all time types unified around
TimePoint.
src/component.cpp (1)

42-43: 清理已失效的 commit_control_state_failed 节流项。

原先 commit(control_state) 存在失败分支,通过 action_throttler.dispatch("commit_control_state_failed", ...) 做节流日志;现在改为无条件 feishu.send(...),该 action 只剩下每帧一次的 reset(...),相当于死代码。建议要么移除注册与 reset,要么在 send 中引入明确的失败返回并恢复 dispatch 分支,保持错误可观测性。

♻️ 建议的最小清理
         action_throttler.register_action("tf_not_ready");
-        action_throttler.register_action("commit_control_state_failed");
     }
...
-        feishu.send([&](auto& data) { data = control_state; });
-        action_throttler.reset("commit_control_state_failed");
+        feishu.send([&](auto& data) { data = control_state; });
     }

Also applies to: 138-140

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/component.cpp` around lines 42 - 43, 当前已注册的节流项
"commit_control_state_failed" 已无实际 dispatch 使用,只剩下每帧调用的
reset,等同死代码;请清理或恢复错误分支:要么删除
action_throttler.register_action("commit_control_state_failed") 并移除对应的 reset
调用(清理死代码),要么在 commit(control_state) 的 feishu.send 路径中恢复明确的失败返回并重新调用
action_throttler.dispatch("commit_control_state_failed", ...)
以保持错误可观测性;定位相关符号:action_throttler.register_action, action_throttler.dispatch,
feishu.send, reset, 以及原先触发 dispatch 的 commit(control_state) 分支,任选其一实施并相应更新注释。
src/module/predictor/regular/robot_state.hpp (1)

1-19: 建议直接 include utility/clock.hpp,与同级头文件保持一致。

本文件在公共签名中使用 TimePoint(Line 16/18/19),但没有直接 include "utility/clock.hpp",当前依赖 module/predictor/snapshot.hpp 的传递性可见性。同目录下 src/module/predictor/robot_state.hpp:7src/module/predictor/outpost/robot_state.hpp:8 都显式包含了该头,建议这里也按 IWYU 对齐,避免未来重构 snapshot.hpp 时破坏编译。

♻️ 建议改动
 `#include` "module/predictor/regular/ekf_parameter.hpp"
 `#include` "module/predictor/snapshot.hpp"
+#include "utility/clock.hpp"
 `#include` "utility/pimpl.hpp"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/module/predictor/regular/robot_state.hpp` around lines 1 - 19, The header
RegularRobotState uses TimePoint in its public API (constructor
RegularRobotState(TimePoint), initialize and predict) but relies on transitive
inclusion via module/predictor/snapshot.hpp; add a direct include of
"utility/clock.hpp" at the top of src/module/predictor/regular/robot_state.hpp
to satisfy IWYU and avoid breakage if snapshot.hpp changes, keeping the rest of
the file unchanged.
src/kernel/feishu.hpp (2)

108-108: 补一个命名空间结束注释(nit)。

文件末尾 } 缺少 // namespace rmcs::kernel,和仓库其它文件风格一致会更好维护。

✏️ 建议
-}
+} // namespace rmcs::kernel
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/kernel/feishu.hpp` at line 108, Add a namespace end comment after the
final closing brace to match project style: locate the closing brace that ends
namespace rmcs::kernel in feishu.hpp and append a trailing comment like "//
namespace rmcs::kernel" so the file's namespace terminator is explicitly
annotated and consistent with other headers.

16-45: recv 直接访问 data.timestamp,但类型约束里没有保证它存在。

类模板仅对 RecvT 要求 context_trait(只校验 kLabel/kLength),而 recv 在第 41 行无条件读取 data.timestamp。若将来有调用方用一个没有 timestamp 字段的类型实例化 Feishu,recv 会在实例化点爆出一大段模板错误,而不是在声明处给出清晰的约束诊断。

建议把 timestamp_trait<RecvT> 合并进类模板约束(或至少作为 recvrequires 约束),与第 80 行 search 中的 static_assert(timestamp_trait<RecvT>) 形成一致的契约:

♻️ 建议改法
-template <context_trait SendT, context_trait RecvT>
+template <context_trait SendT, context_trait RecvT>
+    requires timestamp_trait<RecvT>
 class Feishu {

或者更局部地约束在 recv/search 上。既然 search 已经依赖该 trait,把它提升到类层级更自然,并可移除第 80 行冗余的 static_assert

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/kernel/feishu.hpp` around lines 16 - 45, The recv method in class
template Feishu reads data.timestamp but the class-level context_trait only
ensures kLabel/kLength for RecvT; add the timestamp requirement to the template
constraints so instantiations fail with a clear diagnostic: require
timestamp_trait<RecvT> (or include timestamp_trait in the class template
parameter list) or add a requires clause on recv referencing
timestamp_trait<RecvT>; update the class-level constraint (template
<context_trait SendT, context_trait RecvT> -> include timestamp_trait for RecvT)
so it matches the existing static_assert in search, and then remove the
redundant static_assert; ensure references: Feishu, RecvT, recv, search,
latest_timestamp, and recv_client.with_read are satisfied by the new trait.
src/utility/shared/context.hpp (1)

25-26: kLength 的语义略有歧义,建议考虑更明确的命名。

当前 kLengthsrc/kernel/feishu.hpp heartbeat 中被用作 recv_buffer 的条目数上限(deque 最大长度),但名字也可能被读者解读为"共享内存缓冲区字节长度"或"单条消息字节长度"。在跨进程消息 + 环形缓冲的语境下,这种歧义容易放大。

若不涉及 ABI 兼容,推荐改为 kBufferCapacity / kHistoryCapacity 一类的命名,同时在 context_trait 里也同步更新。若保留现名,建议在结构体上方注释里写清楚单位与用途。

Also applies to: 77-78

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utility/shared/context.hpp` around lines 25 - 26, Rename the ambiguous
static constexpr kLength to a clearer name (e.g., kBufferCapacity or
kHistoryCapacity) and update all usages (including in context_trait and the
heartbeat recv_buffer/deque size logic in kernel::feishu heartbeat) to the new
identifier; alternatively, if you must keep the name, add a concise comment
above the constant explaining its unit and purpose (that it denotes maximum
number of entries in the recv_buffer/deque, not byte length) and mirror that
comment in context_trait to avoid ambiguity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/kernel/feishu.hpp`:
- Around line 78-82: search 函数当前在遇到 target > latest_timestamp 时直接返回
std::nullopt,过于激进;请改为先计算差值并比较 max 容差:当 (target - latest_timestamp) > max(或等价的
Duration 比较)才短路返回 std::nullopt,否则不要早退,继续按现有逻辑将 latest_timestamp
对应的样本视为合法最近邻并返回(参考函数名 search、参数 target、latest_timestamp、max 的比较与 Duration
类型转换以确保类型安全)。

In `@src/runtime.cpp`:
- Around line 110-113: The empty if around feishu.heartbeat() in the main loop
(while (util::get_running())) ignores its meaningful boolean return; replace the
empty conditional with explicit intent: either (A) treat false as an error by
adding handling inside the if (e.g., log the failure via your logger, attempt
feishu.reconnect() or other recovery and/or break/stop the loop) or (B) if only
the side effects of heartbeat() are needed, remove the if and call
feishu.heartbeat(); (or explicitly cast to void to indicate ignored result).
Locate the call to feishu.heartbeat() and implement one of these two options so
the return value is no longer silently discarded.
- Around line 124-133: The code currently creates a new ControlState
(control_state) each frame and only calls feishu.recv(...) when feishu.updated()
is true, so the else branch's "use last cached value" message is misleading and
the default ControlState is silently sent downstream; fix by either (A) lifting
the ControlState instance (ControlState control_state) out of the per-frame loop
so it truly caches the last received value across frames and keep
feishu.recv(...) only when updated(), or (B) always call feishu.recv(...) each
frame to read the latest shared-memory value and use feishu.updated() solely to
throttle/log via action_throttler (control_state_label) without skipping the
recv; adjust action_throttler.reset/dispatch usage accordingly to match the
chosen approach.

---

Outside diff comments:
In `@src/module/predictor/backend/robot_state_backend.cpp`:
- Line 47: 结束注释与实际命名空间不匹配:当前文件在第 9 行打开的是 namespace rmcs::predictor 但文件尾部的注释写成了
// namespace rmcs::predictor::detail,找到文件末尾闭合的右大括号对应的命名空间结束注释并将注释改为 // namespace
rmcs::predictor 以匹配实际作用域(定位参考符号:namespace rmcs::predictor)。

In `@src/module/predictor/regular/snapshot.hpp`:
- Around line 1-13: The header is relying on a transitive definition of
TimePoint; add an explicit include of utility/clock.hpp at the top of
src/module/predictor/regular/snapshot.hpp so TimePoint is defined without
depending on module/predictor/snapshot.hpp changes—update the file containing
the declaration of make_regular_snapshot(Snapshot::NormalEKF::XVec ekf_x,
DeviceId device, CampColor color, int armor_num, TimePoint stamp) noexcept ->
Snapshot to include "utility/clock.hpp" alongside the existing includes to make
the dependency explicit and consistent with other files like robot_state.hpp.

---

Nitpick comments:
In `@src/component.cpp`:
- Around line 42-43: 当前已注册的节流项 "commit_control_state_failed" 已无实际 dispatch
使用,只剩下每帧调用的 reset,等同死代码;请清理或恢复错误分支:要么删除
action_throttler.register_action("commit_control_state_failed") 并移除对应的 reset
调用(清理死代码),要么在 commit(control_state) 的 feishu.send 路径中恢复明确的失败返回并重新调用
action_throttler.dispatch("commit_control_state_failed", ...)
以保持错误可观测性;定位相关符号:action_throttler.register_action, action_throttler.dispatch,
feishu.send, reset, 以及原先触发 dispatch 的 commit(control_state) 分支,任选其一实施并相应更新注释。

In `@src/kernel/feishu.hpp`:
- Line 108: Add a namespace end comment after the final closing brace to match
project style: locate the closing brace that ends namespace rmcs::kernel in
feishu.hpp and append a trailing comment like "// namespace rmcs::kernel" so the
file's namespace terminator is explicitly annotated and consistent with other
headers.
- Around line 16-45: The recv method in class template Feishu reads
data.timestamp but the class-level context_trait only ensures kLabel/kLength for
RecvT; add the timestamp requirement to the template constraints so
instantiations fail with a clear diagnostic: require timestamp_trait<RecvT> (or
include timestamp_trait in the class template parameter list) or add a requires
clause on recv referencing timestamp_trait<RecvT>; update the class-level
constraint (template <context_trait SendT, context_trait RecvT> -> include
timestamp_trait for RecvT) so it matches the existing static_assert in search,
and then remove the redundant static_assert; ensure references: Feishu, RecvT,
recv, search, latest_timestamp, and recv_client.with_read are satisfied by the
new trait.

In `@src/module/capturer/local_video.cpp`:
- Around line 15-21: Replace the locally defined Clock/TimePoint aliases in Impl
with the shared aliases from utility/clock.hpp: include "utility/clock.hpp" and
use rmcs::Clock and rmcs::TimePoint for the types currently declared as Clock
and TimePoint (which affect symbols like capturer, interval_duration,
last_read_time). This keeps behavior identical but aligns with project-wide
typedefs and removes the duplicate local aliases.

In `@src/module/predictor/outpost/snapshot.hpp`:
- Around line 1-10: 在头文件中显式包含 utility/clock.hpp 以暴露 TimePoint 的定义:在
src/module/predictor/outpost/snapshot.hpp 顶部新增 `#include`
"utility/clock.hpp"(或等价头),这样 make_outpost_snapshot 的签名中使用的 TimePoint
不再依赖间接包含;保持其他 include 顺序不变,确保编译器能直接解析 TimePoint。

In `@src/module/predictor/regular/robot_state.hpp`:
- Around line 1-19: The header RegularRobotState uses TimePoint in its public
API (constructor RegularRobotState(TimePoint), initialize and predict) but
relies on transitive inclusion via module/predictor/snapshot.hpp; add a direct
include of "utility/clock.hpp" at the top of
src/module/predictor/regular/robot_state.hpp to satisfy IWYU and avoid breakage
if snapshot.hpp changes, keeping the rest of the file unchanged.

In `@src/utility/clock.hpp`:
- Around line 6-9: Remove the redundant alias by deleting the line "using
Timestamp = TimePoint;" from src/utility/clock.hpp so only Clock, TimePoint and
Duration remain; search the repo for any uses of the global Timestamp alias and,
if any are found, replace them with TimePoint (note feishu.hpp already has its
own local Timestamp and does not depend on the removed alias) to avoid namespace
noise and keep all time types unified around TimePoint.

In `@src/utility/shared/context.hpp`:
- Around line 25-26: Rename the ambiguous static constexpr kLength to a clearer
name (e.g., kBufferCapacity or kHistoryCapacity) and update all usages
(including in context_trait and the heartbeat recv_buffer/deque size logic in
kernel::feishu heartbeat) to the new identifier; alternatively, if you must keep
the name, add a concise comment above the constant explaining its unit and
purpose (that it denotes maximum number of entries in the recv_buffer/deque, not
byte length) and mirror that comment in context_trait to avoid ambiguity.
🪄 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: 4accaa93-3267-47dc-804b-0bb8bbf8d66e

📥 Commits

Reviewing files that changed from the base of the PR and between f2b16f1 and 39456e9.

📒 Files selected for processing (35)
  • AGENTS.md
  • src/component.cpp
  • src/kernel/common.hpp
  • src/kernel/feishu.hpp
  • src/kernel/fire_control.hpp
  • src/kernel/pose_estimator.hpp
  • src/kernel/tracker.cpp
  • src/kernel/tracker.hpp
  • src/module/capturer/local_video.cpp
  • src/module/debug/framerate.hpp
  • src/module/identifier/armor_detection.cpp
  • src/module/predictor/backend/robot_state_backend.cpp
  • src/module/predictor/backend/robot_state_backend.hpp
  • src/module/predictor/backend/snapshot_backend.hpp
  • src/module/predictor/outpost/robot_state.cpp
  • src/module/predictor/outpost/robot_state.hpp
  • src/module/predictor/outpost/snapshot.cpp
  • src/module/predictor/outpost/snapshot.hpp
  • src/module/predictor/regular/robot_state.cpp
  • src/module/predictor/regular/robot_state.hpp
  • src/module/predictor/regular/snapshot.cpp
  • src/module/predictor/regular/snapshot.hpp
  • src/module/predictor/robot_state.cpp
  • src/module/predictor/robot_state.hpp
  • src/module/predictor/snapshot.cpp
  • src/module/predictor/snapshot.hpp
  • src/module/tracker/decider.cpp
  • src/module/tracker/decider.hpp
  • src/runtime.cpp
  • src/utility/clock.hpp
  • src/utility/image/image.cpp
  • src/utility/image/image.hpp
  • src/utility/shared/context.hpp
  • test/feishu_test.cpp
  • test/transform_communication.cpp
💤 Files with no reviewable changes (1)
  • src/kernel/fire_control.hpp

Comment thread src/kernel/feishu.hpp
Comment thread src/runtime.cpp Outdated
Comment thread src/runtime.cpp Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
src/runtime.cpp (1)

106-106: ⚠️ Potential issue | 🟡 Minor

updated 变量被赋值后未使用。

auto updated = feishu.heartbeat(); 之后整个循环中再无对 updated 的引用,heartbeat() 的返回值被静默丢弃。鉴于过去评审已就同一调用点的"返回值未被处理"提过类似问题,建议明确意图:要么 feishu.heartbeat();(直接丢弃),要么真正用 updated 做新鲜度门控(例如只在新一帧 control_state 到达时刷新 received,避免后面的 feishu.latest() 在长时间无新数据时持续返回陈旧值)。

🛠 简单修复
-        auto updated = feishu.heartbeat();
+        feishu.heartbeat();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/runtime.cpp` at line 106, The assignment auto updated =
feishu.heartbeat(); currently discards the return value; either drop the
assignment and call feishu.heartbeat(); directly if its return is intentionally
ignored, or use updated to gate freshness: inside the loop check updated (the
bool/flag returned by feishu.heartbeat()) and only refresh received from
feishu.latest() when updated is true or when control_state changes, so you avoid
returning stale values—update the code paths around feishu.heartbeat(),
feishu.latest(), control_state and received accordingly to reflect the chosen
intent.
🧹 Nitpick comments (5)
src/component.cpp (1)

44-44: commit_control_state_failed 节流器已经无写失败路径,建议清理。

feishu.with_write(...) 不再返回 commit 成功/失败,Line 140 的 action_throttler.reset("commit_control_state_failed") 没有任何配对的 dispatch,而 Line 44 注册的同名 action 也只在此处被 reset。建议把这条注册和 reset 一并删除,避免遗留死代码误导后续维护者。

♻️ 建议删除
         action_throttler.register_action("tf_not_ready");
-        action_throttler.register_action("commit_control_state_failed");
     }
         feishu.with_write([&](auto& data) { data = control_state; });
-        action_throttler.reset("commit_control_state_failed");
     }

Also applies to: 140-140

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/component.cpp` at line 44, Remove the dead throttler action for
"commit_control_state_failed": delete the
register_action("commit_control_state_failed") call and the matching
action_throttler.reset("commit_control_state_failed") since
feishu.with_write(...) no longer returns commit success/failure and there is no
dispatch of this action; verify no other references to
"commit_control_state_failed" remain and remove them to avoid leftover dead
code.
src/utility/shared/context.hpp (2)

68-68: static_assert(context_trait<...>) 没有验证 kLabel/kLength —— 这点值得显式补充。

由于本文件的 context_trait 只校验"trivially copyable",而 Feishu 模板真正依赖的 kLabel/kLength 概念是 rmcs::kernel::context_trait,这两个 static_assert 实际上漏检了 IPC 必备元数据。如果未来误删了 kLabel/kLength,本文件不会报错,错误会推迟到 Feishu 实例化才暴露。可以考虑直接 static_assert(rmcs::kernel::context_trait<AutoAimState>) 加固。

Also applies to: 105-105

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utility/shared/context.hpp` at line 68, 当前对 AutoAimState 的静态断言仅使用本文件的
context_trait(只检查 trivially copyable),未保证 IPC 元数据 kLabel/kLength 存在;请将对应断言改为使用
rmcs::kernel::context_trait(例如
static_assert(rmcs::kernel::context_trait<AutoAimState>))以强制验证 kLabel/kLength 等
IPC 必需概念,并对文件中所有类似位置(包括第105行对应断言)一并替换,确保在编译期就能捕获缺失元数据的问题。

11-12: context_traitrmcs::kernel::context_trait 同名但语义完全不同,建议重命名以避免误导。

本文件在 namespace rmcs 中定义的 context_trait<T> 仅检查 std::is_trivially_copyable_v<T>;而 src/kernel/feishu.hppnamespace rmcs::kernel 中定义的同名 context_trait 要求 T::kLabelT::kLength。两个 concept 的字面名一样但约束完全不同,仅靠所在命名空间区分。在阅读 static_assert(context_trait<AutoAimState>) 时(Line 68 / 105),不结合 ADL/namespace 上下文很容易误以为这里也在校验 kLabel/kLength

建议把本文件内的概念改名为更直白的 trivially_shareable / shm_trivial 之类,或者反之让 feishu.hpp 那个改名为 feishu_message,避免后续维护者踩坑。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utility/shared/context.hpp` around lines 11 - 12, The concept
context_trait in namespace rmcs conflicts semantically with
rmcs::kernel::context_trait (one checks std::is_trivially_copyable_v<T>, the
other requires kLabel/kLength); rename the trivial copy concept (e.g., to
trivially_shareable or shm_trivial) in the header where context_trait is
defined, update all local uses (e.g., static_assert(context_trait<AutoAimState>)
and any templates or constraints referencing context_trait) to the new name, and
run a quick project-wide search for context_trait to ensure only the intended
kernel concept remains under rmcs::kernel::context_trait or alternatively rename
the kernel concept (e.g., feishu_message) if that fits your design.
src/utility/logging_util.hpp (1)

17-17: std::string_view 作为 key 存在悬垂风险。

store 的 key 是 std::string_view,目前调用点(logging.reset("receive", 5) 等)都是字符串字面量、生命周期为静态存储期,所以暂时无问题。但如果未来有调用方传入 std::string 的临时对象或局部 string,键将悬垂导致 UB。建议要么把 key 改为 std::string,要么在文档/契约中明确"name 必须具有静态存储期"。

Also applies to: 33-33

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utility/logging_util.hpp` at line 17, The unordered_map member store uses
std::string_view keys which can dangle; change the map key to std::string (i.e.,
std::unordered_map<std::string, std::int16_t> store) and update any call sites
(e.g., logging.reset("receive", 5)) to rely on implicit conversion or explicitly
construct std::string where necessary so stored keys own their data; adjust
constructors/insert/emplace usages in the class (look for store and the reset
method) to copy names into the map and remove any requirement that callers
provide static-lifetime strings.
src/kernel/feishu.hpp (1)

49-53: 每次 heartbeat() 调用都会尝试 open(),在对端未启动时反复执行系统调用。

heartbeat() 在主循环中每帧调用一次(src/runtime.cpp:106),而 start() 使用 opened() || open(...) 模式——当连接未建立时,每次都会执行:

  • Send 端shm_open() + ftruncate() + mmap()
  • Recv 端shm_open() + mmap()

这意味着主循环中每帧都会触发多个系统调用。在对端尚未启动的场景下,这会导致连续的系统调用堆积。建议添加失败重试的退避机制(如失败后短时间内不再重试)或在外部控制调度频率。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/kernel/feishu.hpp` around lines 49 - 53, start() currently calls
send_client.open(...) and recv_client.open(...) on every heartbeat (via
heartbeat()), causing repeated shm_open/ftruncate/mmap system calls when the
peer isn't ready; add a retry/backoff so failed opens are not retried every
frame. Concretely: add per-endpoint state (e.g., last_send_open_attempt,
last_recv_open_attempt timestamps or a failed_until deadline) inside the Feishu
class and in start() only call send_client.open(SendT::kLabel) or
recv_client.open(RecvT::kLabel) if the corresponding opened() is false AND
enough time has elapsed since the last failed attempt; on failure update the
timestamp/failed_until to impose a short delay (e.g., 100–500ms) before the next
open() attempt so heartbeat() no longer triggers system calls every frame.
Ensure you reference send_client.opened(), send_client.open(...),
recv_client.opened(), recv_client.open(...) and heartbeat() when making the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/component.cpp`:
- Around line 129-133: 在 handle_tf_not_ready 中当前对 control_state 进行 control_state
= ControlState::kInvalid() 会被后续 update_control_state 覆盖且不会触发
publish_control_state(),所以请根据意图处理:如果希望在 tf 未就绪期间通知对端发送 invalid 状态,则在该分支内调用
feishu.with_write(...)(用现有写入/发布路径直接写出并发送包含 kInvalid 的 control_state 或调用
publish_control_state() 的等价写入操作);如果只是想清空内部状态且不通知对端,则删除 control_state =
ControlState::kInvalid() 这一行。保持现有对
publish_auto_aim_outputs(make_invalid_auto_aim_state()) 的调用不变或与写入操作配对发送。

In `@src/runtime.cpp`:
- Around line 117-125: feishu.latest() can return stale ControlState from the
circular buffer, so add a freshness check against received.timestamp using the
same timeout logic as kAutoAimTimeout/has_fresh_auto_aim_state(): after calling
feishu.latest() in the receive block, compare now - received.timestamp to the
timeout and if expired set received = ControlState::kInvalid() (or skip invoking
tracker.set_invincible_armors, pose_estimator.set_odom_to_camera_transform and
fire_control.solve with received.yaw) and log a warning; ensure you reference
feishu.latest(), received.timestamp, ControlState::kInvalid(), kAutoAimTimeout,
has_fresh_auto_aim_state(), tracker.set_invincible_armors,
pose_estimator.set_odom_to_camera_transform and fire_control.solve when making
the change.

In `@src/utility/logging_util.hpp`:
- Around line 35-48: The lambdas used in info/warn/error (inside the templated
methods info, warn, error) capture Args by value with “[=, this]” but are const
by default, so using std::forward<Args>(args) can fail for non-reference deduced
Args; either mark the lambda mutable (e.g., exec(name, [=, this] mutable { ...
})) so std::forward is valid, or stop using std::forward and pass args by value
into rclcpp.* (e.g., rclcpp.info(fmt, args...)); update all three methods
consistently and keep the call through exec unchanged.

In `@src/utility/shared/context.hpp`:
- Around line 57-66: AutoAimState::kInvalid() and ControlState::kInvalid()
currently set timestamp via Clock::now(), which makes "invalid" states appear
fresh to has_fresh_auto_aim_state() (which compares auto_aim_state.timestamp
against kAutoAimTimeout); change both kInvalid() implementations to initialize
timestamp to a zero/epoch value (e.g., TimePoint{} or TimePoint::min()) instead
of Clock::now(), and ensure ControlState::kInvalid() does not default-initialize
capture_signals with Clock::now() (construct them with epoch/empty timestamps)
so that invalid states are unambiguously treated as stale by downstream
freshness checks like has_fresh_auto_aim_state().

---

Duplicate comments:
In `@src/runtime.cpp`:
- Line 106: The assignment auto updated = feishu.heartbeat(); currently discards
the return value; either drop the assignment and call feishu.heartbeat();
directly if its return is intentionally ignored, or use updated to gate
freshness: inside the loop check updated (the bool/flag returned by
feishu.heartbeat()) and only refresh received from feishu.latest() when updated
is true or when control_state changes, so you avoid returning stale
values—update the code paths around feishu.heartbeat(), feishu.latest(),
control_state and received accordingly to reflect the chosen intent.

---

Nitpick comments:
In `@src/component.cpp`:
- Line 44: Remove the dead throttler action for "commit_control_state_failed":
delete the register_action("commit_control_state_failed") call and the matching
action_throttler.reset("commit_control_state_failed") since
feishu.with_write(...) no longer returns commit success/failure and there is no
dispatch of this action; verify no other references to
"commit_control_state_failed" remain and remove them to avoid leftover dead
code.

In `@src/kernel/feishu.hpp`:
- Around line 49-53: start() currently calls send_client.open(...) and
recv_client.open(...) on every heartbeat (via heartbeat()), causing repeated
shm_open/ftruncate/mmap system calls when the peer isn't ready; add a
retry/backoff so failed opens are not retried every frame. Concretely: add
per-endpoint state (e.g., last_send_open_attempt, last_recv_open_attempt
timestamps or a failed_until deadline) inside the Feishu class and in start()
only call send_client.open(SendT::kLabel) or recv_client.open(RecvT::kLabel) if
the corresponding opened() is false AND enough time has elapsed since the last
failed attempt; on failure update the timestamp/failed_until to impose a short
delay (e.g., 100–500ms) before the next open() attempt so heartbeat() no longer
triggers system calls every frame. Ensure you reference send_client.opened(),
send_client.open(...), recv_client.opened(), recv_client.open(...) and
heartbeat() when making the change.

In `@src/utility/logging_util.hpp`:
- Line 17: The unordered_map member store uses std::string_view keys which can
dangle; change the map key to std::string (i.e., std::unordered_map<std::string,
std::int16_t> store) and update any call sites (e.g., logging.reset("receive",
5)) to rely on implicit conversion or explicitly construct std::string where
necessary so stored keys own their data; adjust constructors/insert/emplace
usages in the class (look for store and the reset method) to copy names into the
map and remove any requirement that callers provide static-lifetime strings.

In `@src/utility/shared/context.hpp`:
- Line 68: 当前对 AutoAimState 的静态断言仅使用本文件的 context_trait(只检查 trivially
copyable),未保证 IPC 元数据 kLabel/kLength 存在;请将对应断言改为使用
rmcs::kernel::context_trait(例如
static_assert(rmcs::kernel::context_trait<AutoAimState>))以强制验证 kLabel/kLength 等
IPC 必需概念,并对文件中所有类似位置(包括第105行对应断言)一并替换,确保在编译期就能捕获缺失元数据的问题。
- Around line 11-12: The concept context_trait in namespace rmcs conflicts
semantically with rmcs::kernel::context_trait (one checks
std::is_trivially_copyable_v<T>, the other requires kLabel/kLength); rename the
trivial copy concept (e.g., to trivially_shareable or shm_trivial) in the header
where context_trait is defined, update all local uses (e.g.,
static_assert(context_trait<AutoAimState>) and any templates or constraints
referencing context_trait) to the new name, and run a quick project-wide search
for context_trait to ensure only the intended kernel concept remains under
rmcs::kernel::context_trait or alternatively rename the kernel concept (e.g.,
feishu_message) if that fits your design.
🪄 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: 6c00119f-c605-4d40-ad14-92b633c8f04a

📥 Commits

Reviewing files that changed from the base of the PR and between 39456e9 and d9cd95e.

📒 Files selected for processing (8)
  • src/component.cpp
  • src/kernel/feishu.hpp
  • src/runtime.cpp
  • src/utility/logging_util.hpp
  • src/utility/shared/context.hpp
  • test/CMakeLists.txt
  • test/action_throttler.cpp
  • test/feishu_test.cpp
💤 Files with no reviewable changes (2)
  • test/action_throttler.cpp
  • test/CMakeLists.txt

Comment thread src/component.cpp
Comment on lines 129 to 133
auto handle_tf_not_ready() -> void {
action_throttler.dispatch("tf_not_ready", [&] { rclcpp.warn("rmcs_tf is not ready"); });
control_state.reset();
control_state = ControlState::kInvalid();
publish_auto_aim_outputs(make_invalid_auto_aim_state());
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

handle_tf_not_readycontrol_state = ControlState::kInvalid() 实际上是死赋值。

该分支在 Line 50 直接 return,并不会走到 publish_control_state();下一帧 tf 就绪后,update_control_state() 会把 timestamp/yaw/pitch/odom_to_camera_transform/invincible_devices 等字段全部覆盖。也就是说这次 kInvalid() 赋值不会被发送出去,也不会被下一次发送看到。

如果意图是"tf 未就绪期间也要让对端收到 invalid 信号",应改为在此分支 feishu.with_write(...) 一次;如果意图只是把内部状态清空,那么这一行可以直接删掉。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/component.cpp` around lines 129 - 133, 在 handle_tf_not_ready 中当前对
control_state 进行 control_state = ControlState::kInvalid() 会被后续
update_control_state 覆盖且不会触发 publish_control_state(),所以请根据意图处理:如果希望在 tf
未就绪期间通知对端发送 invalid 状态,则在该分支内调用 feishu.with_write(...)(用现有写入/发布路径直接写出并发送包含
kInvalid 的 control_state 或调用 publish_control_state()
的等价写入操作);如果只是想清空内部状态且不通知对端,则删除 control_state = ControlState::kInvalid()
这一行。保持现有对 publish_auto_aim_outputs(make_invalid_auto_aim_state())
的调用不变或与写入操作配对发送。

Comment thread src/runtime.cpp Outdated
Comment thread src/utility/logging_util.hpp
Comment thread src/utility/shared/context.hpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/runtime.cpp (1)

51-51: 变量名 without_rmcs 与配置键 is_local_runtime 语义反向,建议统一。

读取的是 configuration["is_local_runtime"],但局部变量改名为 without_rmcs。两者在布尔语义上确实等价(无 RMCS ↔ 本地运行),但命名反向会让 Line 118 的 if (!without_rmcs && updated) 多一层心智负担——读者需先把 "without_rmcs == is_local_runtime" 在脑内换算一次,然后再加一个否定。

建议直接命名为 is_local_runtime,与配置 key 保持一致:

♻️ 命名对齐
-    auto without_rmcs      = configuration["is_local_runtime"].as<bool>();
+    auto is_local_runtime  = configuration["is_local_runtime"].as<bool>();
@@
-        if (!without_rmcs && updated) {
+        if (!is_local_runtime && updated) {
             received = *feishu.latest();
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/runtime.cpp` at line 51, The local variable name without_rmcs is
confusing relative to the config key configuration["is_local_runtime"]; rename
the variable to is_local_runtime to match the config key (e.g., change auto
without_rmcs = configuration["is_local_runtime"].as<bool>(); to auto
is_local_runtime = ...), then update all usages of without_rmcs throughout the
file (for example change if (!without_rmcs && updated) to if (!is_local_runtime
&& updated) so behavior stays identical while names align and you remove the
mental inversion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/runtime.cpp`:
- Around line 34-36: The "receive" logging channel is registered via
logging.reset("receive", 5) but never used later, indicating either missing log
calls for ControlState receive failures/timeouts or dead code; update the
ControlState freshness/receive handling (where ControlState is validated in the
main loop) to emit logging.warn("receive", ...) or logging.error("receive", ...)
on stale/missing/timeout conditions, or remove the logging.reset("receive", 5)
call if you decide the receive logs are not needed—ensure you modify the code
paths that process ControlState (the main loop that checks freshness) so they
call the "receive" channel when appropriate to keep registrations consistent.
- Around line 117-120: The current logic discards buffered ControlState when
updated==false and uses ControlState::kInvalid(), causing NaNs to flow into
pose_estimator.set_odom_to_camera_transform, fire_control.solve and feishu.send;
instead always read feishu.latest() (regardless of feishu.heartbeat()/updated),
check the latest state's timestamp against a freshness threshold (reuse the
kAutoAimTimeout/has_fresh_auto_aim_state() pattern from src/component.cpp) and
only fallback to ControlState::kInvalid() when the buffer is empty or the latest
entry is stale; if stale/empty, explicitly skip downstream consumers or set a
clear “no-fresh-control” flag so pose_estimator, fire_control.solve and
feishu.send do not consume NaN values.

---

Nitpick comments:
In `@src/runtime.cpp`:
- Line 51: The local variable name without_rmcs is confusing relative to the
config key configuration["is_local_runtime"]; rename the variable to
is_local_runtime to match the config key (e.g., change auto without_rmcs =
configuration["is_local_runtime"].as<bool>(); to auto is_local_runtime = ...),
then update all usages of without_rmcs throughout the file (for example change
if (!without_rmcs && updated) to if (!is_local_runtime && updated) so behavior
stays identical while names align and you remove the mental inversion.
🪄 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: cebff857-adbe-4e51-9236-8c46f1b66e4b

📥 Commits

Reviewing files that changed from the base of the PR and between d9cd95e and 19ce0eb.

📒 Files selected for processing (2)
  • src/runtime.cpp
  • src/utility/tf/static_tf.hpp
✅ Files skipped from review due to trivial changes (1)
  • src/utility/tf/static_tf.hpp

Comment thread src/runtime.cpp
Comment thread src/runtime.cpp
@creeper5820
creeper5820 merged commit bccd90b into main Apr 26, 2026
2 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in RMCS Auto Aim V2 Apr 26, 2026
@creeper5820
creeper5820 deleted the refactor/feishu branch April 26, 2026 00:48
@coderabbitai coderabbitai Bot mentioned this pull request Jun 24, 2026
Sign up for free to 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.

1 participant