diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..be24278 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# PC の IP アドレス(Pi からの接続先) +PC_IP= + +# 画像送信ポート(Pi → PC) +IMAGE_PORT= + +# 操舵量送信ポート(PC → Pi) +CONTROL_PORT= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..050c8ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# 仮想環境 +.venv/ + +# 環境変数 +.env + +# 旧コード(参照用,Git 管理外) +src_old/ + +# Python +__pycache__/ +*.pyc +*.pyo + +# IDE +.vscode/ +.idea/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..3d33c8c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,48 @@ +# RobotCar プロジェクト + +カメラ搭載ロボットカーの自律走行ライントレースシステム。 +Raspberry Pi + PC 構成で、黒線コースをできるだけ速くコースアウトせずに完走することが目標。 + +## ドキュメント + +作業前に必ず関連するドキュメントを参照し、内容に従うこと。 +docs/ にファイルを追加した際、CLAUDE.md に記載すべき参照があればこのリストに追加すること。 + +### ガイドライン(常に従う) +- `docs/01_GUIDE/GUIDE_01_ドキュメント作成ガイド.txt` — 句読点は「,」「.」、見出し書式等 +- `docs/01_GUIDE/GUIDE_02_ドキュメント命名規則.txt` — `[カテゴリ]_[連番]_[ファイル名].txt` +- `docs/01_GUIDE/GUIDE_03_Git運用ルール.txt` — ブランチ命名、コミットメッセージ `[タグ] 内容` +- `docs/01_GUIDE/GUIDE_04_コーディング規則.txt` — PEP 8 ベース、snake_case、型ヒント必須 +- `docs/01_GUIDE/GUIDE_05_コードコメント規則.txt` — docstring は日本語、句点なし、Google スタイル + +### プロジェクト仕様(実装時に参照) +- `docs/02_PLAN/PLAN_01_プロジェクト概要.txt` — 目的・目標・ハードウェア構成 +- `docs/03_TECH/TECH_01_操舵量計算仕様.txt` — PD 制御、2領域偏差、速度制御 +- `docs/03_TECH/TECH_02_システム構成仕様.txt` — Pi/PC の役割分担、通信フロー、設計方針 + +### 環境(セットアップ時に参照) +- `docs/04_ENV/ENV_01_技術スタック選定.txt` — ZMQ, PySide6, OpenCV, Picamera2, RPi.GPIO +- `docs/04_ENV/ENV_02_PC環境構築手順.txt` — venv 作成、ライブラリインストール +- `docs/04_ENV/ENV_03_RaspPi環境構築手順.txt` — SSH 接続、SCP 転送、Pi への転送対象 +- `docs/04_ENV/ENV_04_ディレクトリ構成.txt` — src/ の構成と実装状態 + +## コーディング規則(要点) + +- 言語: Python(Pi・PC 共通) +- スタイル: PEP 8 準拠、インデント 4 スペース、1行 79 文字以内 +- 命名: 変数・関数は snake_case、クラスは PascalCase、定数は UPPER_SNAKE_CASE +- 文字列: ダブルクォート `"` 統一、f-string 使用 +- 型ヒント: 関数の引数・返り値に必須 +- docstring: 日本語、Google スタイル、句点なし +- コメント: 日本語、句読点は「,」、句点なし + +## ドキュメント作成規則(要点) + +- 句読点: 「,」「.」を使用(「、」「。」は使用しない) +- ファイル命名: `[カテゴリ]_[連番]_[ファイル名].txt` +- 見出し: レベル1 は数字+ハイフン装飾、レベル2 は数字-数字、レベル3 は「■」 + +## コミットメッセージ + +- 書式: `[タグ] 内容`(日本語、末尾句点なし) +- タグ: [add], [update], [fix], [remove], [clean] diff --git "a/docs/01_GUIDE/GUIDE_01_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\344\275\234\346\210\220\343\202\254\343\202\244\343\203\211.txt" "b/docs/01_GUIDE/GUIDE_01_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\344\275\234\346\210\220\343\202\254\343\202\244\343\203\211.txt" new file mode 100644 index 0000000..8dafd98 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_01_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\344\275\234\346\210\220\343\202\254\343\202\244\343\203\211.txt" @@ -0,0 +1,146 @@ +======================================================================== +ドキュメント作成ガイドライン (Style Guide) +======================================================================== + +1. 基本フォーマット (Basic Format) +------------------------------------------------------------------------ +・文字コード: UTF-8 +・改行コード: LF (推奨) または CRLF +・インデント: 半角スペース4つ (4 spaces) + - タブ文字は使用せず,スペースに展開して揃える. +・ファイル命名: `GUIDE_02_ドキュメント命名規則.txt` を参照する. + +■ ファイルヘッダー (File Header) +・ファイルの先頭には必ずタイトルブロックを記述する. +・書式: 上下を「=」(イコール)の列(72文字程度)で挟む. +・例: + ======================================================================== + ドキュメントタイトル (English Title) + ======================================================================== + + +2. 句読点・約物 (Punctuation) +------------------------------------------------------------------------ +・句読点: 「,」(全角カンマ)と「.」(全角ピリオド)を使用する. + - 「、」「。」は使用しない. +・コロン: 半角コロン+半角スペース「: 」を使用する. + - NG: 全角コロン「:」,スペースなし「:」 +・括弧: 原則として半角括弧 `( )` を使用するが,強調や補足には全角 `( )` や `「 」` も許容する. +・注釈: 文末や段落末の補足には「※」(全角米印)+半角スペースを使用する. + - 例: ※ shared は client/server 両方から import して使用する. + + +3. 階層構造と見出し (Headings & Hierarchy) +------------------------------------------------------------------------ + +3-1. レベル1:大見出し (Section) + ・書式: 数字 + ドット + 半角スペース + タイトル + (英語タイトル) + ・装飾: 下行にハイフン「-」による区切り線を挿入する. + ・例: + 1. 基本設計 (Basic Design) + ------------------------------------------------------------------------ + +3-2. レベル2:中見出し (Subsection) + ・書式: 数字-数字 + ドット + 半角スペース + タイトル + ・例: + 1-1. 製品概要 + +3-3. レベル3:小見出し (Group Heading) + ・書式: 「■」+ 半角スペース + タイトル + ・使い分け: + - セクション内で独立したトピック(カテゴリ)を列挙する場合は「■」を使用する. + - 手順やフロー、順序のある項目を示す場合は「1. 」「2. 」を使用する. + + A. 並列・カテゴリ列挙(順序不問) + - 記号: 「■ 」(全角四角+半角スペース) + - 例: ■ フィールド仕様 + + B. 手順・優先順位・ランキング(順序重要) + - 記号: 「1. 」「2. 」(半角数字+ドット+半角スペース) + - 例: 1. ユーザ体験の理想 + +3-4. レベル4:リスト項目 (List Item) + ・記号: 「・」(全角中黒) + ・書式: 「・項目名: 内容」または「・項目名」のみ. + ・使いどころ: セクション内の主要な列挙(親項目)に使用する. + ・例: + ・タイトル: Paint War + +3-5. レベル5:詳細項目 (Detail Item) + ・記号: 「- 」(半角ハイフン+半角スペース) + ・インデント: 親項目のテキスト開始位置に合わせる(基本はスペース8つ). + ・使いどころ: 親が「・」のとき,その補足・条件・内訳を子項目として記述する. + ・ルール: 親が「・」なら子は必ず「- 」を使う. + ・例: + ・接続設定 + - host: localhost + - port: 3000 + +3-6. 特殊なナンバリング (Zero Indexing) + ・目的定義: セクションの冒頭で目的や定義を述べる場合,「X-0. 目的」というナンバリング(ゼロ始まり)を使用してもよい. + - 例: 1-0. 目的 + +3-7. 階層の順守 + ・上位レベルから下位レベルへ順に記述し,階層を飛ばさないこと. + - NG例: レベル1(1. XX)の直下にレベル3(■ XX)を記述する. + - 対策: 必要に応じてレベル2(1-1. 概要 等)を設ける. + + +4. 余白・改行ルール (Spacing) +------------------------------------------------------------------------ +・大見出しの上: 2行空ける. +・中見出し(X-X)の上: 1行空ける. +・小見出し(■や数字)の上: 1行空ける. +・セクション内のリスト: 原則として行間を詰め,まとまりごとに適宜空行を入れる. +・ミニサンプル: + 1. 基本設計 (Basic Design) + ------------------------------------------------------------------------ + + + 1-1. 製品概要 + + ■ 主要要件 + ・要件A: 説明 + ・要件B: 説明 + + ■ 補足 + ・注意点: 説明 + +・NG例(空行不足): + 1. 基本設計 (Basic Design) + ------------------------------------------------------------------------ + 1-1. 製品概要 + ■ 主要要件 + ・要件A: 説明 + + +5. 技術記述・コード表記 (Technical & Code) +------------------------------------------------------------------------ +・1行の最大文字数: 半角80文字(全角40文字)を目安とする.超える場合は適切な位置で折り返す. + +・インラインコード: バッククォート1つで囲む. + - 例: `MAX_DIST`,`useJoystick`,`.env` + +・コマンドライン: 先頭に `$ ` を付与して区別する. + - 例: + + $ git checkout -b feature/260314_yamada_new_function + $ npm install + +・コードブロック: 親の箇条書きレベルに合わせてインデントし,前後に1行空ける. + - 例: + + // 入力座標からベクトルを計算し,半径でクランプして正規化出力する + const handleMove = (e: PointerEvent) => { + const dx = e.clientX - origin.x; + const dy = e.clientY - origin.y; + }; + +・ディレクトリ構造: ツリー記号(`├──`,`│`,`└──`)を使用し,ルートディレクトリからの階層を示す. + - 例: + + src/ + ├── components/ + │ └── Joystick.tsx + └── hooks/ + └── useJoystick.ts \ No newline at end of file diff --git "a/docs/01_GUIDE/GUIDE_02_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\345\221\275\345\220\215\350\246\217\345\211\207.txt" "b/docs/01_GUIDE/GUIDE_02_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\345\221\275\345\220\215\350\246\217\345\211\207.txt" new file mode 100644 index 0000000..a1ff832 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_02_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\345\221\275\345\220\215\350\246\217\345\211\207.txt" @@ -0,0 +1,68 @@ +======================================================================== +ドキュメント管理・ファイル命名規則 (File Naming Conventions) +======================================================================== + +1. 命名の基本方針 (Basic Policy) +------------------------------------------------------------------------ +プロジェクトの規模拡大に伴うファイルの散乱を防ぎ,開発メンバーおよびAI(Gemini/Copilot)がファイルの内容・文脈を即座に特定できるようにするため,以下の規則を適用する. +※ 書式・記述スタイルの基準は `GUIDE_01_ドキュメント作成ガイド.txt` を参照する. + +1-1. 基本フォーマット +`[カテゴリ]_[連番]_[ファイル名].txt` + +・区切り文字: アンダースコア `_` を使用する. +・連番: 01から始まる2桁の数字とする. +・拡張子: プレーンテキスト `.txt` とする. + +1-2. ファイル名部分の規則 +・言語: 日本語を推奨する(例: `通信プロトコル仕様`,`環境構築手順`). +・使用可能文字: 日本語,英数字,アンダースコア `_` のみとする. + - NG: スペース,ハイフン,記号(`/`,`.`,`(` 等) +・文字数: 全角20文字(半角40文字)以内を目安とする. +・例: + - OK: `TECH_01_通信プロトコル仕様.txt` + - OK: `ENV_01_環境構築手順.txt` + - NG: `TECH_01_通信 プロトコル仕様(v2).txt` + + +2. カテゴリ定義 (Category Definitions) +------------------------------------------------------------------------ +ファイル名の先頭に付与するプレフィックス(接頭辞)定義. + +■ GUIDE_ (Guide) +・内容: チーム全体のルール,規約,運用フローなど,「メタ情報」に関する定義. +・対象例: スタイルガイド,命名規則,Git運用ルール. + +■ PLAN_ (Planning) +・内容: プロジェクトの進行計画,スケジュール,要件定義など,「管理・進行」に関する定義. +・対象例: WBS,ロードマップ,要件定義書,タスク一覧. + +■ ENV_ (Environment) +・内容: 開発環境,ディレクトリ構造,ライブラリ選定など,プロジェクトの「土台」に関する定義. +・対象例: 環境構築手順,技術スタック一覧,パッケージ構成図. + +■ SPEC_ (Specification) +・内容: 企画,ゲームルール,UI/UXなど,ユーザーから見える「仕様」に関する定義. +・対象例: ゲーム企画書,画面遷移図,パラメータ設定(マップサイズ・速度など). + +■ TECH_ (Technical) +・内容: 実装詳細,アルゴリズム,データ構造など,エンジニア向けの「技術設計」に関する定義. +・対象例: 通信プロトコル仕様,同期ロジック,データベース設計,クラス設計. + +■ TEST_ (Test) +・内容: テスト計画,テストケース,品質保証手順など,「検証・品質」に関する定義. +・対象例: 単体テスト仕様書,シナリオテスト計画,テストケース一覧,品質基準. + +■ ADR_ (Architecture Decision Record) +・内容: 設計上の意思決定とその根拠,採用・却下の経緯など,「なぜその設計にしたか」の記録.重要な判断をした時点で必ず作成する. +・対象例: 通信方式の選定理由,ライブラリ採用経緯,大きな設計変更の背景. + + +3. 運用ルール (Operational Rules) +------------------------------------------------------------------------ +・1ファイル1テーマ: + ファイルサイズが肥大化しすぎないよう,トピック(例: 通信仕様,判定ロジック)ごとにファイルを分割することを推奨する. + これにより,AIへのコンテキスト入力精度が向上する. + +・スタイルの継承: + 新規作成するファイルも,必ず `GUIDE_01_ドキュメント作成ガイド.txt` に記載された書式(見出し,句読点「,.」等)に従うこと. \ No newline at end of file diff --git "a/docs/01_GUIDE/GUIDE_03_Git\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.txt" "b/docs/01_GUIDE/GUIDE_03_Git\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.txt" new file mode 100644 index 0000000..4fb7537 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_03_Git\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.txt" @@ -0,0 +1,145 @@ +======================================================================== +Git運用ルール (Git Operation Rules) +======================================================================== + +1. 基本方針 (Basic Policy) +------------------------------------------------------------------------ +チーム開発におけるコードの整合性を保ち,手戻りを防ぐために以下の運用フローを徹底する. + +・メインブランチ (main): + - 本番環境または常に動作可能な状態を維持するブランチ. + - 直接のコミット(直プッシュ)は禁止する.必ずプルリクエスト(PR)経由でマージする. +・作業ブランチ (Feature Branch): + - 機能追加やバグ修正ごとに `main` から派生させて作成する. + - 作業完了後,`main` へマージし,原則として削除する. +・`.gitignore`: + - リポジトリ作成時に必ず整備する. + - ビルド成果物,依存パッケージ(`node_modules/` 等),環境変数ファイル(`.env` 等)は必ず除外する. + - `git add .` を安全に使うための前提条件であるため,メンバー追加時にも確認する. + + +2. ブランチ命名規則 (Branch Naming) +------------------------------------------------------------------------ +2-1. プレフィックス (Prefix) +作業の種類を一目で判別するために,以下のプレフィックスを使用する. + +■ カテゴリ一覧 + ・feature/: 新機能の実装,仕様変更 + ・fix/: バグ修正 + ・refactor/: コードの整理(挙動は変えない) + ・docs/: ドキュメントの追記・修正 + ・chore/: ビルド設定やツール導入など,雑多な作業 + +2-2. 書式 (Format) + ・書式: `[プレフィックス][概要]` + ・区切り: スラッシュ `/` を使用する.概要内の単語区切りはハイフン `-` を使用する. + ・概要: 作業内容を端的に表す英単語2〜4語程度(小文字)とする. + ・例: + - feature/player-jump + - fix/collision-bug + - docs/guide-update + + +3. 開発フロー (Development Workflow) +------------------------------------------------------------------------ +作業を開始してからマージされるまでの手順. + +1. ローカルの最新化 + ・作業開始前は必ず `main` ブランチに切り替え,リモートの最新状態を取り込む. + ・コマンド: + $ git checkout main + $ git pull origin main + +2. 作業ブランチの作成 + ・最新の `main` から新しいブランチを作成して移動する. + ・コマンド: + $ git checkout -b feature/new-function + +3. 実装とコミット + ・作業単位(意味のあるまとまり)ごとにコミットする. + ・巨大なコミットは避け,レビューしやすい粒度を心がける. + ・VS CodeでCopilotを使用している場合,AIによるコミットメッセージの生成機能(キラキラアイコン等)を利用してもよい. + ただし,生成されたメッセージは必ず「4. コミットメッセージ」の書式ルール(タグや日本語化)に合わせて修正すること. + ・コマンド: + $ git add . + $ git commit -m "[add] 新機能を実装" + +4. リモートへのプッシュ + ・作業ブランチをリモートリポジトリへ送信する. + ・コマンド: + $ git push origin feature/new-function + +5. プルリクエスト (PR) の作成 + ・GitHubのリポジトリ画面上部に表示される「Compare & pull request」ボタンをクリックする. + ・Baseを `main`、Compareを自分の「作業ブランチ」に設定する. + ・「Reviewers」メニューからチームメンバーを選択し、レビューを依頼する. + ・「Create pull request」ボタンを押してPRをオープンする. + +6. レビューと修正の対応 + ・レビュワーのコメントを確認し、修正が必要な場合はローカルで修正・コミット・プッシュを繰り返す. + ・GitHub上で全ての指摘に対し「Resolve conversation」を行い、やり取りを完了させる. + ・レビュワーから「Approve(承認)」のスタンプまたはメッセージをもらう. + +7. マージの実行(マージボタンの操作) + ・PR画面下部の「Merge pull request」ボタンをクリックする. + ・マージ方式は「Create a merge commit」を選択する(作業ブランチの全コミット履歴が `main` に残る). + - 「Squash and merge」「Rebase and merge」は使用しない. + ・確認用の「Confirm merge」ボタンを押し,`main` への統合を完了させる. + ・マージ直後に表示される「Delete branch」ボタンを押し,リモート上の作業ブランチを削除する. + +8. ローカル環境のクリーンアップ + ・マージ完了後はローカル環境も最新状態に戻し、古いブランチを削除する. + $ git checkout main + $ git pull origin main + $ git branch -d [作業ブランチ名] + + +4. コミットメッセージ (Commit Messages) +------------------------------------------------------------------------ +4-1. 書式 + ・書式: `[タグ] 内容` + ・言語: 日本語 (Japanese) + ・句読点: 末尾に句点は不要. + +4-2. タグ一覧 + ・[add]: ファイルや機能の追加 + ・[update]: 機能やデータの更新・修正 + ・[fix]: バグ修正 + ・[remove]: 削除 + ・[clean]: 整理,リファクタリング + + +5. トラブルシューティング (Troubleshooting) +------------------------------------------------------------------------ +■ コンフリクト (Conflict) が発生した場合 +他メンバーの変更と競合した場合の対処手順. + +1. main の取り込み + ・作業ブランチに `main` の最新内容をリベースして競合箇所を洗い出す. + ・`merge` ではなく `rebase` を使うことで,履歴が線形に保たれレビューしやすくなる. + ・コマンド: + $ git checkout main + $ git pull origin main + $ git checkout feature/new-function + $ git rebase main + +2. 競合の解消 + ・エディタ上で `<<<<<<<`, `=======`, `>>>>>>>` で囲まれた箇所を手動で修正する. + ・修正後,以下のコマンドでリベースを続行する. + $ git add [修正したファイル] + $ git rebase --continue + ・全ての競合が解消されたらプッシュする.リベース後は履歴が書き換わるため `-f` オプションが必要になる. + $ git push -f origin feature/new-function + +■ 間違えて main にコミットしてしまった場合 + +1. まだプッシュしていない場合 + ・コミットを取り消し,変更内容を保持したまま新しいブランチへ移動する. + ・コマンド: + $ git reset --soft HEAD^ + $ git checkout -b feature/new-function + $ git commit -m "[add] ..." + +2. すでにプッシュしてしまった場合 + ・`main` への force push はチーム全員の履歴を壊す危険があるため,自分では対処しない. + ・直ちにチームメンバーに報告し,全員で対応方針を決める. \ No newline at end of file diff --git "a/docs/01_GUIDE/GUIDE_04_\343\202\263\343\203\274\343\203\207\343\202\243\343\203\263\343\202\260\350\246\217\345\211\207.txt" "b/docs/01_GUIDE/GUIDE_04_\343\202\263\343\203\274\343\203\207\343\202\243\343\203\263\343\202\260\350\246\217\345\211\207.txt" new file mode 100644 index 0000000..1bce5cf --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_04_\343\202\263\343\203\274\343\203\207\343\202\243\343\203\263\343\202\260\350\246\217\345\211\207.txt" @@ -0,0 +1,230 @@ +======================================================================== +Python コーディング規則 (Python Coding Style Guide) +======================================================================== + +1. 基本方針 (Basic Policy) +------------------------------------------------------------------------ +PEP 8 を基本とし,チーム内での一貫性を最優先とする. +本規則に明記されていない事項は PEP 8 に従う. +※ 書式・記述スタイルの基準は `GUIDE_01_ドキュメント作成ガイド.txt` を参照する. + + +2. フォーマット (Formatting) +------------------------------------------------------------------------ + +2-1. インデント + ・半角スペース4つを使用する.タブ文字は使用しない. + ・継続行は,開き括弧に揃えるか,ハンギングインデント(スペース4つ追加)とする. + ・例: + + # 開き括弧に揃える + result = some_function(arg_one, arg_two, + arg_three, arg_four) + + # ハンギングインデント + result = some_function( + arg_one, arg_two, + arg_three, arg_four, + ) + +2-2. 1行の最大文字数 + ・79文字を上限とする(PEP 8 準拠). + ・文字列やコメントが長くなる場合は,括弧による暗黙の行継続を優先する. + ・バックスラッシュ `\` による行継続は極力避ける. + +2-3. 空行 + ・トップレベルの関数・クラス定義の間: 2行空ける. + ・クラス内のメソッド定義の間: 1行空ける. + ・関数内の論理的なまとまりの区切り: 1行空ける(使いすぎに注意). + +2-4. 文字コード + ・UTF-8 を使用する. + ・エンコーディング宣言(`# -*- coding: utf-8 -*-`)は Python 3 では不要. + + +3. 命名規則 (Naming Conventions) +------------------------------------------------------------------------ + +3-1. 一覧 + + ■ 変数・関数・メソッド・引数 + ・スタイル: snake_case + ・例: `motor_speed`,`calc_distance`,`handle_input` + + ■ 定数 + ・スタイル: UPPER_SNAKE_CASE + ・例: `MAX_SPEED`,`DEFAULT_PORT`,`PIN_MOTOR_LEFT` + + ■ クラス + ・スタイル: PascalCase + ・例: `MotorController`,`SensorReader`,`UltrasonicSensor` + + ■ モジュール(ファイル名) + ・スタイル: snake_case + ・例: `motor_controller.py`,`sensor_reader.py` + + ■ パッケージ(ディレクトリ名) + ・スタイル: 全て小文字,アンダースコアなし(短い名前を推奨) + ・例: `drivers`,`utils`,`config` + + ■ プライベート + ・先頭にアンダースコア1つを付与する. + ・例: `_internal_value`,`_calc_raw_data` + +3-2. 命名の原則 + ・意味のある名前を付け,略語は最小限にする. + - NG: `d`,`tmp`,`val`,`calc`(単体で使用) + - OK: `distance`,`temperature`,`motor_value` + ・ループカウンタ等,スコープが極めて狭い場合のみ `i`,`j`,`x`,`y` を許容する. + ・bool 型の変数は `is_`,`has_`,`can_` 等の接頭辞を付ける. + - 例: `is_connected`,`has_obstacle`,`can_move` + + +4. import の規則 (Import Rules) +------------------------------------------------------------------------ + +4-1. 順序 + 以下の順序で記述し,グループ間に1行空ける. + + 1. 標準ライブラリ(`os`,`sys`,`time` 等) + 2. サードパーティライブラリ(`RPi.GPIO`,`numpy` 等) + 3. プロジェクト内モジュール + + ・例: + + import os + import sys + import time + + import RPi.GPIO as GPIO + + from drivers.motor import MotorController + from sensors.ultrasonic import UltrasonicSensor + +4-2. スタイル + ・1行に1モジュールを記述する. + - NG: `import os, sys` + - OK: `import os` と `import sys` を別行に記述 + ・`from ... import *` は禁止する(名前空間の汚染を防ぐ). + ・`from ... import` で複数の名前を取り込む場合は括弧でまとめる. + + from sensors.ultrasonic import ( + UltrasonicSensor, + TRIGGER_PIN, + ECHO_PIN, + ) + + +5. 型ヒント (Type Hints) +------------------------------------------------------------------------ + +5-1. 方針 + ・関数の引数と返り値には型ヒントを付与する. + ・ローカル変数への型ヒントは,型が自明でない場合のみ付与する. + +5-2. 書式 + ・Python 3.10 以降の記法(`X | None`,`list[int]`)を使用する. + ・例: + + def calc_distance(speed: float, duration: float) -> float: + return speed * duration + + def find_obstacle(sensors: list[UltrasonicSensor]) -> int | None: + ... + + +6. コーディングルール (Coding Rules) +------------------------------------------------------------------------ + +6-1. 比較 + ・`None` との比較は `is` / `is not` を使用する. + - NG: `if value == None:` + - OK: `if value is None:` + ・bool 値との比較は暗黙的に行う. + - NG: `if is_active == True:` + - OK: `if is_active:` + +6-2. 文字列 + ・引用符はダブルクォート `"` で統一する. + ・文字列の組み立てには f-string を使用する. + - NG: `"Speed: " + str(speed)` + - OK: `f"Speed: {speed}"` + +6-3. 例外処理 + ・裸の `except:` は禁止する.必ず例外クラスを指定する. + - NG: `except:` + - OK: `except ValueError:` + ・`except Exception` も極力避け,具体的な例外を捕捉する. + +6-4. with 文 + ・ファイル操作や GPIO のクリーンアップなど,リソース管理には `with` 文を使用する. + ・例: + + with open("config.json", "r") as f: + config = json.load(f) + +6-5. マジックナンバーの禁止 + ・意味のある数値は定数として定義する. + - NG: `time.sleep(0.5)` + - OK: + SENSOR_INTERVAL_SEC = 0.5 + time.sleep(SENSOR_INTERVAL_SEC) + + +7. ファイル構成 (File Structure) +------------------------------------------------------------------------ +1つの Python ファイル内は,以下の順序で記述する. + + 1. ファイルドキュメント(docstring) + 2. import 文 + 3. 定数定義 + 4. クラス定義 / 関数定義 + 5. `if __name__ == "__main__":` ブロック(必要な場合のみ) + +・例: + + """ + motor_controller + モーターの制御を担当するモジュール + """ + + import time + + import RPi.GPIO as GPIO + + from config.pins import PIN_MOTOR_LEFT, PIN_MOTOR_RIGHT + + MAX_SPEED = 100 + DEFAULT_SPEED = 50 + + + class MotorController: + """左右のモーターを制御するクラス""" + + def __init__(self, left_pin: int, right_pin: int) -> None: + ... + + def forward(self, speed: int = DEFAULT_SPEED) -> None: + ... + + + if __name__ == "__main__": + controller = MotorController(PIN_MOTOR_LEFT, PIN_MOTOR_RIGHT) + controller.forward() + + +8. ツール設定 (Tooling) +------------------------------------------------------------------------ +コードの品質を自動で維持するため,以下のツールの導入を推奨する. + +■ フォーマッター +・black: コードの自動整形に使用する. + - 1行の最大文字数は 79 に設定する. + +■ リンター +・flake8 または ruff: スタイル違反や潜在的なバグを検出する. + +■ 型チェッカー +・mypy: 型ヒントの整合性を静的に検証する. + +※ ツールの具体的な設定や導入手順は `ENV_` カテゴリのドキュメントに記載する. diff --git "a/docs/01_GUIDE/GUIDE_05_\343\202\263\343\203\274\343\203\211\343\202\263\343\203\241\343\203\263\343\203\210\350\246\217\345\211\207.txt" "b/docs/01_GUIDE/GUIDE_05_\343\202\263\343\203\274\343\203\211\343\202\263\343\203\241\343\203\263\343\203\210\350\246\217\345\211\207.txt" new file mode 100644 index 0000000..671a5d3 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_05_\343\202\263\343\203\274\343\203\211\343\202\263\343\203\241\343\203\263\343\203\210\350\246\217\345\211\207.txt" @@ -0,0 +1,197 @@ +======================================================================== +コードコメント・ドキュメント規則 (Code Comment & Documentation Guide) +======================================================================== + + +1. 基本方針 (Basic Policy) +------------------------------------------------------------------------ +コードの可読性と保守性を高めるため,ファイル・クラス・関数・定数それぞれに対して +適切な粒度でコメントを記述する. +※ コードの書き方自体の規則は `GUIDE_04_コーディング規則.txt` を参照する. + +・言語: 日本語で記述する. +・句読点: 「,」(全角カンマ)を使用し,文末の句点(「.」「。」)は付けない. + - 列挙が続く場合は「,」で区切る. +・文体: 体言止め,または「〜する」形で統一する. +・更新: コードを変更した場合は,対応するコメントも必ず合わせて更新する. + - コードと乖離したコメントは誤解を招くため,古いまま放置しない. + + +2. コメントの種類と用途 (Comment Types) +------------------------------------------------------------------------ + +2-1. ファイルドキュメント (Module Docstring) + ・ファイルの先頭に必ず記述する. + ・トリプルダブルクォート(`""" """`)を使用する. + ・書式: + + """ + [ファイル名(拡張子なし)] + [ファイルの主な責務を1行で説明] + [補足情報があれば続けて記述] + """ + + ・例: + + """ + motor_controller + モーターの制御を担当するモジュール + GPIO を介して左右のモーターの速度・方向を制御する + """ + +2-2. クラスドキュメント (Class Docstring) + ・全てのクラスに記述する. + ・クラス定義の直後にトリプルダブルクォートで記述する. + ・書式: + + class ClassName: + """[そのクラスが何を表すかを端的に説明]""" + + ・複数行が必要な場合: + + class ClassName: + """ + [そのクラスが何を表すかを端的に説明] + [補足情報] + """ + + ・例: + + class MotorController: + """左右のモーターを GPIO 経由で制御するクラス""" + +2-3. 関数・メソッドドキュメント (Function Docstring) + ・公開関数・メソッドには必ず記述する. + ・Google スタイルの docstring を使用する. + ・書式: + + def function_name(arg1: type, arg2: type) -> return_type: + """[その関数が何をするかを端的に説明] + + Args: + arg1: [説明] + arg2: [説明] + + Returns: + [返り値の説明] + """ + + ・引数・返り値がない,または自明な場合は1行で省略してよい. + + def stop(self) -> None: + """全モーターを停止する""" + + ・例外をスローする可能性がある場合は `Raises` セクションを付ける. + + def set_speed(self, speed: int) -> None: + """モーターの速度を設定する + + Args: + speed: 0〜100 の範囲の速度値 + + Raises: + ValueError: speed が 0〜100 の範囲外の場合 + """ + + ・廃止予定のものには非推奨であることを明記し,代替を示す. + + def old_method(self) -> None: + """非推奨: new_method を使用すること""" + + ・例: + + def calc_distance(speed: float, duration: float) -> float: + """速度と時間から距離を計算する + + Args: + speed: 移動速度 (m/s) + duration: 経過時間 (s) + + Returns: + 移動距離 (m) + """ + return speed * duration + +2-4. 定数ドキュメント (Constant Comment) + ・公開される定数にはインラインコメント(`#`)を直前行に記述する. + ・書式: + + # [その定数が何を表すかを端的に説明] + CONSTANT_NAME = value + + ・例: + + # UI側と共有する最大速度の既定値 + MAX_SPEED = 100 + + # 超音波センサーの測定間隔 (秒) + SENSOR_INTERVAL_SEC = 0.5 + +2-5. ブロックコメント (Block Comment) + ・関数・メソッド内で,処理のまとまりが変わる箇所に記述する. + ・`#` + 半角スペースを使用する. + ・書式: + + # [このブロックの処理を端的に説明] + ...処理... + + ・例: + + # 入力値を正規化する + normalized = raw_value / MAX_VALUE + + # モーターに速度を反映する + GPIO.output(self._pin, normalized) + +2-6. タスクコメント (Task Comment) + ・後で対応が必要な箇所に記述し,担当者と内容を明記する. + ・`#` + 半角スペースを使用し,以下のタグで種別を区別する. + ・書式: + + # [タグ]([担当者名]): [内容] + + ■ タグ定義: + - TODO : 将来的に実装・対応が必要な箇所 + - FIXME : 既知のバグや不具合があり修正が必要な箇所 + - HACK : 意図的な暫定対応であり,本来あるべき実装ではない箇所 + + ・例: + + # TODO(yamada): タイムアウト処理を実装する + # FIXME(tanaka): 距離が負になるケースでクラッシュする + # HACK(suzuki): API仕様確定まで固定値で代替している + + ・注意: + - 「いつか直す」ではなく,必ずタスク管理ツールとセットで運用する + - FIXME はリリース前に必ず解消する + - HACK は技術的負債として定期的に見直す + + +3. 記述しない場合の判断基準 (When to Omit) +------------------------------------------------------------------------ +・ファイル内部でのみ使用し,外部に公開されない関数・定数は省略してもよい +・コード自体が自明な場合(変数名で意図が十分伝わる場合)は省略してもよい +・ユニットテストファイルは,テストケース名で意図が伝わる場合は省略してもよい + + +4. NG例 (Anti-patterns) +------------------------------------------------------------------------ +・句点を付ける + - NG: """ジョイスティックの入力を受け取る.""" + - OK: """ジョイスティックの入力を受け取る""" + +・「、」「。」を使う + - NG: # 入力開始時の基準座標をセットする。 + - OK: # 入力開始時の基準座標をセットする + +・コードをコメントアウトして残す + - NG: # old_handler = lambda: ... + - OK: 不要なコードは削除する(Git履歴から復元できる) + +・docstring を通常のコメントで書く + - NG: # motor_controller: モーターの制御を担当するモジュール + - OK: + """ + motor_controller + モーターの制御を担当するモジュール + """ diff --git "a/docs/02_PLAN/PLAN_01_\343\203\227\343\203\255\343\202\270\343\202\247\343\202\257\343\203\210\346\246\202\350\246\201.txt" "b/docs/02_PLAN/PLAN_01_\343\203\227\343\203\255\343\202\270\343\202\247\343\202\257\343\203\210\346\246\202\350\246\201.txt" new file mode 100644 index 0000000..d071520 --- /dev/null +++ "b/docs/02_PLAN/PLAN_01_\343\203\227\343\203\255\343\202\270\343\202\247\343\202\257\343\203\210\346\246\202\350\246\201.txt" @@ -0,0 +1,74 @@ +======================================================================== +プロジェクト概要 (Project Overview) +======================================================================== + + +1. プロジェクト概要 (Project Overview) +------------------------------------------------------------------------ + + 1-0. 目的 + + カメラを搭載したロボットカーを自律走行させることを目的とする. + 人間が操作することなく,カメラ画像のみを用いてコース上の黒線を + 認識し,コースアウトせずに走り切るシステムを構築する. + + + 1-1. 最終目標 + + ・走行目標: 黒い1本線が描かれたコースを,コースアウトせずに完走する. + ・速度目標: コースアウトしない範囲で,できるだけ速く1周を完走する. + ・制御方式: カメラ画像を用いた画像処理によるライントレース走行. + ・操作: 人間による操作は不要(完全自律走行). + + + 1-2. コース条件 + + ・ライン色: 黒(周囲は白) + ・ライン形状: 1本線 + + +2. ハードウェア構成 (Hardware Configuration) +------------------------------------------------------------------------ + + 2-1. 使用機器 + + ・メインコンピュータ: Raspberry Pi + ・カメラ: Raspberry Pi カメラモジュール + ・モータードライバ: TB6612FNG + ・モーター: 左右各1基(計2基) + ・センサー: カメラのみ(ラインセンサー等は使用しない) + + 2-2. 機器構成 + + ・カメラ取り付け位置: 車体前方 + ・カメラ向き: 真下(路面の黒線を真上から撮影) + ・駆動方式: 差動2輪駆動 + - 左右モーターの回転速度差によって直進・旋回を制御する. + + +3. システム概要 (System Overview) +------------------------------------------------------------------------ + + 3-1. 処理の大まかな流れ + + 1. カメラで路面を撮影する. + 2. 画像処理により,黒線の位置・向きを認識する. + 3. 認識結果をもとに,操舵量(throttle / steer)を計算する. + 4. 計算結果を左右モーターへ出力し,車体を制御する. + 5. 上記を繰り返すことで,ライン上を継続走行する. + + 3-2. 操舵量計算の方針 + + ・制御方式: PD 制御(ルールベース)を基本とする. + ・偏差の算出: カメラ画像から黒線の位置を検出し, + 画像中心からのずれを偏差として用いる. + ・操舵: 偏差に基づく PD 制御で操舵量を決定する. + ・速度: 操舵量が大きいほど減速し,直線では加速する. + ※ 詳細な計算方法・パラメータは別ドキュメントにて定義する. + + + 3-3. 実行環境 + + ・Raspberry Pi を使用する. + ・Raspberry Pi 単体で完結させるか,PC と連携させるかは未定. + ※ 現状は Raspberry Pi をメインの実行環境として想定する. diff --git "a/docs/03_TECH/TECH_01_\346\223\215\350\210\265\351\207\217\350\250\210\347\256\227\344\273\225\346\247\230.txt" "b/docs/03_TECH/TECH_01_\346\223\215\350\210\265\351\207\217\350\250\210\347\256\227\344\273\225\346\247\230.txt" new file mode 100644 index 0000000..94b66d6 --- /dev/null +++ "b/docs/03_TECH/TECH_01_\346\223\215\350\210\265\351\207\217\350\250\210\347\256\227\344\273\225\346\247\230.txt" @@ -0,0 +1,151 @@ +======================================================================== +操舵量計算仕様 (Steering Calculation Specification) +======================================================================== + + +1. 概要 (Overview) +------------------------------------------------------------------------ + + 1-0. 目的 + + カメラ画像から黒線の位置を検出し,PD 制御によって操舵量と速度を + 算出する方法を定義する. + + + 1-1. 基本方針 + + ・制御方式: PD 制御(I 項なしで開始) + ・偏差の算出: 画像の近方・遠方2領域から黒線の重心位置を取得する. + ・操舵量: 偏差に基づく PD 制御で決定する. + ・速度: 操舵量に応じて動的に調整する(カーブ減速,直線加速). + + +2. 画像処理パイプライン (Image Processing Pipeline) +------------------------------------------------------------------------ + + 2-1. 処理フロー + + 1. カメラからフレームを取得する. + 2. グレースケールに変換する. + 3. ガウシアンブラーを適用する(軽いノイズ除去). + 4. 二値化する(固定閾値 or 大津の方法). + 5. 近方領域・遠方領域それぞれで黒ピクセルの重心 x 座標を算出する. + + 2-2. 2領域方式 + + カメラは真下を向いているため,画像内の位置が路面上の距離に対応する. + 画像を上下2つの領域に分割し,それぞれで線の位置を検出する. + + 画像上部 ─── 遠方領域(これから通る場所) + │ + 画像下部 ─── 近方領域(今いる場所) + + ・近方領域: 画像下部の水平帯.現在の車体位置に対する線のずれを示す. + ・遠方領域: 画像上部の水平帯.この先のコース方向を示す. + + ※ 各領域の具体的な y 座標範囲は実走テストで調整する. + + +3. 偏差の算出 (Error Calculation) +------------------------------------------------------------------------ + + 3-1. 基本偏差 + + 各領域で検出した黒線の重心 x 座標と,画像中心 x 座標との差を + 偏差とする. + + e_near = image_center_x - near_line_x + e_far = image_center_x - far_line_x + + ・e > 0: 線が画像の左側にある(右に寄っている) + ・e < 0: 線が画像の右側にある(左に寄っている) + ・e = 0: 線が画像の中心にある(理想状態) + + 3-2. 制御用偏差 + + 近方偏差と遠方偏差を重み付きで合成し,制御に使用する偏差とする. + + e = α * e_near + β * e_far + + ・α: 近方の重み(現在の位置補正) + ・β: 遠方の重み(先読み補正) + ・α + β = 1.0 とする. + ※ α,β の具体的な値は実走テストで調整する. + + +4. PD 制御 (PD Control) +------------------------------------------------------------------------ + + 4-1. 操舵量の計算 + + steer = Kp * e + Kd * (e - e_prev) / dt + + ・Kp: 比例ゲイン.偏差に比例した操舵量を出力する. + - 大きいほど応答が速いが,振動しやすい. + ・Kd: 微分ゲイン.偏差の変化率に比例した操舵量を出力する. + - 振動を抑制し,カーブへの追従を滑らかにする. + ・e_prev: 前フレームの偏差. + ・dt: 前フレームからの経過時間. + + 4-2. 操舵量の制限 + + 計算結果を -1.0 ~ +1.0 の範囲にクランプする. + + steer = clamp(steer, -1.0, +1.0) + + 4-3. I 項について + + 初期段階では I 項を使用しない. + 理由: カーブ中に偏差が蓄積し,カーブ出口でオーバーシュート + (ワインドアップ)を引き起こすリスクがあるため. + 直線走行で定常的にずれ続ける症状が確認された場合にのみ, + 小さい Ki で追加を検討する. + + +5. 速度制御 (Speed Control) +------------------------------------------------------------------------ + + 5-1. 基本方式(操舵量連動) + + throttle = max_throttle - k * |steer| + + ・max_throttle: 直線での最大速度. + ・k: 減速係数.操舵量が大きいほど減速する. + ・|steer| が大きい → カーブ中 → 減速 + ・|steer| が小さい → 直線 → 加速 + + 5-2. 発展方式(曲率推定連動) + + 基本方式で速度の限界を感じた場合,近方・遠方の偏差差分から + 曲率を推定し,カーブの手前で事前に減速する方式へ移行する. + + curvature = |e_far - e_near| + throttle = max_throttle - k * curvature + + ※ 基本方式で完走を達成した後に検討する. + + +6. パラメータ一覧 (Parameters) +------------------------------------------------------------------------ + + ■ 画像処理パラメータ + + ・画像解像度: 未定(既存設定は 320x240) + ・二値化閾値: 実走テストで決定 + ・近方領域の y 範囲: 実走テストで決定 + ・遠方領域の y 範囲: 実走テストで決定 + + ■ 偏差合成パラメータ + + ・α(近方の重み): 実走テストで決定 + ・β(遠方の重み): 実走テストで決定 + + ■ PD 制御パラメータ + + ・Kp(比例ゲイン): 実走テストで決定 + ・Kd(微分ゲイン): 実走テストで決定 + + ■ 速度制御パラメータ + + ・max_throttle(最大速度): 実走テストで決定 + ・k(減速係数): 実走テストで決定 diff --git "a/docs/03_TECH/TECH_02_\343\202\267\343\202\271\343\203\206\343\203\240\346\247\213\346\210\220\344\273\225\346\247\230.txt" "b/docs/03_TECH/TECH_02_\343\202\267\343\202\271\343\203\206\343\203\240\346\247\213\346\210\220\344\273\225\346\247\230.txt" new file mode 100644 index 0000000..afdc5bf --- /dev/null +++ "b/docs/03_TECH/TECH_02_\343\202\267\343\202\271\343\203\206\343\203\240\346\247\213\346\210\220\344\273\225\346\247\230.txt" @@ -0,0 +1,149 @@ +======================================================================== +システム構成仕様 (System Architecture Specification) +======================================================================== + + +1. 概要 (Overview) +------------------------------------------------------------------------ + + 1-0. 目的 + + ライントレース自律走行を実現するために,Raspberry Pi と PC が + それぞれ担う処理と,両者間の通信の流れを定義する. + + + 1-1. 全体構成 + + Raspberry Pi はカメラ画像の取得とモーター制御を担当し, + PC は画像処理・操舵量計算・GUI 表示を担当する. + + Raspberry Pi PC + ──────────── ── + カメラ撮影 画像受信 + │ │ + └──── 画像送信 ──────> │ + 画像処理・線検出 + │ + 操舵量計算(PD 制御) + │ + ┌──── 操舵量受信 <────── 操舵量送信 + │ + モーター制御 + + +2. Raspberry Pi 側の処理 (Raspberry Pi Processing) +------------------------------------------------------------------------ + + 2-1. カメラ画像の取得 + + ・Picamera2 を使用してフレームを取得する. + ・取得した画像を PC に送信する. + ※ 送信フォーマット(JPEG 圧縮 or RAW 等)は実装時に決定する. + + 2-2. 操舵量の受信 + + ・PC から送信された操舵量(throttle,steer)を受信する. + + 2-3. モーター制御 + + ・受信した throttle,steer を既存の `MotorDriver.set_drive()` に渡し, + 左右モーターを制御する. + ・差動2輪駆動の計算は既存コードを流用する. + - left = throttle + steer + - right = throttle - steer + ・極性補正・PWM 出力も既存コードに従う. + + 2-4. フェイルセーフ + + ・一定時間(例: 0.5秒)操舵量を受信しなかった場合, + モーターを自動停止する. + ・通信切断時の暴走を防止する. + + +3. PC 側の処理 (PC Processing) +------------------------------------------------------------------------ + + 3-1. 画像の受信 + + ・Raspberry Pi から送信されたカメラ画像を受信する. + + 3-2. 画像処理・線検出 + + ・受信した画像から黒線の位置を検出する. + ・処理手順: + 1. グレースケール変換 + 2. ガウシアンブラー(ノイズ除去) + 3. 二値化 + 4. 近方・遠方2領域で黒ピクセルの重心 x 座標を算出 + ・詳細は `TECH_01_操舵量計算仕様.txt` を参照する. + + 3-3. 操舵量計算 + + ・検出した線の位置から偏差を算出し,PD 制御で操舵量を計算する. + ・速度は操舵量に応じて動的に調整する. + ・詳細は `TECH_01_操舵量計算仕様.txt` を参照する. + + 3-4. 操舵量の送信 + + ・計算した throttle,steer を Raspberry Pi に送信する. + + 3-5. GUI 表示 + + ■ カメラ映像表示 + ・受信した画像をリアルタイムで表示する. + ・画像処理の結果(検出した線の位置,偏差等)をオーバーレイ表示する. + + ■ 自動操縦の切り替え + ・自動操縦の ON / OFF を切り替えるボタンを設ける. + ・ON: 画像処理の結果に基づいて操舵量を自動計算・送信する. + ・OFF: 手動操作モードに切り替わる. + + ■ パラメータ調整 + ・PD 制御パラメータ(Kp,Kd 等)をリアルタイムに変更できる + UI を設ける. + ・変更したパラメータは即座に操舵量計算に反映される. + + ■ 手動操作 + ・自動操縦 OFF 時に,ユーザーが手動で車体を操作できる. + ・操作方式は操作性を重視して設計する. + + +4. 設計方針 (Design Policy) +------------------------------------------------------------------------ + + 4-1. 操舵量計算の独立性 + + 操舵量の計算ロジックは,タイム短縮やコースアウト防止のために + 試行錯誤で改善していくことを前提とする. + そのため,操舵量計算を他の処理から独立させ,計算式やアルゴリズムの + 変更が通信・モーター制御・GUI のコードに影響しない構成とする. + + ・入力: カメラ画像(NumPy 配列) + ・出力: throttle(float: -1.0 ~ +1.0),steer(float: -1.0 ~ +1.0) + + この入出力を維持する限り,計算の中身(偏差の取り方,制御式, + 速度調整の方法等)を自由に変更できる. + + +5. 通信の流れ (Communication Flow) +------------------------------------------------------------------------ + + 4-1. 全体のループ + + 以下のサイクルを毎フレーム繰り返す. + + 1. Pi: カメラでフレームを取得する. + 2. Pi → PC: 画像を送信する. + 3. PC: 画像処理・線検出を行う. + 4. PC: 操舵量を計算する(自動時)またはユーザー入力を取得する(手動時). + 5. PC → Pi: 操舵量(throttle,steer)を送信する. + 6. Pi: 受信した操舵量でモーターを制御する. + + 4-2. 通信要件 + + ・双方向通信: Pi → PC(画像),PC → Pi(操舵量). + ・低遅延: 画像取得からモーター反映までの遅延を最小限にする. + ※ 遅延が大きいとコースアウトのリスクが増加する. + ・信頼性: パケットロス時の振る舞いを定義する. + - 画像が届かない場合: 前フレームの操舵量を維持する. + - 操舵量が届かない場合: フェイルセーフでモーター停止する. diff --git "a/docs/04_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257\351\201\270\345\256\232.txt" "b/docs/04_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257\351\201\270\345\256\232.txt" new file mode 100644 index 0000000..68c79f2 --- /dev/null +++ "b/docs/04_ENV/ENV_01_\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257\351\201\270\345\256\232.txt" @@ -0,0 +1,107 @@ +======================================================================== +技術スタック選定 (Technology Stack Selection) +======================================================================== + + +1. 概要 (Overview) +------------------------------------------------------------------------ + + 1-0. 目的 + + ライントレース自律走行システムで使用する技術スタックと, + その選定理由を定義する. + + + 1-1. 全体方針 + + ・言語: Python で統一する(Pi 側・PC 側ともに). + ・既存資産: モーター制御コード(`src/pi/motor.py`)を流用する. + ・選定基準: 低遅延・軽量・Python との親和性を重視する. + + +2. 技術スタック一覧 (Technology Stack) +------------------------------------------------------------------------ + + 2-1. 通信: ZMQ(ZeroMQ) + + ・ライブラリ: pyzmq + ・通信パターン: PUB/SUB + ・オプション: ZMQ_CONFLATE=1(受信側で最新メッセージのみ保持) + ・用途: + - Pi → PC: カメラ画像の送信 + - PC → Pi: 操舵量(throttle,steer)の送信 + + ■ 選定理由 + ・ブローカー不要で軽量,低遅延に適している. + ・PUB/SUB + CONFLATE により,送受信が互いをブロックせず, + 常に最新データのみを扱える. + ・バイナリデータ(画像)の送受信が容易である. + + ■ 不採用とした候補 + ・WebSocket: バイナリ送信のオーバーヘッドが大きい. + ・gRPC: 構造化 API 向きで,リアルタイム制御には過剰. + ・生 UDP: 最も低遅延だが,フレーミングやシリアライズを + 自前で実装する必要がある. + + 2-2. GUI フレームワーク: PySide6 + + ・用途: PC 側のアプリケーション全般 + - カメラ映像のリアルタイム表示 + - 自動操縦 ON/OFF ボタン + - パラメータ調整スライダー + - 手動操作のキー入力ハンドリング + + ■ 選定理由 + ・ボタン・スライダー等のウィジェットが豊富である. + ・QTimer による映像のリアルタイム更新が容易である. + ・キーボード入力のハンドリングが柔軟で,手動操作に適している. + ・ライセンスが LGPL で利用しやすい. + + ■ 不採用とした候補 + ・OpenCV highgui(imshow): ボタンやスライダーの自由度が低い. + ・tkinter: リアルタイム映像表示のパフォーマンスに不安がある. + + 2-3. 画像処理: OpenCV(cv2) + + ・用途: PC 側での画像処理・線検出 + - グレースケール変換 + - ガウシアンブラー + - 二値化 + - 重心算出 + + ■ 選定理由 + ・ライントレースに必要な処理がすべて揃っている. + ・NumPy ベースで PySide6 への画像受け渡しが容易である. + ・既存コードでの使用実績がある. + + 2-4. カメラ制御: Picamera2 + + ・用途: Pi 側でのカメラフレーム取得 + + ■ 選定理由 + ・Raspberry Pi カメラの標準ライブラリである. + ・既存コードでの使用実績がある. + + 2-5. モーター制御: RPi.GPIO + + ・用途: Pi 側での TB6612FNG モータードライバ制御 + + ■ 選定理由 + ・既存コード(`src/pi/motor.py`)をそのまま流用できる. + ・PWM 制御・GPIO 出力に必要な機能が揃っている. + + +3. 構成まとめ (Summary) +------------------------------------------------------------------------ + + ■ Raspberry Pi 側 + + ・Picamera2: カメラフレーム取得 + ・RPi.GPIO: モーター制御 + ・pyzmq: PC との通信 + + ■ PC 側 + + ・PySide6: GUI アプリケーション + ・OpenCV: 画像処理・線検出 + ・pyzmq: Pi との通信 diff --git "a/docs/04_ENV/ENV_02_PC\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.txt" "b/docs/04_ENV/ENV_02_PC\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.txt" new file mode 100644 index 0000000..c27c07e --- /dev/null +++ "b/docs/04_ENV/ENV_02_PC\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.txt" @@ -0,0 +1,91 @@ +======================================================================== +PC 環境構築手順 (PC Environment Setup) +======================================================================== + + +1. 前提条件 (Prerequisites) +------------------------------------------------------------------------ + + 1-1. OS + + ・Windows 11 Home + + 1-2. Python + + ・バージョン: 3.12.10 + ・インストール元: Microsoft Store 版 + ・確認コマンド: + + $ python --version + + 1-3. pip + + ・Python に同梱されているものを使用する. + + +2. venv の作成 (Create Virtual Environment) +------------------------------------------------------------------------ + + 2-1. 作成 + + プロジェクトルートで以下を実行する. + + $ cd c:\Users\rinto\source\RobotCar + $ python -m venv .venv + + ・`.venv/` ディレクトリが作成される. + ・`.venv/` は Git 管理外とする(`.gitignore` に追加). + + 2-2. 有効化 + + ■ PowerShell の場合 + + $ .venv\Scripts\Activate.ps1 + + ■ コマンドプロンプトの場合 + + $ .venv\Scripts\activate.bat + + ■ Git Bash の場合 + + $ source .venv/Scripts/activate + + ・有効化するとプロンプトの先頭に `(.venv)` が表示される. + + 2-3. pip のアップグレード + + $ python -m pip install --upgrade pip + + +3. ライブラリのインストール (Install Libraries) +------------------------------------------------------------------------ + + 3-1. 一括インストール + + `requirements_pc.txt` を使用して一括インストールする. + + $ pip install -r requirements_pc.txt + + 3-2. インストールされるライブラリ + + ・PySide6 (6.10.2): GUI フレームワーク + ・opencv-python (4.13.0.92): 画像処理 + ・pyzmq (27.1.0): ZMQ 通信 + ・numpy (2.4.3): 数値計算(OpenCV の依存ライブラリ) + + 3-3. インストール確認 + + $ pip freeze + + 上記コマンドで `requirements_pc.txt` に記載されたライブラリと + バージョンが表示されることを確認する. + + +4. 動作確認 (Verification) +------------------------------------------------------------------------ + + 4-1. ライブラリの import 確認 + + 以下を Python で実行し,エラーが出ないことを確認する. + + $ python -c "import PySide6; import cv2; import zmq; print('OK')" diff --git "a/docs/04_ENV/ENV_03_RaspPi\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.txt" "b/docs/04_ENV/ENV_03_RaspPi\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.txt" new file mode 100644 index 0000000..d40ac62 --- /dev/null +++ "b/docs/04_ENV/ENV_03_RaspPi\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.txt" @@ -0,0 +1,88 @@ +======================================================================== +Raspberry Pi 環境構築手順 (Raspberry Pi Environment Setup) +======================================================================== + + +1. Pi への接続方法 (SSH Connection) +------------------------------------------------------------------------ + + 1-1. 接続情報 + + ・接続ツール: Tera Term + ・ホスト: rpi-a.local + ・ポート: 22 + ・プロトコル: SSH + ・ユーザー名: user + ・認証方式: パスワード認証 + ・パスワード: user + + 1-2. 接続手順 + + 1. Tera Term を起動する. + 2. 「新しい接続」ダイアログで以下を入力する. + - ホスト: rpi-a.local + - サービス: SSH + - TCPポート: 22 + 3. 「OK」を押す. + 4. セキュリティ警告が表示された場合は「続行」を押す. + 5. 認証ダイアログで以下を入力する. + - ユーザ名: user + - パスフレーズ: user + - 認証方式: 「プレインパスワードを使う」を選択 + 6. 「OK」を押すとログインできる. + + +2. ファイル転送方法 (File Transfer via SCP) +------------------------------------------------------------------------ + + 2-1. 概要 + + PC で作成・編集したファイルを Tera Term の SCP 機能で + Pi に転送する. + + 2-2. PC → Pi へのファイル転送手順 + + 1. Tera Term で Pi に SSH 接続した状態にする. + 2. メニューバーから「ファイル」→「SSH SCP...」を選択する. + 3. 「SCP」ダイアログが表示される. + 4. 上段の「From:」にPC側の転送元ファイルパスを入力する. + ※ ファイルをダイアログにドラッグ&ドロップしても可. + 5. 「To:」に Pi 側の転送先ディレクトリを入力する. + - 例: /home/user/RobotCar/ + 6. 「Send」を押すと転送が開始される. + + 2-3. フォルダ転送の注意 + + ・SCP では単一ファイルの転送が基本となる. + ・複数ファイルをまとめて転送したい場合は,PC 側で zip に圧縮し, + 転送後に Pi 側で展開する. + + $ unzip filename.zip + + 2-4. 転送対象 + + 以下の2ディレクトリを Pi に転送する. + + ・src/common/ → /home/user/RobotCar/common/ + ・src/pi/ → /home/user/RobotCar/pi/ + + ※ src/pc/ は PC 上でのみ使用するため転送不要. + + 2-5. 転送先ディレクトリ + + ・Pi 上の作業ディレクトリ: /home/user/RobotCar/ + ※ 初回はディレクトリを作成する必要がある. + + $ mkdir -p /home/user/RobotCar + + +3. venv の作成・ライブラリインストール (Virtual Environment) +------------------------------------------------------------------------ + + ※ Pi 側の環境構築は実機作業時に手順を確定し,追記する. + + +4. 動作確認 (Verification) +------------------------------------------------------------------------ + + ※ Pi 側の動作確認は実機作業時に手順を確定し,追記する. diff --git "a/docs/04_ENV/ENV_04_\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\346\247\213\346\210\220.txt" "b/docs/04_ENV/ENV_04_\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\346\247\213\346\210\220.txt" new file mode 100644 index 0000000..4d4d0d2 --- /dev/null +++ "b/docs/04_ENV/ENV_04_\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\346\247\213\346\210\220.txt" @@ -0,0 +1,68 @@ +======================================================================== +ディレクトリ構成 (Directory Structure) +======================================================================== + + +1. 概要 (Overview) +------------------------------------------------------------------------ + + 1-0. 目的 + + 自律走行システムのソースコードのディレクトリ構成を定義する. + ディレクトリ構成を変更した場合は本ドキュメントも更新すること. + + 1-1. 状態の表記 + + ・(実装済み): ファイルが存在し,動作する状態. + ・(未実装): 今後作成予定のファイル. + ・表記なし: ディレクトリのみ作成済み. + + +2. ディレクトリ構成 (Directory Structure) +------------------------------------------------------------------------ + + 2-1. 全体構成 + + RobotCar/ + ├── CLAUDE.md (実装済み) + ├── requirements_pc.txt (実装済み) + ├── requirements_pi.txt (実装済み) + ├── docs/ ドキュメント + ├── src/ 自律走行用ソースコード + │ ├── common/ 共通設定(PC・Pi 両方で使用) + │ ├── pc/ PC 側 + │ └── pi/ Pi 側 + └── src_old/ 旧コード(参照用) + + 2-2. src/common/ + + common/ + └── config.py (未実装) + + ・PC・Pi 間で共有する設定値を定義する. + ・内容: ネットワーク設定,画像フォーマット,通信設定等. + + 2-3. src/pc/ + + pc/ + ├── main.py (未実装) エントリーポイント + ├── gui/ GUI 関連 + │ └── main_window.py (未実装) メインウィンドウ + ├── comm/ 通信関連 + │ └── zmq_client.py (未実装) ZMQ 送受信 + ├── steering/ 操舵量計算(独立モジュール) + │ ├── base.py (未実装) 共通インターフェース + │ └── pd_control.py (未実装) PD 制御の実装 + └── vision/ 画像処理 + └── line_detector.py (未実装) 線検出 + + 2-4. src/pi/ + + pi/ + ├── main.py (未実装) エントリーポイント + ├── comm/ 通信関連 + │ └── zmq_client.py (未実装) ZMQ 送受信 + ├── camera/ カメラ関連 + │ └── capture.py (未実装) フレーム取得 + └── motor/ モーター関連 + └── driver.py (未実装) TB6612FNG 制御 diff --git a/requirements_pc.txt b/requirements_pc.txt new file mode 100644 index 0000000..4877e6c --- /dev/null +++ b/requirements_pc.txt @@ -0,0 +1,4 @@ +PySide6==6.10.2 +opencv-python==4.13.0.92 +pyzmq==27.1.0 +numpy==2.4.3 diff --git a/requirements_pi.txt b/requirements_pi.txt new file mode 100644 index 0000000..d073deb --- /dev/null +++ b/requirements_pi.txt @@ -0,0 +1,3 @@ +pyzmq==27.1.0 +picamera2 +RPi.GPIO