Skip to content

Commit 0a09117

Browse files
committed
First working version.
1 parent 53ccf61 commit 0a09117

File tree

3 files changed

+206
-95
lines changed

3 files changed

+206
-95
lines changed

examples/test_prefab_meeting/entity.py

Lines changed: 118 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,69 @@
22

33
import Sofa
44
import dataclasses
5+
6+
def addBidule(self):
7+
return self.addChild("Bidule")
58

9+
DEFAULT_VALUE = object()
610

7-
class VisualModel(Sofa.Core.BasePrefab):
8-
def __init__(self, params, **kwargs):
9-
Sofa.Core.Node.__init__(self, **kwargs)
11+
def NONE(*args, **kwargs):
12+
pass
1013

11-
class Parameters(object):
12-
enabled : bool
13-
filename : str
14+
def to_dict(o):
15+
if isinstance(o, dict):
16+
return o
17+
if hasattr(o, "to_dict"):
18+
return o.to_dict()
19+
return {}
20+
21+
@dataclasses.dataclass
22+
class PrefabParameters(object):
23+
name : str = "Prefab"
24+
kwargs : dict = dataclasses.field(default_factory=dict)
25+
26+
def __getattr__(self, name: str) :
27+
if name == "__getstate__":
28+
getattr(PrefabParameters, "__getstate__")
29+
if name == "__setstate__":
30+
getattr(PrefabParameters, "__setstate__")
31+
32+
try:
33+
a = self.__getattribute__(name)
34+
except Exception as e:
35+
return NONE
36+
return a
37+
38+
def to_dict(self):
39+
return dataclasses.asdict(self)
40+
41+
@dataclasses.dataclass
42+
class VisualModelParameters(PrefabParameters):
43+
name : str = "VisualModel"
44+
45+
filename : str = "mesh/sphere_02.obj"
46+
47+
renderer : dict = dataclasses.field(default_factory=dict)
48+
mapping : dict = dataclasses.field(default_factory=dict)
49+
50+
class VisualModel(Sofa.Core.Node):
51+
52+
def __init__(self, parent=None, parameters : VisualModelParameters = VisualModelParameters()):
53+
Sofa.Core.Node.__init__(self, name=parameters.name)
1454

15-
class DefaultParameters(object):
16-
enabled : bool
17-
filename : str
55+
if parent != None:
56+
parent.addChild(self)
1857

58+
self.addObject("MeshOBJLoader", name="loader", filename=parameters.filename)
59+
self.addRenderer(**to_dict(parameters.renderer) | {"src" : "@loader"} )
60+
self.addMapping(**to_dict(parameters.mapping) )
61+
62+
def addRenderer(self, **kwargs):
63+
self.addObject("OglModel", name="renderer", **kwargs)
64+
65+
def addMapping(self, **kwargs):
66+
self.addObject("RigidMapping", name="mapping", **kwargs)
67+
1968
class CollisionModel(Sofa.Core.BasePrefab):
2069
def __init__(self, params, **kwargs):
2170
Sofa.Core.Node.__init__(self, **kwargs)
@@ -33,133 +82,107 @@ class Parameters(object):
3382
def to_dict(self):
3483
return dataclasses.asdict(self)
3584

36-
37-
def addBidule(self):
38-
return self.addChild("Bidule")
3985

86+
@dataclasses.dataclass
87+
class SimulationParameters(PrefabParameters):
88+
name : str = "Simulation"
89+
iterations : Optional[int] = None
90+
template: Optional[str] = None
91+
solver : dict = dataclasses.field(default_factory=dict)
92+
integration : dict = dataclasses.field(default_factory=dict)
4093

41-
class Entity(Sofa.Core.Prefab):
42-
def __init__(self, **kwargs):
43-
self.addChild(VisualModel(**kwargs), name="visual")
44-
self.addChild(CollisionModel(**kwargs), name="visual")
94+
def to_dict(self):
95+
return self.asdict()
4596

46-
def addConstitutiveLaw(self):
47-
pass
97+
class Simulation(Sofa.Core.Node):
98+
solver : Sofa.Core.Object
99+
integration : Sofa.Core.Object
100+
iterations : int
48101

49-
def addSolver(self):
50-
pass
102+
def __init__(self, parent : Sofa.Core.Node = None, parameters : SimulationParameters = SimulationParameters()):
103+
Sofa.Core.Node.__init__(self, name=parameters.name)
104+
if parent is not None:
105+
parent.addChild(self)
106+
107+
if parameters.iterations != NONE and "iterations" in parameters.solver:
108+
raise Exception("Cannot set direct attribute and internal hack... ")
51109

