PinnZoo.jl Documentation

Conventions

  • Quaternions use [$q_w$ $q_x$ $q_y$ $q_z$] order and represent body to world rotations, using Hamilton's convention $i^2 = j^2 = k^2 = -1$
  • Floating base joints use [$x$ $y$ $z$ $q_w$ $q_x$ $q_y$ $q_z$]$ order where the position is in the world frame
  • Linear and angular velocities corresponding to a floating base joint are in the body frame

Inputs/Variables

  • nq $\rightarrow$ # of configuration variables (1 per revolute/prismatic joint, 7 for floating joint)
  • nv $\rightarrow$ # of velocity variables. Also the number of degrees of freedom (1 per revolute/prismatic joint, 6 for floating joint)
  • nx $\rightarrow$ # of states, nq + nv
  • nc $\rightarrow$ # of points on the robot that kinematics were generated for
  • q $\rightarrow$ configuration vector, size nq.
  • x $\rightarrow$ state vector, size nx. The first nq elements are the configuration and the last nv elements are velocity.
  • x_dot $\rightarrow$ state vector derivative, size nx. The first nq elements are the derivative of the configuration with respect to time, and the last nv are the acceleration (derivative of velocity).
  • tau $\rightarrow$ generalized force vector, size nv. Represents forces/torques at each degree of freedom.

For the dynamics, we assume the following manipulator equation and velocity kinematics:

\[M(x)\dot{v} + C(x) = \tau\]

\[\dot{q} = E(q)v\]

Velocity Kinematics

E(q) is typically the identity except in the following cases (not an exhaustive list):

When the configuration includes a quaternion, E(q) includes the mapping from angular velocity into a quaternion time derivative, respecting $\dot{q}q = 0$, the unit norm constraint at the velocity level. Because angular velocities are related to axis-angles, there is a factor of 2 that shows up, so the mapping back from $v$ to $\dot{q}$ which we refer to as $E\_T$ is not equal to $E^T$.

When the translation velocity of a floating is in the body frame, but the position is in the world frame, so E(q) includes a body-to-world rotation matrix.

Index

Order Conversion Functions

The functions below can be used as helpers to convert between different vector orders to help interfacing with different dynamics packages. For example, to use a configuration vector from this package in mujoco, you can do

q_mujoco = change_order(model, q_pinnzo, :nominal, :mujoco)
PinnZoo.StateOrderType
StateOrder(config_names, vel_names, torque_names = vel_names)

Struct containing the orders of the configuration, velocity and torque vectors. Can be used to help convert between different vector orderings

source
PinnZoo.ConversionIndicesType
ConversionIndices

Holds index vectors mapping model vectors from one form to another, for config, velocity, state, error_state, and torques.

source
PinnZoo.change_order!Function
change_order!(model::PinnZooModel, input::AbstractVector, from::Symbol, to::Symbol)

Gets the relevant ConversionIndices from model.conversions[(from, to)] and converts the input vector order in-place, deducing which conversion to apply (config, velocity, state, error_state, or torque) based on the input vector size.

source
change_order!(model::PinnZooModel, input::AbstractVector, from::Symbol, to::Symbol; dims= (1, 2))

Gets the relevant ConversionIndices from model.conversions[(from, to)] and converts the input matrix order in-place, deducing which conversion to apply (config, velocity, state, error_state, or torque) based on the input matrix rows and columns. Default is to transform both input and output, but the dimensions can be specified using the dims option.

source
change_order!(model::PinnZooModel, input::Adjoint, from::Symbol, to::Symbol)

Gets the relevant ConversionIndices from model.conversions[(from, to)] and converts the input vector order in-place, deducing which conversion to apply (config, velocity, state, error_state, or torque) based on the input vector size.

source
PinnZoo.change_orderFunction
change_order(model::PinnZooModel, input::AbstractVector, from, to)

Gets the relevant ConversionIndices from model.conversions[(from, to)] and converts the input vector order, deducing which conversion to apply (config, velocity, state, error_state, or torque) based on the input vector size.

source
change_order(model::PinnZooModel, input::AbstractMatrix, from::Symbol, to::Symbol)

Gets the relevant ConversionIndices from model.conversions[(from, to)] and converts the input matrix order in-place, deducing which conversion to apply (config, velocity, state, error_state, or torque) based on the input matrix rows and columns. Default is to transform both input and output, but the dimensions can be specified using the dims option.

