2021年の振り返り
1月
Anycubic Mega Proの運用を開始
セールで買ったAnycubic Mega Proをサブ機として運用を開始。かなり組み立ても簡単で音も小さめで良い。 pic.twitter.com/Eq7lxouKtr
— higrademe (@EL2031watson) 2021年1月1日
第四級アマチュア無線技士試験合格
第一級アマチュア無線技士試験も受けるので、免許の申請は保留。(12月に結局申請)
2月
myCobotのグリッパーを入手
myCobotのグリッパーが届いた。 pic.twitter.com/rOkgOlqfHX
— higrademe (@EL2031watson) 2021年2月12日
3月
RealSense F455とD415を入手。
F455も届いたがこの間安かったからついでに買ったD415も届いた。やっぱF455かなり小さいな。 pic.twitter.com/jeo03jLl2V
— higrademe (@EL2031watson) 2021年3月13日
第一級陸上特殊無線技士試験に合格し、免許証を入手。
第一級陸上特殊無線技士試験に合格して無事に免許証を取得。
— higrademe (@EL2031watson) 2021年3月31日
第二種電気工事士に続き自分の方向性が意味不明になってきたが、持ってると技適の例外申請とかドローン系の仕事に使えるとかメリットもあるのと、そもそも無線の勉強も色々面白かった。 pic.twitter.com/Q8ykXh8jPM
4月
第一級アマチュア無線技士試験不合格。
法規パートが及ばなかった。モールス信号を始めて学び、古いが自分の中では新鮮さを感じた。
週末に第一級アマチュア無線試験受けたので自己採点した。無線工学は合格ライン超えたが、法規で1問分及ばず不合格の公算大。
— higrademe (@EL2031watson) 2021年4月13日
電波法に違反した場合の罰金額が30万円か50万円か等を真面目に暗記しなかったところが敗因。
でも勉強の結果モールス信号が少し分かるようになったので収穫はあった。
KickstarterでBackしていたPetoi Bittleを組み立てた。
Petoi Bittleの組み立てが何とか終わり、動かしてみた。赤外線リモコンで簡単な事前に入ってる動作をさせられる。Steppingというのを押したら予想してた以上に激しく動いた。なんか間違ってる気もするが他は良さそう。 pic.twitter.com/8Hc8hIYBEZ
— higrademe (@EL2031watson) 2021年4月14日
5月
UnityとROSでカメラ画像から深層学習でつかむ対象の姿勢を予測してPick and Placeを行うチュートリアルを試す。
Unity公式のROSでpick and placeするチュートリアル終了。
— higrademe (@EL2031watson) 2021年5月7日
位置・姿勢・光源などをランダム化して得た30000枚の単眼カメラの画像を使って深層学習モデルを作成しCubeの位置・姿勢を推定。推定結果をMoveItに飛ばして、Goalまで運ぶ軌道を生成するというもの。たまに失敗するが、単眼にしてはなかなか。 pic.twitter.com/cBRbe6mLRR
KickstarterでbackしていたLooking Glass Portraitを入手
Looking Glass初代も買ってる人にとってはfirstじゃなくてsecondなのかなw pic.twitter.com/UwqAdiHUzx
— higrademe (@EL2031watson) 2021年5月12日
6月
Unitree Go1が気になったが、予算の問題で購入できず。
Unitree Go1 公式サイト見た感じ頭部4か所、腹部に前後それぞれ2か所、左右にそれぞれ4か所カメラか何かのセンサーらしきものが搭載されている。結構多いな。$2700がセンサー込みの値段ではない気はするが、センサー抜きでも前買った犬ロボと同サイズ同価格でかなり安い。https://t.co/p3V9GUn5f5 https://t.co/Q8rCKFTvbd
— higrademe (@EL2031watson) 2021年6月8日
7月
Maker Faire Tokyo 2021の出展が不可という連絡を受け取る。
来年再挑戦する予定。
Maker Faire Tokyo 2021今年は出展叶わず。今年は有料化したのに変わらず出展希望者多いのか。
— higrademe (@EL2031watson) 2021年7月13日
また来年。
xArm用のSuction Cupを入手
xArm用のSuction Cupがちょうど届いた。吸着カップ3種類を選べて、最大5個まで付けられるようだ。
— higrademe (@EL2031watson) 2021年7月19日
ということで、久々にxArmを部屋に設置。 pic.twitter.com/sQS10XNwQr
ROS 2の本を揃え、勉強をする決意をする。
取り敢えずROS 2の本5冊を揃えた。
— higrademe (@EL2031watson) 2021年7月23日
まだ1冊終わって2冊目始めたところだが…
現段階だと先にROS1やった方がいい気もしてきた。
そしてScamperは多分TurtleBot3よりも高いのだろう…
ROS 2でできるかはさておき、現状アームロボは結局myCobotが一番入門機として安いのかな。 pic.twitter.com/BY6S2DreHN
8月
Kickstarterでbackして入手したxArm 5 をアップデートしてxArm 6にした。
xArm 6をゲット。xArm 5からアップデートした。
— higrademe (@EL2031watson) 2021年8月24日
ということで新しく動くようになった軸を回してみた。 pic.twitter.com/urDRjJo0I3
休日会員だったDMM.make AKIBAが8月で終了ということで最後の加工を行った。
DMM.make AKIBA 休日会員だったので、実質最終日となる日曜に行ってきた。
— higrademe (@EL2031watson) 2021年8月31日
アルミ板が70%オフだったので買い込み、xArmのカメラ取り付け部品無くしたので作った。
ボール盤とバンドソーとCNCフライスが使えなくなるのはきつい。ボール盤は買う予定。バンドソーはうるさいからきつい。CNCはそのうち。 pic.twitter.com/vo7Uqrquzo
9月
OAK-D-LiteをKickstarterでback
OpenCV AI Kit - Liteとりあえず安いから2つバックしたが、もう一つくらいあってもいいかなと思って変更しようとしたらもうSuper Early Birdは無くなっていた。なかなかの人気だ。
— higrademe (@EL2031watson) 2021年9月15日
ROS 2の入門として「ScamperとRaspberry Piで学ぶROS 2プログラミング入門」を読んだ。
ScamperとRaspberry Piで学ぶROS 2プログラミング入門をなんとか終えた。
— higrademe (@EL2031watson) 2021年9月23日
C++でROS 2の基礎が学べるのと、OpenCV使ってwebカメラの画像をpublish,subscribeして処理を加えるところまでが全てC++で書かれてるのが特に良かった。しかしOpenCVをC++で使いこなすのはPythonに比べるとなかなか大変そうだ。 pic.twitter.com/ervMbcSyMC
Mini PupperをKickstarterでback
出遅れましたが、念のためMini Pupperをbackしました。
— higrademe (@EL2031watson) 2021年9月30日
10月
ROS 2(Foxy)でカルタ取りロボットシステムを作る最初のステップとして、RealSense D435の画像、深度からカルタの位置推定・札認識を実装した。
ROS 2とC++の勉強として、RealSenseのRGB画像からカード認識、深度を使い位置・向きを計算してRVizで可視化した。カードを傾けるとカード面の法線が追従してくれる。
— higrademe (@EL2031watson) 2021年10月17日
法線からQuaternionの計算は自前で作ったが、なんかライブラリ化されていないのかな。まあクオータニオンの勉強にはなったけど。 pic.twitter.com/tuOuqxVWs7
UFACTORY Lite 6をKickstarterでback
UFACTORY Lite 6を無事Kickstarterでバック。
— higrademe (@EL2031watson) 2021年10月26日
以前バックした7DoFの方は来てないが、UFACTORYならほぼ間違えなく届くだろうし、安いから取り敢えずバックした。
11月
百人一首カルタ取りロボの音声認識部分もシステムに接続し、「読み上げ音声を認識→該当の札を取る」を自動でできるようになった。
百人一首の読み上げ音声を認識して、並べた札を画像認識で識別してロボットが該当するものを取るところまでできた。
— higrademe (@EL2031watson) 2021年11月19日
これでロボットと人の対戦ができる。一部は上の句読み上げ中に動くから多分私より強い。なお対戦時の安全性は… pic.twitter.com/2uGqxaloBi
12月
ZED Miniを入手
StereolabsのZED Miniを入手。今使っているRealSense D435と比較したいと思い。
— higrademe (@EL2031watson) 2021年12月1日
基本VRヘッドセットにつけることを想定して作られてるようだけど、小さいからアームに付けるのも良さそう。レンズ間の中心が本体中心とずれてるからxArmに取り付けるためのマウントもずらして作らないといけないのかも。 pic.twitter.com/dH3z9Fx8IZ
クオータニオン学習用のおもちゃを試作したがいまいちだった。
クオータニオンの回転を感覚的に試したいと思い任意の軸周りに物体(写真では座標軸)を回転させる物を作ったが微妙だった。空間の干渉を回避しないといけないのがつらい。
— higrademe (@EL2031watson) 2021年12月17日
こういうのはXRで作った方がよさそう。
ちなみにxyz座標の原点をボールジョイントの中心にオフセットしたから座標も変な形。 pic.twitter.com/EOv4o80Kl6
ロボセミで「百人一首カルタ取りロボでROS 2に入門」のタイトルで発表
先ほどロボセミで発表した「百人一首カルタ取りロボでROS 2に入門」のスライドを公開しました。https://t.co/rMQlfPrdmT#robosemi
— higrademe (@EL2031watson) 2021年12月17日
OAK-D-Liteが届く
無事OAK-D-Liteが到着。本体は言うまでもなくパッケージもRealSenseと比べて思ったよりかなり小さく驚いた。まあ本体以外も入ってる箱と比べてもしょうがないかもしれないが。 pic.twitter.com/wGPV0MYVYW
— higrademe (@EL2031watson) 2021年12月29日
総括
- 相変わらずガジェットにつぎ込んだ。特にKickstarter経由の比率が高かった。
- 第一級アマチュア無線技士試験は不合格だったが、陸上特殊無線技士試験に合格して技適の例外申請などで役に立ちそうな期待をもった。
- ROS 2の学習を始め、百人一首カルタ取りロボットシステムを試しに作ってみてROS 2への理解が深まった。
ROS 2 FoxyでRealSense D435の画像をsubscribeする(QoSの設定とPython、C++実装)
RealSenseをROS 2で利用するときに、少しつまずきがあったので、こちらに記録用にまとめておきます。
具体的には以下のrealsense-rosパッケージを使い、realsenseから得られるRGB画像及びDepth画像をImageトピックとしてpublishしたものを、自分でsubscribeするプログラムを 作成しましたが、ROS 2ではQoS(Quality of Service)の設定を適切にしないと画像がうまくsubscribeできないということを知りました。 重要なのはreliability settingをbest_effortに変更することなのですが、これを含めたrealsense画像をsubscribeするシンプルなプログラムをサンプルとして紹介します。
私の場合、普段はPythonを中心に使っていますが、画像などの重ためのデータを扱う際にノード間のデータのやり取りをプロセス内通信にして余計なメモリへのコピーをなくし、パフォーマンス低下を防げるcomponentの利用は現状C++が必須のようなのと、その他のパッケージでもサンプルがC++で記述されているものもありそうなので、念の為PythonとC++の両方の実装を行いました。 なおパッケージ名や関数名などはできるだけ両言語で同じようになるようにしましたが、両言語のパッケージをそれぞれ試される場合は重複を避けるためパッケージ名を変更してください。
Componentに興味のある方はこちらを参考にしてください。 docs.ros.org
事前に以下のサイトの手順に従ってrealsense-rosパッケージをビルドしてください。
また今回つまずきのポイントになったQoSに関する説明はこちらにあります。やり取りすデータに欠損などが発生した際のデータの扱いに関するルールを事前に定義しておける機能と理解しましたが、今回はその中のReliabilityPolicyというものがRELIABLEになっていると、RealSenseの画像データがsubscribeされないという問題が発生したので設定を変更してBEST_EFFORTにしています。
Python実装
パッケージを作成し、image_subscriber.pyを作成する。
$ cd ~/ros2_ws/src $ ros2 pkg create --build-type ament_python realsense_subscriber $ touch ~/ros2_ws/src/realsense_subscriber/src/realsense_subscriber/image_subscriber.py
image_subscriber.py
import rclpy from rclpy.node import Node from sensor_msgs.msg import Image from cv_bridge import CvBridge import cv2 class RealSenseSubscriber(Node): def __init__(self): super().__init__("realsense_subscriber_python") self.declare_parameter('image_topic_name', '/camera/color/image_raw') image_topic_name = self.get_parameter('image_topic_name').get_parameter_value().string_value video_qos = rclpy.qos.QoSProfile(depth=10) video_qos.reliability = rclpy.qos.QoSReliabilityPolicy.BEST_EFFORT self.sub_img = self.create_subscription( Image, image_topic_name, self.on_image_subscribed, video_qos ) self.sub_img def on_image_subscribed(self, img): img_np = CvBridge().imgmsg_to_cv2(img) img_np = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB) cv2.imshow("Image", img_np) cv2.waitKey(1) def main(args=None): try: rclpy.init(args=args) rclpy.spin(RealSenseSubscriber()) except KeyboardInterrupt: pass rclpy.shutdown() if __name__ == "__main__": main()
setup.pyを編集し、entry_pointsにrealsense_subscriberを追記する。
from setuptools import setup package_name = 'realsense_subscriber' setup( name=package_name, version='0.0.0', packages=[package_name], data_files=[ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), ], install_requires=['setuptools'], zip_safe=True, maintainer='root', maintainer_email='root@todo.todo', description='TODO: Package description', license='TODO: License declaration', tests_require=['pytest'], entry_points={ 'console_scripts': [ "realsense_subscriber = realsense_subscriber.image_subscriber:main" ], }, )
package.xmlを編集し、rclpyとsensor_msgsを追記する。
<?xml version="1.0"?> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> <package format="3"> <name>realsense_subscriber</name> <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="root@todo.todo">root</maintainer> <license>TODO: License declaration</license> <test_depend>ament_copyright</test_depend> <test_depend>ament_flake8</test_depend> <test_depend>ament_pep257</test_depend> <test_depend>python3-pytest</test_depend> <export> <build_type>ament_python</build_type> <exec_depend>rclpy</exec_depend> <exec_depend>sensor_msgs</exec_depend> </export> </package>
C++実装
パッケージを作成し、image_subscriber.cppを作成する。
$ cd ~/ros2_ws/src $ ros2 pkg create --build-type ament_cmake realsense_subscriber $ touch ~/ros2_ws/src/realsense_subscriber/src/image_subscriber.cpp
image_subscriber.cpp
#include <rclcpp/rclcpp.hpp> #include <rclcpp/qos.hpp> #include <sensor_msgs/msg/image.hpp> #include <cv_bridge/cv_bridge.h> #include <opencv2/opencv.hpp> using sensor_msgs::msg::Image; class RealSenseSubscriber: public rclcpp::Node { public: RealSenseSubscriber(rclcpp::NodeOptions options = rclcpp::NodeOptions()); ~RealSenseSubscriber(){} private: void onImageSubscribed(Image::SharedPtr img); rclcpp::Subscription<Image>::SharedPtr sub_img; std::string image_topic_name; }; RealSenseSubscriber::RealSenseSubscriber(rclcpp::NodeOptions options) : Node("realsense_subscriber", options) { image_topic_name = this->declare_parameter<std::string>("image_topic_name", "/camera/color/image_raw"); rclcpp::QoS video_qos(10); video_qos.best_effort(); video_qos.durability_volatile(); sub_img = this->create_subscription<Image>(image_topic_name, video_qos, std::bind(&RealSenseSubscriber::onImageSubscribed, this, std::placeholders::_1)); } void RealSenseSubscriber::onImageSubscribed(Image::SharedPtr img) { auto cv_img = cv_bridge::toCvShare(img, img->encoding); cv::cvtColor(cv_img->image, cv_img->image, cv::COLOR_RGB2BGR); cv::imshow("Image", cv_img->image); cv::waitKey(1); } int main(int argc, char **argv) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<RealSenseSubscriber>()); rclcpp::shutdown(); return 0; }
CMakeList.txtの記述を追加する。
cmake_minimum_required(VERSION 3.5) project(realsense_subscriber) # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() set(ROS_LIBS rclcpp;cv_bridge;sensor_msgs) find_package(ament_cmake REQUIRED) foreach(lib IN LISTS ROS_LIBS) find_package(${lib} REQUIRED) endforeach() set(target image_subscriber) add_executable(${target} src/${target}.cpp) ament_target_dependencies(${target} rclcpp OpenCV cv_bridge sensor_msgs) install(TARGETS ${target} DESTINATION lib/${PROJECT_NAME}) ament_package()
package.xmlに依存ライブラリとして、rclcppとlibopencv-devを追加する。
<?xml version="1.0"?> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> <package format="3"> <name>realsense_subscriber</name> <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="root@todo.todo">root</maintainer> <license>TODO: License declaration</license> <buildtool_depend>ament_cmake</buildtool_depend> <depend>rclcpp</depend> <depend>libopencv-dev</depend> <test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_common</test_depend> <export> <build_type>ament_cmake</build_type> </export> </package>
PythonとC++共通
こちらをコンパイルする。
$ colcon build --symlink-install --packages-select realsense_subscriber $ source install/setup.bash
コンパイル後にまずrealsense-rosパッケージにあるrs_launch.pyを立ち上げます。
$ ros2 launch realsense2_camera rs_launch.py
その後、別のターミナルで作成したノードを実行します。
$ ros2 run realsense_subscriber image_subscriber
正しく実行できれば、ウィンドウが表示され、RealSenseから取得した画像が表示されます。(筆者環境ではDocker使用のため、表示にXephyrを使用していますが、マシンにROS 2を直接インストールしている場合はWindowが新規に表示されると思います)
なおsubscribeするトピック名をパラメータで定義しているので、ノード起動時に引数を指定することでDepth画像を表示したり、別のWebカメラの画像などをpublishするノードを立ててそのtopicを指定すれば、その画像を表示することも可能です。 参考にdepth画像をsubscribeする際の引数の設定がこちらになります。
$ ros2 run realsense_subscriber image_subscriber --ros-args -p image_topic_name:=/camera/depth/image_rect_raw
なおDepth画像のピクセル値はmmで計測された深度情報が入っているので、そのまま表示しても0~255の値の範囲しか通常の画像表示では行えないので、25.5mm程度の距離までしか適切に表示できません。ピクセル値をそれぞれ一定の値で割って(1000など)、0~255の範囲に計測範囲の距離が収まるようにするとわかりやすく画像を表示することができるようになります。
参考
- ScamperとRaspberry Piで学ぶROS2プログラミング入門(オーム社)
- ロボットプログラミングROS2の実装・実践(科学情報出版株式会社)
2020の振り返り
1月
RTX2080搭載のノートPC(PT515-51-A76Y8)を購入。外付けのNVMeSSD経由でUbuntuを起動する。
なかなか起動しなかったRTX2080搭載のノートUbuntu PCがついに起動。
— higrademe (@EL2031watson) 2020年1月23日
自分の自作PCみたいにWindows Ubuntuを同じSSDに入れてデュアルブートしてたらいつの間にかUbuntuが起動しなくなってしまってたので、今回はNVMeのSSDを外付けUSB-C化してそこに入れた。これならWindows Updateでも大丈夫? pic.twitter.com/dZe3aIujtz
2月
xArmにステーキを焼いてもらう芸を仕込む。
xArm芸その1:本物の肉をひっくり返してもらって裏面を焼く。
— higrademe (@EL2031watson) 2020年2月9日
投資額は国産牛390円。 pic.twitter.com/P9tvmjZYnf
xArm芸その2:焼けた肉をお皿に移動。
— higrademe (@EL2031watson) 2020年2月9日
最後が少し惜しかったが、なんとか皿には入ってるからよし。
なお肉の位置がさっきと違うじゃないかというクレームはなしで... pic.twitter.com/PW2k3Imge4
xArmでクッキング。なんか写真が気に入った pic.twitter.com/Z4sYJqnAlL
— higrademe (@EL2031watson) 2020年2月9日
ロボットに調理とかさせる展示等をすることを見越し、食品衛生責任者の講習を受け資格取得。
ロボットに調理とかさせ始めたので念の為、食品衛生責任者の資格を取得。飲食店に一人必要なやつ。6時間の講習で取れる。食中毒など勉強になった。 pic.twitter.com/9H15dASpmk
— higrademe (@EL2031watson) 2020年2月10日
Universal Robots UR3を入手。Maker Faireへの出展きっかけとなる
UR3でピックアンドプレイスが一応できた。
— higrademe (@EL2031watson) 2020年2月19日
下にキューブはめる溝作れば回すこともできるかも。 pic.twitter.com/K1c1de71lU
3月
2d lidarをいくつか買う。
Lidar用の取り外し可能なマウントを作った。取り外しできないと犬用バッグに入らなくなってしまうという前回の教訓を活かして。 pic.twitter.com/msoS3WD2ti
— higrademe (@EL2031watson) 2020年3月4日
2d lidarのA2M6でスキャンしながら某場所を歩き回ってみた結果(x,yの単位はmm)。
— higrademe (@EL2031watson) 2020年3月6日
動いていることがそれっぽくわかる。
そしてさすが所々10m以上のスキャンができている。 pic.twitter.com/y3RSX1e803
Spot Microに障害物回避歩行機能を実装。
単眼カメラから障害物回避するモデルをJetBotを参考に、組み込んでみた。
— higrademe (@EL2031watson) 2020年3月21日
毎周期ごとにカメラから取得した画像から深層学習モデルで障害物有無を判定、障害物ありならその場旋回で回避。モデルは本家に習いAlexNetを200枚ぐらいのアノテーションデータでチューニング。判定は良好だが、駆動に難あり。 pic.twitter.com/CszBxrmay3
Windows MRでUniversal Robotsを遠隔操作する。
Windows MRのコントローラー経由でロボットアームを遠隔操作。
— higrademe (@EL2031watson) 2020年3月22日
取り敢えず少し値をいじっただけだからか、遅延が結構ある。 pic.twitter.com/Sz1VfgKOQq
やはり本家に習い前面にD435をつけられるようにしようと思い、Noseパーツに穴を開ける。縦L字型TypeCケーブルとかでギリギリ収まるかというレベル。 pic.twitter.com/yPk4BxS3nW
— higrademe (@EL2031watson) 2020年3月28日
ちなみにロボットアームの遠隔操作は操作者からVRヘッドセットからみるとこんな感じ。アームが伸び切るあたりで特異点を通っているように思われるが、それ以外は角度を制限してだいぶ安定化させたつもり。最新版にはUSBカメラの映像を見えるようにしたが、画角等の問題で、結局あまり使えなかった。 pic.twitter.com/zkADbBzcdK
— higrademe (@EL2031watson) 2020年3月23日
Spot Microの頭にD435をつける。
d435のRGBと深度それぞれの垂直視野角を可視化して見た。足が伸びると240mmぐらいだったから、その想定。センサー部から373mm水平に離れた地点から深度センサーで地面が検出可能に。中心の水平方向に関しては、深度は200mm以上からで近場が検出できないので、障害物回避はRGBで対応するのが良いか。 pic.twitter.com/XXAlN2krIf
— higrademe (@EL2031watson) 2020年3月28日
D435取り付け用Noseが印刷できたのでつけた。
— higrademe (@EL2031watson) 2020年3月29日
D435が思った以上に目立って不気味な感じが増す。新型iPadみたいに視野角の異なるRGBカメラ2つに加えて深度カメラ(方式はどちらかというとフロントの深度カメラに近いと思うが)という構成になった。ぼかし入れた記念撮影が出来るに違いない。 pic.twitter.com/zo83m4ZCUG
4月
Jetson Xavier NXのModuleが届く。
Jetson Xavier NXが届いた!
— higrademe (@EL2031watson) 2020年4月22日
Jetson Nano(右)との比較。B01ならボードがNXと互換性あるとのことで、サイズは同じ。しかし放熱用のヒートシンクの固定穴位置が異なり、要調達だ。あとMicroSDポートないからm2スロットかUSBにストレージ確保しないといけなさそう。キャリアボード買った方がいいかも。 pic.twitter.com/9QryPXe8gr
5月
Jetson Xavier NX Developer Kitが届く。
Jetson Xavier NX2種類。
— higrademe (@EL2031watson) 2020年5月17日
Xavier NX Developer KitとXavier NX Moduleを載せたNanoのキャリアボード。ボードサイズは同じだが、背面にWiFiのアンテナを埋め込む分DeveloperKitは少し長い。MicroSDカードスロットあるのは非常に助かる。Module版とは違い、Ubuntuマシンなしでセットアップできる。 pic.twitter.com/3xkSgK6ZjG
6月
Realsense L515が届く。
RealSense L515 早速Viewerで確認。なかなか境界がきれい。壁も結構まっすぐ。 pic.twitter.com/tEhLssFrQd
— higrademe (@EL2031watson) 2020年6月14日
Spot Microをブラウザで操作できる用にvue.js+Flaskでコントローラーを簡易Webアプリケーションとして実装。
4足歩行ロボットのコントローラーをWebアプリとして実装し、スマホからJetson上に立てたwebサーバーにアクセスしてコントローラーを取得、操作に成功。肝心の歩行はバランスがおかしくてうまく行ってないが、操作がかなりやりやすくなった。 pic.twitter.com/HLr1wSzgZk
— higrademe (@EL2031watson) 2020年6月15日
驚異の1万円という低価格の二足歩行ロボットPLEN.Dを購入。
PLEN.Dにローラースケート装着。台に傾斜があるのもあるが滑ってる感があって面白い。 pic.twitter.com/wvM8LuaSC8
— higrademe (@EL2031watson) 2020年6月18日
7月
KickstarterでバックしていたxArmのGripperがついに届く。
KickstarterでバックしてたxArmのGripperがアーム本体到着から6ヶ月以上の時を経てついに到着。
— higrademe (@EL2031watson) 2020年7月31日
遅れたお詫びとしてRealSense D435もついてきた。D435が更に増えた... pic.twitter.com/EVOV4GSXOl
書籍「予算1万円でつくる二足歩行ロボット」の通りに二足歩行ロボットを作る。表面実装に初トライ。
二足歩行に成功!
— higrademe (@EL2031watson) 2020年7月18日
背中のバッテリーの重みがあるから少し前に倒した状態を基本姿勢にする必要があった。 pic.twitter.com/2lkgCeBKJY
8月
RealSense D455が届く。
やっとRealSense D455が届いた。結構大きい。
— higrademe (@EL2031watson) 2020年8月28日
ここ2年でRealSenseシリーズが結構増えた。 pic.twitter.com/8hI0Zh2bjP
Spot Microの改良版として自作四足歩行ロボットの足をカーボンで作る。
初めてのCNCフライスによるカーボンの切削。意外とアルミより素直に行けた。粉は最新の注意を払ったが。そしてやっぱ圧倒的に軽い。 pic.twitter.com/1RYhyBoORc
— higrademe (@EL2031watson) 2020年8月1日
自作4足歩行ロボットの太ももの部分をアルミからカーボンに変えて、20gぐらい減らせた。 pic.twitter.com/TNp4kWf5ev
— higrademe (@EL2031watson) 2020年8月2日
9月
dogotix-MIC-01Bを注文。
10月
MakerFaire出展、またその出展内容についてロボティクス勉強会で発表する。
Maker Faire Tokyo無事終わりました。沢山の方にブース見ていただき、ありがとうございます。
— higrademe (@EL2031watson) 2020年10月4日
チーム名もう少しひねったほうが良かった気もしますが名前の通りの展示に一応なったので、これで良かったかなと。 pic.twitter.com/QX3kGvgCiG
Maker Faire Tokyo 2020に自動卓球返球ロボットを出展します。先人が既に数多くいますが、特徴は人間と同じような目線の高さに設置したステレオカメラ、協働ロボットを使っていることです。
— higrademe (@EL2031watson) 2020年9月27日
共同出展者の@chang_ban と本日調整を行いだいぶラリーが続くようになりました。https://t.co/JLTmPT0dnh pic.twitter.com/VQ0xbV50hr
ソフトグリッパーに興味を持ち、3Dプリンターやシリコンゴムで制作する。
2つで挟むとこんな感じか。確かに形状に沿ってうまいこと変形している。 pic.twitter.com/2QXVoA7R6u
— higrademe (@EL2031watson) 2020年10月9日
ソフトロボティクスの例のグリッパー、TPUで直接印刷してたが、今度は型を作ってシリコンゴムを流し込んで作った。かなり柔らかくなって把持面の摩擦力もかなり上がった。ここらへんでそろそろロボットアーム先端につけてものつかめるかを実験してみたいところ。 pic.twitter.com/vChAQqXvox
— higrademe (@EL2031watson) 2020年10月16日
ソフトロボティクスのグリッバー。2つ合わせて紙コップを掴む実験。
— higrademe (@EL2031watson) 2020年10月19日
握りつぶさず掴めた。 pic.twitter.com/ScIrrfYhMR
Pico Flexxを購入して試す。
動画では分かりづらいが、取り敢えず近づいてデプス取れるかの検証。かなり近くまで寄れる。 pic.twitter.com/ivX9xcB2fO
— higrademe (@EL2031watson) 2020年10月16日
Nintedo Switchのマリオカート ライブ ホームサーキット のレースにJetRacerを妨害キャラとして投入し吹っ飛ばす。
NSXを被ったJetRacerを1年ぶりに蘇らせ、マリオカートに妨害キャラとして投入。車高的にゲートを潜れないので、ゲートを避けるように学習させ自動運転。本気で走ったらマリオたちを破壊する可能性あるので、スピードは合わせた。
— higrademe (@EL2031watson) 2020年10月25日
従来は紙コップで進路分かりやすくしていたが、無しでも走れた。 pic.twitter.com/qNFgYLncGe
11月
M8 Lidarを入手する。
世間ではlidar付きスマホが話題ですが、私は3d lidarを入手しました。DHCPサーバーをPCで立ち上げてIPをlidar側に配布しないといけないとか慣れない作業で手こずりましたがなんとか動くことを確認しました。 pic.twitter.com/VjROR4bh7P
— higrademe (@EL2031watson) 2020年11月1日
16Lineの3D Lidarがあきらめきれず、Velodyne Lidar VLP-16-HiResのジャンク品を修理して使用可能にする。
動作不可品として入手したVelodyne VLP-16-HiResを修理してなんと復活!
— higrademe (@EL2031watson) 2020年11月15日
電源周りが何故か切断された状態だったのでDCジャック調達して半田したら普通に起動した。 pic.twitter.com/nMZTcEj8rI
Velodyne Lidar VLP-16を入手する。
Velodyne Lidarで皆さんがよく使っていらっしゃるのはやっぱ垂直角20度のVLP-16-Hi-Resじゃなくて30度のVLP-16ということで、こちらも入手。というかHi-Resが動いたのが予想外だったから図らずもこうなった。
— higrademe (@EL2031watson) 2020年11月16日
なんかロゴ違うけど偽物?3D Lidarだから取りあえずは動けば良し。 pic.twitter.com/JVZ6Ojlc6h
ROSでVLP-16で取った自前スキャンデータを使って3次元のSLAMを試す。
DockerでROS入りUbuntuイメージを量産出来る様になったので、LeGO-LOAMだけでなくてhdl_graph_slam用イメージも作った。
— higrademe (@EL2031watson) 2020年11月24日
性能比較として某コワーキングスペース内をVelodyne VLP-16で取ったデータで比較。
IMU無し。何回か試したがこの地形だとhld_graph_slamが良い。IMUあるとLeGO-LOAMも良くなるか。 pic.twitter.com/o0Fs4erfQQ
12月
myCobotを入手。
myCobotを早速入手。思ったより小さくて軽い。バックに入れて持ち歩けるレベル。本体は848gで6自由度。8.4V-5AのDCで動くみたいなので移動体に乗っけて使うとかできそう。 pic.twitter.com/njTjuFxVQv
— higrademe (@EL2031watson) 2020年12月1日
何らかの先行事例にインスパイアされて、myCobotに茶せん持たせて抹茶をたててもらった。
— higrademe (@EL2031watson) 2020年12月12日
取りあえずかき混ぜはできるが、スピード不足が理由なのか、美味しく見えるとされる泡がほとんど立たなかった。 pic.twitter.com/dAxDgNfkUZ
犬型ロボット dogotix-MIC-01Bが2か月以上の期間を経てついに届く。
その他
自作PCのグラフィックボードをGTX1080 からRTX3090に変更。
- 暖かいが暖房器具としてはもう少しパワーが欲しい。計算資源としてはなかなか。
iPhone XからiPhone 12 Proに機種変更。
総括
- 相変わらず色々ガジェットを買った。
- 給付金を見越して Jetson Xavier NXを2種類購入したが、サイズはJetson Nanoとほぼ同じ割に性能がかなり高く今後もっと活用していきたいと思った。
- CNCフライスでアルミとカーボン切削に挑戦。パラメータの調整がなかなか大変なことを知る。来年余裕あればCNCフライス購入したい。
- MakerFaireに出展。展示の難しさを知ったがかなり面白かった。
- 3D Lidar面白い。もう少し有効活用していきたい。
- 購入した犬ロボは思ったより大きくパワーもあった。試すスペースがなかなかなく、扱いの難しさを感じたが大きな四足歩行ロボットの可能性を感じた。
2019の振り返り
1月
Looking Glass 到着
やっとLooking Glass受け取った。さて何を出すか。 pic.twitter.com/dPzqOGz6SD
— higrademe (@EL2031watson) January 10, 2019
Cluster, VRChat初体験
- VRChatのすごさに感動するが、すぐにVR酔いしてしまう。
例のグラボ買う
Windows MR購入
- NorthStarMeetupで安いという情報を得たのでその場でポチる。
echo spot 導入
- カメラがついていて、アプリから遠隔監視ができるので、3Dプリンタの印刷状態を遠隔監視する用途に多用するように。
2月
NorthStarMeetup参加で刺激を受け3Dプリンターを購入(CR-10S)
3Dプリンターの進行状況を遠隔で確認出来るようにEcho Spotをプリンター前に置き、Alexaアプリで外出先から確認できるようにした。
— higrademe (@EL2031watson) February 9, 2019
単純だけどなかなか役に立つ。
プリント終了後にクールダウンして電源落とすところもなんとかしたい。 pic.twitter.com/8KyI21UKJH
3月
HoloLens 2の実寸大モックを作成
- 来日していたHoloLens 2の発表プレゼンをしていたMSの方からも賞賛の言葉を得る。
トルクヒンジを取り付けて、HoloLens 2のモックがフリップアップに完全対応。任意の角度で固定できて便利。 pic.twitter.com/nGVdLyHerb
— higrademe (@EL2031watson) August 10, 2019
Project North Star作成
- 3Dプリンターを使った初の大掛かりな製作作業。電源供給等でかなり手こずったが、なんとか動かせた。
今年の1月にアップデートされたProject North Star Update 3を製作した過程をまとめました。(と言ってもメモ書きみたいな感じ)
— higrademe (@EL2031watson) April 19, 2019
このやり方だとゼロから(と言っても3Dプリンター、工具は購入済みとする)作ると総額は5万近くになると思います。https://t.co/avPpcEmKZX#projectnorthstar
Davinci Color Mini購入
- 安くなってたのでカラープリンターに手を出してしまう。しかし狭い部屋に3Dプリンター二台はやりすぎだったことにあとで気づく(CNCフライスにしておけばよかったか)
4月
JetsonNano購入
Jetson Nano 入手 pic.twitter.com/kha4lZYgmz
— higrademe (@EL2031watson) April 6, 2019
xRTechで令和ことブルームと平成の手話で対応する文字を表示するアプリを展示
- 平成最後のxR Tech Tokyo
本日多くの方にNorthStar体験していただきました。ありがとうございます。
— higrademe (@EL2031watson) April 20, 2019
ちなみにどうでもいいですが、展示直前に改造してジェスチャーで額縁が上がって新元号が発表される仕様に変更しました。官房長官をセットにするところまでは間に合いませんでした...#xRTech pic.twitter.com/s2Zxe8ZpHe
Project North StarをT265で6DoF化
NorthStarにT265つけたら簡単に6DoF化した。アタッチメントの設計ミスってT265のカメラの下の方が少しLeapMotionで遮られるが、それでも位置トラッキングは結構良さそう。
— higrademe (@EL2031watson) April 23, 2019
あとはMapping...#projectnorthstar pic.twitter.com/NPDyHxP50X
5月
Jetson Xavierを購入。現在はxArmの制御用に使用。
やってしまった...
— higrademe (@EL2031watson) May 24, 2019
これでJetson TX2, Nano, Xavierの3つが揃ってしまった。
そして帰ったら不在票が3つも...
多分全部なんかのガジェット。1つしか心当たりがないのだが... pic.twitter.com/Izt36BrMKB
Oculus Questを購入
新しいガジェットを手に入れた喜びを昨日から味わいまくっている。
— higrademe (@EL2031watson) May 25, 2019
Oculus Quest pic.twitter.com/fjC4u1fsxA
6月
Structure Coreを購入
Structure CoreサンプルアプリをAndroid向けにビルドしてPixel3とCoreの直接接続でdepthとRGB表示出来た。
— higrademe (@EL2031watson) June 24, 2019
Mac向けにもビルドできて、少しソースいじったらrgbとかdepth mapとply形式の点群も保存できていたので、色々試せそう。 pic.twitter.com/KxdZInJB06
7月
ZEDを購入
Jetson Nano x ZEDモバイル点群メッシュ収集セットが完成した。
— higrademe (@EL2031watson) July 7, 2019
電力が結構ギリギリで、ZEDはセルフパワーUSB HUBにつなぎ、モバイルバッテリーで電力補助してJetsonNanoに入れている。ZEDそのままNanoにつなぐとアプリ起動時に落ちる。まあメモリもかなり厳しめのようだが、とりあえずZEDfuは使える。 pic.twitter.com/Vf3QZlc23k
Xtion Pro Liveを購入
Xtion pro Live がJetson Nanoで動いた。こちらもおそらく電力不足で直接つなぐと落ちたから、セルフパワーののUSBHubで電力を供給。 pic.twitter.com/9qM2oRHQKl
— higrademe (@EL2031watson) July 25, 2019
SR305を購入
とりあえずMacでlibrealsenseがビルドできたのでSR305を繋いでviewer起動したらSR300として認識された。やっぱ中身は... pic.twitter.com/cXIhA2aMok
— higrademe (@EL2031watson) August 1, 2019
8月
例のグラボで自作PCを作成、TensorflowをGPU使用で動かす
例のグラボ、例のマザボで2つ目の自作PC完成。取りあえずtensorflowいれてMNISTが動いた。マザボにPCIe 3.0が一つしかないため、PCIe 2.0につないでいる2つ目のグラボはROCmで使えず、意味なさそう。
— higrademe (@EL2031watson) July 31, 2019
グラボ一枚としてパーツ代は4-5万かな。諸事情により、CPUはPentiumでケースもまだ買ってないが... pic.twitter.com/TqiHvbaBpo
M5Stick VとCを購入
自作アイトラッキング装置を作成、xRTechで展示
自作アイトラッキングシステム、キャリブレーションして、なんとかそれっぽくアイトラッキングできるようになってきた。アプリケーションを作る時間がほぼなくなってしまった...
— higrademe (@EL2031watson) August 17, 2019
明日展示します。#xRTech pic.twitter.com/xWGwGvtYYz
第二種電気工事士に合格
第二種電気工事士に無事合格。初の業務独占資格だ。
— higrademe (@EL2031watson) August 19, 2019
これでIoT系の作業とかできることの幅が増えるはず。
Mediapipeのハンドトラッキングを試し性能の高さにびっくりする
Googleから公開されたmediapipeのハンドトラッキングをPixel3で早速試してみた。一部トラッキング失敗してるが、単眼でリアルタイムでかなりオクルージョンにも強く驚き。 pic.twitter.com/28ssCDOjqf
— higrademe (@EL2031watson) August 20, 2019
JetRacerを作成
NVIDIAの公開している #JetRacer 、ついに紙コップ(別名パイロン)で作られた円形のコースを自動走行成功。一箇所コップをふっとばすが、2周目そこをうまく避けるという技を披露して感心(そして彼走るの早い)。もっともコースが簡単でこれは難易度は低いかもしれないから、複雑な場所で試したい。 pic.twitter.com/umn7c6gWPC
— higrademe (@EL2031watson) August 25, 2019
Coral Dev Boardを購入
Edge TPUのボード、Coral Dev Boardのサンプルの顔認識プログラムををCoral Camera使って実行できた。120fps超えのようだ。 pic.twitter.com/J5yys7v8Yu
— higrademe (@EL2031watson) September 4, 2019
9月
JetBotを作成するが壊れる
JetBotの障害物避け、Nvidiaの公開している学習済みモデル使っただけでも結構うまく柱とか壁とか避けてて、良いなと思い、調子に乗って狭いテーブルで試してみたらこうなった...
— higrademe (@EL2031watson) September 14, 2019
被害総額はカメラ部分の破損により6000円くらい... pic.twitter.com/QVckNYKdQx
JetRacer作成記事を投稿
NvidiaのJetson Nanoを使ってラジコンを自動走行させるJetRacerの作成過程を以下の記事にまとめました。なかなか物品調達や3Dプリントや加工やらハードルは高いですが、参考までに。https://t.co/RWSPwK0KU7
— higrademe (@EL2031watson) September 11, 2019
Spot MiniにインスパイアされたSpot Microというオープンソースの四足歩行ロボの作成に着手(色は青白)
ついに自作4足歩行ロボットが歩行っぽい動作かできるようになった。と言っても色々問題があって右によってしまう...
— higrademe (@EL2031watson) October 5, 2019
PWMのサーボ12個、Jetson Nano。SpotMicroという某社ロボの小さい版のOSSプロジェクト。ソフトは取りあえず自作。IKの座標とかを間違えまくってかなり時間掛かった。 pic.twitter.com/3MzJIEbRgd
10月
回路Cadに入門、作成した基盤を実際に海外に発注
海外に発注した自作基板ついに到着。値段も安く到着までも1週間ちょっと。
— higrademe (@EL2031watson) October 28, 2019
届いた基板、設計通りだが初心者が作りました感に溢れる見た目... これでpca9685の制約を超えて6V以上、一応10Aまでサーボに電流流せるはず、なにか勘違いなければ... 全部同時にストールトルクに達するとまずいが... pic.twitter.com/jxg8hGQJhS
四足歩行ロボ第二世代を作成(色は青黒)
自作4足歩行ロボット、サーボをハイトルクに交換して、歩行パターンも改造してほんの少しマシになった。でもバランス崩すことも多くまだ安定して動くとは言えない。
— higrademe (@EL2031watson) October 21, 2019
4足歩行の歩容の情報が検索しても最近の論文ばかりで気軽に試せるのが見つからない... なにかいいのあったら教えて下さい。 pic.twitter.com/IcFcO4rEJL
11月
xArmをいじる。自動水やりを試しにやってみる。
少し前に届いてたxArmやっと動かす時間取れたので、取り合えずじょうごをテープでつけて水やりをさせてみた。
— higrademe (@EL2031watson) November 3, 2019
個人でロボットアームで遊べる時代?になったのはありがたい。 pic.twitter.com/mSYdWjSUuO
ラズパイ4を購入
とりあえずラズパイ4の起動からメニュー画面出るまでの温度計測をしてみた。
— higrademe (@EL2031watson) December 2, 2019
8倍速。よくわからないが、起動させるだけならこんなところか。
ちなみにCPUには反射しないようラズパイのケースについてきたテープを貼った。 pic.twitter.com/2AWLXNH587
12月
AI Carのアドベントカレンダーに投稿。初アドベントカレンダー参加。
「JetRacerの自動走行の仕組み」という題でAI RC Car Advent Calendar 2019の12/8の記事として投稿しました。
— higrademe (@EL2031watson) December 8, 2019
初めてのアドベントカレンダー参加で、しかも前日にJetRacerの調子が悪くなるという事件もありましたがなんとか1日で投稿まで持って行けたのでとりあえず一安心。https://t.co/Iir9PKjMAb
四足歩行ロボの骨折を機に足回りの改造、trot歩行に成功
4足歩行ロボット、予備で作ってた足に取り替え再度チャレンジ。
— higrademe (@EL2031watson) December 30, 2019
高速で歩くのに向くトロット歩行に成功。
驚異の時速0.67km/hを達成w
足のジョイント部をプラスチックから金属に変えて足位置がしっかり決まるようになったのが良かったと思われる。 pic.twitter.com/VoGKOy1kMo
総括
- 相変わらず色々ガジェットを買った。
- 3DプリンタでNorthStar, HoloLens 2のモック, JetRacer, JetBot, SpotMicroなどを作成し、3Dプリンターに大変お世話になった。
- 第二種電気工事士試験に合格、また回路cadでサーボモーターの電源供給用の自作基盤を制作し総じて電気系の知識が結構増えた。
- 去年まで継続して出していたアプリは今年作らなかったが、ハード制作系に初チャレンジ。色々難しさを知る。
- xArmをいじり初のロボットハンド操作を体験。購入したセンサー類などと組み合わせ、今後様々なタスクにチャレンジしたい。
- 四足歩行ロボットはやっと前進ができるようになった。今後深度カメラ or LidarとSLAM、深層学習等を組み合わせ自動で動くペットのような動きをさせたい。
JetRacerの自動走行の仕組み
JetRacerとは
Nvidiaが公開しているJetsonNanoを用いた自動走行カープロジェクトがあります。 github.com
前回の記事ではこちらの作り方を説明しました。
作った当時はとりあえずサンプルのJupyter Notebookをただ実行するだけで動かしていただけでした。 今回こちらで自動走行ができる仕組みについて少し調べてみました。
基本的なラジコンの仕組み
まず自動走行する以前に、JetRacerの改造前のラジコンについて考えてみます。
車本体の位置を制御することに関して、ラジコンのコントローラー(プロポ)からステアリング(Steering、進行方向)・スロットル(Throttle、進行速度)の2つの信号が車側の受信機に届き、値に応じて車に取り付けられている2つのモーターの動きを制御しています。
ラジコンの自動走行
ラジコンを自動走行させるには基本的には人間に変わり、何らかのセンサーを使い状況を認識し、判断を行いステアリング・スロットルを適切に制御することで自動走行を実現します。
現在の標準のJetRacerではスロットルはあらかじめ指定した固定値を常に維持し、車正面に搭載のカメラから得られた情報を元にステアリングの値を変化させることでコースに沿った走行が実現しています。
ちなみにJetRacerでスロットルを状況に応じて自動で操作するということは可能で、方法はいくつか考えられます(前に参加した大会ではステアリング角に応じた速度の値を決めることでコーナーでは低速、直線では高速にする改良を行い、タイムを大幅に縮めることができました)
スロットル制御については以下の記事でもmasato-kaさんが触れられていますので、興味のある方は参考にしてください。 masato-ka.hatenablog.com
カメラ画像からからステアリング角を決める仕組み
上で述べたように、自動走行には人間の目に変わりコースの形状・車の位置などを認識し、それに応じた制御をする必要があります。
こちらは実際の自動車の自動運転では車両前方につけたカメラで白線認識を行ったり、奥行きまで認識できるセンサー(Lidar、ステレオカメラ、ミリ波レーダー)などを用い、車の空間における位置関係を把握しステアリング・スロットルの判断を行うということが行われていると思われます。白線認識を行ったり、LidarなどのセンサーをJetRacerに搭載することも可能ですが、システムが複雑になったり、重量・価格などがネックになってしまいます。
もっともシンプルに自動走行を実現するには通常のWebカメラのようなカメラ1つ(単眼カメラと呼ばれる)からステアリングを直接推定することです。 そんなこと可能なのかと思われるかもしれませんが、近年人気のディープラーニングを使って、「画像を入力->ステアリング角を出力」を行ったという論文をNvidiaが数年前に発表しました。
End to End Learning for Self-Driving Cars (2016) https://images.nvidia.com/content/tegra/automotive/images/2016/solutions/pdf/end-to-end-dl-using-px.pdf
詳細は省きますが、内容としては「道路を走行中の画像」と「その画像を撮影した時点での車のステアリング角」のペアのデータを大量に収集し、CNNというニューラルネットワークにその関係を学習させ、走行中にその時点での画像から直ちにその時点で取るべきステアリング角を推定し実際にステアリング角を変化させるということを行っています。
JetRacerの自動走行もこの論文と同様の原理で自動走行しています。 唯一異なる点は論文のように実際の走行時のステアリング角を学習のターゲットとせず、各画像に付与した車が向かうべきターゲットピクセル座標(x,y)を使って正しいステアリング角を擬似的に作り出している点です。
具体的に見ていきましょう。
上記のレポジトリ内の jetracer/notebooks/interactive_regression.ipynb を順に実行することでデータ収集、学習を行うことができますが、実行して画像を収集していく過程で、TASKという変数名で指定した名前から始まるフォルダが、jetracer/notebooks内に作成されています。 そのフォルダ内のapex内に画像ファイルが以下のようなファイル名で保存されていると思います。 99_109_xxxxxxxxxxxx.jpg
このファイル名先頭の2つの数字が画像を保存する際にクリックしたピクセル座標x,yに対応しています。
なおこのファイルの保存の処理はnotebooks/xy_dataset.py内のXYDatasetクラスのsave_entry関数で行われています。
class XYDataset(torch.utils.data.Dataset): (中略) def save_entry(self, category, image, x, y): category_dir = os.path.join(self.directory, category) if not os.path.exists(category_dir): subprocess.call(['mkdir', '-p', category_dir]) filename = '%d_%d_%s.jpg' % (x, y, str(uuid.uuid1())) image_path = os.path.join(category_dir, filename) cv2.imwrite(image_path, image) self.refresh()
filenameを x_y_uuid.jpgという形式にしてフォルダに保存していることがわかります。 jupyter notebook上のカメラ画像の座標をクリックするごとにこの関数が呼ばれ、画像とターゲットのピクセル座標をファイル名内に入れて保持します。
ネットワークをトレーニングする際にこの画像とファイル名を読み込んで学習を行います。 なお実際にネットワークから出力するx,yの値はピクセル座標ではなく、画像サイズを元の値から割って得られる -1 から1の値です。
なおこの処理は上の画像を保存する処理が入っているnotebooks/xy_dataset.py内に記述されており、
class XYDataset(torch.utils.data.Dataset): (中略) def __getitem__(self, idx): ann = self.annotations[idx] image = cv2.imread(ann['image_path'], cv2.IMREAD_COLOR) image = PIL.Image.fromarray(image) width = image.width height = image.height if self.transform is not None: image = self.transform(image) x = 2.0 * (ann['x'] / width - 0.5) # -1 left, +1 right y = 2.0 * (ann['y'] / height - 0.5) # -1 top, +1 bottom if self.random_hflip and float(np.random.random(1)) > 0.5: image = torch.from_numpy(image.numpy()[..., ::-1].copy()) x = -x return image, ann['category_index'], torch.Tensor([x, y])
の中の
x = 2.0 * (ann['x'] / width - 0.5) # -1 left, +1 right y = 2.0 * (ann['y'] / height - 0.5) # -1 top, +1 bottom
でターゲットのピクセル座標ann['x']、ann['y'] がそれぞれ-1 ~ 1 に変換された x,yになっていることがわかるかと思います。
お気づきかもしれませんが、このターゲットのピクセル座標を予測しても、実際のステアリング角とは異なるので、通常は予測結果をそのままラジコンのステアリング角には使用できません。
JetRacerではこの予測したピクセル座標(-1~1に正規化)のxの値をそのままステアリング角とみなします。ステアリング角も-1~1の範囲に正規化されているため、例えばもっとも左にステアリング角を取るとき(steering = -1)はx=-1となり、もっとも右にステアリング角を取るとき(steering = 1)はx=1となります。
このxの値をそのままステアリング角とみなすというのはやや極端かと思いますが、カメラが車体進行方向に対してまっすぐに取り付けられているとするならば、画像の真ん中を境にマークの位置に応じて左右のステアリング値に直接変換するというのはもっとも簡単で手軽な方法の1つだと思います。
実際の画像を見ていただくとわかりますが、真ん中から左側をクリックするときはステアリングは左、右側をクリックするときはステアリングは右になっていそうなことがわかると思います。
ピクセル座標の値をステアリング角とみなして、実際にラジコンにステアリング指示を行う処理はjetracer/notebooks/road_following.ipynbの最後のセルに記述されています。
import numpy as np STEERING_GAIN = 0.75 STEERING_BIAS = 0.00 car.throttle = 0.15 while True: image = camera.read() image = preprocess(image).half() output = model_trt(image).detach().cpu().numpy().flatten() x = float(output[0]) car.steering = x * STEERING_GAIN + STEERING_BIAS
の中の
x = float(output[0]) car.steering = x * STEERING_GAIN + STEERING_BIAS
の部分が、学習済みモデルに画像を入れて出力されたピクセル座標のxの値を取り出し、ステアリング角(car.steering)に変換している部分です。 実際の処理ではSTEERING_GAINという値をかけることで、ステアリングの値を多少小さめに指示する操作を行っています。こちらの値は使用するラジコンの最大ステアリング角等を見て調整することでより性能の良い自動走行を実現できると思われます。 またSTEERING_BIASはステアリング値に一定値を常に加える処理ですので、カメラが車体本体から左右にずれていたり、重力の軸周りに回転してしまっている場合あるいはラジコンのステアリング機構自体の左右へのズレを補正するためのもので、そういうズレがなければ通常STEERING_BIAS=0.00で問題ないと思います。
ピクセル座標のyの値は標準のJetRacerでは使用しておりませんが、こちらは画像をクリックしてアノテーションを行うときのことを考えると、奥行き方向に関連する情報を持っている可能性があると思いますので(コース上をクリックするとするならば視界の先をどれだけ見渡せるかで速度を出せるかどうかの目安にできる?)、速度(throttle)に関する制御に使えるのではないかと考えられます。
以上で簡単ですが、JetRacerの自動走行の仕組みについて自分の理解の範囲で解説させていただきました。 勘違いや、JetRacerの自動走行の仕組みについてより詳しい背景等ご存知でしたら是非ご指摘願います。
JetRacerの組み立て
NVIDIAからJetson Nanoを使ったAI自動走行車JetBotに続く、JetRacerが発表されました。 github.com
こちら市販のラジコンカーにJetson Nanoとカメラを取り付け、カメラの画像からその時点でどちらに転舵すべきかを機械学習で学習させ、それを元にラジコンカーを自動走行させるというものです。
参考動画:
NVIDIAの公開している #JetRacer 、ついに紙コップ(別名パイロン)で作られた円形のコースを自動走行成功。一箇所コップをふっとばすが、2周目そこをうまく避けるという技を披露して感心(そして彼走るの早い)。もっともコースが簡単でこれは難易度は低いかもしれないから、複雑な場所で試したい。 pic.twitter.com/umn7c6gWPC
— higrademe (@EL2031watson) August 25, 2019
JetBotと異なり、ラジコンカーならではのスピード感ある自動走行を楽しむことができます。(もっと大きい場所でより複雑な形状のコース作って試してみたいが、なかなか東京付近で場所がない... どなたか場所の提供 or いい場所を教えてください...)
ラジコンカーに馴染みない方向けに簡単に補足しますと、今回取り扱うラジコンカーは二つのモーターから構成されており、
サーボーモータ
- 角度を細かく調整できるモータ
- 前輪の回転軸をサーボーモーターによってずらし、ラジコンカーの進行方向を左右に変更する。
DCモーター
- 角度は細かく調整できないが高速で回転させられる
- 前後輪を回転させ、ラジコンカーを前進・後進させる。
という役割を担っています。 デフォルトのJetRacerではDCモーターは常に一定速度で動かし、カメラから得られた情報からサーボーモータをどの程度動かすかを決め、サーボーモーターにそれを伝え、コースアウトしないように走行することで自動走行を実現しています。
今回こちらをパーツの仕入れから、実際に動かすまで一通りやってみたので、その過程をまとめました。なお車体はlatraxというものとtamiyaの2通りありますが、日本で入手しやすいtamiyaのシャーシのものを作成しました。
作成に関する注意事項
作成部品の入手難易度はやや高めかと思います。その理由は、
- パーツ合計がやや高額になる。(3Dプリントパーツ無しでも5万ぐらい?)
- 3Dプリントするパーツが3点ある。(ボード類取り付け用のベース板、シャーシへの穴あけ用の補助板、カメラモジュール取り付け台)
- まあまあ分厚いシャーシに穴あけするボール盤などの道具を利用する必要がある。(私はDMM.make AKIBAを利用しました。固定を接着剤とか別の方法でやるなら不要かもしれません)
一方で上の3つがクリアできれば組み立ては配線系が少しややこしいことを除けば、ラジコンの知識はほぼなくてもできます。
ただし注意事項として、ラジコン本体・プロポ(ラジコンのコントローラー)の調達はよく調べたほうがいいです。 私の場合、横着をして、シャーシ・プロポ・バッテリー・バッテリー充電用ACアダプタセットのものを買ってしまいました。(これと単三電池4本を買うだけで、ラジコンとして遊ぶことができる)
しかしプロポが2つの信号(進行・後退と左右転舵)しか送れない2chのものだったので、公式で推奨している3chのものとは異なり、プロポから自動走行or手動走行を切り替えることができませんでした。このままだと学習させる時、面倒だったので結局3chプロポを買って受信機を取り替えました。 ただし、マルチプレクサを経由せずモータードライバからの信号or受信機からの信号の配線を手で繋ぎ変えて手動・自動を変えることはできますので、予算厳しい方は私と同じく2chの車体・プロポセットを購入すればマルチプレクサなしで最低限手動自動共にJetRacerを動かすことはできます。
なお3chプロポを最初から使うと言う方は、シャーシ、プロポ、受信機、サーボモータ、ラジコン用バッテリー、ラジコン用ACアダプタを個別で調達すると安く上がると思います。
パーツ一覧(購入するもの)
3Dプリントが必要なパーツ
- ボード類を取り付けるベース板
- シャーシに穴あけするときに穴あけ位置を特定するための補助板
- カメラモジュールを取り付ける台
組み立て
基本的にはこちらに従って組み立てます。 jetracer/hardware_setup.md at master · NVIDIA-AI-IOT/jetracer · GitHub
フェーズ1 (シャーシの穴あけ、モーターカバーの除去、スタンドオフの取り付け、受信機の取り付け)
シャーシに穴あけするため、上で3dプリントした2番の補助板をシャーシの裏側(地面側)にテープなどで固定します。この際3dプリントした板の突起がある部分がシャーシ裏側のネジ部分と一致するはずです。(一部ネジを取り外さないとはみ出るので適宜ネジを外す)
補助板に空いている3mmの穴4箇所をターゲットとして3mmドリルで穴あけ、シャーシまで貫通させます。
(オプション) ネジの皿部分がシャーシからはみ出ないように上の4つの穴に対して、皿穴加工をします。私は適当に6,7mmぐらいのドリルで数ミリ穴あけしました。(公式のStep2 Countersink)
シャーシ表側のDCモーター付近のカバーを外します。(大きなモーターの方) これがあると、あとでベース台を固定するときに邪魔になるかと思います。
モーターカバーを外したシャーシ 先ほど開けた4つの穴を通じて、シャーシにM3x8mmのネジでスタンドオフを取り付けます。
シャーシ背面図 (オプション)受信機を3chプロポ対応のものに取り替えるor取り付けます。 車体・プロポセットで買った方はシャーシに2ch用の受信機が付いていますが、こちらを取り外します。粘着力強めの両面テープで付いているだけですので頑張って外してください。
2ch用の受信機を外した後、3ch用の受信機を取り付けます。
フェーズ2(3Dプリントしたベース板に各種基盤を取り付け)
マルチプレクサをM2x8mmのネジ2つでベース板に取り付けします。2箇所だけで少し不安なので、ネジのない側に何か台なり設置したい気はします...
PWMサーボモータードライバーをM2x8mmのネジ4つでベース板に取り付けします。
Jetson Nanoを M2x8mmのネジ4つでベース板に取り付けします。
カメラモジュールのカメラ部分をIMX219のカメラに取り替え、カメラモジュールを3Dプリントしたカメラ台にM2x8mmネジ4つで取り付けます。カメラモジュールのコネクターをJetsonNanoに取り付けます。さらにカメラ台をベース板にM2x8mmネジ4つで取り付けます。最後にカメラモジュールとJetsonNanoを接続します。ラズパイ公式のカメラモジュール仕様の場合、ケーブルが半ねじりの状態になってしまいます。
USB WiFiアダプタをJetson Nanoに取り付けます。
フェーズ3 結線
- Jetson Nanoとモータードライバの接続
これによって、JetsonNano側から来る前進・後進・右転舵・左転舵の指示をモーター側に伝えることができるようになります。1ピンのジャンパーケーブル1つと、3ピンのジャンパーケーブル1つを取り付けします。
Jetson側
- 1ピンジャンパーはGNDに接続します。(図のJetsonNano上のGPIOピン上、右列側の黒線)
- 3ピンジャンパーは3V3, 3番, 5番 に接続します。(図のJetsonNano上のGPIOピン上、左列側の黒線(3V3)・赤線(3番)・白線(5番) )
サーボモータードライバー側
- 1ピンジャンパーはGNDに接続します(図の下側のモータードライバ上の一番上の黒線)
- 3ピンジャンパーはVCC(黒線), SDA(赤線),SCL(白線)に接続します。
なお、JetsonNanoとモータードライバ間の3ピンの結線は以下のような対応になります。
- 3V3 がVCCに(黒)
- SDAが3番に(赤)
- SCLが5番に(白)
- サーボモータドライバとマルチプレクサの接続
マルチプレクサとはA,Bという二つの信号のどちらかをCから出力するという時にDという別の信号によって電気的にA・Bを切り替えることができる装置です。今回、A・Bの信号はJetsonNano・プロポに対応し、マルチプレクサを使うことで、自動走行or手動走行を切り替えすることができるようになります。
具体的には図のようにマルチプレクサを上から見た図で、
- M1~M4 (上の例でいう信号Aたち。Masterの略か)
- S1~S4 (上の例でいう信号Bたち。Slaveの略か)
- Out1~Out4(上の例でいう信号C。ここをモータに繋ぐことでM1~M4 or S1~S4のどちらかの信号がモーター側に伝わります。 )
- SEL (上の例でいう信号D。M1~M4 or S1~S4の切り替えを担当)
となります。
二箇所取り付けます。 この時向きはGND通しが繋がるように注意してください。
- サーボモータドライバ上の0番(黒赤黄上でJetsonと接続したピンから最も近い方)をマルチプレクサのS1に接続。(転舵信号を担当)
- サーボモータドライバ上の1番(黒赤黄上でJetsonと接続したピンから最も近い方)をマルチプレクサのS2に接続。(前進・後進の信号を担当)
- 受信機とマルチプレクサの接続
マルチプレクサのM1,M2,SELを受信機の1番・2番・3番と接続します。この接続によりプロポからの操作信号(転舵・前進後進・手動自動運転の切り替え)をマルチプレクサに送ることができるようになります。マルチプレクサのGND側のピンと受信機の右側のピンが繋がるように注意してください(図では黒線)
- マルチプレクサとサーボモータ、ESCの接続
上の手順でマルチプレクサにJetsonNano(自動運転)とプロポ(手動運転)の信号が入るようになり、この二つはSELの信号によって切り替えられるようになっています。さらにこの信号をサーボモータとESCに送り実際にモーターを動かせるようにします。
なおESC(Electric Speed Controller)は前進後進を行うDCモーターに電流を供給する装置です。入力として駆動信号とバッテリーからの電流の二つをもち、駆動信号を増幅してモーターに駆動に十分な電流を供給します。放熱用のファンがついているものです。
以下の二つの接続を行います。 なおいずれも黒線がマルチプレクサのGNDに接続されるように気をつけてください。
- サーボモータ(受信機の下に付いている)とマルチプレクサのOut1の接続(図で左側の指あたりから出ているESCの赤白黒の線)
- ESCとマルチプレクサのOut2の接続(図で右側の指あたりから出ているサーボモータの赤白黒の線)
フェーズ4 最終組み立て
JetsonNanoなどが取り付けてあるベース板をM3x8mmのネジ4つを使ってスタンドオフに取り付けます。これによってベース板がシャーシに固定されます。
以上でハードウェア部分は完成です。気が向いたら、別の記事でソフトウェア部分について書こうと思います。
Coin Roller Master Privacy Policy
Privacy Policy
hygradme built the Coin Roller Master app as a Free app. This SERVICE is provided by hygradme at no cost and is intended for use as is.
This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service.
If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy.
The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at Coin Roller Master unless otherwise defined in this Privacy Policy.
Information Collection and Use
For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information, including but not limited to None. The information that I request will be retained on your device and is not collected by me in any way.
The app does use third party services that may collect information used to identify you.
Link to privacy policy of third party service providers used by the app
Log Data
I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics.
Cookies
Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.
This Service does not use these “cookies” explicitly. However, the app may use third party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.
Service Providers
I may employ third-party companies and individuals due to the following reasons:
- To facilitate our Service;
- To provide the Service on our behalf;
- To perform Service-related services; or
- To assist us in analyzing how our Service is used.
I want to inform users of this Service that these third parties have access to your Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.
Security
I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security.
Links to Other Sites
This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.
Children’s Privacy
These Services do not address anyone under the age of 13. I do not knowingly collect personally identifiable information from children under 13. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do necessary actions.
Changes to This Privacy Policy
I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately after they are posted on this page.
Contact Us
If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me.
This privacy policy page was created at privacypolicytemplate.net and modified/generated by App Privacy Policy Generator