Go to Goal - Class instance has no attribute "position"

Hello,
I’m currently working on a project on which I try to make my robot reach a goal (I took inspiration from the code provided here.
However I subscribe to Odometry instead of Pose. Here is the beginning of my code:

#! /usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
from nav_msgs.msg import Odometry
from sensor_msgs.msg import LaserScan
from math import pow, atan2, sqrt
from tf.transformations import euler_from_quaternion

class ToGoal():

def __init__(self):

    rospy.init_node('MoveRobot', anonymous=True)

    # Publisher which will publish to the topic '/cmd_vel'.
    self.pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)

    self.sub = rospy.Subscriber('/odom', Odometry, self.callback)

    self.goalx = 2.0
    self.goaly = 0.0

    self.position = Odometry()
    
    self.rate = rospy.Rate(10)

def callback(self, msg):
    """Callback function which is called when a new message is received by the subscriber."""
   
    self.positionx = msg.pose.pose.position.x
    self.positiony = msg.pose.pose.position.y
    self.orientation_q = msg.pose.pose.orientation
    self.orientation_list = [self.orientation_q.x, self.orientation_q.y, self.orientation_q.z, self.orientation_q.w]
    (self.roll, self.pitch, self.yaw) = euler_from_quaternion (self.orientation_list)
    print(self.positionx, self.positiony, self.yaw)
    

def euclidean_distance(self):
    """Euclidean distance between current pose and the goal."""
    return sqrt(pow((self.goalx - self.positionx), 2) + pow((self.goaly - self.positiony), 2))

When I try to run it, I have the following message "Attribute error : AvoidObstaclesToGoal instance has no attribute “positionx”
I have this message for the first use of positionx in the euclidian_distance method, and for following lines where this method is called

I don’t understand because I saw to to it that I put self. each time in my constructor, so I guess the error comes from somewhere else ?
Let me know if you need more of my code

Cheers

Arthur

@algl2000,

Which course are you doing and which problem are you trying to solve?

It is a rosject which is not in the ROS Ignite courses (as far as I know). I want to make my robot move to the given goal positions so I took inspiration from the code provided here (although I subscribe to /odom and I dont ask the goal position to the user, I predefine it)

The whole code :

#! /usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
from nav_msgs.msg import Odometry
from sensor_msgs.msg import LaserScan
from math import pow, atan2, sqrt
from tf.transformations import euler_from_quaternion

class ToGoal():

    def __init__(self):
    
        rospy.init_node('MoveRobot', anonymous=True)

        # Publisher which will publish to the topic '/cmd_vel'.
        self.pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
        self.sub = rospy.Subscriber('/odom', Odometry, self.callback)

        self.goalx = 2.0
        self.goaly = 0.0

        self.position = Odometry()
        
        self.rate = rospy.Rate(10)

    def callback(self, msg):
        """Callback function which is called when a new message is received by the subscriber."""
       
        self.positionx = msg.pose.pose.position.x
        self.positiony = msg.pose.pose.position.y
        self.orientation_q = msg.pose.pose.orientation
        self.orientation_list = [self.orientation_q.x, self.orientation_q.y, self.orientation_q.z, self.orientation_q.w]
        (self.roll, self.pitch, self.yaw) = euler_from_quaternion (self.orientation_list)
        print(self.positionx, self.positiony, self.yaw)
        

    def euclidean_distance(self):
        """Euclidean distance between current pose and the goal."""
        return sqrt(pow((self.goalx - self.positionx), 2) + pow((self.goaly - self.positiony), 2))

    def linear_vel(self):
        return 1.5 * self.euclidean_distance(self)

    def steering_angle(self):
        return atan2(self.goaly - self.positiony, self.goalx - self.positionx)

    def angular_vel(self):
        return 6 * (self.steering_angle(self.goalx, self.goaly) - self.yaw) 

    def move2goal(self):
        """Moves the turtle to the goal."""
        
        move = Twist()

        print("Distance to goal is %f", self.euclidean_distance())

        while self.euclidean_distance() >= 0.01:

            # Linear velocity in the x-axis.
            move.linear.x = self.linear_vel()
            move.linear.y = 0
            move.linear.z = 0

            # Angular velocity in the z-axis.
            move.angular.x = 0
            move.angular.y = 0
            move.angular.z = self.angular_vel()

            # Publishing our vel_msg
            self.pub.publish(move)

            # Publish at the desired rate.
            self.rate.sleep()

        # Stopping our robot after the movement is over.
        move.linear.x = 0
        move.angular.z = 0
        self.pub.publish(move)

        # If we press control + C, the node will stop.
        rospy.spin()

if __name__ == '__main__':
    try:
        objectToGoal = ToGoal()
        objectToGoal.move2goal()
    except rospy.ROSInterruptException:
        pass

Hi @algl2000,

The problem here seems to be that callback had not been called by the time move2goal is called, and unless callback is called, that variable will not be defined yet.

You probably need to rewrite the code to ensure that those variables are defined before you use them. Maybe:

  • Define them in __init__, or
  • Check that they are defined before trying to use them.

Thank you ! I did that and the program works as expected

1 Like