Skip to content

refactor: pose estimator#43

Merged
creeper5820 merged 4 commits intomainfrom
refactor/pose_estimator
May 1, 2026
Merged

refactor: pose estimator#43
creeper5820 merged 4 commits intomainfrom
refactor/pose_estimator

Conversation

@creeper5820
Copy link
Copy Markdown
Collaborator

No description provided.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

Warning

Rate limit exceeded

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

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ 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: e7147324-9f87-4b3a-b7ee-b1e32007f158

📥 Commits

Reviewing files that changed from the base of the PR and between 5a8663b and ffe7bfe.

📒 Files selected for processing (13)
  • config/config.yaml
  • src/component.cpp
  • src/kernel/pose_estimator.cpp
  • src/kernel/pose_estimator.hpp
  • src/kernel/visualization.cpp
  • src/runtime.cpp
  • src/utility/math/camera.cpp
  • src/utility/math/camera.hpp
  • src/utility/math/linear.hpp
  • src/utility/math/solve_pnp/yaw_optimizer.cpp
  • src/utility/shared/context.hpp
  • test/feishu_test.cpp
  • test/transform_communication.cpp

Walkthrough

该PR进行了广泛的系统重构,重命名了核心类型(ControlStateSystemContext),重设了姿态估计管道(移除solve_pnp,新增estimate_armor和偏航优化),引入了新的工具类(ImageRecorderCameraFeatureYawOptimizerAdapter),更新了配置参数和火控/追踪逻辑,并重构了可视化API与共享上下文通信模式。

Changes

Cohort / File(s) 摘要
文档与配置更新
AGENTS.md, config/config.yaml
更新开发指南结构,移除指令冲突部分;调整全局运行时标志、模型选择、火控参数(初速度、角度阈值)、相机配置和追踪颜色设置。
Adapter与组件集成
src/adapter/sentry.hpp, src/component.cpp
新增Adapter类封装TF变换查询;重构组件输出主题和控制流,用适配器替代直接TF操作,改为基于SystemContext驱动控制。
相机与线性代数基础设施
src/utility/math/camera.hpp, src/utility/math/camera.cpp, src/utility/math/linear.hpp
新增CameraFeatureTransform类型,完善几何基元(Scalar2dScalar3dOrientation),重构坐标转换特征系统。
PnP与偏航优化求解
src/utility/math/solve_pnp/pnp_solution.hpp, src/utility/math/solve_pnp/pnp_solution.cpp, src/utility/math/solve_pnp/yaw_optimizer.hpp, src/utility/math/solve_pnp/yaw_optimizer.cpp
更新PnP输入以使用CameraFeature;新增YawOptimizer模块进行装甲板偏航精化。
姿态估计重构
src/kernel/pose_estimator.hpp, src/kernel/pose_estimator.cpp
移除solve_pnp和IMU接口,新增estimate_armorinto_odom_link;集成偏航优化;重构变换管理。
可视化API重构
src/kernel/visualization.hpp, src/kernel/visualization.cpp, src/utility/rclcpp/visual/arrow.hpp, src/utility/rclcpp/visual/arrow.cpp, src/utility/robot/armor.hpp
重命名send_imageupdate_image;移除solved_pnp_armors/predicted_armors,新增update_visible_armorsupdate_visible_robotupdate_aiming_directionupdate_camera_pose;新增Arrow可视化组件和ArmorVisualScale/ArmorVisualColor辅助类。
火控与追踪
src/kernel/fire_control.hpp, src/kernel/fire_control.cpp, src/module/fire_control/aim_point_chooser.hpp, src/module/fire_control/aim_point_chooser.cpp, src/module/tracker/decider.hpp, src/module/tracker/decider.cpp
移除angular_velocity_threshold;重构目标选择逻辑为基于窗口的过滤;更新追踪决策为确定性排序;重命名allow_takeoverallow_control
预测器与EKF
src/module/predictor/regular/ekf_parameter.hpp, src/module/predictor/regular/robot_state.hpp, src/module/predictor/regular/robot_state.cpp, src/module/predictor/snapshot.hpp
调整EKF初始协方差;增强match()update_single()的验证门控;新增便利方法predicted_armors()
共享上下文与Feishu通信
src/utility/shared/context.hpp, src/runtime.cpp
移除Transform,将ControlState重命名为SystemContext;重命名AutoAimState字段(gimbal_takeovershould_controlshoot_permittedshould_shoot);更新运行时loop使用SystemContextfeishu.search(...)
图像录制与图像工具
src/utility/image/image.hpp, src/utility/image/image.cpp, src/utility/image/recorder.hpp, src/utility/image/recorder.cpp, src/module/debug/recorder.hpp
新增Image::clone()方法;完整实现ImageRecorder类支持视频录制、历史管理和自动保存;移除旧的Recorder类。
采集与数学工具
src/kernel/capturer.cpp, src/utility/math/kalman_filter/ekf.hpp, src/utility/math/mahalanobis.hpp, src/utility/math/conversion.hpp, src/utility/math/point.hpp
修改fetch_image()以获取队列中最新帧;为EKF暴露可变的P()访问器;优化LDLT分解复用;移除point.hpp
可视化调试与移动接口
src/module/debug/visualization/armor_visualizer.hpp, src/module/debug/visualization/armor_visualizer.cpp, src/module/debug/visualization/stream_session.cpp, src/utility/rclcpp/visual/movable.hpp
集中化标记样式逻辑;更新流式传输以获取最新帧;更新特征约束从translation_traitscalar3d_trait
包含管理与工具链
src/module/predictor/robot_state.hpp, src/module/predictor/robot_state.cpp, test/CMakeLists.txt, test/feishu_test.cpp, test/image_recorder.cpp, test/solve_pnp.cpp, test/transform_communication.cpp, tool/CMakeLists.txt, tool/hikcamera.cpp
调整包含顺序;新增图像录制器测试和工具;更新现有测试以适应类型重命名;为hikcamera工具添加异步录制功能。

