Exemple #1
0
 def __init__(self,
              node,
              filepath,
              scale3d,
              offset,
              name_suffix='',
              generatedDir=None):
     r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi
     global idxVisualModel
     self.node = node.createChild('visual' + name_suffix)  # node
     self.model = self.node.createObject('VisualModel',
                                         name='visual' +
                                         str(idxVisualModel),
                                         fileMesh=filepath,
                                         scale3d=concat(scale3d),
                                         translation=concat(offset[:3]),
                                         rotation=concat(r))
     if generatedDir is None:
         self.mapping = self.node.createObject(
             'LinearMapping',
             template='Affine,ExtVec3f',
             name='mapping')
     else:
         serialization.importLinearMapping(
             self.node, generatedDir + "_visualmapping.json")
     idxVisualModel += 1
Exemple #2
0
 def __init__(self,
              node,
              filepath,
              scale3d,
              offset,
              name_suffix='',
              generatedDir=None):
     r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi
     self.node = node.createChild('collision' + name_suffix)  # node
     self.loader = SofaPython.Tools.meshLoader(self.node,
                                               filename=filepath,
                                               name='loader',
                                               scale3d=concat(scale3d),
                                               translation=concat(
                                                   offset[:3]),
                                               rotation=concat(r),
                                               triangulate=True)
     self.topology = self.node.createObject('MeshTopology',
                                            name='topology',
                                            src='@loader')
     self.dofs = self.node.createObject('MechanicalObject',
                                        name='dofs',
                                        template='Vec3' +
                                        template_suffix)
     self.triangles = self.node.createObject('TriangleModel',
                                             name='model')
     if generatedDir is None:
         self.mapping = self.node.createObject('LinearMapping',
                                               template='Affine,Vec3' +
                                               template_suffix,
                                               name='mapping')
     else:
         serialization.importLinearMapping(
             self.node, generatedDir + "_collisionmapping.json")
     self.normals = None
Exemple #3
0
 def addMotor(self, forces=[0, 0, 0, 0, 0, 0]):
     ## adding a constant force/torque to the rigid body (that could be driven by a controller to simulate a motor)
     return self.rigidNode.createObject('ConstantForceField',
                                        template='Rigid3' + template_suffix,
                                        name='motor',
                                        indices='0',
                                        forces=concat(forces))
Exemple #4
0
 def addMotor(self, forces=[0, 0, 0, 0, 0, 0]):
     ## adding a constant force/torque at the offset location (that could be driven by a controller to simulate a motor)
     return self.node.createObject('ConstantForceField',
                                   template='Rigid3' + template_suffix,
                                   name='motor',
                                   points='0',
                                   forces=concat(forces))
Exemple #5
0
    def setManually(self, filepath=None, offset=[[0,0,0,0,0,0,1]], voxelSize=0.01, density=1000, 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)))
        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.affineNode, 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, scale=scale3d)  # 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='@../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='@../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:
            print "You need a mesh to create an articulated system"
        self.frame = []
        for o in offset:
            self.frame.append(Frame.Frame(o))
Exemple #6
0
 def __init__(self, node, color=[1, 1, 1, 1]):
     global idxVisualModel
     self.node = node.createChild('visual')  # node
     self.visual = self.node.createObject(
         'VisualModel',
         name='model' + str(idxVisualModel),
         color=concat(color)
     )  # @to do: Add the filename in order to keep the texture coordinates otherwise we lost them ...
     self.mapping = self.node.createObject('IdentityMapping',
                                           name='mapping')
     idxVisualModel += 1
Exemple #7
0
 def addSkinning(self,
                 node,
                 armatureNode,
                 indices,
                 weights,
                 assemble=True,
                 isMechanical=True):
     """ Add skinning (linear) mapping based on the armature (Rigid3) in armatureNode using
     """
     self.mapping = node.createObject("LinearMapping",
                                      template="Affine,Vec3",
                                      name="mapping",
                                      input="@" +
                                      armatureNode.getPathName(),
                                      indices=concat(indices),
                                      weights=concat(weights),
                                      assemble=assemble,
                                      mapForces=isMechanical,
                                      mapConstraints=isMechanical,
                                      mapMasses=isMechanical)
Exemple #8
0
 def __init__(self, node, name, position):
     self.node = node.createChild(name)
     self.dofs = self.node.createObject('MechanicalObject',
                                        name='dofs',
                                        template='Vec3' +
                                        template_suffix,
                                        position=concat(position))
     self.mapping = self.node.createObject(
         'LinearMapping',
         name='mapping',
         geometricStiffness=geometric_stiffness)
Exemple #9
0
 def addVisualModel(self,
                    filepath,
                    scale3d=[1, 1, 1],
                    offset=[0, 0, 0, 0, 0, 0, 1],
                    name_suffix='',
                    generatedDir=None,
                    color=[1, 1, 1, 1]):
     ## adding a visual model to the rigid body with a relative offset
     self.visual = ShearlessAffineBody.VisualModel(
         self.affineNode,
         filepath,
         scale3d, (self.bodyOffset * Frame.Frame(offset)).offset(),
         name_suffix,
         generatedDir=generatedDir,
         color=concat(color))
     return self.visual
Exemple #10
0
    def setMeshLess(self, offset=[[0,0,0,0,0,0,1]], mass=1, rayleigh=0.1, 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)
        self.rigidNode.createObject('UniformMass', totalMass=mass, rayleighStiffness=rayleigh);

        # scale dofs

        self.scaleDofs = self.scaleNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='dofs', position= concat([1,1,1]*len(offset)))
        self.scaleNode.createObject('UniformMass', totalMass=mass, rayleighStiffness=rayleigh);
        #positiveNode = self.scaleNode.createChild('positive')
        #positiveNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='positivescaleDOFs')
        #target_scale = [0.5,0.5,0.5]
        #positiveNode.createObject('DifferenceFromTargetMapping', template='Vec3d,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')
        self.affineNode.createObject('RigidScaleToAffineMultiMapping', template='Rigid,Vec3,Affine', input1=path_affine_rigid, input2=path_affine_scale, output='@.', autoInit='1', printLog='0')
        
        self.frame = []
        for o in offset:
            self.frame.append(Frame.Frame(o))
Exemple #11
0
    def setMeshLess(self, offset=[[0,0,0,0,0,0,1]], mass=1, rayleigh=0.1, 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)
        self.rigidNode.createObject('UniformMass', totalMass=mass, rayleighStiffness=rayleigh);

        # scale dofs

        self.scaleDofs = self.scaleNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='dofs', position= concat([1,1,1]*len(offset)))
        self.scaleNode.createObject('UniformMass', totalMass=mass, rayleighStiffness=rayleigh);
        #positiveNode = self.scaleNode.createChild('positive')
        #positiveNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='positivescaleDOFs')
        #target_scale = [0.5,0.5,0.5]
        #positiveNode.createObject('DifferenceFromTargetMapping', template='Vec3d,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')
        self.affineNode.createObject('RigidScaleToAffineMultiMapping', template='Rigid,Vec3,Affine', input1=path_affine_rigid, input2=path_affine_scale, output='@.', autoInit='1', printLog='0')
        
        self.frame = []
        for o in offset:
            self.frame.append(Frame.Frame(o))
Exemple #12
0
    def setFromMesh(self, filepath, density=1000, offset=[0,0,0,0,0,0,1], scale3d=[1,1,1], voxelSize=0.01, numberOfPoints=1, generatedDir=None):
        # variables
        self.bodyOffset = Frame.Frame(offset)
        path_affine_rigid = '@' + Tools.node_path_rel(self.affineNode, self.rigidNode)
        path_affine_scale = '@' + Tools.node_path_rel(self.affineNode, self.scaleNode)
        massInfo = SofaPython.mass.RigidMassInfo()
        massInfo.setFromMesh(filepath, density, scale3d)

        self.image = SofaImage.API.Image(self.node, name="image_" + self.name, imageType="ImageUC")
        self.image.node.addChild(self.affineNode)  # for initialization
        self.image.node.addChild(self.rigidNode)  # for initialization
        self.shapeFunction = Flexible.API.ShapeFunction(self.rigidNode)

        if generatedDir is None:
            self.image.addMeshLoader(filepath, value=1, insideValue=1, offset=offset, scale=scale3d) # TODO support multiple meshes closingValue=1,
            self.image.addMeshToImage(voxelSize)
            # rigid dofs
            self.sampler = SofaImage.API.Sampler(self.rigidNode)
            self.sampler.addImageSampler(self.image, numberOfPoints)
            self.rigidDofs = self.sampler.addMechanicalObject('Rigid3'+template_suffix)
        else:
            self.image.addContainer(filename=self.node.name+"_rasterization.raw", directory=generatedDir)
            self.rigidDofs = serialization.importRigidDofs(self.rigidNode, generatedDir+"/"+self.node.name+'_dofs.json')

        # scale dofs
        self.scaleDofs = self.scaleNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='dofs', position=concat([1,1,1]*numberOfPoints))
        positiveNode = self.scaleNode.createChild('positive')
        positiveNode.createObject('MechanicalObject', template='Vec3'+template_suffix, name='positivescaleDOFs')
        positiveNode.createObject('DifferenceFromTargetMapping', template='Vec3d,Vec3'+template_suffix, applyRestPosition=1, targets=concat(target_scale))
        positiveNode.createObject('UniformCompliance', isCompliance=1, compliance=0)
        positiveNode.createObject('UnilateralConstraint')

        # affine dofs
        self.affineDofs = self.affineNode.createObject('MechanicalObject', template='Affine', name='dofs')
        self.affineNode.createObject('RigidScaleToAffineMultiMapping', template='Rigid,Vec3d,Affine', input1=path_affine_rigid, input2=path_affine_scale, output='@.', autoInit='1', printLog='0')

        # shapefunction and mass
        if generatedDir is None:
            self.shapeFunction.addVoronoi(self.image, position='@dofs.rest_position')
            # mass
            densityImage = self.image.createTransferFunction(self.affineNode, "density", param='0 0 1 '+str(density))
            affineMass = Flexible.API.AffineMass(self.affineNode)
            affineMass.massFromDensityImage(self.affineNode, densityImage=densityImage)
            self.mass = affineMass.mass
        else:
            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")

        # hack to get the frame position
        self.node.init()
        for p in self.rigidDofs.position:
            p.extend([0,0,0,1])
            self.frame.append(Frame.Frame(p))
Exemple #13
0
 def __init__(self, node, name, position):
     self.node = node.createChild(name)
     self.dofs = self.node.createObject('MechanicalObject', name='dofs', template='Vec3'+template_suffix, position=concat(position))
     self.mapping = self.node.createObject('LinearMapping', name='mapping', geometricStiffness = geometric_stiffness)
Exemple #14
0
 def addMotor(self, forces=[0,0,0,0,0,0]):
     ## adding a constant force/torque at the offset location (that could be driven by a controller to simulate a motor)
     return self.node.createObject('ConstantForceField', template='Rigid3'+template_suffix, name='motor', points='0', forces=concat(forces))
Exemple #15
0
 def __init__(self, node, filepath, scale3d, offset, name_suffix='', generatedDir=None):
     r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi
     global idxVisualModel;
     self.node = node.createChild('visual'+name_suffix)  # node
     self.model = self.node.createObject('VisualModel', name='visual'+str(idxVisualModel), fileMesh=filepath, scale3d=concat(scale3d), translation=concat(offset[:3]), rotation=concat(r))
     if generatedDir is None:
         self.mapping = self.node.createObject('LinearMapping', template='Affine,ExtVec3f', name='mapping')
     else:
         serialization.importLinearMapping(self.node, generatedDir+"_visualmapping.json")
     idxVisualModel+=1
Exemple #16
0
 def __init__(self, node, filepath, scale3d, offset, name_suffix='', generatedDir=None):
     r = Quaternion.to_euler(offset[3:]) * 180.0 / math.pi
     self.node = node.createChild('collision'+name_suffix)  # node
     self.loader = SofaPython.Tools.meshLoader(self.node, filename=filepath, name='loader', scale3d=concat(scale3d), translation=concat(offset[:3]) , rotation=concat(r), triangulate=True)
     self.topology = self.node.createObject('MeshTopology', name='topology', src='@loader')
     self.dofs = self.node.createObject('MechanicalObject', name='dofs', template='Vec3'+template_suffix)
     self.triangles = self.node.createObject('TriangleModel', name='model')
     if generatedDir is None:
         self.mapping = self.node.createObject('LinearMapping', template='Affine,Vec3'+template_suffix, name='mapping')
     else:
         serialization.importLinearMapping(self.node, generatedDir+"_collisionmapping.json")
     self.normals = None
Exemple #17
0
    def setFromMesh(self,
                    filepath,
                    density=1000,
                    offset=[0, 0, 0, 0, 0, 0, 1],
                    scale3d=[1, 1, 1],
                    voxelSize=0.01,
                    numberOfPoints=1,
                    generatedDir=None):
        # variables
        self.bodyOffset = Frame.Frame(offset)
        path_affine_rigid = '@' + Tools.node_path_rel(self.affineNode,
                                                      self.rigidNode)
        path_affine_scale = '@' + Tools.node_path_rel(self.affineNode,
                                                      self.scaleNode)
        massInfo = SofaPython.mass.RigidMassInfo()
        massInfo.setFromMesh(filepath, density, scale3d)

        self.image = SofaImage.API.Image(self.node,
                                         name="image_" + self.name,
                                         imageType="ImageUC")
        self.image.node.addChild(self.affineNode)  # for initialization
        self.image.node.addChild(self.rigidNode)  # for initialization
        self.shapeFunction = Flexible.API.ShapeFunction(self.rigidNode)

        if generatedDir is None:
            self.image.addMeshLoader(
                filepath, value=1, insideValue=1, offset=offset,
                scale=scale3d)  # TODO support multiple meshes closingValue=1,
            self.image.addMeshToImage(voxelSize)
            # rigid dofs
            self.sampler = SofaImage.API.Sampler(self.rigidNode)
            self.sampler.addImageSampler(self.image, numberOfPoints)
            self.rigidDofs = self.sampler.addMechanicalObject('Rigid3' +
                                                              template_suffix)
        else:
            self.image.addContainer(filename=self.node.name +
                                    "_rasterization.raw",
                                    directory=generatedDir)
            self.rigidDofs = serialization.importRigidDofs(
                self.rigidNode,
                generatedDir + "/" + self.node.name + '_dofs.json')

        # scale dofs
        self.scaleDofs = self.scaleNode.createObject(
            'MechanicalObject',
            template='Vec3' + template_suffix,
            name='dofs',
            position=concat([1, 1, 1] * numberOfPoints))
        positiveNode = self.scaleNode.createChild('positive')
        positiveNode.createObject('MechanicalObject',
                                  template='Vec3' + template_suffix,
                                  name='positivescaleDOFs')
        positiveNode.createObject('DifferenceFromTargetMapping',
                                  template='Vec3d,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='dofs')
        self.affineNode.createObject('RigidScaleToAffineMultiMapping',
                                     template='Rigid,Vec3d,Affine',
                                     input1=path_affine_rigid,
                                     input2=path_affine_scale,
                                     output='@.',
                                     autoInit='1',
                                     printLog='0')

        # shapefunction and mass
        if generatedDir is None:
            self.shapeFunction.addVoronoi(self.image,
                                          position='@dofs.rest_position')
            # mass
            densityImage = self.image.createTransferFunction(self.affineNode,
                                                             "density",
                                                             param='0 0 1 ' +
                                                             str(density))
            affineMass = Flexible.API.AffineMass(self.affineNode)
            affineMass.massFromDensityImage(self.affineNode,
                                            densityImage=densityImage)
            self.mass = affineMass.mass
        else:
            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")

        # hack to get the frame position
        self.node.init()
        for p in self.rigidDofs.position:
            p.extend([0, 0, 0, 1])
            self.frame.append(Frame.Frame(p))
Exemple #18
0
 def addSkinning(self, node, armatureNode, indices, weights, assemble=True, isMechanical=True):
     """ Add skinning (linear) mapping based on the armature (Rigid3) in armatureNode using
     """
     self.mapping = node.createObject("LinearMapping", template="Affine,Vec3", name="mapping", input="@"+armatureNode.getPathName(), indices=concat(indices), weights=concat(weights), assemble=assemble, mapForces=isMechanical, mapConstraints=isMechanical, mapMasses=isMechanical)
Exemple #19
0
    def setManually(self,
                    filepath=None,
                    offset=[[0, 0, 0, 0, 0, 0, 1]],
                    voxelSize=0.01,
                    density=1000,
                    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)))
        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.affineNode,
                                             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='@../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='@../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:
            print "You need a mesh to create an articulated system"
        self.frame = []
        for o in offset:
            self.frame.append(Frame.Frame(o))