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

Arduino publisher: unable to sync with device

asked 2021-03-19 21:03:41 -0500

ffbo gravatar image

I'm trying to use an IR reader and an Arduino Uno as the basis for my odometry. I'm using the attached code. The code compiles and uploads successfully to the Arduino. I then run roscore and rosrun rosserial_python serial_node.py _port:=/dev/ttyACM0 _baud:=57600 which produces the following errors:

pi@raspberrypi:~/odom_ws $ rosrun rosserial_python serial_node.py _port:=/dev/ttyACM0 _baud:=57600
[INFO] [1616083210.822040]: ROS Serial Python Node
[INFO] [1616083210.834459]: Connecting to /dev/ttyACM0 at 57600 baud
[INFO] [1616083212.945610]: Requesting topics...
[INFO] [1616083213.425535]: Wrong checksum for msg length, length 8, dropping message.
[ERROR] [1616083227.953649]: Unable to sync with device; possible link problem or link software version mismatch such as hydro rosserial_python with groovy Arduino
[INFO] [1616083227.960634]: Requesting topics...
[ERROR] [1616083242.968012]: Unable to sync with device; possible link problem or link software version mismatch such as hydro rosserial_python with groovy Arduino
[INFO] [1616083242.977686]: Requesting topics...
[ERROR] [1616083257.984978]: Unable to sync with device; possible link problem or link software version mismatch such as hydro rosserial_python with groovy Arduino

All help and feedback is much appreciated.

// Include ros.h header file and header files for all messages we'll be using
#include <ros.h>
#include <ros/time.h>
#include <tf/tf.h>
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>

const double dx = 0.1;   // Distance increment per reading in meters
                         // Dummy variable used here for support purposes

// Instantiate node handle (allows us to create publishers and subscribers)
ros::NodeHandle nh;
nav_msgs::Odometry odom_msg;
ros::Publisher odom_pub("/odom", &odom_msg);
tf::TransformBroadcaster odom_broadcaster;

// Initial position
double x = 0.0;
double y = 0.0;
double theta = 0.0;

// Set time
ros::Time current_time = nh.now();
ros::Time last_time = nh.now();

void setup()
{

  // Enable interruption pin when going from LOW to HIGH
  // Calls Pulse_Event()
  attachInterrupt(digitalPinToInterrupt(IR_Pin), Pulse_Event, RISING);

  // Set time
  current_time = nh.now();
  last_time = nh.now();

  // Initialize node and broadcast it
  nh.initNode();
  nh.advertise(odom_pub);

}

void loop()
{
  // Process the publishing queue
  nh.spinOnce();

  // Delay in µs
  delay(1000);
}

