def insertRigidScale(parentNode, solidModel, param): """ create a RigidScale.API.ShearlessAffineBody from the solidModel """ if printLog: Sofa.msg_info("RigidScale.sml", "insertRigidScale "+solidModel.name) body = RigidScale.API.ShearlessAffineBody(parentNode, solidModel.name) if (not len(solidModel.mesh)==1): Sofa.msg_warning("RigidScale.sml", "insertRigidScale support only single mesh solid (nb meshes={0}) - solid {1} ignored".format(len(solidModel.mesh), solidModel.name)) return None # TODO support multi meshes body.setFromMesh(solidModel.mesh[0].source, numberOfPoints = SofaPython.sml.getValueByTag(param.rigidScaleNbDofByTag, solidModel.tags), voxelSize = SofaPython.units.length_from_SI(param.voxelSize), density = SofaPython.units.massDensity_from_SI(1000.), offset = solidModel.position) body.addBehavior(youngModulus=SofaPython.units.elasticity_from_SI(param.rigidScaleStiffness), numberOfGaussPoint=8) cm = body.addCollisionMesh(solidModel.mesh[0].source) cm.addVisualModel() body.affineDofs.showObject=param.showAffine body.affineDofs.showObjectScale=SofaPython.units.length_from_SI(param.showAffineScale) if param.showImage: body.image.addViewer() return body
def createScene(self): model=self.model # shortcut for solid in model.solids.values(): if printLog: Sofa.msg_info("SofaPython.sml","SceneDisplay: Display solid:" + solid.name) color = getValueByTag(self.param.colorByTag, solid.tags) insertVisual(self.node, solid, color)
def processProperties(self, key, kv, stack, frame): if not isinstance(kv, list): raise Exception("This shouldn't happen, exepecting only list") msg = "" for k, v in kv: ## Check if the property named by "k" already exists. if hasattr(self, k): msg += " - cannot add a property named '" + k + "' as it already exists" continue if isAStringToken(v): v = processString(v, stack, frame) if isinstance(v, int): self.addNewData(k, "Properties", "", "d", v) elif isinstance(v, str) or isinstance(v, unicode): self.addNewData(k, "Properties", "", "s", str(v)) elif isinstance(v, float): self.addNewData(k, "Properties", "", "f", v) if hasattr(self, k): msg += " - adding: '" + str(k) + "' = " + str(v) else: msg += " - unable to create a property from the value '" + str( v) + "'" Sofa.msg_info(self, pslprefix + "Adding a user properties: \n" + msg)
def setupUnits(myUnits): message = "units:" for quantity, unit in myUnits.iteritems(): exec("units.local_{0} = units.{0}_{1}".format(quantity, unit)) message += " " + quantity + ":" + unit if printLog: Sofa.msg_info("SofaPython.sml", message)
def read(self, filenamePrefix=None, directory="", **kwargs): filename = self.getFilename(filenamePrefix, directory) data = dict() with open(filename, 'r') as f: data.update(json.load(f)) self.type = data['type'] self.sampler = self.node.createObject( 'GaussPointContainer', name='GPContainer', volumeDim=data['volumeDim'], inputVolume=data['inputVolume'], position=data['position'], **kwargs) if not self.labelImage is None and not self.labels is None: if self.labelImage.prefix == "Branching": celloffsets = self.node.createObject( "BranchingCellOffsetsFromPositions", template=self.labelImage.template(), name="cell", position=self.sampler.getLinkPath() + ".position", src=self.labelImage.getImagePath(), labels=concat(self.labels)) self.cell = celloffsets.getLinkPath() + ".cell" if printLog: Sofa.msg_info("Flexible.API.Behavior", 'Imported Gauss Points from ' + filename)
def read(self, filenamePrefix=None, directory=""): filename = self.getFilename(filenamePrefix, directory) if os.path.isfile(filename): data = dict() with open(filename, 'r') as f: data.update(json.load(f)) # dofs self.dof = self.node.createObject( "MechanicalObject", name="dofs", template=data['template'], position=(data['position']), rest_position=(data['rest_position'])) # mesh if 'hexahedra' in data and 'tetrahedra' in data: self.mesh = self.node.createObject( "Mesh", name="mesh", position=(data['rest_position']), hexahedra=data['hexahedra'], tetrahedra=data['tetrahedra']) # uniform mass if 'totalMass' in data: self.addUniformMass(data['totalMass']) if printLog: Sofa.msg_info("Flexible.API.FEMDof", 'Imported FEM Dof from ' + filename)
def setupUnits(myUnits): message = "units:" for quantity,unit in myUnits.iteritems(): exec("units.local_{0} = units.{0}_{1}".format(quantity,unit)) message+=" "+quantity+":"+unit if printLog: Sofa.msg_info("SofaPython.sml",message)
def createScene(self): model=self.model # shortcut for solid in model.solids.values(): if printLog: Sofa.msg_info("SofaPython.sml","SceneDisplay: Display solid:" + solid.name) color = solid.getValueByTag(self.param.colorByTag) insertVisual(self.node, solid, color)
def write(self, filenamePrefix=None, directory=""): filename = self.getFilename(filenamePrefix,directory) data = {'massMatrix': str(self.mass.findData('massMatrix').value).replace('\n',' ')} with open(filename, 'w') as f: json.dump(data, f) if printLog: Sofa.msg_info("Flexible.API.AffineMass",'Exported Affine Mass to '+filename)
def getVisualsByTags(self, solidId=None, solidTags=set(), meshTags=set()): """ \return a selection of visual models, based on solidTags and meshTags an empty tag set means all solids or meshes """ visuals = list() if not solidId is None and len(solidTags): Sofa.msg_warning("sml.Model.getVisualsByTags", "solidId and solidTags both specified, solidTags ignored") solids = None if not solidId is None: solids = [self.model.solids[solidId]] elif len(solidTags) : solids = self.model.getSolidsByTags(solidTags) else : solids = self.model.solids.values() for solid in solids: if not solid.id in self.visuals: if printLog: Sofa.msg_info("SofaPython.sml", "No visual for solid "+solid.id) continue solidVisuals = self.visuals[solid.id] meshes = solid.getMeshesByTags(meshTags) if len(meshTags) else solid.mesh for mesh in meshes: if not mesh.id in solidVisuals: if printLog: Sofa.msg_info("SofaPython.sml", "No visual for solid "+solid.id+", mesh: "+mesh.id) continue visual = solidVisuals[mesh.id] visual.mesh = mesh # make sure we known which mesh is attached to this visual visuals.append(visual) return visuals
def AnimationManager(node): """ A Controller to manage all animations in the scene. Before using the animation framework an AnimationManager must be added to the scene. It has in charge, at each time step to update all the running animations. Returns: AnimationManagerController Example: .. sourcecode:: python def createScene(rootNode) AnimationManager(rootNode) """ global manager if manager != None: Sofa.msg_info( node, "There is already one animation manager in this scene...why do you need a second one ?" ) return manager manager = AnimationManagerController(node) return manager
def processProperties(self, key, kv, stack, frame): if not isinstance(kv, list): raise Exception("This shouldn't happen, exepecting only list") msg = "" for k,v in kv: ## Check if the property named by "k" already exists. if hasattr(self, k): msg += " - cannot add a property named '"+k+"' as it already exists" continue if isAStringToken(v): v=processString(v, stack, frame) if isinstance(v, int): self.addNewData(k, "Properties", "", "d", v) elif isinstance(v, str) or isinstance(v,unicode): self.addNewData(k, "Properties", "", "s", str(v)) elif isinstance(v, float): self.addNewData(k, "Properties", "", "f", v) if hasattr(self, k): msg += " - adding: '"+str(k)+"' = "+str(v) else: msg += " - unable to create a property from the value '"+str(v)+"'" Sofa.msg_info(self, pslprefix+"Adding a user properties: \n"+msg)
def createScene(node): # some code before a = 0 # w/ emitter Sofa.msg_info( "MyPythonEmitter", "my message info a="+str(a) ) Sofa.msg_warning( "MyPythonEmitter a="+str(a), "my message warning" ) Sofa.msg_error( "MyPythonEmitter", "my message error" ) Sofa.msg_fatal( "MyPythonEmitter", "my message fatal" ) # some code in between a = 2 # w/o emitter Sofa.msg_info( "my message info a="+str(a) ) Sofa.msg_warning( "my message warning" ) Sofa.msg_error( "my message error" ) Sofa.msg_fatal( "my message fatal" ) # more complex code was causing trouble, so try it model = SofaPython.sml.Model("smlSimple.sml") # # invalid calls # Sofa.msg_info( 100 ) # Sofa.msg_info( "emitter", "message", "extra" ) sys.stdout.flush()
def writeStrains(self, filenamePrefix=None, directory=""): if not self.strainDofs is None: filename = self.getFilename(filenamePrefix,directory).replace(".json","_E.json") data = {'type': self.type,'position': SofaPython.Tools.listListToStr(self.strainDofs.position) } with open(filename, 'w') as f: json.dump(data, f) if printLog: Sofa.msg_info("Flexible.API.Behavior",'Exported Strains in: '+filename)
def writeObj(self, filenamePrefix=None, directory=""): filename = self.getFilename(filenamePrefix,directory).replace("json","obj") with open(filename, 'w') as f: f.write(self.name+"\n") for p in self.sampler.position: f.write("v "+SofaPython.Tools.listToStr(p)+"\n") if printLog: Sofa.msg_info("Flexible.API.Behavior",'Exported Gauss Points as a mesh: '+filename)
def test_loggedMessagesBinding(self): node = create_scene("a_node") self.assertEqual(node.getLoggedMessagesAsString(), "") Sofa.msg_info(node, "This is a new message") self.assertTrue("This is a new message" in node.getLoggedMessagesAsString()) self.assertEqual(node.countLoggedMessages(), 1) node.clearLoggedMessages() self.assertEqual(node.countLoggedMessages(), 0)
def insertJoint(jointModel, rigids, param): """ create a StructuralAPI.GenericRigidJoint from the jointModel """ frames = list() for i, offset in enumerate(jointModel.offsets): if not jointModel.solids[i].id in rigids: Sofa.msg_warning( "Compliant.sml", "insertJoint " + jointModel.name + " failed: " + jointModel.solids[i].id + " is not a rigid body") return None rigid = rigids[jointModel.solids[i].id] # shortcut if rigid is None: Sofa.msg_warning( "Compliant.sml", "in joint {0}, solid {1} is missing, ignored".format( jointModel.name, jointModel.solids[i].id)) return if not offset is None: if offset.isAbsolute(): frames.append( rigid.addAbsoluteOffset(offset.name, offset.value)) else: frames.append(rigid.addOffset(offset.name, offset.value)) if not param is None: frames[-1].dofs.showObject = param.showOffset frames[ -1].dofs.showObjectScale = SofaPython.units.length_from_SI( param.showOffsetScale) else: frames.append(rigid) if printLog: Sofa.msg_info("Compliant.sml", "insertJoint " + jointModel.name) mask = [1] * 6 limits = [] # mask for limited dofs isLimited = True # does the joint have valid limits? for d in jointModel.dofs: if isLimited: if d.min == None or d.max == None: isLimited = False # as soon as a limit is not defined, the limits cannot work else: limits.append(d.min) limits.append(d.max) mask[d.index] = 0 joint = StructuralAPI.GenericRigidJoint( jointModel.name, frames[0].node, frames[1].node, mask, compliance=SofaPython.sml.getValueByTag(param.jointComplianceByTag, jointModel.tags), isCompliance=SofaPython.sml.getValueByTag(param.jointIsComplianceByTag, jointModel.tags)) if isLimited: joint.addLimits(limits) return joint
def read(self, filenamePrefix=None, directory=""): filename = self.getFilename(filenamePrefix,directory) if os.path.isfile(filename): data = dict() with open(filename,'r') as f: data.update(json.load(f)) self.dof = self.node.createObject("MechanicalObject", name="dofs", template=data['template'], position=data['position'], rest_position=data['rest_position']) if printLog: Sofa.msg_info("Flexible.API.AffineDof",'Imported Affine Dof from '+filename)
def read(self, filenamePrefix=None, directory=""): filename = self.getFilename(filenamePrefix,directory) if os.path.isfile(filename): data = dict() with open(filename,'r') as f: data.update(json.load(f)) self.mass = self.dofAffineNode.createObject('AffineMass', name='mass', massMatrix=data['massMatrix']) if printLog: Sofa.msg_info("Flexible.API.AffineMass",'Imported Affine Mass from '+filename)
def checkSysPathDuplicate(): for p in sys.path: print p for p in sys.path: print p if (sys.path.count(p)>1): Sofa.msg_info("Found duplicate path : "+p) if not EXPECT_EQ(1,sys.path.count(p),"sys.path.count("+p+")"): return False return True
def write(self, filenamePrefix=None, directory=""): if self.dof is None: Sofa.msg_error("Flexible.API.AffineDof","write : no dof") return filename = self.getFilename(filenamePrefix,directory) data = {'template':'Affine', 'rest_position': affineDatatostr(self.dof.rest_position), 'position': affineDatatostr(self.dof.position)} with open(filename, 'w') as f: json.dump(data, f) if printLog: Sofa.msg_info("Flexible.API.AffineDof",'Exported Affine Dof to '+filename)
def initGraph(self, node): Sofa.msg_info("initGraph ENTER") child = node.createChild("temporary_node") # FROM HERE, 'child' was added to the nodes to init in ScriptEnvironment, but it is not anymore node.removeChild(child) # 'child' is no longer in the scene graph but still was in ScriptEnvironment, but it is not anymore Sofa.msg_info("initGraph EXIT")
def initGraph(self, node): Sofa.msg_info("initGraph ENTER") child = node.createChild("temporary_node") # FROM HERE, 'child' was added to the nodes to init in ScriptEnvironment, but it is not anymore node.removeChild( child ) # 'child' is no longer in the scene graph but still was in ScriptEnvironment, but it is not anymore Sofa.msg_info("initGraph EXIT")
def write(self, filenamePrefix=None, directory=""): filename = self.getFilename(filenamePrefix,directory) volumeDim = len(self.sampler.volume)/ len(self.sampler.position) if isinstance(self.sampler.volume, list) is True else 1 # when volume is a list (several GPs or order> 1) data = {'type': self.type, 'volumeDim': str(volumeDim), 'inputVolume': SofaPython.Tools.listListToStr(self.sampler.volume), 'position': SofaPython.Tools.listListToStr(self.sampler.position), 'indices': self.mapping.indices, 'weights': self.mapping.weights, 'weightGradients': self.mapping.weightGradients, 'weightHessians': self.mapping.weightHessians} # @todo: add restShape ? with open(filename, 'w') as f: json.dump(data, f) if printLog: Sofa.msg_info("Flexible.API.Behavior",'Exported Gauss Points to '+filename)
def read(self, filenamePrefix=None, directory="", **kwargs): filename = self.getFilename(filenamePrefix,directory) data = dict() with open(filename,'r') as f: data.update(json.load(f)) self.sampler = self.node.createObject('GaussPointContainer',name='GPContainer', volumeDim=data['volumeDim'], inputVolume=data['inputVolume'], position=data['position'], **kwargs) if not self.labelImage is None and not self.labels is None: if self.labelImage.prefix == "Branching": celloffsets = self.node.createObject("BranchingCellOffsetsFromPositions", template=self.labelImage.template(), name="cell", position =self.sampler.getLinkPath()+".position", src=self.labelImage.getImagePath(), labels=concat(self.labels)) self.cell = celloffsets.getLinkPath()+".cell" if printLog: Sofa.msg_info("Flexible.API.Behavior",'Imported Gauss Points from '+filename)
def write(self, filenamePrefix=None, directory=""): """ write weights of the linear mapping """ if self.mapping is None: return if self.mapping.getClassName().find("Linear") == -1: return filename = self.getFilename(filenamePrefix,directory) data = {'indices': self.mapping.indices, 'weights': self.mapping.weights} with open(filename, 'w') as f: json.dump(data, f) if printLog: Sofa.msg_info("Flexible.API.Deformable",'Exported Weights to '+filename)
def onAnimateBeginEvent(self, event): # receive data, addr = self.sock.recvfrom(8192) # simulink's UDP buffer size is fixed at 8192 bytes and is not configurable. # msg_in = struct.unpack('d', data) # works with simulink msg_in = struct.unpack('b', data) # works with matlab Sofa.msg_info("received message:"+str(msg_in)) # send pos = numpy.matrix(self.meca.position[0]) # msg_out = struct.pack('d', pos[0,0]) # works with simulink msg_out = struct.pack('b', int(pos[0,0])) # works with matlab self.sock.sendto(msg_out, (self.UDP_IP, self.UDP_port_out)) Sofa.msg_info("sent message:"+str(pos[0,0]))
def insertRigidScale(parentNode, rigidModel, param): """ Create a RigidScale.API.ShearlessAffineBody from the solidModel """ if printLog: Sofa.msg_info("RigidScale.sml", "insertRigidScale " + rigidModel.name) body = RigidScale.API.ShearlessAffineBody(parentNode, rigidModel.name) if (not len(rigidModel.mesh) == 1): Sofa.msg_warning( "RigidScale.sml", "insertRigidScale support only single mesh solid (nb meshes={0}) - solid {1} ignored" .format(len(rigidModel.mesh), rigidModel.name)) return None # TODO support multi meshes meshFormatSupported = True for mesh in rigidModel.mesh: meshFormatSupported &= mesh.format == "obj" or mesh.format == "vtk" if len(rigidModel.mesh) > 0 and meshFormatSupported: body.setFromMesh(rigidModel.mesh[0].source, numberOfPoints=SofaPython.sml.getValueByTag( param.rigidScaleNbDofByTag, rigidModel.tags), voxelSize=SofaPython.units.length_from_SI( param.voxelSize), density=SofaPython.units.massDensity_from_SI(1000.), offset=rigidModel.position) cm = body.addCollisionMesh(rigidModel.mesh[0].source) cm.addVisualModel() else: body.setManually(offset=rigidModel.position) body.addBehavior(youngModulus=SofaPython.units.elasticity_from_SI( param.rigidScaleStiffness), numberOfGaussPoint=8) #cm = body.addCollisionMesh(rigidModel.mesh[0].source) #cm.addVisualModel() body.affineDofs.showObject = param.showAffine body.affineDofs.showObjectScale = SofaPython.units.length_from_SI( param.showAffineScale) body.rigidDofs.showObject = param.showRigid body.rigidDofs.showObjectScale = SofaPython.units.length_from_SI( param.showRigidScale) if param.showImage: body.image.addViewer() return body
def processImportPY(parent, importname, filename, key, stack, frame): Sofa.msg_info(parent, pslprefix+"Importing '"+importname+".py' file format.") pythonfile = open(filename).read() locals = {} frame = flattenStackFrame(stack) exec(pythonfile, frame, locals) if not "PSLExport" in locals: Sofa.msg_error(parent, pslprefix+"The file '"+filename+"' does not seem to contain PSL templates.") return for name in locals: templates[importname+"."+name] = locals[name]
def createObject(parentNode, name, stack , frame, kv): if name in sofaComponents: obj = parentNode.createObject(name, **kv) for k in kv: if getField(obj, k) == None: Sofa.msg_info(obj, pslprefix+" attribute '"+str(k)+"' is a parsing hook. Let's add Data field to fix it. To remove this warning stop using parsing hook.") d = obj.addNewData(k, "PSL", "", "s", str(kv[k])) obj.findData(k).setPersistant(True) return obj kv["name"] = name failureObject = parentNode.createObject("Undefined", **kv) Sofa.msg_error(failureObject, pslprefix+" unable to create the object '"+str(name)+"'") return failureObject
def processImportPSL(parent, importname, filename, key, stack, frame): global imports, templates im = parent.createObject("Import") im.name = importname f = open(filename).read() loadedcontent = pslparserhjson.parse(f) imports[filename] = importTemplates(loadedcontent) msg = "From <i>" + filename + "</i> importing: <ul>" for tname in imports[filename].keys(): templates[importname + "." + tname] = imports[filename][tname] msg += " <li> template <i>" + tname + "</i> </li>" msg += "</ul>" Sofa.msg_info(im, msg)
def processImportPSL(parent, importname, filename, key, stack, frame): global imports, templates im = parent.createObject("Import") im.name = importname f = open(filename).read() loadedcontent = pslparserhjson.parse(f) imports[filename] = importTemplates(loadedcontent) msg = "From <i>"+filename+"</i> importing: <ul>" for tname in imports[filename].keys(): templates[importname+"."+tname] = imports[filename][tname] msg+=" <li> template <i>"+tname+"</i> </li>" msg += "</ul>" Sofa.msg_info(im, msg)
def read(self, filenamePrefix=None, directory=""): filename = self.getFilename(filenamePrefix,directory) if os.path.isfile(filename): data = dict() with open(filename,'r') as f: data.update(json.load(f)) # dofs self.dof = self.node.createObject("MechanicalObject", name="dofs", template=data['template'], position=(data['position']), rest_position=(data['rest_position'])) # mesh if 'hexahedra' in data and 'tetrahedra' in data: self.mesh = self.node.createObject("Mesh", name="mesh", position=(data['rest_position']), hexahedra=data['hexahedra'], tetrahedra=data['tetrahedra'] ) # uniform mass if 'totalMass' in data : self.addUniformMass(data['totalMass']) if printLog: Sofa.msg_info("Flexible.API.FEMDof",'Imported FEM Dof from '+filename)
def processImportPY(parent, importname, filename, key, stack, frame): Sofa.msg_info(parent, pslprefix + "Importing '" + importname + ".py' file format.") pythonfile = open(filename).read() locals = {} frame = flattenStackFrame(stack) exec(pythonfile, frame, locals) if not "PSLExport" in locals: Sofa.msg_error( parent, pslprefix + "The file '" + filename + "' does not seem to contain PSL templates.") return for name in locals: templates[importname + "." + name] = locals[name]
def read(self, filenamePrefix=None, directory=""): """ read weights of the linear mapping WARNING: the mapping should already be created """ if self.mapping is None: return if self.mapping.getClassName().find("Linear") == -1: return filename = self.getFilename(filenamePrefix,directory) if os.path.isfile(filename): data = dict() with open(filename,'r') as f: data.update(json.load(f)) self.mapping.indices= str(data['indices']) self.mapping.weights= str(data['weights']) if printLog: Sofa.msg_info("Flexible.API.Deformable",'Imported Weights from '+filename)
def initGraph(self, node): name = u"aaé朮ßþ" mechanical_object = node.createObject("MechanicalObject", name=name) self.ASSERT(unicode(mechanical_object.name, "utf-8") == name, "test1") mechanical_object.name = name self.ASSERT(unicode(mechanical_object.name, "utf-8") == name, "test2") mechanical_object.name = u"ijðð…" self.ASSERT(unicode(mechanical_object.name, "utf-8") == u"ijðð…", "test3") self.ASSERT(isinstance(mechanical_object.name, str), "test4") Sofa.msg_info(mechanical_object.name) mechanical_object.name = mechanical_object.name
def initGraph(self, node): name = u"aaé朮ßþ" mechanical_object = node.createObject("MechanicalObject", name=name) self.ASSERT(unicode(mechanical_object.name, "utf-8") == name, "test1") mechanical_object.name = name self.ASSERT(unicode(mechanical_object.name, "utf-8") == name, "test2") mechanical_object.name = u"ijðð…" self.ASSERT( unicode(mechanical_object.name, "utf-8") == u"ijðð…", "test3") self.ASSERT(isinstance(mechanical_object.name, str), "test4") Sofa.msg_info(mechanical_object.name) mechanical_object.name = mechanical_object.name
def insertJoint(jointModel, rigids, scale=1, param=None): """ create a StructuralAPI.GenericRigidJoint from the jointModel """ frames=list() for i,offset in enumerate(jointModel.offsets): if not jointModel.solids[i].id in rigids: Sofa.msg_warning("Compliant.sml","insertJoint "+jointModel.name+" failed: "+jointModel.solids[i].id+" is not a rigid body") return None rigid = rigids[jointModel.solids[i].id] # shortcut if rigid is None: Sofa.msg_warning("Compliant.sml", "in joint {0}, solid {1} is missing, ignored".format(jointModel.name, jointModel.solids[i].id)) return if not offset is None: if offset.isAbsolute(): frames.append( rigid.addAbsoluteOffset(offset.name, StructuralAPI.scaleOffset(scale,offset.value)) ) else: frames.append( rigid.addOffset(offset.name, StructuralAPI.scaleOffset(scale,offset.value)) ) if not param is None: frames[-1].dofs.showObject = param.showOffset frames[-1].dofs.showObjectScale = SofaPython.units.length_from_SI(param.showOffsetScale) else: frames.append(rigid) if printLog: Sofa.msg_info("Compliant.sml","insertJoint "+jointModel.name) mask = [1]*6 limits=[] # mask for limited dofs isLimited = True # does the joint have valid limits? for d in jointModel.dofs: if isLimited: if d.min==None or d.max==None: isLimited = False # as soon as a limit is not defined, the limits cannot work else: limits.append(d.min) limits.append(d.max) mask[d.index] = 0 joint = StructuralAPI.GenericRigidJoint(jointModel.name, frames[0].node, frames[1].node, mask, compliance=SofaPython.sml.getValueByTag(param.jointComplianceByTag, jointModel.tags), isCompliance=SofaPython.sml.getValueByTag(param.jointIsComplianceByTag, jointModel.tags)) if isLimited: joint.addLimits(limits) return joint
def insertRigidScale(parentNode, rigidModel, param): """ Create a RigidScale.API.ShearlessAffineBody from the solidModel """ if printLog: Sofa.msg_info("RigidScale.sml", "insertRigidScale "+rigidModel.name) body = RigidScale.API.ShearlessAffineBody(parentNode, rigidModel.name) if (not len(rigidModel.mesh)==1): Sofa.msg_warning("RigidScale.sml", "insertRigidScale support only single mesh solid (nb meshes={0}) - solid {1} ignored".format(len(rigidModel.mesh), rigidModel.name)) return None # TODO support multi meshes meshFormatSupported = True for mesh in rigidModel.mesh : meshFormatSupported &= mesh.format=="obj" or mesh.format=="vtk" if len(rigidModel.mesh)>0 and meshFormatSupported: body.setFromMesh(rigidModel.mesh[0].source, numberOfPoints = SofaPython.sml.getValueByTag(param.rigidScaleNbDofByTag, rigidModel.tags), voxelSize = SofaPython.units.length_from_SI(param.voxelSize), density = SofaPython.units.massDensity_from_SI(1000.), offset = rigidModel.position) else: body.setManually(offset=rigidModel.position); #body.addBehavior(youngModulus=SofaPython.units.elasticity_from_SI(param.rigidScaleStiffness), numberOfGaussPoint=8) #cm = body.addCollisionMesh(rigidModel.mesh[0].source) #cm.addVisualModel() body.affineDofs.showObject = param.showAffine body.affineDofs.showObjectScale = SofaPython.units.length_from_SI(param.showAffineScale) body.rigidDofs.showObject = param.showRigid body.rigidDofs.showObjectScale = SofaPython.units.length_from_SI(param.showRigidScale) print "affines:", body.affineDofs.showObject, body.affineDofs.showObjectScale print "rigids: ", body.rigidDofs.showObject, body.rigidDofs.showObjectScale if param.showImage: body.image.addViewer() return body
def createObject(parentNode, name, stack, frame, kv): if name in sofaComponents: obj = parentNode.createObject(name, **kv) for k in kv: if getField(obj, k) == None: Sofa.msg_info( obj, pslprefix + " attribute '" + str(k) + "' is a parsing hook. Let's add Data field to fix it. To remove this warning stop using parsing hook." ) d = obj.addNewData(k, "PSL", "", "s", str(kv[k])) obj.findData(k).setPersistant(True) return obj kv["name"] = name failureObject = parentNode.createObject("Undefined", **kv) Sofa.msg_error( failureObject, pslprefix + " unable to create the object '" + str(name) + "'") return failureObject
def write(self, filenamePrefix=None, directory=""): if self.dof is None: Sofa.msg_error("Flexible.API.FEMDof", "write : no dof") return filename = self.getFilename(filenamePrefix, directory) data = { 'template': 'Vec3', 'rest_position': lconcat(self.dof.rest_position), 'position': lconcat(self.dof.position) } # add mapping data if existing if not self.mapping is None: if self.mapping.getClassName().find("Linear") != -1: data['mappingType'] = self.mapping.getClassName() data['indices'] = self.mapping.indices data['weights'] = self.mapping.weights elif self.mapping.getClassName().find("SubsetMultiMapping") != -1: data['mappingType'] = self.mapping.getClassName() data['indexPairs'] = lconcat(self.mapping.indexPairs) elif self.mapping.getClassName().find("SubsetMapping") != -1: data['mappingType'] = self.mapping.getClassName() data['indices'] = lconcat(self.mapping.indices) # add some topology data if existing if not self.mesh is None: # data['edges']=self.mesh.edges # data['triangles']=self.mesh.triangles # data['quads']=self.mesh.quads data['hexahedra'] = lconcat(self.mesh.hexahedra) data['tetrahedra'] = lconcat(self.mesh.tetrahedra) # add mass data if existing if not self.mass is None: data['totalMass'] = self.mass.totalMass with open(filename, 'w') as f: json.dump(data, f) if printLog: Sofa.msg_info("Flexible.API.FEMDof", 'Exported FEM Dof to ' + filename)
def readMapping(self, filenamePrefix=None, directory=""): """ read mapping parameters WARNING: the mapping shoud be already created """ if self.mapping is None: return filename = self.getFilename(filenamePrefix,directory) if os.path.isfile(filename): data = dict() with open(filename,'r') as f: data.update(json.load(f)) if 'mappingType' in data: if data['mappingType'].find("Linear") != -1: self.mapping.indices= str(data['indices']) self.mapping.weights= str(data['weights']) elif data['mappingType'].find("SubsetMultiMapping") != -1: self.mapping.indexPairs= str(data['indexPairs']) elif data['mappingType'].find("SubsetMapping") != -1: self.mapping.indices= str(data['indices']) if printLog: Sofa.msg_info("Flexible.API.FEMDof",'Imported FEM Dof mapping from '+filename)
def __init__(self, parent, surfaceMeshFileName, name="VisualModel", color=[1., 1., 1.], rotation=[0., 0., 0.], translation=[0., 0., 0.], scale=[1., 1., 1.]): self.node = Node(parent, name) if not self.getRoot().getObject("SofaOpenglVisual", warning=False): if not self.getRoot().getObject("/Config/SofaOpenglVisual", warning=False): Sofa.msg_info( "Missing RequiredPlugin SofaOpenglVisual in the scene, add it from Prefab VisualModel." ) self.getRoot().createObject("RequiredPlugin", name="SofaOpenglVisual") if surfaceMeshFileName.endswith(".stl"): self.loader = self.node.createObject('MeshSTLLoader', name="loader", filename=surfaceMeshFileName) elif surfaceMeshFileName.endswith(".obj"): self.loader = self.node.createObject('MeshObjLoader', name="loader", filename=surfaceMeshFileName) else: print( "Extension not handled in STLIB/python/stlib/visuals for file: " + str(surfaceMeshFileName)) self.model = self.node.createObject('OglModel', name="model", src="@loader", rotation=rotation, translation=translation, scale3d=scale, color=color, updateNormals=False)
def write(self, filenamePrefix=None, directory=""): if self.dof is None: Sofa.msg_error("Flexible.API.FEMDof","write : no dof") return filename = self.getFilename(filenamePrefix,directory) data = {'template':'Vec3', 'rest_position': lconcat(self.dof.rest_position), 'position': lconcat(self.dof.position)} # add mapping data if existing if not self.mapping is None: if self.mapping.getClassName().find("Linear") != -1: data['mappingType']=self.mapping.getClassName() data['indices']=self.mapping.indices data['weights']=self.mapping.weights elif self.mapping.getClassName().find("SubsetMultiMapping") != -1: data['mappingType']=self.mapping.getClassName() data['indexPairs']=lconcat(self.mapping.indexPairs) elif self.mapping.getClassName().find("SubsetMapping") != -1: data['mappingType']=self.mapping.getClassName() data['indices']=lconcat(self.mapping.indices) # add some topology data if existing if not self.mesh is None: # data['edges']=self.mesh.edges # data['triangles']=self.mesh.triangles # data['quads']=self.mesh.quads data['hexahedra']=lconcat(self.mesh.hexahedra) data['tetrahedra']=lconcat(self.mesh.tetrahedra) # add mass data if existing if not self.mass is None: data['totalMass']=self.mass.totalMass with open(filename, 'w') as f: json.dump(data, f) if printLog: Sofa.msg_info("Flexible.API.FEMDof",'Exported FEM Dof to '+filename)
def insertRigid(parentNode, rigidModel, density, scale=1, param=None): """ create a StructuralAPI.RigidBody from the rigidModel. The model geometry is scaled with scale. The rigidMass is computed from: 1) mass, com and inertia if present 2) mesh if possible 3) default to a unit sphere TODO: is it relevant to do so ? """ if printLog: Sofa.msg_info("Compliant.sml","insertRigid "+rigidModel.name) for mesh in rigidModel.mesh : if rigidModel.meshAttributes[mesh.id].collision is True: Sofa.msg_info("Compliant.sml"," collision mesh: "+mesh.name) rigid = StructuralAPI.RigidBody(parentNode, rigidModel.name) if not rigidModel.mass is None and not rigidModel.com is None and not rigidModel.inertia is None: if not 1==scale: Sofa.msg_info("Compliant.sml","scale is not supported in that case") # all inertial data is present, let's use it massinfo = SofaPython.mass.RigidMassInfo() massinfo.mass = rigidModel.mass # TODO: convert units ? massinfo.com = rigidModel.com # TODO: convert units ? if len(rigidModel.inertia)==3 and not rigidModel.inertia_rotation is None: massinfo.diagonal_inertia = rigidModel.inertia massinfo.inertia_rotation = rigidModel.inertia_rotation else: massinfo.setFromInertia(rigidModel.inertia[0], rigidModel.inertia[1], rigidModel.inertia[2], # Ixx, Ixy, Ixz rigidModel.inertia[3], rigidModel.inertia[4], # Iyy, Iyz rigidModel.inertia[5] ) # Izz rigid.setFromRigidInfo(massinfo, offset=rigidModel.position, inertia_forces = False ) # TODO: handle inertia_forces ? elif len(rigidModel.mesh)!=0 : # get inertia from meshes and density rigid.setFromRigidInfo(rigidModel.getRigidMassInfo(density, scale), offset=StructuralAPI.scaleOffset(scale, rigidModel.position), inertia_forces = False ) # TODO: handle inertia_forces ? #if not rigidModel.mass is None : ## no density but a mesh let's normalise computed mass with specified mass #mass= SofaPython.units.mass_from_SI(rigidModel.mass) #inertia = [] #for inert,m in zip(rigid.mass.inertia, rigid.mass.mass): #for i in inert: #inertia.append( i/m[0]*mass) #rigid.mass.inertia = concat(inertia) #rigid.mass.mass = mass else: # no mesh, get mass/inertia if present, default to a unit sphere Sofa.msg_warning("Compliant.sml","insertRigid: using default rigidMass") mass = rigidModel.mass if not rigidModel.mass is None else SofaPython.units.mass_from_SI(1.) inertia = scale*scale*[1,1,1] t = scale*rigidModel.position if not rigidModel.com is None: t[0] += scale*rigidModel.com[0] t[1] += scale*rigidModel.com[1] t[2] += scale*rigidModel.com[2] rigid.setManually(t, mass, inertia) if not param is None: rigid.dofs.showObject = param.showRigid rigid.dofs.showObjectScale = SofaPython.units.length_from_SI(param.showRigidScale) # walk around to handle multiple meshes # @todo: handle them in StructuralAPI ? rigid.collisions=dict() rigid.visuals=dict() for mesh in rigidModel.mesh : if rigidModel.meshAttributes[mesh.id].collision is True: rigid.collisions[mesh.id] = rigid.addCollisionMesh(mesh.source,name_suffix='_'+mesh.name, scale3d=[scale]*3) if rigidModel.meshAttributes[mesh.id].visual is True: rigid.visuals[mesh.id] = rigid.collisions[mesh.id].addVisualModel() elif rigidModel.meshAttributes[mesh.id].visual is True: rigid.visuals[mesh.id] = rigid.addVisualModel(mesh.source,name_suffix='_'+mesh.name, scale3d=[scale]*3) return rigid
def createScene(rootNode): Sofa.msg_info("Message with emitter='SofaPython'") Sofa.msg_info("Hello", "Message with emitter='Hello'") Sofa.msg_info(rootNode, "Message with emitter='rootNode'") Sofa.msg_error("Message with emitter='SofaPython'") Sofa.msg_error("Hello", "Message with emitter='Hello'") Sofa.msg_error(rootNode, "Message with emitter='rootNode'") Sofa.msg_info("Message with emitter='SofaPython'", __file__, 1) Sofa.msg_info("Hello", "Message with emitter='Hello'",__file__, 1) Sofa.msg_info(rootNode, "Message with emitter='rootNode'",__file__, 1) Sofa.msg_error("Message with emitter='SofaPython'",__file__, 1) Sofa.msg_error("Hello", "Message with emitter='Hello'",__file__, 1) Sofa.msg_error(rootNode, "Message with emitter='rootNode'",__file__, 1)
def onEndAnimationStep(self, dt): Sofa.msg_info("onEndAnimationStep") self.sendSuccess()
def setManually(self, filepath=None, offset=[[0,0,0,0,0,0,1]], voxelSize=0.01, density=1000, mass=1, inertia=[1,1,1], inertia_forces=False, generatedDir=None): if len(offset) == 0: Sofa.msg_error("RigidScale.API","ShearlessAffineBody should have at least 1 ShearLessAffine") return self.framecom = Frame.Frame() self.bodyOffset = Frame.Frame([0,0,0,0,0,0,1]) path_affine_rigid = '@' + Tools.node_path_rel(self.affineNode, self.rigidNode) path_affine_scale = '@' + Tools.node_path_rel(self.affineNode, self.scaleNode) if len(offset) == 1: self.frame = [Frame.Frame(offset[0])] str_position = "" for p in offset: str_position = str_position + concat(p) + " " ### scene creation # rigid dof self.rigidDofs = self.rigidNode.createObject('MechanicalObject', template='Rigid3'+template_suffix, name='dofs', position=str_position, rest_position=str_position) # scale dofs self.scaleDofs = self.scaleNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='dofs', position=concat([1,1,1]*len(offset))) # The positiveNode is now commented for the moment since it seems not working """positiveNode = self.scaleNode.createChild('positive') positiveNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='positivescaleDOFs') positiveNode.createObject('DifferenceFromTargetMapping', template='Vec3'+template_suffix+',Vec3'+template_suffix, applyRestPosition=1, targets=concat(target_scale)) positiveNode.createObject('UniformCompliance', isCompliance=1, compliance=0) positiveNode.createObject('UnilateralConstraint') positiveNode.createObject('Stabilization', name='Stabilization')""" # affine dofs self.affineDofs = self.affineNode.createObject('MechanicalObject', template='Affine', name='parent', showObject=0) self.affineNode.createObject('RigidScaleToAffineMultiMapping', template='Rigid,Vec3,Affine', input1=path_affine_rigid, input2=path_affine_scale, output='@.', autoInit='1', printLog='0') if filepath: self.image = SofaImage.API.Image(self.rigidNode, name="image_" + self.name, imageType="ImageUC") self.shapeFunction = Flexible.API.ShapeFunction(self.affineNode) if generatedDir is None: self.image.addMeshLoader(filepath, value=1, insideValue=1) # TODO support multiple meshes closingValue=1, self.image.addMeshToImage(voxelSize) self.shapeFunction.addVoronoi(self.image, position='@dofs.rest_position') # mass self.affineMassNode = self.affineNode.createChild('mass') self.affineMassNode.createObject('TransferFunction', name='density', template='ImageUC,ImageD', inputImage='@' + Tools.node_path_rel(self.affineMassNode, self.image.node) + '/image.image', param='0 0 1 '+str(density)) self.affineMassNode.createObject('MechanicalObject', template='Vec3'+template_suffix) self.affineMassNode.createObject('LinearMapping', template='Affine,Vec3'+template_suffix) self.affineMassNode.createObject('MassFromDensity', name='MassFromDensity', template='Affine,ImageD', image='@density.outputImage', transform='@' + Tools.node_path_rel(self.affineMassNode, self.image.node) + '/image.transform', lumping='0') self.mass = self.affineNode.createObject('AffineMass', massMatrix='@mass/MassFromDensity.massMatrix') else: self.image.addContainer(filename=self.node.name + "_rasterization.raw", directory=generatedDir) self.shapeFunction.shapeFunction = serialization.importImageShapeFunction(self.affineNode, generatedDir+self.node.name+"_SF_indices.raw", generatedDir+self.node.name+"_SF_weights.raw", 'dofs') self.mass = serialization.importAffineMass(self.affineNode, generatedDir+self.node.name+"_affinemass.json") # computation of the object mass center massInfo = SofaPython.mass.RigidMassInfo() massInfo.setFromMesh(filepath, density, [1,1,1]) # get the object mass center self.framecom.rotation = massInfo.inertia_rotation self.framecom.translation = massInfo.com else: if (mass and inertia) and inertia != [0,0,0]: Sofa.msg_info("RigidScale", "A RigidMass and a UniformMass are created for respectively the rigid and the scale since there is no mesh which can be used to compute the model mass.") self.mass = self.rigidNode.createObject('RigidMass', name='mass', mass=mass, inertia=concat(inertia[:3]), inertia_forces=inertia_forces) self.scaleNode.createObject('UniformMass', name='mass', mass=mass) self.frame = [] for o in offset: self.frame.append(Frame.Frame(o))