ROS学习实验2

一、话题通讯中的发布者和订阅者

1、创建包

打开终端输入

mkdir -p ~/lab2/src && cd ~/lab2/src
catkin_create_pkg learning_communication rospy roscpp std_msgs std_srvs
cd learning_communication && mkdir msg srv

这些操作是在src目录下创建一个learn_communication的文件夹,并在其下创建src、msg、srv文件夹

2、写消息发布者

在src文件下创建string_publisher.cpp文件,并在编写程序:

#include <ros/ros.h>
#include "sstream"
#include "std_msgs/String.h"
int main(int argc, char **argv)
{
// ROS node initialization
ros::init(argc, argv, "string_publisher");
// create node handler
ros::NodeHandle n;
// Create a Publisher, publish a topic named /chatter, topic message type is std_msgs::String.h, queue length is 100
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("/chatter", 100);
// set loop frequency
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world" << count;
msg.data = ss.str();
// Publish message
ROS_INFO("%s",msg.data.c_str());
chatter_pub.publish(msg);
// Loop waiting for the callback function
ros::spinOnce;
// delay based on the loop frequency
loop_rate.sleep();
++count;
}
return 0;
}

3、写消息订阅者

在src文件下创建string_listener.cpp文件,并在编写程序:

#include <ros/ros.h>
#include "std_msgs/String.h"
// call the cakllback function after receive a subscription message
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
// print the received message
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
// ROS node initializ
  ros::init(argc, argv, "string_listener");
// create node handler
  ros::NodeHandle n;
// Create a Subsriber, subscribe the topic /chatte, register callback function chatterCallback
  ros::Subscriber sub = n.subscribe("chatter",1000,chatterCallback);
// Loop waiting for the callback function
  ros::spin();
  return 0;
}

4、修改CMakeList.txt

打开CMakeList.txt文件,找到以下配置项,并做小的修改

include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)

add_executable(string_publisher src/string_publisher.cpp)
target_link_libraries(string_publisher ${catkin_LIBRARIES})

add_executable(string_listener src/string_listener.cpp)
target_link_libraries(string_listener ${catkin_LIBRARIES})

5、运行程序查看结果

1)编译程序

打开终端,输入:

cd ~/lab2
catkin_make

2)运行程序

打开终端并启动roscore

roscore

在另一个终端中启动string_publisher:

source ~/lab2/devel/setup.bash
rosrun learning_communication string_publisher

新建终端,启动string_listener:

source ~/lab2/devel/setup.bash
rosrun learning_communication string_listener

 

二、服务通信中的服务器和客户端

1、定制化服务数据

在srv文件下新建一个Penson.srv文件,并输入:

string name
uint8 age
uint8 sex
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
---
string result

2、编写服务器

在src下创建person_server.cpp

#include <ros/ros.h>
#include "learning_communication/Person.h"
// service callback function, input parameter req, output parameter res
bool personCallback(learning_communication::Person::Request &req,
learning_communication::Person::Response &res)
{
// Display received service
ROS_INFO("Person: name:%s age:%d sex:%d", req.name.c_str(), req.age, req.sex);
// set result data
res.result = "OK";
return true;
}
int main(int argc, char **argv)
{
// ROS node initialize
ros::init(argc, argv, "person_server");
// Create node handler
ros::NodeHandle n;
// create the server for service /show_person, register the callback function personCallback
ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);
// Loop waiting for the callback function

ROS_INFO("Ready to show person informtion.");
ros::spin();
return 0;
}

3、编写客户端

在src创建person_client.cpp

#include <ros/ros.h>
#include "learning_communication/Person.h"
int main(int argc, char** argv)
{
// ROS node initialize
ros::init(argc, argv, "person_client");
// create node handler
ros::NodeHandle node;
// After the server of /show_person shows up, create a client for the service /show_person
ros::service::waitForService("/show_person");
ros::ServiceClient person_client =
node.serviceClient<learning_communication::Person>("/show_person");
// Initialize learning_service::Person data structure
learning_communication::Person srv;
srv.request.name = "Tom";
srv.request.age = 20;
srv.request.sex = learning_communication::Person::Request::male;
// call the service
ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]",
srv.request.name.c_str(), srv.request.age, srv.request.sex);
person_client.call(srv);
// show the result of the service
ROS_INFO("Show person result : %s", srv.response.result.c_str());
return 0;
}

