ros的init机制

动机
这篇博客主要关注一个问题:ros系统中init()的运行过程是怎么样的?调用这个函数后会生成哪些东西或者说系统开辟了哪些服务线程?
语句ros::init(argc, argv, "add_two_ints_client");
note:这条语句来源于ros的Wiki教程,链接
完整的程序段如下:

/*
 * Copyright (C) 2008, Morgan Quigley and Willow Garage, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "ros/ros.h"
#include "roscpp_tutorials/TwoInts.h"
#include <cstdlib>


int main(int argc, char **argv)
{
    
    
  ros::init(argc, argv, "add_two_ints_client");
  if (argc != 3)
  {
    
    
    ROS_INFO("usage: add_two_ints_client X Y");
    return 1;
  }

  ros::NodeHandle n;
  ros::ServiceClient client = n.serviceClient<roscpp_tutorials::TwoInts>("add_two_ints");
  roscpp_tutorials::TwoInts srv;
  srv.request.a = atoi(argv[1]);
  srv.request.b = atoi(argv[2]);
  if (client.call(srv))
  {
    
    
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);
  }
  else
  {
    
    
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }

  return 0;
}

要想弄清楚这条语句做了哪些事,需要找到其定义的地方,这个文件包含三个头文件,其中"ros/ros.h"是ros的公共头文件,"roscpp_tutorials/TwoInts.h"是这段程序用到的服务类型文件(不是我们关注的),剩下的“cstdlib”是C++里面的一个常用函数库, 等价于C中的<stdlib.h>。明显init就是定义再"ros/ros.h"中。
ros.h文件的内容如下:

/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ROSCPP_ROS_H
#define ROSCPP_ROS_H

#include "ros/time.h"
#include "ros/rate.h"
#include "ros/console.h"
#include "ros/assert.h"

#include "ros/common.h"
#include "ros/types.h"
#include "ros/node_handle.h"
#include "ros/publisher.h"
#include "ros/single_subscriber_publisher.h"
#include "ros/service_server.h"
#include "ros/subscriber.h"
#include "ros/service.h"
#include "ros/init.h"
#include "ros/master.h"
#include "ros/this_node.h"
#include "ros/param.h"
#include "ros/topic.h"
#include "ros/names.h"

#endif

这里是包含了一大堆ros的相关功能的头文件,这也就是为什么只要包含ros.h就可以使用ros的大部分功能了。在这里有一个显目的头文件“#include "ros/init.h"”,好像这个是与探讨的问题相关。
init.h文件的内容如下:

/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ROSCPP_INIT_H
#define ROSCPP_INIT_H

#include "ros/forwards.h"
#include "ros/spinner.h"
#include "common.h"

namespace ros
{
    
    

namespace init_options
{
    
    
/**
 * \brief Flags for ROS initialization
 */
enum InitOption
{
    
    
  /**
   * 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.
   */
  NoSigintHandler = 1 << 0,
  /** \brief Anonymize the node name.  Adds a random number to the end of your node's name, to make it unique.
   */
  AnonymousName = 1 << 1,
  /**
   * \brief Don't broadcast rosconsole output to the /rosout topic
   */
  NoRosout = 1 << 2,
};
}
typedef init_options::InitOption InitOption;

/** @brief ROS initialization function.
 *
 * This function will parse any ROS arguments (e.g., topic name
 * remappings), and will consume them (i.e., argc and argv may be modified
 * as a result of this call).
 *
 * Use this version if you are using the NodeHandle API
 *
 * \param argc
 * \param argv
 * \param name Name of this node.  The name must be a base name, ie. it cannot contain namespaces.
 * \param options [optional] Options to start the node with (a set of bit flags from \ref ros::init_options)
 * \throws InvalidNodeNameException If the name passed in is not a valid "base" name
 *
 */
ROSCPP_DECL void init(int &argc, char **argv, const std::string& name, uint32_t options = 0);

/**
 * \brief alternate ROS initialization function.
 *
 * \param remappings A map<string, string> where each one constitutes a name remapping, or one of the special remappings like __name, __master, __ns, etc.
 * \param name Name of this node.  The name must be a base name, ie. it cannot contain namespaces.
 * \param options [optional] Options to start the node with (a set of bit flags from \ref ros::init_options)
 * \throws InvalidNodeNameException If the name passed in is not a valid "base" name
 */
ROSCPP_DECL void init(const M_string& remappings, const std::string& name, uint32_t options = 0);

