Skip to content

Commit

Permalink
Merge branch 'master' into pre-commit-ci-update-config
Browse files Browse the repository at this point in the history
  • Loading branch information
CagtayFabry authored Nov 6, 2024
2 parents 55693a2 + e0e3a65 commit 43d1b7d
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 2 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## 0.6.9 (unreleased)

### Changes

- added support for homogeneous transformation matrices \[{pull}`949`\]:
- added `create_cs_from_homogeneous_transformation` to `CoordinateSystemManager`
- added `from_homogeneous_transformation` to `LocalCoordinateSystem`
- added `as_homogeneous_matrix` to `LocalCoordinateSystem`

### Fixes

- rename (fix typo) argument to `lcs_child_in_parent` in `CoordinateSystemManager.add_cs` \[{pull}`936`\].
Expand Down
16 changes: 16 additions & 0 deletions weldx/tests/transformations/test_cs_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2749,6 +2749,10 @@ def test_coordinate_system_manager_create_coordinate_system():
orientations = np.matmul(rot_mat_x, rot_mat_y)
coords = Q_([[1, 0, 0], [-1, 0, 2], [3, 5, 7], [-4, -5, -6]], "mm")

transformation_matrix = np.resize(np.identity(4), (4, 4, 4))
transformation_matrix[:, :3, :3] = orientations
transformation_matrix[:, :3, 3] = coords.m

csm = tf.CoordinateSystemManager("root")
lcs_default = tf.LocalCoordinateSystem()

Expand Down Expand Up @@ -2790,6 +2794,18 @@ def test_coordinate_system_manager_create_coordinate_system():
time=time,
)

# from homogeneous transformation ---------------------
csm.create_cs_from_homogeneous_transformation(
"lcs_homogeneous_default", "root", transformation_matrix, coords.u, time
)
check_coordinate_system(
csm.get_cs("lcs_homogeneous_default"),
orientations,
coords,
True,
time=time,
)


def test_coordinate_system_manager_transform_data():
"""Test the coordinate system managers transform_data function."""
Expand Down
48 changes: 47 additions & 1 deletion weldx/transformations/cs_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
from weldx.exceptions import WeldxDeprecationWarning, WeldxException
from weldx.geometry import SpatialData
from weldx.time import Time, types_time_like, types_timestamp_like
from weldx.types import UnitLike
from weldx.util import check_matplotlib_available, dataclass_nested_eq

from .local_cs import LocalCoordinateSystem
from .types import types_coordinates, types_orientation
from .types import types_coordinates, types_homogeneous, types_orientation

# only import heavy-weight packages on type checking
if TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -830,6 +831,51 @@ def create_cs_from_axis_vectors(
coordinate_system_name, reference_system_name, lcs, lcs_child_in_parent
)

def create_cs_from_homogeneous_transformation(
self,
coordinate_system_name: str,
reference_system_name: str,
transformation_matrix: types_homogeneous,
translation_unit: UnitLike,
time: types_time_like = None,
time_ref: types_timestamp_like = None,
lcs_child_in_parent: bool = True,
):
"""Create a coordinate system from a homogeneous transformation matrix and add
it to the coordinate system manager.
This function uses the `LocalCoordinateSystem.from_homogeneous_transformation`
method of the `LocalCoordinateSystem` class.
Parameters
----------
coordinate_system_name :
Name of the new coordinate system.
reference_system_name :
Name of the parent system. This must have been already added.
transformation_matrix :
Describes the homogeneous transformation matrix that includes the rotation
and the translation (coordinates).
translation_unit :
Unit describing the value of the translation. Necessary, because the
homogeneous transformation matrix is unitless.
time :
Time data for time dependent coordinate systems.
time_ref :
Reference time for time dependent coordinate systems
lcs_child_in_parent :
If set to `True`, the passed `LocalCoordinateSystem` instance describes
the new system orientation towards is parent. If `False`, it describes
how the parent system is positioned in its new child system.
"""
lcs = LocalCoordinateSystem.from_homogeneous_transformation(
transformation_matrix, translation_unit, time, time_ref
)
self.add_cs(
coordinate_system_name, reference_system_name, lcs, lcs_child_in_parent
)

