Skip to content

fix(crane_robot_receiver): byte 2 をチェックサムとして扱う誤った前提を除去する - #1396

Merged
HansRobo merged 1 commit into
developfrom
fix/receiver-checksum-validation
Sep 17, 2026
Merged

HansRobo merged 1 commit into
developfrom
fix/receiver-checksum-validation

Conversation

@HansRobo

@HansRobo HansRobo commented May 30, 2026

Copy link
Copy Markdown
Member

概要

このPRは当初の内容から全面的に差し替えました。

当初は「実装済みなのに呼ばれていないチェックサム検証を有効化する」修正でしたが、実機ファームウェアの一次ソースを確認した結果、フィードバックパケットの byte 2 はチェックサムではないことが判明しました。当初の修正はマージすると実機フィードバックが全滅する致命的リグレッションだったため、修正内容を「誤った前提そのものの除去」へ差し替えます。

根拠(一次ソース)

ソース 記述
G474_Orion_main Core/Src/ai_comm.c sendRobotInfo() buf[2] = 10; // CRC, 10:dummy
Orion_CM4 cm4/bridge/robot_feedback_packet.h 「実機は定数 10 を書くだけで、実際のチェックサムは計算していない(…)検証に使ってはいけない」
Orion_CM4 doc/feedback_packet.md byte 2 はチェックサムではありません」「受信側でこの判定を有効にしてはいけません

byte 2 を検証すると readRawByte(buf, 2) は常に 10computeChecksum(buf) は byte 3..127 の総和下位 8bit となり、両者が一致することは事実上ありません。結果として実機フィードバックが全パケット破棄され、電圧・エラーID・ボールセンサ・odom・診断がすべて停止します。crane_robot_skills/src/single_ball_placement.cpp のボール保持判定も ball_sensor に依存しているため機能しなくなります。

問題の本質

当初の誤修正は偶然生まれたものではなく、誤検出を誘発する仕掛けがコード側に3つ残っていたことが原因です。これを放置すると同じ修正が再提出されます。

  1. robot_feedback_protocol.hppcomputeChecksum() / PacketValidationResult::checksum_valid が「正しいのに未使用の API」の顔で残っていた
  2. scenario_test/inject_feedback.py が byte 2 に本物のチェックサムを書いていた → 誤った修正が sim では全て緑、実機でだけ死ぬ
  3. test_robot_feedback_protocol.cpp が存在しないプロトコルを緑で守っていた

修正内容

crane_robot_receiver/include/crane_robot_receiver/robot_feedback_protocol.hpp

  • computeChecksum()PacketValidationResult::checksum_valid を削除

  • offset::CHECKSUMoffset::DUMMY_CRC にリネームし、ファームの出典をコメントで明記。DUMMY_CRC_VALUE = 10 を追加

  • validatePacket()received_size 引数を追加

    受信バッファは BUFFER_SIZE (2048) 長の使い回しで渡されるため、従来の buffer.size() == PACKET_SIZE は実受信経路では常に false でした。validatePacket() は事実上テスト内でしか成立しない死にコードだったため、素直に配線すると全パケットが落ちる状態でした。

crane_robot_receiver/src/robot_receiver_node.cpp

  • onReceive の独自検証を validatePacket() へ一本化(検証定義の二重化を解消)
  • checksum_error_count_ を削除

crane_msgs/msg/RobotFeedback.msg / diagnostic_publisher.cpp

  • 構造的に永久に 0 である checksum_error_count を削除(常に0の診断は無いより悪いため)
  • gh search code --owner ibis-ssl "checksum_error_count" で org 内を確認し、crane 以外に consumer が無いことを確認済み

scenario_test/inject_feedback.py

  • byte 2 に本物のチェックサムを書いていたのを、実機と同じ定数 10 に変更
  • パケットレイアウトの正本は crane のヘッダではなく実機ファームである旨を docstring に明記

crane_robot_receiver/test/test_robot_feedback_protocol.cpp

  • 存在しないプロトコルを検証していたチェックサムのテストを削除
  • byte 2 の値が検証結果に影響しないことを固定する回帰テストを追加(誤修正の再発防止)
  • 2048 バイトバッファに 128 バイトが届く実受信形状のテストを追加

レビュー観点

  • byte 2 に関する一次ソース(ai_comm.c / feedback_packet.md)の解釈が正しいか
  • validatePacket()received_size 追加により、onReceive の判定が従来と等価か
  • checksum_error_count の msg フィールド削除による影響範囲

