マイクロマウスを始める

最近唐突にマイクロマウスを始めたくなったので、メモ代わりに開発の方針や進捗をブログに書いていこうと思います。

マイクロマウスとは?

マイクロマウスとは、自立型ロボットが自力で迷路を探索してゴールまで行き、その最短時間を競う競技です。マイクロハウスには、マイクロマウス(ハーフサイズ)競技とクラシックマウス競技の2つがあります。私はクラシックマウス競技のフレッシュマンクラスに一回目の大会として出ようと思います。

モチベーション

周りにマイクロマウスをやっている人がいないので、とりあえず人のブログに掲載されているロボットを見様見真似で作ってマイクロマウスについて知る。特に大会に勝ちたいというモチベーションはなく、ロボットを体系的に開発しながら学びたい。

 

参考する機体

自分が3年前くらいに北信越大会に見学に行ったことがあり、その時にKERISE v5を見た時に衝撃を受けました。ひとまず構成部品や回路をKERISE v1のgithubのページから適宜参考にしながら、自分で回路設計・機体設計をしてみようと思います。

github.com

今後の予定

使おうと思ってたファウルハーバーのモータが思ったより高かったので、バイトをいつもより多めに入れて、お金を集めつつその間に基板設計と機体設計を終わらせておきたいなと思っています。

www.rt-shop.jp

platformIO+USB Host Shield 2.0でDual Senseの値をArduinoで読み取る

モチベーション

最近よく後輩にコントローラ関連で質問されることが多くて、部内向けwikiに記事を書いたのですがせっかくなのでブログ用に載せてみます。

USB Host Shieldのすごいところ

github.com

コントローラーを使用するときに使うUSB Host Shield2.0ライブラリは更新頻度が高く、最近ではDualSense(PS5コントローラ)やSwitchProが対応されています。 もちろん昔ながらのwiiのコントローラやDual Shockシリーズなど使えます。 市販のコントローラならなんでも使えると思ってもらっても大丈夫です笑

必要なもの

IMG_6831.jpg (2.9 MB)

やり方

1.platformIOをインストールとプロジェクトの作成、Lチカ

VSCodeプラグインであるPlatformIOをインストールして、プロジェクトの作成、Lチカなどを以下のサイトを参考にして頑張ってください。 qiita.com Arduinoを開発するときにArduino IDE使う場合が多いと思いますが、Arduino IDEが使いづらいこととUSB Host Shieldのライブラリを使おうとするとメモリが足りないなどの警告が出るので、PlatformIOを使います。使い慣れればPlatformIOの方が使いやすいです。ひとまず上記のサイトを見ながらuploadの部分までやって、Lチカできるか確かめてください。

2.platformio.iniの書き換え

VScodeの左側にあるplatformio.iniにボードの定義や依存するライブラリを書き加えます。 以下のように書き換えてください。

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:uno]
platform = atmelavr
board = uno
framework = arduino
monitor_speed = 115200

3.ライブラリの追加

github.com githubのページからライブラリをクローンします。DownloadZIPを押してダウンロードしてください。

スクリーンショット 2021-12-12 225513.png (133.8 kB)

ダウンロードが終わったら、解凍してワークスペースのlibにドラック&ドロップして追加してください。

image.png (11.6 kB)

3.settings.hの変更

さきほど追加した中にあるsettings.hの中身を変更します。

スクリーンショット 2021-12-12 230329.png (10.4 kB)

////////////////////////////////////////////////////////////////////////////////
// DEBUGGING
////////////////////////////////////////////////////////////////////////////////

/* Set this to 1 to activate serial debugging */
#define ENABLE_UHS_DEBUGGING 1

ファイルの中から上と同じような部分を見つけて、ENABLE_UHS_DEBUGGING 0をENABLE_UHS_DEBUGGING 1に変更してください。 これをすることによって、コントローラをデバックができるようになります。 逆にここを変えないと一生コントローラー使えません笑

3.サンプルコード実行

