ros下tcp通信的过程

2023-05-16

                                                       ros框架下的tcp通信的过程

    博主在编写一个需要通过wifi传输两个整数和一个状态的问题中,通过构建ros(Ubuntu16.04)框架下的tcp(c++)通信过程解决了问题。

一、ros串口通信的实现

    首先我们需要从单片机中接收需要传输的数据,为了方便,我将状态和两个整数合成为一个七个字符的字符串传输,在需要调用的地方解析该字符串。

    ros的串口通信我们可以使用官方自带的serial通信包,主要调用了串口打开函数open()和串口读取函数read(),至于ros节点的创建与话题的发布,我在这里不再赘述,不太了解的可以参考http://wiki.ros.org/ROS。

    该ros功能包里我自定义了消息类型wifi_good.msg,虽然里面只有string一种消息类型,但是为以后程序改进留有空间

string message
    具体代码如下:
#include "ros/ros.h"
#include <std_msgs/Empty.h>
#include <std_msgs/String.h>
#include <serial/serial.h>  
#include <std_msgs/String.h>
#include <wifi_nice/wifi_good.h>


serial::Serial ser; 


int main (int argc, char** argv)
{
  //初始化节点
  ros::init(argc, argv, "serial_common_node");
  //声明节点句柄
  ros::NodeHandle nh;
  //发布主题
  ros::Publisher read_pub = nh.advertise<wifi_nice::wifi_good>("read", 33);


  try
  {
  //设置串口属性,并打开串口
      ser.setPort("/dev/ttyUSB0");
      ser.setBaudrate(921600);
      serial::Timeout to = serial::Timeout::simpleTimeout(1000);
      ser.setTimeout(to);
      ser.open();
  }
  catch (serial::IOException& e)
  {
      ROS_ERROR_STREAM("Unable to open port ");
      return -1;
  }
  //检测串口是否已经打开,并给出提示信息
  if(ser.isOpen())
  {
      ROS_INFO_STREAM("Serial Port initialized");
  }
  else
  {
      return -1;
  }


  ros::Rate loop_rate(50);
  while(ros::ok())
  {

      if(ser.available()){
          ROS_INFO_STREAM("Reading from serial port\n");
          wifi_nice::wifi_good result;
          result.message=ser.read(ser.available());
          ROS_INFO_STREAM("Read: " << result.message);
          read_pub.publish(result);
      }

      //处理ROS的信息,比如订阅消息,并调用回调函数
      ros::spinOnce();
      loop_rate.sleep();

  }



}

二、话题的订阅与消息的发送

    以上的代码中将消息发送到滤read话题上,我们通过订阅该话题来实现传输

    为了方便,我在回调函数中写了tcp通信的代码(需要注意的是在每次调用回调函数时,一定要记得在回调函数后面添加ros::spin()或ros::spinOnce()函数,不清楚区别的可以自行百度),通过限定回调函数调用的频率,实现tcp消息传输的循环发送。

博主需要实现一个客户端对应多个服务端,因此定义了多个IP地址,通过定义多个socket来实现该过程。

     tcp传输主要调用了write()函数,具体代码如下:

#include <ros/ros.h>
#include<iostream>
#include<cstring>
#include<string>
#include <fstream>
#include <std_msgs/String.h>
#include <std_msgs/Empty.h>
#include <wifi_nice/wifi_good.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SERVPORT 8080
#define MAXDATASIZE 100
#define SERVER_IP_1 "192.168.1.102"
#define SERVER_IP_2 "192.168.1.101"
#define SERVER_IP_3 "192.168.1.104"
using namespace std;

