Source code for brom_drake.example_helpers.block_handler_system
from importlib import resources as impresources
from pydrake.math import RollPitchYaw, RigidTransform, RotationMatrix
from pydrake.multibody.math import SpatialVelocity
from pydrake.multibody.parsing import Parser
from pydrake.multibody.plant import MultibodyPlant, CoulombFriction
from pydrake.systems.framework import Diagram, DiagramBuilder, LeafSystem, PortDataType, BasicVector
import numpy as np
# Internal Imports
from brom_drake import example_helpers as eh
from brom_drake.utils import AddGround, AddMultibodyTriad
[docs]
class BlockHandlerSystem(LeafSystem):
def __init__(
self,
plant: MultibodyPlant,
scene_graph,
block_name: str = "block_with_slots",
model_urdf_path: str = None,
):
LeafSystem.__init__(self)
# Input Processing
if model_urdf_path is None:
model_urdf_path = str(
impresources.files(eh) / "models/slider-block.urdf",
)
# Constants
self.block_name = block_name
# Add the Block to the given plant
self.plant = plant
self.block_model_idx = Parser(plant=self.plant).AddModels(model_urdf_path)[0]
self.block_model_name = self.plant.GetModelInstanceName(self.block_model_idx)
self.block_body_name = "block"
AddGround(self.plant) #Add ground to plant
# Add the Triad
self.scene_graph = scene_graph
AddMultibodyTriad(plant.GetFrameByName(self.block_body_name), self.scene_graph)
self.plant.Finalize()
self.context = self.plant.CreateDefaultContext()
# Create Input Port for the Slider Block System
self.desired_pose_port = self.DeclareVectorInputPort(
"desired_pose",
BasicVector(6),
)
# Create Output Port which should share the pose of the block
self.DeclareVectorOutputPort(
"measured_block_pose",
BasicVector(6),
self.SetBlockPose,
{self.time_ticket()} # indicate that this doesn't depend on any inputs,
) # but should still be updated each timestep
[docs]
def SetBlockPose(self, context, output):
"""
Description:
This function sets the desired pose of the block.
"""
# Get Desired Pose from Port
plant_context = self.context
pose_as_vec = self.desired_pose_port.Eval(context)
self.plant.SetFreeBodyPose(
plant_context,
self.plant.GetBodyByName(self.block_body_name),
RigidTransform(RollPitchYaw(pose_as_vec[:3]),pose_as_vec[3:])
)
# self.plant.SetFreeBodySpatialVelocity(
# self.plant.GetBodyByName(self.block_body_name),
# SpatialVelocity(np.zeros(3),np.array([0.0,0.0,0.0])),
# plant_context
# )
X_WBlock = self.plant.GetFreeBodyPose(
plant_context,
self.plant.GetBodyByName(self.block_body_name)
)
pose_as_vector = np.hstack([RollPitchYaw(X_WBlock.rotation()).vector(), X_WBlock.translation()])
# Create Output
output.SetFromVector(pose_as_vector)
[docs]
def SetInitialBlockState(self,diagram_context):
"""
Description:
Sets the initial position to be slightly above the ground (small, positive z value)
to be .
"""
# Set Pose
p_WBlock = [0.0, 0.0, 0.2]
R_WBlock = RotationMatrix.MakeXRotation(np.pi/2.0) # RotationMatrix.MakeXRotation(-np.pi/2.0)
X_WBlock = RigidTransform(R_WBlock, p_WBlock)
self.plant.SetFreeBodyPose(
self.plant.GetMyContextFromRoot(diagram_context),
self.plant.GetBodyByName(self.block_body_name),
X_WBlock)
# Set Velocities
self.plant.SetFreeBodySpatialVelocity(
self.plant.GetBodyByName(self.block_body_name),
SpatialVelocity(np.zeros(3),np.array([0.0,0.0,0.0])),
self.plant.GetMyContextFromRoot(diagram_context))