0

I am trying to perform system identification on an object attached to a KUKA iiwa using Drake in Python. My goal is to do lumped parameter estimation using least squares, which involves decomposing the multibody equations using symbolic.DecomposeLumpedParameters.

The issue I am running into is that the resulting symbolic equation in the parameters I am trying to estimate roughly resemble the form I would expect, however they contain terms in the denominator that could be simplified. This prevents the entire equation from being simplified as a polynomial, and it returns hundreds of terms with small coefficients.

This is challenging to deal with computationally, and it also is inconsistent in the parameters that are found for the exact same system, given different inputs for the state and velocities.

The modified ManipulationStation I am using would be too large to put here, but the same problem occurs with a normal iiwa model in this example. Here I load up a 7-DOF iiwa as my plant, and try to estimate the parameters of the 7th link:

import numpy as np
import pydrake.symbolic as sym
from pydrake.all import (
    Parser, AddMultibodyPlantSceneGraph, SpatialInertia_, RotationalInertia_, DiagramBuilder,
    FindResourceOrThrow,
)

# Create the plant
builder = DiagramBuilder()
plant, scene_graph = AddMultibodyPlantSceneGraph(builder,
                                                 time_step=0)
Parser(plant, scene_graph).AddModelFromFile(
    FindResourceOrThrow("drake/manipulation/models/iiwa_description/sdf/iiwa14_no_collision.sdf"))
plant.WeldFrames(plant.world_frame(), plant.GetFrameByName("iiwa_link_0"))
plant.Finalize()
diagram = builder.Build()

context = plant.CreateDefaultContext()
sym_plant = plant.ToSymbolic()
sym_context = sym_plant.CreateDefaultContext()
sym_context.SetTimeStateAndParametersFrom(context)
sym_plant.FixInputPortsFrom(plant, context, sym_context)

state = sym_context.get_continuous_state()

# Random state/command inputs
# (Normally these are recorded from the robot executing a trajectory)
q = np.random.random(size=state.num_q())
v = np.random.random(size=state.num_v())
vd = np.random.random(size=state.num_v())
tau = np.random.random(size=state.num_q())  # Remove -1  for fully actuated system

# Parameters
I = sym.MakeVectorVariable(6, 'I')  # Inertia tensor/mass matrix
m = sym.Variable('m')  # mass
cx = sym.Variable('cx')  # center of mass
cy = sym.Variable('cy')
cz = sym.Variable('cz')

sym_plant.get_actuation_input_port().FixValue(sym_context, tau)
sym_plant.SetPositions(sym_context, q)
sym_plant.SetVelocities(sym_context, v)

obj = sym_plant.GetBodyByName('iiwa_link_7')
inertia = SpatialInertia_[sym.Expression].MakeFromCentralInertia(m, [cx, cy, cz],
                                                                 RotationalInertia_[sym.Expression](
                                                                     I[0], I[1], I[2], I[3], I[4], I[5]))
obj.SetSpatialInertiaInBodyFrame(sym_context, inertia)

derivatives = sym_context.Clone().get_mutable_continuous_state()
derivatives.SetFromVector(np.hstack((0 * v, vd)))
residual = sym_plant.CalcImplicitTimeDerivativesResidual(
    sym_context, derivatives)

W, alpha, w0 = sym.DecomposeLumpedParameters(residual[2:],
                                             [m, cx, cy, cz, I[0], I[1], I[2], I[3], I[4], I[5]])

return W, alpha, w0

The output I see when running this is too large to paste here, while some of the parameters are okay (i.e. m, m * cx, m * cy, m * cz), the lumped parameters involving the inertial parameters are very long and contain terms with m in the denominator.

Here is an example of a term that could be simplified: ((7.0279621408873449 * (I(5) * m) - 7.0279621408873449 * (pow(m, 2) * cy * cz)) / m)

Is there a reason this may be happening, or is there a way to avoid it? Thank you!

1 Answers1

0

I just checked the code (thanks for the reproduction). The m in the denominator is happening in the MakeFromCentralInertia step. If you add

display(Math(ToLatex(inertia.CopyToFullMatrix6(), 2)))

right after the inertia is created, you'll see it. I think we need a different way to construct that SpatialInertia.

My recommendation is to change to parameterizing the inertia with the UnitInertia instead of the RotationalInertia:

G = sym.MakeVectorVariable(6, 'G')  # Inertia tensor/mass matrix
m = sym.Variable('m')  # mass
cx = sym.Variable('cx')  # center of mass
cy = sym.Variable('cy')
cz = sym.Variable('cz')

sym_plant.get_actuation_input_port().FixValue(sym_context, tau)
sym_plant.SetPositions(sym_context, q)
sym_plant.SetVelocities(sym_context, v)

obj = sym_plant.GetBodyByName('iiwa_link_7')
inertia = SpatialInertia_[sym.Expression](
    m, [cx, cy, cz], UnitInertia_[sym.Expression](G[0], G[1], G[2], G[3],
                                                        G[4], G[5]))
display(Math(ToLatex(inertia.CopyToFullMatrix6(), 2)))

which results in symbolic inertia

Russ Tedrake
  • 4,703
  • 1
  • 7
  • 10
  • I see the same behavior when using the UnitInertia after decomposing the parameters. I've noticed is that the strange behavior does have to do with the mass term...if I only try to decompose w.r.t mass by using DecomposeLumpedParameters, the expressions are still unpredictable. However, if I only try to find CoM and the inertial tensor, the parameters are very simple and expected. – Andy Lambert May 05 '22 at 04:20
  • Using only the change I proposed, and using `display(Math(ToLatex(...)))` for W, alpha0, and w0 at the end of your notebook gives me a beautiful decomposition with no problems with m in the denominator. Is the problem you're still having with a different version of the notebook? perhaps with q,v,vdot as symbolic again? – Russ Tedrake May 05 '22 at 10:11
  • That is super helpful to know. I actually have never been able to get the latex display working in deepnote, so I was just looked at the equations when printed to the console. I would expect them to be the same but maybe they're representations are different? – Andy Lambert May 05 '22 at 15:12
  • Resolved, I was still using MakeFromCentralInertia instead of the SpatialInertia constructor – Andy Lambert May 05 '22 at 16:38