VIVITABLOG

VIVITAで活躍するメンバーの情報発信サイト

ArduPilotを使って(ちょっとだけ)自動運転ラジコンカーを作ってみた

VIVITAの新居です。

今回は手持ちのラジコンカーを改造して、ArduPilotを使って(ちょっとだけ)自動運転の実験をおこなったのでその内容を紹介します。

f:id:hnii1970:20200424104604j:plain

改造した点が安全かどうか検証したわけではありません。実際に試す場合には各自でよく考えてすすめてください。

はじめに

表題のArduPilotはドローンや自動車のラジコンと組み合わせて操縦をアシスト(操縦を簡単にしたり、あらかじめ決められたコースを自動航行)するソフトです。まずはどんなことができるか、動画をご覧下さい。

youtu.be

ところで、自動運転というとAIが画像処理をおこない、自動的に障害物をよけていくようなイメージがあります。 例えば、「ドンキーカー」などと呼ばれるAIロボットカーの競技もおこなわれています。しかし、今回は自分の考える面白いところを押さえて、自動運転車を作ってみました。

面白いところとは?

ラジコンって面白いですよね。「自分で操縦してうまく走れる」という部分が特に面白さを感じるところだと思います。 次にうまく走れる部分をソフトにして、「自分でプログラムしてうまく走れるラジコンを作る」、というところもとても好きなんです。学生の頃はマイクロマウスをやっていたので、その体験が関係しているかもしれません。

今回は自分が面白いと思った、 「GPSの正確な座標をとって手元で指示したコースを走る移動車」を簡単に(既存のシステムを使って)作って実験してみました。 障害物の回避もできるような構成ですが、今回は衝突回避がまったくつけられなかったので、題名に「ちょっとだけ」と入っています。

基本方針

20年前の昔ならマイコンボードを自分で作って、データシートとにらめっこをしながらマイコンの初期設定やポート設定をおこなうところからはじめて、そのペースで自動移動車を完成させるとなると何年もかかってしまいそうです。

しかし、現代はマイコンをちょっと触りたい場合はArduinoです。ポートの設定もデータシートを読まずにちゃっちゃとできて、C言語でやりたい所だけを書けば良いので快適です。

同じような考え方はラジコンにも広がっています。その一例が今回紹介する「ArduPilot」というシステムです。 今回はこのArduPilotを使って簡単にラジコンを(ちょっとだけ)自動運転車に改造して見ました。

ArduPilotとは?

ArduPilotは小さなマイコンボードに搭載される飛行(走行)制御用ソフトウェアの事を指します。 このソフトはマイコン上の自動操縦部分だけでなく、操縦をサポートするWindowsソフト(Mission Planner)も同時に頒布されていて、ArduPilotの設定をGUIでできるのはもちろん、地図上で現在地を表示したり、行き先を指定する機能、詳細なlogを記録、分析する機能がついてるのが特徴だと思います。

このArduPilot、当初は本当のAVR MEGAボード上のArduinoの開発環境で動いていたそうです。

f:id:hnii1970:20200424103520j:plain
2010年ごろ開発されたArduino Pro miniで制御されたドローンの例
その後、オープンソースのドローン制御用システムとして進化して、今ではドローン以外に飛行機は勿論、自動車、船、潜水艦までサポートされています。

ちなみに、Arduinoのソフトを書くときに最初にお目にかかるsetup()とloop()ですが、現在のArduPilotのソースコードにも残っています。自分で機能を追加するのも結構簡単で、setup側で初期化してloopで機能を実行するという意味では同じです。それに加えて組み込み用マルチタスクOSが乗っているので、タイマーで周期的に実行する関数などは簡単に実現できます。このようにマイコンのデータシートを読まなくても結構いろいろな機能拡張ができてしまうのは驚きです。

どのような構成にするか?

まずは基本戦略は以下の通り。

ArduPilotはソフトだけなので、それをサポートしたボードを購入する必要があります。 メーカー製のしっかりしたボードが2万円程度で売られているので、仕事で使うならそちらが良いですが、ポケットマネーで買うには高いです。 この手のボードが多数売られているbanggood.comを眺めてみると、非常に多くの種類があります。

ardupilot nav - Buy Cheap ardupilot nav - From Banggood

どれを選ぶか迷います。以前VIVITAでドローンワークショップをおこなったのですが、その時お世話になった方から5千円以下で買える使いやすいボードとしてFC-10というのをお勧めされましたので、これを使って作ることにしました。

