学生ロボコン2026が終わったので、今年やったことをまとめておきます。

今年は回路・制御をゴリゴリ書くというよりは、機体間の通信周りとR1の操縦用GUIアプリを作っていました。
あとは運営とか会計とか、ものづくり以外の仕事もやってました。学ロボ人生もこれで一区切りです。

結果はベスト8でした。まぁいいロボコン人生だったかなと思います。


作ってたもの

ethernet2can

何を作ったか

Classic CAN ↔ Ethernet(TCP)のゲートウェイです。マイコンはSTM32G473、EthernetコントローラはW5500を使っています。
STM32G473はFDCANを3チャンネル持っているので、それを全部1本のTCP接続で扱えるようにしました。

実機はこんな感じです。RJ45コネクタがついてるとカッコ良く見えて好きです。あとはCANのXAコネクタが並んでます。

プロトコル仕様

パケットは20バイト固定のフォーマットです。

+--------+----------+----------+
| Offset | Size     | Field    |
+--------+----------+----------+
| 0      | 1 byte   | Channel  |
| 1      | 3 byte   | (pad)    |
| 4      | 4 byte   | CAN ID   |
| 8      | 4 byte   | DLC等    |
| ...    | 8 byte   | Data     |
+--------+----------+----------+

Classic CANのみ対応(データは最大8バイト)です。FDCANのデータレート部分には対応していません。

チャンネル番号はそのままペリフェラルに対応させています。

Channelペリフェラル
0FDCAN1
1FDCAN2
2FDCAN3

ちなみにシルクの配置が間違ってて制御を困らせました

CAN IDフィールドはSocketCAN互換にしました。すでに使い慣れてる人が多いフォーマットに合わせておくと、Python側のクライアントを書くときも楽です。

  • Bit 31 (0x80000000): EFF — 拡張フレームフラグ(29ビットID)
  • Bit 30 (0x40000000): RTR — リモートフレームフラグ
  • Bit 0–28: CAN ID(標準: 下位11ビット / 拡張: 29ビット)
フレームタイプID範囲EFFRTR
標準データフレーム0x000–0x7FF00
標準リモートフレーム0x000–0x7FF01
拡張データフレーム0x000–0x1FFFFFFF10
拡張リモートフレーム0x000–0x1FFFFFFF11

アーキテクチャ

CAN→Ethernet方向はこんな流れです。

FDCAN割り込み (HAL_FDCAN_RxFifo0Callback)
  └→ RAMキュー(64メッセージ循環バッファ)に追加(SPIなし)
       └→ メインループ: キューから取り出し → W5500でTCP送信

Ethernet→CAN方向はこう。

W5500 TCP受信
  └→ 20バイトパケットをパース
       └→ FDCAN送信

ポイントは、割り込みハンドラの中で直接W5500のSPIにアクセスしないことです。
最初はFDCANの受信割り込みでそのままSPI送信していたのですが、メインループ側のSPIアクセスと競合してしまい、データが欠落したりタイミングがズレることがありました。
受信データを一旦RAMの循環バッファに積んでおいて、メインループ側でまとめてW5500に流す方式に変えたことで安定しました。割り込みハンドラ内でSPI(やそれに準ずる重い処理)を叩くと痛い目を見るというのが、今回の一番の学びです。

DMA?知らない子ですね…


gakurobo_controller(R1操縦用アプリ)

概要

R1の操縦システムです。DualSenseコントローラの入力をiPhoneアプリ経由でロボットに送るパイプラインを組みました。
スマホ本体にはiphone16eを使用しています。個人的に買ったiOSアプリ開発用の端末を流用しただけなので、iPhoneを使っている深い理由は特にないです。

ROS2との連携は以下のようになっています。

DualSense → iPhone (Flutter) → WebSocket → PC (ROS2) → /joy トピック

PCでROS2を動かしてフィールド全体の制御をしている前提で、操縦入力だけをiPhoneから飛ばす形です。
スマホ,コントローラ,Wi-Fiルーター間は有線で直結する構成にしています。NHKの電波管制がひどいので、無線を極力減らしたかった
最終的に無線関連のトラブルのリスクを考えて、この構成に落ち着きました。

実際の運用イメージです。iPhoneをDualSenseにマウントして、フィールド表示と操作ボタンを画面に出しています。

構成

iPhone側のアプリ(flutter/、v1.4.0)は3ページ構成にしています。

ファイル内容
pages/controller_page.dartメインコントローラ画面
pages/field_page.dartフィールド表示画面
pages/settings_page.dart設定画面
widgets/gamepad_panel.dartゲームパッド入力表示
widgets/telemetry_panel.dartテレメトリ表示
widgets/aruco_panel.dartArUcoマーカー関連

主な依存ライブラリはroslibdart(ROS2連携)とuniversal_gamepad(DualSense入力)です。
ROS2との通信をネイティブで書くのは大変なのでroslibdartでWebSocket越しにrosbridgeと喋らせています。DualSenseの入力周りもuniversal_gamepadに任せて、自前で実装するのはアプリ側のロジックとUIだけに絞りました。
自前で実装しても良かったのですが、トラブル時の問題の切り分けが面倒だったので、既存ライブラリを使用しました。

メイン画面の表示です。左から操作ボタン、ログ、ゲームパッド入力のパネルが並んでいます。rosbridgeとの接続状態もここで確認できます。
Arucoマーカーの指定などもこの画面で行います。

フィールド画面です。陣地ごとのKFSの状態やルート選択をここから操作します。 ここのUIは割と見やすくできたので、お気に入りです。

kfsおくとこんな感じになります。


それ以外(運営・会計)

ものづくり以外だと、チームの運営と会計をやっていました。
予算管理やイベント周りの調整など、地味だけどチームが大会まで走り切るために必要な仕事です。ここに書けることはあまりないですが、これも含めて今年の学ロボでした。


結果と所感

結果はベスト8でした。
ethernet2canもgakurobo_controllerも、本番までに動かし切れたという意味では満足しています。
特にethernet2canはキューイング方式に変えたあとはCAN通信周りのトラブルでロボットが止まることはなかったので、回路・通信基盤としてはちゃんと役目を果たしたと思います。
GUIアプリも依頼されてから1ヶ月半くらいで完成させられたので、ひとまずは良かったですかね。

まぁいいロボコン人生だったかな、というのが今の感想です。
一区切りついたので、ESCでも自作しようかな〜