ROS 节点通过topic 或者service 控制节点启动关闭

需求 在安卓端想通过topic 或者 service 控制某人节点的启动 关闭

代码

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
#include <stdio.h>
using namespace std;


int statue_flag = 0;
bool exit_flag = false;
void HandleCmdCallback(const std_msgs::String::ConstPtr& msg)
{
	ROS_INFO("I herad :[%s]",msg->data.c_str());
	
/*
	if(msg->data == "start")
	{
		ROS_INFO("start");
		system("/home/tank/carto030_ws/src/tank_app/sh/start_cartographer.sh");	
		ROS_INFO("start  end");
	}
	if(msg->data == "close")
	{
		ROS_INFO("close");
		system("/home/tank/carto030_ws/src/tank_app/sh/shut_cartographer.sh");		
	}
*/
	if(msg->data == "start")
	{
		if(statue_flag != 0)
		{
		    statue_flag = 0;
		    ::ros::shutdown();
     		}
		else
		{
		  cout << "statue_flag err "<<endl;
		}
	}
	if(msg->data == "close")
	{
		
		  if(statue_flag != 1)
		  {
		      ::ros::shutdown();
		      statue_flag = 1;

		  }
	 	  else
		  {
		     cout << "statue_flag err "<<endl;
		  }
			
	}
	if(msg->data == "shutdown")
	{
		exit_flag = true;
		ROS_INFO("shutdown");
		::ros::shutdown();
	}

}


void start_cartographer(int argc, char** argv)
{
  
  ros::init(argc, argv, "cartographer_node");
  ros::NodeHandle nh;


  ROS_INFO("cartographer_node");

  ros::Subscriber sub = nh.subscribe("cartographer_topic",1000,HandleCmdCallback);
  //::ros::start();
  
  ros::spin();

  ROS_INFO("shutdown");
  cout<<("cartographer_node shutdown\n");

}


void manage_node(int argc, char** argv)
{
 
  ros::init(argc, argv, "tank_app");
  ros::NodeHandle nh;

  ROS_INFO("manage_node");

  ros::Subscriber sub = nh.subscribe("tank_control",1000,HandleCmdCallback);
 
  ros::spin();

  ROS_INFO("shutdown");
  cout<<("manerage end\n")<<endl;

}

int main(int argc, char** argv)
{

	int loop_cnt =0;

	//for(loop_cnt = 0; loop_cnt < 3; loop_cnt++)
    while(exit_flag == false)
	{
		cout<<"loop_cnt"<< loop_cnt<<endl;
		switch(statue_flag)
		{
		    case 0:
			start_cartographer(argc, argv);
			statue_flag = 1;
			break;
		    case 1:
			manage_node(argc, argv);
			statue_flag = 0;
			// sleep(10);
			break;
		   default:

		   break;
		}
		loop_cnt++;

		while(ros::ok())
		{
			sleep(10);
			cout<<"--wait for shutdown"<<endl;
		}
		
		{
			cout<<"--shutdown ok"<<endl;
		}

	}

ROS_INFO("exit exit");

#if 0
loop:
ros::init(argc, argv, "tank_app2s"); 
ros::NodeHandle nh;
ros::Subscriber sub2 = nh.subscribe("tank_control_XXX",1000,HandleCmdCallback);
ros::Rate loop_rate(10);
while(ros::ok())
{
    ros::spinOnce();
    loop_rate.sleep();
}

goto loop;

#endif
  return(0);
}

实例 安卓通过topic service 控制 cartographer_ros 建图启动与关闭node_main.c