def delete_cs(self, coordinate_system_name: str, delete_children: bool = False):
"""Delete a coordinate system from the coordinate system manager.
Expand Down
84 changes: 83 additions & 1 deletion weldx/transformations/local_cs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@
from weldx.core import TimeSeries
from weldx.exceptions import WeldxException
from weldx.time import Time, TimeDependent, types_time_like, types_timestamp_like
from weldx.transformations.types import types_coordinates, types_orientation
from weldx.transformations.types import (
types_coordinates,
types_homogeneous,
types_orientation,
)
from weldx.transformations.util import normalize
from weldx.types import UnitLike

__all__ = ("LocalCoordinateSystem",)

Expand Down Expand Up @@ -540,6 +545,45 @@ def from_axis_vectors(
t_axes = (1, 0) if mat.ndim == 2 else (1, 2, 0)
return cls(mat.transpose(t_axes), coordinates, time, time_ref)

@classmethod
def from_homogeneous_transformation(
cls,
transformation_matrix: types_homogeneous,
translation_unit: UnitLike,
time: types_time_like = None,
time_ref: types_timestamp_like = None,
) -> LocalCoordinateSystem:
"""Construct a local coordinate system from a homogeneous transformation matrix.
Parameters
----------
transformation_matrix :
Describes the homogeneous transformation matrix that includes the rotation
and the translation (coordinates).
translation_unit :
Unit describing the value of the translation. Necessary, because the
homogeneous transformation matrix is unitless.
time :
Time data for time dependent coordinate systems (Default value = None)
time_ref :
Optional reference timestamp if ``time`` is a time delta.
Returns
-------
LocalCoordinateSystem
Local coordinate system
"""
if isinstance(transformation_matrix, xr.DataArray):
transformation_matrix = np.array(transformation_matrix.data)
if transformation_matrix.ndim == 3:
orientation = transformation_matrix[:, :3, :3]
coordinates = Q_(transformation_matrix[:, :3, 3], translation_unit)
else:
orientation = transformation_matrix[:3, :3]
coordinates = Q_(transformation_matrix[:3, 3], translation_unit)
return cls(orientation, coordinates=coordinates, time=time, time_ref=time_ref)

@property
def orientation(self) -> xr.DataArray:
"""Get the coordinate systems orientation matrix.
Expand Down Expand Up @@ -690,6 +734,44 @@ def as_rotation(self) -> Rot: # pragma: no cover
"""
return Rot.from_matrix(self.orientation.values)

def as_homogeneous_matrix(self, translation_unit: UnitLike) -> np.ndarray:
"""Get a homogeneous transformation matrix from the coordinate system
orientation.
Parameters
----------
translation_unit : UnitLike
Unit the translation part of the homogeneous transformation matrix
should represent.
Returns
-------
numpy.ndarray
Numpy array representing the homogeneous transformation matrix.
"""

if self.is_time_dependent:
time_dim = self.time.shape[0]
else:
time_dim = 1

rotation = np.resize(self.orientation.data, (time_dim, 3, 3))
coordinates = self.coordinates
if not isinstance(coordinates, TimeSeries):
translation = np.resize(
coordinates.data.to(translation_unit).m, (time_dim, 3)
)
homogeneous_matrix = np.resize(np.identity(4), (time_dim, 4, 4))
homogeneous_matrix[:, :3, :3] = rotation
homogeneous_matrix[:, :3, 3] = translation

return np.squeeze(homogeneous_matrix)
else:
raise NotImplementedError(
"Cannot convert LCS with `TimeSeries` coordinates to homogeneous matrix"
)

def _interp_time_orientation(self, time: Time) -> xr.DataArray:
"""Interpolate the orientation in time."""
if "time" not in self.orientation.dims: # don't interpolate static
Expand Down
3 changes: 3 additions & 0 deletions weldx/transformations/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

from typing import Union

import numpy as np
import numpy.typing as npt
import pint
import xarray as xr
from scipy.spatial.transform import Rotation

types_coordinates = Union[xr.DataArray, npt.ArrayLike, pint.Quantity]
types_orientation = Union[xr.DataArray, npt.ArrayLike, Rotation]
types_homogeneous = Union[xr.DataArray, np.ndarray]


__all__ = [
"types_coordinates",
"types_orientation",
"types_homogeneous",
]

0 comments on commit 43d1b7d

Please sign in to comment.