Module pyastrobee.trajectories.simple_trajectories
Simple examples of position/orientation trajectories
View Source
"""Simple examples of position/orientation trajectories"""
import numpy as np
import numpy.typing as npt
from pyastrobee.utils.quaternions import (
quaternion_slerp,
get_closest_heading_quat,
quaternion_dist,
)
from pyastrobee.utils.math_utils import normalize
def point_and_move_pose_traj(
start_pose: npt.ArrayLike,
end_pose: npt.ArrayLike,
pos_step: float,
orn_step: float,
) -> np.ndarray:
"""Simple pose-only trajectory where the robot points at the goal, moves along a straight line,
then aligns with the goal
Args:
start_pose (npt.ArrayLike): Starting position + xyzw quaternion pose, shape (7,)
end_pose (npt.ArrayLike): Ending position + xyzw quaternion pose, shape (7,)
pos_step (float): Position stepsize (meters)
orn_step (float): Orientation stepsize (quaternion distance)
Returns:
np.ndarray: Trajectory, shape (n1 + n2 + n3, 7)
"""
# Interpolate the orientation, interpolate the position, interpolate the orientation
start_position = start_pose[:3]
start_quat = start_pose[3:]
end_position = end_pose[:3]
end_quat = end_pose[3:]
# Trajectory part 1: Maintain same pose, turn to point towards the final position
# First, need to find the quaternion to point in the right direction
heading = normalize(end_position - start_position)
heading_quat = get_closest_heading_quat(start_quat, heading)
# Also determine the discretization based on this intermediate orientation
n1 = int(np.ceil(quaternion_dist(start_quat, heading_quat) / orn_step))
traj_1 = fixed_pos_pose_traj(start_position, start_quat, heading_quat, n1)
# Trajectory part 2: Maintain the same orientation, move to final position
n2 = int(np.ceil(np.linalg.norm(end_position - start_position) / pos_step))
traj_2 = fixed_orn_pose_traj(start_position, end_position, heading_quat, n2)
# Trajectory part 3: Maintain the same final position, turn to goal orientation
n3 = int(np.ceil(quaternion_dist(heading_quat, end_quat) / orn_step))
traj_3 = fixed_pos_pose_traj(end_position, heading_quat, end_quat, n3)
# Merge the trajectory components together
return np.vstack((traj_1, traj_2, traj_3))
def fixed_orn_pose_traj(
pos_1: npt.ArrayLike, pos_2: npt.ArrayLike, quat: npt.ArrayLike, n: int
) -> np.ndarray:
"""Simple pose-only trajectory interpolated between two positions with a fixed orientation
Args:
pos_1 (npt.ArrayLike): Starting XYZ position, shape (3,)
pos_2 (npt.ArrayLike): Ending XYZ position, shape (3,)
quat (npt.ArrayLike): Fixed orientation (XYZW quaternion), shape (4,)
n (int): Number of timesteps
Returns:
np.ndarray: Trajectory, shape (n, 7)
"""
positions = np.linspace(pos_1, pos_2, n)
quats = quat * np.ones((n, 4))
return np.hstack((positions, quats))
def fixed_pos_pose_traj(
pos: npt.ArrayLike, q1: npt.ArrayLike, q2: npt.ArrayLike, n: int
) -> np.ndarray:
"""Simple pose-only trajectory interpolated between two orientations with a fixed position
Args:
pos (npt.ArrayLike): Fixed XYZ position, shape (3,)
q1 (npt.ArrayLike): Starting orientation (XYZW quaternion), shape (4,)
q2 (npt.ArrayLike): Ending orientation (XYZW quaternion), shape (4,)
n (int): Number of timesteps
Returns:
np.ndarray: Trajectory, shape (n, 7)
"""
positions = pos * np.ones((n, 3))
quats = quaternion_slerp(q1, q2, np.linspace(0, 1, n))
return np.hstack((positions, quats))
def interpolation_pose_traj(
start_pose: npt.ArrayLike, end_pose: npt.ArrayLike, n: int
) -> np.ndarray:
"""Simple pose-only trajectory, interpolates between two poses across n timesteps
Args:
start_pose (npt.ArrayLike): Starting position + xyzw quaternion pose, shape (7,)
end_pose (npt.ArrayLike): Ending position + xyzw quaternion pose, shape (7,)
n (int): Number of timesteps
Returns:
np.ndarray: Trajectory, shape (n, 7)
"""
start_position = start_pose[:3]
start_quat = start_pose[3:]
end_position = end_pose[:3]
end_quat = end_pose[3:]
positions = np.linspace(start_position, end_position, n)
quats = quaternion_slerp(start_quat, end_quat, np.linspace(0, 1, n))
return np.hstack((positions, quats))
Functions
fixed_orn_pose_traj
def fixed_orn_pose_traj(
pos_1: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
pos_2: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
quat: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
n: int
) -> numpy.ndarray
Simple pose-only trajectory interpolated between two positions with a fixed orientation
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
| pos_1 | npt.ArrayLike | Starting XYZ position, shape (3,) | None |
| pos_2 | npt.ArrayLike | Ending XYZ position, shape (3,) | None |
| quat | npt.ArrayLike | Fixed orientation (XYZW quaternion), shape (4,) | None |
| n | int | Number of timesteps | None |
Returns:
| Type | Description |
|---|---|
| np.ndarray | Trajectory, shape (n, 7) |
View Source
def fixed_orn_pose_traj(
pos_1: npt.ArrayLike, pos_2: npt.ArrayLike, quat: npt.ArrayLike, n: int
) -> np.ndarray:
"""Simple pose-only trajectory interpolated between two positions with a fixed orientation
Args:
pos_1 (npt.ArrayLike): Starting XYZ position, shape (3,)
pos_2 (npt.ArrayLike): Ending XYZ position, shape (3,)
quat (npt.ArrayLike): Fixed orientation (XYZW quaternion), shape (4,)
n (int): Number of timesteps
Returns:
np.ndarray: Trajectory, shape (n, 7)
"""
positions = np.linspace(pos_1, pos_2, n)
quats = quat * np.ones((n, 4))
return np.hstack((positions, quats))
fixed_pos_pose_traj
def fixed_pos_pose_traj(
pos: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
q1: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
q2: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
n: int
) -> numpy.ndarray
Simple pose-only trajectory interpolated between two orientations with a fixed position
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
| pos | npt.ArrayLike | Fixed XYZ position, shape (3,) | None |
| q1 | npt.ArrayLike | Starting orientation (XYZW quaternion), shape (4,) | None |
| q2 | npt.ArrayLike | Ending orientation (XYZW quaternion), shape (4,) | None |
| n | int | Number of timesteps | None |
Returns:
| Type | Description |
|---|---|
| np.ndarray | Trajectory, shape (n, 7) |
View Source
def fixed_pos_pose_traj(
pos: npt.ArrayLike, q1: npt.ArrayLike, q2: npt.ArrayLike, n: int
) -> np.ndarray:
"""Simple pose-only trajectory interpolated between two orientations with a fixed position
Args:
pos (npt.ArrayLike): Fixed XYZ position, shape (3,)
q1 (npt.ArrayLike): Starting orientation (XYZW quaternion), shape (4,)
q2 (npt.ArrayLike): Ending orientation (XYZW quaternion), shape (4,)
n (int): Number of timesteps
Returns:
np.ndarray: Trajectory, shape (n, 7)
"""
positions = pos * np.ones((n, 3))
quats = quaternion_slerp(q1, q2, np.linspace(0, 1, n))
return np.hstack((positions, quats))
interpolation_pose_traj
def interpolation_pose_traj(
start_pose: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
end_pose: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
n: int
) -> numpy.ndarray
Simple pose-only trajectory, interpolates between two poses across n timesteps
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
| start_pose | npt.ArrayLike | Starting position + xyzw quaternion pose, shape (7,) | None |
| end_pose | npt.ArrayLike | Ending position + xyzw quaternion pose, shape (7,) | None |
| n | int | Number of timesteps | None |
Returns:
| Type | Description |
|---|---|
| np.ndarray | Trajectory, shape (n, 7) |
View Source
def interpolation_pose_traj(
start_pose: npt.ArrayLike, end_pose: npt.ArrayLike, n: int
) -> np.ndarray:
"""Simple pose-only trajectory, interpolates between two poses across n timesteps
Args:
start_pose (npt.ArrayLike): Starting position + xyzw quaternion pose, shape (7,)
end_pose (npt.ArrayLike): Ending position + xyzw quaternion pose, shape (7,)
n (int): Number of timesteps
Returns:
np.ndarray: Trajectory, shape (n, 7)
"""
start_position = start_pose[:3]
start_quat = start_pose[3:]
end_position = end_pose[:3]
end_quat = end_pose[3:]
positions = np.linspace(start_position, end_position, n)
quats = quaternion_slerp(start_quat, end_quat, np.linspace(0, 1, n))
return np.hstack((positions, quats))
point_and_move_pose_traj
def point_and_move_pose_traj(
start_pose: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
end_pose: Union[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[Union[bool, int, float, complex, str, bytes]]],
pos_step: float,
orn_step: float
) -> numpy.ndarray
Simple pose-only trajectory where the robot points at the goal, moves along a straight line,
then aligns with the goal
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
| start_pose | npt.ArrayLike | Starting position + xyzw quaternion pose, shape (7,) | None |
| end_pose | npt.ArrayLike | Ending position + xyzw quaternion pose, shape (7,) | None |
| pos_step | float | Position stepsize (meters) | None |
| orn_step | float | Orientation stepsize (quaternion distance) | None |
Returns:
| Type | Description |
|---|---|
| np.ndarray | Trajectory, shape (n1 + n2 + n3, 7) |
View Source
def point_and_move_pose_traj(
start_pose: npt.ArrayLike,
end_pose: npt.ArrayLike,
pos_step: float,
orn_step: float,
) -> np.ndarray:
"""Simple pose-only trajectory where the robot points at the goal, moves along a straight line,
then aligns with the goal
Args:
start_pose (npt.ArrayLike): Starting position + xyzw quaternion pose, shape (7,)
end_pose (npt.ArrayLike): Ending position + xyzw quaternion pose, shape (7,)
pos_step (float): Position stepsize (meters)
orn_step (float): Orientation stepsize (quaternion distance)
Returns:
np.ndarray: Trajectory, shape (n1 + n2 + n3, 7)
"""
# Interpolate the orientation, interpolate the position, interpolate the orientation
start_position = start_pose[:3]
start_quat = start_pose[3:]
end_position = end_pose[:3]
end_quat = end_pose[3:]
# Trajectory part 1: Maintain same pose, turn to point towards the final position
# First, need to find the quaternion to point in the right direction
heading = normalize(end_position - start_position)
heading_quat = get_closest_heading_quat(start_quat, heading)
# Also determine the discretization based on this intermediate orientation
n1 = int(np.ceil(quaternion_dist(start_quat, heading_quat) / orn_step))
traj_1 = fixed_pos_pose_traj(start_position, start_quat, heading_quat, n1)
# Trajectory part 2: Maintain the same orientation, move to final position
n2 = int(np.ceil(np.linalg.norm(end_position - start_position) / pos_step))
traj_2 = fixed_orn_pose_traj(start_position, end_position, heading_quat, n2)
# Trajectory part 3: Maintain the same final position, turn to goal orientation
n3 = int(np.ceil(quaternion_dist(heading_quat, end_quat) / orn_step))
traj_3 = fixed_pos_pose_traj(end_position, heading_quat, end_quat, n3)
# Merge the trajectory components together
return np.vstack((traj_1, traj_2, traj_3))