/*
 * Copyright 2016 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cartographer_ros/node.h"
#include "cartographer_ros/node_options.h"
#include "cartographer_ros/ros_log_sink.h"
#include "gflags/gflags.h"
#include "tf2_ros/transform_listener.h"

#include <map>
#include <string>

#include "cartographer/io/proto_stream.h"
#include "cartographer/io/submap_painter.h"
#include "cartographer/mapping/proto/pose_graph.pb.h"
#include "cartographer/mapping/proto/serialization.pb.h"
#include "cartographer/mapping/proto/submap.pb.h"
#include "cartographer/mapping/submaps.h"
#include "cartographer/mapping_2d/probability_grid.h"
#include "cartographer/mapping_2d/submaps.h"
#include "cartographer/mapping_3d/submaps.h"
#include "cartographer_ros/ros_map.h"
#include "cartographer_ros/submap.h"
#include "glog/logging.h"
#include "std_msgs/String.h"


DEFINE_string(configuration_directory, "",
              "First directory in which configuration files are searched, "
              "second is always the Cartographer installation to allow "
              "including files from there.");
DEFINE_string(configuration_basename, "",
              "Basename, i.e. not containing any directory prefix, of the "
              "configuration file.");
DEFINE_string(map_filename, "", "If non-empty, filename of a map to load.");
DEFINE_bool(
    start_trajectory_with_default_topics, true,
    "Enable to immediately start the first trajectory with default topics.");
DEFINE_string(
    save_map_filename, "",
    "If non-empty, serialize state and write it to disk before shutting down.");

namespace cartographer_ros {
namespace {

void Run() {
  constexpr double kTfBufferCacheTimeInSeconds = 1e6;
  tf2_ros::Buffer tf_buffer{::ros::Duration(kTfBufferCacheTimeInSeconds)};
  tf2_ros::TransformListener tf(tf_buffer);
  NodeOptions node_options;
  TrajectoryOptions trajectory_options;
  std::tie(node_options, trajectory_options) =
      LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);

  Node node(node_options, &tf_buffer);
  
  if (!FLAGS_map_filename.empty()) {
  	LOG(ERROR)<<"-----------------LoadMap() FLAGS_map_filename:"<<FLAGS_map_filename;
    node.LoadMap(FLAGS_map_filename);
  }

  if (FLAGS_start_trajectory_with_default_topics) {
    node.StartTrajectoryWithDefaultTopics(trajectory_options);
  }
   
   //savemap_thread_ = new boost::thread(boost::bind(&Node::OptimizationAndSaveMap, this));
  ::ros::spin();
  LOG(ERROR)<<"-------::ros::spin();end------";
  node.FinishAllTrajectories();
  node.RunFinalOptimization();

  if (!FLAGS_save_map_filename.empty()) {
    //LOG(ERROR)<<"-------FLAGS_save_map_filename------mapname"<<FLAGS_save_map_filename;
    //node.SerializeState(FLAGS_save_map_filename);
  }
  //std::string map_path_name = "/home/tank/map/map_data.pbstream";
  //node.SerializeState(map_path_name);
  node.save_to_ros_map();
  LOG(ERROR)<<"-------exite run------";
}

}  // namespace
}  // namespace cartographer_ros
#if 0
int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);

  CHECK(!FLAGS_configuration_directory.empty())
      << "-configuration_directory is missing.";
  CHECK(!FLAGS_configuration_basename.empty())
      << "-configuration_basename is missing.";
/*
  CHECK(!FLAGS_save_map_pgm.empty())
  	  << "-save_map_pgm is missing.";
  	  */

  ::ros::init(argc, argv, "cartographer_node");
  ::ros::start();

  cartographer_ros::ScopedRosLogSink ros_log_sink;

  cartographer_ros::Run();
  ::ros::shutdown();
}

#else

int statue_flag = 1;
bool exit_flag = false;
void HandleCmdCallback(const std_msgs::String::ConstPtr& msg)
{
	LOG(INFO)<<"I herad :[%s]"<<msg->data.c_str();
	
/*
	if(msg->data == "start")
	{
		ROS_INFO("start");
		system("/home/tank/carto030_ws/src/tank_app/sh/start_cartographer.sh");	
		ROS_INFO("start  end");
	}
	if(msg->data == "close")
	{
		ROS_INFO("close");
		system("/home/tank/carto030_ws/src/tank_app/sh/shut_cartographer.sh");		
	}
*/


	if(msg->data == "start")
	{
		if(statue_flag != 0)
		{
		    statue_flag = 0;
		    ::ros::shutdown();
     		}
		else
		{
		  ROS_INFO("statue_flag err ");
		}
	}
	if(msg->data == "close")
	{
		
		  if(statue_flag != 1)
		  {
		      ::ros::shutdown();
		      statue_flag = 1;

		  }
	 	  else
		  {
		     ROS_INFO("statue_flag err ");
		  }
			
	}
	if(msg->data == "shutdown")
	{
		exit_flag = true;
		ROS_INFO("shutdown\n");
		::ros::shutdown();
	}

}

void  cartographer_node(int argc, char** argv) 
{

  LOG(ERROR)<<"************entry cartographer_node *******************";
  ::ros::init(argc, argv, "cartographer_node");
  ::ros::NodeHandle nh_xx;
  ::ros::start();

  cartographer_ros::ScopedRosLogSink ros_log_sink;

  ROS_INFO("manage_node");

  ::ros::Subscriber sub = nh_xx.subscribe("tank_control_c",1000,HandleCmdCallback);
  cartographer_ros::Run();
    LOG(ERROR)<<"------- exite cartographer_node ------";
//  ::ros::shutdown();
}