/**
 * \brief alternate ROS initialization function.
 *
 * \param remappings A vector<pair<string, string> > where each one constitutes a name remapping, or one of the special remappings like __name, __master, __ns, etc.
 * \param name Name of this node.  The name must be a base name, ie. it cannot contain namespaces.
 * \param options [optional] Options to start the node with (a set of bit flags from \ref ros::init_options)
 * \throws InvalidNodeNameException If the name passed in is not a valid "base" name
 */
ROSCPP_DECL void init(const VP_string& remapping_args, const std::string& name, uint32_t options = 0);

/**
 * \brief Returns whether or not ros::init() has been called
 */
ROSCPP_DECL bool isInitialized();
/**
 * \brief Returns whether or not ros::shutdown() has been (or is being) called
 */
ROSCPP_DECL bool isShuttingDown();

/** \brief Enter simple event loop
 *
 * This method enters a loop, processing callbacks.  This method should only be used
 * if the NodeHandle API is being used.
 *
 * This method is mostly useful when your node does all of its work in
 * subscription callbacks.  It will not process any callbacks that have been assigned to
 * custom queues.
 *
 */
ROSCPP_DECL void spin();

/** \brief Enter simple event loop
 *
 * This method enters a loop, processing callbacks.  This method should only be used
 * if the NodeHandle API is being used.
 *
 * This method is mostly useful when your node does all of its work in
 * subscription callbacks.  It will not process any callbacks that have been assigned to
 * custom queues.
 *
 * \param spinner a spinner to use to call callbacks.  Two default implementations are available,
 * SingleThreadedSpinner and MultiThreadedSpinner
 */
ROSCPP_DECL void spin(Spinner& spinner);
/**
 * \brief Process a single round of callbacks.
 *
 * This method is useful if you have your own loop running and would like to process
 * any callbacks that are available.  This is equivalent to calling callAvailable() on the
 * global CallbackQueue.  It will not process any callbacks that have been assigned to
 * custom queues.
 */
ROSCPP_DECL void spinOnce();

/**
 * \brief Wait for this node to be shutdown, whether through Ctrl-C, ros::shutdown(), or similar.
 */
ROSCPP_DECL void waitForShutdown();

/** \brief Check whether it's time to exit.
 *
 * ok() becomes false once ros::shutdown() has been called and is finished
 *
 * \return true if we're still OK, false if it's time to exit
 */
ROSCPP_DECL bool ok();
/**
 * \brief Disconnects everything and unregisters from the master.  It is generally not
 * necessary to call this function, as the node will automatically shutdown when all
 * NodeHandles destruct.  However, if you want to break out of a spin() loop explicitly,
 * this function allows that.
 */
ROSCPP_DECL void shutdown();

/**
 * \brief Request that the node shut itself down from within a ROS thread
 *
 * This method signals a ROS thread to call shutdown().
 */
ROSCPP_DECL void requestShutdown();

/**
 * \brief Actually starts the internals of the node (spins up threads, starts the network polling and xmlrpc loops,
 * connects to internal subscriptions like /clock, starts internal service servers, etc.).
 *
 * Usually unnecessary to call manually, as it is automatically called by the creation of the first NodeHandle if
 * the node has not already been started.  If you would like to prevent the automatic shutdown caused by the last
 * NodeHandle going out of scope, call this before any NodeHandle has been created (e.g. immediately after init())
 */
ROSCPP_DECL void start();
/**
 * \brief Returns whether or not the node has been started through ros::start()
 */
ROSCPP_DECL bool isStarted();

/**
 * \brief Returns a pointer to the global default callback queue.
 *
 * This is the queue that all callbacks get added to unless a different one is specified, either in the NodeHandle
 * or in the individual NodeHandle::subscribe()/NodeHandle::advertise()/etc. functions.
 */
ROSCPP_DECL CallbackQueue* getGlobalCallbackQueue();

/**
 * \brief searches the command line arguments for the given arg parameter. In case this argument is not found
 * an empty string is returned.
 *
 * \param argc the number of command-line arguments
 * \param argv the command-line arguments
 * \param arg argument to search for
 */
ROSCPP_DECL std::string getROSArg(int argc, const char* const* argv, const std::string& arg);

/**
 * \brief returns a vector of program arguments that do not include any ROS remapping arguments.  Useful if you need
 * to parse your arguments to determine your node name
 *
 * \param argc the number of command-line arguments
 * \param argv the command-line arguments
 * \param [out] args_out Output args, stripped of any ROS args
 */
