Robotics StackExchange | Archived questions

Rosserial Creation of Subscriber Failed

After running:

rosrun rosserial_python serial_node.py /dev/ttyACM0

I receive these info and error messages (node connects, but can't find subscriber):

[INFO] [1553102815.473901]: ROS Serial Python Node
[INFO] [1553102815.508651]: Connecting to /dev/ttyACM0 at 57600 baud
[ERROR] [1553102817.635874]: Creation of subscriber failed: need more than 1 value to unpack

I am running ROS Kinetic on a 4G/64G LattePanda with Ubuntu 16.04 LTS, 64 bit, kernel 4.12.1-20180417

This is my first time using ROS.

My goal is to use rosserial and the LattePanda's onboard arduino (Arduino Leonardo) to create a subscriber to a custom message format. I have another publisher that is running in a terminal session on the LattePanda. I use the following procedure as setup:

After using:

catkin_make

I see no errors or issues. I then try and build the arduino headers that will be necessary to flash. First, I delete the ros_lib folder in the ~/Arduino/library/ directory. Then:

~/Arduino/libraries$ rosrun rosserial_client make_libraries .

This seems to run properly, giving output in the terminal and recreating the ros_lib folder in the ~/Arduino/libraries/ directory.

After running roscore and my publisher node, the messages are being published properly because I can view them using:

rostopic echo /moveControl

I will say that one of my issues is that after creating the header files for the arduino, when I try and use

#include <beginnner_tutorials/Movement.h>

in the arduino code, I am presented with the following error when I attempt to compile:

movementControl:4:41: error: beginner_tutorials/Movement.h: No such file or directory
compilation terminated.
exit status 1
beginner_tutorials/Movement.h: No such file or directory

This is extra irksome, because I can clearly see that the file and directory do exist. I assumed that this was a problem that could be resolved by exiting and reopening the arduino editor (maybe to refresh libraries?), but that did not solve the issue. The only fix I found was to manually include the absolute filepath as shown in my code below. After doing this, it does compile, but I can't help but feel it must be related to rosserial not being able to see my subscriber on the arduino.

I will say that I have had rosserial working before when I was using a stdmsgs uint16t. This must be an issue with my custom message type.

I am a newbie when it comes to ROS and C++, so I would appreciate any and all help!

All of my files are below:

Movement.msg:

int16 servoVal
int16 motorVal

movementControl.ino:

#define USE_USBCON

#include <ros.h>
#include </home/rosuser/Arduino/libraries/ros_lib/beginner_tutorials/Movement.h>

ros::NodeHandle n;

#include <PololuMaestro.h>
#include <SoftwareSerial.h>
SoftwareSerial maestroSerial(7, 8);
MiniMaestro maestro(maestroSerial);

// Defining upper and lower bounds for servo target values
int16_t servoLowTarget = 4000;
int16_t servoMid = 6000;
int16_t servoHighTarget = 8000;

int16_t servoGroup1 = 6000;
int16_t servoGroup2 = 6000;


// Defining Pins for Motor Drivers
const int IN1=10;
const int IN2=11;
const int ENA=9;

const int IN3=5;
const int IN4=6;
const int ENB=3;

// ######################################################
// void Maestro::setAcceleration (  uint8_t channelNumber,
//                                  uint16_t acceleration )
// ######################################################

// ######################################################
// void Maestro::setSpeed (  uint8_t channelNumber,
//                           uint16_t speed )
// ######################################################

// ######################################################
// void Maestro::setTarget (  uint8_t channelNumber,
//                            uint16_t target )
//
// Where target is represented in quarter-microseconds
// ######################################################

void servo_cb( const beginner_tutorials::Movement& cmd_msg ){

  servoGroup1 = servoMid + cmd_msg.servoVal;
  servoGroup2 = servoMid - cmd_msg.servoVal;

  // Setting servos to current target values
  maestro.setTarget(0, (uint16_t)servoGroup1);
  maestro.setTarget(2, (uint16_t)servoGroup1);
  maestro.setTarget(4, (uint16_t)servoGroup2);
  maestro.setTarget(6, (uint16_t)servoGroup2);

  // Setting motors to current target values
  if (cmd_msg.motorVal == 1) Move_Forward(100);
  if (cmd_msg.motorVal == -1) Move_Backward(100);

}

ros::Subscriber<beginner_tutorials::Movement> sub("moveControl", servo_cb);

void setup() {

  // Setting maestro serial buad rate to 9600 (standard)
  maestroSerial.begin(9600);

  n.initNode();
  n.subscribe(sub);

  // Setting servo speed to unlimited
  maestro.setSpeed(0, 0);
  maestro.setSpeed(2, 0);
  maestro.setSpeed(4, 0);
  maestro.setSpeed(6, 0);

  // Setting servo acceleration to unlimited
  maestro.setAcceleration(0,0);
  maestro.setAcceleration(2,0);
  maestro.setAcceleration(4,0);
  maestro.setAcceleration(6,0);

  // Setting Pin Modes for Motor Driver
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENA, OUTPUT);

  pinMode(IN4, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(ENB, OUTPUT);

}

void loop() {

  n.spinOnce();
  delay(1);

}

//#######################################################
//#############DEFINING MOTOR FUNCTIONS##################
//#######################################################

void Motor1_Forward(int Speed) 
{
     digitalWrite(IN1,HIGH); 
     digitalWrite(IN2,LOW);  
     analogWrite(ENA,Speed);
}

void Motor1_Backward(int Speed) 
{    
     digitalWrite(IN1,LOW); 
     digitalWrite(IN2,HIGH);  
     analogWrite(ENA,Speed);
}
void Motor1_Brake()      
{
     digitalWrite(IN1,LOW); 
     digitalWrite(IN2,LOW); 
}     
void Motor2_Forward(int Speed) 
{
     digitalWrite(IN3,HIGH); 
     digitalWrite(IN4,LOW);  
     analogWrite(ENB,Speed);
}

void Motor2_Backward(int Speed) 
{    
     digitalWrite(IN3,LOW); 
     digitalWrite(IN4,HIGH);  
     analogWrite(ENB,Speed);
}
void Motor2_Brake()
{
     digitalWrite(IN3,LOW); 
     digitalWrite(IN4,LOW); 
}
void Move_Forward(int Speed)
{
    Motor1_Forward(Speed);
    Motor2_Forward(Speed);
    delay(500);
    Motor1_Brake();
    Motor2_Brake();
    delay(100); 
}
void Move_Backward(int Speed)
{
    Motor1_Backward(Speed);
    Motor2_Backward(Speed);
    delay(500);
    Motor1_Brake();
    Motor2_Brake();
    delay(100);
}

//#######################################################
//#######################################################
//#######################################################

command_pub.cpp running on in terminal session on LattePanda:

#include "ros/ros.h"
#include "beginner_tutorials/Movement.h"

#include <sstream>

#include <ncurses.h>

uint16_t servoLowTarget = 4000;
uint16_t servoHighTarget = 8000;
int maxDisplace = 2000;

int main(int argc, char **argv)
{

    initscr();
    raw();
    keypad(stdscr, TRUE);
    noecho();
    cbreak();

    ros::init(argc, argv, "command_pub");

    ros::NodeHandle n;

    ros::Publisher command_pub = n.advertise<beginner_tutorials::Movement>("moveControl", 1000);

    ros::Rate loop_rate(10);

    int c = 0;
    int currentServoVal = 0;
    int currentMotorVal = 0;

    beginner_tutorials::Movement command;

    while (ros::ok())
    {

        c = 0;
        c = getch();

        currentMotorVal = 0;
        switch(c) {

            case 'q':
                printw("quitting...");
                endwin();
                return 0;
                break;

            case KEY_RIGHT:
                currentServoVal += 200;
                break;

            case KEY_LEFT:
                currentServoVal -= 200;
                break;

            case KEY_UP:
                currentMotorVal = 1;
                break;

            case KEY_DOWN:
                currentMotorVal = -1;
                break;

            default:
                printw("I don't recognize that\n");

        }

        if (currentServoVal >= maxDisplace) currentServoVal = maxDisplace;
        if (currentServoVal <= -(maxDisplace)) currentServoVal = -(maxDisplace);

        command.servoVal = currentServoVal;
        command.motorVal = currentMotorVal;

        command_pub.publish(command);

        printw("Current Servo Value: %d\n", (int)currentServoVal);
        printw("Current Motor Value: %d\n", (int)currentMotorVal);
        refresh();

        ros::spinOnce();

        loop_rate.sleep();

    }

    endwin();
    return 0;

}

package.xml:

<?xml version="1.0"?>
<package format="2">
  <name>beginner_tutorials</name>
  <version>0.0.0</version>
  <description>The beginner_tutorials package</description>

  <maintainer email="rosuser@todo.todo">rosuser</maintainer>


  <license>TODO</license>

  <build_depend>message_generation</build_depend>

  <exec_depend>message_runtime</exec_depend>

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <depend>beginner_tutorials/Movement</depend>


  <export>

  </export>
</package>

excerpts from CMakeLists.txt:

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
add_message_files(
    FILES
    Movement.msg
)
generate_messages(
    DEPENDENCIES
    std_msgs
)
CATKIN_DEPENDS message_runtime
find_package(Curses REQUIRED)

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

add_executable(command_pub src/command_pub.cpp)
target_link_libraries(command_pub ${catkin_LIBRARIES} ${CURSES_LIBRARIES})
add_dependencies(command_pub beginner_tutorials_generate_messages_cpp)

Asked by Booker on 2019-03-20 15:00:07 UTC

Comments

I have almost the exact same problem. Getting the same error message "Creation of subscriber failed...".

I am trying both a combination of running ROS melodic on Debian stretch 9.8 and ROS kinetic on Ubuntu 16.04.

As is also the case in the question asked I have had success using rosserial_arduino before with both combinations using predefined ROS messages, but when trying to implement a custom message (containing two float64) I was not successful. I have checked that the custom message is valid when I use it without rosserial and I am able to build the Arduino sketch without errors with the custom message.

Therefore I am convinced, that the problem is due to the very combination of rosserial, Arduino and custom message.

Did anyone find a solution to the problem ? Thank you very much!

Asked by Amalie on 2019-05-15 02:31:15 UTC

Hi. Answers like this -- which are not actually answers, but follow-up questions -- have very poor visibility. It would be better to post it as a separate question and then refer back to this one.

Asked by gvdhoorn on 2019-05-15 02:56:58 UTC

Same issue. Works perfectly for standard messages. Only throws "Creation of Sub failed. Need more than 1 values to unpack" for custom messages. Have you found a fix? Would have to change a lot of dependent code to revert to standard messages.

Asked by ringo47 on 2020-09-26 15:35:56 UTC

Answers

I had the same issue. This worked out for me.

We need a simplified header file for custom messages in Arduino sketches. The usual header files in devel have boost dependencies. We can generate a simplified header file by running the following:

rosrun rosserial_arduino make_library.py path_to_libraries your_message_package

The resources I used: ROS wiki and Ch 7. in Mastering ROS for Robotics Programming

Asked by ajaygunalan on 2022-11-04 08:27:37 UTC

Comments