リアルタイムに Mission Plannerに現在位置を伝えたり、中継地点を変更するための通信機能(テレメトリーと呼ばれる)がプロポ以外に必要です。日本では安価な製品がないのでRaspberryPiZeroのWiFiを使うことにします。屋外で実験するときには携帯のテザリングにつなぎ、同じネットワーク内のWindowsマシンにテレメトリーデータを送るようにしてみました。 電池は当初モータ電源と共用していたのですが、NiCd電圧が下がってくると(5.7Vあたりで)RaspberryPiが死ぬ現象が出てくるので、別の電池(LiFe 6.6V)を使うことにしました。

まずは、元々のラジコンの配線を以下に示します。

f:id:hnii1970:20200424142258p:plain
元のラジコンの構成

ごく一般的な2chプロポと、サーボ1つ、モータコントローラ1つの構成です。 これにFC-10コントローラをつけると構成は以下のようになりました。

f:id:hnii1970:20200425233756p:plain
改造後の構成

この図中のFC-10とオレンジのパーツを新たに追加します。

ハードウェアの準備

ArduPilotボード

www.banggood.com こちらでみると、2020年4月現在3000円を切っています。

f:id:hnii1970:20200424105606j:plain
3000円程のフライトコントローラ FC-10 (コンパス、6軸加速度センサ、気圧センサ付き)
到着したボードはこんな感じです。このボードは本来飛行機用に設計されているようですが、自動車でも問題ないはずです。

以前pixhawkというこの業界でとても一般的なモジュールを使っていましたが、それと比べてFC-10のよかった点、悪かった点は以下の通りです。

よかった点

  • ポートも少ないが今回の用途では十分で、サイズが小さい(面積だと約半分)
  • 必要な機能が全部入っている(バッテリー電圧・電流モニター、RCサーボ用電圧変換、FPVカメラをつけた場合に必要なテレメトリーデータを画面に重畳するユニット)
  • コネクタが全てピンヘッダーなので、自分でコネクタを作りやすい

悪かった点

  • SDカードがないので、logが内部に保存できない(しかし今回はラズパイ上で記録するのでいいことにします)

FC-10の下準備

  1. FC-10については、サーボとESCの電源をつなぐために、ちょっとハンダ付けが必要です。 S1、S2(基板上の表記ではM1, M2)のサーボコネクタを差すところの電源ピンには何も繋がっていません。NCと書かれている隣あったピン2点をハンダで繋ぎます。それにより、ESCで生成された5Vがサーボに供給されるようになります。
  2. 次にB+, B-に制御用バッテリーコネクタを繋いでおきます。
  3. ボードには元々iNavのソフトが書き込まれています。それをArduPilotに書き換える必要があります。 最初にArduPilotのboot loaderが含まれた、「_bl.hex」の名をもつファイルを以下のサイトから探します。

ArduPilot firmware : /Rover/latest/F35Lightning

次に、iNav configuratorをインストールし、内蔵のfirmware焼き込みメニューを用いて、先ほどダウンロードした.hexを焼き込みます。 このように、一度ArduPilotのboot loaderを焼き込むと、次はMission Plannerからアップデートが可能となります。