ROSCPP_DECL void removeROSArgs(int argc, const char* const* argv, V_string& args_out);

}

#endif

在这个文件中找到 ROSCPP_DECL void init(int &argc, char **argv, const std::string& name, uint32_t options = 0);就是需要探讨的函数(存在四个参数,但是有一个默认参数)。
看看官方给出的介绍:

** @brief ROS initialization function.(简介:ros的初始化函数)
 *
 * This function will parse any ROS arguments (e.g., topic name
 * remappings), and will consume them (i.e., argc and argv may be modified
 * as a result of this call).(将一些命令参数转换)
 *
 * Use this version if you are using the NodeHandle API(如果要使用ros的话柄(用来初始订阅和发布等)需要使用这个初始函数)
 *
 * \param argc
 * \param argv
 * \param name Name of this node.  The name must be a base name, ie. it cannot contain namespaces.(第三个参数是话题的名称,需要注意的是如果使用launch文件启动节点,则节点的名称是以launch文件的为准)
 * \param options [optional] Options to start the node with (a set of bit flags from \ref ros::init_options)(第四个参数是启动ros节点的一些控制标志位)
 * \throws InvalidNodeNameException If the name passed in is not a valid "base" name(如果节点的名称无效,则节点启动会失败并抛出异常)
 *
 */

总结:这个函数的作用是利用配置的参数启动ros节点并且当传送的参数不符合要求时将抛出异常。

下面对这个文件的代码做进一步解释,首先看头文件:这里有三个头文件

#include "ros/forwards.h"
#include "ros/spinner.h"
#include "common.h"

看看各个头文件的内容:

-ros/forwards.h

/*
 * Copyright (C) 2008, Morgan Quigley and Willow Garage, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ROSCPP_FORWARDS_H
#define ROSCPP_FORWARDS_H

#include <string>
#include <vector>
#include <map>
#include <set>
#include <list>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/function.hpp>

#include <ros/time.h>
#include <ros/macros.h>
#include "exceptions.h"
#include "ros/datatypes.h"

namespace ros
{
    
    

typedef boost::shared_ptr<void> VoidPtr;
typedef boost::weak_ptr<void> VoidWPtr;
typedef boost::shared_ptr<void const> VoidConstPtr;
typedef boost::weak_ptr<void const> VoidConstWPtr;

class Header;
class Transport;
typedef boost::shared_ptr<Transport> TransportPtr;
class TransportTCP;
typedef boost::shared_ptr<TransportTCP> TransportTCPPtr;
class TransportUDP;
typedef boost::shared_ptr<TransportUDP> TransportUDPPtr;
class Connection;
typedef boost::shared_ptr<Connection> ConnectionPtr;
typedef std::set<ConnectionPtr> S_Connection;
typedef std::vector<ConnectionPtr> V_Connection;
class Publication;
typedef boost::shared_ptr<Publication> PublicationPtr;
typedef std::vector<PublicationPtr> V_Publication;
class SubscriberLink;
typedef boost::shared_ptr<SubscriberLink> SubscriberLinkPtr;
typedef std::vector<SubscriberLinkPtr> V_SubscriberLink;
class Subscription;
typedef boost::shared_ptr<Subscription> SubscriptionPtr;
typedef boost::weak_ptr<Subscription> SubscriptionWPtr;
typedef std::list<SubscriptionPtr> L_Subscription;
typedef std::vector<SubscriptionPtr> V_Subscription;
typedef std::set<SubscriptionPtr> S_Subscription;
class PublisherLink;
typedef boost::shared_ptr<PublisherLink> PublisherLinkPtr;
typedef std::vector<PublisherLinkPtr> V_PublisherLink;
class ServicePublication;
typedef boost::shared_ptr<ServicePublication> ServicePublicationPtr;
typedef std::list<ServicePublicationPtr> L_ServicePublication;
typedef std::vector<ServicePublicationPtr> V_ServicePublication;
class ServiceServerLink;
typedef boost::shared_ptr<ServiceServerLink> ServiceServerLinkPtr;
typedef std::list<ServiceServerLinkPtr> L_ServiceServerLink;
class Transport;
typedef boost::shared_ptr<Transport> TransportPtr;
class NodeHandle;
typedef boost::shared_ptr<NodeHandle> NodeHandlePtr;


class SingleSubscriberPublisher;
typedef boost::function<void(const SingleSubscriberPublisher&)> SubscriberStatusCallback;

class CallbackQueue;
class CallbackQueueInterface;
class CallbackInterface;
typedef boost::shared_ptr<CallbackInterface> CallbackInterfacePtr;

struct SubscriberCallbacks
{
    
    
  SubscriberCallbacks(const SubscriberStatusCallback& connect = SubscriberStatusCallback(),
                      const SubscriberStatusCallback& disconnect = SubscriberStatusCallback(),
                      const VoidConstPtr& tracked_object = VoidConstPtr(),
                      CallbackQueueInterface* callback_queue = 0)
  : connect_(connect)
  , disconnect_(disconnect)
  , callback_queue_(callback_queue)
  {
    
    
    has_tracked_object_ = false;
    if (tracked_object)
    {
    
    
      has_tracked_object_ = true;
      tracked_object_ = tracked_object;
    }
  }
  SubscriberStatusCallback connect_;
  SubscriberStatusCallback disconnect_;

  bool has_tracked_object_;
  VoidConstWPtr tracked_object_;
  CallbackQueueInterface* callback_queue_;
};
typedef boost::shared_ptr<SubscriberCallbacks> SubscriberCallbacksPtr;

/**
 * \brief Structure passed as a parameter to the callback invoked by a ros::Timer
 */