サンプルコードがあるlib/USB_Host_Shield_2.0/examples/Bluetooth/PS5BT/PS5BT.inoをsrc/main.cppにコピペしてください。ここでのサンプルコードはArduinoIDE向けのサンプルコードであって、PlatformIO用ではないので、必ず#include <Arduino.h>をインクルードしてください。 ちなみにこのexampleの中に入っているコントローラーならなんでも動きます。 一応自分がやったサンプルコードを載せておきます。

#include <Arduino.h>
#include <PS5BT.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so

/* You can create the instance of the PS5BT class in two ways */
// This will start an inquiry and then pair with the PS5 controller - you only have to do this once
// You will need to hold down the PS and Share button at the same time, the PS5 controller will then start to blink rapidly indicating that it is in pairing mode
PS5BT PS5(&Btd, PAIR);

// After that you can simply create the instance like so and then press the PS button on the device
//PS5BT PS5(&Btd);

bool printAngle = false, printTouch = false;
uint16_t lastMessageCounter = -1;
uint8_t player_led_mask = 0;
bool microphone_led = false;
uint32_t ps_timer;

void setup() {
  Serial.begin(115200);
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); // Halt
  }
  Serial.print(F("\r\nPS5 Bluetooth Library Started"));
}

void loop() {
  Usb.Task();

  if (PS5.connected() && lastMessageCounter != PS5.getMessageCounter()) {
    lastMessageCounter = PS5.getMessageCounter();

    if (PS5.getAnalogHat(LeftHatX) > 137 || PS5.getAnalogHat(LeftHatX) < 117 || PS5.getAnalogHat(LeftHatY) > 137 || PS5.getAnalogHat(LeftHatY) < 117 || PS5.getAnalogHat(RightHatX) > 137 || PS5.getAnalogHat(RightHatX) < 117 || PS5.getAnalogHat(RightHatY) > 137 || PS5.getAnalogHat(RightHatY) < 117) {
      Serial.print(F("\r\nLeftHatX: "));
      Serial.print(PS5.getAnalogHat(LeftHatX));
      Serial.print(F("\tLeftHatY: "));
      Serial.print(PS5.getAnalogHat(LeftHatY));
      Serial.print(F("\tRightHatX: "));
      Serial.print(PS5.getAnalogHat(RightHatX));
      Serial.print(F("\tRightHatY: "));
      Serial.print(PS5.getAnalogHat(RightHatY));
    }

    if (PS5.getAnalogButton(L2) || PS5.getAnalogButton(R2)) { // These are the only analog buttons on the PS5 controller
      Serial.print(F("\r\nL2: "));
      Serial.print(PS5.getAnalogButton(L2));
      Serial.print(F("\tR2: "));
      Serial.print(PS5.getAnalogButton(R2));
    }

    // Set the left trigger to resist at the right trigger's level
    static uint8_t oldR2Value = 0xFF;
    if (PS5.getAnalogButton(R2) != oldR2Value) {
      oldR2Value = PS5.getAnalogButton(R2);
      PS5.leftTrigger.setTriggerForce(oldR2Value, 255);
    }

    // Hold the PS button for 1 second to disconnect the controller
    // This prevents the controller from disconnecting when it is reconnected,
    // as the PS button is sent when it reconnects
    if (PS5.getButtonPress(PS)) {
      if (millis() - ps_timer > 1000)
        PS5.disconnect();
    } else
      ps_timer = millis();

    if (PS5.getButtonClick(PS))
      Serial.print(F("\r\nPS"));
    if (PS5.getButtonClick(TRIANGLE)) {
      Serial.print(F("\r\nTriangle"));
      PS5.setRumbleOn(RumbleLow);
    }
    if (PS5.getButtonClick(CIRCLE)) {
      Serial.print(F("\r\nCircle"));
      PS5.setRumbleOn(RumbleHigh);
    }
    if (PS5.getButtonClick(CROSS)) {
      Serial.print(F("\r\nCross"));

      // Set the player LEDs
      player_led_mask = (player_led_mask << 1) | 1;
      if (player_led_mask > 0x1F)
        player_led_mask = 0;
      PS5.setPlayerLed(player_led_mask); // The bottom 5 bits set player LEDs
    }
    if (PS5.getButtonClick(SQUARE)) {
      Serial.print(F("\r\nSquare"));
      PS5.setRumbleOff();
    }

    if (PS5.getButtonClick(UP)) {
      Serial.print(F("\r\nUp"));
      PS5.setLed(Red);
    } if (PS5.getButtonClick(RIGHT)) {
      Serial.print(F("\r\nRight"));
      PS5.setLed(Blue);
    } if (PS5.getButtonClick(DOWN)) {
      Serial.print(F("\r\nDown"));
      PS5.setLed(Yellow);
    } if (PS5.getButtonClick(LEFT)) {
      Serial.print(F("\r\nLeft"));
      PS5.setLed(Green);
    }

    if (PS5.getButtonClick(L1))
      Serial.print(F("\r\nL1"));
    if (PS5.getButtonClick(L3))
      Serial.print(F("\r\nL3"));
    if (PS5.getButtonClick(R1))
      Serial.print(F("\r\nR1"));
    if (PS5.getButtonClick(R3))
      Serial.print(F("\r\nR3"));

    if (PS5.getButtonClick(CREATE))
      Serial.print(F("\r\nCreate"));
    if (PS5.getButtonClick(OPTIONS)) {
      Serial.print(F("\r\nOptions"));
      printAngle = !printAngle;
    }
    if (PS5.getButtonClick(TOUCHPAD)) {
      Serial.print(F("\r\nTouchpad"));
      printTouch = !printTouch;
    }
    if (PS5.getButtonClick(MICROPHONE)) {
      Serial.print(F("\r\nMicrophone"));
      microphone_led = !microphone_led;
      PS5.setMicLed(microphone_led);
    }

    if (printAngle) { // Print angle calculated using the accelerometer only
      Serial.print(F("\r\nPitch: "));
      Serial.print(PS5.getAngle(Pitch));
      Serial.print(F("\tRoll: "));
      Serial.print(PS5.getAngle(Roll));
    }

    if (printTouch) { // Print the x, y coordinates of the touchpad
      if (PS5.isTouching(0) || PS5.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad
        Serial.print(F("\r\n"));
      for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers
        if (PS5.isTouching(i)) { // Print the position of the finger if it is touching the touchpad
          Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": "));
          Serial.print(PS5.getX(i));
          Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": "));
          Serial.print(PS5.getY(i));
          Serial.print(F("\t"));
        }
      }
    }
  }
}

