0
$\begingroup$

Rosanswers logo

Hello, i'm trying to control mobile robot 'rb1 base', it has elevate function which can move its head up and down. You can see the Service caller in the down side of the picture, it has the service topic named '/rb1_base/robotnik_base_control/set_elevator', based on that information, i wrote the service call program, you can see this top of the picture. In the SetElevator.h there is only one variable named 'int32 action', if i make the action variable to 1 then the robot elevate up, if i make it to -1 then the robot elevate down. so i wrote the code 'srv(1)' to elevate up the robot. But it says 'AttributeError : 'int' object has no attribute 'action''. Is there special way to change the variable 'int32 action'? Is it not just int?

here is the code.

from random import sample
from math import pow, sqrt
from actionlib_msgs.msg import *
from geometry_msgs.msg import Pose, PoseWithCovarianceStamped, Point, Quaternion, Twist
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal
from robotnik_msgs.srv import SetElevator, SetElevatorRequest, SetElevatorResponse
import rospy
import actionlib



class MultiPointNav():
    def __init__(self):
        rospy.init_node('multi_point_nav', anonymous=True)
          
        rospy.on_shutdown(self.shutdown)
        
        # How long in seconds should the robot pause at each location?
        self.rest_time = rospy.get_param("~rest_time", 3)
        
        # Are we running in the fake simulator?
        self.fake_test = rospy.get_param("~fake_test", False)
        
        # Goal state return values
        goal_states = ['PENDING', 'ACTIVE', 'PREEMPTED', 
                       'SUCCEEDED', 'ABORTED', 'REJECTED',
                       'PREEMPTING', 'RECALLING', 'RECALLED',
                       'LOST']
        
  
        locations = dict()
        
        locations['Point1'] = Pose(Point(-0.64500000000, 0.82600000000, 0.000), Quaternion(0.000, 0.000, 0.000, 1.000))
        locations['Point2'] = Pose(Point(-1.24000000000, -0.95300000000, 0.000), Quaternion(0.000, 0.000, 0.000, 1.000))
        #locations['Point3'] = Pose(Point(-2.50947999954, -5.9229183197, 0.000), Quaternion(0.000, 0.000, 0.000, 1.000))
        #locations['Point4'] = Pose(Point(-12.919, -23.867, 0.000), Quaternion(0.000, 0.000, 0.000, 1.000))
        #locations['Point5'] = Pose(Point(1.471, 1.007, 0.000), Quaternion(0.000, 0.000, 0.480, 0.877))
        #locations['Point6'] = Pose(Point(-0.861, -0.019, 0.000), Quaternion(0.000, 0.000, 0.892, -0.451))
        
        # Publisher to manually control the robot (e.g. to stop it, queue_size=5)
        self.cmd_vel_pub = rospy.Publisher('/rb1_base/cmd_vel', Twist, queue_size=5)
        
        # Subscribe to the move_base action server
        self.move_base = actionlib.SimpleActionClient("rb1_base/move_base", MoveBaseAction)
        
        rospy.loginfo("Waiting for move_base action server...")
        
        # Wait 60 seconds for the action server to become available
        self.move_base.wait_for_server(rospy.Duration(60))
        
        rospy.loginfo("Connected to move base server")
        
        # A variable to hold the initial pose of the robot to be set by 
        # the user in RViz
        initial_pose = PoseWithCovarianceStamped()
        
        # Variables to keep track of success rate, running time,
        # and distance traveled
        n_locations = len(locations)
        n_goals = 0
        n_successes = 0
        i = n_locations
        distance_traveled = 0
        start_time = rospy.Time.now()
        running_time = 0
        location = ""
        last_location = ""
        
        # Get the initial pose from the user
        rospy.loginfo("*** Click the 2D Pose Estimate button in RViz to set the robot's initial pose...")
        rospy.wait_for_message('/rb1_base/initialpose', PoseWithCovarianceStamped)
        self.last_location = Pose()
        rospy.Subscriber('/rb1_base/initialpose', PoseWithCovarianceStamped, self.update_initial_pose)

    # try to service
    rospy.wait_for_service('/rb1_base/robotnik_base_control/set_elevator')
    srv = rospy.ServiceProxy('/rb1_base/robotnik_base_control/set_elevator', SetElevator)
    #self.srv = srv
    #self.srv(1)
    req = SetElevatorRequest(1)
    srv(req)

        # Make sure we have the initial pose
        while initial_pose.header.stamp == "":
            rospy.sleep(1)
            
        rospy.loginfo("Starting navigation test")

