Xacro unable to dynamically parse file paths
Describe the bug When describing a robot via the URDF format in a Xacro file, file paths are unable to be dynamically formed. Paths such as "$(find franka_description)/robots/frankie_arm.xacro" do not actually evaluate the find argument, instead this evaluates to the working directory with no text appended. This can also be seen when trying to run $(pwd) which returns nothing.
Version information
Did you install from PyPI or GitHub? If PyPI what version number? 1.1.0 If GitHub what commit hash?
Robotics Toolbox depends heavily on two other packages: Swift (3D graphics) and SpatialMath toolbox (underpinning maths utilities). If you think your issue is related to these, then please answer the questions above for them.
To Reproduce Steps to reproduce the behavior: This can be demonstrated by breaking the frankie robot description.
- Go to the install location of the rtbdata package/xacro/franka_description/robots/frankie_arm_hand.urdf.xacro.
- Replace the line <xacro:include filename="$(find franka_description)/robots/frankie_arm.xacro"/> with <xacro:include filename="$(find franka_description)/test/robots/frankie_arm.xacro"/>
- This will break the file path and it can be seen that this actually evaluates this string with the directory that the URDF_read function is looking in with ../ appended
- It can be seen that commands do not work by replacing this line with <xacro:include filename="$(find franka_description)/test/$(pwd)/robots/frankie_arm.xacro"/> as the /$(pwd)/ section evaluates to //
- This is an issue when importing custom robots in xacros as the same line gets evaluated in multiple places (once relative to where it is defined, and once relative to where the xacro is called from), preventing robot definitions from correctly evaluating.
- Error message: No such file or directory: C:\Users\user\AppData\Local\Programs\Python\Python39\Lib\site-packages\rtbdata\xacro\franka_description\robots..//test/robots/frankie_arm.xacro when evaluating the "$(find franka_description)/test/$(pwd)/robots/frankie_arm.xacro" string
Expected behavior This should evaluate the find commands correctly rather than using a workaround to just add ../
Environment (please complete the following information):
- Your OS (MacOS, Linux, Windows). Windows 11
- Your Python version. 3.9.13
Additional context I am trying to bring in the UR10e robot description from https://github.com/ros-industrial/universal_robot
I looked into your issue and tried to solve it by changing: https://github.com/petercorke/robotics-toolbox-python/blob/2a8111b10dd09c5ce8b8a94495c84ff27bcb6862/roboticstoolbox/tools/xacro/init.py#L204 to
# Extract the package name between '$(find ' and ')'
pkg_name = s[len('$(find '):-1].strip()
# Try to find the package path using only os, searching upwards from the current file
parent_filename = filestack[-1] if filestack else None
search_dir = os.path.dirname(parent_filename) if parent_filename else os.getcwd()
while True:
candidate = os.path.join(search_dir, pkg_name)
if os.path.isdir(candidate):
# return candidate
path_to_package = Path(candidate)
return path_to_package.as_posix()
new_search_dir = os.path.dirname(search_dir)
if new_search_dir == search_dir:
break
search_dir = new_search_dir
# Fallback: just return the package name as a placeholder
return pkg_name
# return tld
and it works, but for the UR10e robot description from https://github.com/ros-industrial/universal_robot I still receive another error, which I don't have the time and energy to solve right now:
AttributeError: 'Table' object has no attribute 'get'
name 'xacro' is not defined
when evaluating expression 'xacro.load_yaml(joint_limits_parameters_file)'
when evaluating expression 'config_joint_limit_parameters['joint_limits']'
when evaluating expression 'sec_limits['shoulder_pan']['min_position']'
when instantiating macro: read_model_data
Maybe this helps you and you can look into it!