: started with pid [11747]
[INFO] [1678223798.285249, 1831.599000]: OdomRecord action started
[INFO] [1678223798.367049, 1831.601000]: the robot does not start moving yet
[INFO] [1678223798.459553, 1831.625000]: the robot does not start moving yet
[ERROR] [1678223798.468999, 1831.650000]: Exception in your execute callback: ‘Point’ object has no attribute ‘pose’
Traceback (most recent call last):
File “/home/simulations/public_sim_ws/src/all/actionlib/actionlib/src/actionlib/simple_action_server.py”, line 289, in executeLoop
self.execute_callback(goal)
File “/home/user/catkin_ws/src/project/src/action_server.py”, line 82, in callback_action
distance_x_home = (self.current_position.pose.pose.position.x) - (home_position.pose.pose.position.x)
AttributeError: ‘Point’ object has no attribute ‘pose’
#! /usr/bin/env python
import math
import rospy
import actionlib
from project.msg import OdomRecordAction ,OdomRecordResult , OdomRecordFeedback
from nav_msgs.msg import Odometry
import tf
class record_odomClass(object):
_feedback = OdomRecordFeedback()
_result = OdomRecordResult()
def __init__(self):
self.server = actionlib.SimpleActionServer('record_odom',OdomRecordAction,self.callback_action,False)
rospy.sub = rospy.Subscriber('/odom' , Odometry , self.callback)
rospy.wait_for_message('/odom' , Odometry)
self.server.start()
self.odom = Odometry()
self.current_position = Odometry()
self.last_position = Odometry()
def callback(self,msg):
self.odom = msg
def callback_action(self,goal):
r =rospy.Rate(1)
success = True
distance = 0
distance_from_home_position = 0
home_position = Odometry()
home_position = self.odom.pose.pose.position
self._feedback.current_total = 0
self._result.list_of_odoms = []
rospy.loginfo("OdomRecord action started")
#theta
orientation_= Odometry()
orientation_.pose.pose.orientation = self.current_position.pose.pose.orientation
quaternion = [orientation_.pose.pose.orientation.x, orientation_.pose.pose.orientation.y,orientation_.pose.pose.orientation.z, orientation_.pose.pose.orientation.w]
euler = tf.transformations.euler_from_quaternion(quaternion)
angle = euler[2] # Get the yaw angle from the euler angles
#x and y
self.current_position.pose.pose.position = self.odom.pose.pose.position
self.last_position.pose.pose.position = self.odom.pose.pose.position
self._result.list_of_odoms.append(self.odom.pose.pose.position.x)
self._result.list_of_odoms.append(self.odom.pose.pose.position.y)
self._result.list_of_odoms.append(angle)
while(1):
if self.server.is_preempt_requested():
rospy.loginfo("the goal is cnaceled")
self.server.set_preempted()
success = False
break
self.current_position.pose.pose.position = self.odom.pose.pose.position
if self.current_position == self.last_position:
rospy.loginfo("the robot does not start moving yet")
else:
distance_x = self.current_position.pose.pose.position.x - self.last_position.pose.pose.position.x
distance_y = self.current_position.pose.pose.position.y - self.last_position.pose.pose.position.y
#theta
orientation_.pose.pose.orientation = self.current_position.pose.pose.orientation
quaternion = [orientation_.pose.pose.orientation.x, orientation_.pose.pose.orientation.y,orientation_.pose.pose.orientation.z, orientation_.pose.pose.orientation.w]
euler = tf.transformations.euler_from_quaternion(quaternion)
angle = euler[2] # Get the yaw angle from the euler angles
#distance
distance += math.sqrt(distance_x**2 + distance_y**2)
#distance from home
distance_x_home = (self.current_position.pose.pose.position.x) - (home_position.pose.pose.position.x)
distance_y_home = (self.current_position.pose.pose.position.y) - (home_position.pose.pose.position.y)
distance_from_home_position = math.sqrt(distance_x_home**2 + distance_y_home**2)
#publish the feedback
self._feedback = distance
self.server.publish_feedback(self._feedback)
#store the recorded odometery
self._result.list_of_odoms.append(self.odom.pose.pose.position.x)
self._result.list_of_odoms.append(self.odom.pose.pose.position.y)
self._result.list_of_odoms.append(angle)
#see if the turtlebot done a complete loop
if ((distance_from_home_position < 0.3) and (distance_from_home_position > 0 )):
break
r.sleep()
if success:
rospy.loginfo("action successd")
self.server.set_succeeded(self._result)
if __name__ == '__main__':
rospy.init_node('action_node')
record_odomClass()
rospy.spin()
thanks it worked one last question i am finding some trouble in knowing when the robot has done a full lab in my code if the robot current_position - home position is less than 0.1 the loop will break and the action is succeed but this is not valid as the second the robot moves this condition becomes true is there is another way to done this ?
#! /usr/bin/env python
import math
import rospy
import actionlib
from project.msg import OdomRecordAction ,OdomRecordResult , OdomRecordFeedback
from nav_msgs.msg import Odometry
from geometry_msgs.msg import Point
import tf
class record_odomClass(object):
_feedback = OdomRecordFeedback()
_result = OdomRecordResult()
def __init__(self):
self.server = actionlib.SimpleActionServer('record_odom',OdomRecordAction,self.callback_action,False)
rospy.sub = rospy.Subscriber('/odom' , Odometry , self.callback)
rospy.wait_for_message('/odom' , Odometry)
self.server.start()
self.odom = Odometry()
self.current_position = Odometry()
self.last_position = Odometry()
def callback(self,msg):
self.odom = msg
def callback_action(self,goal):
r =rospy.Rate(1)
success = True
count = 0
distance = 0
distance_from_home_position = 0
home_position = Odometry()
home_position = self.odom.pose.pose.position
self._feedback = 0.0
self._result.list_of_odoms = []
rospy.loginfo("OdomRecord action started")
#theta
orientation_= Odometry()
orientation_.pose.pose.orientation = self.current_position.pose.pose.orientation
quaternion = [orientation_.pose.pose.orientation.x, orientation_.pose.pose.orientation.y,orientation_.pose.pose.orientation.z, orientation_.pose.pose.orientation.w]
euler = tf.transformations.euler_from_quaternion(quaternion)
angle = euler[2] # Get the yaw angle from the euler angles
#x and y
self.current_position.pose.pose.position = self.odom.pose.pose.position
self.last_position.pose.pose.position = self.odom.pose.pose.position
self._result.list_of_odoms.append(self.odom.pose.pose.position.x)
self._result.list_of_odoms.append(self.odom.pose.pose.position.y)
self._result.list_of_odoms.append(angle)
while(1):
self.current_position.pose.pose.position = self.odom.pose.pose.position
while self.current_position == self.last_position:
rospy.loginfo("the robot does not start moving yet")
rospy.sleep(1)
if self.server.is_preempt_requested():
rospy.loginfo("the goal is cnaceled")
self.server.set_preempted()
success = False
break
else:
distance_x = self.current_position.pose.pose.position.x - self.last_position.pose.pose.position.x
distance_y = self.current_position.pose.pose.position.y - self.last_position.pose.pose.position.y
#theta
orientation_.pose.pose.orientation = self.current_position.pose.pose.orientation
quaternion = [orientation_.pose.pose.orientation.x, orientation_.pose.pose.orientation.y,orientation_.pose.pose.orientation.z, orientation_.pose.pose.orientation.w]
euler = tf.transformations.euler_from_quaternion(quaternion)
angle = euler[2] # Get the yaw angle from the euler angles
#distance
distance += math.sqrt(distance_x**2 + distance_y**2)
#distance from home
distance_x_home = (self.current_position.pose.pose.position.x) - (home_position.x)
distance_y_home = (self.current_position.pose.pose.position.y) - (home_position.y)
distance_from_home_position = math.sqrt(distance_x_home**2 + distance_y_home**2)
#publish the feedback
self._feedback = distance
self.server.publish_feedback(self._feedback)
#update position
self.last_position = self.current_position
#store the recorded odometery
my_point = Point()
my_point.x = distance_x
my_point.y = distance_y
my_point.z = angle
self._result.list_of_odoms.append(my_point)
#see if the turtlebot done a complete loop
if (0.3 > distance_from_home_position > 0.1):
rospy.loginfo(distance_from_home_position)
break
r.sleep()
if success:
rospy.loginfo("action successd")
self.server.set_succeeded(self._result)
if __name__ == '__main__':
rospy.init_node('action_node')
record_odomClass()
rospy.spin()
The best way to fix this is to move the robot for a few seconds, say 30 seconds, and then start calculating the distance between the starting pose and current pose. This way you can complete a lap successfully.
You are calculating the distance between the robot and start pose from the very beginning which causes this problem.
This is what I did in my project too. So I am telling this from my experience. This will fix your problem.
thanks your advise really helped me but i want to ask another simple question the self.last_position is seems to be updated at every call so that the current and last values will be always be the same how can i fix this?
#! /usr/bin/env python
import math
#import time
import rospy
import actionlib
from project.msg import OdomRecordAction ,OdomRecordResult , OdomRecordFeedback
from nav_msgs.msg import Odometry
from geometry_msgs.msg import Point
import tf
class record_odomClass(object):
_feedback = OdomRecordFeedback()
_result = OdomRecordResult()
def __init__(self):
self.server = actionlib.SimpleActionServer('record_odom',OdomRecordAction,self.callback_action,False)
rospy.sub = rospy.Subscriber('/odom' , Odometry , self.callback)
rospy.wait_for_message('/odom' , Odometry)
self.server.start()
self.odom = Odometry()
self.current_position = Odometry()
self.last_position = Odometry()
def callback(self,msg):
self.odom = msg
def callback_action(self,goal):
r =rospy.Rate(1)
success = True
count = 0
distance = 0
distance_from_home_position = 0
home_position = Odometry()
home_position = self.odom.pose.pose.position
self._feedback = 0.0
self._result.list_of_odoms = []
rospy.loginfo("OdomRecord action started")
#theta
orientation_= Odometry()
orientation_.pose.pose.orientation = self.current_position.pose.pose.orientation
quaternion = [orientation_.pose.pose.orientation.x, orientation_.pose.pose.orientation.y,orientation_.pose.pose.orientation.z, orientation_.pose.pose.orientation.w]
euler = tf.transformations.euler_from_quaternion(quaternion)
angle = euler[2] # Get the yaw angle from the euler angles
#x and y
self.current_position.pose.pose.position = self.odom.pose.pose.position
self.last_position.pose.pose.position = self.odom.pose.pose.position
self._result.list_of_odoms.append(self.odom.pose.pose.position.x)
self._result.list_of_odoms.append(self.odom.pose.pose.position.y)
self._result.list_of_odoms.append(angle)
t_start = rospy.Time.now()
rospy.logwarn(t_start)
rospy.logwarn(t_start.to_sec())
while(1):
self.current_position.pose.pose.position = self.odom.pose.pose.position
while round(self.current_position.pose.pose.position.x, 3) == round(self.last_position.pose.pose.position.x, 3) and \
round(self.current_position.pose.pose.position.y, 3) == round(self.last_position.pose.pose.position.y, 3):
self.current_position.pose.pose.position = self.odom.pose.pose.position
rospy.logwarn(self.current_position.pose.pose.position)
rospy.logwarn(self.last_position.pose.pose.position)
rospy.loginfo("the robot is not moving")
rospy.sleep(1)
if self.server.is_preempt_requested():
rospy.loginfo("the goal is cnaceled")
self.server.set_preempted()
success = False
break
else:
distance_x = self.current_position.pose.pose.position.x - self.last_position.pose.pose.position.x
distance_y = self.current_position.pose.pose.position.y - self.last_position.pose.pose.position.y
#theta
orientation_.pose.pose.orientation = self.current_position.pose.pose.orientation
quaternion = [orientation_.pose.pose.orientation.x, orientation_.pose.pose.orientation.y,orientation_.pose.pose.orientation.z, orientation_.pose.pose.orientation.w]
euler = tf.transformations.euler_from_quaternion(quaternion)
angle = euler[2] # Get the yaw angle from the euler angles
#distance
distance += math.sqrt(distance_x**2 + distance_y**2)
#distance from home
distance_x_home = (self.current_position.pose.pose.position.x) - (home_position.x)
distance_y_home = (self.current_position.pose.pose.position.y) - (home_position.y)
distance_from_home_position = math.sqrt(distance_x_home**2 + distance_y_home**2)
#publish the feedback
self._feedback = distance
self.server.publish_feedback(self._feedback)
#update position
self.last_position = self.current_position
#store the recorded odometery
my_point = Point()
my_point.x = distance_x
my_point.y = distance_y
my_point.z = angle
self._result.list_of_odoms.append(my_point)
t_before_end = rospy.Time.now()
if((t_before_end - t_start).to_sec() > 20):
rospy.loginfo(t_before_end-t_start)
#see if the turtlebot done a complete loop
if (0.3 > round(distance_from_home_position,3) > 0.1):
rospy.loginfo(distance_from_home_position)
break
r.sleep()
if success:
rospy.loginfo("action successd")
self.server.set_succeeded(self._result)
if __name__ == '__main__':
rospy.init_node('action_node')
record_odomClass()
rospy.spin()
i actually know the mistake but i asked about a differrent way so they did not get the same value as you can see at each callback of the odom msg they both get update despite there place in the code
In my opinion, you do not require those two variables : current_position and last_position.
The reason being, you should return the list of all poses travelled by the robot when the action server returns the result. So, the better way to do this is to store the odometry readings in a list and use the last two pose values from the list to calculate the distance moved every second.
So, the best way to remove this error would be to refactor your code logic.