0
$\begingroup$

Rosanswers logo

Hi all,

I am wondering how to pass an arguments when trying to call rosservice from python script.

I have this server called bcap_service which takes 2 arguments. (This is bcap.srv)

int32 func_id
variant[] vntArgs
---
int32 HRESULT
variant vntRet

(This is variant.msg)

int16 vt
string value

and I am trying to pass these arguments.

rosservice call /bcap_service '{func_id: 3, vntArgs: [{vt: 8, value: "b-CAP"}, {vt: 8, value: "CaoProv.DENSO.VRC"}, {vt: 8, value: "localhost"}, {vt: 8, value: ""}] }'

I have tried assigning them to variables. Tried writing like a YAML and had no results. Here is my code:

def gripper_control():
        rospy.wait_for_service('bcap_service')
             
        func_id = 3
               
        vt = 8
        value_1 = 'value: b-CAP'
        value_2 = 'CaoProv.DENSO.VRC'
        value_3 = 'localhost'
        value_4 = ''
    
        vntArgs = [vt, value_1, vt, value_2, vt, value_3, vt, value_4]
    
        rospy.ServiceProxy('bcap_service', func_id, vntArgs)

After running the code, I get error like this:

Traceback (most recent call last):
  File "/opt/ros/kinetic/lib/denso_robot_bringup/move_group_python_interface_cobotta.py", line 224, in <module>
    gripper_control()
  File "/opt/ros/kinetic/lib/denso_robot_bringup/move_group_python_interface_cobotta.py", line 197, in gripper_control
    rospy.ServiceProxy('bcap_service', func_id, vntArgs)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/impl/tcpros_service.py", line 404, in __init__
    super(ServiceProxy, self).__init__(name, service_class)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/service.py", line 59, in __init__
    self.request_class = service_class._request_class
AttributeError: 'int' object has no attribute '_request_class'

EDIT:

Full code below:

import sys
import copy
import rospy
import math
import moveit_commander
import moveit_msgs.msg
import geometry_msgs.msg
from geometry_msgs.msg import Pose, Point
from math import pi
from std_msgs.msg import String
from bcap_service.srv import *


def gripper_control():

    rospy.wait_for_service('bcap_service')
    try:
        
        #create handler to call the service
        bcap_service = rospy.ServiceProxy('bcap_service', bcap)
        print "ServiceProxy success ..."

        #define the request
        func_id = 3
        vt = 8
        value_1 = 'value: b-CAP'
        value_2 = 'CaoProv.DENSO.VRC'
        value_3 = 'localhost'
        value_4 = ''
        vntArgs = [vt, value_1, vt, value_2, vt, value_3, vt, value_4]
        print "Assignment success ..."
        print vntArgs

        #call the service by passing the request to the handler
        #it doesn't require to have the same names as in the .srv
        #But I did it for clarity
        response = bcap_service(func_id, vntArgs)
        print "rosservice call success"

        #store the response in some variables
        result1 = response.HRESULT
        result2 = response.vntRet

        #return the whole response
        return response

    except rospy.ServiceException, e:
        print "Service call failed: %s"%e
    
    
if __name__ == '__main__':

    rospy.init_node('cobotta_node')
    robot = moveit_commander.RobotCommander()
    scene = moveit_commander.PlanningSceneInterface()
    group = moveit_commander.MoveGroupCommander("arm")

    gripper_control()

Originally posted by Tulga on ROS Answers with karma: 16 on 2019-04-24

Post score: 0

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

rospy.ServiceProxy() requires as argument the name of the service and its type. This is used to create a handler that you can use as a function that needs the srv request as arguments. Have a look at the ros tutorial, it is well documented.

I haven't tested but this should do what you want :

def gripper_control():
    try:
        rospy.wait_for_service('bcap_service')

        #define the request
        func_id = 3
        vt = 8
        value_1 = 'value: b-CAP'
        value_2 = 'CaoProv.DENSO.VRC'
        value_3 = 'localhost'
        value_4 = ''
        vntArgs = [vt, value_1, vt, value_2, vt, value_3, vt, value_4]

        #create handler to call the service
        call_bcap = rospy.ServiceProxy('bcap_service', bcap)

        #call the service by passing the request to the handler
        #it doesn't require to have the same names as in the .srv
        #But I did it for clarity
        response = call_bcap(func_id, vntArgs)

        #store the response in some variables
        result1 = response.HRESULT
        result2 = response.vntRet

        #return the whole response
        return response

    except rospy.ServiceException, e:
        print "Service call failed: %s"%e

Originally posted by Delb with karma: 3907 on 2019-04-24

This answer was NOT ACCEPTED on the original site

Post score: 1


Original comments

Comment by Tulga on 2019-04-25:
Thank you for the quick reply. Error AttributeError: 'int' object has no attribute 'vt' is still there. I suppose now it has problem with defining vntArgs = [vt, value_1, vt, value_2, vt, value_3, vt, value_4]

Comment by Delb on 2019-04-25:
Can you give your full code please ? Also maybe try to modify the .srv so that vntArgs and vntRet are arrays of strings instead of mixed types (because you just have the same value vt before each different string which doesn't really make sense)

Comment by Tulga on 2019-04-25:
I edited post with full code. Is it alright to modify predefined services? If it is okay, I will change type to string or some other type.

Comment by Delb on 2019-04-25:
I actually think the error is just related to the variant type. It seems to require some workaround to use this with python. So if you must use this specific service you should consider do that in C++ instead of python or maybe try to wrap some C++ code using Boost.Python

$\endgroup$
0
$\begingroup$

Rosanswers logo

Update

I was able to solve this problem thanks to this post.

Variant type is defined as a message file in bcap_service package.

Here is simplified code:

rospy.wait_for_service('bcap_service')
    
    try:
        
        bcapReq = bcap_service.srv.bcapRequest()
        bcapReq.func_id = 3
        bcapReq.vntArgs.append(variant(vt=8, value="b-CAP"))
        bcapReq.vntArgs.append(variant(vt=8, value="CaoProv.DENSO.VRC"))
        bcapReq.vntArgs.append(variant(vt=8, value="localhost"))
        bcapReq.vntArgs.append(variant(vt=8, value=""))

        bcapSrv = rospy.ServiceProxy('bcap_service', bcap)
        response = bcapSrv(bcapReq)

        # print 'HRESULT:', response.HRESULT
        # print 'vntRet.vt:', response.vntRet.vt
        # print 'vntRet.value:', response.vntRet.value

    except rospy.ServiceException, e:
        print "Service call failed: %s"%e

Cheers.


Originally posted by Tulga with karma: 16 on 2019-05-15

This answer was ACCEPTED on the original site

Post score: 0

$\endgroup$

Your Answer

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