void Pulse_Event()
{  
  // Set current time
  current_time = nh.now();

  // Calculate velocity
  double dt = (current_time.toSec() - last_time.toSec());
  double delta_x = cos(theta)*dx;
  double delta_y = sin(theta)*dx;
  double delta_th = 0.0;

  double vx = delta_x / dt;
  double vy = delta_y / dt;
  double vth = delta_th / dt;

  // Update x,y
  x += delta_x;
  y += delta_y;
  theta += delta_th;

  // Since all odometry is 6DOF we'll need a quaternion created from yaw
  geometry_msgs::Quaternion odom_quat = tf::createQuaternionFromYaw(theta);

  // Publish transform over tf
  geometry_msgs::TransformStamped odom_trans;
  odom_trans.header.stamp = current_time;
  odom_trans.header.frame_id = "odom";
  odom_trans.child_frame_id = "base_link";

  // Set transform for x,y,z coordinates
  odom_trans.transform.translation.x = x;
  odom_trans.transform.translation.y = y;
  odom_trans.transform.translation.z = 0.0;
  odom_trans.transform.rotation = odom_quat;

  // Send the transform
  odom_broadcaster.sendTransform(odom_trans);

  // Set odom header
  odom_msg.header.stamp = current_time;
  odom_msg.header.frame_id = "odom";

  // Set the position
  odom_msg.pose.pose.position.x = x;
  odom_msg.pose.pose.position.y = y;
  odom_msg.pose.pose.position.z = 0.0;
  odom_msg.pose.pose.orientation = odom_quat;

  // Set the velocity
  odom_msg.child_frame_id = "base_link ...
(more)
edit retag flag offensive close merge delete

Comments

Things to consider. Are you really publishing at 56700Baud from the arduino? Those odometry calculations are a lot for an Arduino and ISRs (Interrupt service routines) schould be as short as possible. Copy a single variable or similar. Your update cycle/delay is at 1hz, you comment its 1000micros, but the arduino standard is millis!

I would suggest checking the publish frequency and baudrates are really right. Decouple the performance demanding calculations from the Interrupt, you have more then enought time in the "delay" to make the calculations, no need to block. Also maybe even let the "PC" figure out TF and only calculate odom on the arduino itself. Aditionally a long time ago I red that Arduino delay can somehow affect timers running in the background. Interrupts were said to mess with them as well, specially long running ISRs. Though this is more about the quality of the data ...(more)

Dragonslayer gravatar image Dragonslayer  ( 2021-03-20 03:31:48 -0500 )edit

2 Answers

Sort by » oldest newest most voted
0

answered 2021-03-23 12:10:15 -0500

ffbo gravatar image

Thanks for your input. I've tried running nh.now() only after nh.initNode(), and I've added Serial.begin(57600) to setup().

I get the same set of error messages. I tried running rostopic echo /rosout to see what's published and it looks like something goes seriously wrong. Are you able to see what causes this?

$ rostopic echo /rosout
header: 
  seq: 8
  stamp: 
    secs: 1616519114
    nsecs:  97291946
  frame_id: ''
level: 2
name: "/serial_node"
msg: "Requesting topics..."
file: "SerialClient.py"
function: "SerialClient.requestTopics"
line: 403
topics: [/diagnostics, /rosout]
---
header: 
  seq: 9
  stamp: 
    secs: 1616519119
    nsecs: 213711977
  frame_id: ''
level: 4
name: "/serial_node"
msg: "Last read step: message length"
file: "SerialClient.py"
function: "SerialClient.run"
line: 543
topics: [/diagnostics, /rosout]
---
header: 
  seq: 10
  stamp: 
    secs: 1616519119
    nsecs: 219691038
  frame_id: ''
level: 4
name: "/serial_node"
msg: "Run loop error: Serial Port read failure: Returned short (expected 3 bytes, received\
  \ 2 instead)."
file: "SerialClient.py"
function: "SerialClient.run"
line: 544
topics: [/diagnostics, /rosout]
---
header: 
  seq: 11
  stamp: 
    secs: 1616519119
    nsecs: 225771903
  frame_id: ''
level: 2
name: "/serial_node"
msg: "Requesting topics..."
file: "SerialClient.py"
function: "SerialClient.requestTopics"
line: 403
topics: [/diagnostics, /rosout]
---
edit flag offensive delete link more

Comments

Of interest -> similar question

"Run loop error: Serial Port read failure: Returned short (expected 3 bytes, received\ \ 2 instead)."

Seems you serialize to another standard then expected.

By the way different Arduinos use different byte size for different types ->Arduino Reference

Dragonslayer gravatar image Dragonslayer  ( 2021-03-24 11:32:11 -0500 )edit
1

answered 2021-03-20 06:38:31 -0500

cch gravatar image

updated 2021-03-24 14:30:40 -0500

Hello.

It can be read in the documentation here that :

In order to get the current ROS time, you must be connected to ROS.

So maybe you should perform calls to nh.now() only after the connection to ROS has been initialised with nh.initNode(). (Note that I don't have an Arduino to double check this now though).

Edit 1

Hi. I tried your code on an ESP8266, and managed to get it working after three changes:

  • Manually call the Pulse_Event() function in the loop function (since I don't have an encoder to test).
  • Increasing the default size of the serial buffer in ros.h to 1024 (instead of the default 512). The odometry message seemed to be too big otherwise. Specifically I used typedef NodeHandle_<ArduinoHardware, 10, 10, 1024, 1024> NodeHandle;. You can get more information about this here.
  • Add odom_broadcaster.init(nh); just after nh.initNode(); (as per here)

Don't mind my previous comment. It seems indeed that it makes no difference in practice.

One general advice (if not already done of course): try with a very simple case scenario, publishing only one Float32 message, and see whether you still face the issue. Once you made sure it is working, add complexity bit by bit. It might be easier to isolate problems.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2021-03-19 21:03:41 -0500

Seen: 632 times

Last updated: Mar 24 '21