1. ワークスペースの作成と機能パッケージ
1.1 ワークスペースとは
ワークスペースは、ROS開発のためのディレクトリ構造です。IDEにおけるプロジェクトフォルダに相当し、以下のサブディレクトリを持ちます:
- src: ソースコード領域。機能パッケージのソースコードを配置
- build: ビルド領域。コンパイル中に生成される中間ファイル(通常は直接操作しない)
- devel: 開発領域。開発中に生成される実行可能ファイルやライブラリを配置
- install: インストール領域。最終的に生成された実行可能ファイルを配置
1.2 ワークスペース作成手順
以下のコマンドでワークスペースを作成します:
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/src
$ catkin_init_workspace
注意: mkdir -pはディレクトリを再帰的に作成します。初期化が完了すると、CMakeLists.txtが自動生成されます。
次にワークスペースをビルドします:
$ cd ~/catkin_ws/
$ catkin_make
この時点ではbuild、devel、srcの3つのフォルダが存在します。installフォルダを追加するには:
$ catkin_make install
1.3 環境変数の設定
システムがワークスペースを認識できるようにするため、環境変数を設定します:
$ source devel/setup.bash
設定を確認するには:
$ echo $ROS_PACKAGE_PATH
1.4 機能パッケージの作成
機能パッケージを作成する基本的なコマンド構文は次の通りです:
$ catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
具体例:
$ cd ~/catkin_ws/src
$ catkin_create_pkg test_pkg std_msgs rospy roscpp
このコマンドは、test_pkgというパッケージを作成し、std_msgs(標準メッセージライブラリ)、rospy(Python依存)、roscpp(C++依存)を依存関係として設定します。
パッケージをビルド:
$ cd ~/catkin_ws
$ catkin_make
注意事項: 同一ワークスペース内で同名パッケージは作成できませんが、異なるワークスペースでは同名が許可されます。
パッケージ内の構成ファイル:
- include: ヘッダファイル
- src: ソースコード
- CMakeLists.txt: コンパイルルールを記述
- package.xml: XML形式でパッケージ情報を記述
2. Publisherの実装
2.1 話題モデル
ROSの通信モデルでは、Publisherが特定の話題(Topic)にメッセージを送信します。
2.2 機能パッケージ作成
$ cd ~/catkin_ws/src
$ catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim
2.3 Publisherコード作成
Publisher実装の基本手順:
- ROSノードを初期化
- ROS Masterに話題名とメッセージ型を登録
- メッセージデータを作成
- 一定周期でメッセージをパブリッシュ
C++コード例:
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char **argv) {
ros::init(argc, argv, "velocity_publisher");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
ros::Rate rate(10);
while (ros::ok()) {
geometry_msgs::Twist msg;
msg.linear.x = 0.5;
msg.angular.z = 0.2;
pub.publish(msg);
ROS_INFO("Published velocity: [%.2f m/s, %.2f rad/s]", msg.linear.x, msg.angular.z);
rate.sleep();
}
return 0;
}
Pythonコード例:
#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
def publisher():
rospy.init_node('velocity_publisher', anonymous=True)
pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
rate = rospy.Rate(10)
while not rospy.is_shutdown():
msg = Twist()
msg.linear.x = 0.5
msg.angular.z = 0.2
pub.publish(msg)
rospy.loginfo("Published velocity: [%.2f m/s, %.2f rad/s]", msg.linear.x, msg.angular.z)
rate.sleep()
if __name__ == '__main__':
try:
publisher()
except rospy.ROSInterruptException:
pass
2.4 CMakeLists.txtの設定
以下の行をCMakeLists.txtに追加します:
add_executable(velocity_publisher src/velocity_publisher.cpp)
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})
2.5 ビルドと実行
$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_topic velocity_publisher
3. Subscriberの実装
3.1 実装手順
- ROSノードを初期化
- 購読する話題を指定し、コールバック関数を登録
- メッセージ受信時に呼び出されるコールバック関数内で処理を実行
3.2 Subscriberコード作成
C++コード例:
#include <ros/ros.h>
#include <turtlesim/Pose.h>
void callback(const turtlesim::Pose::ConstPtr& msg) {
ROS_INFO("Pose: x=%.6f, y=%.6f", msg->x, msg->y);
}
int main(int argc, char **argv) {
ros::init(argc, argv, "pose_subscriber");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("/turtle1/pose", 10, callback);
ros::spin();
return 0;
}
Pythonコード例:
#!/usr/bin/env python
import rospy
from turtlesim.msg import Pose
def callback(msg):
rospy.loginfo("Pose: x=%.6f, y=%.6f", msg.x, msg.y)
def subscriber():
rospy.init_node('pose_subscriber', anonymous=True)
rospy.Subscriber("/turtle1/pose", Pose, callback)
rospy.spin()
if __name__ == '__main__':
subscriber()
3.3 コンパイル設定
CMakeLists.txtに以下を追加:
add_executable(pose_subscriber src/pose_subscriber.cpp)
target_link_libraries(pose_subscriber ${catkin_LIBRARIES})
3.4 ビルドと実行
$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun turtlesim turtlesim_node
$ rosrun learning_topic pose_subscriber