it's about navigation from this line.

and this is the log.

error log

eh420@EH420-INDUSTRY:~/catkin_ws/src$ python multi_point_nav/multi_point_nav.py [INFO] [1552719722.921687]: Waiting for move_base action server...
[INFO] [1552719723.034903]: Connected to move base server
[INFO] [1552719723.035198]: *** Click the 2D Pose Estimate button in RViz to set the robot's initial pose...
Traceback (most recent call last):
  File "multi_point_nav/multi_point_nav.py", line 186, in <module>
    MultiPointNav()
  File "multi_point_nav/multi_point_nav.py", line 83, in __init__
    srv(req)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/impl/tcpros_service.py", line 435, in __call__
    return self.call(*args, **kwds)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/impl/tcpros_service.py", line 512, in call
    transport.send_message(request, self.seq)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/impl/tcpros_base.py", line 665, in send_message
    serialize_message(self.write_buff, seq, msg)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/msg.py", line 152, in serialize_message
    msg.serialize(b)
  File "/home/eh420/catkin_ws/devel/lib/python2.7/dist-packages/robotnik_msgs/srv/_SetElevator.py", line 63, in serialize
    buff.write(_get_struct_i().pack(self.action.action))
AttributeError: 'int' object has no attribute 'action'
[INFO] [1552719727.562072]: Stopping the robot...

Originally posted by suho0515 on ROS Answers with karma: 16 on 2019-03-15

Post score: 0


Original comments

Comment by jarvisschultz on 2019-03-15:
Is there any way that you can share a bit of code? You are likely incorrectly using the classes created from the service definition.

Comment by jarvisschultz on 2019-03-15:
You probably need something like the following:

from robotnik_msgs.srv import SetElevatorRequest
req = SetElevatorRequest(1)
service_client(req)

Where service_client would be an instance of rospy.ServiceProxy

Comment by suho0515 on 2019-03-16:
Thank you for your information, jarvisschultz! okay i would share a bit of code where related with service call, and i fixed the code based on what you said, like

try to call service

rospy.wait_for_service('/rb1_base/robotnik_base_control/set_elevator')
srv = rospy.ServiceProxy('/rb1_base/robotnik_base_control/set_elevator', SetElevator)
#self.srv = srv
#self.srv(1)
req = SetElevatorRequest(1)
srv(req)

but it came same error 'AttributeError : 'int' object has no attribute 'action'' i would post more information you told me!

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

I solved this issue somehow! jarvisschultz told me it could be problem with service definition. so i try to make differnce about service definition,

I fixed it to

# fixed code
rospy.wait_for_service('/rb1_base/robotnik_base_control/set_elevator')
srv = rospy.ServiceProxy('/rb1_base/robotnik_base_control/set_elevator', SetElevator)
req = SetElevator()
req.action = 1 or -1
srv(req)

now i can handle it perfectly. thanks for advice, jarvisschultz!


Originally posted by suho0515 with karma: 16 on 2019-03-18

This answer was ACCEPTED on the original site

Post score: 0


Original comments

Comment by gvdhoorn on 2019-03-18:
You should be able to use keyword args. Something like this should also work:

req = SetElevator(action=1)

Comment by jarvisschultz on 2019-03-18:
Are you using SetElevator() or SetElevatorRequest()? Shouldn't you need to instantiate a request to pass into the ServiceProxy? The keyword arguments @gvdhoorn mentioned certainly work, but the positional arguments first mentioned in my comment should work as well.

Comment by suho0515 on 2019-03-18:
Hm... it doesn't works in those ways... If i put SetElevatorRequest argument in ServicePoxy then it says 'AttributeError: type object 'SetElevatorRequest' has no attribute '_request_class' And if i use 'req = SetElevator(action=1)' then it says 'TypeError: object() takes no parameters' And if i use 'req = SetElevatorRequest(1)' then it says 'AttributError: 'int' object has no attribute 'action''

$\endgroup$

Your Answer

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