Windows11にROS2を入れてみた
やりたいこと
windows11にROS2をインストールしたい
参考にしたサイト
ほとんどこの通りにやって動きました! (Dockerを使わない場合) Windows10のWSL2にROS2をインストールする - Qiita
手順(差分だけ記載していきます)
1. Windows11にWSL2をインストール
2. Xserver → 不要
windows11からはlinux guiが使えるようになったので不要でした。
3. ROS2導入
参考サイトの手順通りです。
4. RVIZ2を導入
この手順通りですが、git cloneのときにブランチを指定(foxy)しないとエラーになる
[Processing: rviz_ogre_vendor] Finished <<< rviz_ogre_vendor [11min 38s] Starting >>> rviz_rendering --- stderr: rviz_rendering /home/rviz2_ws/src/rviz/rviz_rendering/src/rviz_rendering/mesh_loader.cpp:65:10: fatal error: resource_retriever/retriever.hpp: No such file or directory 65 | #include "resource_retriever/retriever.hpp" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. make[2]: *** [CMakeFiles/rviz_rendering.dir/build.make:145: CMakeFiles/rviz_rendering.dir/src/rviz_rendering/mesh_loader.cpp.o] Error 1 make[2]: *** Waiting for unfinished jobs.... make[1]: *** [CMakeFiles/Makefile2:344: CMakeFiles/rviz_rendering.dir/all] Error 2 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:141: all] Error 2 --- Failed <<< rviz_rendering [16.7s, exited with code 2]
git clone https://github.com/ros2/rviz.git -b foxy
で解決
5. pythonのインストール
(入ってたので省略)
6. gazeboのインストール
参考サイト通りにやる
さいごに
以上です。 windows11のwslはUSBが使えるようなので、webカメラ使えそうですね。
zenn.dev 私は、unityかUE4を使ってロボットアームを動かしたいので、 連携方法を探してます。 何かいい方法を知ってる人はコメントください。
pythonでGUIアプリ作成 ~画像表示・回転~
やりたいこと
調べたこと
kivyのドキュメント pyky.github.io
作ったアプリ
- ファイルパスを読み込む(FileChooser)
- 画像を表示する(Image)
- opencvで回転させる
コード(python部分)
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.floatlayout import FloatLayout from kivy.graphics.texture import Texture from kivy.properties import ObjectProperty from kivy.factory import Factory from kivy.uix.popup import Popup from kivy.core.window import Window import os import cv2 class LoadDialog(FloatLayout): load = ObjectProperty(None) cancel = ObjectProperty(None) class Root(BoxLayout): # loadfile = ObjectProperty(None) image_texture = ObjectProperty(None) imgData = None def dismiss_popup(self): self._popup.dismiss() def show_load(self): content = LoadDialog(load=self.load, cancel=self.dismiss_popup) self._popup = Popup(title="Load file", content=content, size_hint=(0.9, 0.9)) self._popup.open() def load(self, path, filename): imgFilepath = os.path.join(path, filename[0]) # print(self.imgFliepath) # with open(os.path.join(path, filename[0])) as stream: # self.text_input.text = stream.read() self.imgData = cv2.imread(imgFilepath) self.img_show() self.dismiss_popup() def img_show(self): # filename = "../guiapp/IMG_0162.JPG" img = self.imgData img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.flip(img, 0) texture = Texture.create(size=(img.shape[1], img.shape[0])) texture.blit_buffer(img.tobytes()) self.image_texture = texture def img_show(self): img = self.imgData img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.flip(img, 0) texture = Texture.create(size=(img.shape[1], img.shape[0])) texture.blit_buffer(img.tobytes()) self.image_texture = texture def rotation_clockwise(self): self.imgData = cv2.rotate(self.imgData, cv2.ROTATE_90_CLOCKWISE) self.img_show() def rotation_affine(self, value): img = self.imgData center = (img.shape[1] / 2, img.shape[0] / 2) angle = -float(value) scale = 1.0 print(center, angle, scale) trans = cv2.getRotationMatrix2D(center, angle, scale) img = cv2.warpAffine(img, trans, (img.shape[1], img.shape[0])) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.flip(img, 0) texture = Texture.create(size=(img.shape[1], img.shape[0])) texture.blit_buffer(img.tobytes()) self.image_texture = texture class mainApp(App): def build(self): return Root() Factory.register('Root', cls=Root) Factory.register('LoadDialog', cls=LoadDialog) Window.size = (600, 600) ap = mainApp() ap.run()
コード(kv部分)
<Root>: BoxLayout: orientation: "vertical" ScrollView: bar_width: 10 Image: id: im texture: root.image_texture size_hint: (1, 1) BoxLayout: orientation: "horizontal" size_hint: (1, 0.25) Slider: id: slider1 size_hint: (0.75, 1) min: 0 max: 90 step: 0.1 on_value: root.rotation_affine(self.value) TextInput: id: tx1 size_hint: (0.25, 1) text: str(slider1.value) BoxLayout: orientation: "horizontal" size_hint: (1, 0.25) Slider: id: slider2 size_hint: (0.75, 1) min: 0 max: 100 step: 0.1 TextInput: id: tx2 size_hint: (0.25, 1) text: str(slider2.value) ActionBar: background_color: 1, 0, 0, 1 ActionView: use_separator: True ActionPrevious: text: "new" with_previous: False ActionGroup: text: "menu" ActionButton: text: "open" on_release: root.show_load() ActionButton: text: "clockwise" on_release: root.rotation_clockwise() ActionButton: text: "button3" <LoadDialog>: BoxLayout: size: root.size pos: root.pos orientation: "vertical" # FileChooserListView: # id: filechooser FileChooser: id: filechooser rootpath: "../" path: "/mnt/c/workspace/" filters: ['*.jpg', '*.png','*.JPG', '*.PNG'] FileChooserListLayout FileChooserIconLayout BoxLayout: size_hint_y: None height: 30 Button: text: "Cancel" on_release: root.cancel() Button: text: "Load" on_release: root.load(filechooser.path, filechooser.selection) BoxLayout: orientation: "vertical" Button: text: 'Icon View' on_press: filechooser.view_mode = 'icon' Button: text: 'List View' on_press: filechooser.view_mode = 'list'
結果
起動時
ファイル選択
スライダーでの回転量調整
購入検討中の本
pythonでGUIアプリ作成 ~Kivyのインストール~
やりたいこと
調べたこと
pythonでは、GUIアプリを作るのに以下の4つの環境が候補としてあげられる。
この中で、近年人気なのがKivyらしい techplay.jp
Kivyのインストール
私の開発環境は以下のとおりである - WSLのubuntu18.04LTS - python3.6
できればこの環境を使いまわしたいので、インストールするのはubuntuに決定。
どうやら、ubuntuに入れる方法はややこしいらしい。
これを参考にインストールをしていく。
躓いたところ
stable buildsだとエラーが出る
[CRITICAL] [Window ] Unable to find any valuable Window provider. Please enable debug logging (e.g. add -d if running from the command line, or change the log level in the config) and re-run your app to identify potential causes egl_rpi - ImportError: cannot import name 'bcm' File "/usr/lib/python3/dist-packages/kivy/core/__init__.py", line 63, in core_select_lib fromlist=[modulename], level=0) File "/usr/lib/python3/dist-packages/kivy/core/window/window_egl_rpi.py", line 12, in <module> from kivy.lib.vidcore_lite import bcm, egl sdl2 - ImportError: libSDL2_image-2.0.so.0: cannot open shared object file: No such file or directory File "/usr/lib/python3/dist-packages/kivy/core/__init__.py", line 63, in core_select_lib fromlist=[modulename], level=0) File "/usr/lib/python3/dist-packages/kivy/core/window/window_sdl2.py", line 27, in <module> from kivy.core.window._window_sdl2 import _WindowSDL2Storage x11 - ImportError: No module named 'kivy.core.window.window_x11' File "/usr/lib/python3/dist-packages/kivy/core/__init__.py", line 63, in core_select_lib fromlist=[modulename], level=0) [CRITICAL] [App ] Unable to get a Window, abort.
これは、ubuntuのインストーラーにbcmが含まれないからだそう
解決策
nightly buildsを使う
$ sudo add-apt-repository ppa:kivy-team/kivy-daily $ sudo apt-get install python3-kivy
これでinstallが終了。
テストコードの実行
コード
from kivy.app import App from kivy.uix.widget import Widget class MainWindow(Widget): pass class HelloWorldApp(App): def build(self): return MainWindow() if __name__ == '__main__': HelloWorldApp().run()
躓いたところ
openGLが2.0以下なのでErrorになる
解決方法
いろいろ試したが、xwindowが選ぶopenGLが1.4になってたのが問題だった。
unset LIBGL_ALWAYS_INDIRECT
と、VcXsrvの起動時に Extra settingsでNative openglをチェックアウトする
すると、openGLが変更され起動する。
結果
購入検討中の本
pythonでROS1のservice
やること
- ROS1でサービスを使ってみる
やったこと
チュートリアルをやってみて、追加しないといけなかったことを記載しています。(チュートリアルも途中から見るとだめで、ちゃんと前後関係把握しないとだめですね。。。)
前回の環境の続きで始めます。
~/rospython/src/ros_pubsubtest
にて、
サービスのパッケージをコピーしてくる
roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
結果
ros_bubsubtest/srv/AddTwoInts.srv
が生成される。
ros_pubsubtest/CMakeList.txtにおいて、
add_service_files( FILES AddTwoInts.srv )
をコメント解除&追記する
その後、~/rospython
にて、catkin_make
を実行する
すると、以下のファイルが生成されているはず。
~/rospython/devel/lib/python2.7/dist-packages/ . └── ros_pubsubtest ├── __init__.py ├── __init__.pyc ├── msg │ ├── __init__.py │ ├── __init__.pyc │ ├── _pubsub.py │ └── _pubsub.pyc └── srv # 新たに生成されたフォルダ ├── _AddTwoInts.py └── __init__.py
では、サービスのソースコードを書いていく。(chmod +xで実行権限を与えるのを忘れない)
#! /usr/bin/python import sys import rospy from ros_pubsubtest.srv import * def add_two_ints_client(x, y): rospy.wait_for_service('add_two_ints') try: add_two_ints = rospy.ServiceProxy("add_two_ints", AddTwoInts) resp1 = add_two_ints(x, y) return resp1.sum except rospy.ServiceExpection, e: print "Service call failed: %s"%e def usage(): return "%s [x y]"%sys.argv[0] if __name__ == "__main__": if len(sys.argv) == 3: x = int(sys.argv[1]) y = int(sys.argv[2]) else: print usage() sys.exit(1) print "Requesting %s+%s"%(x, y) print "%s + %s = %s"%(x, y, add_two_ints_client(x, y))
#! /usr/bin/python from ros_pubsubtest.srv import * import rospy def handle_add_two_ints(req): print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b)) return AddTwoIntsResponse(req.a + req.b) def add_two_ints_server(): rospy.init_node("add_two_ints_server") s = rospy.Service("add_two_ints", AddTwoInts, handle_add_two_ints) print "Ready to add two ints." rospy.spin() if __name__== "__main__": add_two_ints_server()
いつものように、~/rospython/catkin_make
を実行し、ターミナル1でroscore
を起動後、ターミナル2, 3それぞれで、
# ターミナル2 rosrun ros_pubsubtest add_two_ints_client.py 10 8 # ターミナル3 rosrun ros_pubsubtest add_two_ints_server.py
実行する。
結果は、
# ターミナル2 Requesting 10+8 # server起動までは待ちが入る 10 + 8 = 18 # ターミナル3 Returning [10 + 8 = 18]
となる。
無事にサービスを作ることができた。
参考になる本
pythonでROS1のpub/sub_part2
やること
- ROS1でメッセージのやり取り(pub/sub)
前回の記事
前回失敗したところ
ビルドが完了したので実行してみる
terminal1
cd ~/rospython; source devel/setup.bash roscore
無事にroscore起動
terminal2
cd ~/rospython; source devel/setup.bash rosrun ros_pubsubtest publish.py
エラーが出る
[rosrun] Couldn't find executable named publish.py below /home/hogehoge/rospython/src/ros_pubsubtest [rosrun] Found the following, but they're either not files, [rosrun] or not executable: [rosrun] /home/hogehoge/rospython/src/ros_pubsubtest/script/publish.py
ソースコードの確認
terminal1でroscore起動
termnial2でpython publish.py
でpubを起動
terminal3でpython subscribe.py
でsubを起動
左がpubのlogで右がsubのログです。
両方意図通り動いているのでソースコードの不具合ではなさそう。
そもそも、エラーログが、ファイルが存在しないてきな感じなので、やっぱりbuildの設定が原因?
そもそも、タブ補完されないのが怪しすぎる。。。
いろいろ確認していくと、ファイルに実行権限が与えられていなかったのが原因でした。
chmod +x publish.py chmod +x subscribe.py
を実行
その後、
# ターミナル2 rosrun ros_pubsubtest publish.py # ターミナル3 rosrun ros_pubsubtest subscribe.py
を実行すると、無事に起動しました。
参考になりそうな本
- 価格: 4730 円
- 楽天で詳細を見る
pythonでROS1のpub/sub_part1
やること
- ROS1の作業フォルダ作成
- ROS1でメッセージのやり取り(pub/sub)
(pub/subは失敗)
ROS1の作業フォルダの作成
フォルダの作成及び、melodicのpath設定
mkdir -p rospython/src cd rospython source /opt/ros/melodic/setup.bash tree .
実行結果
. └── src 1 directory, 0 files
makeで必要なファイルを作成
catkin_make
実行結果
Base path: /home/hogehoge/rospython Source space: /home/hogehoge/rospython/src Build space: /home/hogehoge/rospython/build Devel space: /home/hogehoge/rospython/devel Install space: /home/hogehoge/rospython/install Creating symlink "/home/hogehoge/rospython/src/CMakeLists.txt" pointing to "/opt/ros/melodic/share/catkin/cmake/toplevel.cmake" #### #### Running command: "cmake /home/hogehoge/rospython/src -DCATKIN_DEVEL_PREFIX=/home/hogehoge/rospython/devel -DCMAKE_INSTALL_PREFIX=/home/hogehoge/rospython/install -G Unix Makefiles" in "/home/hogehoge/rospython/build" #### -- The C compiler identification is GNU 7.5.0 -- The CXX compiler identification is GNU 7.5.0 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Using CATKIN_DEVEL_PREFIX: /home/hogehoge/rospython/devel -- Using CMAKE_PREFIX_PATH: /opt/ros/melodic -- This workspace overlays: /opt/ros/melodic -- Found PythonInterp: /usr/bin/python2 (found suitable version "2.7.17", minimum required is "2") -- Using PYTHON_EXECUTABLE: /usr/bin/python2 -- Using Debian Python package layout -- Using empy: /usr/bin/empy -- Using CATKIN_ENABLE_TESTING: ON -- Call enable_testing() -- Using CATKIN_TEST_RESULTS_DIR: /home/hogehoge/rospython/build/test_results -- Found gtest sources under '/usr/src/googletest': gtests will be built -- Found gmock sources under '/usr/src/googletest': gmock will be built -- Found PythonInterp: /usr/bin/python2 (found version "2.7.17") -- Looking for pthread.h -- Looking for pthread.h - found -- Looking for pthread_create -- Looking for pthread_create - not found -- Looking for pthread_create in pthreads -- Looking for pthread_create in pthreads - not found -- Looking for pthread_create in pthread -- Looking for pthread_create in pthread - found -- Found Threads: TRUE -- Using Python nosetests: /usr/bin/nosetests-2.7 -- catkin 0.7.23 -- BUILD_SHARED_LIBS is on -- BUILD_SHARED_LIBS is on -- Configuring done -- Generating done -- Build files have been written to: /home/hogehoge/rospython/build #### #### Running command: "make -j8 -l8" in "/home/hogehoge/rospython/build" ####
するとファイルが作成される
├── build │ ├── CMakeFiles │ │ ├── 3.10.2 │ │ │ ├── CompilerIdC │ │ │ │ └── tmp │ │ │ └── CompilerIdCXX │ │ │ └── tmp │ │ ├── CMakeTmp │ │ ├── clean_test_results.dir │ │ ├── download_extra_data.dir │ │ ├── doxygen.dir │ │ ├── run_tests.dir │ │ └── tests.dir │ ├── atomic_configure │ ├── catkin │ │ └── catkin_generated │ │ └── version │ ├── catkin_generated │ │ ├── installspace │ │ └── stamps │ │ └── Project │ ├── gtest │ │ ├── CMakeFiles │ │ └── googlemock │ │ ├── CMakeFiles │ │ │ ├── gmock.dir │ │ │ │ ├── __ │ │ │ │ │ └── googletest │ │ │ │ │ └── src │ │ │ │ └── src │ │ │ └── gmock_main.dir │ │ │ ├── __ │ │ │ │ └── googletest │ │ │ │ └── src │ │ │ └── src │ │ └── gtest │ │ └── CMakeFiles │ │ ├── gtest.dir │ │ │ └── src │ │ └── gtest_main.dir │ │ └── src │ └── test_results ├── devel │ └── lib └── src
必要なパッケージを追加して、オリジナルのパッケージを作る
cd src catkin_create_pkg ros_pubsubtest roscpp rospy std_msgs
出力結果
Created file ros_pubsubtest/package.xml Created file ros_pubsubtest/CMakeLists.txt Created folder ros_pubsubtest/include/ros_pubsubtest Created folder ros_pubsubtest/src Successfully created files in /home/hogehoge/rospython/src/ros_pubsubtest. Please adjust the values in package.xml.
すると、以下の要はフォルダーが出来上がります
/rospython/src$ tree . . ├── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake └── ros_pubsubtest ├── CMakeLists.txt ├── include │ └── ros_pubsubtest ├── package.xml └── src
最後に、もう一度catkin_makeをrospython内で行うとフォルダの完成です
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- ~~ traversing 1 packages in topological order: -- ~~ - ros_pubsubtest -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- +++ processing catkin package: 'ros_pubsubtest' -- ==> add_subdirectory(ros_pubsubtest)
こんなログが出てきます
pub/sub作成
/rospython/src/ros_pubsubtest/msg/にpubsub.msgというファイルを作り、以下を記述する
int32 arg_x int32 arg_y
14行目ぐらいのfind_packageにmessage_generation
を追加
51行目ぐらいのadd_message_filesをコメント解除し、pubsub.msg
を追加
73行目ぐらいのgenerate_messagesをすべてコメント解除
107行目ぐらいのcatkin_packageのLIBRARIES ros_pubsubtest
, CATKIN_DEPENDS roscpp rospy std_msgs
, DEPENDS system_lib
をコメント解除
rospythonに戻って、catkin_makeを実行すると
Base path: /home/hogehoge/rospython Source space: /home/hogehoge/rospython/src Build space: /home/hogehoge/rospython/build Devel space: /home/hogehoge/rospython/devel Install space: /home/hogehoge/rospython/install #### #### Running command: "make cmake_check_build_system" in "/home/hogehoge/rospython/build" #### -- Using CATKIN_DEVEL_PREFIX: /home/hogehoge/rospython/devel -- Using CMAKE_PREFIX_PATH: /opt/ros/melodic -- This workspace overlays: /opt/ros/melodic -- Found PythonInterp: /usr/bin/python2 (found suitable version "2.7.17", minimum required is "2") -- Using PYTHON_EXECUTABLE: /usr/bin/python2 -- Using Debian Python package layout -- Using empy: /usr/bin/empy -- Using CATKIN_ENABLE_TESTING: ON -- Call enable_testing() -- Using CATKIN_TEST_RESULTS_DIR: /home/hogehoge/rospython/build/test_results -- Found gtest sources under '/usr/src/googletest': gtests will be built -- Found gmock sources under '/usr/src/googletest': gmock will be built -- Found PythonInterp: /usr/bin/python2 (found version "2.7.17") -- Using Python nosetests: /usr/bin/nosetests-2.7 -- catkin 0.7.23 -- BUILD_SHARED_LIBS is on -- BUILD_SHARED_LIBS is on -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- ~~ traversing 1 packages in topological order: -- ~~ - ros_pubsubtest -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- +++ processing catkin package: 'ros_pubsubtest' -- ==> add_subdirectory(ros_pubsubtest) -- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy -- ros_pubsubtest: 1 messages, 0 services CMake Warning at /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:166 (message): catkin_package() DEPENDS on 'system_lib' but neither 'system_lib_INCLUDE_DIRS' nor 'system_lib_LIBRARIES' is defined. Call Stack (most recent call first): /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package) ros_pubsubtest/CMakeLists.txt:107 (catkin_package) -- Configuring done -- Generating done -- Build files have been written to: /home/hogehoge/rospython/build #### #### Running command: "make -j8 -l8" in "/home/hogehoge/rospython/build" #### Scanning dependencies of target std_msgs_generate_messages_eus Scanning dependencies of target _ros_pubsubtest_generate_messages_check_deps_pubsub Scanning dependencies of target std_msgs_generate_messages_nodejs Scanning dependencies of target std_msgs_generate_messages_py Scanning dependencies of target std_msgs_generate_messages_lisp Scanning dependencies of target std_msgs_generate_messages_cpp [ 0%] Built target std_msgs_generate_messages_eus [ 0%] Built target std_msgs_generate_messages_nodejs [ 0%] Built target std_msgs_generate_messages_py [ 0%] Built target std_msgs_generate_messages_cpp [ 0%] Built target std_msgs_generate_messages_lisp [ 0%] Built target _ros_pubsubtest_generate_messages_check_deps_pubsub Scanning dependencies of target ros_pubsubtest_generate_messages_eus Scanning dependencies of target ros_pubsubtest_generate_messages_py Scanning dependencies of target ros_pubsubtest_generate_messages_nodejs Scanning dependencies of target ros_pubsubtest_generate_messages_cpp Scanning dependencies of target ros_pubsubtest_generate_messages_lisp [ 14%] Generating EusLisp code from ros_pubsubtest/pubsub.msg [ 28%] Generating Python from MSG ros_pubsubtest/pubsub [ 57%] Generating EusLisp manifest code for ros_pubsubtest [ 57%] Generating Javascript code from ros_pubsubtest/pubsub.msg [ 71%] Generating C++ code from ros_pubsubtest/pubsub.msg [ 85%] Generating Lisp code from ros_pubsubtest/pubsub.msg [ 85%] Built target ros_pubsubtest_generate_messages_nodejs [ 85%] Built target ros_pubsubtest_generate_messages_lisp [ 85%] Built target ros_pubsubtest_generate_messages_cpp [100%] Generating Python msg __init__.py for ros_pubsubtest [100%] Built target ros_pubsubtest_generate_messages_py [100%] Built target ros_pubsubtest_generate_messages_eus Scanning dependencies of target ros_pubsubtest_generate_messages [100%] Built target ros_pubsubtest_generate_messages
というログが出る
次に、pub/subをするpythonコードを作成する
ros_pubsubtestフォルダ内に、scriptフォルダを作成し、その中にコードを作る
publish.py
#! /usr/bin/python # -*- cording: utf-8 -*- import rospy from ros_pubsubtest.msg import pubsub def pub(): rospy.init_node('pub', anonymous=True) pub = rospy.Publisher('input_data', pubsub, queue_size=100) r = rospy.Rate(10) para_x = 0 para_y = 2 msg = pubsub() while not rospy.is_shutdown(): msg.arg_x = para_x msg.arg_y = para_y pub.publish(msg) print "published arg_x=%d arg_y=%d"%(msg.arg_x, msg.arg_y) para_x += 1 para_y += 1 r.sleep() if __name__=='__main__': try: pub() except rospy.ROSInterruptException: pass
subscribe.py
#! /usr/bin/python # -*- coding: utf-8 -*- import rospy from ros_pubsubtest.msg import pubsub def callback(data): print data.arg_x + data.arg_y def sub(): rospy.init_node('sub', anonymous = True) rospy.Subscriber('input_data', pubsub, callback) rospy.spin() if __name__ == '__main__': sub()
~/rospython/でcatkin_makeを実行
Base path: /home/hogehoge/rospython Source space: /home/hogehoge/rospython/src Build space: /home/hogehoge/rospython/build Devel space: /home/hogehoge/rospython/devel Install space: /home/hogehoge/rospython/install #### #### Running command: "make cmake_check_build_system" in "/home/hogehoge/rospython/build" #### #### #### Running command: "make -j8 -l8" in "/home/hogehoge/rospython/build" #### [ 0%] Built target std_msgs_generate_messages_eus [ 0%] Built target std_msgs_generate_messages_py [ 0%] Built target std_msgs_generate_messages_nodejs [ 0%] Built target std_msgs_generate_messages_cpp [ 0%] Built target std_msgs_generate_messages_lisp [ 0%] Built target _ros_pubsubtest_generate_messages_check_deps_pubsub [ 42%] Built target ros_pubsubtest_generate_messages_eus [ 57%] Built target ros_pubsubtest_generate_messages_py [ 85%] Built target ros_pubsubtest_generate_messages_nodejs [ 85%] Built target ros_pubsubtest_generate_messages_cpp [100%] Built target ros_pubsubtest_generate_messages_lisp [100%] Built target ros_pubsubtest_generate_messages
ビルドが完了したので実行してみる
terminal1
cd ~/rospython; source devel/setup.bash roscore
無事にroscore起動
terminal2
cd ~/rospython; source devel/setup.bash rosrun ros_pubsubtest publish.py
エラーが出る
[rosrun] Couldn't find executable named publish.py below /home/hogehoge/rospython/src/ros_pubsubtest [rosrun] Found the following, but they're either not files, [rosrun] or not executable: [rosrun] /home/hogehoge/rospython/src/ros_pubsubtest/script/publish.py
長くなったので、エラー解析は次回ということで。。。
点群データの平面推定_part3
やること
- 平面の導出
- RANSACの勉強
前回の記事
RANSACの勉強
前回は理想的な点群に対して、最小二乗平面を推定した。 今回は、ノイズのあるデータを考える。
ノイズデータの平面推定
前回のコードに対してノイズ成分を付加する
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D %matplotlib inline A = 0; B = 0; C = -1 ; D = 1 points = [] cnt = 0 for x in np.arange(0, 10, 0.5): for y in np.arange(0, 10, 0.5): for z in np.arange(0, 10, 0.5): if(abs(A*x + B*y + C*z + D) < 1e-8): points.append([x, y, z]) if((x+y+z) == 15): points.append([x, y, z*1000]) cnt+=1 points = np.asarray(points).T fig = plt.figure() ax = Axes3D(fig) ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") ax.scatter3D(points[0],points[1],points[2]) plt.show()
prePoints = np.copy(points) points = points.T vecB = -points[:,2] points[:,2] = 1 dim = np.dot(points.T, points) vec = np.dot(vecB, points) ans = np.dot(np.linalg.inv(dim), vec) A = ans[0]; B = ans[1]; C = ans[2] xmesh, ymesh = np.meshgrid(np.linspace(0, 10, 20), np.linspace(0, 10, 20)) print(xmesh.shape, ymesh.shape) zmesh = (C + A * xmesh.ravel() + B * ymesh.ravel()).reshape(xmesh.shape) fig = plt.figure() ax = Axes3D(fig) ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") from matplotlib.ticker import ScalarFormatter ax.zaxis.set_major_formatter(ScalarFormatter(useMathText=True)) ax.ticklabel_format(style="sci", axis="z",scilimits=(0,0)) ax.scatter(prePoints[0],prePoints[1],prePoints[2]) ax.plot_wireframe(xmesh, ymesh, zmesh, color='r')
このように、ノイズ成分の影響で平面推定にずれが生じる このノイズ成分を除去するためにRandom Sample Consensus(RANSAC)を使う
RANSAC
前回の記事では、Open3dを使った平面推定を行ったが、その際にRANSACによるノイズ除去が実行されていた。
RANSACとは、簡単に言うと以下の処理をする
- すべての点群データから、モデル導出に必要な数だけランダムに点群を選ぶ
- 直線なら2点
- 平面なら3点
- 最小二乗法などで、モデル推定(モデルパラメータ導出)
- 直線なら直線の方程式がモデルになる
- 平面なら平面の方程式がモデルになる
- 推定したモデルに対して、点群情報を入力し、実値とモデルを使った推定値の差を取る
- 差が閾値以下ならモデルにフィットする点、閾値以上なら外れ値として定義
- フィットする点が閾値以上集まったら、推定モデルは正しいモデルの候補の一つとする
- 1.~5.を任意の数だけ繰り返し、モデルの候補を作る
- モデルの候補から最も良いモデルを選ぶ
以上が、RANSACのイメージである
実行したコードを以下に示す
def fit_plane(samples): if(len(samples) < 3): print("error: The number of samples is small.") return 0 vecB = -samples[:,2] samples[:,2] = 1 dim = np.dot(samples.T, samples) print("dim") print(dim) vec = np.dot(vecB, samples) print("vec") print(vec) print("inv") print(np.linalg.inv(dim)) ans = np.dot(np.linalg.inv(dim), vec) return ans def check_outlier(coeff, p): return np.abs((coeff[0]*p[0]+coeff[1]*p[1]+coeff[2]) - (-p[2])) def ransac(data, n=3, k=100, t=2.0, d=300): good_models = [] good_model_errors = [] iterations = 0 while iterations < k: sample = data[np.random.choice(len(data), n, False)] coeff = fit_plane(sample) # print(coeff) inliers = [] for points in data: if (points == sample).all(1).any(): continue if check_outlier(coeff, points) > t: continue else: inliers.append(points) # print(len(inliers)) if len(inliers) > d: error_array = [] for points in data: error_array.append(check_outlier(coeff, points)) error_array = np.asarray(error_array) ave_error = np.mean(error_array) good_models.append(coeff) good_model_errors.append(ave_error) iterations += 1 best_model_index = np.argmin(good_model_errors) return good_models[best_model_index] a, b, c = ransac(prePoints.T) print(a, b, c)
実行結果(ax+by+c = -z)は、
a = -1.1102230246251565e-16 b = 0.0 c = -1.0
となる。
今回の方程式の解き方では、逆行列が生成できないケースが出てくる(singular matrix)