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

Calling predefined service from python script

asked 2019-04-24 03:50:55 -0500

Tulga gravatar image

updated 2019-04-25 03:29:07 -0500

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()
edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
0

answered 2019-05-15 03:44:42 -0500

Tulga gravatar image

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.

edit flag offensive delete link more
1

answered 2019-04-24 04:20:50 -0500

Delb gravatar image

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
edit flag offensive delete link more

Comments

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]

Tulga gravatar image Tulga  ( 2019-04-25 00:37:00 -0500 )edit

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)

Delb gravatar image Delb  ( 2019-04-25 03:23:43 -0500 )edit

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.

Tulga gravatar image Tulga  ( 2019-04-25 03:30:05 -0500 )edit

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

Delb gravatar image Delb  ( 2019-04-25 04:02:30 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2019-04-24 03:50:55 -0500

Seen: 1,444 times

Last updated: May 15 '19