別途対応(このPRには含めない)

一次ソースとの突き合わせで、チェックサムとは独立したレイアウト不整合も検出しています。別PRで対応します。

offset ファーム実体 crane の解釈
14 tx_cycle_count(feedback 送信ごとに++) ball_detection[2]
28 buf[28] = 0; // unused ball_detection[3](常に0)

ball_sensorball_detection[0](byte 12)のみを見ているため制御への影響はありませんが、publish 値は誤っています。また byte 14 の tx_cycle_count こそフィードバック側のパケットロス検知に使うべき連番です。現在の counter_jump_count は byte 3 を使っていますが、byte 3 は実機では ai_cmd->check_counter の反射にすぎず、さらに crane_sender/src/ibis_sender_node.cppcounter_ を 0..200 で折り返すのに対し受信側は uint8 の last + 1 を期待しているため、折り返しのたびに誤カウントします。

@HansRobo

HansRobo commented Jun 7, 2026

Copy link
Copy Markdown
Member Author

チェックサムの計算方法が多分違う

@HansRobo
HansRobo force-pushed the fix/receiver-checksum-validation branch from 179af75 to 98a20ee Compare September 17, 2026 08:50
## 背景

当初このブランチは「実装済みなのに呼ばれていないチェックサム検証を有効化する」
修正だった。しかし実機ファームウェアの一次ソースを確認した結果、
フィードバックパケットの byte 2 はチェックサムではないことが判明したため、
修正内容を全面的に差し替える。

- G474_Orion_main `Core/Src/ai_comm.c` sendRobotInfo():
  `buf[2] = 10;  // CRC, 10:dummy`
- Orion_CM4 `cm4/bridge/robot_feedback_packet.h`:
  「実機は定数 10 を書くだけで、実際のチェックサムは計算していない。検証に使ってはいけない」
- Orion_CM4 `doc/feedback_packet.md`:
  「byte 2 はチェックサムではありません」「受信側でこの判定を有効にしてはいけません」

byte 2 を検証すると `readRawByte(buf, 2)` は常に 10、`computeChecksum(buf)` は
byte 3..127 の総和下位 8bit となり、実機フィードバックが全パケット破棄される。
電圧・エラー・ボールセンサ・odom・診断がすべて停止する致命的リグレッションだった。

## 修正内容

誤った前提を再発させている3点を取り除く。

- `robot_feedback_protocol.hpp`
  - `computeChecksum()` と `PacketValidationResult::checksum_valid` を削除
  - `offset::CHECKSUM` を `offset::DUMMY_CRC` にリネームし、ファームの出典を明記
  - `validatePacket()` に `received_size` を追加。受信バッファは BUFFER_SIZE (2048) 長の
    使い回しなので `buffer.size()` をパケット長と見なすと常に size_valid=false になる
- `robot_receiver_node.cpp`
  - `onReceive` の独自検証を `validatePacket()` へ一本化(検証定義の二重化を解消)
  - `checksum_error_count_` を削除
- `crane_msgs/msg/RobotFeedback.msg` / `diagnostic_publisher.cpp`
  - 構造的に永久に 0 である `checksum_error_count` を削除
- `scenario_test/inject_feedback.py`
  - byte 2 に本物のチェックサムを書いていたのを実機と同じ定数 10 に変更。
    これが「sim では緑、実機だけ死ぬ」状態を作っていた
- `test_robot_feedback_protocol.cpp`
  - 存在しないプロトコルを検証していたチェックサムのテストを削除
  - byte 2 の値が検証結果に影響しないことの回帰テストを追加
  - 2048 バイトバッファに 128 バイト届く実受信形状のテストを追加
@HansRobo
HansRobo force-pushed the fix/receiver-checksum-validation branch from 98a20ee to ad4a49f Compare September 17, 2026 09:07
@HansRobo HansRobo changed the title fix(crane_robot_receiver): フィードバック受信のチェックサム検証を有効化 fix(crane_robot_receiver): byte 2 をチェックサムとして扱う誤った前提を除去する Sep 17, 2026
@HansRobo
HansRobo merged commit 17463b3 into develop Sep 17, 2026
8 checks passed
@HansRobo
HansRobo deleted the fix/receiver-checksum-validation branch September 17, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant