ros-navigation / navigation2

ROS 2 Navigation Framework and System
https://nav2.org/
Other
2.31k stars 1.2k forks source link

Compute Path Through Poses, transformPoseInTargetFrame "base link" does not exist #4508

Closed T-Lemmel closed 5 days ago

T-Lemmel commented 6 days ago

Bug report ??

Required Info:

Hello, when launching navigation THROUGH poses from the rvizz nav2 panel i get this error : [bt_navigator-10] [ERROR] [1719908993.170399840] [transformPoseInTargetFrame]: No Transform available Error looking up target frame: "base_link" passed to lookupTransform argument source_frame does not exist.

The frame "base_link" indeed doesn't exist, in my case it is robot_name/body but i don't find anyway to change the frame used here, the robot_frame/body frame is used correctly in all nodes (bt_navigator, controller_server, both costmaps...), which i achieved through remapping in my launch file, i checked every node and none has the frame base_link has a parameter.

I haven't found anything regarding transformPoseInTargetFrame neither online or in source files. So i'm not sure what is the problem but it seems like it is a function used in bt_navigator that doesn't properly use the bt_navigator robot_base_frame parameter.

Thanks in advance for the help

CptCurty commented 5 days ago

I have the same issue with the same operating system and ros2 version where I get the error [bt_navigator-33] [ERROR] [1719931676.740139953] [transformPoseInTargetFrame]: No Transform available Error looking up target frame: "map" passed to lookupTransform argument target_frame does not exist. Eventhough I have specified the global_frame and robot_base_frame:

 bt_navigator:
  ros__parameters:
    use_sim_time: True
    global_frame: agent1/map
    robot_base_frame: agent1/base_link
    odom_topic: /agent1/odometry
    bt_loop_duration: 20
    default_server_timeout: 30
    navigators: ["navigate_to_pose","navigate_through_poses"]
    navigate_to_pose:
      plugin: "nav2_bt_navigator/NavigateToPoseNavigator"
    navigate_through_poses:
      plugin: "nav2_bt_navigator/NavigateThroughPosesNavigator"

I use it in the following script:

#! /usr/bin/env python3

import time
import os
from copy import deepcopy
from ament_index_python.packages import get_package_share_directory
from geometry_msgs.msg import PoseStamped
from rclpy.exceptions import ROSInterruptException
import rclpy
from nav2_simple_commander.robot_navigator import BasicNavigator, TaskResult
import yaml

def main():
    try:
        rclpy.init()
        #Location of the waypoint yaml file
        main_package_location = get_package_share_directory('core_cleaning_robot')
        yaml_params_location = os.path.join(main_package_location, 'config', 'waypoint_nav_params.yaml')

        #Get the parameters from the yaml file
        with open(yaml_params_location, 'r') as file:
            params = yaml.safe_load(file)
            trajectories = params['follow_waypoints']['trajectories']

        #get the parameters declared in the launch file
        navigator = BasicNavigator()
        namespace= navigator.get_namespace()

        #trim / of namespace
        trimmed_namespace = namespace[1:]

        inspection_route = []

        for trajectory in trajectories:
            if trajectory['name'] == namespace:
                points= trajectory['points']
                for point_name in points:
                    point_to_append = params['follow_waypoints'][point_name]
                    inspection_route.append([point_to_append['x_pose'], point_to_append['y_pose']])

        # Wait for navigation to fully activate
        navigator.waitUntilNav2Active(localizer=f"{namespace}/planner_server")

        while rclpy.ok():
            # Send our route
            inspection_points = []
            inspection_pose = PoseStamped()
            inspection_pose.header.frame_id = f'{trimmed_namespace}/map'
            inspection_pose.header.stamp = navigator.get_clock().now().to_msg()
            inspection_pose.pose.orientation.z = 1.0
            inspection_pose.pose.orientation.w = 0.0
            for pt in inspection_route:
                inspection_pose.pose.position.x = pt[0]
                inspection_pose.pose.position.y = pt[1]
                inspection_points.append(deepcopy(inspection_pose))
            navigator.goThroughPoses(inspection_points)

            i = 0
            while not navigator.isTaskComplete():
                i = i + 1
                feedback = navigator.getFeedback()
                if feedback and i % 40 == 0:
                    print('Timestep:', i)

            result = navigator.getResult()
            if result == TaskResult.SUCCEEDED:
                print('Task completed!')
            elif result == TaskResult.CANCELED:
                print('Task was canceled.')
                exit(1)
            elif result == TaskResult.FAILED:
                print('Task failed! ')

            while not navigator.isTaskComplete:
                pass
    except ROSInterruptException as e:
        print(f"ROS interrupt exception caught: {e}")
    except Exception as e:
        print(f"General exception caught: {e}")
    finally:
        navigator.lifecycleShutdown()

if __name__ == '__main__':
    main()
SteveMacenski commented 5 days ago

I did a 5 minute scan of the codebase and can't find anywhere that we have hardcoded base_link that isn't parameterized by the node. Please see the configuration guides at docs.nav2.org for a full parameter list and set the robot's base frame appropriately for each node.

Happy to reopen if you fine a bug, but this seems like missing some subtle configurations.