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

Rosservice Kinetic vs Melodic

asked 2019-07-02 19:21:52 -0600

Qwertazertyl gravatar image

updated 2019-07-04 09:22:01 -0600

jayess gravatar image

I'm currently working on a project that was left partly complete by someone else, a while ago. The project is written with ROS Kinetic, but I'd like to make it compatible with melodic too (running on ubuntu 16.04 and 18.04 respectively, both on VMs). I've had some issues, though. Rosservice commands in particular don't work with Melodic, while they do work with Kinetic. I get errors saying "String has no len()" (this is a std_msgs String) but I never called len() in my code! Are there any differences between the implementation of Rosservice that I should be aware of? Sorry if it's something simple; I'm completely new to ROS.

The code:

import rospy
import ethernetcommunicator
import serialcommunicator
from std_msgs.msg import Bool
from std_msgs.msg import Float64
from std_msgs.msg import String
from mswrapper.srv import *

cm = serialcommunicator.Serialcommunicator()

def send_command_callback(data):
    return cm.send_command(data.data)

def set_speed_callback(data):
    cm.motor_jog(data.data)

def handle_send_command(req):
    controller_response = cm.send_command(str(req.command)[6:])
    if not controller_response:
        controller_response = ""
    return SendCommandResponse(String(controller_response))

def loop():
    input_1_pub = rospy.Publisher('mswrapper/input_1', Bool, queue_size=10)
    rospy.Subscriber('mswrapper/set_speed', Float64, set_speed_callback)
    rospy.Subscriber('mswrapper/send_command', String, send_command_callback)
    rospy.init_node('asciicom', anonymous=False)
    send_command_service = rospy.Service('mswrapper/send_command', SendCommand, handle_send_command)
    rate = rospy.Rate(1)
    while not rospy.is_shutdown():
        input_1_pub.publish(cm.get_input_1())
        rate.sleep()

if __name__ == '__main__':
    try:
        loop()
    except rospy.ROSInterruptException:
        pass

The error message is quite odd:

ERROR: Unable to send request. One of the fields has an incorrect type: 

     <type 'exceptions.TypeError'>: 'object of type 'String' has no len()' when writing 'data: 'mtr on''

srv file:

std_msgs/String command
    string data
---
std_msgs/String result
    string data

As you can see, there is no line number provided, only an error and a printout of my .srv file.

Meanwhile, on the node I'm running this from, I get another error message:

[ERROR] [numbers]: incoming connection failed: unable to receive data from sender, check sender's logs for details

So I have no idea where the error is coming from since I don't get a line number or even a file where this is taking place. Any help would be much appreciated!

edit retag flag offensive close merge delete

Comments

Please describe how rosservice "doesn't work". Please check in with the support guideline http://wiki.ros.org/Support#Do

130s gravatar image 130s  ( 2019-07-02 20:26:22 -0600 )edit
1

Edited, is this ok?

Qwertazertyl gravatar image Qwertazertyl  ( 2019-07-02 20:55:35 -0600 )edit

Can you please update your question with your code?

jayess gravatar image jayess  ( 2019-07-02 21:44:14 -0600 )edit

Code has been added

Qwertazertyl gravatar image Qwertazertyl  ( 2019-07-03 11:48:15 -0600 )edit

Does it really say

[ERROR] [some numbers]:

? I've never seen any error like this. Can you please update your question with the full error (not redacted) and the full code (not abbreviated).

jayess gravatar image jayess  ( 2019-07-03 17:48:19 -0600 )edit

The error numbers change every time...

Qwertazertyl gravatar image Qwertazertyl  ( 2019-07-03 18:05:46 -0600 )edit

Correct, but my point was more along the lines of what else are we missing from the error, if anything?

jayess gravatar image jayess  ( 2019-07-03 18:27:22 -0600 )edit

That's the full error. I'll update the whole program if you want.

Qwertazertyl gravatar image Qwertazertyl  ( 2019-07-03 18:33:19 -0600 )edit

2 Answers

Sort by ยป oldest newest most voted
2

answered 2019-07-03 11:49:03 -0600

gvdhoorn gravatar image
def handle_send_command(req):
    controller_response = cm.send_command(str(req.command)[6:])

this is most likely your problem: req.command is a std_msgs.String, not a str.

A std_msgs.String contains a data field, which is a str.

So you'll probably want to do something like:

 def handle_send_command(req):
    controller_response = cm.send_command(str(req.command.data)[6:])

Additionally:

def loop():
    ...
    send_command_service = rospy.Service('mswrapper/send_command', SendCommand, handle_send_command)

Are you (re)creating Service servers in a loop? That's probably not something you want to do.

edit flag offensive delete link more

Comments

PS: I'm also uncertain why you are using std_msgs/String in your custom .srv: why not use the string type directly for the command and result fields?

PPS: using some other than a string may actually be better, as a string can contain any arbitrary string, not just valid ones.

And PPPS: I'm not sure how this would've ever worked. Afaik this hasn't changed between Kinetic and Melodic.

gvdhoorn gravatar image gvdhoorn  ( 2019-07-03 11:50:36 -0600 )edit

I tried changing to req.command.data but still get the same "String has no len()" error. Also, I tried adding some print statements in handle_send_command but nothing appears.

Qwertazertyl gravatar image Qwertazertyl  ( 2019-07-03 12:40:26 -0600 )edit

And should I just move the service definition out of loop? Or should I put it in main, another function, etc?

Qwertazertyl gravatar image Qwertazertyl  ( 2019-07-03 12:41:43 -0600 )edit
1

answered 2019-07-03 02:18:57 -0600

knxa gravatar image

std_msgs/String does not have a method 'len'.

std_msgs/String has a field named 'data' and this field is a python string, where you can use 'len'.

Fire up a python interpreter:

>>> from std_msgs.msg import String
>>> s = String()
>>> len(s.data)
0
>>> len(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'String' has no len()

So look for the place where the exception is thrown, and correct the issue. It has probably nothing to do with kinetic vs melodic, you are maybe just hitting a different execution path in the code.

edit flag offensive delete link more

Comments

The thing is, I didn't call len() anywhere in my code, and I don't have a line number to work with. That's why I thought it was melodic calling len() because of some new feature that kinetic didn't have

Qwertazertyl gravatar image Qwertazertyl  ( 2019-07-03 11:45:31 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2019-07-02 19:21:52 -0600

Seen: 1,823 times

Last updated: Jul 04 '19