4、修改CMakeList.txt

打开文件做一些修改

1)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  std_srvs
  message_generation
)

2)

add_service_files(
FILES
Person.srv
)

3)

generate_messages(
DEPENDENCIES
std_msgs
)

4)

catkin_package(
CATKIN_DEPENDS roscpp rospy std_msgs std_srvs
)

5)

add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_generate_messages_cpp)
add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_generate_messages_cpp)

 5、运行程序查看结果

1)编译程序

cd ~/lab2
catkin_make

2)运行程序

roscore

在 另一个终端启动person_server:

source ~/lab2/devel/setup.bash
rosrun learning_communication person_server

再新建终端,启动person_client:

source ~/lab3/devel/setup.bash
rosrun learning_communication person_client

得到结果:

 三、参数和参数服务器的使用

1、编写代码来更改海龟的背景颜色

创建src/parameter_config.cpp

#include <string>
#include <ros/ros.h>
#include <std_srvs/Empty.h>
int main(int argc, char **argv)
{
int red, green, blue;
// ROS node initialize
ros::init(argc, argv, "parameter_config");
// create node handler
ros::NodeHandle node;
// get the background color parameters
ros::param::get("/turtlesim/background_r", red);
ros::param::get("/turtlesim/background_g", green);
ros::param::get("/turtlesim/background_b", blue);
ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);
// set the background color parameters
ros::param::set("/turtlesim/background_r", 255);
ros::param::set("/turtlesim/background_g", 60);
ros::param::set("/turtlesim/background_b", 255);
ROS_INFO("Set Backgroud Color[255, 60, 255]");
// get the background color parameters
ros::param::get("/turtlesim/background_r", red);
ros::param::get("/turtlesim/background_g", green);
ros::param::get("/turtlesim/background_b", blue);
ROS_INFO("Re-get Backgroud Color[%d, %d, %d]", red, green, blue);
// call the service to refresh the background color
ros::service::waitForService("/clear");
ros::ServiceClient clear_background = node.serviceClient<std_srvs::Empty>("/clear");
std_srvs::Empty srv;
clear_background.call(srv);
sleep(1);
return 0;
}

2、修改CMakeList.txt

add_executable(parameter_config src/parameter_config.cpp)
target_link_libraries(parameter_config ${catkin_LIBRARIES})

3、运行程序查看结果

1)编译程序

cd ~/lab2
catkin_make

2)运行程序

roscore

在 另一个终端启动海龟

rosrun turtlesim turtlesim_node

在另一个终端启动parameter_config:

source ~/lab3/devel/setup.bash
rosrun learning_communication parameter_config

四、action

1、自定义动作数据

首先在包下创建一个名为action的新文件夹,并创建一个名为addintts.action的操作文件。action内容如下:

#Define the goal
int32 num
---
#Define the result
int32 result
---
#Define a feedback message
float64 progress_bar

2、编写操作服务器

创建src/actionAdd_server.cpp

#include "ros/ros.h"
#include "actionlib/server/simple_action_server.h"
#include "learning_communication/AddIntsAction.h"
typedef actionlib::SimpleActionServer<learning_communication::AddIntsAction> Server;
void cb(const learning_communication::AddIntsGoalConstPtr &goal,Server* server){
// get the action target
int num = goal->num;
ROS_INFO("Target:%d",num);
// add and respond to the continuous feedback
int result = 0;
learning_communication::AddIntsFeedback feedback; // continuous feedback
ros::Rate rate(10);
for (int i = 1; i <= num; i++)
{
result += i;
//calculate and publish the continuous feedback
feedback.progress_bar = i / (double)num;
server->publishFeedback(feedback);
rate.sleep();
}
// set final result
learning_communication::AddIntsResult r;
r.result = result;
server->setSucceeded(r);
ROS_INFO("Result:%d",r.result);
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ROS_INFO("action Server");
ros::init(argc,argv,"AddInts_server");
ros::NodeHandle nh;
// create the server for the action
Server server(nh,"addInts",boost::bind(&cb,_1,&server),false);
server.start();
// start the server
// spin().
ros::spin();
return 0;
}

