动机:
这篇博客主要关注一个问题: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);
各个函数的具体实现过程见下一篇博客分析