4.書き込む

下のメニューにプログラムのビルドとアップロードボタンがあるので順番にポチポチ押してください。何かしらトラブルがあると進みません。

画像1.png (1.6 MB)

赤いマルで括った通りにsuccessと表示されればプログラムは書き込めました。ちなみにplatform ioの機能でポートをauto detectがあるのでいちいちポート選択しなくても大丈夫です。(この機能めっちゃ好き♡) アップロードの隣のボタンにあるシリアルモニタを押してください。

画像2.png (2.1 MB)

USB host shield基板とArduinoBluetooth ドングルはこんな感じでつなげておいてください。

IMG_6832.jpg (3.0 MB)

シリアルモニタを起動するとこのような画面が出て、ドングルのデータをArduinoが読みとってくれました。

画像3.png (2.4 MB)

あとはコントローラを起動させます。dual shock 5は赤丸の部分(「PSボタン」「SHAREボタン」)を同時に押して繋がるまで待つと勝手に接続されます。(dual shock4も同じ接続方法です。)

画像5.png (3.6 MB)

こんな感じで動いてくれたら成功です!

世の中で流通しているコントローラでロボット動かせたりすると結構テンションあがりますよね笑 ちなみに何年か前にこのUSB Host Shield 2.0ライブラリとwiiのバランスボードを使って重心移動で操縦できるロボット作りました。結構おもしろいですよね笑

参考サイト

ht-deko.com

MyCobotをROSで動かす

f:id:robohase01:20220207192514p:plain

はじめに

高専の卒業研究でMyCobot280を使っていていましたが、最初にROSで動かすまで時間がかかってしまったので、自分がやったROSでの動かし方を紹介します。

