Home › Forum › SOFA › Using SOFA › Rotating an object with an angular velocity and conserving collisions
Tagged: 64_bits, SOFA_1806, Windows_10
- This topic has 5 replies, 2 voices, and was last updated 5 years, 5 months ago by
Hugo.
-
AuthorPosts
-
13 March 2019 at 16:51 #13204
chrissim
BlockedI wanted to rotate a object with angular velocity. I understand that I can apply a base rotation to a mechanical object at initialization but I want to model the movement of an object that can also rotate in a specified velocity.
I have found that using AffineMovementConstraint can rotate an object around a specific axis but this does fix the object nodes and limits the deformation of them. Meaning I can still see the collision of the rotating object with another object but the rotating object, which is fixed by AffineMovementConstraint will not be deformed.I don’t know if there is a method I might have missed which can be used to perform a rotation with a specific angular velocity and also conserve collisions and deformations of the rotating or if it is possible to implement this inside the MechanicalObject method.
I have attached a code excerpt of my attempt using AffineMovementConstraint but that does not yield any deformation results.
<?xml version="1.0" ?> <Node name="root" dt="0.01" gravity="0 0 0"> <VisualStyle displayFlags="showForceFields showCollisionModels showBehaviorModels" /> <CollisionPipeline /> <BruteForceDetection /> <DefaultContactManager /> <MinProximityIntersection alarmDistance="0.5" contactDistance="0.2" /> <DefaultCollisionGroupManager /> <Node name="Plane"> <EulerImplicitSolver name="EulerImplicit" rayleighStiffness="0.1" rayleighMass="0.1" /> <CGLinearSolver name="CG Solver" iterations="25" tolerance="1e-5" threshold="1e-5"/> <MechanicalObject template="Vec3d" name="mObject1" showObject="true" showObjectScale="3"/> <RegularGrid name ="loader" nx="5" ny="5" nz="1" xmin="0" xmax="1" ymin="0" ymax="1" zmin="0" zmax="1" position="@mObject1.position" drawHexahedra="true"/> <UniformMass template="Vec3d" totalMass="1"/> <MeshSpringForceField template="Vec3d" name="forcefield" linesStiffness="10" /> <BoxROI name="Box" box="-0.1 -0.1 0 1.1 1.1 0" drawBoxes="true"/> <PairBoxROI name="PairBox" inclusiveBox="-0.1 -0.1 0 1.1 1.1 0" includedBox="0.4 0.4 0 0.6 0.6 0"/> <SphereModel radius="0.1"/> <AffineMovementConstraint name="bilinearConstraint" template="Vec3d" indices="@Box.indices" meshIndices = "@PairBox.indices" rotation="[0.7 -0.7 0,0.7 0.7 0,0 0 1]" drawConstrainedPoints="1"/> </Node> <Node name="CubeSphere"> <EulerImplicitSolver name="EulerImplicit" rayleighStiffness="0.1" rayleighMass="0.1" /> <CGLinearSolver name="CG Solver" /> <MechanicalObject name="Particles" template="Vec3d" position="0 0 1 1 0 1 0 1 1 1 1 1 0 0 2 1 0 2 0 1 2 1 1 2" translation="-2 0 -1" /> <MeshTopology name="Topology" hexas="0 4 6 2 1 5 7 3" /> <UniformMass name="Mass" totalMass="1" /> <FixedConstraint fixAll="true"/> <MeshSpringForceField name="Springs" stiffness="100" damping="1" /> <SphereModel name="Spheres Cube" radius="0.4" /> </Node> </Node>
19 March 2019 at 19:28 #13226Hugo
KeymasterDear @chrissim
Thank you for your question and sorry to reply so late.
We are currently very busy, and we are unfortunately not as responsive as usual on the forum. I will have a look at your issue and get back to you.Cheers,
Hugo
19 March 2019 at 21:00 #13231chrissim
BlockedThanks for the reply Hugo
I started working on a method of creating a rotation using different rotation matrices and implementing it in a python script to utilize the animation time steps for an incremental rotation.
I can rotate an object around a specific angle as well as conserve collisions it causes in other objects. But since I am applying fixed constraints on the rotating object it is not possible for it to deform itself. I have to apply fixed constraint to the rotating object since otherwise the mesh will loose coherence and shoot away in space.
I was curious is there a way already implemented in SOFA to rotate an object and have it deform? In this case I would like the cylinder, which I am rotating to deform as well.
This is the rotation matrix I am using to rotate and object around a specific vector in space. This is done by creating a rotation matrix according to the vector that is input (compared to a unit vector) and the angle that the object should be rotated from its base. I have also included a transformation so as to move the rotation base to a specific point in space.
def createRotationMatrix(self, b, ab_angle): if (b[0] == 1 and b[1] == 0 and b[2] == 0): a_vec = np.array([0, 1, 0]) b_vec = np.array([b[2], b[1], b[0]]) else: a_vec = np.array([1, 0, 0]) b_vec = np.array([b[0], b[2], -b[1]]) cross = np.cross(a_vec, b_vec) vx = np.array([[0,-cross[2],cross[1]],[cross[2],0,-cross[0]],[-cross[1],cross[0],0]]) R = np.identity(3)*np.cos(ab_angle) + (1-np.cos(ab_angle))*np.outer(cross,cross) + np.sin(ab_angle)*vx rotMatrix = np.identity(4) rotMatrix[0:3,:-1] = R if self.transform is not None: rotMatrix = np.matmul(np.matmul(self.transform,rotMatrix), self.transform_inv) return rotMatrix
This is the animation of the object rotation I have implemented. I have setup the rotation to be performed over 500 steps and create an new rotation matrix for each new time step. This will ensure that the object that is rotating does not change in length but only gets rotated in a small angle. Through the variation of the amount of time steps the rotation speed can be adjusted and the object rotated faster or slower.
There is probably a more elegant way of doing a rotation, but this seems to perform the rotation without issue and keeps collisions with other objects intact.def onBeginAnimationStep(self, deltaTime): posX=[] posY=[] posZ=[] if (self.counter == 2): self.state += 1 steps = 500 b = np.array([1, 0, 0]) ab_angle = -math.pi/4 if (self.state <= steps): angle = self.state*(ab_angle)/steps rotMatrix = self.createRotationMatrix(b, angle) modelTransposed = np.transpose(self.modelPosition) size = modelTransposed.shape[1] modelTransposed = np.concatenate((modelTransposed, np.ones((1,size))), axis=0) modelRotated = np.matmul(rotMatrix,modelTransposed) modelRotated = np.transpose(modelRotated) print str(self.state) for i in range(size): posX.append(modelRotated[i][0]) posY.append(modelRotated[i][1]) posZ.append(modelRotated[i][2]) allPos = '' for i in range(size): allPos = allPos + str(posX[i]) + ' ' + str(posY[i]) + ' ' + str(posZ[i]) + ' ' self.model.getObject('mecha_model').findData('position').value = allPos self.counter = 0 else: self.counter += 1 return 0;
I have attached a dropbox link with the python file as well as the objects I am rotating and testing the collision with. If you have any recommendations of what could be changed to improve this rotation method I would be more than happy to try implementing that.
https://www.dropbox.com/sh/0mpjhdtaree9kel/AABnrI3i32gQaWsUzWy1AKXQa?dl=0
Chris
20 March 2019 at 18:46 #13236Hugo
KeymasterHi Chris,
I did this from your scene (rotation in x axis here but could be any rotation):
Is this what you want?
BestHugo
26 March 2019 at 23:20 #13271chrissim
BlockedHi Hugo
Yes this is definitely what I was looking for, in this case you are using the AffineMovementConstraint to perform the rotation around the x-axis?
But is it possible to rotate an object and have that object deform due to collision? Because the way I understood this method of rotating, it constrains the rotating object and will not permit deformation. Or is it not possible for the rotating object itself to undergo deformations?
Chris
29 March 2019 at 21:32 #13296Hugo
KeymasterHi @chrissim
Sorry for the delay.
Here were my files (one is *.scn the other is *.py) it should fit your needs.Scene (xml):
<?xml version="1.0" ?> <Node name="root" dt="0.01" gravity="0 0 0"> <VisualStyle displayFlags="showForceFields showCollisionModels showBehaviorModels" /> <RequiredPlugin name="SofaPython" pluginName="SofaPython" /> <CollisionPipeline /> <BruteForceDetection /> <DefaultContactManager /> <MinProximityIntersection alarmDistance="0.4" contactDistance="0.2" /> <DefaultCollisionGroupManager /> <Node name="ParticleControl" > <TransformEngine template="Rigid3d" name="engine" input_position="0 0 0 0 0 0 1" /> <EulerImplicitSolver name="EulerImplicit" rayleighStiffness="0.1" rayleighMass="0.1" /> <CGLinearSolver name="CG Solver" iterations="25" tolerance="1e-5" threshold="1e-5"/> <MechanicalObject template="Rigid3d" name="myRigidParticleForRotation" position="@engine.output_position" showObject="true" showObjectScale="0.1"/> <Node name="Plane"> <EulerImplicitSolver name="EulerImplicit" rayleighStiffness="0.1" rayleighMass="0.1" /> <CGLinearSolver name="CG Solver" iterations="25" tolerance="1e-5" threshold="1e-5"/> <RegularGrid name="loader" nx="5" ny="5" nz="1" xmin="0" xmax="1" ymin="0" ymax="1" zmin="0" zmax="1" position="@mObject1.position" drawHexahedra="true"/> <MechanicalObject template="Vec3d" name="mObject1" showObject="true" showObjectScale="3"/> <UniformMass template="Vec3d" totalMass="1"/> <MeshSpringForceField template="Vec3d" name="forcefield" linesStiffness="10" /> <BoxROI name="Box" box="-0.1 -0.1 0 1.1 1.1 0" drawBoxes="true"/> <PairBoxROI name="PairBox" inclusiveBox="-0.1 -0.1 0 1.1 1.1 0" includedBox="0.4 0.4 0 0.6 0.6 0"/> <SphereModel radius="0.1"/> <RigidMapping input="@.." output="@." /> <!-- <AffineMovementConstraint name="bilinearConstraint" template="Vec3d" indices="@Box.indices" meshIndices = "@PairBox.indices" rotation="[07 -07 7,0.7 0.7 0,0 0 1]" drawConstrainedPoints="1"/> --> </Node> </Node> <Node name="CubeSphere"> <EulerImplicitSolver name="EulerImplicit" rayleighStiffness="0.1" rayleighMass="0.1" /> <CGLinearSolver name="CG Solver" /> <MechanicalObject name="Particles" template="Vec3d" position="0 0 1 1 0 1 0 1 1 1 1 1 0 0 2 1 0 2 0 1 2 1 1 2" translation="-2 0 -1" /> <MeshTopology name="Topology" hexas="0 4 6 2 1 5 7 3" /> <UniformMass name="Mass" totalMass="1" /> <FixedConstraint fixAll="true"/> <MeshSpringForceField name="Springs" stiffness="100" damping="1" /> <SphereModel name="Spheres Cube" radius="0.4" /> </Node> <PythonScriptController name="angularVel" filename="angularVel.py" classname="rotate"/> </Node>
Associated python script:
import Sofa import sys class rotate(Sofa.PythonScriptController): # optionnally, script can create a graph... def initGraph(self,node): nodeParticle = node.getChild('ParticleControl') self.engine = nodeParticle.getObject('engine') return 0 def onBeginAnimationStep(self,dt): # adding at each time step a rotation angle in x (Euler angle) of 5 degree rotation = self.engine.findData('rotation').value rotation[0][0] = rotation[0][0] + 5 print rotation[0][0] self.engine.findData('rotation').value = rotation return 0
Let me know if it helps.
BestHugo
-
AuthorPosts
- You must be logged in to reply to this topic.