(いろいろ試してみると、iNavでうまくいかない場合が結構ありそうです。その時にはdfu-utilを使う方法が良さそうです。 https://ardupilot.org/dev/docs/using-DFU-to-load-bootloader.html こちらのリンクを参照してください。)

GPSモジュール

GPSモジュールは今回もRTKを用いるので以前購入したublox社のF9Pのモジュールを使い回します。 ケーブルは前回同様JST SHコネクタとピンヘッダのメス型のケーブルを準備します。

f:id:hnii1970:20200424170555j:plain

詳しくは、以前のブログを参照してください。

RTK-GPSを使った1m毎のパルス発生装置の試作(その2) - VIVITABLOG

ただし、ブログで使っていたF9Pモジュールを販売しているサイトは以下の所に変わったようです。

ZED-F9P RTK GNSS receiver board with SMA Base or Rover - Eltehs GNSS OEM Store

F9Pはちょっと高価(アンテナ込で4万円)なので、RTKを使わずDGPSで2~3m精度でもよければ以下のモジュール(約1500円程)を繋いでもまったく同じ設定で遊べます。

www.banggood.com

Raspberry Pi Zero W

言わずと知れたラズパイです。 今回はピンヘッダが付いてないタイプを購入しました。 www.switch-science.com

それにこのようなアングル型ピンヘッダを取付、メスメスのジャンパーケーブルを接続します。

f:id:hnii1970:20200424154902j:plain
RaspberryPi Zero W シリアル接続

PPM Encoder

FC-10や他のArduPilotのボードのラジコンの信号入力端子はPPMやS.BUS1と言われる信号だけになります。 高級なラジコンなら受信機から直接その信号を出せますが、今回使うのはタミヤの最も安価なプロポなので、 その機能がありません。そこで、PPM Encoderと呼ばれる部品を購入します。

www.banggood.com

これを受信機とFC-10の間に挟み信号を中継します。 正確には、PPM Encoderの入力側のch1を受信機のch1に、同様にch3を受信機のch2につなぎます。 なぜこのようにつなぐかというと、ArduPilotは元々ドローン用ソフトであるため、6chとか多チャンネルプロポで使われるように設計されており、ch1がradderでch3がthrottleと決まっていたらしいのです。勿論変更できますが、今回はそれをそのまま使えるようにしました。(Ardupilotはバッテリー電圧低下などでパラメータが突然初期化されることがあります。その時にデフォルト設定で動くと、ハード故障じゃ無いことがわかってうれしかったので、このように設定しています)

ブザー

電圧を掛けるとピーとなるブザーを使います。これにもピンヘッダに刺さるメス型のケーブルをつけておきます。 電子ブザー 12mm UDB−05LFPN: パーツ一般 秋月電子通商-電子部品・ネット通販

配線等

配線の全体像は以下の通りです。

f:id:hnii1970:20200424151544j:plain
自動運転ユニット

FC-10の配線は上の図の改造後の構成を見ながらつなぎます。例えば、図中TX5と書かれている部分はFC-10のTX5とラズパイのRXとをつなぐという意味です。 但し、ラジコン付属だったサーボのコネクタはFC-10のコネクタを下とした時に、左から以下の様に差します。

f:id:hnii1970:20200424211325j:plain
RCサーボの接続法

これでラジコンに自動操縦ユニットを搭載します。FC-10は上下と前後があるので矢印を前に向け正しく貼り付けて下さい。 他のパーツも少々の振動では取れないように、両面テープやゴム紐などでとめて下さい。

コンフィグレーションその1

まずは、システムの電源を入れて、WindowsマシンとUSBで接続、Mission Plannerを起動します。 すると以下のような画面がでます。

f:id:hnii1970:20200425115819j:plain
Mission Planner起動画面

このソフトの細かい使い方は各所にあるので、google等で調べて下さい。

https://www.google.com/search?q=Mission+Planner+%E5%88%9D%E3%82%81%E3%81%A6+%E9%A3%9B%E8%A1%8C&oq=Mission+Planner+%E5%88%9D%E3%82%81%E3%81%A6+%E9%A3%9B%E8%A1%8C

やることは空飛ぶドローンと全く一緒です。まずは「初期設定」のタブをクリックしてから、以下の作業を順次おこないます。

  1. 最新のfirmwareを書き込みます。今回はRoverを選択しましょう。
  2. 加速度センサキャリブレーション(車体の向きなどを確認)
  3. 気圧計キャリブレーション(床に置いて、その気圧を高度0mと設定)
  4. コンパスキャリブレーション(磁気コンパスのキャリブレーション、車体をぐるぐる回す。終わった後リブートが必要なので、USBを一度抜き差しし接続しなおす)
  5. Radio キャリブレーション(プロポを繋いで、スティックの動きがキチンと伝わるか)

その後、「設定・調整」の中のフルパラメータリストのページで、ArduPilotの設定を書き換えていきます。 パラメータリストにどのようなものがあるかは、こちらのページを見ていきます。 Complete Parameter List — Rover documentation

絶対おこなう変更は以下の3点だけです。これで最小限Roverが使えるようになります。簡単ですよね。

○ FC-10にはlog記録機能が無いので
ARMING_CHECK の10bit目(Logging Available)を0に、(初めて実験する場合にはARMING_CHECK -> 0でも良い)

○スロットルのサーボをch3からch2に変えたので
SERVO2_FUNCTION 0 -> 70(Throttle)
SERVO3_FUNCTION 70 -> 0

また、以下の設定はデフォルトのはずですが違っていると動作しないので値を確認します。

○ CH1につなぐサーボの設定
SERVO1_FUNCTION -> 26

○ GPS TX2, RX2の対応
SERIAL3_PROTOCOL -> 5 (GPS)
SERIAL3_BAUD -> 38 (38400bps)

○ Telemetry TX5, RX5の対応
SERIAL2_PROTOCOL -> 1 (MAVLink1)
SERIAL2_BAUD -> 57 (57600bps)

このとき、SERIAL5とかは基板上のTX5とは異なります。 Furious FPV F-35 Lightning and Wing FC10 — Copter documentation こちらのサイトをよく確認してください。

私の場合、田宮のプロポとESCの問題なのか前進でサーボのパルス幅が小さくなるように動いていました。一方ArduPilotで制御する時には、前進ならサーボのパルス幅が増えるように動きます。 そこでFC-10の受信機入力とサーボ出力のところで極性を反対にします。

RC3_REVERSED 0 -> 1
SERVO2_REVERSED 0 -> 1

これで、ArduPilotからでも、プロポからでも正しく前進するようになります。 あと、自動操縦の時の速度がdefaultだと早すぎるので、以下のパラメータを変化させました。

WP_SPEED -> 0.5  (単位はm/s, AUTOモードにおける移動スピード)
CRUISE_SPEED -> 0.5  (単位はm/s, 基本的な移動スピード)
CRUISE_THROTTLE -> 30  (単位は%, 基本的な移動時のスタート時スロットル量)

ここで、USB接続で設定できるところは終了です。あとはWiFi接続できてからです。

ソフトウェアの準備

Raspberry piにはraspbianの最新版をmicroSDに書き込み、それぞれの環境にあったWiFiで動作するようにしてください。 次にGPIOのシリアルポートを使えるように設定します。動作確認しにくいので、GPIOのピンヘッダでtxとrxの間をショートジャンパーでつなぎループバック確認するのが良さそうです。

その後、AruPilotのテレメトリーを中継するmavproxyというソフトをインストールします。

MAVProxy — MAVProxy 1.6.4 documentation

こちらを見ながらインストールをおこないます。

ターミナル上での起動コマンドは以下の様になります。勿論IPアドレスはMission Plannerが動作しているパソコンのアドレスに変えて下さい。

$ mavproxy.py --master=/dev/ttyAMA0,57600 --out=udpout:192.168.1.29:14500

MAV> Waiting for heartbeat from /dev/ttyAMA0
online system 1
ARMED
HOLD> Mode HOLD
Arming checks disabled
APM: ArduRover V4.0.0 (0e52bafa)
APM: ChibiOS: 0997003f
APM: F35Lightning 0054002F 554B5017 2030334B
APM: ArduRover V4.0.0 (0e52bafa)
APM: ChibiOS: 0997003f
APM: F35Lightning 0054002F 554B5017 2030334B
APM: ArduRover V4.0.0 (0e52bafa)
APM: ChibiOS: 0997003f
APM: F35Lightning 0054002F 554B5017 2030334B

GPIOのシリアルポートが使えない場合、Waiting for heartbeatの行から先に進みません。 うまく動くとターミナル内に、ArduPilotのバージョンナンバーが表示されます。 このターミナルの動作を確認後、Windowsマシン上でMission Plannerを起動します。 今度は接続に「UDP」を使い、port番号を(この起動例では)14500とすると動作します。 USBで繋いだ場合と同じように(ちょっと時間がかかりますが)ラジコンを手で動かすと画面上の角度が変わることを確認して下さい。

これ以後、ArduPilotをリブートさせなければいけないことがありますが、今回の仕組みでは電源を落とすのが面倒です。その時にはmavproxyのターミナルからrebootコマンドを直接送ると、FC-10だけをリブートさせることができます。

    > reboot

コンフィギュレーションその2

これでWifi経由でMission Plannerが動作するようになりました。ここで屋外に持っていき動作実験です。GPSの安定動作のため、全天が見えるところが良いです。また、設定が不十分で暴走するかもしれません。人のいないところで実験しましょう。

これも詳細はドローンと変わらないのでgoogleで調べて下さい。 やることは以下の通りです。

1. ARMED確認

動力をONにする儀式です。ARMEDになると、動力モータが動作するようになります。(ブザーをつけていると、ピーと鳴ります) Mission Plannerのフライトデータ画面の中のアクションタブをクリックして、以下の作業を行います。

f:id:hnii1970:20200425013230j:plain

Arm/Disarmと書かれているボタンを押して、画面がDISARMEDからARMEDに変化するか確認します。 エラーがでたら、Armできない原因を解消してください。 例えばGPSモジュールが正しく繋がってないとエラーがでます。画面はNO GPSのままになります。 他には、上記のキャリブレーションを忘れているとエラーがでます。 またArm/Disarmボタンをもう一度押すとDISARMEDになり、その後は動力モータが回らなくなります。

実はデフォルト設定(フルパラメータリストでARMING_RUDDER->2)だと、ManualやHOLDモードなら、プロポのスティックを右にいっぱいに倒すだけででもARMできます。

2. Manualモードの確認

上の図のアクションタブ内でARMさせた後に、Manualに設定して「モードをセット」というボタンを押します。 その後、スティック操作によりラジコンが正しく動作するか、前後左右が正しいか確認します。

3. Autoモードの確認

Autoモードでラジコンの前進方向や左右方向が正しいか確認します。

まずは、Mission Plannerの「フライト・プラン」画面でway-pointを以下のよう(Lの配置で)に2つ設定します。 WPまでの距離はそれぞれ5m以上離しましょう。次に「WPの書き込み」をおこなってください。

f:id:hnii1970:20200425110727j:plain

その後フライトデータのアクションタグ内の、Autoボタンを押すと走り出します。 このときに以下の点に注意して下さい。

  • WP1に向かっているか確認します。サーボの左右が間違っていると、全く近づきません!
  • WP1を超えたら、WP2に向かうか確認します。WPの位置が正しく入ってないと、WP2に切り替わりません!
  • WP2まで到着したら停止するはずです。
  • 途中で急に停止したいときには、アクションタグ内でManualモードにするのがお勧めです。

4. RTK-GPSの設定

Mission Plannerの初期設定-> オプションハードウェア-> RTK/GPS Injectというメニューを開き、図の接続をクリックします。

f:id:hnii1970:20200425003511j:plain

ここでRTK-GPSの基準局のアドレスを入力します。 アドレスは「善意の基準局掲示板」で調べることができます。今回はCQ出版のサイトを利用させていただきます。

http://guest:guest@160.16.134.72:80/CQ-F9P

これでサーバーが動作していると画面が次のように変わります。 f:id:hnii1970:20200511002724j:plain

この状態でフライトデータに戻るとGPSの表示が3D fixとなっていたのが、rtk floatやrtk fixという表示に変わります。

以上で設定は終わりです。

経験談ですが、ArduPilotを設定していて、なにかおかしいなと思ったらすぐに工場出荷時に戻しましょう。 やりかたは、Mission Plannerで一度飛行機用firmwareを書き込んでからMission plannerに接続し動作確認、その後もう一度Rover用firmwareを書き込みます。 この方法を使うとRAM設定もクリアされパラメータも初期化されるので、その後に自分で変更したい設定を入れていくことでおかしな状態から脱出できるようです。

実験

これを近所の公園で動作を確認してきました。 この環境では停止するとすぐにrtk fix、走り出すとrtk floatになる感じです。 しかしRTK-GPSが効いて1cm単位で座標が正しいので毎回同じルートを走るかというと、そうはなりませんでした。 ハンドルの制御の方が難しく、安定した経路を走る制御ができませんでした。

基本的にはWP_SPEEDの速度を速めながら、安定するパラメータを探します。 この調整の時にはMission Plannerの「設定調整」-> ベーシックチューニングのページが便利です。

f:id:hnii1970:20200425112509j:plain この中の右上の赤枠がWP_SPEEDの値です。このビデオ撮影時には3.2m/sまで上げてみました。 またway-pointを切り替えるときに大回りしてしまうことを防ぐため、TURN_RADIUS->0.3mに 設定してみたところ(図中の左下の赤枠です)、それっぽく動くようになりました。 その様子を以下のビデオにまとめました。

youtu.be

一周走っている様子を撮影し、その時の軌跡を記録しました。 その後ラズパイのコンソールにアクセスし、mavproxyを実行したディレクトリに生成されたmav.tlogというファイルを使ってMission Plannerでプレイバックや解析を行う事ができます。

参考のため、この時のパラメータファイルをこちらにおいておきます。 Dropbox - Rover.param.zip - Simplify your life

まとめ

まずはRTK-GPSを用いて指定したコースを走る「ちょっとだけ自動運転ラジコンカー」を作って実験をしてみました。一応動作しましたが、今後はRTK-GPSならではの使い方とかを試してみたいと思います。また、Ardupilotでは距離センサなどを搭載すると障害物検出も可能なので是非搭載して実験してみたいと思います。

最後に、VIVITAではいつでも面白いエンジニアを求めています。もしご興味がありましたらご連絡ください。


  1. どちらも複数のサーボ信号を時分割で一本の信号に多重化した信号。PPMはパルス幅で情報を表し、S.BUSはシリアル信号とのこと。