Partial rigidification of a deformable object #4139
AliceCatalano
started this conversation in
Ideas / Suggestions
Replies: 2 comments 11 replies
-
You should have a look on |
Beta Was this translation helpful? Give feedback.
11 replies
-
I finally had some time to build you a dedicated scene based on the rigidification example scene. Here is the case you are looking at, a cube with rigidified faces: # -*- coding: utf-8 -*-
"""
Templates to rigidify a deformable object.
The rigidification consist in mixing in a single object rigid and deformable parts.
The rigid and deformable parts are interacting together.
**Sofa Templates:**
.. autosummary::
Rigidify
stlib3.physics.mixedmaterial.Rigidify
*******************************
.. autofunction:: Rigidify
Contributors:
[email protected]
[email protected]
"""
import Sofa
from splib3.numerics import Vec3, Quat, sdiv
def getBarycenter(selectedPoints):
poscenter = [0., 0., 0.]
if len(selectedPoints) != 0:
poscenter = sdiv(sum(selectedPoints), float(len(selectedPoints)))
return poscenter
def Rigidify(targetObject, sourceObject, groupIndices, frames=None, name=None):
""" Transform a deformable object into a mixed one containing both rigid and deformable parts.
:param targetObject: parent node where to attach the final object.
:param sourceObject: node containing the deformable object. The object should be following
the ElasticMaterialObject template.
:param list groupIndices: array of array indices to rigidify. The length of the array should be equal to the number
of rigid component.
:param list frames: array of frames. The length of the array should be equal to the number
of rigid component. The orientation are given in eulerAngles (in degree) by passing
three values or using a quaternion by passing four values.
[[rx,ry,rz], [qx,qy,qz,w]]
User can also specify the position of the frame by passing six values (position and orientation in degree)
or seven values (position and quaternion).
[[x,y,z,rx,ry,rz], [x,y,z,qx,qy,qz,w]]
If the position is not specified, the position of the rigids will be the barycenter of the region to rigidify.
:param str name: specify the name of the Rigidified object, is none provided use the name of the SOurceObject.
"""
if frames is None:
frames = [[0., 0., 0.]]*len(groupIndices)
assert len(groupIndices) == len(frames), "size mismatch."
if name is None:
name = sourceObject.name
# sourceObject.reinit()
ero = targetObject.addChild(name)
allPositions = sourceObject.container.position.value
allIndices =list(range(len(allPositions)))
rigids = []
indicesMap = []
def mfilter(si, ai, pts):
tmp = []
for i in ai:
if i in si:
tmp.append(pts[i])
return tmp
# get all the points from the source.
selectedIndices = []
for i in range(len(groupIndices)):
selectedPoints = mfilter(groupIndices[i], allIndices, allPositions)
if len(frames[i]) == 3:
orientation = Quat.createFromEuler(frames[i], inDegree=True)
poscenter = getBarycenter(selectedPoints)
elif len(frames[i]) == 4:
orientation = frames[i]
poscenter = getBarycenter(selectedPoints)
elif len(frames[i]) == 6:
orientation = Quat.createFromEuler([frames[i][3], frames[i][4], frames[i][5]], inDegree=True)
poscenter = [frames[i][0], frames[i][1], frames[i][2]]
elif len(frames[i]) == 7:
orientation = [frames[i][3], frames[i][4], frames[i][5], frames[i][6]]
poscenter = [frames[i][0], frames[i][1], frames[i][2]]
else:
Sofa.msg_error("Do not understand the size of a frame.")
rigids.append(poscenter + list(orientation))
selectedIndices += map(lambda x: x, groupIndices[i])
indicesMap += [i] * len(groupIndices[i])
otherIndices = list(filter(lambda x: x not in selectedIndices, allIndices))
Kd = {v: None for k, v in enumerate(allIndices)}
Kd.update({v: [0, k] for k, v in enumerate(otherIndices)})
Kd.update({v: [1, k] for k, v in enumerate(selectedIndices)})
indexPairs = [v for kv in Kd.values() for v in kv]
freeParticules = ero.addChild("DeformableParts")
freeParticules.addObject("MechanicalObject", template="Vec3", name="dofs",
position=[allPositions[i] for i in otherIndices])
rigidParts = ero.addChild("RigidParts")
rigidParts.addObject("MechanicalObject", template="Rigid3", name="dofs", reserve=len(rigids), position=rigids)
rigidifiedParticules = rigidParts.addChild("RigidifiedParticules")
rigidifiedParticules.addObject("MechanicalObject", template="Vec3", name="dofs",
position=[allPositions[i] for i in selectedIndices])
rigidifiedParticules.addObject("RigidMapping", name="mapping", globalToLocalCoords=True, rigidIndexPerPoint=indicesMap)
if "solver" in sourceObject.objects:
sourceObject.removeObject(sourceObject.solver)
if "integration" in sourceObject.objects:
sourceObject.removeObject(sourceObject.integration)
if "correction" in sourceObject.objects:
sourceObject.removeObject(sourceObject.correction)
sourceObject.addObject("SubsetMultiMapping", name="mapping", template="Vec3,Vec3",
input=[freeParticules.dofs.getLinkPath(),rigidifiedParticules.dofs.getLinkPath()],
output=sourceObject.dofs.getLinkPath(),
indexPairs=indexPairs)
rigidifiedParticules.addChild(sourceObject)
freeParticules.addChild(sourceObject)
return ero
def createScene(rootNode):
"""
"""
from stlib3.scene import MainHeader
from stlib3.physics.deformable import ElasticMaterialObject
from splib3.objectmodel import setData
rootNode.addObject("DefaultAnimationLoop")
rootNode.addObject("VisualStyle")
rootNode.VisualStyle.displayFlags = "showBehavior"
rootNode.addObject("RegularGridTopology", name="grid", nx="8", ny="8", nz="8", xmin="-1", xmax="1", ymin="-1", ymax="1", zmin="-1", zmax="1", drawQuads=False)
plugins = rootNode.addChild("LoadedPlugins")
plugins.addObject('RequiredPlugin', name='Sofa.Component.Mass') # Needed to use components [UniformMass]
plugins.addObject('RequiredPlugin', name='Sofa.Component.SolidMechanics.FEM.Elastic') # Needed to use components [TetrahedronFEMForceField]
plugins.addObject('RequiredPlugin', name='Sofa.Component.StateContainer') # Needed to use components [MechanicalObject]
plugins.addObject('RequiredPlugin', name='Sofa.Component.Topology.Container.Dynamic') # Needed to use components [TetrahedronSetGeometryAlgorithms,TetrahedronSetTopologyContainer,TetrahedronSetTopologyModifier]
plugins.addObject('RequiredPlugin', name='Sofa.Component.Topology.Container.Grid') # Needed to use components [RegularGridTopology]
plugins.addObject('RequiredPlugin', name='Sofa.Component.Topology.Mapping') # Needed to use components [Hexa2TetraTopologicalMapping]
plugins.addObject('RequiredPlugin', name='Sofa.Component.Visual') # Needed to use components [VisualStyle]
plugins.addObject('RequiredPlugin', name='Sofa.Component.Constraint.Projective') # Needed to use components [FixedConstraint]
plugins.addObject('RequiredPlugin', name='Sofa.Component.LinearSolver.Iterative') # Needed to use components [CGLinearSolver]
plugins.addObject('RequiredPlugin', name='Sofa.Component.Mapping.Linear') # Needed to use components [SubsetMultiMapping]
plugins.addObject('RequiredPlugin', name='Sofa.Component.Mapping.NonLinear') # Needed to use components [RigidMapping]
plugins.addObject('RequiredPlugin', name='Sofa.Component.ODESolver.Backward') # Needed to use components [EulerImplicitSolver]
###########################################################
# Define the deformable object (cube)
tetraTopo = rootNode.addChild("TetrahedralTopology")
tetraTopo.addObject('TetrahedronSetTopologyContainer', position="@../grid.position",name='container')
tetraTopo.addObject('TetrahedronSetTopologyModifier', name='modifier')
tetraTopo.addObject('Hexa2TetraTopologicalMapping', name='mapping')
deformableCube = tetraTopo.addChild("DeformableCube")
deformableCube.addObject('EulerImplicitSolver', name='integration')
deformableCube.addObject('SparseLDLSolver', name="solver", template='CompressedRowSparseMatrixd')
deformableCube.addObject('TetrahedronSetTopologyContainer', src="@../container",name='container')
deformableCube.addObject('TetrahedronSetGeometryAlgorithms', template="Vec3d", name="GeomAlgo", drawTetrahedra=False, drawScaleTetrahedra=0.5)
deformableCube.addObject('MechanicalObject', template='Vec3', position="@../../grid.position",name='dofs', showObject=False, showObjectScale=10)
deformableCube.addObject('UniformMass', totalMass=1., name='mass')
deformableCube.addObject('TetrahedronFEMForceField', template='Vec3',
method='large', name='forcefield',
poissonRatio=0.4, youngModulus=5e3)
rootNode.init()
###########################################################
# Rigidification of the elasticobject for given indices with given frameOrientations.
o = Rigidify(tetraTopo,
deformableCube,
name="RigidifiedStructure",
frames=[[0, 0, 1], [1, 0, 0]], # HERE you define the rigid frames located in the middle of the faces
groupIndices=[[475,473,483,484], [223, 231,287,295]]) # HERE you define which are the DOFs of the deformable associated to each rigid frame
###########################################################
# Activate some rendering on the rigidified object.
setData(o.RigidParts.dofs, showObject=True, showObjectScale=1, drawMode=2)
setData(o.RigidParts.RigidifiedParticules.dofs, showObject=True, showObjectScale=0.1,
drawMode=1, showColor=[1., 1., 0., 1.])
setData(o.DeformableParts.dofs, showObject=True, showObjectScale=0.1, drawMode=2)
o.RigidParts.addObject("FixedConstraint", indices=0)
simulationNode = rootNode.addChild("Simulation")
simulationNode.addObject("EulerImplicitSolver")
simulationNode.addObject("CGLinearSolver", iterations=25, tolerance=1e-5, threshold=1e-5)
simulationNode.addChild(o)
return rootNode All you need to run this scene (with runSofa) is to have the |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
This discussion is created to have insights about the partial rigidification of a deformable ogject. With this I mean creating rigid ares in a mesh representing a deformable object. In my study case, for example, I have a deformable cube, on which I want to define 4 rigid planes, which orientation will be controlled by values coming from four IMUs.
The objective is to detect deformations with the IMU and seeing it represented in the simulation in the most realistic way possible. The deformations are imposed by simply pass as normal vector of the 4 rigid planes, the normal vector computed by the IMUs.
Untill now I succeded in the control part but not in the rigidification process and for this reason the simulation is not realistic at all. Deformations are happening even inside the constrained planes and the motion doesn't spread efficiently.
Beta Was this translation helpful? Give feedback.
All reactions