struct TimerEvent
{
    
    
  Time last_expected;                     ///< In a perfect world, this is when the last callback should have happened
  Time last_real;                         ///< When the last callback actually happened

  Time current_expected;                  ///< In a perfect world, this is when the current callback should be happening
  Time current_real;                      ///< This is when the current callback was actually called (Time::now() as of the beginning of the callback)

  struct
  {
    
    
    WallDuration last_duration;           ///< How long the last callback ran for
  } profile;
};
typedef boost::function<void(const TimerEvent&)> TimerCallback;

/**
 * \brief Structure passed as a parameter to the callback invoked by a ros::WallTimer
 */
struct WallTimerEvent
{
    
    
  WallTime last_expected;                 ///< In a perfect world, this is when the last callback should have happened
  WallTime last_real;                     ///< When the last callback actually happened

  WallTime current_expected;              ///< In a perfect world, this is when the current callback should be happening
  WallTime current_real;                  ///< This is when the current callback was actually called (Time::now() as of the beginning of the callback)

  struct
  {
    
    
    WallDuration last_duration;           ///< How long the last callback ran for
  } profile;
};
typedef boost::function<void(const WallTimerEvent&)> WallTimerCallback;

/**
 * \brief Structure passed as a parameter to the callback invoked by a ros::SteadyTimer
 */
struct SteadyTimerEvent
{
    
    
  SteadyTime last_expected;            ///< In a perfect world, this is when the last callback should have happened
  SteadyTime last_real;                ///< When the last callback actually happened

  SteadyTime current_expected;         ///< In a perfect world, this is when the current callback should be happening
  SteadyTime current_real;             ///< This is when the current callback was actually called (SteadyTime::now() as of the beginning of the callback)

  struct
  {
    
    
    WallDuration last_duration;           ///< How long the last callback ran for
  } profile;
};
typedef boost::function<void(const SteadyTimerEvent&)> SteadyTimerCallback;

class ServiceManager;
typedef boost::shared_ptr<ServiceManager> ServiceManagerPtr;
class TopicManager;
typedef boost::shared_ptr<TopicManager> TopicManagerPtr;
class ConnectionManager;
typedef boost::shared_ptr<ConnectionManager> ConnectionManagerPtr;
class XMLRPCManager;
typedef boost::shared_ptr<XMLRPCManager> XMLRPCManagerPtr;
class PollManager;
typedef boost::shared_ptr<PollManager> PollManagerPtr;

}

#endif

这个文件包括C++的基本容器和boost库中共享指针和函数的内容,并且对一些数据类型起别名,这里暂时不具体分析,以后关联内容将具体探讨。

  • ros/spinner.h
/*
 * Copyright (C) 2009, Willow Garage, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ROSCPP_SPINNER_H
#define ROSCPP_SPINNER_H

#include "ros/types.h"
#include "common.h"

#include <boost/shared_ptr.hpp>

namespace ros
{
    
    
class NodeHandle;
class CallbackQueue;

/**
 * \brief Abstract interface for classes which spin on a callback queue.
 */
class ROSCPP_DECL Spinner
{
    
    
public:
  virtual ~Spinner() {
    
    }

  /**
   * \brief Spin on a callback queue (defaults to the global one).  Blocks until roscpp has been shutdown.
   */
  virtual void spin(CallbackQueue* queue = 0) = 0;
};

/**
 * \brief Spinner which runs in a single thread.
 */
class SingleThreadedSpinner : public Spinner
{
    
    
public:
  virtual void spin(CallbackQueue* queue = 0);
};

/**
 * \brief Spinner which spins in multiple threads.
 */
class ROSCPP_DECL MultiThreadedSpinner : public Spinner
{
    
    
public:
  /**
   * \param thread_count Number of threads to use for calling callbacks.   0 will
   * automatically use however many hardware threads exist on your system.
   */
  MultiThreadedSpinner(uint32_t thread_count = 0);

  virtual void spin(CallbackQueue* queue = 0);

private:
  uint32_t thread_count_;
};

class AsyncSpinnerImpl;
typedef boost::shared_ptr<AsyncSpinnerImpl> AsyncSpinnerImplPtr;

/**
 * \brief AsyncSpinner is a spinner that does not conform to the abstract Spinner interface.  Instead,
 * it spins asynchronously when you call start(), and stops when either you call stop(), ros::shutdown()
 * is called, or its destructor is called
 *
 * AsyncSpinner is reference counted internally, so if you copy one it will continue spinning until all
 * copies have destructed (or stop() has been called on one of them)
 */
class ROSCPP_DECL AsyncSpinner
{
    
    
public:
  /**
   * \brief Simple constructor.  Uses the global callback queue
   * \param thread_count The number of threads to use.  A value of 0 means to use the number of processor cores
   */
  AsyncSpinner(uint32_t thread_count);

  /**
   * \brief Constructor with custom callback queue
   * \param thread_count The number of threads to use.  A value of 0 means to use the number of processor cores
   * \param queue The callback queue to operate on.  A null value means to use the global queue
   */
  AsyncSpinner(uint32_t thread_count, CallbackQueue* queue);



  /**
   * \brief Check if the spinner can be started. The spinner shouldn't be started if
   * another single-threaded spinner is already operating on the callback queue.
   *
   * This function is not necessary anymore. start() will always try to start spinning
   * and throw a std::runtime_error if it failed.
   */
  // TODO: deprecate in L-turtle
  bool canStart();
  /**
   * \brief Start this spinner spinning asynchronously
   */
  void start();
  /**
   * \brief Stop this spinner from running
   */
  void stop();

private:
  AsyncSpinnerImplPtr impl_;
};

}

#endif // ROSCPP_SPIN_POLICY_H

这个文件主要是与话题的回调有关,定义和实现了异步回调处理、单线程及多线程回调处理。

  • common.h
/*
 * Copyright (C) 2008, Morgan Quigley and Willow Garage, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ROSCPP_COMMON_H
#define ROSCPP_COMMON_H

#include <stdint.h>
#include <assert.h>
#include <stddef.h>
#include <string>

#include "ros/assert.h"
#include "ros/forwards.h"
#include "ros/serialized_message.h"

#include <boost/shared_array.hpp>

#define ROS_VERSION_MAJOR @roscpp_VERSION_MAJOR@
#define ROS_VERSION_MINOR @roscpp_VERSION_MINOR@
#define ROS_VERSION_PATCH @roscpp_VERSION_PATCH@
#define ROS_VERSION_COMBINED(major, minor, patch) (((major) << 20) | ((minor) << 10) | (patch))
#define ROS_VERSION ROS_VERSION_COMBINED(ROS_VERSION_MAJOR, ROS_VERSION_MINOR, ROS_VERSION_PATCH)

#define ROS_VERSION_GE(major1, minor1, patch1, major2, minor2, patch2) (ROS_VERSION_COMBINED(major1, minor1, patch1) >= ROS_VERSION_COMBINED(major2, minor2, patch2))
#define ROS_VERSION_MINIMUM(major, minor, patch) ROS_VERSION_GE(ROS_VERSION_MAJOR, ROS_VERSION_MINOR, ROS_VERSION_PATCH, major, minor, patch)

#include <ros/macros.h>

// Import/export for windows dll's and visibility for gcc shared libraries.

#ifdef ROS_BUILD_SHARED_LIBS // ros is being built around shared libraries
  #ifdef roscpp_EXPORTS // we are building a shared lib/dll
    #define ROSCPP_DECL ROS_HELPER_EXPORT
  #else // we are using shared lib/dll
    #define ROSCPP_DECL ROS_HELPER_IMPORT
  #endif
#else // ros is being built around static libraries
  #define ROSCPP_DECL
#endif

namespace ros
{
    
    

void disableAllSignalsInThisThread();

}

#endif

这个文件定义了版本和编译规则,dll、静态库或者动态库。
以上就是头文件部分,下面介绍各个语句的含义。


命名空间

namespace ros
namespace init_options

枚举类型,定义初始化节点的命令(也就是上面init的第四个参数)

enum InitOption
{
    
    
  /**
   * 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.
   */
  NoSigintHandler = 1 << 0,//***这个的意思是这个节点不接收ctrl+C或者ctrl+z所发出的终止信号***
  /** \brief Anonymize the node name.  Adds a random number to the end of your node's name, to make it unique.
   */
  AnonymousName = 1 << 1,//这个的意思是在节点的后面加上随机的数字保证节点名称的唯一性
  /**
   * \brief Don't broadcast rosconsole output to the /rosout topic
   */
  NoRosout = 1 << 2,//这个的意思是没有将节点的运行信息发送到/rosout topic,正常启动ros,一般我们会看到有/rosout话题的发出,这里可以控制其不创建这个话题
};

