1. 案例一:创建ROS工作空间
首先,我们需要创建一个ROS工作空间,这是进行ROS编程的基础。下面是创建ROS工作空间的步骤:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make
source devel/setup.bash
这个工作空间将会存放所有的ROS项目和依赖。
2. 案例二:编写第一个节点
在ROS中,节点(Node)是程序的基本单元。下面是一个简单的节点例子,用于打印“Hello, ROS!”:
#include <ros/ros.h>
int main(int argc, char **argv) {
ros::init(argc, argv, "hello_node");
ros::NodeHandle nh;
ROS_INFO("Hello, ROS!");
return 0;
}
将上述代码保存为hello_node.cpp,然后编译和运行:
cd ~/catkin_ws/src
catkin_make
cd ~/catkin_ws/devel/
rosrun hello_node hello_node
3. 案例三:订阅话题
在机器人编程中,订阅话题是获取信息的重要方式。以下是一个订阅/chatter话题的节点例子:
#include <ros/ros.h>
#include <std_msgs/String.h>
void chatterCallback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv) {
ros::init(argc, argv, "listener");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("chatter", 1000, chatterCallback);
ros::spin();
return 0;
}
4. 案例四:发布话题
发布话题是向其他节点发送信息的方式。以下是一个发布/chatter话题的节点例子:
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>
void talker(const int& loop_count) {
ros::NodeHandle nh;
ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter", 1000);
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << loop_count;
msg.data = ss.str();
chatter_pub.publish(msg);
}
int main(int argc, char **argv) {
ros::init(argc, argv, "talker");
ros::NodeHandle nh;
int loop_count = 0;
while (loop_count < 10) {
talker(loop_count);
loop_count++;
ros::Duration(1.0).sleep();
}
return 0;
}
5. 案例五:服务调用
服务(Service)是ROS中另一种通信机制。以下是一个简单的服务例子:
#include <ros/ros.h>
#include <std_srvs/Empty.h>
bool my_service_call(std_srvs::Empty::Request &req,
std_srvs::Empty::Response &res)
{
ROS_INFO("service called");
return true;
}
int main(int argc, char **argv) {
ros::init(argc, argv, "service_server");
ros::NodeHandle nh;
ros::ServiceServer service = nh.advertiseService("my_service", my_service_call);
ros::spin();
return 0;
}
6. 案例六:参数服务器
参数服务器(Parameter Server)用于存储和检索ROS参数。以下是一个例子:
#include <ros/ros.h>
int main(int argc, char **argv) {
ros::init(argc, argv, "parameter_example");
ros::NodeHandle nh;
int num;
nh.param("my_int", num, 0);
ROS_INFO("The value of my_int is %d", num);
return 0;
}
7. 案例七:动态重新配置
动态重新配置(Dynamic Reconfigure)允许在运行时修改节点参数。以下是一个简单的动态重新配置节点:
#include <dynamic_reconfigure/server.h>
#include <example_ros/dynamic_reconfigureConfig.h>
void callback(example_ros::dynamic_reconfigureConfig &config, uint32_t level) {
ROS_INFO("Reconfigure Request: %d", config.x);
}
int main(int argc, char **argv) {
ros::init(argc, argv, "dynamic_reconfigure_server");
dynamic_reconfigure::Server<example_ros::dynamic_reconfigureConfig> server;
dynamic_reconfigure::Server<example_ros::dynamic_reconfigureConfig>::CallbackType f;
f = boost::bind(&callback, _1, _2);
server.setCallback(f);
ros::spin();
return 0;
}
8. 案例八:TF变换
在机器人编程中,变换(Transform)非常重要。以下是一个使用TF库的节点例子:
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
int main(int argc, char **argv) {
ros::init(argc, argv, "tf_broadcaster");
tf::TransformBroadcaster broadcaster;
while (ros::ok()) {
tf::Transform transform;
transform.setOrigin(tf::Vector3(0.0, 0.0, 0.0));
transform.setRotation(tf::Quaternion(0, 0, 0, 1));
broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", "base_link"));
ros::Duration(1.0).sleep();
}
return 0;
}
9. 案例九:Gazebo仿真
使用Gazebo进行仿真是一个非常好的实践。以下是一个在Gazebo中设置简单的仿真场景的例子:
from gazebo_msgs.srv import SpawnModel
import rospy
def spawn_model(model_name, pose):
rospy.wait_for_service('gazebo/spawn_urdf_model')
try:
spawn_urdf = rospy.ServiceProxy('gazebo/spawn_urdf_model', SpawnModel)
resp = spawn_urdf(model_name, "", "", pose, "world")
return resp.success
except rospy.ServiceException as e:
rospy.logerr("Service call failed: %s" % e)
if __name__ == '__main__':
rospy.init_node('spawn_model')
model_name = "robot.urdf"
pose = tf.transformations.translation_matrix(tf.transformations.quaternion_from_euler(0, 0, 0))
if spawn_model(model_name, pose):
rospy.loginfo("Model spawned successfully")
else:
rospy.logerr("Failed to spawn model")
10. 案例十:多机器人协同
在多机器人协同中,节点通信和协调非常重要。以下是一个简单的多机器人协同节点例子:
#include <ros/ros.h>
#include <std_msgs/String.h>
void callback(const std_msgs::String::ConstPtr& msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv) {
ros::init(argc, argv, "robot_1");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("topic", 1000, callback);
ros::spin();
return 0;
}
通过这些案例,你将能够快速掌握ROS编程的基础知识,并在此基础上进行更深入的探索。记住,实践是学习的关键,不断尝试和调试,你会越来越熟练。祝你学习愉快!