Source code for brom_drake.systems.end_effector_wrench_calculator

import numpy as np
from pydrake.multibody.tree import JacobianWrtVariable
from pydrake.systems.framework import LeafSystem, BasicVector


[docs] class EndEffectorWrenchCalculator(LeafSystem): """ **Description** A simple system which takes as input joint torques and outputs the corresponding wrench applied to the end-effector. **Diagram** The system can be illustrated with the following block: :: --------------------------------- | | | | | | joint_positions --> | EndEffectorWrenchCalculator | ---> end_effector_wrench joint_angles -----> | | joint_torques ----> | | | | | | --------------------------------- """ def __init__(self, plant, end_effector_frame): LeafSystem.__init__(self) self.plant = plant self.context = self.plant.CreateDefaultContext() self.ee_frame = end_effector_frame # Inputs are joint positions, angles and torques self.q_port = self.DeclareVectorInputPort( "joint_positions", BasicVector(plant.num_positions()) ) self.v_port = self.DeclareVectorInputPort( "joint_velocities", BasicVector(plant.num_velocities()) ) self.tau_port = self.DeclareVectorInputPort( "joint_torques", BasicVector(plant.num_actuators()) ) # Output is applied wrench at the end-effector self.DeclareVectorOutputPort( "end_effector_wrench", BasicVector(6), self.CalcEndEffectorWrench ) def CalcEndEffectorWrench(self, context, output): # Gather inputs q = self.q_port.Eval(context) v = self.v_port.Eval(context) tau = self.tau_port.Eval(context) # Set internal model state self.plant.SetPositions(self.context, q) self.plant.SetVelocities(self.context, v) # Some dynamics computations M = self.plant.CalcMassMatrixViaInverseDynamics(self.context) tau_g = -self.plant.CalcGravityGeneralizedForces(self.context) # Compute end-effector jacobian J = self.plant.CalcJacobianSpatialVelocity( self.context, JacobianWrtVariable.kV, self.ee_frame, np.zeros(3), self.plant.world_frame(), self.plant.world_frame(), ) # Compute jacobian pseudoinverse Minv = np.linalg.inv(M) Lambda = np.linalg.pinv(J @ Minv @ J.T) Jbar = Lambda @ J @ Minv # Compute wrench (spatial force) applied at end-effector w = Jbar @ (tau - tau_g) output.SetFromVector(w)