また無限に時間を溶かしてしまいました
概要
とある試みのため,WSLではなくWindows上でROS 2を入れて動かしたかったんですが,
Pythonのノードを立ち上げようとするとNoModuleError
が出て立ち上がりませんでした.
ごちょごちょやってる間に動くようになったので備忘録を兼ねて解決方法を書きます
(Windows11で,と書いてますがたぶんWim10でも同様だと思います)
##環境
- AMD Ryzen 7 Pro 4750U
- Windows 11 ※1
- Visual Studio 2019 Community
- ROS 2 foxy ※2
- Python 3.8.3
※1: WSLgを使いたくて,プレビュー版のWin11を入れて試しています.Win10でも同様になると思っていますが未検証です
※2: ROS 2のインストールはhttps://docs.ros.org/en/foxy/Installation/Windows-Install-Binary.html#downloading-ros-2にあるとおり,githubのreleasesからzipをダウンロード・展開して行いました
起こった現象
注意:以下コマンドの入出力はVS2019 Developer Command Promptで行ってます.
- 以下の記事の通りに,Pythonで実装するパッケージを作成しました
ROS2で自分で作成したpythonプログラムを動かす方法
※ros-windowsはC直下,(あまりよくないと思いますが)ros2_wsはros-windows内に作りました -
ros2 run my_python my_listener
したところ,以下のエラーが出てノードが立ち上がりませんでした
(talker
も同様)
C:\ros2-windows\ros2_ws>ros2 run my_python my_listener
Traceback (most recent call last):
File "C:\ros2-windows\ros2_ws\install\my_python\lib\my_python\my_listener-script.py", line 33, in <module>
sys.exit(load_entry_point('my-python==0.0.0', 'console_scripts', 'my_listener')())
File "C:\ros2-windows\ros2_ws\install\my_python\lib\my_python\my_listener-script.py", line 25, in importlib_load_entry_point
return next(matches).load()
File "c:\python38\lib\importlib\metadata.py", line 77, in load
module = import_module(match.group('module'))
File "c:\python38\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
File "<frozen importlib._bootstrap>", line 991, in _find_and_load
File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 783, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "C:\ros2-windows\ros2_ws\install\my_python\Lib\site-packages\python_programs\listener.py", line 2, in <module>
from rclpy.node import Node
File "C:\ros2-windows\Lib\site-packages\rclpy\node.py", line 41, in <module>
from rclpy.client import Client
File "C:\ros2-windows\Lib\site-packages\rclpy\client.py", line 22, in <module>
from rclpy.impl.implementation_singleton import rclpy_implementation as _rclpy
File "C:\ros2-windows\Lib\site-packages\rclpy\impl\implementation_singleton.py", line 31, in <module>
rclpy_implementation = _import('._rclpy')
File "C:\ros2-windows\Lib\site-packages\rclpy\impl\__init__.py", line 28, in _import
return importlib.import_module(name, package='rclpy')
File "c:\python38\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
ModuleNotFoundError: No module named 'rclpy._rclpy'
The C extension 'C:\ros2-windows\Lib\site-packages\rclpy\_rclpy.pyd' isn't present on the system. Please refer to 'https://index.ros.org/doc/ros2/Troubleshooting/Installation-Troubleshooting/#import-failing-without-library-present-on-the-system' for possible solutions
- rclpyは
C:\ros2-windows\Lib\site-packages\rclpy
を参照しており,同パスはPYTHONPATH
にも登録されていました -
C:\ros2-windows\Lib\site-packages\rclpy
には_rclpy.lib
と_rclpy_d.pyd
があるものの,_rclpy.pyd
はありませんでした
結論
- Pythonは3.8系(公式ページでは3.8.3が示されています)を使う必要がありました
- 通常のPython(python.exe)ではなく,**Windows デバッグ版(python_d.exe)**を使う必要がありました
- デバッグ版Pythonを使う場合,
numpy
など一部モジュールはそれ用にインストールしなおす必要がありました - デバッグ版Pythonを使う場合,colcon buildの時にそのためのコマンドを使う必要がありました
解決策
Pythonインストール
上述のとおり,デバッグ版のpython_d.exe
を使う必要があります.
この実行ファイルは,インストールの時にオプションで選択しないと入らないようになっています.
Python公式サイト> Downloads > WindowsからPython3.8.3のインストーラをダウンロード・実行し,以下の画像のようにAdvanced Optionsからdebugging symbols
とdebug binaries
を入れてやるとよいです.
なお,ROS 2はPythonのインストールフォルダがC:\Python38\
であると想定していますが,インストーラのデフォルト設定ではProgram Files
以下になっているので,そこも修正が必要です.
また,choco
やanaconda
等からすでにPythonをインストールしている場合,インストーラが動作しません.
(私はchoco
で入れたpythonをuninstallしてインストーラから入れなおしました)
インストールがうまくて来ていると,Pythonのインストールフォルダ(C:\Python38
)に,python_d.exe
が存在します.
また,コマンドプロンプトからpython_d
コマンドでPythonの立ち上げが行えます
C:\ros2-windows\ros2_ws>python_d
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:20:16) [MSC v.1925 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Debug版Python向けの環境構築
python_d
を利用する場合に必要な依存パッケージ類ですが,ROS 2ドキュメントのBuilding ROS 2 on Windowsページに記載があります
Extra stuff for Debug mode - Building ROS 2 on Windows, ROS 2 Documentation
このページにあるとおり,chocoを使って依存パッケージをインストールする必要があります.
(なお,インストールには管理者権限が必要です.
choco install -y peazip
choco install -y svn hg
また,pythonパッケージも一部再インストールが必要です
python_d -m pip install --force-reinstall https://github.com/ros2/ros2/releases/download/numpy-archives/numpy-1.18.4-cp38-cp38d-win_amd64.whl
python_d -m pip install --force-reinstall https://github.com/ros2/ros2/releases/download/lxml-archives/lxml-4.5.1-cp38-cp38d-win_amd64.whl
注:AMDのCPUを使用している場合
ここで,僕の環境(AMD)では以下のエラーのためインストールできませんでした.
(Intelの場合どうなるかは未検証です)
C:\ros2-windows\ros2_ws>python_d -m pip install --force-reinstall https://github.com/ros2/ros2/releases/download/numpy-archives/numpy-1.18.4-cp38-cp38d-win_amd64.whl
ERROR: numpy-1.18.4-cp38-cp38d-win_amd64.whl is not a supported wheel on this platform.
pipは.whlファイルのファイル名からバージョンを認識しているようで,次の手順のようにリネームしてやると解決します(ええんやろか)
-
https://github.com/ros2/ros2/releases/download/numpy-archives/numpy-1.18.4-cp38-cp38d-win_amd64.whl
およびhttps://github.com/ros2/ros2/releases/download/lxml-archives/lxml-4.5.1-cp38-cp38d-win_amd64.whl
にアクセスして,.whl
ファイルをダウンロードする - それぞれのファイルについて,
...win_amd64.whl
とあるところを...win32.whl
にリネームする - 通常通り,
python_d -m pip install --force-reinstall <ダウンロードした.whlファイル>
を実行してインストールする
インストールがうまくいけば,エラーが出ずにそれぞれのパッケージをimportできるはずです
C:\ros2-windows\ros2_ws>python_d
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:20:16) [MSC v.1925 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from lxml import etree
>>> import numpy
#何もエラーが出ない
参考:
【Python】pipでwhlファイルをインストールするときのエラー - 俺言語.
numpyインストールで四苦八苦 - Hajime Satoさんのnote記事
パッケージのビルド・実行
あとは,インストールしたpython_d
でパッケージをビルドし,実行します.
Extra stuff for Debug mode - Building ROS 2 on Windows, ROS 2 Documentationにもあるように,python_d
にcolcon
の実行ファイルのパスを与えます.
僕の場合,pythonをC:\Python38
にインストールしていたので,コマンドは以下のようになります.
(なお,すでにcolcon build
でビルドしたものがある場合,--cmake-clean-cache
で消去してから実行する必要があります.)
C:\ros2-windows\ros2_ws>colcon build --cmake-clean-cache #すでにcolcon buildを走らしていた場合
C:\ros2-windows\ros2_ws>python_d C:\Python38\Scripts\colcon.exe build
ビルド後実行してやるとうまく動きました.
C:\ros2-windows\ros2_ws>ros2 run my_python my_talker
[INFO] [1627127739.241812500] [talker]: Publishing: "Hello World: 0"
[INFO] [1627127740.085704200] [talker]: Publishing: "Hello World: 1"
コマンドプロンプトを2つ立ち上げてtalkerとlistenerを同時に実行してみたところ,メッセージの送受信が行われていることも確認できました.めでたしめでたし.
補足
"_rclpy not found"みたいなので調べていると,以下のようにcolcon build
時にオプションをつけるといいよという記述がありました.
ROS2: DebugModuleNotFoundError: No module named ‘rclpy._rclpy’ - ROS Discourse
こんな感じです
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debug
ただ,python_d colcon
した場合とこれとは振る舞いが違うみたいで,僕はこのargsをつけるやり方では_rclpy not found
エラーは解消できませんでした.
python_dを利用してbuildする場合でも,このオプションをつけるとうまくいかなかったです.
ちなみに,--cmake-args
をつけてビルドした場合,同様にcmake-clean-cache
する必要があるのですが,その時にも--camke-args
オプションは必要です.
colcon build --cmake-cache-clean --cmake-args -DCMAKE_BUILD_TYPE=Debug
##おわりに
僕が調べた範囲だと日本語の記事等出てこなくて,結構苦労しました.
ほとんどの人WSLとかDocker使うやろうしWindows上で頑張ってもしゃあないってことですかね
公式ドキュメントのインストールガイドだと,動作確認としてdemo_nodes_py
を用いるんですが,これはpython_d
を使わなくても動いちゃうんですよね.
なので,実はビルドしたPythonパッケージは動かない状態なのに,exampleが通ったので環境構築の時にはそれでオッケーにしちゃって,あとでハマるみたいなことになるじゃないかなと思いました.というかなりました.