Sequence Diagram(s)

sequenceDiagram
    participant Runtime as Runtime Loop
    participant Feishu as Feishu<br/>(Comm)
    participant Adapter as Adapter<br/>(TF)
    participant Detector as Detector
    participant PoseEst as PoseEstimator
    participant YawOpt as YawOptimizer
    participant FireCtrl as FireControl
    participant Tracker as Tracker
    participant Viz as Visualization

    Note over Runtime: Main Loop Iteration

    Runtime->>Feishu: heartbeat()
    Feishu-->>Runtime: ok

    Runtime->>Feishu: search(image_ts, 50ms)
    Feishu-->>Runtime: SystemContext

    Runtime->>Adapter: ready()
    Adapter-->>Runtime: bool

    Runtime->>Adapter: camera_transform()
    Adapter-->>Runtime: Transform

    Runtime->>Detector: detect(image)
    Detector-->>Runtime: Armor2D[]

    Runtime->>PoseEst: estimate_armor(Armor2D[])
    PoseEst->>YawOpt: solve(camera_feature, armor_shape, corners)
    YawOpt-->>PoseEst: Orientation (optimized yaw)
    PoseEst-->>Runtime: Armor3D[]

    Runtime->>PoseEst: into_odom_link(Armor3D[])
    PoseEst-->>Runtime: Armor3D[] (transformed)

    Runtime->>Tracker: update(Armor3D[], context)
    Tracker-->>Runtime: Snapshot

    Runtime->>FireCtrl: solve(Snapshot, context)
    FireCtrl-->>Runtime: (control_dir, should_shoot)

    Runtime->>Viz: update_camera_pose(context.camera_transform)
    Runtime->>Viz: update_visible_armors(Armor3D[])
    Runtime->>Viz: update_aiming_direction(yaw, pitch)
    Runtime->>Viz: update_image(image)

    Note over Runtime: Publish control output
Loading
sequenceDiagram
    participant Tool as hikcamera Tool
    participant Capturer as Capturer
    participant ImageRec as ImageRecorder
    participant Queue as Frame Queue
    participant Worker as Record Worker

    Note over Tool: Recording Flow (Async)

    Tool->>ImageRec: set_saving_location(path)
    Tool->>ImageRec: set_framerate(30)

    Tool->>Worker: request_start_recording()
    activate Worker

    loop Per Frame
        Capturer->>Capturer: fetch_image()
        Note over Capturer: Drain queue,<br/>return latest

        Tool->>Queue: push(cloned_frame)
        
        Worker->>Queue: dequeue_burst()
        Worker->>ImageRec: write_frame(frame)
        ImageRec->>ImageRec: encode & save
    end

    Tool->>Worker: request_stop_recording()
    deactivate Worker
    Worker->>ImageRec: stop()
    ImageRec-->>Worker: last_saved_path
    Tool->>Tool: display saved path & stats
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • PR #25: 直接修改火控、AimPointChooser、配置参数和共享上下文类型,与本PR的火控重构和ControlStateSystemContext重命名高度重叠。
  • PR #12: 同时修改PnP管道、PoseEstimator、相机标定和可视化钩子,涉及相同的函数/类型重构。
  • PR #42: 新增相同的工具类(AdapterYawOptimizerCameraFeatureImageRecorder)和匹配的API重构。

Suggested labels

enhancement

Suggested reviewers

  • heyeuu

Poem

🐰✨ 码改得妙,架构轻盈飘,
相机变换巧,偏航优化了,
追踪更精准,画面更绚烂! 🎯🔥

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.20% 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 标题准确地概括了核心变化:重构姿态估计器模块及其相关依赖的API,改变了PnP求解方式、坐标转换、可视化流程等。
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/pose_estimator

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
Review rate limit: 0/1 reviews remaining, refill in 47 minutes and 19 seconds.

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (3)
AGENTS.md (1)

17-25: ⚡ Quick win

建议补充“指令优先级/冲突处理”小节,减少执行歧义。

当前文档同时定义了 SOP、代码风格和协作规范,但未明确冲突时的优先级,后续多 Agent/多人协作下容易出现执行不一致。建议加一个简短规则段落。

📌 建议补充示例
 ## Agent 协作开发规范(Auto Aim)
 
 本文件用于约束 Agent 在本仓库中的行为,目标是:
@@
 - 让 Agent 在可控范围内稳定提供辅助价值