void read_callback(const wifi_nice::wifi_good msg)
{
  char DATA[MAXDATASIZE];
  istringstream stream1;
  stream1.str(msg.message);
  int number;
  stream1 >> number;
  sprintf(DATA,"%d",number);
  ROS_INFO_STREAM("RECEIVE: "<< number);


      int sockfd_1;
      struct sockaddr_in serv_addr_1;

	if ((sockfd_1 = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

		perror("socket error!");
		exit(1);
	}

	bzero(&serv_addr_1, sizeof(serv_addr_1));
	serv_addr_1.sin_family = AF_INET;
	serv_addr_1.sin_port = htons(SERVPORT);
	serv_addr_1.sin_addr.s_addr = inet_addr(SERVER_IP_1);

	connect(sockfd_1, (struct sockaddr *) &serv_addr_1, sizeof(struct sockaddr));
        write(sockfd_1, DATA, sizeof(DATA));
	close(sockfd_1);

       
       //int sockfd_2;
       //struct sockaddr_in serv_addr_2;

	//if ((sockfd_2 = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
       
        //	perror("socket error!");
	//	exit(1);
	//}

	//bzero(&serv_addr_2, sizeof(serv_addr_2));
	//serv_addr_2.sin_family = AF_INET;
	//serv_addr_2.sin_port = htons(SERVPORT);
	//serv_addr_2.sin_addr.s_addr = inet_addr(SERVER_IP_2);

	//connect(sockfd_2, (struct sockaddr *) &serv_addr_2, sizeof(struct sockaddr));
	//write(sockfd_2, DATA, sizeof(DATA));
	//close(sockfd_2);

        
        //int sockfd_3;
        //struct sockaddr_in serv_addr_3;

	//if ((sockfd_3 = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        
 		//perror("socket error!");
		//exit(1);
	//}

	//bzero(&serv_addr_3, sizeof(serv_addr_3));
	//serv_addr_3.sin_family = AF_INET;
	//serv_addr_3.sin_port = htons(SERVPORT);
	//serv_addr_3.sin_addr.s_addr = inet_addr(SERVER_IP_3);

	//connect(sockfd_3, (struct sockaddr *) &serv_addr_3, sizeof(struct sockaddr));
	//write(sockfd_3, DATA, sizeof(DATA));
	//close(sockfd_3);

}


int main(int argc, char **argv)
{
  
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("read", 1, read_callback);
  ros::spin(); 
  return 0;
}

三、消息的接收与发布

    消息发送后,需要在上位机创建一个功能包实现消息的接受与发布,具体代码如下:

#include <ros/ros.h>
#include <wifi_get/wifi_nice.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#define SERVPORT 8080
#define BACKLOG 10
#define MAXSIZE 1024
using namespace std;

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

        int sockfd, client_fd;
	struct sockaddr_in my_addr;
	struct sockaddr_in remote_addr;
	//创建套接字
if ((sockfd = socket( AF_INET, SOCK_STREAM, 0 ) )== -1 ){
		perror("socket create failed!");
		exit(1);
	}
	//绑定端口地址
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(SERVPORT);
	my_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(my_addr.sin_zero), 8);
	if (bind(sockfd, (struct sockaddr*) &my_addr, sizeof(struct sockaddr))== -1) {
		perror("bind error!");
		exit(1);
	}
	//监听端口
	if (listen(sockfd, BACKLOG) == -1) {
		perror("listen error");
		exit(1);
	}


  //用于解析ROS参数,第三个参数为本节点名
  ros::init(argc, argv, "talker");
  ros::NodeHandle nh;
  wifi_get::wifi_nice msg;
  msg.message="0000000";
  ros::Publisher pub = nh.advertise<wifi_get::wifi_nice>("read", 1);
  ros::Rate loop_rate(1.0);

  while (1)
  {
    
    //int sin_size = sizeof(struct sockaddr_in);
socklen_t sin_size = sizeof(struct sockaddr_in);
if ((client_fd = accept(sockfd,(struct sockaddr*) &remote_addr,&sin_size)) == -1){
			perror("accept error!");
			continue;
		}

                

	
                        char buf[MAXSIZE];
			//接受client发送的请示信息
			int rval;
			
			if ((rval = read(client_fd, buf, MAXSIZE)) < 0) {
				perror("reading stream error!");
				continue;
			}
                

			string s(&buf[0],&buf[strlen(buf)]);  
                        msg.message=s;
                        cout<<"发布的数据为:"<<s<<endl;
                        
			close(client_fd);
	
    
                        pub.publish(msg);
    //根据前面定义的频率, sleep 1s
    loop_rate.sleep();
}
  return 0;
} 

    数据在read话题上发布后,我们在需要应用到传输消息的主函数中通过回调函数,解析传输的消息,实现消息的应用,具体代码如下:

//ROS头文件
#include <ros/ros.h>
#include <string.h>
#include <wifi_get/wifi_nice.h>
#include <unistd.h>
#include <iostream>
using namespace std;


void wifi_Callback(const wifi_get::wifi_nice msg)
{  
    istringstream stream_ck;
    stream_ck.str(msg.message);
    int number;
    stream_ck>>number;
    ROS_INFO_STREAM("msg: "<<msg.message);
    int left,right,get;
    left=number%1000;
    right=(number/1000)%1000;
    get=(number/1000)/1000;
    ROS_INFO_STREAM("left: "<<left<<"     right:"<<right);
    ROS_INFO_STREAM("------------------- ");
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("read", 1, wifi_Callback);
  ros::spin(); 
  return 0;
}
    至此,我们实现了ros框架下tcp通信的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ros下tcp通信的过程 的相关文章

  • 无法分配请求的地址 - 可能的原因?

    我有一个由主服务器和分布式从服务器组成的程序 从属服务器向服务器发送状态更新 如果服务器在固定时间内没有收到特定从属服务器的消息 则会将该从属服务器标记为关闭 这种情况一直在发生 通过检查日志 我发现从站只能向服务器发送一个状态更新 然后永
  • 如何强制关闭 TcpListener

    我有一个通过 tcpListener 进行通信的服务 问题是当用户重新启动服务时 抛出 地址已在使用 异常 并且服务在几分钟左右无法启动 有没有办法告诉系统终止旧连接 以便我可以打开一个新连接 我不能只使用随机端口 因为服务无法通知客户端端
  • Erlang gen_tcp 连接问题

    简单的问题 这段代码 client gt SomeHostInNet localhost to make it runnable on one machine ok Sock gen tcp connect SomeHostInNet 56
  • 中断 Select 以添加另一个要在 Python 中监视的套接字

    我正在 Windows XP 应用程序中使用 TCP 实现点对点 IPC 我正在使用select and socketPython 2 6 6 中的模块 我有三个 TCP 线程 一个读取线程通常会阻塞select 一个通常等待事件的写入线程
  • 如何抑制Windows防火墙的Windows安全警报?

    当我从这里找到的 ZeroMQ 指南中用 C 创建 Hello World 示例时 http zguide zeromq org page all Ask and Ye Shall Receive http zguide zeromq or
  • 为什么SOCKS5需要通过UDP中继UDP?

    The SOCKS5 https en wikipedia org wiki SOCKS SOCKS5协议 描述为RFC1928 https www rfc editor org rfc rfc1928提供对 UDP 的支持 总而言之 希望
  • 使用 TCP 时是否需要使用校验和来保护我的消息?

    使用 TCP 作为网络协议 在通过线路发送消息之前 我会为每条消息的大小 以及可能的校验和 添加前缀 我想知道 计算和传输消息的校验和是否有意义 以确保消息将被不变地传递 如果以及何时传递 例如因为一些网络错误 目前 我在发送消息本身之前发
  • StreamWriter的正确使用

    经过几次尝试后 我无法让 StreamWriter 正确构建 工作 所以我做了一些根本错误的事情 C Visual Studio 我有一个现有的 TCP 客户端 它连接并充当读取器 它工作正常 private System Net Sock
  • 用 C 语言进行非阻塞 udp 套接字编程:我能得到什么?

    我在理解从非阻塞 UDP 套接字返回什么recv recvfrom 时遇到问题 与 TCP 相比更具体一点 如果我错了 请纠正我 阻塞套接字 TCP 或 UDP 在缓冲区中有一些数据之前不会从 recv 返回 这可以是一定数量的字节 TCP
  • 恐慌:拨打 tcp 127.0.0.1:3306:连接:连接被拒绝

    我正在尝试使用 golang gin gorm 从 docker 连接 mysql 服务器 构建本身已经成功 但是如标题所示 出现了以下错误 panic dial tcp 127 0 0 1 3306 connect connection
  • 创建 ip 网络数据包 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我必须使用任何协议手动创建自己的网络
  • ConnectionTimeout 与 SocketTimeout

    我正在使用的库有问题 可能是图书馆的问题 也可能是我用错了 基本上 当我这样做时 超时以毫秒为单位 ignitedHttp setConnectionTimeout 1 v short ignitedHttp setSocketTimeou
  • PHP 通过 TCP/IP 发送消息

    我尝试通过 TCP IP 从 PHP 网站向 Arduino 发送消息 使用以下代码我可以从 php 网站发送消息 问题是 当第一次调用该网站时 消息不会立即发送 网站刷新几次后 消息就会到达 但逻辑上很多次 就像网站刷新量一样 已经尝试将
  • 在 Google Colaboratory 上运行gym-gazebo

    我正在尝试在 Google Colaboratory 上运行gym gazebo 在Colab上运行gazebo服务器 没有gui的gazebo 有问题 显示警告 Unable to create X window Rendering wi
  • 使用 TcpClient 通过 C# 通过 TCP 发送多个文件

    我正在尝试使用 C TcpClient 通过 TCP 发送多个文件 对于单个文件来说它效果很好 但是当我有多个文件时 它只发送第一个文件 这是我的代码 发送文件 try TcpClient tcpClient new TcpClient N
  • 在 ROS 中运行tensorRT时出现“LogicError:explicit_context_dependent失败:无效的设备上下文 - 没有当前活动的上下文?”

    我在 TensorRT 使用 python 中有一个推理代码 我想在 ROS 中运行此代码 但在尝试分配缓冲区时出现以下错误 LogicError explicit context dependent failed invalid devi
  • 伪TCP通道

    什么是伪 TCP 通道以及如何实现 伪 TCP 是一种协议 它实现了 TCP 的一些思想 通过不可靠的基于数据包的接口提供可靠的数据流 例如 如果您只能访问 UDP 但想要 一种可靠的方式来传递数据 则可以使用此方法 您可以在这里找到示例代
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时

    我试图通过 SO RCVTIMEO 套接字选项在 Ruby 中设置套接字超时 但它似乎对任何最近的 nix 操作系统都没有影响 使用 Ruby 的 Timeout 模块不是一个选择 因为它需要为每个超时生成和连接线程 这可能会变得昂贵 在需
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成

