常用命令
//查看话题列表
rostopic list
//查看某个话题信息
rostopic info 话题名
//输出某个话题的内容
rostopic echo 话题名
//查看节点列表
rosnode list
//节点拓扑结构
rqt_graph
自动启动多个节点
创建launch启动文件
编写launch启动文件
<launch>
<node name="minimal_subscriber" pkg="my_minimal_nodes" type="my_minimal_subscriber"/>
<node name="minimal_publisher" pkg="my_minimal_nodes" type="my_minimal_publisher"/>
</launch>
注:
通过指定三个值来启动一个节点,第一个值是节点名node name,第二个值是程序包名pkg,第三个值是可执行文件名type。在这里node name可以随便写,也就是给了你一次重新命名的机会。
运行launch启动文件
注:
在使用launch启动文件的时候,不需要启动可执行节点roscore
查看运行结果
在ROS控制台观察输出
rqt_console
使用rosbag记录并回放数据
当系统运行时,我们可以指定记录一系列话题,rosbag会订阅这些话题并将发布的消息以及时间戳记录在包文件中,生成的文件会保存在运行命令的同一目录下。
rosbag record 话题名
rosbag回放包文件,重建已记录的系统环境。
rosbag play 包名.bag
rqt_plot
这里我们就以一个仿真器和控制器交互为例子,来展示一下怎么使用rqt_plot可视化吧。
//仿真器
#include <ros/ros.h>
#include <std_msgs/Float64.h>
std_msgs::Float64 g_velocity;
std_msgs::Float64 g_force;
void myCallback(const std_msgs::Float64& message_holder)
{
g_force.data=message_holder.data;
ROS_INFO("received force value is: %f",message_holder.data);
}
int main(int argc,char **argv)
{
ros::init(argc,argv,"minimal_simulator");
ros::NodeHandle n;
ros::Subscriber my_subscriber_object=n.subscribe("force_cmd",1,myCallback);
ros::Publisher my_publisher_object=n.advertise<std_msgs::Float64>("velocity",1);
double mass=1.0; //质量为1kg
double dt=0.01; //10毫秒采一次样
double sample_rate=1.0/dt;
g_velocity.data=0.0;
g_force.data=0.0;
ros::Rate naptime(sample_rate);
while(ros::ok())
{
g_velocity.data=g_velocity.data+(g_force.data/mass)*dt;
my_publisher_object.publish(g_velocity);
ROS_INFO("velocity = %f",g_velocity.data);
ros::spinOnce();
naptime.sleep();
}
return 0;
}
//控制器
#include <ros/ros.h>
#include <std_msgs/Float64.h>
std_msgs::Float64 g_velocity;
std_msgs::Float64 g_vel_cmd;
std_msgs::Float64 g_force;
void myCallbackVelocity(const std_msgs::Float64& message_holder)
{
g_velocity.data=message_holder.data;
ROS_INFO("received velocity value is: %f",message_holder.data);
}
void myCallbackVelCmd(const std_msgs::Float64& message_holder)
{
g_vel_cmd.data=message_holder.data;
ROS_INFO("received velocity command value is: %f",message_holder.data);
}
int main(int argc,char **argv)
{
ros::init(argc,argv,"minimal_controller");
ros::NodeHandle n;
ros::Subscriber my_subscriber_object1=n.subscribe("velocity",1,myCallbackVelocity);
ros::Subscriber my_subscriber_object2=n.subscribe("vel_cmd",1,myCallbackVelCmd);
ros::Publisher my_publisher_object=n.advertise<std_msgs::Float64>("force_cmd",1);
g_velocity.data=0.0;
g_vel_cmd.data=0.0;
g_force.data=0.0;
double Kv=1.0;
double dt_controller=0.1;
double sample_rate=1.0/dt_controller;
double vel_err=0.0;
ros::Rate naptime(sample_rate);
while(ros::ok())
{
vel_err=g_vel_cmd.data-g_velocity.data;
g_force.data=Kv*vel_err;
my_publisher_object.publish(g_force);
ROS_INFO("force command = %f",g_force.data);
ros::spinOnce();
naptime.sleep();
}
return 0;
}
上面的代码是什么意思呢?这里首先有三个话题“vel_cmd”,“force_cmd”,“velocity”,这三个话题分别代表了期望速度、实际力、实际速度。没错,到这里大家应该已经能猜到了,就是一个简单的F=ma。
仿真器根据v=v0+at计算实际速度,并发布实际速度,同时订阅实际力并显示。
控制器根据F=ma计算实际力,并发布实际力,同时订阅实际速度、期望速度并显示。
那么在操作的时候,首先要打开roscore,然后再运行控制器节点和仿真器节点(这两个顺序就无所谓了),然后需要手动发布一个期望速度的话题消息,这样控制器才可以订阅,最后执行rqt_plot命令就可以看到变化曲线了。
原谅我没有截到rqt_plot的图,这个速度实在是太快了,但是我确实是成功了的,可以看下面两张图的实际速度velocity在“慢慢”的逼近期望速度(实际上是很快就逼近了,导致我还没有打开rqt_plot它就结束了)。
算了,最后再贴一张图吧,不然大家都不知道plot长啥样的,在官网上找的图,和这个例子没有关系…