myCobotをM5StickCで操作してみた
前回ではMQTTを使ってmyCobotを動かせるようにしました。
これによりMQTTに対応した他のデバイス、アプリケーションとロボットが連携するようになります。
その例として今回は、M5StickCをAWS IoTに接続してmyCobotを操作してみたいと思います。
先に動かしているところ
前回軽く紹介しているので今回作ったもののデモ動画をのせておきます。
地味ですが、M5StickC内臓のIMUの傾きに応じてmyCobotが横方向に角度を変えるようになります。(縦方向はバランスを崩してすぐ倒れるので、イベント用には使わないようにしました。)
用意するもの
- myCobot Pi 280(OS: Ubuntu 20.04, ROS: Noetic)
- M5StickC(現在は販売終了しているのでこの記事の内容を試したくて購入する場合は上位互換のStickC Plusを選ぶといいです)
AWS IoT Coreの設定
以下のドキュメントを参考にAWS IoTにmyCobotとM5Stackをそれぞれモノとして登録して、証明書を作成します。
証明書を作成した後に以下のファイルをダウンロードしておきます。
- デバイス証明書
- パブリックキーファイル(不要ですが、ダウンロードしないと完了にできないのでダウンロードしておきます)
- プライベートキーファイル
- CA1のルートCA証明書(myCobotでmqtt_bridgeを使って接続するために必要です)
また、設定
タブからデバイスデータエンドポイントをメモしておきます。
M5StickCのプログラム
プログラムはUI Flowを使います。
プログラムの内容はM5StickCに内蔵されたIMUの傾きに合わせてmyCobotの姿勢をAWS IoT CoreにPublishするという内容です。
コピペ用のフローのソースはこちらです。以下の内容を .m5f
の拡張子にして保存します。
{"components":[{"id":"_stickscreen","createTime":1683177003904,"name":"screen","x":0,"y":0,"width":120,"height":240,"backgroundColor":"#111111","backgroundImage":"","size":0,"screenType":"default","type":"screen"},{"id":"=B#4DFLFx3yu^gZQ","createTime":1683178633880,"isCoreInk":false,"isPaper":false,"name":"title0","x":0,"y":0,"width":213,"height":13,"color":"#FFFFFF","backgroundColor":"#0000FF","text":"myCobot","textOffset":3,"font":"lcd.FONT_Default","screenType":"default","type":"title","layer":4},{"id":"dd&uaHXdwbsflFKm","createTime":1683178674806,"isCoreTwo":false,"isPaper":false,"name":"xaxis","x":0,"y":48,"color":"#FFFFFF","text":"0","font":"lcd.FONT_Default","rotation":0,"screenType":"default","type":"label","layer":7},{"id":"A$n2TaRx%6WO`^9e","createTime":1683178695491,"isCoreTwo":false,"isPaper":false,"name":"yaxis","x":0,"y":93,"color":"#FFFFFF","text":"0","font":"lcd.FONT_Default","rotation":0,"screenType":"default","type":"label","layer":9}],"type":"stick-C","versions":"Beta","units":[],"hats":[],"stamps":[],"blockly":"<block type=\"basic_on_setup\" id=\"setup_block\" deletable=\"false\" x=\"50\" y=\"50\"><next><block type=\"aws_init\" id=\"^VbQfe4kvqJ|yLp^7LRh\"><mutation key=\"m5pem.key\" cert=\"m5.pem.crt\"></mutation><value name=\"things_name\"><shadow type=\"text\" id=\";@MwvTbz;-C{ksp:YiE3\"><field name=\"TEXT\">m5stickC</field></shadow></value><value name=\"host\"><shadow type=\"text\" id=\"w{@;kPK5@m{2:d9_^nFF\"><field name=\"TEXT\">sample.iot.ap-northeast-1.amazonaws.com</field></shadow></value><value name=\"port\"><shadow type=\"math_number\" id=\"`RTS{?!07YG-;JwE71gf\"><field name=\"NUM\">8883</field></shadow></value><value name=\"keepalive\"><shadow type=\"math_number\" id=\"(-?Mc`mYf~r%O:DT4U~x\"><field name=\"NUM\">600</field></shadow></value><next><block type=\"aws_start\" id=\"_|$.Y[E9(_Ky1VJaA.ax\"><next><block type=\"controls_whileUntil\" id=\"s7g^!dX)1RG72HP(Sxwq\"><field name=\"MODE\">WHILE</field><value name=\"BOOL\"><block type=\"logic_boolean\" id=\"wNUbV5YW*qOI16)YtBqS\"><field name=\"BOOL\">TRUE</field></block></value><statement name=\"DO\"><block type=\"label_set_text\" id=\"Bejlik`XSY@y8?5zkfYm\"><field name=\"COMPONENT\">xaxis</field><value name=\"TEXT\"><shadow type=\"text\" id=\"qLRSU-!p}+8vV^Q)6qdJ\"><field name=\"TEXT\">Hello M5</field></shadow><block type=\"IMU_GET_ACC_X\" id=\"uZ?4ViFV}0/DsiM[K[uT\"></block></value><next><block type=\"label_set_text\" id=\"bjJ8P,*t3dgFB(j[2a[r\"><field name=\"COMPONENT\">yaxis</field><value name=\"TEXT\"><shadow type=\"text\" id=\"@M?1ai*9^P4v6eFCMy4v\"><field name=\"TEXT\">Hello M5</field></shadow><block type=\"IMU_GET_ACC_Y\" id=\"PK.!De__xnp3Sf=44w$`\"></block></value><next><block type=\"aws_publish\" id=\"Epj-C@@lAL=@^vFWySC8\"><value name=\"FROM\"><shadow type=\"text\" id=\"`BJ=`}NQV`rz4wRfeEtl\"><field name=\"TEXT\">/pose</field></shadow></value><value name=\"MSG\"><shadow type=\"text\" id=\"?g0#@M-@JiPFByojRcn^\"><field name=\"TEXT\"></field></shadow><block type=\"dumps_json\" id=\"^}|Z((rvX@U?sdnZ=84%\"><value name=\"JSON_VAR\"><block type=\"map_on_loop\" id=\"O]XaG;n$CkYu6k;t^PJT\"><statement name=\"LOOP\"><block type=\"create_map_key\" id=\"Rr[hpZ,n;aK2j++vR@cO\"><value name=\"key\"><block type=\"text\" id=\"GXKDFobC{@Ya_K{2E!C@\"><field name=\"TEXT\">name</field></block></value><value name=\"value\"><block type=\"lists_create_with\" id=\"mdAbS-Z#(}Bx9o]7yaK2\"><mutation items=\"6\"></mutation><value name=\"ADD0\"><block type=\"text\" id=\"H|0GV+@2NTK7t.`^r3Rf\"><field name=\"TEXT\">joint2_to_joint1</field></block></value><value name=\"ADD1\"><block type=\"text\" id=\"L@W@xLL^5R?HZ?~/F^u`\"><field name=\"TEXT\">joint3_to_joint2</field></block></value><value name=\"ADD2\"><block type=\"text\" id=\"A^%CAB/YF6^I!_rLuCLp\"><field name=\"TEXT\">joint4_to_joint3</field></block></value><value name=\"ADD3\"><block type=\"text\" id=\"yFVTO*9,+)C*vs/-rk6Q\"><field name=\"TEXT\">joint5_to_joint4</field></block></value><value name=\"ADD4\"><block type=\"text\" id=\"DbN8:qcWO}s@$iD2+y,E\"><field name=\"TEXT\">joint6_to_joint5</field></block></value><value name=\"ADD5\"><block type=\"text\" id=\"N#;cP4*yI*A.GBEA|J7e\"><field name=\"TEXT\">joint6output_to_joint6</field></block></value></block></value><next><block type=\"create_map_key\" id=\"G`DE{yRt0au,RPtk-aeW\"><value name=\"key\"><block type=\"text\" id=\"kiN?tTSl#f)XK04T{#T,\"><field name=\"TEXT\">position</field></block></value><value name=\"value\"><block type=\"lists_create_with\" id=\"Vj~P8ac-y7u@zgo(Xw[y\"><mutation items=\"6\"></mutation><value name=\"ADD0\"><block type=\"IMU_GET_ACC_X\" id=\"`7}jMS)ptXQI/@:u#hAE\"></block></value><value name=\"ADD1\"><block type=\"math_number\" id=\"gnCTZ9xjT?x5V{Ts4kv`\"><field name=\"NUM\">0</field></block></value><value name=\"ADD2\"><block type=\"math_number\" id=\"h4vRJYWpukzM{sp`R7la\"><field name=\"NUM\">0</field></block></value><value name=\"ADD3\"><block type=\"math_number\" id=\"^q_Zg{2,-CrvK?6i%}ju\"><field name=\"NUM\">0</field></block></value><value name=\"ADD4\"><block type=\"math_number\" id=\"8a~wKR$!16.03EDR-~h^\"><field name=\"NUM\">0</field></block></value><value name=\"ADD5\"><block type=\"math_number\" id=\"qHuk#I?}q@[68-s5J?9#\"><field name=\"NUM\">0</field></block></value></block></value></block></next></block></statement></block></value></block></value><next><block type=\"timer_delay\" id=\"yxK217|2+a!%Gqh_:8}C\"><value name=\"DELAY\"><shadow type=\"math_number\" id=\"xP-yvo[L.7678Vc]:lgL\"><field name=\"NUM\">5</field></shadow></value></block></next></block></next></block></next></block></statement></block></next></block></next></block></next></block>","Blockly.Remotes":[],"Blockly.RemotePlus":[{"id":"__title","blockId":"","createTime":1683394114907,"name":"M5RemoteTitle","dragAndDrop":false,"resizable":false,"options":{"minWidth":1,"minHeight":1,"maxWidth":6,"maxHeight":10,"defaultWidth":2,"defaultHeight":1},"w":2,"h":1,"bgColor":"#0080FF","color":"#fff","fontsize":"M","label":"M5Remote","interval":3000,"code":"","event":"","dataSource":"none","ezdataToken":"","topic":"","needShadow":false,"type":"title","x":0,"y":0}],"modules":["imu"],"cbIdList_":[],"eventCBIdList_":[],"apikey":"76E775E4","uuid":"c9ba80ee-805a-4882-9dc2-88e45f44e11e"}
AWSに接続するために以下の設定を行います。
-
Init things name
: モノを登録するときに設定したモノの名前 -
host
: AWS IoTの設定画面で確認したデバイスデータエンドポイント - 証明書ファイル、キーファイルをファイルアップロードアイコンからそれぞれアップロードして
keyFile
とcertFile
でそれぞれ該当するファイルを選択しておきます
myCobot側の設定
そして、設定ファイル~/catkin_ws/src/mqtt_bridge/config/mycobot_config.yaml
の中身を以下の通り書き換えます。
mqtt:
client:
protocol: 4 # MQTTv311
connection:
host: 【デバイスデータエンドポイント】
port: 8883 # ←ポートを8883に設定
keepalive: 60
serializer: json:dumps
deserializer: json:loads
bridge:
# pose joint_state
- factory: mqtt_bridge.bridge:RosToMqttBridge
msg_type: sensor_msgs.msg:JointState
topic_from: /joint_states
topic_to: pose
- factory: mqtt_bridge.bridge:MqttToRosBridge
msg_type: sensor_msgs.msg:JointState
topic_from: ~/pose
topic_to: /joint_states
AWS IoTで生成したmyCobot用のキーファイル、証明書ファイルをmyCobot内蔵のRaspberry Piの任意のファイルに保存します。
さらにそれらの証明書ファイルを読み込むための追加の設定として ~/catkin_ws/src/mqtt_bridge/config/tls_params.yaml
を以下の内容に書き換えます。
tls:
ca_certs: 【CA証明書のファイルパス】
certfile: 【デバイス証明書のファイルパス】
keyfile: 【プライベートキーのファイルパス】
tls_insecure: true
動かしてみる
それでは実際に動かしてみます。
myCobotのRaspberry Piのターミナルで以下のコマンドを実行してmqtt_bridgeのノードを起動します(前回作成したmycobot.launchを使用します)
MQTT connected
が表示されれば、AWS IoTに正常に接続されています。もし、MQTT disconnected
が先に表示されて MQTT connected
となっている場合は、接続に失敗しているので、一度ノードを止めて再度立ち上げる必要があります。
roslaunch mqtt_bridge mycobot.launch use_tls:=true
別ターミナルで実機を動かすためのノードを起動します。
rosrun mycobot_280 slider_control.py _port:=/dev/ttyAMA0 _baud:=1000000
M5StickC側はUI Flowにファームウェアを書き込むかブラウザ上で実行させると、M5StickCの傾きに合わせてmyCobotの角度が変わるようになります。(縦方向は入れてませんが、y軸方向の値もアームの姿勢情報を送信するときに入れてあげることで、アームの姿勢を自由に設定できるようになります)
Discussion