void manager_node(int argc, char** argv) 
{
  LOG(ERROR)<<"进入 : manager_node ";
  ::ros::init(argc, argv, "manager_node");
  ::ros::NodeHandle nh_xx;;
  //::ros::start();
  ::ros::Subscriber sub = nh_xx.subscribe("tank_control_m",1000,HandleCmdCallback);
  ::ros::spin();
  
  //cartographer_ros::Run();
  //::ros::shutdown();
LOG(ERROR)<<"退出 : manager_node ";
}
int main(int argc, char** argv) 
{
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);

  CHECK(!FLAGS_configuration_directory.empty())
      << "-configuration_directory is missing.";
  CHECK(!FLAGS_configuration_basename.empty())
      << "-configuration_basename is missing.";
 int loop_cnt = 0;
//for(loop_cnt = 0; loop_cnt < 3; loop_cnt++)
while(exit_flag == false)
{
	LOG(ERROR)<<"--------loop_cnt:  "<< loop_cnt;
	switch(statue_flag)
	{
	    case 0:
		cartographer_node(argc, argv);
		statue_flag = 1;
		break;
	    case 1:
		manager_node(argc, argv);
		statue_flag = 0;
		// sleep(10);
		break;
	   default:

	   break;
	}
	loop_cnt++;

	while(::ros::ok())
	{
		sleep(1);
		LOG(ERROR)<<("--wait for shutdown");
	}
	
	{
	    sleep(1);
		LOG(ERROR)<<("--shutdown ok");
	} 
	
}
	return 0;
ROS_INFO("exit exit");
}
#endif 


<think>好的,我现在需要帮助用户了解ROS节点的概念和用法。首先,根据用户提供的引用资料,我需要整合这些信息,确保准确性和全面性。 首先,引用[1]提到ROS节点是软件包中的可执行文件,使用客户端库进行通信,可以发布或订阅话题,提供或使用服务。引用[2]和[3]进一步解释了节点的基本功能和在ROS2中的应用。引用[4]涉及launch文件管理节点,而引用[5]虽然主要讲动作,但也提到了节点间的交互。 接下来,我需要将这些信息结构化。可能需要分为定义、功能、创建步骤、管理工具(如ros2 run和launch文件)以及应用场景。需要注意用户要求的中文回答,LaTeX格式的正确使用,以及生成相关问题。 需要确保独立公式用$$,行内用$,比如节点间通信可能涉及服务调用,可以用$语法。另外,检查引用标注是否正确,每个引用末尾添加对应的标识符,如[^1]。 然后,生成相关问题需要考虑用户可能的后续疑问,比如节点通信机制、命令行工具、launch文件编写或调试方法。确保问题相关且覆盖用户可能感兴趣的方向。 最后,验证回答是否符合用户的结构要求,包括示例代码的正确性(虽然当前问题没有代码示例,但引用的示例有Python代码),以及引用是否正确对应。确保没有使用markdown,段落清晰,语言自然。</think>### ROS节点概念及用法解析 #### 1. 节点定义 ROS节点(Node)是ROS系统中的基本执行单元,本质是**软件包中的可执行文件**。每个节点负责完成特定功能(如传感器数据处理、运动控制等),通过ROS客户端库(如`roscpp`或`rospy`)与其他节点通信[^3]。 #### 2. 节点核心功能 - **通信能力**: - 发布/订阅话题(Topic):异步数据传输,如传感器数据流$v(t)=s'(t)$ - 提供/调用服务(Service):同步请求-响应机制 - 执行动作(Action):支持长时间任务交互(包含目标、反馈、结果三部分)[^5] - **独立性**: $$ \text{节点}_A \xrightarrow{\text{Topic}} \text{节点}_B \xrightarrow{\text{Service}} \text{节点}_C $$ 不同节点可运行于同一设备或分布式网络环境[^2] #### 3. 节点创建步骤(以Python为例) ```python # 导入rclpy库 import rclpy from rclpy.node import Node class MyNode(Node): def __init__(self): super().__init__('my_node') # 节点名称注册 self.create_timer(1.0, self.timer_callback) def timer_callback(self): self.get_logger().info('Hello ROS2!') def main(): rclpy.init() # 初始化ROS上下文 node = MyNode() # 实例化节点 rclpy.spin(node) # 保持节点运行 rclpy.shutdown() # 关闭节点 ``` #### 4. 节点管理工具 | 工具 | 功能描述 | 示例命令 | |------------------|----------------------------|-----------------------------| | `ros2 run` | 运行单个节点 | `ros2 run package_name node_name` | | launch文件[^4] | 批量启动节点及参数配置 | ```<launch><node pkg="..." .../></launch>``` | | `ros2 node list` | 查看活跃节点列表 | 输出:`/my_node /camera_node` | #### 5. 典型应用场景 - **多传感器融合**:相机节点+雷达节点→数据融合节点 - **机械臂控制**:路径规划节点→逆运动学求解节点→执行器驱动节点 - **自主导航**:建图节点+定位节点+路径规划节点[^3]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值