I have been stuck on this python script for two weeks and was wondering if anyone could help. I am doing the first rosject and have this code for my action client:
#! /usr/bin/env python
import rospy
import actionlib
import turtle2.msg
from turtle2.msg import turtlemvmtAction, turtlemvmtGoal, turtlemvmtResult, turtlemvmtFeedback
import rospy
import sensor_msgs.msg
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
from std_msgs.msg import String
#Get information from /scan into turtlemvmtGoal
class ActionClient(): #prereq instead of of object , or self???
def __init__(self, dist): #Constructors are used to initialize the objectâs state. The task of constructors is to initialize(assign values) to the data members of the class when an object of class is created. Like methods, a constructor also contains collection of statements(i.e. instructions) that are executed at time of Object creation. It is run as soon as an object of a class is instantiated. The method is useful to do any initialization you want to do with your object.
self.dist = dist
self.sub = rospy.Subscriber('/scan', LaserScan, self.callback)
def callback(self, msg) :
dist = (msg.ranges[180])
print ("point 1", dist)
self.call_server()
def feedback_cb(self):
print ("point 4: completed")
def call_server(self):
print ("point 2, server called")
print ("point 3", self.dist)
self.dist = turtlemvmtGoal()
client = actionlib.SimpleActionClient('sharedspace', turtlemvmtAction)
client.wait_for_server()
client.send_goal(self.dist, feedback_cb = self.feedback_cb)
client.wait_for_result()
result = client.get_result()
return result
if name == âmainâ:
try:
rospy.init_node(âaction_clientâ)
j = ActionClient(dist=None)
print (âThe result is:â,)
rospy.spin()
except rospy.ROSInterruptException as e:
print (âSomething went wrong:â, e)
Everything seems ok until point 3, where my ranges end up empty even though I called on self.dist.
My script failes to continue to point 4, which I assume is because of the error Iâm getting to point 3,
When I investigate to see
Caveat - Iâm not familiar with the details of this Rosject. Regardless, hereâs what I noticed:
You initiate your action client object with a dist of None
therefore self.dist is set as None as a result of this:
When you get a scan result, you assign the distance to one of the ranges
Note that you do not make an assignment to self.dist. Here dist is simply a local variable. Self.dist is still equal to None.
I am a bit confused as to then why when you do this:
You actually get âranges: â and not just None back. Did you leave anything out in what you posted?
Iâm also a little confused by your data flow - as far as I can tell youâll call the action client when you get a sensor message. The comment in your program says:
But further down you have
So here you are redefining self.dist as a turtlemovementGoal object. But you donât have any data in it when you then send it to the action server.
These are super helpful thank you so much for your time and patience!
Note that you do not make an assignment to self.dist . Here dist is simply a local variable. Self.dist is still equal to None.
Thank you! I think I had that initially then went ot make changes and forgot to reset and dug myself into a hole. That was really helpful!
You actually get âranges: â and not just None back. Did you leave anything out in what you posted?
This really confused me!!! I dont know why I got that. On my .action file I have it as a float so its werid that it shows up like that. Either way, thats resolved with the above changes
So here you are redefining self.dist as a turtlemovementGoal object. But you donât have any data in it when you then send it to the action server.
Now that I made the correction above (self.dist instead of dist), I feel that I should have data in it. When I run the action client, I get
HOWEVER, when I run rostopic echo on sharedspace/goal I come up empty
Shouldnt ranges be filled with the data from self.dist???
Also, if we continue on the script, when we get to:
No. When you do this: self.dist = turtlemvmtGoal() what you are doing is re-assigning the variable self.dist to be a turtlemvmtGoal message object. The distance that you had stored is no longer there. You just have an empty message object. Thatâs OK - you actually need that to send the message to the action server. Since this is a whole message object, youâll need to assign a value to the part of the object that contains the distance. As I said - Iâm not familiar with the specifics of this Rosject. Did you make a custom message? What is the structure of the message? Usually you do something like this:
Since you are taking a reading from where you already are, and then sending that distance to a goal, Iâm not sure that youâll actually go anywhere unless your action server is programmed to move a certain distance away from the âgoalâ.
I also tried client.send_goal(goal_message, feedback_cb = self.feedback_cb) but got errors as well
I dont fully understand it because it goes outside of the catkin workspace but im getting the impression that one of my variables or objects is configured incorrectly. If I need to make a custom message to address then then I can work on trying to do that.
The goal of the overall project is the move the robot in a square around a room while maintaning a certain distance from the wall. In my action server Im trying to program the robot to move forward and made adjustments in its path if it senses the wall less than a certain value
Thank you very much - I dont have much program experience prior to this endeavor and your help really make me understand the concepts better
So you did actually create a custom message as part of that. But your goal is a list of float 32 (float32), which probably isnât what you want. What value does the action server expect? Probably the distance from the wall so it can adjust the path. So now I see why youâd send the current distance.
Iâd work backward from what the action server wants and make sure youâre sending the right data type.
/K