Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/user_guide/transform_manager.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ you. For the given example, this would be the corresponding code

.. literalinclude:: ../../../examples/plots/plot_transform_manager.py
:language: python
:lines: 27-32
:lines: 30-35

We can also export the underlying graph structure as a PNG with

Expand Down
5 changes: 4 additions & 1 deletion doc/source/user_guide/transformation_modeling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Now we can use the transformation matrix :math:`\boldsymbol T_{CA}` to transform
a point :math:`_A\boldsymbol{p}` from frame :math:`A` to frame
:math:`C` by multiplication :math:`_C\boldsymbol{p} = \boldsymbol{T}_{CA}\,_A\boldsymbol{p}`.

In code this might look differently. Here we should prefer the notation `A2B`
This might look differently in code. Here we should prefer the notation `A2B`
for a transformation from frame `A` to frame `B`.

.. code-block::
Expand All @@ -48,5 +48,8 @@ a point from `C` to `A` we can now use
p_in_A = vector_to_point(...) # point in frame A
p_in_C = transform(A2C, p_in_A)
This notation is particuarly effective when we use it in combination with
longer, more readable frame names, e.g., ``left_hand_palm`` or ``robot_base``.

For more complex cases the :class:`~pytransform3d.transform_manager.TransformManager`
can help.
6 changes: 3 additions & 3 deletions doc/source/user_guide/transformation_over_time.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ First, you need to prepare the transfomation sequences using the

.. literalinclude:: ../../../examples/plots/plot_interpolation_for_transform_manager.py
:language: python
:lines: 43-56
:lines: 47-60

In this example, the screw linear interpolation (ScLERP) will be used
(which operates on dual quaternions, refer to
Expand All @@ -47,7 +47,7 @@ Next, you need to pass the transformations to an instance of

.. literalinclude:: ../../../examples/plots/plot_interpolation_for_transform_manager.py
:language: python
:lines: 58-61
:lines: 62-65

------------------------------------
Transform Between Coordinate Systems
Expand All @@ -58,7 +58,7 @@ Finally, you can transform between coordinate systems at a particular time

.. literalinclude:: ../../../examples/plots/plot_interpolation_for_transform_manager.py
:language: python
:lines: 63-68
:lines: 67-72

The coordinates of A's origin (blue diamond) transformed to B are visualized
in the plot below:
Expand Down
2 changes: 1 addition & 1 deletion pytransform3d/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""3D transformations for Python."""

__version__ = "3.14.2"
__version__ = "3.14.3"
30 changes: 30 additions & 0 deletions pytransform3d/test/test_urdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,36 @@ def test_missing_child_link_name():
UrdfTransformManager().load_urdf(urdf)


def test_xml_namespace():
urdf = """
<robot name="robot_name" xmlns="http://www.ros.org">
<link name="link0"/>
<link name="link1">
<visual name="link1_visual">
<origin xyz="0 0 1"/>
<geometry/>
</visual>
</link>
<joint name="joint0" type="fixed">
<parent link="link0"/>
<child link="link1"/>
<origin xyz="0 1 0"/>
</joint>
</robot>
"""

robot_name, links, joints = parse_urdf(urdf)

assert robot_name == "robot_name"
assert len(links) == 2
assert len(joints) == 1

for link in links:
assert link.name in ["link0", "link1"]

assert joints[0].joint_name == "joint0"


def test_reference_to_unknown_child():
urdf = """
<robot name="robot_name">
Expand Down
11 changes: 5 additions & 6 deletions pytransform3d/transform_manager/test/test_transform_manager.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
import os
import pickle
import tempfile
Expand Down Expand Up @@ -193,10 +194,9 @@ def test_pickle():
tm2 = pickle.load(f)
finally:
if os.path.exists(filename):
try:
# workaround for permission problem on Windows
with contextlib.suppress(OSError):
os.remove(filename)
except OSError:
pass # workaround for permission problem on Windows
A2B2 = tm2.get_transform("A", "B")
assert_array_almost_equal(A2B, A2B2)

Expand Down Expand Up @@ -293,10 +293,9 @@ def test_png_export():
pytest.skip("pydot is required for this test")
finally:
if os.path.exists(filename):
try:
# workaround for permission problem on Windows
with contextlib.suppress(OSError):
os.remove(filename)
except OSError:
pass # workaround for permission problem on Windows


def test_png_export_without_pydot_fails():
Expand Down
15 changes: 15 additions & 0 deletions pytransform3d/urdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""

import os
import re
import warnings

import numpy as np
Expand Down Expand Up @@ -412,6 +413,13 @@ def parse_urdf(urdf_xml, mesh_path=None, package_dir=None, strict_check=True):
# URDF XML schema:
# https://github.com/ros/urdfdom/blob/master/xsd/urdf.xsd

# If there is an XML namespace (xmlns=...) specified, this will break
# parsing as the root tag, and the tag of all elements underneath root,
# will have a {namespace} prefix. As such, normalize the namespace to the
# default (i.e. no namespace).

_normalize_namespace(root)

if root.tag != "robot":
raise UrdfException("Robot tag is missing.")

Expand Down Expand Up @@ -462,6 +470,13 @@ def initialize_urdf_transform_manager(tm, robot_name, links, joints):
_add_joints(tm, joints)


def _normalize_namespace(root):
"""Normalizes the namespace of the root node and all elements underneath."""
root.tag = re.sub(r"\{.*?\}", "", root.tag)
for element in root.iter():
element.tag = re.sub(r"\{.*?\}", "", element.tag)


def _parse_material(material):
"""Parse material."""
if "name" not in material.attrib:
Expand Down