環境

  • Ubuntu 18.04
  • ROS Melodic Morenia
  • MyCobot280
  • windows10(ファームウェア更新時のみ)
  • MyCobot280

    1.ファームウェアの更新

    MyCobotはm5stack coreとATOM Matrixの2つのマイコンが使われています。工場出荷時にはm5stack coreにmainControlATOM MatrixにatomMainと呼ばれるファームウェアがインストールされており、ティーチング動作を行うことができます。しかしこのファームウェアのままだとROSで動かすことができません。詳しいファームウェアの種類は公式ページのSoftware Platform & APIのところに対応表が載っています。GitHubにある「myCobot固件烧录器」を使ってファームウェアを更新しましょう。ファームウェアの更新にはwindows10を使用します。(MacOSubuntuの環境でも大丈夫です。たまたまwindows10の方が都合が良かったので使っています。)現在公式ではMyStudioと呼ばれる最新のファームウェアの更新ソフトを推奨されていますが、何故か僕の環境だとMyStudioがうまく使えなかったので、「myCobot固件烧录器」を使用しました。GitHubから「myCobot固件烧录器」をダウンロードします。クリックして進むとmyCobot_windows_x64.zipがあるのでこれをダウンロードします。 github.com f:id:robohase01:20220207010420p:plain ダウンロードしている間にm5stack用のUSBドライバをダウンロードします。m5stackは少しUSBドライバー周りがややこしく、適切なドライバが入っていないとファームウェアを更新できません。 dev.classmethod.jp このサイトを参考にするとm5stack BasicはCP210x or CP2104 driverAtomにはFTDI driverが必要なのであることがわかります。それぞれを公式のページからダウンロードします。 docs.m5stack.com 公式のサイトを元にしてそれぞれのドライバをインストールしましょう。インストール方法がわからない時は「ドライバー名 windows10」のように調べれば出てきます。 インストールが終わったら、myCobot_windows_x64.zipを解凍して、myCobot固件烧录器を実行させてください。 その後m5stack coreにtransponderATOM Matrixにatom mainファームウェアを焼き付けてください。ここでPortに「No Port」と表示される場合はUSBドライバがうまく動いていません。

m5stack Basicに「Transponder」をburn f:id:robohase01:20220207010926p:plain

m5Atomに「AtomMain」をburn f:id:robohase01:20220207010954p:plain ここまで出来たら準備完了です。

2.ROSで動かす

ここからはubuntu機を使ってROSで動かします。 ROSのインストールができていない方はこちらを参考にしてみてください。 qiita.com まずはMyCobotのPythonAPIライブラリをインストールします。

$ pip install pymycobot --upgrade

catkin_wsのsrcフォルダにelephantrobotics公式のパッケージをインストールします。

$ cd ~/catkin_ws/src
$ git clone https://github.com/elephantrobotics/myCobotROS.git
$ catkin build
$ source ~/catkin_ws/devel/setup.bash

その後m5stack BasicとPCを接続して以下を実行します。

$ sudo chmod 666 /dev/ttyUSB0
$ rosrun mycobot_280 slider_control.py

ttyUSB0はUSBを差し戻したりすると名前が変わるので、TABキーの補完機能を使って直してください。 公式のサイトやgithubではパッケージ名の表記がmycobot_rosとなっていることが多いですが、自分が使っているmycobotの型番を入れてください。 今回の場合はmycobot_280です。 別タブでlaunchファイルを実行してください。

$ roslaunch mycobot_280 slider_control.launch

そうするとGUIのスライダーを用いて各ジョイントを動かせるようになります。

myCobotROSのパッケージの中にいろんなROSの実行ファイルがあるのでいろいろ実行してみると面白いです!

小ネタ

記事の一番最初にある動画はMyCobotのPythonAPIを使って逆運動学的動作をしている様子です。get_coords()で現在のロボット手先先端位置の座標を取得し、その後send_coords(coords, speed, mode)を実行すると先ほど取得した座標系の差分だけ動いてくれます。詳しいPythonAPIの情報は以下のサイトが参考になります。それでは! note.com

参考

docs.elephantrobotics.com

qiita.com