|
10 | 10 | import copy
|
11 | 11 | import os
|
12 | 12 | import xml.etree.ElementTree as ETT
|
13 |
| -from spatialmath import SE3 |
14 |
| -from spatialmath.base import unitvec_norm, angvec2r, tr2rpy |
| 13 | +from spatialmath import SE3, SO3 |
| 14 | +from spatialmath.base import ArrayLike3, getvector, unitvec, unitvec_norm, angvec2r, tr2rpy |
15 | 15 |
|
16 | 16 | from io import BytesIO
|
17 | 17 | from roboticstoolbox.tools.data import rtb_path_to_datafile
|
|
23 | 23 | # Global variable for the base path of the robot meshes
|
24 | 24 | _base_path = None
|
25 | 25 |
|
| 26 | +def rotation_fromVec_toVec( |
| 27 | + from_this_vector: ArrayLike3, to_this_vector: ArrayLike3 |
| 28 | +) -> SO3: |
| 29 | + """ |
| 30 | + Computes the rotation matrix from the first to the second vector. |
| 31 | +
|
| 32 | + Attributes |
| 33 | + ---------- |
| 34 | + from_this_vector: ArrayLike3 |
| 35 | + to_this_vector: ArrayLike3 |
| 36 | +
|
| 37 | + Returns |
| 38 | + ------- |
| 39 | + rotation_from_to: SO3 |
| 40 | + Rotation matrix |
| 41 | +
|
| 42 | + Notes |
| 43 | + ----- |
| 44 | + Vector length is irrelevant. |
| 45 | + """ |
| 46 | + from_this_vector = getvector(from_this_vector) |
| 47 | + to_this_vector = getvector(to_this_vector) |
| 48 | + |
| 49 | + is_zero = np.all(np.isclose(from_this_vector, 0)) |
| 50 | + if is_zero: |
| 51 | + target_axis = to_this_vector |
| 52 | + else: |
| 53 | + target_axis = unitvec(from_this_vector) |
| 54 | + |
| 55 | + dt = np.dot(target_axis, to_this_vector) |
| 56 | + crss = np.cross(target_axis, to_this_vector) |
| 57 | + |
| 58 | + is_parallel = np.all(np.isclose(crss, 0)) |
| 59 | + if is_parallel: |
| 60 | + rotation_plane = unitvec( |
| 61 | + np.cross(target_axis, to_this_vector + np.array([1, 1, 1])) |
| 62 | + ) |
| 63 | + else: |
| 64 | + rotation_plane = unitvec(crss) |
| 65 | + |
| 66 | + x = dt |
| 67 | + y = np.linalg.norm(crss) |
| 68 | + rotation_angle = np.arctan2(y, x) |
| 69 | + |
| 70 | + rotation_from_to = SO3.AngVec(rotation_angle, rotation_plane) |
| 71 | + return rotation_from_to |
| 72 | + |
26 | 73 | def _find_standard_joint(joint: "Joint") -> "rtb.ET | None":
|
27 | 74 | """
|
28 | 75 | Finds a pure rtb.ET joint corresponding to the URDF joint axis.
|
|
0 commit comments