52-
DEFAULT_VALUE = object()
110+
self.addObject("EulerImplicitSolver", name = "integration", **to_dict(parameters.integration))
111+
self.addObject("CGLinearSolver", name = "solver", iterations=parameters.iterations, **to_dict(parameters.solver))
112+
53113

54-
def addSolver(node : Sofa.Core.Node, template=DEFAULT_VALUE, numiterations=DEFAULT_VALUE, **kwargs):
55-
node.addObject("ODESolver", name = "integrationscheme",numiterations = numiterations, **kwargs)
56-
node.addObject("LinearSolver", name = "numericalsolver", template=DEFAULT_VALUE, **kwargs)
57114

58115
#@dataclasses.dataclass
59116
#class Solver(object):
60117
# integrationscheme : str
61118
# numericalsolver : str
62119

63120
@dataclasses.dataclass
64-
class SolverParameters(object):
65-
numiteration : int | object = DEFAULT_VALUE
66-
template: str | object = DEFAULT_VALUE
121+
class EntityParameters(PrefabParameters):
122+
name : str = "Entity"
67123

68-
kwargs : dict = {"intergrato"}
124+
addSimulation : Callable = Simulation
125+
addCollisionModel : Callable = CollisionModel
126+
addVisualModel : Callable = VisualModel
69127

70-
def to_dict(self):
71-
return self.asdict() | self.kwargs
72-
73-
class Entity(Sofa.Core.Prefab):
128+
#setConstitutiveLaw # : Callable = addBidule
129+
#setBoundaryCondition #: Callable = addBidule
130+
131+
mechanical : dict = dataclasses.field(default_factory=dict)
132+
collision : CollisionModel.Parameters = CollisionModel.Parameters()
133+
visual : VisualModelParameters = VisualModelParameters()
134+
simulation : SimulationParameters = SimulationParameters()
135+
136+
class Entity(Sofa.Core.Node):
74137
# A simulated object
138+
simulation : Simulation
75139
visual : VisualModel
76140
collision : CollisionModel
77-
141+
78142
parameters : EntityParameters
79143

80-
addSolver : PrefabMethod
144+
def __init__(self, parent=None, parameters=EntityParameters(), **kwargs):
145+
Sofa.Core.Node.__init__(self, name=parameters.name)
81146

82-
def __init__(self, params):
83-
self.params = params
147+
if parent is not None:
148+
parent.addChild(self)
84149

85-
self.addChild(VisualModel(params.visual), name="visual")
150+
self.parameters = parameters
86151

87-
self.addSolver()
152+
self.addMechanicalModel(**parameters.mechanical)
153+
self.addSimulation(parameters=parameters.simulation)
154+
self.addVisualModel(parameters=parameters.visual)
88155
self.addCollisionModel()
89156

90-
#@staticmethod
91-
#def addSolver(self):
92-
# pass
157+
def addMechanicalModel(self, **kwargs):
158+
self.addObject("MechanicalObject", **kwargs)
93159

94-
#def defaultAddSolver(self):
95-
# pass
160+
def addSimulation(self, **kwargs):
161+
self.parameters.addSimulation(self, **kwargs)
162+
163+
def addVisualModel(self, **kwargs):
164+
self.parameters.addVisualModel(self, **kwargs)
96165

97-
@prefab.method
98166
def addCollisionModel(self):
99167
pass
100168

101-
@dataclasses.dataclass
102-
class EntityParameters(object):
103-
addSolver : Callable = addSolver
104-
setConstitutiveLaw # : Callable = addBidule
105-
setBoundaryCondition #: Callable = addBidule
106-
107-
addCollisionModel : CollisionModel
108-
109-
#mechanical : MechanicalObject.Parameters = MechanicalObject.Parameters()
110-
collision : CollisionModel.Parameters = CollisionModel.Parameters()
111-
visual : VisualModel.Parameters = VisualModel.Parameters()
112-
solver : SolverParameters = SolverParameters()
113-
114-
kwargs : dict = {}
115-
def to_dict(self):
116-
return dataclasses.asdict(self)
117-
118-
119169
class Rigid(Entity):
120170
def __init__(self, **kwargs):
121171
Entity.__init__(self, **kwargs)
122172

123-
class Parameters(Entity.Parameters):
124-
pass
125173

