diff --git a/src/roboticstoolbox/models/URDF/KinovaGen3.py b/src/roboticstoolbox/models/URDF/KinovaGen3.py index 638c57c2..454ed5a6 100644 --- a/src/roboticstoolbox/models/URDF/KinovaGen3.py +++ b/src/roboticstoolbox/models/URDF/KinovaGen3.py @@ -31,7 +31,7 @@ class KinovaGen3(URDFRobot): def __init__(self): super().__init__( - "kortex_description/robots/gen3.xacro", + "gen3", manufacturer="Kinova", gripper_link_index=10, ) diff --git a/src/roboticstoolbox/models/URDF/URDFRobot.py b/src/roboticstoolbox/models/URDF/URDFRobot.py index ad035980..50f7de28 100644 --- a/src/roboticstoolbox/models/URDF/URDFRobot.py +++ b/src/roboticstoolbox/models/URDF/URDFRobot.py @@ -116,7 +116,7 @@ def _load_rd_module(robot_name: str): ) from last_error -def _load_urdf_from_RD(robot_name: str) -> Path: +def _load_urdf_from_RD(robot_name: str) -> "tuple[Path, dict | None]": """Fetch the URDF/xacro path from robot_descriptions and register its packages. robot_descriptions models expose different path attributes depending on their @@ -125,6 +125,13 @@ def _load_urdf_from_RD(robot_name: str) -> Path: - XACRO_PATH — a xacro source that must be processed by xacrodoc (e.g. j2n6s200, ur5, kinova family) Both are passed to XacroDoc.from_file(), which handles either format. + + Some xacro-based models also expose ``XACRO_ARGS`` — substitution + values required to compile the file at all (e.g. Kinova Gen3's + ``{"dof": "7"}``, which selects the 6dof/7dof arm variant; several UR + and xArm variants have the same pattern). Returned alongside the path + so the caller can forward them to xacrodoc as ``subargs`` — without + them, xacro fails on an unresolved ``$(arg ...)``/property reference. """ module = _load_rd_module(robot_name) @@ -138,7 +145,7 @@ def _load_urdf_from_RD(robot_name: str) -> Path: "URDF_PATH nor XACRO_PATH." ) _register_rd_packages(urdf_path) - return urdf_path + return urdf_path, getattr(module, "XACRO_ARGS", None) def _parse_urdf(urdf_str: str): @@ -285,10 +292,11 @@ def URDF_file( pkg_map = {d.name: str(d) for d in xacro_root.iterdir() if d.is_dir()} packages.update_package_cache(pkg_map) + xacro_args = None if isinstance(file, str): file = Path(file) if file.suffix not in (".urdf", ".xacro"): - file = Path(_load_urdf_from_RD(str(file))) + file, xacro_args = _load_urdf_from_RD(str(file)) resolved_path = None if isinstance(file, Path): @@ -299,9 +307,11 @@ def URDF_file( # mirrors XacroDoc.from_file()'s own package-discovery step, # since we bypass from_file() here to patch the text first packages.walk_up_from(file) - doc = XacroDoc.from_string(patch(file.read_text()), rootdir=file.parent) + doc = XacroDoc.from_string( + patch(file.read_text()), rootdir=file.parent, subargs=xacro_args + ) else: - doc = XacroDoc.from_file(file) + doc = XacroDoc.from_file(file, subargs=xacro_args) else: text = file.read() if patch is not None: