ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Launch a ros node over wifi

asked 2016-04-25 01:57:11 -0500

rderensy gravatar image

updated 2016-05-10 01:51:08 -0500

Hello,

I want to link my Arduino Uno (with a wifi-shield) with my PC (on Ubuntu 14.04, ROS Indigo) over wifi and run the ROS-node on the Arduino with the following command :

rosrun rosserial_python serial_node.py tcp

or

rosrun rosserial_python serial_node.py _port:=tcp _baud:=57600

But when I launch that, the Arduino open the socket on the port 11411, the serial_node.py say calling startSerialClient and I get the message Unable to sync with device; possible link problem or link software version mismatch such as hydro rosserial_python with groovy Arduino.

I don't understand that error because when I link them using USB connection, I don't have any problem. I searched on Google but nothing solved this problem.

Thank you !

edit retag flag offensive close merge delete

Comments

The first part is important: "Unable to sync with device; possible link problem". Forget the rest. Check that your shield works and that you send/receive data over it.

Humpelstilzchen gravatar image Humpelstilzchen  ( 2016-04-25 02:14:54 -0500 )edit

This is not a standard configuration, and to the best of my knowledge the rosserial_arduino libraries don't usually support communication over TCP. How are you setting up the TCP connection on the arduino?

ahendrix gravatar image ahendrix  ( 2016-04-25 02:26:30 -0500 )edit

@Humpelstilzchen Yup the shield works, when I create a C++ socket on my PC, the Arduino can connect to it and send/receive data

@ahendrix I connect the Arduino to wifi with WiFi.begin(ssid, pass); then I connect it to the socket on port 11411 client.connect(server, 11411);

rderensy gravatar image rderensy  ( 2016-04-25 02:36:31 -0500 )edit

rosserial_arduino is set up to use serial communication; it isn't going to automatically detect that you have an open TCP socket and suddenly start using it.

ahendrix gravatar image ahendrix  ( 2016-04-25 02:57:05 -0500 )edit

In the serial_node.py, there's

if port_name == "tcp" : server = RosSerialServer(tcp_portnum, fork_server)

try : server.listen()

so I guess that's for wireless connection. How is it supposed to work ?

rderensy gravatar image rderensy  ( 2016-04-25 03:03:02 -0500 )edit

The tcp option to rosserial_python is for other rosserial clients such as http://wiki.ros.org/rosserial_embedde... . As far as I know, the arduino client doesn't support wifi

ahendrix gravatar image ahendrix  ( 2016-04-25 03:39:15 -0500 )edit

3 Answers

Sort by ยป oldest newest most voted
3

answered 2016-04-25 03:09:38 -0500

ahendrix gravatar image

updated 2016-04-25 11:41:41 -0500

You will need to make an adapter that allows you to use rosserial_arduino with the WiFi shield.

As described in rosserial new hardware support guide, you will need to add a class that provides the interface between your WiFi shield and rosserial_arduino.

Since it doesn't look like the WiFi library behaves like a serial port, you'll probably need to implement the methods in the Hardware class directly.

It sounds like rosserial_python is expecting to connect to a TCP server, so you should probably use the WiFiServer class as the starting point for your implementation.

UPDATE

The Hardware implementation that you want to create should go in your sketch, and it should look something like this. You'll need to fill in the init(), read() and write() methods:

class WiFiHardware {

    WiFiHardware() {};

    void init() {
        // do your initialization here. this probably includes TCP server/client setup
    }

    // read a byte from the serial port. -1 = failure
    int read() {
        // implement this method so that it reads a byte from the TCP connection and returns it
        //  you may return -1 is there is an error; for example if the TCP connection is not open
    }

    // write data to the connection to ROS
    void write(uint8_t* data, int length) {
        // implement this so that it takes the arguments and writes or prints them to the TCP connection
    }

    // returns milliseconds since start of program
    unsigned long time() {
         return millis(); // easy; did this one for you
    }

private:
    // declare any class variables that you use here; this probably includes the variable for your TCP client/server object
};
edit flag offensive delete link more

Comments

I began the ROS/C++/Arduino 3 weeks ago for a work experience, I had never dev in C++/for Arduino before that. So, I have no idea how to do that, I don't know what is Serial and Serial1, what put inside the Hardware class, etc etc .. Firstly, where do I put the Hardware class ?

rderensy gravatar image rderensy  ( 2016-04-25 03:37:11 -0500 )edit

You'll want to create your new Hardware class inside of your arduino sketch. I'll update my answer with a framework that you can fill in, but I don't know the specifics of the WiFi shield, so I can't fill in the details.

ahendrix gravatar image ahendrix  ( 2016-04-25 11:32:18 -0500 )edit

I understood that with the links you gave me, I'll try with that and see, thank you! When I put it in my sketch, is it "auto-included" by the ros.h or must I modify it? Do I compile the WiFiHardware to .h? I don't understand how create a hardware class could help me to launch the ros-node via wifi

rderensy gravatar image rderensy  ( 2016-04-26 01:47:44 -0500 )edit

You don't need to modify ros.h or create any additional headers; you can specify the new hardware implementation as a template parameter when you create your NodeHandle. (as described in the new hardware support guide).

