(2)NodeHandle源码分析
2018-06-19 本文已影响7人
PIBOT导航机器人
官方demo
初始化完成后创建了个NodeHandle
ros::NodeHandle n;
NodeHandle::NodeHandle
具体构造函数见下面文件
node_handle.h
node_handle.cpp
NodeHandle(const std::string& ns = std::string(), const M_string& remappings = M_string());
NodeHandle::NodeHandle(const std::string& ns, const M_string& remappings)
: namespace_(this_node::getNamespace())
, callback_queue_(0)
, collection_(0)
{
std::string tilde_resolved_ns;
if (!ns.empty() && ns[0] == '~')// starts with tilde
tilde_resolved_ns = names::resolve(ns);
else
tilde_resolved_ns = ns;//传入全空 这里也为空
construct(tilde_resolved_ns, true);
initRemappings(remappings);
}
construct
void NodeHandle::construct(const std::string& ns, bool validate_name)
{
if (!ros::isInitialized())
{
ROS_FATAL("You must call ros::init() before creating the first NodeHandle");
ROS_BREAK();
}
collection_ = new NodeHandleBackingCollection;
unresolved_namespace_ = ns;
// if callback_queue_ is nonnull, we are in a non-nullary constructor
if (validate_name)
namespace_ = resolveName(ns, true);
else
{
namespace_ = resolveName(ns, true, no_validate());
// FIXME validate namespace_ now
}
ok_ = true;
boost::mutex::scoped_lock lock(g_nh_refcount_mutex);
if (g_nh_refcount == 0 && !ros::isStarted())
{
g_node_started_by_nh = true;
ros::start();
}
++g_nh_refcount;
}
collection_ = new NodeHandleBackingCollection;
构造了个NodeHandleBackingCollection
对象,参见NodeHandleBackingCollection
ROS
相关的数据,有ros::Publisher
, ros::Subscriber
, ros::ServiceServer
, ros::ServiceClient
后面加了引用计数保证ros:start()
只被调用一次,但从名字看应该是核心启动函数
ros::start
直接看ros::start
void start()
{
boost::mutex::scoped_lock lock(g_start_mutex);
if (g_started)
{
return;
}
g_shutdown_requested = false;
g_shutting_down = false;
g_started = true;
g_ok = true;
bool enable_debug = false;
std::string enable_debug_env;
if ( get_environment_variable(enable_debug_env,"ROSCPP_ENABLE_DEBUG") )
{
try
{
enable_debug = boost::lexical_cast<bool>(enable_debug_env.c_str());
}
catch (boost::bad_lexical_cast&)
{
}
}
char* env_ipv6 = NULL;
#ifdef _MSC_VER
_dupenv_s(&env_ipv6, NULL, "ROS_IPV6");
#else
env_ipv6 = getenv("ROS_IPV6");
#endif
bool use_ipv6 = (env_ipv6 && strcmp(env_ipv6,"on") == 0);
TransportTCP::s_use_ipv6_ = use_ipv6;
XmlRpc::XmlRpcSocket::s_use_ipv6_ = use_ipv6;
#ifdef _MSC_VER
if (env_ipv6)
{
free(env_ipv6);
}
#endif
param::param("/tcp_keepalive", TransportTCP::s_use_keepalive_, TransportTCP::s_use_keepalive_);
//下面2句主要是检查退出请求
PollManager::instance()->addPollThreadListener(checkForShutdown);
XMLRPCManager::instance()->bind("shutdown", shutdownCallback);
initInternalTimerManager();
TopicManager::instance()->start();
ServiceManager::instance()->start();
ConnectionManager::instance()->start();
PollManager::instance()->start();
XMLRPCManager::instance()->start();
if (!(g_init_options & init_options::NoSigintHandler))
{
signal(SIGINT, basicSigintHandler);
}
ros::Time::init();
if (!(g_init_options & init_options::NoRosout))
{
g_rosout_appender = new ROSOutAppender;
ros::console::register_appender(g_rosout_appender);
}
if (g_shutting_down) goto end;
{
ros::AdvertiseServiceOptions ops;
ops.init<roscpp::GetLoggers>(names::resolve("~get_loggers"), getLoggers);
ops.callback_queue = getInternalCallbackQueue().get();
ServiceManager::instance()->advertiseService(ops);
}
if (g_shutting_down) goto end;
{
ros::AdvertiseServiceOptions ops;
ops.init<roscpp::SetLoggerLevel>(names::resolve("~set_logger_level"), setLoggerLevel);
ops.callback_queue = getInternalCallbackQueue().get();
ServiceManager::instance()->advertiseService(ops);
}
if (g_shutting_down) goto end;
if (enable_debug)
{
ros::AdvertiseServiceOptions ops;
ops.init<roscpp::Empty>(names::resolve("~debug/close_all_connections"), closeAllConnections);
ops.callback_queue = getInternalCallbackQueue().get();
ServiceManager::instance()->advertiseService(ops);
}
if (g_shutting_down) goto end;
{
bool use_sim_time = false;
param::param("/use_sim_time", use_sim_time, use_sim_time);
if (use_sim_time)
{
Time::setNow(ros::Time());
}
if (g_shutting_down) goto end;
if (use_sim_time)
{
ros::SubscribeOptions ops;
ops.init<rosgraph_msgs::Clock>(names::resolve("/clock"), 1, clockCallback);
ops.callback_queue = getInternalCallbackQueue().get();
TopicManager::instance()->subscribe(ops);
}
}
if (g_shutting_down) goto end;
g_internal_queue_thread = boost::thread(internalCallbackQueueThreadFunc);
getGlobalCallbackQueue()->enable();
ROSCPP_LOG_DEBUG("Started node [%s], pid [%d], bound on [%s], xmlrpc port [%d], tcpros port [%d], using [%s] time",
this_node::getName().c_str(), getpid(), network::getHost().c_str(),
XMLRPCManager::instance()->getServerPort(), ConnectionManager::instance()->getTCPPort(),
Time::useSystemTime() ? "real" : "sim");
// Label used to abort if we've started shutting down in the middle of start(), which can happen in
// threaded code or if Ctrl-C is pressed while we're initializing
end:
// If we received a shutdown request while initializing, wait until we've shutdown to continue
if (g_shutting_down)
{
boost::recursive_mutex::scoped_lock lock(g_shutting_down_mutex);
}
}
- 下面2句主要信号检测,关闭
PollManager::instance()->addPollThreadListener(checkForShutdown);
XMLRPCManager::instance()->bind("shutdown", shutdownCallback);
可以看到这里注册了2个Service, 输入rosservice list可以验证
,这里具体实现先不关注
initInternalTimerManager
该函数会构造InternalTimerManager
对象
typedef TimerManager<WallTime, WallDuration, WallTimerEvent> InternalTimerManager;
这个是一个内部的定时器管理器
可以看到在这里有使用到该对象
getInternalTimerManager
,即主要TransportPublisherLink
类,主要是对重试的处理
start
接下来的几个start
TopicManager::instance()->start();
ServiceManager::instance()->start();
ConnectionManager::instance()->start();
PollManager::instance()->start();
XMLRPCManager::instance()->start();