Arduino publisher: unable to sync with device
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 ...
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)