Dynamics
Moro models serial-manipulator dynamics with the standard rigid-body manipulator equation
The Robot class constructs the symbolic terms. The moro.dynamics module evaluates them numerically and integrates the resulting ordinary differential equation.
Generalized coordinates
For an \(n\)-DOF manipulator,
with generalized velocity and acceleration
The same notation applies to revolute and prismatic joints; only the physical units differ.
Kinetic energy
For link \(i\), with mass \(m_i\), center-of-mass linear velocity \(v_{C_i}\), angular velocity \(\omega_i\), orientation \(R_i^0\), and inertia tensor \(I_{C_i}^{i}\) expressed at the center of mass,
The total kinetic energy is
Using center-of-mass Jacobians,
which leads to
Moro constructs
Potential energy and gravity
With gravity vector \(g\) expressed in the base frame and center-of-mass position \(r_{C_i}\),
The total potential energy is
The generalized gravity vector is
Euler-Lagrange equations
Define the Lagrangian
For each generalized coordinate,
In Moro 0.5.0 these equations are returned by
robot.euler_lagrange_equations()
Coriolis matrix
Moro forms the velocity-dependent terms through Christoffel symbols of the first kind,
Then
Therefore the velocity-dependent generalized-force term is
Matrix dynamic model
Collecting inertia, Coriolis/centrifugal and gravity effects gives
In Moro 0.5.0 this symbolic matrix equation is returned by
robot.dynamic_model()
dynamic_model_matrix_form() remains temporarily as a deprecated alias.
Inverse dynamics
If \(q\), \(\dot q\) and \(\ddot q\) are prescribed, the required generalized force is
Numerically:
inverse_dynamics(robot, q, qd, qdd)
Forward dynamics
If \(q\), \(\dot q\) and \(\tau\) are known, forward dynamics solves
Thus
The equation above is mathematical notation. Numerically Moro uses a linear solve,
np.linalg.solve(M, rhs)
rather than explicitly forming \(M^{-1}\).
A singular mass matrix is treated as a dynamic-model failure; no pseudoinverse fallback is used.
State-space form for integration
Define
Then
This first-order system is the quantity integrated by scipy.integrate.solve_ivp in moro.dynamics.simulate().
Numerical model preparation
Moro does not derive a second, independent numerical dynamic model. Instead it reuses symbolic
applies fixed parameter substitutions, validates unresolved symbols and creates numerical callables with SymPy lambdify.
For simulation, these numerical callables are prepared once and reused inside the ODE right-hand side.
Applied generalized force
Simulation supports
a constant generalized-force vector, or a callable
tau(t, q, qd)
which permits time-dependent inputs and simple feedback laws without introducing a controller framework.
Acceleration reconstruction
The ODE solver returns sampled \(q(t)\) and \(\dot q(t)\). Moro reconstructs
at every returned sample by evaluating forward dynamics at the same \((t_k,q_k,\dot q_k)\) state.
It does not estimate acceleration by finite differences.
Energy in conservative motion
For a system with no applied generalized force, no dissipation and no contacts, the mechanical energy
is conserved analytically.
A numerical integrator such as RK45 may show small energy drift; conservation should therefore be interpreted within the requested numerical tolerances rather than as exact floating-point equality.
Physical scope
The 0.5.0 numerical model is unconstrained rigid-body joint dynamics. It does not include friction, contacts, impacts, actuator dynamics, torque saturation, joint-stop physics, closed-chain constraints or collision response.
Configured joint limits are therefore not automatically enforced during forward simulation.