+
+### 指令优先级与冲突处理
+
+- 若出现冲突,按“系统/平台指令 > 开发者当前明确指令 > 本文档 > 其他参考资料”执行
+- 发生冲突时在回复中显式说明采用了哪条高优先级指令
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 17 - 25, 在 AGENTS.md 中在 “核心原则:算法开发由人类主导” 下新增一个名为
“指令优先级/冲突处理” 的短段落,明确列出冲突决策顺序(例如:人类指令 > 项目SOP/安全策略 > 代码风格/约定 > Agent
自动建议),并说明遇到指令或规范冲突时应如何记录(谁做出决定、理由、变更记录位置)和如何通知协作成员(PR/Issue/日志);引用现有标题文本(“核心原则:算法开发由人类主导”)来定位插入点并保证语言简洁可执行。
src/utility/math/solve_pnp/yaw_optimizer.hpp (1)

3-8: ⚡ Quick win

建议统一头文件分组顺序,避免风格漂移。

这里建议按“本地 → 标准库 → 第三方”分组,和仓库其余头文件保持一致。

♻️ 建议修改
-#include <array>
-
 `#include` "utility/math/camera.hpp"
 `#include` "utility/math/linear.hpp"
 `#include` "utility/robot/id.hpp"
+
+#include <array>

As per coding guidelines: **/*.{h,hpp,hxx}: Header files should follow the order: local headers, standard library headers, third-party library headers, with blank lines separating each section (can merge into one block when headers are few).

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

In `@src/utility/math/solve_pnp/yaw_optimizer.hpp` around lines 3 - 8, The include
order in yaw_optimizer.hpp is inconsistent with project style; reorder the
includes so local headers come first (utility/math/camera.hpp,
utility/math/linear.hpp, utility/robot/id.hpp), then the standard library header
(array), and ensure a blank line separates the local block from the
standard-library block; update the include block in yaw_optimizer.hpp
accordingly to match the "local → standard → third-party" grouping.
src/utility/math/camera.hpp (1)

3-7: ⚡ Quick win

请按仓库规范调整头文件分组顺序。

当前顺序是“标准库 → 第三方 → 本地”,与仓库约定不一致。建议改为“本地 → 标准库 → 第三方”,并保留分组空行。

♻️ 建议修改
-#include <array>
-#include <opencv2/core/mat.hpp>
-
 `#include` "utility/math/linear.hpp"
+
+#include <array>
+#include <opencv2/core/mat.hpp>

As per coding guidelines: **/*.{h,hpp,hxx}: Header files should follow the order: local headers, standard library headers, third-party library headers, with blank lines separating each section (can merge into one block when headers are few).

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

