Trajectory Generation
Moro 0.5.0 provides numerical point-to-point trajectory generation in joint space and Cartesian position space.
The trajectory module is independent of Robot: it does not inspect robot geometry, joint types, joint limits, inverse kinematics, dynamics, collisions, or visualization state.
Path versus trajectory
A path describes geometry. A trajectory adds an explicit time parametrization:
Two trajectories may follow the same path with different timing.
Joint-space trajectories
Use:
import numpy as np
from moro.trajectory import joint_trajectory
t = np.linspace(0.0, 2.0, 101)
traj = joint_trajectory(
[0.0, 0.2, -0.4],
[0.8, -0.3, 0.5],
t,
method="quintic",
)
The result stores time-major arrays:
traj.t.shape == (N,)
traj.q.shape == (N, dof)
traj.qd.shape == (N, dof)
traj.qdd.shape == (N, dof)
Useful derived properties are:
traj.samples
traj.duration
traj.dof
For one degree of freedom, scalar endpoints are accepted:
traj = joint_trajectory(0.0, 1.0, t)
but the result still has shape (N, 1).
Cartesian position trajectories
Use:
from moro.trajectory import position_trajectory
cart = position_trajectory(
[0.0, 0.0, 0.0],
[1.0, 0.5, 0.0],
t,
)
Cartesian outputs always retain three components:
cart.p.shape == (N, 3)
cart.v.shape == (N, 3)
cart.a.shape == (N, 3)
Two-component planar inputs are intentionally not promoted to three dimensions.
Interpolation methods
The supported methods are:
linear
cubic
quintic
The default is "quintic".
Linear
Linear interpolation constrains endpoint positions only:
Velocity is constant and acceleration is zero inside the interval. Explicit velocity or acceleration boundary conditions are rejected.
Cubic
Cubic interpolation constrains position and velocity at both endpoints.
If qd0/qdf or v0/vf are omitted, they default independently to zero.
Acceleration boundary conditions are not supported by the cubic method.
Quintic
Quintic interpolation constrains position, velocity, and acceleration at both endpoints.
Omitted velocity and acceleration boundary conditions default independently to zero, making quintic interpolation a convenient smooth point-to-point default.
Explicit time vector
The caller supplies the complete numerical time vector:
t = np.linspace(5.0, 7.0, 101)
The initial time does not need to be zero.
Nonuniform samples are also valid:
t = [0.0, 0.1, 0.4, 1.0]
Time values must be finite and strictly increasing.
Public velocities and accelerations are derivatives with respect to physical time, not normalized time.
Boundary conditions
For multi-DOF joint trajectories, derivative boundary vectors must match the joint dimension exactly.
Scalar broadcasting is intentionally not supported:
# Invalid for a 2-DOF trajectory
qd0 = 0.5
For 1-DOF trajectories, scalar derivative conditions are accepted.
Integration with inverse kinematics
Cartesian trajectory generation and inverse kinematics remain separate operations:
cart = position_trajectory(
p0,
pf,
t,
method="quintic",
)
ik = solve_position_trajectory(
robot,
cart.p,
q0=q_initial,
)
Current position IK consumes only cart.p; it does not use cart.v or cart.a.
Integration with visualization
RobotVisualizer accepts numerical joint vectors directly:
viz.plot([0.3, -0.2])
and numerical joint matrices:
traj = joint_trajectory(
[0.0, 0.0],
[0.6, -0.4],
t,
)
viz.animate(traj.q)
The visualizer maps columns to robot.qs order.
Animation timing still uses the backend’s interval-style controls. Passing traj.q does not imply that a nonuniform traj.t is reproduced exactly in time.
Scope
Moro 0.5.0 trajectory generation intentionally does not include waypoints, splines, trapezoidal profiles, S-curves, automatic time allocation, pose interpolation, collision-aware planning, or dynamic-feasibility planning.