3、编写操作客户端

创建src/actionAdd_client.cpp

#include "ros/ros.h"
#include "actionlib/client/simple_action_client.h"
#include "learning_communication/AddIntsAction.h"
typedef actionlib::SimpleActionClient<learning_communication::AddIntsAction> Client;
// action finished callback funtion
void done_cb(const actionlib::SimpleClientGoalState &state, const
learning_communication::AddIntsResultConstPtr &result){
if (state.state_ == state.SUCCEEDED)
{
ROS_INFO("Result: %d",result->result);
} else {
ROS_INFO("Action failed!");
}
}
// action starts callback function
void active_cb(){
ROS_INFO("action activated ....");
}
// Continuous feedback callback function
void feedback_cb(const learning_communication::AddIntsFeedbackConstPtr &feedback){
ROS_INFO("Progress: %.2f",feedback->progress_bar);
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"AddInts_client");
ros::NodeHandle nh;
// create the client for the action
// SimpleActionClient(ros::NodeHandle & n, const std::string & name, bool spin_thread = true)
//actionlib::SimpleActionClient<learning_communication::AddIntsAction> client(nh,"addInts");
Client client(nh,"addInts",true);
// wait for the action server starts
client.waitForServer();
learning_communication::AddIntsGoal goal;
goal.num = 10;
// send the action, and set the callback functions
client.sendGoal(goal,&done_cb,&active_cb,&feedback_cb);
ros::spin();
return 0;
}

4、修改CMakeList.txt

1)

find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
std_srvs
message_generation
actionlib
actionlib_msgs
)


2)

add_action_files(
FILES
AddInts.action
)


3)

generate_messages(
DEPENDENCIES
std_msgs
actionlib_msgs
)


4)

catkin_package(
CATKIN_DEPENDS roscpp rospy std_msgs std_srvs actionlib actionlib_msgs
)


5)

add_executable(actionAdd_server src/actionAdd_server.cpp)
target_link_libraries(actionAdd_server ${catkin_LIBRARIES})
add_dependencies(actionAdd_server ${PROJECT_NAME}_generate_messages_cpp)
add_executable(actionAdd_client src/actionAdd_client.cpp)
target_link_libraries(actionAdd_client ${catkin_LIBRARIES})
add_dependencies(actionAdd_client ${PROJECT_NAME}_generate_messages_cpp)

5、修改package.xml

添加:

<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>

6、 运行程序查看结果

1)编译程序

cd ~/lab2
catkin_make

2)运行程序

启动

roscore

 在新终端启动actionAdd_server

source ~/lab2/devel/setup.bash
rosrun learning_communication actionAdd_server

 在新终端启动actionAdd_client

source ~/lab2/devel/setup.bash
rosrun learning_communication actionAdd_client

五、日志记录工具

修改src/string_publisher.cpp,增加以下内容:

#include <ros/console.h>



while (ros::ok())
{
ROS_ERROR("ERROR!!!");
ROS_WARN("WARN!!!");
ROS_ERROR_STREAM("YES"<<"I am");
ROS_WARN_STREAM("YES"<<"I am");
}

运行程序查看结果

cd ~/lab2
catkin_make
roscore

 在另一个终端中启动string_publisher:

source ~/lab2/devel/setup.bash
rosrun learning_communication string_publisher

新建终端,启动string_listener:

source ~/lab2/devel/setup.bash
rosrun learning_communication string_listener

最后观察日志消息

rqt_console

六、发布文件

创建包

cd ~/lab2/src
catkin_create_pkg learning_common_tools
cd learning_common_tools && mkdir scripts launch config

1)编写消息发布者、订阅者的发布文件

