自作ノード
このレッスンでは、ROS2 Humble環境において、Pythonで簡単な自作ノードを作成し、移動ロボットを制御する基本的なプログラムの作り方を学びます。ノードは /kachaka/manual_control/cmd_vel
トピックに対して geometry_msgs/Twist
型のメッセージを発行します。
1. プログラムの概要
- 移動ロボットを簡単なフィードフォワード制御で制御します
- 基本的な動作(前進、停止、回転)を順番に実行します
2. 前提条件
- ROS2 Humble がインストール済み
- Python3 が利用可能
- ROS2ワークスペース(例:
~/ros2_ws
)がセットアップ済み
必要なパッケージ
rclpy
: ROS2のPythonクライアントライブラリgeometry_msgs
: 位置や速度などの幾何学メッセージを扱うためのパッケージ
3. パッケージの作成
まず、ROS2ワークスペースの src
ディレクトリ内でパッケージを作成します。--node-name
オプションを使用して、ノード名を指定します。
cd ./ros2_ws/src
ros2 pkg create --build-type ament_python kachaka_simple_control --dependencies rclpy geometry_msgs --node-name kachaka_simple_control
このコマンドにより、以下の構造のパッケージが生成されます:
kachaka_simple_control/
├── resource/
│ └── kachaka_simple_control
├── kachaka_simple_control/
│ ├── __init__.py
│ └── kachaka_simple_control.py
├── test/
├── package.xml
└── setup.py
4. ノードの実装
kachaka_simple_control
パッケージ内の kachaka_simple_control
ディレクトリに、以下の内容の kachaka_simple_control.py
ファイルを作成します。
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
from rclpy.duration import Duration
class KachakaSimpleControl(Node):
def __init__(self):
super().__init__('kachaka_simple_control')
# Create a Publisher that sends Twist type messages to the /cmd_vel topic
self.publisher = self.create_publisher(Twist, '/kachaka/manual_control/cmd_vel', 10)
self.get_logger().info('Robot control node has started')
def move_robot(self, linear_x, angular_z, duration):
"""
Move the robot at specified speed and time
Parameters:
linear_x: Forward speed [m/s]
angular_z: Rotation speed [rad/s]
duration: Movement duration [seconds]
"""
# Create velocity command message
vel = Twist()
vel.linear.x = linear_x
vel.angular.z = angular_z
# Calculate end time
end_time = self.get_clock().now() + Duration(seconds=duration)
# Continue publishing velocity commands until the specified time
while self.get_clock().now() < end_time:
self.publisher.publish(vel)
rclpy.spin_once(self, timeout_sec=0.1) # Wait for 0.1 seconds
# Stop after the movement is complete
self.stop_robot()
self.get_logger().info(f'Movement completed: Forward={linear_x}, Rotation={angular_z}, Time={duration} seconds')
def stop_robot(self):
"""Stop the robot"""
vel = Twist()
vel.linear.x = 0.0
vel.angular.z = 0.0
self.publisher.publish(vel)
self.get_logger().info('Robot has stopped')
def main(args=None):
rclpy.init(args=args)
robot_control = KachakaSimpleControl()
try:
# Execute the following movement sequence
robot_control.move_robot(0.0, 0.0, 1.0) # Stop
robot_control.move_robot(0.1, 0.0, 1.0) # Forward
robot_control.move_robot(0.0, 0.0, 1.0) # Stop
robot_control.move_robot(0.0, 0.5, 2.0) # Rotate left
robot_control.move_robot(0.0, 0.0, 1.0) # Stop
robot_control.move_robot(0.0, -0.5, 2.0) # Rotate right
robot_control.move_robot(0.0, 0.0, 1.0) # Stop
except KeyboardInterrupt:
robot_control.get_logger().info('Program was interrupted')
finally:
robot_control.stop_robot()
robot_control.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
5. setup.py の編集
–node-nameを使用していない場合はパッケージルートにある setup.py
のエントリーポイントを設定します。
entry_points={
'console_scripts': [
'kachaka_simple_control = kachaka_simple_control.kachaka_simple_control:main'
],
},
6. パッケージのビルドと実行
パッケージのビルド
cd ~/ros2_ws
colcon build --packages-select kachaka_simple_control
環境設定の読み込み
source install/setup.bash
ノードの実行
ros2 run kachaka_simple_control kachaka_simple_control
7. コードの説明
クラスとメソッド
KachakaSimpleControl
: メインのノードクラス__init__
: ノードの初期化とパブリッシャーの設定move_robot
: 指定された速度と時間でロボットを動かすメソッドstop_robot
: ロボットを停止させるメソッド
制御パラメータ
linear_x
: 直進速度 [m/s]- 正の値: 前進
- 負の値: 後退
- 0: 停止
angular_z
: 回転速度 [rad/s]- 正の値: 左回転
- 負の値: 右回転
- 0: 回転なし
duration
: 動作を継続する時間 [秒]
動作シーケンス
プログラムは以下の動作シーケンスを実行します:
- 停止 (1.0秒)
- 前進 (1.0秒)
- 停止 (1.0秒)
- 左回転 (2.0秒)
- 停止 (1.0秒)
- 右回転 (2.0秒)
- 停止 (1.0秒)
8. ROS2の基本概念の説明
ノード(Node)
ノードは、ROS2システムの基本的な実行単位です。各ノードは特定の機能を持ち、他のノードと通信します。この例では、KachakaSimpleControl
クラスがノードとして機能します。
トピック(Topic)
トピックは、ノード間でメッセージをやり取りするための通信チャネルです。この例では、/kachaka/manual_control/cmd_vel
トピックを使用して、ロボットへの速度指令を送信します。
メッセージ(Message)
メッセージは、トピックを通じて送信されるデータの形式を定義します。この例では、geometry_msgs/Twist
型のメッセージを使用して、ロボットの線形速度と角速度を指定します。
パブリッシャー(Publisher)
パブリッシャーは、特定のトピックにメッセージを発行(送信)するためのオブジェクトです。この例では、self.publisher
が/kachaka/manual_control/cmd_vel
トピックに速度指令を発行します。
フィードフォワード制御
フィードフォワード制御は、事前に定義された指令を実行する制御方式です。この例では、速度と時間を指定して、ロボットの動作を制御します。センサーフィードバックを使用せず、事前に決められた動作を実行します。