希望大家收藏:
本文更新地址:https://haoqchen.site/2018/04/28/ROS-node-init/
左側專欄還在更新其他ROS實用技巧哦,關注一波?
很多ROS新手編寫節點的時候都不知道要怎么才能Ctrl+c退出,根本都沒有注意到一個節點的生命流程,看完你就懂了~~
先上程序:
完整版工程已經上傳到github:https://github.com/HaoQChen/init_shutdown_test,下載完麻煩大家點個贊
所有知識點都寫在注釋里了,請慢慢閱讀,每個語句前面的注釋是ROS官方注釋,后面的注釋則是作者自己寫的
#include "ros/ros.h"
#include <signal.h>
void MySigintHandler(int sig)
{
	//這里主要進行退出前的數據保存、內存清理、告知其他節點等工作
	ROS_INFO("shutting down!");
	ros::shutdown();
}
int main(int argc, char** argv){
//ros::init()
	/**
	  * The ros::init() function needs to see argc and argv so that it can perform
	  * any ROS arguments and name remapping that were provided at the command line. For programmatic
	  * remappings you can use a different version of init() which takes remappings
	  * directly, but for most command-line programs, passing argc and argv is the easiest
	  * way to do it.  The third argument to init() is the name of the node.
	  *
	  * You must call one of the versions of ros::init() before using any other
	  * part of the ROS system.
	*/
	ros::init(argc, argv, "ist_node");
	//初始化節點名字必須在最前面,如果ROS系統中出現重名,則之前的節點會被自動關閉
	//如果想要多個重名節點而不報錯,可以在init中添加ros::init_options::AnonymousName參數
	//該參數會在原有節點名字的后面添加一些隨機數來使每個節點獨一無二
	//ros::init(argc, argv, "my_node_name", ros::init_options::AnonymousName);
//ros::NodeHandle
	/**
	  * NodeHandle is the main access point to communications with the ROS system.
	  * The first NodeHandle constructed will fully initialize this node, and the last
	  * NodeHandle destructed will call ros::shutdown() to close down the node.
	*/
	ros::NodeHandle h_node;
	//獲取節點的句柄,init是初始化節點,這個是Starting the node
	//如果不想通過對象的生命周期來管理節點的開始和結束,你可以通過ros::start()和ros::shutdown() 來自己管理節點。
	
	ros::Rate loop_rate(1);
	//loop once per second
	//Cannot use before the first NodeHandle has been created or ros::start() has been called.
//shut down
	signal(SIGINT, MySigintHandler);
	//覆蓋原來的Ctrl+C中斷函數,原來的只會調用ros::shutdown()
	//為你關閉節點相關的subscriptions, publications, service calls, and service servers,退出進程
//run status
	int sec = 0;
	while(ros::ok() && sec++ < 5){
		loop_rate.sleep();
		ROS_INFO("ROS is ok!");
		ros::spinOnce();
	}
	//ros::ok()返回false,代表可能發生了以下事件
		//1.SIGINT被觸發(Ctrl-C)調用了ros::shutdown()
		//2.被另一同名節點踢出 ROS 網絡
		//3.ros::shutdown()被程序的另一部分調用
		//4.節點中的所有ros::NodeHandles 都已經被銷毀
	//ros::isShuttingDown():一旦ros::shutdown()被調用(注意是剛開始調用,而不是調用完畢),就返回true
	//一般建議用ros::ok(),特殊情況可以用ros::isShuttingDown()
	ROS_INFO("Node exit");
	printf("Process exit\n");
	return 0;
}下載工程運行后可以看到,終端每隔一秒會輸出ROS is ok!的信息
- 如果5秒之內沒有按下Ctrl+C正常退出,則會正常退出。輸出:

- 如果5秒內按下了Ctrl+C,則會調用MySigintHandler,然后ros::shutdown();從終端信息我們可以看到,調用ros::shutdown();后,所有ROS服務已經不可以使用,連ROS_INFO也是不能用的,輸出信息失敗。所以在程序中要密切注意退出部分的程序不要使用ROS的東西。

參考:
ROS官網:roscppOverviewInitialization and Shutdown
https://blog.csdn.net/wuguangbin1230/article/details/76889753
http://blog.sina.com.cn/s/blog_8a2281f70102xi2v.html