In `@src/utility/math/camera.hpp` around lines 3 - 7, In
src/utility/math/camera.hpp reorder the `#include` blocks to match repository
convention: place local headers first (e.g. `#include` "utility/math/linear.hpp"),
then standard library headers (e.g. `#include` <array>), then third‑party headers
(e.g. `#include` <opencv2/core/mat.hpp>), keeping blank lines between each group;
update the three include lines shown so they appear in the order:
"utility/math/linear.hpp", then "<array>", then "<opencv2/core/mat.hpp>".
🤖 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 54-60: The timeout check using Clock::now() and kAutoAimTimeout
currently sets *should_control and *should_shoot to false but is immediately
overwritten by unguarded assignments from command.should_control and
command.should_shoot; fix by preventing the later assignments when the timeout
condition is true — either return early after setting
*should_control/*should_shoot to false or make the assignments conditional (e.g.
only assign from command.should_control/command.should_shoot when (Clock::now()
- command.timestamp) <= kAutoAimTimeout) so the timeout protection is not
overwritten.
- Around line 51-52: When feishu.heartbeat() returns false you must explicitly
disable or reset any active control outputs instead of simply returning; update
the branch around the feishu.heartbeat() call so that on failure you (1) disable
the control path (e.g., clear/send-off to actuators or call the component's
control-disable method), (2) reset any persistent output state/flags (e.g.,
control_enabled = false or zero outputs), and (3) then return. Locate the
heartbeat check (feishu.heartbeat()) in component.cpp and invoke the
module/utility that turns off outputs or zeroes commands before returning to
avoid leaving previous outputs active.

In `@src/kernel/capturer.cpp`:
- Around line 90-97: fetch_image() currently drains the entire capture_queue and
returns only the newest frame, which breaks the semantics of
local_video.allow_skipping; change fetch_image() (and/or add a Capturer member
like allow_skipping_) so that when allow_skipping is false it returns the next
frame in FIFO order (pop a single frame and return it) preserving sequence, and
only when allow_skipping is true perform the current drain-to-latest behavior;
update any call sites relying on fetch_image() (e.g., the main loop in runtime
that expects no-skipping behavior) to read the new flag from the Capturer
instance.

In `@src/kernel/pose_estimator.hpp`:
- Around line 15-21: The header pose_estimator.hpp exposes Transform, std::span
and std::vector via the APIs (update_camera_transform, estimate_armor,
into_odom_link) but does not explicitly include the corresponding headers; add
explicit includes for <span> and <vector> and also include the local math header
"utility/math/linear.hpp" to make Transform/type dependencies clear; finally
reorder the include block so local project headers (e.g.,
"utility/math/linear.hpp", "utility/robot/armor.hpp") appear before
standard/third-party headers to follow the project include-order guideline.

In `@src/utility/image/recorder.cpp`:
- Line 205: The ImageRecorder currently allows invalid configuration (e.g.,
framerate == 0, negative durations, min_duration > max_duration) which leads to
silent non-recording; update ImageRecorder to perform fail-fast validation when
configuration is applied (e.g., in the configuration setter or initialization
path that mutates pimpl), validate fields like framerate, duration, min_duration
and max_duration and if any are invalid: return an error / throw an exception
(or log and set an explicit error state) rather than silently accepting them;
ensure the validation lives next to the existing setter
(ImageRecorder::set_saving_location and the pimpl-backed config setters) and
references pimpl->framerate, pimpl->min_duration, pimpl->max_duration (or their
actual names) so invalid values are rejected immediately with a clear error
message.

In `@src/utility/math/linear.hpp`:
- Line 68: The three uses of static_assert(false, ...) in the template functions
(e.g., inside clone_scalar2d and the other two branches) are non-dependent and
fire at template definition time; add a dependent-false helper template (e.g.,
template<class...> inline constexpr bool dependent_false_v = false;) and replace
each static_assert(false, "...") with static_assert(dependent_false_v<Src, Dst>,
"...") (or use the actual template parameter pack for that function) so the
assertion becomes dependent on template parameters and is evaluated only at
instantiation.

In `@src/utility/math/solve_pnp/yaw_optimizer.cpp`:
- Around line 76-77: The yaw search loop is coupling the iteration count to a
hardcoded assumption that kSearchStepDeg == 1 and misses the +70° boundary;
change the loop to compute the number of samples from the range and step (e.g.
samples = round(kSearchRangeDeg / kSearchStepDeg) + 1) and iterate i from 0 to
samples-1 so candidate_yaw = yaw_start + i * deg2rad(kSearchStepDeg) covers both
endpoints; update the loop that produces candidate_yaw (references: yaw_start,
kSearchRangeDeg, kSearchStepDeg, deg2rad, candidate_yaw) to use this computed
sample count instead of static_cast<int>(kSearchRangeDeg).

In `@src/utility/rclcpp/visual/arrow.hpp`:
- Around line 1-5: arrow.hpp currently relies on indirect includes but uses
std::string and std::unique_ptr; explicitly include the missing standard headers
by adding <string> and <memory> at the top of the header so usages of
std::string and std::unique_ptr are guaranteed (update the include list near the
existing includes "utility/rclcpp/node.hpp" and
"utility/rclcpp/visual/movable.hpp").

In `@tool/hikcamera.cpp`:
- Around line 149-153: shutdown() writes shared flag enabled without locking
while the worker reads/writes enabled/stop_pending under a mutex, causing a data
race; update shutdown() (and the similar code at the other occurrence) to
acquire the same mutex used by the worker before modifying enabled/stop_pending,
set the flag(s) while holding the lock, then release and call cv.notify_one()
(or notify after unlocking) and join the worker; reference the member names
enabled, stop_pending, the shutdown() method, the worker thread lambda/function,
and the cv/mutex pair to locate and fix the accesses.
- Around line 68-130: The worker recreation can deadlock because assigning a new
std::jthread to member worker will join the old thread while that thread may be
blocked and not exiting; before creating or assigning a new worker in start(),
request the old thread to stop and wake it: set stop_requested = true (or
enabled = false), call cv.notify_all(), and call worker.request_stop() if used;
then wait for the old worker to finish without holding mutex (e.g., release
locks, then let the old jthread be destroyed/assigned) before constructing the
new std::jthread; update start() to ensure you don't hold mutex across the
worker reassignment and use worker/request_stop()/cv.notify_all() to guarantee
the old loop sees the stop signal and exits.

---

Nitpick comments:
In `@AGENTS.md`:
- Around line 17-25: 在 AGENTS.md 中在 “核心原则:算法开发由人类主导” 下新增一个名为 “指令优先级/冲突处理”
的短段落,明确列出冲突决策顺序(例如:人类指令 > 项目SOP/安全策略 > 代码风格/约定 > Agent
自动建议),并说明遇到指令或规范冲突时应如何记录(谁做出决定、理由、变更记录位置)和如何通知协作成员(PR/Issue/日志);引用现有标题文本(“核心原则:算法开发由人类主导”)来定位插入点并保证语言简洁可执行。

In `@src/utility/math/camera.hpp`:
- Around line 3-7: In src/utility/math/camera.hpp reorder the `#include` blocks to
match repository convention: place local headers first (e.g. `#include`
"utility/math/linear.hpp"), then standard library headers (e.g. `#include`
<array>), then third‑party headers (e.g. `#include` <opencv2/core/mat.hpp>),
keeping blank lines between each group; update the three include lines shown so
they appear in the order: "utility/math/linear.hpp", then "<array>", then
"<opencv2/core/mat.hpp>".

In `@src/utility/math/solve_pnp/yaw_optimizer.hpp`:
- Around line 3-8: The include order in yaw_optimizer.hpp is inconsistent with
project style; reorder the includes so local headers come first
(utility/math/camera.hpp, utility/math/linear.hpp, utility/robot/id.hpp), then
the standard library header (array), and ensure a blank line separates the local
block from the standard-library block; update the include block in
yaw_optimizer.hpp accordingly to match the "local → standard → third-party"
grouping.
🪄 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: 9b8b7c45-93c6-4cfd-b610-cad7afb9ed6d

📥 Commits

Reviewing files that changed from the base of the PR and between a64efc1 and 5a8663b.

📒 Files selected for processing (56)
  • AGENTS.md
  • config/config.yaml
  • src/adapter/adapter.hpp
  • src/adapter/sentry.hpp
  • src/component.cpp
  • src/kernel/capturer.cpp
  • src/kernel/fire_control.cpp
  • src/kernel/fire_control.hpp
  • src/kernel/pose_estimator.cpp
  • src/kernel/pose_estimator.hpp
  • src/kernel/visualization.cpp
  • src/kernel/visualization.hpp
  • src/module/debug/recorder.hpp
  • src/module/debug/visualization/armor_visualizer.cpp
  • src/module/debug/visualization/armor_visualizer.hpp
  • src/module/debug/visualization/stream_session.cpp
  • src/module/fire_control/aim_point_chooser.cpp
  • src/module/fire_control/aim_point_chooser.hpp
  • src/module/predictor/outpost/robot_state.cpp
  • src/module/predictor/regular/ekf_parameter.hpp
  • src/module/predictor/regular/robot_state.cpp
  • src/module/predictor/regular/robot_state.hpp
  • src/module/predictor/robot_state.cpp
  • src/module/predictor/robot_state.hpp
  • src/module/predictor/snapshot.hpp
  • src/module/tracker/decider.cpp
  • src/module/tracker/decider.hpp
  • src/runtime.cpp
  • src/utility/image/image.cpp
  • src/utility/image/image.hpp
  • src/utility/image/recorder.cpp
  • src/utility/image/recorder.hpp
  • src/utility/math/camera.cpp
  • src/utility/math/camera.hpp
  • src/utility/math/conversion.hpp
  • src/utility/math/kalman_filter/ekf.hpp
  • src/utility/math/linear.hpp
  • src/utility/math/mahalanobis.hpp
  • src/utility/math/point.hpp
  • src/utility/math/solve_pnp/pnp_solution.cpp
  • src/utility/math/solve_pnp/pnp_solution.hpp
  • src/utility/math/solve_pnp/yaw_optimizer.cpp
  • src/utility/math/solve_pnp/yaw_optimizer.hpp
  • src/utility/rclcpp/visual/armor.cpp
  • src/utility/rclcpp/visual/arrow.cpp
  • src/utility/rclcpp/visual/arrow.hpp
  • src/utility/rclcpp/visual/movable.hpp
  • src/utility/robot/armor.hpp
  • src/utility/shared/context.hpp
  • test/CMakeLists.txt
  • test/feishu_test.cpp
  • test/image_recorder.cpp
  • test/solve_pnp.cpp
  • test/transform_communication.cpp
  • tool/CMakeLists.txt
  • tool/hikcamera.cpp
💤 Files with no reviewable changes (5)
  • src/kernel/fire_control.hpp
  • src/module/predictor/robot_state.cpp
  • src/module/debug/visualization/armor_visualizer.hpp
  • src/module/debug/recorder.hpp
  • src/utility/math/point.hpp

Comment thread src/component.cpp
Comment thread src/component.cpp
Comment on lines +54 to +60
if (Clock::now() - command.timestamp > kAutoAimTimeout) {
*should_control = false;
*should_shoot = false;
}

const auto& [yaw, pitch] = std::tie(state.yaw, state.pitch);
*should_control = command.should_control;
*should_shoot = command.should_shoot;
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 | 🔴 Critical | ⚡ Quick win

超时保护被后续赋值覆盖,导致失效。

Line 54-57 置 false 后,Line 59-60 又无条件回写 command.should_*,超时命令仍可生效。

建议修复(示例)
         auto command = *feishu.latest();
         if (Clock::now() - command.timestamp > kAutoAimTimeout) {
             *should_control = false;
             *should_shoot   = false;
+            return;
         }
 
         *should_control = command.should_control;
         *should_shoot   = command.should_shoot;
📝 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
if (Clock::now() - command.timestamp > kAutoAimTimeout) {
*should_control = false;
*should_shoot = false;
}
const auto& [yaw, pitch] = std::tie(state.yaw, state.pitch);
*should_control = command.should_control;
*should_shoot = command.should_shoot;
if (Clock::now() - command.timestamp > kAutoAimTimeout) {
*should_control = false;
*should_shoot = false;
return;
}
*should_control = command.should_control;
*should_shoot = command.should_shoot;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/component.cpp` around lines 54 - 60, The timeout check using Clock::now()
and kAutoAimTimeout currently sets *should_control and *should_shoot to false
but is immediately overwritten by unguarded assignments from
command.should_control and command.should_shoot; fix by preventing the later
assignments when the timeout condition is true — either return early after
setting *should_control/*should_shoot to false or make the assignments
conditional (e.g. only assign from command.should_control/command.should_shoot
when (Clock::now() - command.timestamp) <= kAutoAimTimeout) so the timeout
protection is not overwritten.

Comment thread src/kernel/capturer.cpp
Comment on lines +90 to +97
// 为了实时性,一般取最新的帧
auto fetch_image() noexcept -> ImageUnique {
auto raw = RawImage { nullptr };
capture_queue.pop(raw);
return std::unique_ptr<Image> { raw };
auto result = ImageUnique { nullptr };
auto image = RawImage { };
while (capture_queue.pop(image)) {
result = ImageUnique { image };
}
return result;
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 | 🟠 Major | ⚡ Quick win

不要在 fetch_image() 里无条件丢弃中间帧。

这里把队列一次性 drain 到最新帧后,local_video.allow_skipping: false 的语义就失效了。只要 src/runtime.cpp:110-114 的主循环一轮处理慢于采集线程,就会直接跳过中间视频帧,无法再保证按顺序完整播放。建议把“只取最新帧”的策略限制在允许跳帧的来源/模式下,或者把丢帧策略显式做成 Capturer 级配置。

Based on learnings: "when allow_skipping is false, the intended behavior is to play all frames strictly in sequence without caring about actual elapsed time; when allow_skipping is true, the intended behavior is to maintain the expected playback rate and catch up when falling behind."

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

In `@src/kernel/capturer.cpp` around lines 90 - 97, fetch_image() currently drains
the entire capture_queue and returns only the newest frame, which breaks the
semantics of local_video.allow_skipping; change fetch_image() (and/or add a
Capturer member like allow_skipping_) so that when allow_skipping is false it
returns the next frame in FIFO order (pop a single frame and return it)
preserving sequence, and only when allow_skipping is true perform the current
drain-to-latest behavior; update any call sites relying on fetch_image() (e.g.,
the main loop in runtime that expects no-skipping behavior) to read the new flag
from the Capturer instance.

Comment on lines 15 to +21
auto initialize(const YAML::Node&) noexcept -> std::expected<void, std::string>;
auto update_camera_transform(Transform const& transform) -> void;

auto visualize(RclcppNode& visual_node) -> void;

auto solve_pnp(std::vector<Armor2D> const&) const -> std::optional<std::vector<Armor3D>>;

auto set_odom_to_camera_transform(Transform const& transform) -> void;
auto estimate_armor(std::vector<Armor2D> const&) const -> std::vector<Armor3D>;

auto odom_to_camera(std::span<Armor3D const> armors) const -> std::vector<Armor3D>;
auto odom_to_camera(Armor3D const& armor) const -> Armor3D;

auto update_imu_link(const Orientation&) noexcept -> void;
auto into_odom_link(std::span<Armor3D const> armors) const -> std::vector<Armor3D>;
auto into_odom_link(Armor3D const& armor) const -> Armor3D;
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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n src/kernel/pose_estimator.hpp | head -40

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 871


🏁 Script executed:

# Check the current includes in the file
rg "#include" src/kernel/pose_estimator.hpp -A 1 -B 1

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 193


🏁 Script executed:

# Search for Transform definition and its header
fd -t f -e hpp -e h | xargs rg "class Transform|struct Transform" | head -20

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 195


🏁 Script executed:

# Check if utility/math/linear.hpp is already included indirectly through other headers
rg "#include.*linear" src/kernel/pose_estimator.hpp

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 61


🏁 Script executed:

# Check what's in utility/robot/armor.hpp - see if it includes the Transform or vector/span
cat -n src/utility/robot/armor.hpp | head -50

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 1843


🏁 Script executed:

# Check what's in utility/pimpl.hpp
cat -n src/utility/pimpl.hpp | head -50

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 1366


🏁 Script executed:

# Check the implementation file to see which Transform is imported
fd -t f -e cpp -e cxx | xargs rg "pose_estimator" -l

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 125


🏁 Script executed:

# Search for Transform usage in pose_estimator implementation or related files
rg "Transform" src/kernel/ -B 2 -A 2

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 1844


🏁 Script executed:

# Verify the include order guideline by checking if other header files in the codebase follow the local-standard-third-party order
fd -t f -e hpp | head -5 | xargs -I {} sh -c 'echo "=== {} ===" && head -20 {}'

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 2304


🏁 Script executed:

# Check what Armor2D and Armor3D are to ensure we need vector
rg "struct Armor3D|class Armor3D" -A 3

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 264


🏁 Script executed:

# Check the correct include order more carefully by looking at capturer.hpp which seems to follow it
cat -n src/kernel/capturer.hpp | head -15

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 453


补回 PoseEstimator 新 API 的显式依赖,并修正头文件包含顺序。

update_camera_transform() / estimate_armor() / into_odom_link() 直接暴露了 Transformstd::spanstd::vector,但这个头文件缺少 <span><vector> 的显式包含。虽然 Transform 可通过 "utility/robot/armor.hpp" 传递获得,但建议显式包含 "utility/math/linear.hpp" 以提高清晰度。

此外,当前包含顺序不符合编码规范。根据指南,本地头文件应先于标准库和第三方头文件。

🔧 建议修正
 `#pragma` once
 
+#include "utility/math/linear.hpp"
+#include "utility/pimpl.hpp"
+#include "utility/robot/armor.hpp"
+
 `#include` <expected>
+#include <span>
+#include <vector>
 `#include` <yaml-cpp/yaml.h>
-
-#include "utility/pimpl.hpp"
-#include "utility/robot/armor.hpp"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/kernel/pose_estimator.hpp` around lines 15 - 21, The header
pose_estimator.hpp exposes Transform, std::span and std::vector via the APIs
(update_camera_transform, estimate_armor, into_odom_link) but does not
explicitly include the corresponding headers; add explicit includes for <span>
and <vector> and also include the local math header "utility/math/linear.hpp" to
make Transform/type dependencies clear; finally reorder the include block so
local project headers (e.g., "utility/math/linear.hpp",
"utility/robot/armor.hpp") appear before standard/third-party headers to follow
the project include-order guideline.

}
};

auto ImageRecorder::set_saving_location(const std::string& path) -> void { pimpl->location = path; }
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 | 🟠 Major | ⚡ Quick win

在配置入口增加 fail-fast 参数校验,避免“静默不录制”。

Line [207]、Line [213]、Line [217] 当前允许无效配置(如 framerate=0、负时长、min_duration > max_duration),后续会表现为录制失败或文件总被丢弃,但没有明确错误反馈。

🔧 建议修复
 `#include` "recorder.hpp"
+ `#include` "utility/panic.hpp"
@@
 auto ImageRecorder::set_saving_location(const std::string& path) -> void { pimpl->location = path; }

-auto ImageRecorder::set_framerate(std::size_t rate) -> void { pimpl->framerate = rate; }
+auto ImageRecorder::set_framerate(std::size_t rate) -> void {
+    if (rate == 0) {
+        util::panic("ImageRecorder: framerate must be greater than 0");
+    }
+    pimpl->framerate = rate;
+}
@@
 auto ImageRecorder::set_max_recording_duration(std::chrono::seconds duration) -> void {
+    if (duration.count() < 0 || duration < pimpl->min_duration) {
+        util::panic("ImageRecorder: max_recording_duration is invalid");
+    }
     pimpl->max_duration = duration;
 }
 
 auto ImageRecorder::set_min_recording_duration(std::chrono::seconds duration) -> void {
+    if (duration.count() < 0 || duration > pimpl->max_duration) {
+        util::panic("ImageRecorder: min_recording_duration is invalid");
+    }
     pimpl->min_duration = duration;
 }

Based on learnings: "Default strategy for error handling: fail fast to avoid silent fallback ... report errors explicitly for invalid configuration/parameters without defaults."

Also applies to: 207-207, 213-219

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

In `@src/utility/image/recorder.cpp` at line 205, The ImageRecorder currently
allows invalid configuration (e.g., framerate == 0, negative durations,
min_duration > max_duration) which leads to silent non-recording; update
ImageRecorder to perform fail-fast validation when configuration is applied
(e.g., in the configuration setter or initialization path that mutates pimpl),
validate fields like framerate, duration, min_duration and max_duration and if
any are invalid: return an error / throw an exception (or log and set an
explicit error state) rather than silently accepting them; ensure the validation
lives next to the existing setter (ImageRecorder::set_saving_location and the
pimpl-backed config setters) and references pimpl->framerate,
pimpl->min_duration, pimpl->max_duration (or their actual names) so invalid
values are rejected immediately with a clear error message.

dst.x() = src.x;
dst.y() = src.y;
} else {
static_assert(false, "clone_scalar2d: unsupported trait combination");
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 验证源码中是否存在会导致该问题的写法
rg -n 'static_assert\(false' src/utility/math/linear.hpp

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 338


🏁 Script executed:

# Read the relevant file to understand the code context and template structure
cat -n src/utility/math/linear.hpp | head -130

Repository: Alliance-Algorithm/rmcs_auto_aim_v2

Length of output: 5625


模板中的 static_assert(false) 会导致编译直接失败,需要修复为依赖表达式。

第 68、91、118 行的 static_assert(false, ...) 在模板定义阶段直接被评估,因为它是非依赖表达式。即使 if constexpr 分支在实例化时不会被执行,非依赖的 static_assert 仍会在模板定义时触发,导致编译无法进行。

需要引入依赖于模板参数的 false 值,使断言延迟到模板实例化时评估:

template <class...>
inline constexpr bool dependent_false_v = false;

然后将三处 static_assert(false, ...) 改为 static_assert(dependent_false_v<Src, Dst>, ...)

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

In `@src/utility/math/linear.hpp` at line 68, The three uses of
static_assert(false, ...) in the template functions (e.g., inside clone_scalar2d
and the other two branches) are non-dependent and fire at template definition
time; add a dependent-false helper template (e.g., template<class...> inline
constexpr bool dependent_false_v = false;) and replace each static_assert(false,
"...") with static_assert(dependent_false_v<Src, Dst>, "...") (or use the actual
template parameter pack for that function) so the assertion becomes dependent on
template parameters and is evaluated only at instantiation.

Comment on lines +76 to +77
for (auto i = int { }; i < static_cast<int>(kSearchRangeDeg); ++i) {
auto candidate_yaw = double { yaw_start + i * deg2rad(kSearchStepDeg) };
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 | ⚡ Quick win

Yaw 搜索循环有边界与步长耦合问题。

当前实现不会覆盖 +70° 边界,且循环次数写死依赖“步长=1°”;建议用 range/step 计算采样数并包含上下边界。

建议修复(示例)
-    for (auto i = int { }; i < static_cast<int>(kSearchRangeDeg); ++i) {
+    const auto sample_count = static_cast<int>(kSearchRangeDeg / kSearchStepDeg);
+    for (auto i = int { }; i <= sample_count; ++i) {
         auto candidate_yaw = double { yaw_start + i * deg2rad(kSearchStepDeg) };
📝 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
for (auto i = int { }; i < static_cast<int>(kSearchRangeDeg); ++i) {
auto candidate_yaw = double { yaw_start + i * deg2rad(kSearchStepDeg) };
const auto sample_count = static_cast<int>(kSearchRangeDeg / kSearchStepDeg);
for (auto i = int { }; i <= sample_count; ++i) {
auto candidate_yaw = double { yaw_start + i * deg2rad(kSearchStepDeg) };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utility/math/solve_pnp/yaw_optimizer.cpp` around lines 76 - 77, The yaw
search loop is coupling the iteration count to a hardcoded assumption that
kSearchStepDeg == 1 and misses the +70° boundary; change the loop to compute the
number of samples from the range and step (e.g. samples = round(kSearchRangeDeg
/ kSearchStepDeg) + 1) and iterate i from 0 to samples-1 so candidate_yaw =
yaw_start + i * deg2rad(kSearchStepDeg) covers both endpoints; update the loop
that produces candidate_yaw (references: yaw_start, kSearchRangeDeg,
kSearchStepDeg, deg2rad, candidate_yaw) to use this computed sample count
instead of static_cast<int>(kSearchRangeDeg).

Comment on lines +1 to +5
#pragma once

#include "utility/rclcpp/node.hpp"
#include "utility/rclcpp/visual/movable.hpp"

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 | 🟠 Major | ⚡ Quick win

头文件缺少直接依赖的标准库包含,存在编译脆弱性。

该文件直接使用了 std::stringstd::unique_ptr,建议显式包含 <string><memory>,避免依赖间接包含。

🐛 建议修改
 `#pragma` once
 
+#include <memory>
+#include <string>
+
 `#include` "utility/rclcpp/node.hpp"
 `#include` "utility/rclcpp/visual/movable.hpp"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utility/rclcpp/visual/arrow.hpp` around lines 1 - 5, arrow.hpp currently
relies on indirect includes but uses std::string and std::unique_ptr; explicitly
include the missing standard headers by adding <string> and <memory> at the top
of the header so usages of std::string and std::unique_ptr are guaranteed
(update the include list near the existing includes "utility/rclcpp/node.hpp"
and "utility/rclcpp/visual/movable.hpp").

Comment thread tool/hikcamera.cpp
Comment thread tool/hikcamera.cpp
Comment on lines +149 to +153
auto shutdown() -> void {
enabled = false;
cv.notify_one();
if (worker.joinable()) worker.join();
}
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 | 🟠 Major | ⚡ Quick win

共享状态存在数据竞争(enabled/stop_pending 跨线程无同步访问)。

shutdown() 无锁写 enabled,主线程无锁读 stop_pending,而这些字段在 worker 内是受互斥锁保护读写的;当前混用会导致未定义行为。

建议修复(示例)
 struct Recording {
@@
+    auto is_stop_pending() -> bool {
+        auto lock = std::lock_guard { mutex };
+        return stop_pending;
+    }
@@
     auto shutdown() -> void {
-        enabled = false;
+        {
+            auto lock = std::lock_guard { mutex };
+            enabled = false;
+        }
         cv.notify_one();
         if (worker.joinable()) worker.join();
     }
 };
@@
-                    if (recording.stop_pending) {
+                    if (recording.is_stop_pending()) {
                         std::println("[main] Stop in progress, please wait");
                         continue;
                     }

Also applies to: 254-255

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

In `@tool/hikcamera.cpp` around lines 149 - 153, shutdown() writes shared flag
enabled without locking while the worker reads/writes enabled/stop_pending under
a mutex, causing a data race; update shutdown() (and the similar code at the
other occurrence) to acquire the same mutex used by the worker before modifying
enabled/stop_pending, set the flag(s) while holding the lock, then release and
call cv.notify_one() (or notify after unlocking) and join the worker; reference
the member names enabled, stop_pending, the shutdown() method, the worker thread
lambda/function, and the cv/mutex pair to locate and fix the accesses.

@creeper5820 creeper5820 force-pushed the refactor/pose_estimator branch from 5a8663b to ffe7bfe Compare May 1, 2026 10:34
@creeper5820 creeper5820 merged commit 71b756a into main May 1, 2026
2 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in RMCS Auto Aim V2 May 1, 2026
@creeper5820 creeper5820 deleted the refactor/pose_estimator branch May 1, 2026 10:44
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