【esp32&ROS】ROS与多个ESP32的无线连接

目录

一、前言

二、ROS与单个ESP32的连接

2.1 ESP32端

2.2 主机端

三、ROS与多个ESP32的连接

3.1 ESP32_1端

3.2 ESP32_2端

3.3 主机端

 参考文献 


一、前言

        最近的工作中需要用到ROS和多个ESP32单片机无线通讯(wifi)的需求,因此这里简单记录一下这个过程中遇到的坑,以供参考。

        说来惭愧,由于本人不是计算机领域的学者,对于网络知识基础确实比较有限,之前一直以为ESP32只要和roscore在同一个局域网中,能ping通就能直接进行esp32上的ros节点和主机ros节点的通讯,今天实际上手之后吗,发现并没有那么简单,还是需要一些其他的设定才能实现这种通讯。不过好在最后发现其实也确实不算复杂,只是中间增加了一个socket工具和端口来进行设备间的通讯,稍加了解socket的工作原理后还是成功实现了这一工作。

二、ROS与单个ESP32的连接

        ROS与ESP32连接可以参考ROS的官方例程,也就是rosserial_arduino,基本不需要太多修改,官方例程拿过来直接用即可。这里还是简述一下我开发环境及对应的流程:

2.1 ESP32端

        我最常使用的ESP32开发环境是基于VS Code的Platform IO插件,首先新建一个ESP32的项目,并通过导入Platform IO平台导入库的功能导入Rosserial Arduino Library这个库

图-导入Rosserial Arduino Library库

        之后将库内包含的Esp8266例程复制粘贴到自己的main.cpp内即可,当然需要修改一些信息,下面贴出我的代码并对修改的内容进行说明:

  • WIFI的头文件,例程是用的esp8266,我的硬件是esp32,根据自身硬件修改即可
  • WIFI的SSID和密码,这个无需多说,连入主机(运行roscore的设备)所在的局域网即可,此处注意:需要和主机在同一网段
  • 主机的IP地址,这里根据自身硬件情况设置即可,可在主机上通过指令ifconfig查看
  • 其他的例如发布者的名称,topic的设定自己随便设定,我这里只是尝试一下功能,就不做复杂的修改了,就用的例程的代码。
#include <WiFi.h>
#include <ros.h>
#include <std_msgs/String.h>

const char* ssid     = "LAB121";
const char* password = "12345678";
// Set the rosserial socket server IP address
IPAddress server(10,1,1,12);
// Set the rosserial socket server port
const uint16_t serverPort = 11411;

ros::NodeHandle nh;
// Make a chatter publisher
std_msgs::String str_msg;
ros::Publisher chatter("esp32dev", &str_msg);

// Be polite and say hello
char hello[13] = "hello world!";

void setup()
{
  // Use ESP8266 serial to monitor the process
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  // Connect the ESP8266 the the wifi AP
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Set the connection to rosserial socket server
  nh.getHardware()->setConnection(server, serverPort);
  nh.initNode();

  // Another way to get IP
  Serial.print("IP = ");
  Serial.println(nh.getHardware()->getLocalIP());

  // Start to be polite
  nh.advertise(chatter);
}

void loop()
{

  if (nh.connected()) {
    Serial.println("Connected");
    // Say hello
    str_msg.data = hello;
    chatter.publish( &str_msg );
  } else {
    Serial.println("Not Connected");
  }
  nh.spinOnce();
  // Loop exproximativly at 1Hz
  delay(1000);
}

2.2 主机端

        本人主机是实验室的jetson nano国产套件,运行ubuntu 18.04,估计其他的随便什么ubuntu都适用这一方法。

        主机端就比较容易了,先运行:

roscore

        然后运行

rosrun rosserial_python serial_node.py tcp

        即可实现通讯,之后通过rostopic list即可查看到esp32发布的话题,也可以通过rostopic echo 查看话题内容,或通过其他节点同时也订阅这个话题。这里注意命令的最后有一个tcp的后缀,ros官方的例程大部分是通过有线的串口,这里写的是串口的地址。这里也是参考了其他大佬的方法:

(60条消息) 在Arduino平台上使用ESP8266:订阅ROS消息,通过tcp无线控制IO_庆钊你好呀的博客-CSDN博客

        现在我们已经实现了单个ESP32与ros主机的通讯,下面就是多个esp32与主机的通讯。

三、ROS与多个ESP32的连接

        这里用到了两个esp32设备,但是方法适用于更多的设备,但是由于ros官方的rosserial包似乎只支持最多25个Publishers和Subscribers,当然这个数字一般情况下是够用了,如果需要似乎还可以更大,这就需要更深入的学习,暂不考虑。

3.1 ESP32_1端

        ESP32_1的代码与上述第二节一致,无需进行其他任何修改。

3.2 ESP32_2端

        ESP32_2的代码如下,有两个地方与 ESP32_1的不同需要进行修改“

  • 修改一个与 ESP32_1不同的主机端口号,即serverPort。(在前言提到过,esp32与ros主机的基于wifi的通讯实际上还是一种通过端口的通讯,只不过相较于常规的串口端口,这里用到了虚拟端口的概念。本人也不是网络方面的专业从业者,只是百度上简单搜索了一些资料过了这个坎就没再深入研究,因此这里就不在展开说这一问题了,可以搜索一些相关的资料自己学习。)rosserial默认的端口是11411,这里只要选择一个不同于11411的端口即可,但是别用一些其他进程正在使用的端口,可以在主机上通过netstat -anp指令查看端口占用情况,经过测试我这里11412是可以的;
  • 修改一下topic的名称,ros不支持同样名字的topic。
  • #include <WiFi.h>
    #include <ros.h>
    #include <std_msgs/String.h>
    
    const char* ssid     = "LAB121";
    const char* password = "12345678";
    // Set the rosserial socket server IP address
    IPAddress server(10,1,1,12);
    // Set the rosserial socket server port
    const uint16_t serverPort = 11412;
    
    ros::NodeHandle nh;
    // Make a chatter publisher
    std_msgs::String str_msg;
    ros::Publisher chatter("esp32pico", &str_msg);
    
    // Be polite and say hello
    char hello[13] = "hello world!";
    
    void setup()
    {
      // Use ESP8266 serial to monitor the process
      Serial.begin(115200);
      Serial.println();
      Serial.print("Connecting to ");
      Serial.println(ssid);
    
      // Connect the ESP8266 the the wifi AP
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
    
      // Set the connection to rosserial socket server
      nh.getHardware()->setConnection(server, serverPort);
      nh.initNode();
    
      // Another way to get IP
      Serial.print("IP = ");
      Serial.println(nh.getHardware()->getLocalIP());
    
      // Start to be polite
      nh.advertise(chatter);
    }
    
    void loop()
    {
    
      if (nh.connected()) {
        Serial.println("Connected");
        // Say hello
        str_msg.data = hello;
        chatter.publish( &str_msg );
      } else {
        Serial.println("Not Connected");
      }
      nh.spinOnce();
      // Loop exproximativly at 1Hz
      delay(1000);
    }

3.3 主机端

        主机端这里就不能再直接通过命令行调用ros官方的rosserial节点来运行了,需要通过一个launch文件来运行:

<launch>
<node pkg="rosserial_python" type="serial_node.py" name="ESP32DEV" args="tcp 11411"/>
<node pkg="rosserial_python" type="serial_node.py" name="ESP32PCIO" args="tcp 11412"/>
</launch>

        launch文件随便放在那个功能包都行,反正调用的也是官方rosseria节点,实际使用的时候可以卸载bringup.launch中。

        这里需要注意的是,需要给两个节点起不同的名字,才能运行,此外最后的args也是需要与上述ESP32端的端口号一一对应。

        最后展示一下运行结果,可以看到两个话题都能被rostopic list出来,且rostopic echo也能正常打印通讯内容,大功告成。

 参考文献 

rosserial - ROS Wiki

Ubuntu查看端口占用情况_51CTO博客_查看端口占用情况linux

【Arduino】【ROS】rosserial连接两片Arduino 英伟达NVIDIA jetson nano ROS_哔哩哔哩_bilibili

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值