Rototraslation of a cylinder

Asked by Paolo on 2020-02-16

Hi!
I'd like do realize a counterclockwise rotating cylinder in order to spread some particles/spheres in a layer. The cylinder has to translate and rotate and so I included in the code both RotationEngine and TranslationEngine.

The problem is that during the roto-translation the pieces that constitute the cylinder rotate with respect to their centroids instead of the center of the cylinder. I saw on yade manual that it is possible to add the zeroPoint condition in the Rotatonal engine but the zeroPoint (which is the center of the cylinder) is moving due to the TranslationEngine and so not fixed.

Moreover I'd like to know if it is possible to make the cylinder restart from the initial position after some iter (i.e. the cylinder roto-translate for 10cm and then it disappear and reappear in the initial position like a cycle).

Thank you!

raggio=0.0004
rullo=O.bodies.append(geom.facetCylinder((-raggio,raggio,raggio),radius=raggio,height=0.0008,orientation=Quaternion((0,1,0),pi/2),wallMask=7,segmentsNumber=50))

O.engines=...

rotEngine = RotationEngine(ids=rullo,angularVelocity=10,rotationAxis=(1,0,0))
transEngine = TranslationEngine(ids=rullo,translationAxis=(0,1,0),velocity=vel)
O.engines = O.engines[:4]+[rotEngine+transEngine]+O.engines[4:]

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Jan Stránský
Solved:
2020-02-18
Last query:
2020-02-18
Last reply:
2020-02-18
Jan Stránský (honzik) said : #1

> but the zeroPoint (which is the center of the cylinder) is moving due to the TranslationEngine and so not fixed.

you have to set new position each iteration e.g. using PyRunner

> if it is possible to make the cylinder restart from the initial position after some iter

yes. You can:
- create a new at original position (and destroy the old one)
- set appropriate state.pos of the cylinder components to match the original position
- set for one iteration velocity and angular velocity such that the cylinder moves to its original position

cheers
Jan

Paolo (p4olo) said : #2

Hi Jan and thank you for your answer.

Just to clarify:

>you have to set new position each iteration e.g. using PyRunner

Have I to define a function that compute the next position of the center (es. transl_velocity*O.dt) which is called by the command of the pyrunner at iterPeriod=1?

>create a new at original position (and destroy the old one)

How can i destroy the old cylinder? And once i generate the new cylinder, do I have to update the translational and rotational engine in order to fit the new roller or can i simply name it as the previous one so that the engine works automaticalluy?

Thanks

Jan Stránský (honzik) said : #3

> Have I to define a function ...

exactly

> How can i destroy the old cylinder?

for i in rullo:
   O.bodies.erase(i) # [1]

> And once i generate the new cylinder, do I have to update the translational and rotational engine in order to fit the new roller or can i simply name it as the previous one so that the engine works automaticalluy?

you can name is the same, but you have to update rotEngine.ids and transEngine.ids
Depending on specific realization, you might also need to update the function computing new zeroPoint

cheers
Jan

[1] https://yade-dem.org/doc/yade.wrapper.html#yade.wrapper.BodyContainer.erase

Paolo (p4olo) said : #5

Hi!

I succeeded in doing the rototranslation of the roller pretty well also thanks to a code I found here [1] and the erasing too, but I have trouble in generating the second roller after the deleting of the previous one. Actually I was able to write a script which generates 2 rollers at the very start of the simulation which are overlapped. The simulation makes firstly the first roller move, erases it and then the second one strarts to move. However, I'd like to generate the second one after the deleting of the firt one because I think that the final simulation could be faster if I have one cylinder at a time. Here's a draft of the code.

rullo = geom.facetCylinder((0,0,0),radius=r,height=d,orientation=Quaternion((0,1,0),pi/2),wallMask=7,segmentsNumber=50,material=Mat1)
O.bodies.append(rullo)
idsr = [r1.id for r1 in rullo]

rullo1 = geom.facetCylinder((0,0,0),radius=r,height=d,orientation=Quaternion((0,1,0),pi/2),wallMask=7,segmentsNumber=50,material=Mat1)
O.bodies.append(rullo1)
idsr1 = [r2.id for r2 in rullo1]

O.engines=[
..........

  CombinedKinematicEngine(ids=idsr,label='combEngine') + TranslationEngine(translationAxis=(0,1,0),velocity=0) + RotationEngine(rotationAxis=(1,0,0), angularVelocity=0,rotateAroundZero=True,zeroPoint=(0,0,0)),

.....
   ]

transEngine, rotEngine = combEngine.comb[0], combEngine.comb[1]

def updateRoller():
 transEngine.velocity = vel
 rotEngine.angularVelocity = angVel
 rotEngine.zeroPoint += Vector3(0,1,0)*vel*O.dt
 if rotEngine.zeroPoint[1]>limit:
  for t in range(min(idsr),max(idsr)+1):
   rotEngine.zeroPoint *= 0
   transEngine.velocity = 0
   rotEngine.angularVelocity = 0
   O.bodies.erase(t)
   checker.command='step2()'

def step2():
 combEngine.ids=idsr1
 transEngine.velocity = vel
 rotEngine.angularVelocity = angVel
 rotEngine.zeroPoint += Vector3(0,1,0)*vel*O.dt

[1]: https://gitlab.com/yade-dev/trunk/blob/master/examples/test/combined-kinematic-engine.py

Jan Stránský (honzik) said : #6

> but I have trouble in generating the second roller after the deleting of the previous one.

please be more specific, what have you tried and why/how it did not work

thanks
Jan

Paolo (p4olo) said : #7

Let's suppose to define the second roller "rullo1" after deleting the previous one "rullo" as follows. After the deleting, the simulation generates 2 rollers in the position(0,0,0): one remains fixed and the other one moves correctly. I don't know why it generates 2 rollers.

def updateRoller():
 transEngine.velocity = vel
 rotEngine.angularVelocity = angVel
 rotEngine.zeroPoint += Vector3(0,1,0)*vel*O.dt
 if rotEngine.zeroPoint[1]>l3-r:
  for t in range(min(idsr),max(idsr)+1):
   rotEngine.zeroPoint *= 0
   transEngine.velocity = 0
   rotEngine.angularVelocity = 0
   O.bodies.erase(t)
   rullo1 = geom.facetCylinder((0,0,0),radius=r,height=d,orientation=Quaternion((0,1,0),pi/2),wallMask=7,segmentsNumber=50,material=Mat1)
   O.bodies.append(rullo1)
                        global idsr1
   idsr1 = [r2.id for r2 in rullo1]
   checker.command='step2()'

def step2():
 combEngine.ids=idsr1
 transEngine.velocity = vel
 rotEngine.angularVelocity = angVel
 rotEngine.zeroPoint += Vector3(0,1,0)*vel*O.dt

Best Jan Stránský (honzik) said : #8

> for t in range(min(idsr),max(idsr)+1):
> ...
> rullo1 = geom.facetCylinder(...)

are you sure you have only two cylinders? :-)
put the creating line oustide the for loop and it should work

another note, O.bodies.append returns list of IDs, so you can save some lines (and potention source of problems) as :
##
global idsr1
idsr1 = O.bodies.append(rullo1)
##

cheers
Jan

Paolo (p4olo) said : #9

Thanks Jan Stránský, that solved my question.