126174
class Deformable(Entity):
127175
def __init__(self, **kwargs):
128176
Entity.__init__(self, **kwargs)
129-
130-
class Parameters(Entity.Parameters):
131-
addConstitutiveLaw : Callable
132-
mass = 3.4
133-
name = "Deformable"
134-
135-
def to_dict(self):
136-
return dataclasses.asdict(self)
137177

178+
@dataclasses.dataclass
179+
class DeformableEntityParameters(EntityParameters):
180+
addConstitutiveLaw : Callable = lambda x: x
138181

139-
Entity.Rigid = Rigid
140-
Entity.Deformable = Deformable
141-
142-
class SoftRobots:
143-
class Cable(Sofa.Core.BasePrefab):
144-
length : float
145-
146-
def __init__(self,**kwargs):
147-
pass
148-
149-
def Parameters(object):
150-
lenght : float
182+
mass : Optional[float] = None
151183

152-
class Trunk(Sofa.Core.BasePrefab):
153-
body : Entity.Deformable
154-
cables : list [SoftRobots.Cable]
155-
156-
def __init__(self, params):
157-
body = Entity.Deformable()
184+
def to_dict(self):
185+
return dataclasses.asdict(self)
158186

159-
for param in range(params.cables):
160-
cables.append(SoftRobots.Cable(body, param))
161187

162-
class Parameters(object):
163-
body : Entity.Deformable.Parameters
164-
cables : list[SoftRobots.Cable.Parameters]
165188

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class SoftRobots:
2+
class Cable(Sofa.Core.BasePrefab):
3+
length : float
4+
5+
def __init__(self,**kwargs):
6+
pass
7+
8+
def Parameters(object):
9+
lenght : float
10+
11+
class Trunk(Sofa.Core.BasePrefab):
12+
body : Entity.Deformable
13+
cables : list [SoftRobots.Cable]
14+
15+
def __init__(self, params):
16+
body = Entity.Deformable()
17+
18+
for param in range(params.cables):
19+
cables.append(SoftRobots.Cable(body, param))
20+
21+
class Parameters(object):
22+
body : Entity.Deformable.Parameters
23+
cables : list[SoftRobots.Cable.Parameters]
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import Sofa.Core
2+
import copy
3+
import entity
4+
from entity import PrefabParameters, EntityParameters, Entity, Simulation
5+
6+
7+
oldAdd=Sofa.Core.Node.addObject
8+
def myAddObject(self : Sofa.Core.Node, tname, **kwargs):
9+
kwargs = copy.copy(kwargs)
10+
previouslen = len(self.objects)
11+
try:
12+
oldAdd(self, tname, **kwargs)
13+
except Exception as e:
14+
target = self
15+
if len(self.objects) != previouslen:
16+
target = list(self.objects)[-1]
17+
Sofa.msg_error(target, str(e))
18+
19+
Sofa.Core.Node.addObject = myAddObject
20+
21+
22+
def myAdd(self : Sofa.Core.Node, c, params = PrefabParameters(), **kwargs):
23+
def findName(cname, node):
24+
"""Compute a working unique name in the node"""
25+
rname = cname
26+
for i in range(0, len(node.children)):
27+
if rname not in node.children:
28+
return rname
29+
rname = cname + str(i+1)
30+
return rname
31+
32+
for k,v in kwargs.items():
33+
if hasattr(params, k):
34+
setattr(params, k, v)
35+
36+
params = copy.copy(params)
37+
if params.name in self.children:
38+
params.name = findName(params.name, self)
39+
40+
return c(parent = self, parameters=params)
41+
Sofa.Core.Node.add = myAdd
42+
43+
def createScene(root):
44+
#@optionalkwargs
45+
46+
#def eulalieAddOde(self, **kwargs):
47+
# self.addObject("EulerExplicitSolver", name="numericalintegration")
48+
# self.addObject("LinearSolver", name="numericalsolver", firstOrder=True)
49+
50+
params = EntityParameters()
51+
params.simulation.iterations = 10
52+
params.simulation.integration["rayleighStiffness"] = 2.0
53+
params.addSimulation = entity.NONE
54+
55+
params.mechanical["template"] = "Rigid3"
56+
57+
#params.simulation.integration["rayleightStiffnessXXX"] = 2.0
58+
59+
#params.solver.kwargs["numericalintegration"] = { "firstOrder" : True }
60+
61+
root.add(Entity, params)
62+
root.add(Entity, params)
63+
root.add(Entity, params)
64+
65+
#root.add(Simulation, name="mySimulation")

0 commit comments

Comments
 (0)