ROS实战_1.4 ROSCPP (基于Pioneer 3dx )

本文详细介绍了ROS中ROSCPP的初始化、节点启动、订阅发布、信号处理、回调函数等关键概念,并提供了相关示例代码。通过ros::init()初始化节点,使用ros::NodeHandle启动和关闭节点,探讨了节点命名、选项设置和命令行参数的访问。此外,还讨论了多线程旋转、回调队列和时间管理在ROSCPP中的应用。
摘要由CSDN通过智能技术生成

例程: go_three_second.cpp

#include<ros/ros.h>
#include<geometry_msgs/Twist.h>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "go_three_second"); //初始化,创建节点
  ros::NodeHandle nh; //启动节点
  
  ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("RosAria/cmd_vel", 1000); 
  geometry_msgs::Twist msg;                     
// 类似与 int a=1; 此句的返回值的数据类型是ros::publisher, 调用句柄nh的一个advertise函数,这个函数返回值的数据类型是 geometry_msgs::Twist;
// 最后的效果便是告诉master,要在话题RosAria/cmd_vel 上发布一个 geometry_msgs::Twist的数据类型;

  double BASE_SPEED = 0.2, MOVE_TIME = 3.0, CLOCK_SPEED = 0.5; 
  int count = 0; 
  ros::Rate rate(CLOCK_SPEED);// 单位 hz: 若1HZ,则1秒更新一次 

  // Make the robot stop (robot perhaps has a speed already) 
  msg.linear.x = 0; 
  msg.linear.y = 0; 
  msg.linear.z = 0; 
  msg.angular.x = 0; 
  msg.angular.y = 0; 
  msg.angular.z = 0; 
  pub.publish(msg); //向所有订阅 RosAria/cmd_vel 话题的节点发布消息

  while(ros::ok() && count<MOVE_TIME/CLOCK_SPEED + 1) 
  { 
    if (count == 0 || count == 1)
      { 
        msg.linear.x = BASE_SPEED; 
        pub.publish(msg);
      }
    ROS_INFO_STREAM("The robot is now moving forward!"); 
    count++; 
    ros::spinOnce(); //will call all the callbacks waiting to be called at that point in time. 
    rate.sleep(); //maintaining a particular rate for a loop. 
  } 

  // make the robot stop 
  for (int i = 0; i < 2; i++) 
   { 
     msg.linear.x = 0; 
     msg.linear.y = 0; 
     msg.linear.z = 0; 
     pub.publish(msg); 
   } 

  ROS_INFO_STREAM("The robot finished moving forward three seconds!"); 

  // Guard, make sure the robot stops. 
  rate.sleep(); 
  msg.linear.x = 0; 
  msg.linear.y = 0; 
  msg.linear.z = 0; 
  pub.publish(msg); 
}



I:Initialization and Shutting Down

1. Initialization

There are two levels of initialization for a roscpp Node:

  1. Initializing the node through a call to one of the ros::init() functions. This provides command line arguments to ROS, and allows you to name your node and specify other options.

  2. Starting the node is most often done through creation of a ros::NodeHandle, but in advanced cases can be done in different ways.

1.1 Initializing the roscpp Node

See also: ros::init() code API

Before calling any other roscpp functions in a node you must call one of the ros::init() functions. The two most common init()invokations are:

切换行号显示
   1 ros::init(argc, argv, "my_node_name");

and

切换行号显示
   1 ros::init(argc, argv, "my_node_name", ros::init_options::AnonymousName);

In general, the form of ros::init() conforms(符合) to:

切换行号显示
   1 void ros::init(<command line or remapping arguments>, std::string node_name, uint32_t options);

Let's Go over the arguments in order:

  • argc and argv

    • ROS uses these to parse remapping arguments from the command line. It also modifies them so that they no longer contain any remapping arguments, so that if you call ros::init() before processing your command line you will not need to skip those arguments yourself.

    • Note:remapping arguments -- :Any ROS name within a node can be remapped when it is launched at the command-line. This is a powerful feature of ROS that lets you launch the same node under multiple configurations from the command-line. All resource names can be remapped. You can also provide assignment for private node parameters. This feature of ROS allows you to defer complex name assignments to the actual runtime loading of the system. (详见链接)

    node_name

    • This is the name that will be assigned to your node unless it's overridden by one of the remapping arguments. Node names must be unique across the ROS system. If a second node is started with the same name as the first, the first will be shutdown automatically. In cases where you want multiple of the same node running without worrying about naming them uniquely, you may use the init_options::AnonymousName option described below.

    options

    • This is an optional argument that lets you specify certain options that change roscpp's behavior. The field is a bitfield, so multiple options can be specified. The options are described in the Initialization Options section.

There are other forms of ros::init() that do not take argc/argv, instead taking explicit remapping options. Specifically, there are versions that take a std::map<std::string, std::string> and a std::vector<std::pair<std::string, std::string> >.

Initializing the node simply reads the command line arguments and environment to figure out things like the node name, namespace and remappings. It does not contact the master. This lets you use ros::master::check() and other ROS functions after calling ros::init() to check on the status of the master. The node only full spins up once it has been started, which is described in the Starting the roscpp Node section.

1.1.1 Initialization Options

See also: ros::init_options code API

  • ros::init_options::NoSigintHandler

    • Don't install a SIGINT handler. You should install your own SIGINT handler in this case, to ensure that the node gets shutdown correctly when it exits. Note that the default action for SIGINT tends to be to terminate the process, so if you want to do your own SIGTERM handling you will also have to use this option.

    ros::init_options::AnonymousName

    • Anonymize(隐去) the node name. Adds a random number to the end of your node's name, to make it unique.

    ros::init_options::NoRosout

    • Don't broadcast rosconsole output to the /rosout topic.

1.1.2 Accessing Your Command Line Arguments

As mentioned above, calling ros::init() with argc and argv will remove ROS arguments from the command line. If you need to parse the command line before calling ros::init(), you can call the (new in ROS 0.10) ros::removeROSArgs() function.

1.2 Starting the roscpp Node

The most common way of starting a roscpp node is by creating a ros::NodeHandle:

切换行号显示
   1 ros::NodeHandle nh;

    When the first ros::NodeHandle is created it will call ros::start(),   and when the last ros::NodeHandle is destroyed, it will call ros::shutdown()

If you want to manually manage the lifetime of the node you may call ros::start() yourself, in which case you should call ros::shutdown() before your program exits.

2. Shutting Down

2.1 Shutting Down the Node

    At any time you may call the ros::shutdown() function to shutdown your node. This will kill all open subscriptions, publications, service calls, and service servers.

    By default roscpp also installs a SIGINT handler which will detect Ctrl-C and automatically shutdown for you.

2.2 Testing for Shutdown

    There are two methods to check for various states of shutdown. The most common is ros::ok().Once ros::ok() returns false, the node has finished shutting down.A common use of ros::ok():

切换行号显示
   1 while (ros::ok())
   2 {
    
   3   ...
   4 }

    The other method to check for shutdown is the ros::isShuttingDown() method. This method will turn true as soon as ros::shutdown() is called, not when it is done. Use of ros::isShuttingDown() is generally discouraged, but can be useful in advanced cases. For example, to test inside of a prolonged service callback whether the node is requested to shut down and the callback should therefore quit now, ros::isShuttingDown() is needed. ros::ok() would not work here because the node can't finish its shutdown as long as the callback is running.

2.2.1 Custom SIGINT Handler

  You can install a custom SIGINT handler that plays nice with ROS like so:

切换行号显示
#include <ros/ros.h>
#include <signal.h>

void mySigintHandler(int sig)
{
    
  // Do some custom action.
  // For example, publish a stop message to some other nodes.
  
  // All the default sigint handler does is call shutdown()
  ros::shutdown();
}

int main(int argc, char** argv)
{
    
  ros::init(argc, argv, "my_node_name", ros::init_options::NoSigintHandler);
  ros::NodeHandle nh;

  // Override the default ros sigint handler.
  // This must be set after the first NodeHandle is created.
  signal(SIGINT, mySigintHandler);
  
  //...
  ros::spin();
  return 0;
}

**************************************************************************************************************************************************************************

II:  NodeHandle

    The ros::NodeHandle class serves two purposes: 
(1)  First, it provides RAII-style startup and shutdown of the internal node inside a roscpp program. 
(2)  Second, it provides an extra layer of namespace resolution that can make writing subcomponents easier.

1. Automatic Startup and Shutdown

As explained in the Initialization and Shutdown roscpp overviewros::NodeHandle manages an internal reference count to make starting and shutting down a node as simple as:

切换行号显示
   1 ros::NodeHandle nh;

On creation, if the internal node has not been started already, ros::NodeHandle will start the node. Once all ros::NodeHandle instances have been destroyed,the node will be automatically shutdown.

2. Namespaces

See also: ROS names documentation

关于C++中的 namespace详见:http://blog.csdn.NET/yao_zhuang/article/details/1853625

NodeHandles let you specify a namespace to their constructor:

切换行号显示
   1 ros::NodeHandle nh("my_namespace");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值