创建 launch/simple.launch,并编写

<launch>
<node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node" output="screen" />
<node pkg="turtlesim" type="turtle_teleop_key" name="turtle_teleop_key" output="screen" />
</launch>

2)编写参数配置文件

创建launch/turtlesim_paramter_config.launch,并编写:

<launch>
<param name="/turtle_number" value="2"/>
<arg name="TurtleName1" default="Tom" />
<arg name="TurtleName2" default="Jerry" />
<node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node">
<param name="turtle_name1" value="$(arg TurtleName1)"/>
<param name="turtle_name2" value="$(arg TurtleName2)"/>
<rosparam file="$(find learning_common_tools)/config/param.yaml" command="load"/>
</node>
</launch>

创建config/param.yaml ,并编写

A: 123
B: "hello"


group:
  C: 456
  D: "hello"

3)编写主题重新映射启动文件

创建launch/turtlesim_remap.launch

<launch>
<node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node">
<remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
</node>
<node pkg="turtlesim" type="turtle_teleop_key" name="turtle_teleop_key" output="screen" >
<remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
</node>
</launch>

4)运行程序查看结果

cd ~/lab2 && catkin_make && source devel/setup.bash
roslaunch learning_common_tools simple.launch

中止,运行:

roslaunch learning_common_tools turtlesim_parameter_config.launch

可以使用以下命令:

rosparam get /turtle_number
rosparam get /turtlesim_node/turtle_name1
rosparam get /turtlesim_node/turtle_name2
rosparam get /turtlesim_node/A
rosparam get /turtlesim_node/B
rosparam get /turtlesim_node/group/C
rosparam get /turtlesim_node/group/D

中止,运行:

roslaunch learning_common_tools turtlesim_remap.launch

海龟就可以通过/cmd_vel话题进行控制

实验

1、练习使用话题通信程序

1)发布spark_gazebo.launch在提供的包里。如lab1的实验4:

catkin_make
source devel/setup.bash
roslaunch spark1_description spark_gazebo.launch

2)参考话题通信示例,在spark_description包下创建发布者节点src/move_pub.cpp,并修改CMakeList.txt

在CMakeList.txt添加:

add_executable(move_pub src/move_pub.cpp)
target_link_libraries(move_pub ${catkin_LIBRARIES})

3)实现spark在仿真环境中分别跑10m直线和半径为5m的圆

画圆move_pub.cpp:

#include "ros/ros.h"
#include<geometry_msgs/Twist.h> //运动速度结构体类型  geometry_msgs::Twist的定义文件
 
int main(int argc, char *argv[])
{
    ros::init(argc, argv, "move_pub");  //对该节点进行初始化操作
    ros::NodeHandle n;         //申明一个NodeHandle对象n,并用n生成一个广播对象vel_pub
    ros::Publisher move_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel", 10);
    //vel_pub会在主题"/cmd_vel"(机器人速度控制主题)里广播geometry_msgs::Twist类型的数据
    ROS_INFO("draw_circle start...");//输出显示信息
    while(ros::ok())
    {
        geometry_msgs::Twist move_cmd; //声明一个geometry_msgs::Twist 类型的对象vel_cmd,并将速度的值赋值到这个对象里面
 
        move_cmd.linear.x = 2.0;//前后(+-) m/s
        move_cmd.linear.y = 0.0;  //左右(+-) m/s
        move_cmd.linear.z = 0.0;
 
        move_cmd.angular.x = 0;
        move_cmd.angular.y = 0;
        move_cmd.angular.z = 0.4; //机器人的自转速度,+左转,-右转,单位是rad/s
        move_pub.publish(move_cmd); //赋值完毕后,发送到主题"/cmd_vel"。机器人的核心节点会从这个主题接受发送过去的速度值,并转发到硬件体上去执行
 
        ros::spinOnce();//调用此函数给其他回调函数得以执行(比例程未使用回调函数)
    }
    return 0;
}
catkin_make
source ~/gazebo-learn/gazebo-learn/devel/setup.bash
rosrun spark1_description move_pub


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值