簡単ではあるが、地味に記事がない内容だったので、まとめておく
動作環境
項目 | 説明 |
---|---|
OS | Ubuntu 20.04.05 LTS |
ROSディストリビューション | noetic |
Flask | 2.2.2 |
Python3 | 3.9.14 |
ROSでflaskを使う
参考サイト
手順
$ catkin_make
$ source devel/setup.bash
を使用した後、新たなプロジェクトとして
$ cd src
$ catkin_create_pkg ros_flask_test
として、ros_flask_testというプロジェクトを作成。
ros_flask_test内は、(例えばVisual Studio Codeを使うとして)
以下のフォルダ構成とする
flask_server.pyはinit_nodeとしてros_flask_testを、
ローカルホストでポート番号を11000として使うとすると
import rospy
import threading
from flask import Flask
app = Flask(__name__)
threading.Thread(target=lambda: rospy.init_node('ros_flask_test', disable_signals=True)).start()
@app.route('/')
def root_page():
return "Hello World"
if __name__ == '__main__':
app.run(debug=True, port=11000)
このプログラムでは使わないが、some_page.htmlとして
<html>
<body>
Test Page
</body>
</html>
CMakelists.txt
cmake_minimum_required(VERSION 3.0.2)
project(ros_flask_test)
find_package(catkin REQUIRED)
catkin_package(
)
include_directories(
)
catkin_install_python(
PROGRAMS
scripts/flask_server.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
として、プロジェクトより上のフォルダに移動して
$ catkin_make
とすることで、ビルド完了。
$ rosrun ros_flask_test flask_server.py
を実行することで、
ちゃんとサーバが実行され、
Hello Worldが表示された。
この方法はWeb APIの方法に近いと思われる。
ROS(開発環境)でrender_templateを使いたい
上手く行かない例
素直に、先程のflask_server.pyを拡張する。
import rospy
import threading
from flask import Flask, render_template
app = Flask(__name__)
print(app.root_path) # ここをチェックする
threading.Thread(target=lambda: rospy.init_node('ros_flask_test', disable_signals=True)).start()
@app.route('/')
def root_page():
return "Hello World"
@app.route('/some_page')
def some_page():
return render_template("some_page.html")
if __name__ == '__main__':
app.run(debug=True, port=11000)
つまり、
http://127.0.0.1:5000/some_page
を開けば、some_page.htmlがレンダリングされて表示されるはず。シンプルな内容だ。
ところが、これを実行すると
TemplateNotFoundエラーが出る。
まあ、通常のflaskであれば、このディレクトリ構成で良いのだが、
要はディレクトリが良くないわけだ。
改善
というわけで、# ここをチェックするの行で出てきたprintで何が出てきたかを調べると、
〜(rospyを実行しているディレクトリ)/devel/lib/ros_flask_test
となっていることが分かる。
そして、確かによく見てみると
devel/libフォルダにもpyファイルがあるのだ。
ただここは開発環境用の自動スクリプトであるから、
ここを編集して、というわけにはいかない。
そこで、flaskのroot_pathを常に変えられるように実行する。
ros_flank_testのフォルダの下にlaunchフォルダを作成し、
local_html_render.launchというファイルをとりあえず作る(何でも良い)。
<launch>
<node pkg="ros_flask_test" type="flask_server.py"
name="flask_server" respawn="true" output="screen">
<param name="flask_root_path" value="$(find ros_flask_test)/scripts/" />
</node>
</launch>
とし、
flask_server.pyを
import rospy
import threading
from flask import Flask, render_template
import rosparam
root_path = rosparam.get_param("/flask_server/flask_root_path")
if root_path != "":
app = Flask(__name__, root_path=root_path)
else:
app = Flask(__name__)
threading.Thread(target=lambda: rospy.init_node('ros_flask_test', disable_signals=True)).start()
@app.route('/')
def root_page():
return "Hello World"
@app.route('/some_page')
def some_page():
return render_template("some_page.html")
if __name__ == '__main__':
app.run(debug=True, port=11000)
という風に書き換える。つまり、launchファイルを先に用意しておいて、ローカルファイルのtemplatesフォルダをバインド出来るようにするのだ。
そして、実行方法はrosrunではなく、roslaunchを使用して
$ roslaunch ros_flask_test local_html_render.launch
とすることで、きちんと実行されたことを確認した。
なお、上記のプログラムの場合、もしlocalフォルダを指定しない場合は、
のvalueを"" とすれば良い。