source
change_order!(model::PinnZooModel, input::Adjoint, from::Symbol, to::Symbol)

Gets the relevant ConversionIndices from model.conversions[(from, to)] and converts the input vector order, deducing which conversion to apply (config, velocity, state, error_state, or torque) based on the input vector size.

source
PinnZoo.change_orders!Function
change_orders!(model::PinnZooModel, inputs::Vector{<:AbstractArray}, from, to; dims = (1, 2))

Changes ordering in-place according to the appropriate convention for each object in inputs

source
PinnZoo.change_ordersFunction
change_orders!(model::PinnZooModel, inputs::Vector{<:AbstractArray}, from, to; dims = (1, 2))

Changes ordering according to the appropriate convention for each object in inputs

source
PinnZoo.generate_conversionsFunction
generate_conversions(orders::Dict{Symbol, StateOrder}, 
        conversions::Dict{Tuple{Symbol, Symbol}, ConversionIndices}=Dict{Tuple{Symbol, Symbol}, ConversionIndices}();
        from_scratch = false)

Given the vector orders specified, creates ConversionIndices objects that can be used with change_orders to convert between each order in orders (i.e. nominal, Pinocchio, MuJoCo)

source

Dynamics Functions

PinnZoo.M_funcFunction
M_func(model::PinnZooModel, x::AbstractVector{Float64})

Return the mass matrix of the model as a function of the configuration (x[1:model.nq])

source
PinnZoo.C_funcFunction
C_func(model::PinnZooModel, x::AbstractVector{Float64})

Return the dynamics bias of the model (coriolos + centrifugal + gravitational forces)

source
PinnZoo.dynamicsFunction
dynamics(model::PinnZooModel, x::AbstractVector{Float64}, τ::AbstractVector{Float64})

Returns dynamics [v; v̇] where v̇ = M(x) \ (τ - C) where M is the mass matrix and C is the dynamics bias vector.

source
PinnZoo.dynamics_derivFunction
dynamics_deriv(model::PinnZooModel, x::AbstractVector{Float64}, τ::AbstractVector{Float64})

Return a tuple of derivatives of the dynamics (ẋ) with respect to x and τ

source
PinnZoo.forward_dynamicsFunction
forward_dynamics(model::PinnZooModel, x::AbstractVector{Float64}, τ::AbstractVector{Float64})

Return the forward dynamics v̇ = M(x) \ (τ - C) where M is the mass matrix and C is the dynamics bias vector.

source
PinnZoo.forward_dynamics_derivFunction
forward_dynamics_deriv(model::PinnZooModel, x::AbstractVector{Float64}, τ::AbstractVector{Float64})

Return a tuple of derivatives of the forward dynamics (v̇) with respect to x and τ

source
PinnZoo.inverse_dynamicsFunction
inverse_dynamics(model::PinnZooModel, x::AbstractVector{Float64}, v̇::AbstractVector{Float64})

Return the inverse dynamics τ = M⩒ + C where M is the mass matrix and C is the dynamics bias vector