ahendrix gravatar image ahendrix  ( 2016-04-26 12:03:10 -0500 )edit

rosserial does not currently support WiFi. Defining a new hardware implementation defines how rosserial should send and receive bytes over WiFi, and therefore adds WiFi support.

ahendrix gravatar image ahendrix  ( 2016-04-26 12:04:49 -0500 )edit

Atm, I put the WiFiHardware.cpp in my sketchbook/libraries/ros_lib with the connection to the socket in init(), my client.read() in read() and client.print(data[i]) in a for loop in write(). I don't know if it's right

rderensy gravatar image rderensy  ( 2016-04-27 02:00:43 -0500 )edit

For a first prototype, you should put the WiFiHardware class directly at the top of your .ino file; not in a separate file. This is what I meant by "inside of your arduino sketch"

ahendrix gravatar image ahendrix  ( 2016-04-27 15:07:57 -0500 )edit
3

answered 2016-04-28 02:32:45 -0500

rderensy gravatar image

updated 2016-05-19 02:15:18 -0500

@ahendrix

#include <ros.h>
#include <std_msgs/String.h>
#include <Arduino.h>
#include <SPI.h>
#include <WiFi.h>
#include <Servo.h>

IPAddress server(192, 168, 0, 10);
WiFiClient client;

class WiFiHardware {

  public:
  WiFiHardware() {};

  void init() {
    // do your initialization here. this probably includes TCP server/client setup
    client.connect(server, 11411);
  }

  // read a byte from the serial port. -1 = failure
  int read() {
    // implement this method so that it reads a byte from the TCP connection and returns it
    //  you may return -1 is there is an error; for example if the TCP connection is not open
    return client.read();         //will return -1 when it will works
  }

  // write data to the connection to ROS
  void write(uint8_t* data, int length) {
    // implement this so that it takes the arguments and writes or prints them to the TCP connection
    for(int i=0; i<length; i++)
      client.write(data[i]);
  }

  // returns milliseconds since start of program
  unsigned long time() {
     return millis(); // easy; did this one for you
  }
};

Servo s;
int i;

void chatterCallback(const std_msgs::String& msg) {
  i = atoi(msg.data);
  s.write(i);
}

char ssid[] = "ssid";
char pass[] = "password";
ros::Subscriber<std_msgs::String> sub("message", &chatterCallback);
ros::NodeHandle_<WiFiHardware> nh;

void setup() {
  WiFi.begin(ssid, pass);
  s.attach(9);
  nh.initNode();
  nh.subscribe(sub);
}

void loop() {
  nh.spinOnce();
  delay(500);
}

I've done that, the connection works but the rosrun rosserial_python serial_node.py tcp still doesn't work, always the same message

edit flag offensive delete link more

Comments

It looks like you're heading in the right direction. From here I would start using TCP debugging tools: (1) netstat to confirm that the connection is established, and then (2) a data inspection tool (wireshark or tcpdump) to see that the correct data is being transferred.

ahendrix gravatar image ahendrix  ( 2016-04-28 19:22:27 -0500 )edit

One thing that looks suspicious is the use of client.println(), which will inject newlines into the data stream. rosserial is expecting raw data, and these extra newlines will probably corrupt the data stream.

ahendrix gravatar image ahendrix  ( 2016-04-28 19:24:13 -0500 )edit

Okay ... I replaced client.println() to client.write() and it works fine, thank you !

rderensy gravatar image rderensy  ( 2016-04-29 01:51:28 -0500 )edit

Rallph, Is there any chance you could share what you ended up writing for void init(), int read(), and void write() in the WifiHardware class? I am trying to do something similar but cannot figure out why it won't connect.

johnrom gravatar image johnrom  ( 2016-05-19 01:12:06 -0500 )edit

@johnrom My last post (on April 18) is exactly what I wrote into these functions

rderensy gravatar image rderensy  ( 2016-05-19 02:17:28 -0500 )edit

I'm using Arduino yun mini which has inbuilt wifi and trying to launch ros node over it...do i need to implement hardware changes in sketch??

suraj-reddy gravatar image suraj-reddy  ( 2016-10-06 07:38:33 -0500 )edit

The hello world example works over wifi with USB cable connected...but i'm using network port as my connection

suraj-reddy gravatar image suraj-reddy  ( 2016-10-06 07:41:29 -0500 )edit

@suraj-reddy: the Yun has a completely different Wifi/Network setup compared to using a Wifi shield. You'll probably need to do something different.

ahendrix gravatar image ahendrix  ( 2016-10-06 15:58:48 -0500 )edit
0

answered 2017-04-04 15:29:04 -0500

anunez gravatar image

Thanks to @ahendrix, I managed to adapt its code for ESP8266 that, unlike Arduino, provides WiFi option as standard, becoming one of the smaller, cheapest, wireless ROS node for any sensor or actuator. Please find a working demo code at https://github.com/agnunez/espros

edit flag offensive delete link more

Comments

Does this work if I have a ESP01 connected to an arduino Uno in my robot? @anunez

diogosilva0307 gravatar image diogosilva0307  ( 2019-02-18 12:41:20 -0500 )edit

Question Tools

3 followers

Stats

Asked: 2016-04-25 01:57:11 -0500

Seen: 6,808 times

Last updated: May 19 '16