0
$\begingroup$

Rosanswers logo

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 !


Originally posted by rderensy on ROS Answers with karma: 33 on 2016-04-25

Post score: 0


Original comments

Comment by Humpelstilzchen on 2016-04-25:
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.

Comment by ahendrix on 2016-04-25:
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?

Comment by rderensy on 2016-04-25:
@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);

Comment by ahendrix on 2016-04-25:
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.

Comment by rderensy on 2016-04-25:
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 ?

Comment by ahendrix on 2016-04-25:
The tcp option to rosserial_python is for other rosserial clients such as http://wiki.ros.org/rosserial_embeddedlinux . As far as I know, the arduino client doesn't support wifi

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

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
};

Originally posted by ahendrix with karma: 47576 on 2016-04-25

This answer was ACCEPTED on the original site

Post score: 3


Original comments

Comment by rderensy on 2016-04-25:
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 ?

Comment by ahendrix on 2016-04-25:
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.

Comment by rderensy on 2016-04-26:
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

Comment by ahendrix on 2016-04-26:
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).

Comment by ahendrix on 2016-04-26:
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.

Comment by rderensy on 2016-04-27:
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

Comment by ahendrix on 2016-04-27:
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"

$\endgroup$
0
$\begingroup$

Rosanswers logo

@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


Originally posted by rderensy with karma: 33 on 2016-04-28

This answer was NOT ACCEPTED on the original site

Post score: 3


Original comments

Comment by ahendrix on 2016-04-28:
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.

Comment by ahendrix on 2016-04-28:
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.

Comment by rderensy on 2016-04-29:
Okay ... I replaced client.println() to client.write() and it works fine, thank you !

Comment by johnrom on 2016-05-19:
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.

Comment by rderensy on 2016-05-19:
@johnrom My last post (on April 18) is exactly what I wrote into these functions

Comment by suraj-reddy on 2016-10-06:
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??

Comment by suraj-reddy on 2016-10-06:
The hello world example works over wifi with USB cable connected...but i'm using network port as my connection

Comment by ahendrix on 2016-10-06:
@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.

Comment by suraj-reddy on 2016-10-07:
Can it be done with existing rosserial_arduino package??....can u suggest me the way to do it.

Comment by ahendrix on 2016-10-07:
@suraj-reddy: This isn't really an appropriate place for this conversation. In case it wasn't clear before, I think you should ask as a new question.

Comment by Waqas on 2017-03-29:
i have used this as it is,it is the response. "[INFO] [WallTime: 1490810137.517429] ROS Serial Python Node Fork_server is: False [INFO] [WallTime: 1490810137.528240] Waiting for socket connections on port 11411 waiting for socket connection " i am using arduino uno. Kindly help!!! Thanks in advance

Comment by anunez on 2017-05-27:
ros::NodeHandle_ nh; works but when I try to initialize tf::TransformBroadcaster broadcaster; with
broadcaster.init(nh); got error: no known conversion for argument 1 from 'ros::NodeHandle_' to 'ros::NodeHandle& {aka ros::NodeHandle_&}' any hint?

Comment by ahendrix on 2017-05-28:
It looks like the TF code is using the NodeHandle typedef from ros.h: https://github.com/ros-drivers/rosserial/blob/009dd9156d2f66b07eea012d9a0cb38464a7f810/rosserial_arduino/src/ros_lib/ros.h#L60 , which is still using ArduinoHardware.

Comment by ahendrix on 2017-05-28:
You can probably edit ros.h to fix this, or use the new ESP8266 support that was recently added to rosserial_arduino, which includes the proper NodeHandle type: https://github.com/ros-drivers/rosserial/pull/279

Comment by anunez on 2017-05-28:
I did edit ros.h & included WiFiHardware class in a separate .h that was activated with an #if in ros.h, and tf and odom works now inside ESP8266 in https://github.com/agnunez/espros. I discovered just now your updates to ros.h doing the same but more elegant, tested and udated my repository.Thks!!

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.