source
PinnZoo.inverse_dynamics_derivFunction
inverse_dynamics_deriv(model::PinnZooModel, x::AbstractVector{Float64}, v̇::AbstractVector{Float64}

Return a tuple of derivatives of the inverse dynamics (τ) with respect to x and v̇

source
PinnZoo.velocity_kinematicsFunction
velocity_kinematics(model::PinnZooModel, x::AbstractVector{Float64})

Return the matrix E mapping v to q̇, i.e. q̇ = E(q)v, where q = x[1:model.nq]. This mapping is exact, i.e. ET*E = I where ET comes from velocitykinematicsT. For an explanation for why Eᵀ != E_T refer to TODO

source
PinnZoo.velocity_kinematics_TFunction
velocity_kinematics_T(model::PinnZooModel, x::AbstractVector{Float64})

Return the matrix ET projecting q̇ onto v, i.e. v = ET(q)q̇, where q = x[1:model.nq]. This respects the tangent space structure. For a further explanation, as well as details on why E_T != Eᵀ refer to TODO

source
PinnZoo.velocity_kinematics_jvp_derivFunction
velocity_kinematics_jvp_deriv(model::PinnZooModel, x::AbstractVector{Float64}, v::AbstractVector{Float64})

Derivative of the jacobian vector product E(x)v with respect to x

source
PinnZoo.velocity_kinematics_T_jvp_derivFunction
velocity_kinematics_T_jvp_deriv(model::PinnZooModel, x::AbstractVector{Float64}, q::AbstractVector{Float64})

Derivative of the jacobian vector product E_T(x)q with respect to x

source
PinnZoo.state_errorFunction
state_error(model::PinnZooFloatingBaseModel, x, x0)

Return the state_error between x and x0, using axis-angles for quaternion error, and representing body position error in the body frame (matches with body velocity convention).

Here we use q0'q for the quaternion error because we defined the attitude jacobian as f(q0Δq) (delta on the left), so q0Δq = q => Δq = q0'q

source
PinnZoo.apply_ΔxFunction
apply_Δx(model::PinnZooFloatingBaseModel, x_k, Δx)

Return Δx added to x while respecting the configuration space/tangent space relationship (i.e. do quaternion multiplication, rotate Δbody pos from body frame to world frame). Δx should be model.nv*2, x_k should be model.nx. Floating base rotation in Δx should be axis angle.

source
PinnZoo.error_jacobianFunction
error_jacobian(model::PinnZooFloatingBaseModel, x)

Return the jacobian mapping Δx to x where Δx is in the tangent space (look at stateerror for our choice of tangent space). This matches the derivative of applyΔx(model, x, Δx) around Δx = 0

source
PinnZoo.error_jacobian_TFunction
error_jacobian_T(model::PinnZooFloatingBaseModel, x)

Return the jacobian mapping x to Δx where Δx is in the tangent space (look at stateerror for our choice of tangent space). This matches the derivative of stateerror(model, _x, x) around _x = x (error = 0)

source

Kinematics Functions

PinnZoo.kinematicsFunction
kinematics(model::PinnZooModel, x::AbstractVector{Float64})

Return a list of the locations of each body in model.kinematics_bodies in the world frame.

source
PinnZoo.kinematics_jacobianFunction
kinematics_jacobian(model::PinnZooModel, x::AbstractVector{Float64})

Return the jacobian of the kinematics function with respect to x (not projected into the tangent space).

source
PinnZoo.kinematics_velocityFunction
kinematics_velocity(model::PinnZooModel, x::AbstractVector{Float64})

Return a list of the instantaneous linear velocities of each body in model.kinematics_bodies in the world frame.

source
PinnZoo.kinematics_velocity_jacobianFunction
kinematics_velocity_jacobian(model::PinnZooModel, x::AbstractVector{Float64})

Return the jacobian of the kinematics_velocity function with respect to x (not in the tangent space). If $J_q$ is the derivative of the kinematics with respect to $q$, this jacobian $J$ = [$\dot{J_q}$ $J_q$] where $\dot{J_q} = \frac{\partial}{\partial q} J_qv$ and $J_qv$ is equal to kinematics_velocity. This also means that $J\dot{x}$ expresses the constraint at the acceleration level, i.e. $\dot{J_q}\dot{q} + J_q\dot{v} = 0$

source
PinnZoo.kinematics_force_jacobianFunction
kinematics_force_jacobian(model::PinnZooModel, x::AbstractVector{Float64}, λ::AbstractVector{Float64})

Return the jacobian (nv x nx matrix) of (J(x))'*λ with respect to x, where J(x) maps joint velocities into kinematics velocities

source

Utility Functions

PinnZoo.is_floatingFunction
is_floating(model::PinnZooModel)

Return whether the model includes a floating base joint

source
PinnZoo.randn_stateFunction
randn_state(model::PinnZooModel)

Return a state vector where every coordinate is drawn from a normal distribution

source
PinnZoo.init_stateFunction
init_state(model::Go1)

Return state vector with the robot on the ground in the starting pose

source
init_state(model::Go2)

Return state vector with the robot on the ground in the starting pose

source
init_state(model::PinnZooModel)

Return a custom initial state for the model (like standing) if defined, otherwise returns all zeros

source

Quaternion functions

PinnZoo.skewFunction
skew(v)

Return a matrix M such that $v \times x = Mx$ where $\times$ denotes the cross product

source
PinnZoo.L_multFunction
L_mult(q)

Return a matrix representation of left quaternion multiplication, i.e. $q1 \cdot q2 = L(q1)q2$ where $\cdot$ is quaternion multiplication.

source
PinnZoo.R_multFunction
R_mult(q)

Return a matrix representation of right quaternion multiplication, i.e. $q1 \cdot q2 = R(q2)q1$ where $\cdot$ is quaternion multiplication.

source
PinnZoo.attitude_jacobianFunction
attitude_jacobian(q)

Return the attitude jacobian G define as $\dot{q} = 0.5G\omega$, mapping angular velocity into quaternion time derivative.

source
PinnZoo.quat_to_rotFunction
quat_to_rot(q)

Return a rotation matrix R that q represents, defined by $\hat{p}^+ = q\hat{p}q^\dagger$ where $\hat{p}$ turns $p$ into a quaternion with zero scalar part and $p$ as the vector part, and $^\dagger$ is the quaternion conjugate.

source

Quadruped functions

TODO: Generalize state error and related functions to all models

PinnZoo.B_funcFunction
B_func(quad::Quadruped)

Return the input jacobian mapping motor torques into joint torques

source
PinnZoo.fix_joint_limitsFunction
fix_joint_limits(model::Quadruped, x; supress_error = false)

Return x with joint angles wrapped to 2pi to fit within joint limits if possible. If not and supress_error is false, this will error. Otherwise, this will return a clamped version.

source
PinnZoo.nearest_ikFunction
nearest_ik(model::Quadruped, q, foot_locs; obey_limits = true)

Return the ik solution for the given foot_locs and body orientation in q that is closest to the current joint angles in q (defined by minimum norm per joint).

source

Models

Pendulum

PinnZoo.PendulumType
Pendulum() <: PinnZooModel

Return an inverted pendulum dynamics model. θ = 0 is up, m = 1, l = 1, point mass at tip. Rotation axis is the positive x-axis (positive is counter-clockwise, right hand rule).

source

Double Pendulum

PinnZoo.DoublePendulumType
DoublePendulum() <: PinnZooModel

Return an inverted double pendulum dynamics model. θ = 0 is up, m = 1, l = 1, point mass at tip for both poles. Rotation axis is the positive x-axis (positive is counter-clockwise, right hand rule).

source

Cartpole

PinnZoo.CartpoleType
Cartpole() <: PinnZooModel

Return a Cartpole dynamics model, cart moves along the y-axis, pole rotates around positive x-axis. cart m = 1, pole m = 1, l = 1 (mass concentrated at pole tip).

source

Double Cartpole

PinnZoo.DoubleCartpoleType
DoubleCartpole() <: PinnZooModel

Return a DoubleCartpole dynamics model, cart moves along the y-axis, poles rotates around positive x-axis. cart m = 1, pole m = 1, l = 1 (mass concentrated at pole tip for both poles).

source

RigidBody

PinnZoo.RigidBodyType
RigidBody() <: PinnZooFloatingBaseModel

Return a RigidBody dynamics model, with m = 1, I = Diag([1.0; 1.0; 1.0]).

source

Quadrotor

PinnZoo.QuadrotorType
Quadrotor() <: PinnZooFloatingBaseModel

Return a Quadrotor dynamics model, with m = 1, I = Diag([0.0046; 0.0046; 0.008])

source

Unitree Go1

PinnZoo.Go1Type
Go1(; μ = 0.3) <: Quadruped

Return the Unitree Go1 dynamics and kinematics model

source
PinnZoo.init_stateMethod
init_state(model::Go1)

Return state vector with the robot on the ground in the starting pose

source
PinnZoo.inverse_kinematicsMethod
inverse_kinematics(model::Go1, x, foot_locs)

Return 12 by 2 matrix containing the 2 possible joint angle solutions that put the feet at foot_locs given the body pose in x. Will be populated with NaN or Inf if solutions don't exist.

source

Unitree Go2

PinnZoo.Go2Type
Go2(; μ = 0.3) <: Quadruped

Return the Unitree Go2 dynamics and kinematics model

source
PinnZoo.init_stateMethod
init_state(model::Go2)

Return state vector with the robot on the ground in the starting pose

source
PinnZoo.inverse_kinematicsMethod
inverse_kinematics(model::Go2, x, foot_locs)

Return 12 by 2 matrix containing the 2 possible joint angle solutions that put the feet at foot_locs given the body pose in x. Will be populated with NaN or Inf if solutions don't exist.

source

IHMC Nadia

PinnZoo.NadiaType
Nadia(; simple = true, nc_per_foot = 1, μ = 1.0, kinematics_ori = :None)

Return a Nadia dynamics and kinematics model. Currently supports 1 or 4 contact points per foot, and only the simple knee (does not support simple = false). For 1 contact point you can also include foot orientation (kinematics_ori = :Quaterion or :AxisAngle).

source