随机推荐

  • 故障解决:端口已被占用 1080

    更新记录 版本时间修订内容1 02018 3 28增加了方案二1 12019 8 9增加了方案三 问题的提出 实验环境 xff1a Win7 64bit 也许你会碰到以下错误 xff1a 本文给出2种解决方案 方案一 既然说端口已被占用 x
  • git cherry-pick 详解 —— Git 学习笔记 18

    git cherry pick 详解 初识 git cherry pick xff08 拣选 xff09 拣选会提取某次提交的补丁 xff0c 之后尝试将其重新应用到当前分支上 这种方式在你只想引入特性分支中的某个提交时很有用 假设你的项目
  • 问题解决: SSR 的 1080 端口被占用

    问题解决 xff1a SSR 的 1080 端口被占用 在我的博客 故障解决 xff1a 端口已被占用 1080 中已经讨论了一些方法 xff0c 但也不是每次都能成功 对于 SSR xff0c 我们完全可以换一种思路 xff1a 既然 1
  • USB开发简述

    由于工作需要 xff0c 接触了USB xff0c 经过这两三周的学习 xff0c 我只想说一句 xff0c 我们USB说简单也简单 xff0c 说复杂也有那么多知识 xff01 这怎么说呢 xff1f 简单 xff1a 无非就那几个结构体
  • 基于PX4六旋翼无人机百米悬停定点降落

  • 手把手教你实现ROS Melodic+Realsense D435i

    硬件配置 xff1a HP ProDesk 480 G6 MT 系统内存 xff1a 8G 处理器 xff1a Intel i7 8700 CPU 操作系统 xff1a Ubuntu 18 04 相机配置 xff1a Intel Reals
  • pixhawk调试过程中QGC报错显示问题及解决方案汇总

    1 室内环境下解锁无人机 xff0c 报错 xff1a Not arming geofence RTL requiers valid home 解决 xff1a 去掉安全设置里面的地理围栏 xff0c 否则只能在有GPS的环境下解锁
  • pixhawk4连接PX4 Flow光流传感器调试过程记录

    主控型号 Pixhawk4 光流型号 PX4 FLow V1 3 地面站 QGroundControl 1 拔掉PX4 Flow连接Pixhawk4的连接线 用USB连接PX4 Flow 打开QGC地面站 烧写固件 烧写完成后就可以在QGC
  • 使用Xshell连接Ubuntu主机失败

    1 问题 在将一台Ubuntu系统的电脑作为服务器 xff0c 使用Xshell连接时 xff0c 发生如下错误 此时使用ping工具检查是否能够ping通 说明能够连接上 xff0c 但是不能使用Xshell进行远程操作 2 解决方法 首
  • P900数传参数配置

    端口定义 xff1a xff08 从左往右 xff09 GND RX TX 5V 调试软件 xff1a X CTU 启动调试 xff1a 按住数传板上SW2 xff0c 同时按住SW1 xff0c 然后松开SW2 xff0c 再松开SW1
  • 利用ROS实现PX4 offboard板外控制

    基于ROS Melodic xff0c 以px4开发者手册实例程序为例 xff0c 实现gazebo下无人机起飞两米悬停 xff0c 具体操作分为三步 xff1a 1 创建工作空间 xff0c 建立offboard包 2 构建mavros
  • Jetson TX2开发板配置Intel T265环境的必要解决方式

    在Jetson TX2配置T265相关依赖时会发生错误 xff0c 因此需要提前对相关参数进行设置 xff0c 主要要将网络设置里面的相关参数改成下图的配置 xff1a
  • pixhawk日志ulg格式转matlab数据csv格式

    1 windows下打开Anconda Prompt xff0c 执行pip install pyulog安装pyulog包 2 在日志文件所在文件夹下执行ulog2csv 文件名 ulg即可生成相关的csv文件
  • 悲催的秋招之路

    个人情况 双非工科硕 民办本 专科起点 基础不行 专业知识不扎实 无技术无论文无项目 投递记录 企业名称 投递时间 岗位1 岗位2 岗位3 岗位4 国电南自 2021 5 19 嵌入式软件研发工程师 民生银行 2021 5 26 金融科技方
  • Matlab读取EXCEL文本中的数据并绘制二维三维曲线图脚本

    Matlab读取EXCEL文本中的数据并绘制二维三维曲线图需要将EXCEL保存为CSV格式 xff0c 然后取数据成矩阵进行处理 转CSV的方式 xff1a pixhawk日志ulg格式转matlab数据csv格式 1 导入文件 span
  • 零基础教会你用github创建个人博客网站

    1 创建账号 进入github网站 xff0c 在网站首页右上角进行用户注册 2 填写相关信息 按照提示填写相关信息完成用户注册 3 搭建个人博客库 进入个人主页 xff0c 在右上角选择 43 好 xff0c 进入 new reposit
  • SV2-4G移动终端使用配置与使用

    一 硬件连接 1接位置天线 xff0c 2接方向天线 xff0c 3接4G天线 xff0c 4接GPS配置专用线 xff0c 5接4G配置专用线 二 运行状态识别 1处为指示灯 xff08 运行 SIM卡 网络 电源 xff09 xff0c
  • yapi插件开发及安装的一些备注

    yapi官方文档有些缺失 xff0c 这里做一下补充 xff0c 官方文档地址 xff1a https hellosean1025 github io yapi documents redev html 插件开发需要调试 xff0c 这个需
  • VSCode修改编辑器(代码窗口)背景色

    VSCode 的背景色是放在主题里面定义的 xff0c 所以在vscode的设置中无法修改到编辑器也就是代码窗口的背景色 xff0c 对应想要自定义编辑器背景的同志们来说 xff0c 可以通过修改主题文件来实现 xff0c 操作起来也并不复
  • ros下tcp通信的过程

    ros框架下的tcp通信的过程 博主在编写一个需要通过wifi传输两个整数和一个状态的问题中 xff0c 通过构建ros xff08 Ubuntu16 04 框架下的tcp c 43 43 通信过程解决了问题 一 ros串口通信的实现 首先