|
2 | 2 |
|
3 | 3 | from abc import ABC, abstractmethod |
4 | 4 | from dataclasses import dataclass, field |
5 | | -from typing import List, Tuple, TYPE_CHECKING |
| 5 | +from typing import List, TYPE_CHECKING, Union |
6 | 6 |
|
7 | 7 | import numpy as np |
8 | 8 |
|
9 | 9 | from . import spatial_types as cas |
10 | 10 | from .degree_of_freedom import DegreeOfFreedom |
11 | 11 | from .prefixed_name import PrefixedName |
12 | | -from .spatial_types.derivatives import Derivatives, DerivativeMap |
| 12 | +from .spatial_types.derivatives import DerivativeMap |
13 | 13 | from .spatial_types.math import quaternion_from_rotation_matrix |
14 | 14 | from .types import NpMatrix4x4 |
15 | 15 | from .world_entity import Connection |
@@ -111,61 +111,13 @@ def passive_dofs(self) -> List[DegreeOfFreedom]: |
111 | 111 | return [] |
112 | 112 |
|
113 | 113 |
|
114 | | -@dataclass |
115 | | -class UnitVector: |
116 | | - """ |
117 | | - Represents a unit vector which is always of size 1. |
118 | | - """ |
119 | | - |
120 | | - x: float |
121 | | - y: float |
122 | | - z: float |
123 | | - |
124 | | - def __post_init__(self): |
125 | | - self.normalize() |
126 | | - |
127 | | - def normalize(self): |
128 | | - length = self.length |
129 | | - self.x /= length |
130 | | - self.y /= length |
131 | | - self.z /= length |
132 | | - |
133 | | - @property |
134 | | - def length(self): |
135 | | - return np.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) |
136 | | - |
137 | | - def __getitem__(self, item: int) -> float: |
138 | | - if item == 0: |
139 | | - return self.x |
140 | | - if item == 1: |
141 | | - return self.y |
142 | | - if item == 2: |
143 | | - return self.z |
144 | | - raise IndexError |
145 | | - |
146 | | - def as_tuple(self) -> Tuple[float, float, float]: |
147 | | - return self.x, self.y, self.z |
148 | | - |
149 | | - @classmethod |
150 | | - def X(cls): |
151 | | - return cls(1, 0, 0) |
152 | | - |
153 | | - @classmethod |
154 | | - def Y(cls): |
155 | | - return cls(0, 1, 0) |
156 | | - |
157 | | - @classmethod |
158 | | - def Z(cls): |
159 | | - return cls(0, 0, 1) |
160 | | - |
161 | | - |
162 | 114 | @dataclass |
163 | 115 | class PrismaticConnection(ActiveConnection, Has1DOFState): |
164 | 116 | """ |
165 | 117 | Allows the movement along an axis. |
166 | 118 | """ |
167 | 119 |
|
168 | | - axis: UnitVector = field(kw_only=True) |
| 120 | + axis: cas.Vector3 = field(kw_only=True) |
169 | 121 | """ |
170 | 122 | Connection moves along this axis, should be a unit vector. |
171 | 123 | The axis is defined relative to the local reference frame of the parent body. |
@@ -200,7 +152,7 @@ def __post_init__(self): |
200 | 152 | self._post_init_world_part() |
201 | 153 |
|
202 | 154 | motor_expression = self.dof.symbols.position * self.multiplier + self.offset |
203 | | - translation_axis = cas.Vector3(self.axis) * motor_expression |
| 155 | + translation_axis = cas.Vector3.from_iterable(self.axis) * motor_expression |
204 | 156 | parent_T_child = cas.TransformationMatrix.from_xyz_rpy(x=translation_axis[0], |
205 | 157 | y=translation_axis[1], |
206 | 158 | z=translation_axis[2]) |
@@ -230,7 +182,7 @@ class RevoluteConnection(ActiveConnection, Has1DOFState): |
230 | 182 | Allows rotation about an axis. |
231 | 183 | """ |
232 | 184 |
|
233 | | - axis: UnitVector = field(kw_only=True) |
| 185 | + axis: cas.Vector3 = field(kw_only=True) |
234 | 186 | """ |
235 | 187 | Connection rotates about this axis, should be a unit vector. |
236 | 188 | The axis is defined relative to the local reference frame of the parent body. |
@@ -265,9 +217,8 @@ def __post_init__(self): |
265 | 217 | self._post_init_world_part() |
266 | 218 |
|
267 | 219 | motor_expression = self.dof.symbols.position * self.multiplier + self.offset |
268 | | - rotation_axis = cas.Vector3(self.axis) |
269 | | - parent_R_child = cas.RotationMatrix.from_axis_angle(rotation_axis, motor_expression) |
270 | | - self.origin_expression = self.origin_expression.dot(cas.TransformationMatrix(parent_R_child)) |
| 220 | + parent_R_child = cas.RotationMatrix.from_axis_angle(self.axis, motor_expression) |
| 221 | + self.origin_expression = self.origin_expression @ cas.TransformationMatrix(parent_R_child) |
271 | 222 | self.origin_expression.reference_frame = self.parent |
272 | 223 | self.origin_expression.child_frame = self.child |
273 | 224 |
|
@@ -318,13 +269,13 @@ class Connection6DoF(PassiveConnection): |
318 | 269 | def __post_init__(self): |
319 | 270 | super().__post_init__() |
320 | 271 | self._post_init_world_part() |
321 | | - parent_P_child = cas.Point3((self.x.symbols.position, |
322 | | - self.y.symbols.position, |
323 | | - self.z.symbols.position)) |
324 | | - parent_R_child = cas.Quaternion((self.qx.symbols.position, |
325 | | - self.qy.symbols.position, |
326 | | - self.qz.symbols.position, |
327 | | - self.qw.symbols.position)).to_rotation_matrix() |
| 272 | + parent_P_child = cas.Point3(x=self.x.symbols.position, |
| 273 | + y=self.y.symbols.position, |
| 274 | + z=self.z.symbols.position) |
| 275 | + parent_R_child = cas.Quaternion(x=self.qx.symbols.position, |
| 276 | + y=self.qy.symbols.position, |
| 277 | + z=self.qz.symbols.position, |
| 278 | + w=self.qw.symbols.position).to_rotation_matrix() |
328 | 279 | self.origin_expression = cas.TransformationMatrix.from_point_rotation_matrix(point=parent_P_child, |
329 | 280 | rotation_matrix=parent_R_child, |
330 | 281 | reference_frame=self.parent, |
@@ -354,11 +305,13 @@ def passive_dofs(self) -> List[DegreeOfFreedom]: |
354 | 305 | return [self.x, self.y, self.z, self.qx, self.qy, self.qz, self.qw] |
355 | 306 |
|
356 | 307 | @property |
357 | | - def origin(self) -> NpMatrix4x4: |
| 308 | + def origin(self) -> cas.TransformationMatrix: |
358 | 309 | return super().origin |
359 | 310 |
|
360 | 311 | @origin.setter |
361 | | - def origin(self, transformation: NpMatrix4x4) -> None: |
| 312 | + def origin(self, transformation: Union[NpMatrix4x4, cas.TransformationMatrix]) -> None: |
| 313 | + if isinstance(transformation, cas.TransformationMatrix): |
| 314 | + transformation = transformation.to_np() |
362 | 315 | orientation = quaternion_from_rotation_matrix(transformation) |
363 | 316 | self._world.state[self.x.name].position = transformation[0, 3] |
364 | 317 | self._world.state[self.y.name].position = transformation[1, 3] |
|
0 commit comments