为这个枚举类型起别名

typedef init_options::InitOption InitOption;

这三个都说节点的初始函数,只是前面的参数有区别。

ROSCPP_DECL void init(int &argc, char **argv, const std::string& name, uint32_t options = 0);
ROSCPP_DECL void init(const M_string& remappings, const std::string& name, uint32_t options = 0);
ROSCPP_DECL void init(const VP_string& remapping_args, const std::string& name, uint32_t options = 0);

ROSCPP_DECL是编译控制标志,定义在common.h中

#ifdef ROS_BUILD_SHARED_LIBS // ros is being built around shared libraries
  #ifdef roscpp_EXPORTS // we are building a shared lib/dll
    #define ROSCPP_DECL ROS_HELPER_EXPORT
  #else // we are using shared lib/dll
    #define ROSCPP_DECL ROS_HELPER_IMPORT
  #endif
#else // ros is being built around static libraries
  #define ROSCPP_DECL
#endif

后面的两个初始化函数能够替换原有的初始函数(alternate ROS initialization function.)
M_string和VP_string定义在此处

/*
 * Copyright (C) 2008, Morgan Quigley and Willow Garage, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef CPP_CORE_TYPES_H
#define CPP_CORE_TYPES_H

#include <string>
#include <vector>
#include <map>
#include <set>
#include <list>

#include <boost/shared_ptr.hpp>

namespace ros {
    
    

typedef std::vector<std::pair<std::string, std::string> > VP_string;
typedef std::vector<std::string> V_string;
typedef std::set<std::string> S_string;
typedef std::map<std::string, std::string> M_string;
typedef std::pair<std::string, std::string> StringPair;

typedef boost::shared_ptr<M_string> M_stringPtr;

}

#endif // CPP_CORE_TYPES_H

下面是简单的系统状态判断函数:


是否已经初始化了

ROSCPP_DECL bool isInitialized();

是否已经结束节点了

ROSCPP_DECL bool isShuttingDown();

调用等待回调函数

ROSCPP_DECL void spin();
ROSCPP_DECL void spin(Spinner& spinner);
ROSCPP_DECL void spinOnce();

等待结束节点

ROSCPP_DECL void waitForShutdown();

返回当前节点是否正常工作

ROSCPP_DECL bool ok();

结束一个节点

ROSCPP_DECL void shutdown();

请求结束一个节点

ROSCPP_DECL void requestShutdown();

开始一个节点(自动开启,不需要手动开)

ROSCPP_DECL void start();

节点是否已经通过手动开启

ROSCPP_DECL bool isStarted();

返回全局回调函数的队列

ROSCPP_DECL CallbackQueue* getGlobalCallbackQueue();

操作ros的变量

ROSCPP_DECL std::string getROSArg(int argc, const char* const* argv, const std::string& arg);
ROSCPP_DECL void removeROSArgs(int argc, const char* const* argv, V_string& args_out);

各个函数的具体实现过程见下一篇博客分析

猜你喜欢

转载自blog.csdn.net/yyl80/article/details/124936442