Exemple #1
0
 def execute(self, context):
     objlist = []
     for obj in bpy.data.objects:
         if obj.phobostype == self.seltype:
             objlist.append(obj)
     selectionUtils.selectObjects(objlist, True)
     return {'FINISHED'}
Exemple #2
0
def bakeModel(objlist, path, modelname):
    visuals = [o for o in objlist if ("phobostype" in o and o.phobostype == "visual")]
    selectionUtils.selectObjects(visuals, active=0)
    log("Copying objects for joining...", "INFO")
    print("Copying objects for joining...")
    bpy.ops.object.duplicate(linked=False, mode='TRANSLATION')
    log("joining...", "INFO")
    print("joining...")
    bpy.ops.object.join()
    obj = bpy.context.active_object
    log("Deleting vertices...", "INFO")
    print("Deleting vertices...")
    bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.select_all(action='TOGGLE')
    bpy.ops.mesh.select_all(action='TOGGLE')
    bpy.ops.mesh.remove_doubles()
    bpy.ops.object.editmode_toggle()
    log("Adding modifier...", "INFO")
    print("Adding modifier...")
    bpy.ops.object.modifier_add(type='DECIMATE')
    bpy.context.object.modifiers["Decimate"].decimate_type = 'DISSOLVE'
    log("Applying modifier...", "INFO")
    print("Applying modifier...")
    bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Decimate")
    name = "bake.stl"
    obj.name = name
    bpy.ops.export_mesh.stl(filepath=os.path.join(path, name))
    obj.select = True
    bpy.ops.object.delete()
    log("Done baking...", "INFO")
    print("Done baking...")
Exemple #3
0
def deriveStoredPoses():
    """
    """
    poses_dict = {}
    if len(bpy.data.actions) == 0:
        return {}
    pose_lib_name = bpy.data.actions.keys()[0]
    some_obj = bpy.context.scene.objects.active
    bpy.ops.object.mode_set(mode='OBJECT')
    for pose_name, i in zip(bpy.data.actions[pose_lib_name].pose_markers.keys(), range(len(bpy.data.actions[pose_lib_name].pose_markers.keys()))):
        selectionUtils.selectObjects([selectionUtils.getRoot(some_obj)], clear=True, active=0)
        pose_dict = {}
        bpy.ops.object.mode_set(mode='POSE')
        bpy.ops.poselib.apply_pose(pose_index=i)
        bpy.ops.object.mode_set(mode='OBJECT')
        for obj in bpy.context.scene.objects:
            if obj.phobostype == 'link':
                selectionUtils.selectObjects([obj], clear=True, active=0)
                bpy.ops.object.mode_set(mode='POSE')
                obj.pose.bones['Bone'].rotation_mode = 'XYZ'
                y_angle = obj.pose.bones['Bone'].rotation_euler.y
                bpy.ops.object.mode_set(mode='OBJECT')
                pose_dict[obj.name] = y_angle
        poses_dict[pose_name] = pose_dict

    return poses_dict
Exemple #4
0
    def execute(self, context):
        """

        Args:
          context: 

        Returns:

        """
        root = sUtils.getRoot(context.selected_objects[0])

        modelsPosesColl = bUtils.getPhobosPreferences().models_poses
        activeModelPoseIndex = bpy.context.scene.active_ModelPose
        selected_robot = modelsPosesColl[bpy.data.images[activeModelPoseIndex].name]

        objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False)
        sUtils.selectObjects([root] + objectlist, clear=True, active=0)
        models.loadPose(selected_robot.robot_name, selected_robot.label)
        parameter = self.decimate_ratio
        if self.decimate_type == 'UNSUBDIV':
            parameter = self.decimate_iteration
        elif self.decimate_type == 'DISSOLVE':
            parameter = self.decimate_angle_limit
        exporter.bakeModel(
            objectlist,
            root['model/name'],
            selected_robot.label,
            decimate_type=self.decimate_type,
            decimate_parameter=parameter,
        )
        sUtils.selectObjects([root] + objectlist, clear=True, active=0)
        bpy.ops.scene.reload_models_and_poses_operator()
        return {'FINISHED'}
Exemple #5
0
def createInertial(obj):
    """Creates an empty inertial object with the same world transform as the corresponding
    object and parents it to the correct link.

    :param obj: The object you want to copy the world transform from.
    :type obj: blender object.
    :return: blender object -- the newly created inertia.

    """
    if obj.phobostype == 'link':
        parent = obj
        size = (0.04, 0.04, 0.04)
    else:
        parent = obj.parent
        size = (0.02, 0.02, 0.02)
    rotation = obj.matrix_world.to_euler()
    center = obj.matrix_world.to_translation()
    inertial = blenderUtils.createPrimitive('inertial_' + obj.name, 'box', size,
                                   defs.layerTypes["inertial"], 'phobos_inertial', center, rotation)
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    inertial.phobostype = 'inertial'
    bpy.ops.object.select_all(action="DESELECT")
    #utility.selectObjects([inertial], True, 0)

    selectionUtils.selectObjects([parent, inertial], True, 0)
    #bpy.context.scene.objects.active = parent.pose.bones[0]
    bpy.ops.object.parent_set(type='BONE_RELATIVE')
    return inertial
Exemple #6
0
    def execute(self, context):
        """

        Args:
          context: 

        Returns:

        """
        log("Jumping to object " + self.objectname + ".", 'DEBUG')

        # switch the scene if the object is anywhere else
        scene = None
        if self.objectname not in context.scene:
            for sce in bpy.data.scenes:
                if self.objectname in sce.objects:
                    scene = sce
                    break
            else:
                log("Could not find scene of object {}. Aborted.".format(self.objectname), 'ERROR')
                return {'CANCELLED'}
            bUtils.switchToScene(scene.name)

        # toggle layer to make object visible
        bUtils.setObjectLayersActive(scene.objects[self.objectname], extendlayers=True)

        sUtils.selectObjects([scene.objects[self.objectname]], clear=True, active=0)
        return {'FINISHED'}
Exemple #7
0
    def execute(self, context):
        """

        Args:
          context: 

        Returns:

        """
        objects = context.selected_objects
        annotation = defs.definitions[self.annotationtype][self.devicetype]

        # add annotation (objects) to the selected objects
        annot_objects = []
        for obj in objects:
            if self.asObject:
                annot_objects.append(
                    eUtils.addAnnotationObject(
                        obj,
                        annotation,
                        name=obj.name + '_annotation',
                        namespace=self.annotationtype.rstrip('s'),
                    )
                )
            else:
                eUtils.addAnnotation(obj, annotation, namespace=self.annotationtype.rstrip('s'))

        # reselect the original objects and additional annotation objects
        sUtils.selectObjects(objects + annot_objects, clear=True)
        bUtils.toggleLayer(defs.layerTypes['annotation'], value=True)
        return {'FINISHED'}
Exemple #8
0
    def execute(self, context):
        """

        Args:
          context: 

        Returns:

        """
        selection = []
        if self.modelname:
            log("phobos: Selecting model" + self.modelname, "INFO")
            roots = sUtils.getRoots()
            for root in roots:
                if nUtils.getModelName(root) == self.modelname:
                    selection = sUtils.getChildren(root)
        else:
            log("No model name provided, deriving from selection...", "INFO")
            roots = set()
            for obj in bpy.context.selected_objects:
                roots.add(sUtils.getRoot(obj))
            for root in list(roots):
                selection.extend(sUtils.getChildren(root))
        sUtils.selectObjects(list(selection), True)
        return {'FINISHED'}
Exemple #9
0
    def execute(self, context):
        """

        Args:
          context: 

        Returns:

        """
        roots = set()

        # add root object of each selected object
        for obj in context.selected_objects:
            roots.add(sUtils.getRoot(obj))

        # select all found root objects
        if roots:
            # toggle layer to make objects visible
            for root in roots:
                bUtils.setObjectLayersActive(root, extendlayers=True)

            # select objects
            sUtils.selectObjects(list(roots), True)
            context.scene.objects.active = list(roots)[0]
        else:
            log("Couldn't find any root object.", 'ERROR')
        return {'FINISHED'}
Exemple #10
0
def createInertials(link, empty=False, preserve_children=False):
    """Creates inertial representations for visual and collision objects in link.

    :param link: The link you want to create the inertial for.
    :type link: bpy_types.Object
    :param empty: If set to True the new inertial object will contain no information.
    :type empty: bool
    :param preserve_children: If set to False already existent inertial objects will be deleted.
    :type preserve_children: bool

    """
    #
    viscols = getInertiaRelevantObjects(link)
    # clean existing data
    if not preserve_children:
        oldinertials = selectionUtils.getImmediateChildren(link, ['inertial'])
    else:
        try:
            oldinertials = [bpy.data.objects['inertial_'+link.name]]
        except KeyError:
            oldinertials = None
    if oldinertials:
        selectionUtils.selectObjects(oldinertials, clear=True, active=0)
        bpy.ops.object.delete()
    if not preserve_children:
        for obj in viscols:
            if not empty:
                mass = obj['mass'] if 'mass' in obj else None
                geometry = robotdictionary.deriveGeometry(obj)
                if mass is not None:
                    if geometry['type'] == 'mesh':
                        selectionUtils.selectObjects([obj])
                        bpy.context.scene.objects.active = obj
                        inert = calculateMeshInertia(obj.data, mass)
                        #print('mesh:', inert)
                        #print('ellipsoid:', calculateEllipsoidInertia(mass, geometry['size']))
                        #print('box:', calculateBoxInertia(mass, geometry['size']))
                    else:
                        inert = calculateInertia(mass, geometry)
                    if inert is not None:
                        inertial = createInertial(obj)
                        inertial['mass'] = mass
                        inertial['inertia'] = inert
            else:
                createInertial(obj)
    # compose inertial object for link
    if not empty:
        mass, com, inert = fuseInertiaData(selectionUtils.getImmediateChildren(link, ['inertial']))
        if mass and com and inert:
            inertial = createInertial(link)
            com_translate = mathutils.Matrix.Translation(com)
            inertial.matrix_local = com_translate
            bpy.ops.transform.translate(value=(0, 0, 0))  # FIXME: this is a trick to force Blender to apply matrix_local
            inertial['inertial/mass'] = mass
            inertial['inertial/inertia'] = inertiaMatrixToList(inert)
    else:
        createInertial(link)
Exemple #11
0
        def execute(self, context):
            """

            Args:
              context: 

            Returns:

            """
            phobos_dict = ioUtils.getDictFromYamlDefs(
                self.phobostype, self.preset_name, self.obj_name
            )
            selected_objs = context.selected_objects

            # store collected object data properties in the props dictionary
            for i in range(len(self.phobos_data)):
                if self.phobos_data[i].name[0] == 'b':
                    store = '$' + str(bool(self.phobos_data[i]['boolProp'])).lower()
                elif self.phobos_data[i].name[0] == 'i':
                    store = self.phobos_data[i]['intProp']
                elif self.phobos_data[i].name[0] == 's':
                    store = self.phobos_data[i]['stringProp']
                elif self.phobos_data[i].name[0] == 'f':
                    store = self.phobos_data[i]['floatProp']

                phobos_dict['props'][self.phobos_data[i].name[2:]] = store

            annotations = {}
            # add annotation objects for other categories
            for custom_anno in self.annotation_checks:
                if custom_anno.boolProp:
                    # parse object dictionaries if "$selected_objects:..." syntax is found
                    annot = defs.definitions[self.phobostype + 's'][self.preset_name][
                        custom_anno.name[2:]
                    ]

                    annotations[custom_anno.name[2:]] = linkObjectLists(annot, selected_objs)

            # let the exectute function handle the object creation
            new_objs, annot_objs, otherobjs = execute_func(
                phobos_dict, annotations, selected_objs, context.active_object, *args
            )

            # select the newly added objects
            sUtils.selectObjects(new_objs + annot_objs + otherobjs, clear=True, active=0)
            bUtils.toggleLayer(defs.layerTypes[self.phobostype], value=True)

            if annot_objs:
                bUtils.toggleLayer(defs.layerTypes['annotation'], value=True)

            # toggle layers for generic objects
            if otherobjs:
                for obj in otherobjs:
                    bUtils.toggleLayer(defs.layerTypes[obj.phobostype], value=True)

            return {'FINISHED'}
Exemple #12
0
        def execute(self, context):
            """

            Args:
              context: 

            Returns:

            """
            phobos_dict = ioUtils.getDictFromYamlDefs(
                self.phobostype, self.preset_name, self.obj_name
            )
            selected_objs = context.selected_objects

            # store collected object data properties in the props dictionary
            for i in range(len(self.phobos_data)):
                if self.phobos_data[i].name[0] == 'b':
                    store = '$' + str(bool(self.phobos_data[i]['boolProp'])).lower()
                elif self.phobos_data[i].name[0] == 'i':
                    store = self.phobos_data[i]['intProp']
                elif self.phobos_data[i].name[0] == 's':
                    store = self.phobos_data[i]['stringProp']
                elif self.phobos_data[i].name[0] == 'f':
                    store = self.phobos_data[i]['floatProp']

                phobos_dict['props'][self.phobos_data[i].name[2:]] = store

            annotations = {}
            # add annotation objects for other categories
            for custom_anno in self.annotation_checks:
                if custom_anno.boolProp:
                    # parse object dictionaries if "$selected_objects:..." syntax is found
                    annot = defs.definitions[self.phobostype + 's'][self.preset_name][
                        custom_anno.name[2:]
                    ]

                    annotations[custom_anno.name[2:]] = linkObjectLists(annot, selected_objs)

            # let the exectute function handle the object creation
            new_objs, annot_objs, otherobjs = execute_func(
                phobos_dict, annotations, selected_objs, context.active_object, *args
            )

            # select the newly added objects
            sUtils.selectObjects(new_objs + annot_objs + otherobjs, clear=True, active=0)
            bUtils.toggleLayer(self.phobostype, value=True)

            if annot_objs:
                bUtils.toggleLayer('annotation', value=True)

            # toggle layers for generic objects
            if otherobjs:
                for obj in otherobjs:
                    bUtils.toggleLayer(obj.phobostype, value=True)

            return {'FINISHED'}
Exemple #13
0
def createJoint(joint, linkobj=None):
    """Adds joint data to 'link' object.

    Args:
        joint (dict): dictionary containing the joint definition
        linkobj (bpy.types.Object): the obj of phobostype 'link' that receives the joint

    Returns:

    """
    # add joint information
    if not linkobj:
        linkobj = sUtils.getObjectByName(joint['child'])
        if isinstance(linkobj, list):
            log(
                "Could not identify object to define joint '{0}'.".format(
                    joint['name']), 'ERROR')
            return
    if joint['name'] != linkobj.name:
        linkobj['joint/name'] = joint['name']
    # get hold of object
    bUtils.toggleLayer(list(linkobj.layers).index(True),
                       True)  # any layer containing the object
    sUtils.selectObjects([linkobj], clear=True, active=0)

    # set axis
    if 'axis' in joint:
        if mathutils.Vector(tuple(joint['axis'])).length == 0.:
            log('Axis of joint {0} is of zero length: '.format(joint['name']),
                'ERROR')
        else:
            bpy.ops.object.mode_set(mode='EDIT')
            editbone = linkobj.data.edit_bones[0]
            length = editbone.length
            axis = mathutils.Vector(tuple(joint['axis']))
            editbone.tail = editbone.head + axis.normalized() * length

    # add constraints
    for param in ['effort', 'velocity']:
        try:
            if 'limits' in joint:
                linkobj['joint/max' + param] = joint['limits'][param]
        except KeyError:
            log("Joint limits incomplete for joint {0}".format(joint['name']),
                'ERROR')
    try:
        lower = joint['limits']['lower']
        upper = joint['limits']['upper']
    except KeyError:
        lower = 0.0
        upper = 0.0
    setJointConstraints(linkobj, joint['type'], lower, upper)
    for prop in joint:
        if prop.startswith('$'):
            for tag in joint[prop]:
                linkobj['joint/' + prop[1:] + '/' + tag] = joint[prop][tag]
Exemple #14
0
def addLight(light_dict):
    # DOCU add some docstring

    if light_dict['type'] == 'spotlight':
        light_type = 'SPOT'
    elif light_dict['type'] == 'omnilight':
        light_type = 'POINT'

    position = light_dict['pose']['translation']
    rotation = light_dict['pose']['rotation_euler']

    bpy.ops.object.lamp_add(type=light_type,
                            location=position,
                            rotation=rotation)
    light = bpy.context.active_object
    if 'parent' in light_dict:
        sUtils.selectObjects([light, bpy.data.objects[light_dict['parent']]],
                             clear=True,
                             active=1)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')

    light_data = light.data
    light.name = light_dict['name']

    colour_vals = ['r', 'g', 'b']
    colour_data = light_dict['color']['diffuse']
    light_data.color = [colour_data[v] for v in colour_vals]
    for v in colour_vals:
        if light_dict['color']['specular'][v] > 0:
            light_data.use_specular = True
            break

    if type == 'SPOT':
        light_data.spot_size = light_dict['angle']

    # TODO delete me?
    #if light_dict['attenuation']['constant'] > 0:
    light_data.energy = light_dict['attenuation']['constant']
    falloff = 'CONSTANT'
    if light_dict['attenuation']['linear'] > 0:
        light_data.linear_attenuation = light_dict['attenuation']['linear']
        falloff = 'INVERSE_LINEAR'
    if light_dict['attenuation']['quadratic'] > 0:
        light_data.quadratic_attenuation = light_dict['attenuation'][
            'quadratic']
        if falloff == 'INVERSE_LINEAR':
            falloff = 'LINEAR_QUADRATIC_WEIGHTED'
        else:
            falloff = 'INVERSE_SQUARE'
    light_data.falloff_type = falloff

    light.phobostype = 'light'
    light['light/exponent'] = light_dict['exponent']
    light.phobostype = 'light'
    light['light/directional'] = light_dict['directional']
    return light
Exemple #15
0
def dissolveLink(obj, delete_other=False):
    """Remove the selected link and reparent all links, inertia, visual and collisions to its effective Parent.

    Args:
      obj(bpy.types.Object): the link to dissolve
      delete_other: (Default value = False)

    Returns:

    """

    # Store original layers and show all layers
    originallayers = {}
    for name, coll in bpy.context.window.view_layer.layer_collection.children.items(
    ):
        originallayers[name] = coll.exclude
        coll.exclude = False

    if not obj.phobostype == 'link':
        log('Selected object {} is not a link!'.format(obj.name), 'ERROR')
        return

    else:
        delete = [obj]
        # Get all children
        children = sUtils.getRecursiveChildren(obj,
                                               phobostypes=('link', 'inertial',
                                                            'visual',
                                                            'collision'),
                                               include_hidden=True)

        if delete_other:
            other_children = sUtils.getRecursiveChildren(
                obj,
                recursion_depth=2,
                phobostypes=('motor', 'controller', 'sensor', 'submodel'),
                include_hidden=True,
            )
            delete += [
                child for child in other_children if child not in children
            ]

        # Get the parent
        parent = obj.parent
        # If parent is not None ( Root )
        if obj.parent:
            # Reparent
            parentObjectsTo(children, parent, clear=True)
            # Delete the objects
            sUtils.selectObjects(delete, clear=True, active=-1)
            bpy.ops.object.delete()
    # Restore original layers
    for key, value in originallayers.items():
        bpy.context.window.view_layer.layer_collection.children[
            key].exclude = value
Exemple #16
0
    def execute(self, context):
        """

        Args:
          context: 

        Returns:

        """
        sUtils.selectObjects(sUtils.getObjectsByPhobostypes([self.seltype]), True)
        return {'FINISHED'}
Exemple #17
0
 def execute(self, context):
     roots = set()
     for obj in bpy.context.selected_objects:
         roots.add(sUtils.getRoot(obj))
     if len(roots) > 0:
         sUtils.selectObjects(list(roots), True)
         bpy.context.scene.objects.active = list(roots)[0]
     else:
         # bpy.ops.error.message('INVOKE_DEFAULT', type="ERROR", message="Couldn't find any root object.")
         log("Couldn't find any root object.", "ERROR")
     return {'FINISHED'}
Exemple #18
0
 def execute(self, context):
     master = context.active_object
     slaves = context.selected_objects
     to_cadorigin = self.cursor_location - master.matrix_world.to_translation()
     com_shift_world = to_cadorigin + self.com_shift
     for s in slaves:
         selectionUtils.selectObjects([s], True, 0)
         context.scene.cursor_location = s.matrix_world.to_translation() + com_shift_world
         bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
     selectionUtils.selectObjects(slaves, True, slaves.index(master))
     context.scene.cursor_location = self.cursor_location.copy()
     return {'FINISHED'}
Exemple #19
0
def createInertial(inertialdict, obj, size=0.03, errors=None, adjust=False, logging=False):
    """Creates the Blender representation of a given inertial provided a dictionary.

    Args:
      inertialdict(dict): intertial data
      obj: 
      size: (Default value = 0.03)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:
      : bpy_types.Object -- newly created blender inertial object

    """
    if errors and not adjust:
        log('Can not create inertial object.', 'ERROR')

    try:
        origin = mathutils.Vector(inertialdict['pose']['translation'])
    except KeyError:
        origin = mathutils.Vector()

    # create new inertial object
    name = nUtils.getUniqueName('inertial_' + nUtils.getObjectName(obj), bpy.data.objects)
    inertialobject = bUtils.createPrimitive(
        name,
        'box',
        (size,) * 3,
        defs.layerTypes["inertial"],
        pmaterial='phobos_inertial',
        phobostype='inertial',
    )
    sUtils.selectObjects((inertialobject,), clear=True, active=0)
    bpy.ops.object.transform_apply(scale=True)

    # set position according to the parent link
    inertialobject.matrix_world = obj.matrix_world
    parent = obj
    if parent.phobostype != 'link':
        parent = sUtils.getEffectiveParent(obj, ignore_selection=True)
    eUtils.parentObjectsTo(inertialobject, parent)

    # position and parent the inertial object relative to the link
    # inertialobject.matrix_local = mathutils.Matrix.Translation(origin)
    sUtils.selectObjects((inertialobject,), clear=True, active=0)
    # bpy.ops.object.transform_apply(scale=True)

    # add properties to the object
    for prop in ('mass', 'inertia'):
        inertialobject['inertial/' + prop] = inertialdict[prop]
    return inertialobject
Exemple #20
0
def createInertial(inertialdict, obj, size=0.03, errors=None, adjust=False, logging=False):
    """Creates the Blender representation of a given inertial provided a dictionary.

    Args:
      inertialdict(dict): intertial data
      obj: 
      size: (Default value = 0.03)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:
      : bpy_types.Object -- newly created blender inertial object

    """
    if errors and not adjust:
        log('Can not create inertial object.', 'ERROR')

    try:
        origin = mathutils.Vector(inertialdict['pose']['translation'])
    except KeyError:
        origin = mathutils.Vector()

    # create new inertial object
    name = nUtils.getUniqueName('inertial_' + nUtils.getObjectName(obj), bpy.data.objects)
    inertialobject = bUtils.createPrimitive(
        name,
        'box',
        (size,) * 3,
        defs.layerTypes["inertial"],
        pmaterial='phobos_inertial',
        phobostype='inertial',
    )
    sUtils.selectObjects((inertialobject,), clear=True, active=0)
    bpy.ops.object.transform_apply(scale=True)

    # set position according to the parent link
    inertialobject.matrix_world = obj.matrix_world
    parent = obj
    if parent.phobostype != 'link':
        parent = sUtils.getEffectiveParent(obj, ignore_selection=True)
    eUtils.parentObjectsTo(inertialobject, parent)

    # position and parent the inertial object relative to the link
    # inertialobject.matrix_local = mathutils.Matrix.Translation(origin)
    sUtils.selectObjects((inertialobject,), clear=True, active=0)
    # bpy.ops.object.transform_apply(scale=True)

    # add properties to the object
    for prop in ('mass', 'inertia'):
        inertialobject['inertial/' + prop] = inertialdict[prop]
    return inertialobject
Exemple #21
0
def calculateInertia(obj,
                     mass,
                     geometry_dict=None,
                     errors=None,
                     adjust=False,
                     logging=False):
    """Calculates the inertia of an object using the specified mass and
       optionally geometry.

    Args:
      obj(bpy.types.Object): object to calculate inertia from
      mass(float): mass of object
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple): (Default value = None)
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple):
    tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:

    """
    if errors and not adjust:
        if logging:
            log("Can not calculate inertia from object.", 'ERROR')
        return None

    inertia = None
    if not geometry_dict:
        geometry = deriveGeometry(obj)

    # Get the rotation of the object
    object_rotation = obj.rotation_euler.to_matrix()

    if geometry['type'] == 'box':
        inertia = calculateBoxInertia(mass, geometry['size'])
    elif geometry['type'] == 'cylinder':
        inertia = calculateCylinderInertia(mass, geometry['radius'],
                                           geometry['length'])
    elif geometry['type'] == 'sphere':
        inertia = calculateSphereInertia(mass, geometry['radius'])
    elif geometry['type'] == 'mesh':
        sUtils.selectObjects((obj, ), clear=True, active=0)
        inertia = calculateMeshInertia(mass, obj.data, scale=obj.scale)

    # Correct the inertia orientation to account for Cylinder / mesh orientation issues
    inertia = object_rotation * inertiaListToMatrix(
        inertia) * object_rotation.transposed()

    return inertiaMatrixToList(inertia)
Exemple #22
0
 def execute(self, context):
     startLog(self)
     roots = set()
     for obj in bpy.context.selected_objects:
         roots.add(selectionUtils.getRoot(obj))
     if len(roots) > 0:
         selectionUtils.selectObjects(list(roots), True)
         bpy.context.scene.objects.active = list(roots)[0]
     else:
         # bpy.ops.error.message('INVOKE_DEFAULT', type="ERROR", message="Couldn't find any root object.")
         log("Couldn't find any root object.", "ERROR")
     endLog()
     return {'FINISHED'}
Exemple #23
0
def dissolveLink(obj, delete_other=False):
    """Remove the selected link and reparent all links, inertia, visual and collisions to its effective Parent.

    Args:
      obj(bpy.types.Object): the link to dissolve
      delete_other: (Default value = False)

    Returns:

    """

    # Store original layers
    originallayers = list(bpy.context.scene.layers)
    # Select all layers which contain
    bpy.context.scene.layers = [True for i in range(20)]

    if not obj.phobostype == 'link':
        log('Selected object {} is not a link!'.format(obj.name), 'ERROR')
        return

    else:
        delete = [obj]
        # Get all children
        children = sUtils.getRecursiveChildren(obj,
                                               phobostypes=('link', 'inertial',
                                                            'visual',
                                                            'collision'),
                                               include_hidden=True)

        if delete_other:
            other_children = sUtils.getRecursiveChildren(
                obj,
                recursion_depth=2,
                phobostypes=('motor', 'controller', 'sensor', 'submodel'),
                include_hidden=True,
            )
            delete += [
                child for child in other_children if child not in children
            ]

        # Get the parent
        parent = obj.parent
        # If parent is not None ( Root )
        if obj.parent:
            # Reparent
            parentObjectsTo(children, parent, clear=True)
            # Delete the objects
            sUtils.selectObjects(delete, clear=True, active=-1)
            bpy.ops.object.delete()
    # Restore original layers
    bpy.context.scene.layers = originallayers
Exemple #24
0
def addLight(light_dict):

    if light_dict['type'] == 'spotlight':
        light_type = 'SPOT'
    elif light_dict['type'] == 'omnilight':
        light_type = 'POINT'

    position = light_dict['pose']['translation']
    rotation = light_dict['pose']['rotation_euler']

    bpy.ops.object.lamp_add(type=light_type,
                           location=position,
                           rotation=rotation)
    light = bpy.context.active_object
    if 'parent' in light_dict:
        selectionUtils.selectObjects([light, bpy.data.objects[light_dict['parent']]], clear=True, active=1)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')

    light_data = light.data
    light.name = light_dict['name']

    colour_vals = ['r', 'g', 'b']
    colour_data = light_dict['color']['diffuse']
    light_data.color = [colour_data[v] for v in colour_vals]
    for v in colour_vals:
        if light_dict['color']['specular'][v] > 0:
            light_data.use_specular = True
            break

    if type == 'SPOT':
        light_data.spot_size = light_dict['angle']

    #if light_dict['attenuation']['constant'] > 0:
    light_data.energy = light_dict['attenuation']['constant']
    falloff = 'CONSTANT'
    if light_dict['attenuation']['linear'] > 0:
        light_data.linear_attenuation = light_dict['attenuation']['linear']
        falloff = 'INVERSE_LINEAR'
    if light_dict['attenuation']['quadratic'] > 0:
        light_data.quadratic_attenuation = light_dict['attenuation']['quadratic']
        if falloff == 'INVERSE_LINEAR':
            falloff = 'LINEAR_QUADRATIC_WEIGHTED'
        else:
            falloff = 'INVERSE_SQUARE'
    light_data.falloff_type = falloff

    light.phobostype = 'light'
    light['light/exponent'] = light_dict['exponent']
    light.phobostype = 'light'
    light['light/directional'] = light_dict['directional']
    return light
Exemple #25
0
def cameraRotLock(object):
    selectionUtils.selectObjects([object], active=0)
    bpy.ops.transform.rotate(value=-1.5708, axis=(-1, 0, 0), constraint_axis=(False, False, True), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
    bpy.ops.transform.rotate(value=1.5708, axis=(0, -1, 0), constraint_axis=(True, False, False), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
    bpy.ops.object.constraint_add(type='LIMIT_ROTATION')
    object.constraints["Limit Rotation"].use_limit_x = True
    object.constraints["Limit Rotation"].use_limit_y = True
    object.constraints["Limit Rotation"].use_limit_z = True
    object.constraints["Limit Rotation"].min_x = object.rotation_euler[0]
    object.constraints["Limit Rotation"].max_x = object.rotation_euler[0]
    object.constraints["Limit Rotation"].min_y = object.rotation_euler[1]
    object.constraints["Limit Rotation"].max_y = object.rotation_euler[1]
    object.constraints["Limit Rotation"].min_z = object.rotation_euler[2]
    object.constraints["Limit Rotation"].max_z = object.rotation_euler[2]
Exemple #26
0
    def execute(self, context):
        roots = set()

        # add root object of each selected object
        for obj in bpy.context.selected_objects:
            roots.add(sUtils.getRoot(obj))

        # select all found root objects
        if len(roots) > 0:
            sUtils.selectObjects(list(roots), True)
            bpy.context.scene.objects.active = list(roots)[0]
        else:
            log("Couldn't find any root object.", "ERROR")
        return {'FINISHED'}
Exemple #27
0
 def execute(self, context):
     startLog(self)
     objs = context.selected_objects
     root = sUtils.getRoot(context.selected_objects[0])
     model = robotdictionary.buildModelDictionary(root)
     sUtils.selectObjects(objs)
     if bpy.data.worlds[0].relativePath:
         outpath = exporter.securepath(os.path.expanduser(os.path.join(bpy.path.abspath("//"), bpy.data.worlds[0].path)))
     else:
         outpath = exporter.securepath(os.path.expanduser(bpy.data.worlds[0].path))
     exporter.bakeModel(objs, outpath, model["modelname"])
     with open(os.path.join(outpath, "info.bake"), "w") as f:
         f.write(yaml.dump({"name": model["modelname"]}))
     endLog()
     return {'FINISHED'}
Exemple #28
0
def createJoint(joint, linkobj=None):
    # TODO add some docstring
    # add joint information
    if not linkobj:
        linkobj = bpy.data.objects[joint['child']]  # TODO: Make this generic?
    if joint['name'] != linkobj.name:
        linkobj['joint/name'] = joint['name']
    # get hold of object
    bUtils.toggleLayer(defs.layerTypes['link'], True)
    sUtils.selectObjects([linkobj], clear=True, active=0)

    # set axis
    if 'axis' in joint:
        # Providing a zero axis joint will size the editbone to zero scale
        if mathutils.Vector(tuple(joint['axis'])).length == 0.:
            log(
                'Faulty joint definition ({0}): Axis is of zero length.'.
                format(joint['name']), 'ERROR')
        else:
            bpy.ops.object.mode_set(mode='EDIT')
            editbone = linkobj.data.edit_bones[0]
            #oldaxis = editbone.vector
            length = editbone.length
            axis = mathutils.Vector(tuple(joint['axis']))
            #oldaxis.cross(axis) # rotation axis
            editbone.tail = editbone.head + axis.normalized() * length

    # add constraints
    for param in ['effort', 'velocity']:
        try:
            if 'limits' in joint:
                linkobj['joint/max' + param] = joint['limits'][param]
        except KeyError:
            # TODO more details
            log("Key Error in adding joint constraints for joint",
                joint['name'])
    try:
        lower = joint['limits']['lower']
        upper = joint['limits']['upper']
    except KeyError:
        lower = 0.0
        upper = 0.0
    setJointConstraints(linkobj, joint['type'], lower, upper)
    for prop in joint:
        if prop.startswith('$'):
            for tag in joint[prop]:
                linkobj['joint/' + prop[1:] + '/' + tag] = joint[prop][tag]
Exemple #29
0
def dissolveLink(obj, delete_other=False):
    """Remove the selected link and reparent all links, inertia, visual and collisions to its effective Parent.

    Args:
      obj(bpy.types.Object): the link to dissolve
      delete_other: (Default value = False)

    Returns:

    """

    # Store original layers
    originallayers = list(bpy.context.scene.layers)
    # Select all layers which contain
    bpy.context.scene.layers = [True for i in range(20)]

    if not obj.phobostype == 'link':
        log('Selected object {} is not a link!'.format(obj.name), 'ERROR')
        return

    else:
        delete = [obj]
        # Get all children
        children = sUtils.getRecursiveChildren(
            obj, phobostypes=('link', 'inertial', 'visual', 'collision'), include_hidden=True
        )

        if delete_other:
            other_children = sUtils.getRecursiveChildren(
                obj,
                recursion_depth=2,
                phobostypes=('motor', 'controller', 'sensor', 'submodel'),
                include_hidden=True,
            )
            delete += [child for child in other_children if child not in children]

        # Get the parent
        parent = obj.parent
        # If parent is not None ( Root )
        if obj.parent:
            # Reparent
            parentObjectsTo(children, parent, clear=True)
            # Delete the objects
            sUtils.selectObjects(delete, clear=True, active=-1)
            bpy.ops.object.delete()
    # Restore original layers
    bpy.context.scene.layers = originallayers
Exemple #30
0
 def execute(self, context):
     startLog(self)
     objs = context.selected_objects
     robot = robotdictionary.buildRobotDictionary()
     selectionUtils.selectObjects(objs)
     outpath = ""
     if bpy.data.worlds[0].relativePath:
         outpath = exporter.securepath(os.path.expanduser(os.path.join(bpy.path.abspath("//"), bpy.data.worlds[0].path)))
     else:
         outpath = exporter.securepath(os.path.expanduser(bpy.data.worlds[0].path))
     #expPath = os.path.join(outpath, robot["modelname"] + "_bake")
     #exporter.export(path=expPath, robotmodel=robot)
     exporter.bakeModel(objs, outpath, robot["modelname"])
     with open(os.path.join(outpath, "info.bake"), "w") as f:
         f.write(yaml.dump({"name": robot["modelname"]}))
     endLog()
     return {'FINISHED'}
Exemple #31
0
 def execute(self, context):
     if self.bakeObj == "None":
         return {"FINISHED"}
     with open(os.path.join(os.path.dirname(defs.__file__), "RobotLib.yml"), "r") as f:
         robot_lib = yaml.load(f.read())
     root = links.createLink(1.0, name=self.robName + "::" + self.bakeObj)
     root["modelname"] = self.bakeObj
     root["entityname"] = self.robName
     root["isInstance"] = True
     bpy.ops.import_mesh.stl(filepath=os.path.join(robot_lib[self.bakeObj], "bake.stl"))
     bpy.ops.view3d.snap_selected_to_cursor(use_offset=False)
     obj = context.active_object
     obj.name = self.robName + "::visual"
     obj.phobostype = "visual"
     selectionUtils.selectObjects([root, obj], clear=True, active=0)
     bpy.ops.object.parent_set(type='BONE_RELATIVE')
     return {"FINISHED"}
Exemple #32
0
 def execute(self, context):
     selection = []
     if self.modelname:
         log("phobos: Selecting model" + self.modelname, "INFO")
         roots = sUtils.getRoots()
         for root in roots:
             if root["modelname"] == self.modelname:
                 selection = sUtils.getChildren(root)
     else:
         log("No model name provided, deriving from selection...", "INFO")
         roots = set()
         for obj in bpy.context.selected_objects:
             roots.add(sUtils.getRoot(obj))
         for root in list(roots):
             selection.extend(sUtils.getChildren(root))
     sUtils.selectObjects(list(selection), True)
     return {'FINISHED'}
Exemple #33
0
def calculateInertia(obj, mass, geometry_dict=None, errors=None, adjust=False, logging=False):
    """Calculates the inertia of an object using the specified mass and
       optionally geometry.

    Args:
      obj(bpy.types.Object): object to calculate inertia from
      mass(float): mass of object
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple): (Default value = None)
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple):
    tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:

    """
    if errors and not adjust:
        if logging:
            log("Can not calculate inertia from object.", 'ERROR')
        return None

    inertia = None
    if not geometry_dict:
        geometry = deriveGeometry(obj)

    # Get the rotation of the object
    object_rotation = obj.rotation_euler.to_matrix()

    if geometry['type'] == 'box':
        inertia = calculateBoxInertia(mass, geometry['size'])
    elif geometry['type'] == 'cylinder':
        inertia = calculateCylinderInertia(mass, geometry['radius'], geometry['length'])
    elif geometry['type'] == 'sphere':
        inertia = calculateSphereInertia(mass, geometry['radius'])
    elif geometry['type'] == 'mesh':
        sUtils.selectObjects((obj,), clear=True, active=0)
        inertia = calculateMeshInertia(mass, obj.data)

    # Correct the inertia orientation to account for Cylinder / mesh orientation issues
    inertia = object_rotation * inertiaListToMatrix(inertia) * object_rotation.transposed()

    return inertiaMatrixToList(inertia)
Exemple #34
0
 def execute(self, context):
     selection = []
     if self.modelname:
         print("phobos: Selecting model", self.modelname)
         roots = selectionUtils.getRoots()
         for root in roots:
             if root["modelname"] == self.modelname:
                 selection = selectionUtils.getChildren(root)
     else:
         print("phobos: No model name provided, deriving from selection...")
         roots = set()
         for obj in bpy.context.selected_objects:
             print("Selecting", selectionUtils.getRoot(obj).name)
             roots.add(selectionUtils.getRoot(obj))
         for root in list(roots):
             selection.extend(selectionUtils.getChildren(root))
     selectionUtils.selectObjects(list(selection), True)
     return {'FINISHED'}
Exemple #35
0
 def execute(self, context):
     if self.bakeObj == "None":
         return {"FINISHED"}
     with open(os.path.join(os.path.dirname(defs.__file__), "RobotLib.yml"), "r") as f:
         robot_lib = yaml.load(f.read())
     root = links.createLink(1.0, name=self.robName + "::" + self.bakeObj)
     root["modelname"] = self.bakeObj
     root["entity/name"] = self.robName
     root["isInstance"] = True
     bpy.ops.import_mesh.stl(filepath=os.path.join(
         robot_lib[self.bakeObj], "bake.stl"))
     bpy.ops.view3d.snap_selected_to_cursor(use_offset=False)
     obj = context.active_object
     obj.name = self.robName + "::visual"
     obj.phobostype = "visual"
     sUtils.selectObjects([root, obj], clear=True, active=0)
     bpy.ops.object.parent_set(type='BONE_RELATIVE')
     return {"FINISHED"}
Exemple #36
0
def calculateInertia(obj,
                     mass,
                     geometry_dict=None,
                     errors=None,
                     adjust=False,
                     logging=False):
    """Calculates the inertia of an object using the specified mass and
       optionally geometry.

    Args:
      obj(bpy.types.Object): object to calculate inertia from
      mass(float): mass of object
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple): (Default value = None)
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple):
    tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:

    """
    if errors and not adjust:
        if logging:
            log("Can not calculate inertia from object.", 'ERROR')
        return None

    inertia = None
    if not geometry_dict:
        geometry = deriveGeometry(obj)

    if geometry['type'] == 'box':
        inertia = calculateBoxInertia(mass, geometry['size'])
    elif geometry['type'] == 'cylinder':
        inertia = calculateCylinderInertia(mass, geometry['radius'],
                                           geometry['length'])
    elif geometry['type'] == 'sphere':
        inertia = calculateSphereInertia(mass, geometry['radius'])
    elif geometry['type'] == 'mesh':
        sUtils.selectObjects((obj, ), clear=True, active=0)
        inertia = calculateMeshInertia(mass, obj.data)
    return inertia
Exemple #37
0
 def execute(self, context):
     startLog(self)
     objs = context.selected_objects
     root = sUtils.getRoot(context.selected_objects[0])
     model = robotdictionary.buildModelDictionary(root)
     sUtils.selectObjects(objs)
     if bpy.data.worlds[0].relativePath:
         outpath = exporter.securepath(
             os.path.expanduser(
                 os.path.join(bpy.path.abspath("//"),
                              bpy.data.worlds[0].path)))
     else:
         outpath = exporter.securepath(
             os.path.expanduser(bpy.data.worlds[0].path))
     exporter.bakeModel(objs, outpath, model["modelname"])
     with open(os.path.join(outpath, "info.bake"), "w") as f:
         f.write(yaml.dump({"name": model["modelname"]}))
     endLog()
     return {'FINISHED'}
Exemple #38
0
def createSensor(sensor, reference, origin=mathutils.Matrix()):
    blenderUtils.toggleLayer(defs.layerTypes['sensor'], value=True)
    # create sensor object
    if 'Camera' in sensor['type']:
        bpy.context.scene.layers[defs.layerTypes['sensor']] = True
        bpy.ops.object.add(type='CAMERA', location=origin.to_translation(),
                           rotation=origin.to_euler(),
                           layers=blenderUtils.defLayers([defs.layerTypes['sensor']]))
        newsensor = bpy.context.active_object
        if reference is not None:
            selectionUtils.selectObjects([newsensor, bpy.data.objects[reference]], clear=True, active=1)
            bpy.ops.object.parent_set(type='BONE_RELATIVE')
    elif sensor['type'] in ['RaySensor', 'RotatingRaySensor', 'ScanningSonar', 'MultiLevelLaserRangeFinder']:
        # TODO: create a proper ray sensor scanning layer disc here
        newsensor = blenderUtils.createPrimitive(sensor['name'], 'disc', (0.5, 36),
                                            defs.layerTypes['sensor'], 'phobos_laserscanner',
                                            origin.to_translation(), protation=origin.to_euler())
        if reference is not None and reference != []:
            if type(reference) == str:
                key = reference
            else:
                key = reference[0]
            selectionUtils.selectObjects([newsensor, bpy.data.objects[key]], clear=True, active=1)
            bpy.ops.object.parent_set(type='BONE_RELATIVE')
    else:  # contact, force and torque sensors (or unknown sensors)
        newsensor = blenderUtils.createPrimitive(sensor['name'], 'sphere', 0.05,
                                            defs.layerTypes['sensor'], 'phobos_sensor',
                                            origin.to_translation(), protation=origin.to_euler())
        if 'Node' in sensor['type']:
            newsensor['sensor/nodes'] = sorted(reference)
        elif 'Joint' in sensor['type'] or 'Motor' in sensor['type']:
            newsensor['sensor/joints'] = sorted(reference)
        if reference is not None and reference != []:
            selectionUtils.selectObjects([newsensor, selectionUtils.getRoot(bpy.data.objects[0])], clear=True, active=1)
            bpy.ops.object.parent_set(type='BONE_RELATIVE')
    # set sensor properties
    newsensor.phobostype = 'sensor'
    newsensor.name = sensor['name']
    newsensor['sensor/type'] = sensor['type']
    for prop in sensor['props']:
        newsensor['sensor/'+prop] = sensor['props'][prop]

    # add custom properties
    #for prop in sensor:
    #    if prop.startswith('$'):
    #        for tag in sensor[prop]:
    #            newsensor[prop[1:]+'/'+tag] = sensor[prop][tag]

    # throw warning if type is not known
    if sensor['type'] not in defs.sensortypes:
        print("### Warning: sensor", sensor['name'], "is of unknown/custom type.")
    selectionUtils.selectObjects([newsensor], clear=False, active=0)
    return newsensor
Exemple #39
0
def cameraRotLock(object):
    """TODO: PLEASE ADD PYDOC. What should this do exactly?

    :param object: The object to lock the rotation for
    :type object: bpy_types.Object

    """
    selectionUtils.selectObjects([object], active=0)
    bpy.ops.transform.rotate(value=-1.5708, axis=(-1, 0, 0), constraint_axis=(False, False, True), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
    bpy.ops.transform.rotate(value=1.5708, axis=(0, -1, 0), constraint_axis=(True, False, False), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
    bpy.ops.object.constraint_add(type='LIMIT_ROTATION')
    object.constraints["Limit Rotation"].use_limit_x = True
    object.constraints["Limit Rotation"].use_limit_y = True
    object.constraints["Limit Rotation"].use_limit_z = True
    object.constraints["Limit Rotation"].min_x = object.rotation_euler[0]
    object.constraints["Limit Rotation"].max_x = object.rotation_euler[0]
    object.constraints["Limit Rotation"].min_y = object.rotation_euler[1]
    object.constraints["Limit Rotation"].max_y = object.rotation_euler[1]
    object.constraints["Limit Rotation"].min_z = object.rotation_euler[2]
    object.constraints["Limit Rotation"].max_z = object.rotation_euler[2]
Exemple #40
0
    def execute(self, context):
        roots = ioUtils.getExportModels()
        if not roots:
            log("No properly defined models selected or present in scene.",
                'ERROR')
            return {'CANCELLED'}
        elif not self.exportall:
            roots = [
                root for root in roots if root['modelname'] == self.modelname
            ]
            if len(roots) > 1:
                log(
                    "Ambiguous model definitions: " + self.modelname +
                    " exists " + str(len(roots)) + " times.", "ERROR")
                return {'CANCELLED'}

        for root in roots:
            # setup paths
            exportpath = ioUtils.getExportPath()
            if not securepath(exportpath):
                log("Could not secure path to export to.", "ERROR")
                continue
            log("Export path: " + exportpath, "DEBUG")
            ioUtils.exportModel(models.deriveModelDictionary(root), exportpath)

        # select all exported models after export is done
        if ioUtils.getExpSettings().selectedOnly:
            for root in roots:
                objectlist = sUtils.getChildren(root,
                                                selected_only=True,
                                                include_hidden=False)
                sUtils.selectObjects(objectlist, clear=False)
        else:
            bpy.ops.object.select_all(action='DESELECT')
            for root in roots:
                sUtils.selectObjects(list([root]), False)
            bpy.ops.phobos.select_model()

        # report success to user
        log("Export successful.", "INFO")
        return {'FINISHED'}
Exemple #41
0
 def execute(self, context):
     startLog(self)
     objs = context.selected_objects
     robot = robotdictionary.buildRobotDictionary()
     selectionUtils.selectObjects(objs)
     outpath = ""
     if bpy.data.worlds[0].relativePath:
         outpath = exporter.securepath(
             os.path.expanduser(
                 os.path.join(bpy.path.abspath("//"),
                              bpy.data.worlds[0].path)))
     else:
         outpath = exporter.securepath(
             os.path.expanduser(bpy.data.worlds[0].path))
     #expPath = os.path.join(outpath, robot["modelname"] + "_bake")
     #exporter.export(path=expPath, robotmodel=robot)
     exporter.bakeModel(objs, outpath, robot["modelname"])
     with open(os.path.join(outpath, "info.bake"), "w") as f:
         f.write(yaml.dump({"name": robot["modelname"]}))
     endLog()
     return {'FINISHED'}
Exemple #42
0
def placeLinkSubelements(link):
    """Finds all subelements for a given link and sets the appropriate relations.
    In this case subelements are interials, visuals and collisions.

    :param link: The parent link you want to set the subelements for
    :type link: dict
    """
    elements = getGeometricElements(link) + ([link['inertial']]
                                             if 'inertial' in link else [])
    bpy.context.scene.layers = bUtils.defLayers(
        [defs.layerTypes[t] for t in defs.layerTypes])
    parentlink = bpy.data.objects[link['name']]
    log(
        'Placing subelements for link: ' + link['name'] + ': ' +
        ', '.join([elem['name'] for elem in elements]), 'DEBUG')
    for element in elements:
        if 'pose' in element:
            log('Pose detected for element: ' + element['name'], 'DEBUG')
            location = mathutils.Matrix.Translation(
                element['pose']['translation'])
            rotation = mathutils.Euler(
                tuple(element['pose']['rotation_euler']),
                'XYZ').to_matrix().to_4x4()
        else:
            log('No pose in element: ' + element['name'], 'DEBUG')
            location = mathutils.Matrix.Identity(4)
            rotation = mathutils.Matrix.Identity(4)
        try:
            obj = bpy.data.objects[element['name']]
        except KeyError:
            log('Missing link element for placement: ' + element['name'],
                'ERROR')
            continue
        sUtils.selectObjects([obj, parentlink], True, 1)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')
        obj.matrix_local = location * rotation
        try:
            obj.scale = mathutils.Vector(element['geometry']['scale'])
        except KeyError:
            log('No scale defined for element ' + element['name'], 'DEBUG')
Exemple #43
0
def importBlenderModel(filepath, namespace='', prefix=False):
    """Imports an existing Blender model into the current .blend scene

    Args:
      filepath(str): Path of the .blend file
      namespace: (Default value = '')
      prefix: (Default value = False)

    Returns:

    """
    if os.path.exists(filepath) and os.path.isfile(filepath) and filepath.endswith('.blend'):
        log("Importing Blender model" + filepath, "INFO")
        objects = []
        with bpy.data.libraries.load(filepath) as (data_from, data_to):
            for objname in data_from.objects:
                objects.append({'name': objname})
        bpy.ops.wm.append(directory=filepath + "/Object/", files=objects)
        imported_objects = bpy.context.selected_objects
        resources = [obj for obj in imported_objects if obj.name.startswith('resource::')]
        new_objects = [obj for obj in imported_objects if not obj.name.startswith('resource::')]
        if resources:
            if 'resources' not in bpy.data.scenes.keys():
                bpy.data.scenes.new('resources')
            sUtils.selectObjects(resources)
            bpy.ops.object.make_links_scene(scene='resources')
            bpy.ops.object.delete(use_global=False)
            sUtils.selectObjects(new_objects)
        bpy.ops.view3d.view_selected(use_all_regions=False)
        # allow the use of both prefixes and namespaces, thus truly merging
        # models or keeping them separate for export
        if namespace != '':
            if prefix:
                for obj in bpy.context.selected_objects:
                    # set prefix instead of namespace
                    obj.name = namespace + '__' + obj.name
                    # make sure no internal name-properties remain
                    for key in obj.keys():
                        try:
                            if obj[key].endswidth("/name"):
                                del obj[key]
                        except AttributeError:  # prevent exceptions from non-string properties
                            pass
            else:
                for obj in bpy.context.selected_objects:
                    nUtils.addNamespace(obj, namespace)
        submechanism_roots = [
            obj
            for obj in bpy.data.objects
            if obj.phobostype == 'link' and 'submechanism/spanningtree' in obj
        ]
        for root in submechanism_roots:
            partlist = [root] + root['submechanism/spanningtree']
            if 'submechanism/freeloader' in root:
                partlist += root['submechanism/freeloader']
            sUtils.selectObjects(partlist, active=0)
            bpy.ops.group.create(name='submechanism:' + root['submechanism/name'])
        return True
    else:
        return False
Exemple #44
0
def importBlenderModel(filepath, namespace='', prefix=False):
    """Imports an existing Blender model into the current .blend scene

    Args:
      filepath(str): Path of the .blend file
      namespace: (Default value = '')
      prefix: (Default value = False)

    Returns:

    """
    if os.path.exists(filepath) and os.path.isfile(filepath) and filepath.endswith('.blend'):
        log("Importing Blender model" + filepath, "INFO")
        objects = []
        with bpy.data.libraries.load(filepath) as (data_from, data_to):
            for objname in data_from.objects:
                objects.append({'name': objname})
        bpy.ops.wm.append(directory=filepath + "/Object/", files=objects)
        imported_objects = bpy.context.selected_objects
        resources = [obj for obj in imported_objects if obj.name.startswith('resource::')]
        new_objects = [obj for obj in imported_objects if not obj.name.startswith('resource::')]
        if resources:
            if 'resources' not in bpy.data.scenes.keys():
                bpy.data.scenes.new('resources')
            sUtils.selectObjects(resources)
            bpy.ops.object.make_links_scene(scene='resources')
            bpy.ops.object.delete(use_global=False)
            sUtils.selectObjects(new_objects)
        bpy.ops.view3d.view_selected(use_all_regions=False)
        # allow the use of both prefixes and namespaces, thus truly merging
        # models or keeping them separate for export
        if namespace != '':
            if prefix:
                for obj in bpy.context.selected_objects:
                    # set prefix instead of namespace
                    obj.name = namespace + '__' + obj.name
                    # make sure no internal name-properties remain
                    for key in obj.keys():
                        try:
                            if obj[key].endswidth("/name"):
                                del obj[key]
                        except AttributeError:  # prevent exceptions from non-string properties
                            pass
            else:
                for obj in bpy.context.selected_objects:
                    nUtils.addNamespace(obj, namespace)
        submechanism_roots = [
            obj
            for obj in bpy.data.objects
            if obj.phobostype == 'link' and 'submechanism/spanningtree' in obj
        ]
        for root in submechanism_roots:
            partlist = [root] + root['submechanism/spanningtree']
            if 'submechanism/freeloader' in root:
                partlist += root['submechanism/freeloader']
            sUtils.selectObjects(partlist, active=0)
            bpy.ops.group.create(name='submechanism:' + root['submechanism/name'])
        return True
    else:
        return False
Exemple #45
0
 def execute(self, context):
     root = sUtils.getRoot(context.selected_objects[0])
     objectlist = sUtils.getChildren(root,
                                     selected_only=True,
                                     include_hidden=False)
     sUtils.selectObjects(objectlist)
     poses = models.getPoses(root['modelname'])
     i = 1
     for pose in poses:
         sUtils.selectObjects([root] + objectlist, clear=True, active=0)
         models.loadPose(root['modelname'], pose)
         parameter = self.decimate_ratio
         if self.decimate_type == 'UNSUBDIV':
             parameter = self.decimate_iteration
         elif self.decimate_type == 'DISSOLVE':
             parameter = self.decimate_angle_limit
         exporter.bakeModel(objectlist,
                            root['modelname'],
                            pose,
                            decimate_type=self.decimate_type,
                            decimate_parameter=parameter)
         display.setProgress(i / len(poses))
         i += 1
     sUtils.selectObjects([root] + objectlist, clear=True, active=0)
     bpy.ops.scene.reload_models_and_poses_operator()
     return {'FINISHED'}
Exemple #46
0
    def execute(self, context):
        """

        Args:
          context: 

        Returns:

        """
        root = sUtils.getRoot(context.selected_objects[0])
        objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False)
        sUtils.selectObjects(objectlist)
        poses = models.getPoses(root['model/name'])
        i = 1
        for pose in poses:
            sUtils.selectObjects([root] + objectlist, clear=True, active=0)
            models.loadPose(root['model/name'], pose)
            parameter = self.decimate_ratio
            if self.decimate_type == 'UNSUBDIV':
                parameter = self.decimate_iteration
            elif self.decimate_type == 'DISSOLVE':
                parameter = self.decimate_angle_limit
            exporter.bakeModel(
                objectlist,
                root['model/name'],
                pose,
                decimate_type=self.decimate_type,
                decimate_parameter=parameter,
            )
            display.setProgress(i / len(poses))
            i += 1
        sUtils.selectObjects([root] + objectlist, clear=True, active=0)
        bpy.ops.scene.reload_models_and_poses_operator()
        return {'FINISHED'}
Exemple #47
0
def placeChildLinks(model, parent):
    """Creates parent-child-relationship for a given parent and all existing children in Blender.

    :param parent: This is the parent link you want to set the children for.
    :type: dict
    """
    bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes['link'])
    children = []
    for l in model['links']:
        if 'parent' in model['links'][l] and model['links'][l][
                'parent'] == parent['name']:
            children.append(model['links'][l])
    for child in children:
        # 1: set parent relationship (this makes the parent inverse the inverse of the parents world transform)
        parentLink = bpy.data.objects[parent['name']]
        childLink = bpy.data.objects[child['name']]
        sUtils.selectObjects([childLink, parentLink], True, 1)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')
        # 2: move to parents origin by setting the world matrix to the parents world matrix
        # removing this line does not seem to make a difference (TODO delete me?)
        childLink.matrix_world = parentLink.matrix_world

        # TODO delete me?
        # #bpy.context.scene.objects.active = childLink
        # if 'pivot' in child:
        #     pivot = child['pivot']
        #     cursor_location = bpy.context.scene.cursor_location
        #     bpy.context.scene.cursor_location = mathutils.Vector((-pivot[0]*0.3, -pivot[1]*0.3, -pivot[2]*0.3))
        #     bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
        #     bpy.context.scene.cursor_location = cursor_location

        # 3: apply local transform as saved in model (changes matrix_local)
        location = mathutils.Matrix.Translation(child['pose']['translation'])
        rotation = mathutils.Euler(tuple(child['pose']['rotation_euler']),
                                   'XYZ').to_matrix().to_4x4()
        transform_matrix = location * rotation
        childLink.matrix_local = transform_matrix
        # 4: be happy, as world and basis are now the same and local is the transform to be exported to urdf
        # 5: take care of the rest of the tree
        placeChildLinks(model, child)
Exemple #48
0
def mergeLinks(links, targetlink, movetotarget=False):
    """

    Args:
      links: 
      targetlink: 
      movetotarget: (Default value = False)

    Returns:

    """
    for link in links:
        if movetotarget:
            link.matrix_world = targetlink.matrix_world
        sUtils.selectObjects([link], clear=True, active=0)
        bpy.ops.object.select_grouped(type='CHILDREN')
        bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
        try:
            parentObjectsTo(bpy.context.selected_objects, targetlink)
        except RuntimeError as e:
            log("Cannot resolve new parent hierarchy: " + str(e), 'ERROR')
        del link
Exemple #49
0
def mergeLinks(links, targetlink, movetotarget=False):
    """

    Args:
      links: 
      targetlink: 
      movetotarget: (Default value = False)

    Returns:

    """
    for link in links:
        if movetotarget:
            link.matrix_world = targetlink.matrix_world
        sUtils.selectObjects([link], clear=True, active=0)
        bpy.ops.object.select_grouped(type='CHILDREN')
        bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
        try:
            parentObjectsTo(bpy.context.selected_objects, targetlink)
        except RuntimeError as e:
            log("Cannot resolve new parent hierarchy: " + str(e), 'ERROR')
        del link
Exemple #50
0
    def execute(self, context):
        root = sUtils.getRoot(context.selected_objects[0])

        modelsPosesColl = bUtils.getPhobosPreferences().models_poses
        activeModelPoseIndex = bpy.context.scene.active_ModelPose
        selected_robot = modelsPosesColl[
            bpy.data.images[activeModelPoseIndex].name]

        objectlist = sUtils.getChildren(
            root, selected_only=True, include_hidden=False)
        sUtils.selectObjects([root] + objectlist, clear=True, active=0)
        models.loadPose(selected_robot.robot_name, selected_robot.label)
        parameter = self.decimate_ratio
        if self.decimate_type == 'UNSUBDIV':
            parameter = self.decimate_iteration
        elif self.decimate_type == 'DISSOLVE':
            parameter = self.decimate_angle_limit
        exporter.bakeModel(objectlist, root['modelname'], selected_robot.label, decimate_type=self.decimate_type,
                           decimate_parameter=parameter)
        sUtils.selectObjects([root] + objectlist, clear=True, active=0)
        bpy.ops.scene.reload_models_and_poses_operator()
        return {'FINISHED'}
Exemple #51
0
def createInertials(link, empty=False, preserve_children=False):
    # create inertial representations for visual and collision objects in link
    viscols = getInertiaRelevantObjects(link)
    # clean existing data
    if not preserve_children:
        oldinertials = selectionUtils.getImmediateChildren(link, ['inertial'])
    else:
        try:
            oldinertials = [bpy.data.objects['inertial_'+link.name]]
        except KeyError:
            oldinertials = None
    if oldinertials:
        selectionUtils.selectObjects(oldinertials, clear=True, active=0)
        bpy.ops.object.delete()
    if not preserve_children:
        for obj in viscols:
            if not empty:
                mass = obj['mass'] if 'mass' in obj else None
                geometry = robotdictionary.deriveGeometry(obj)
                if mass is not None:
                    inert = calculateInertia(mass, geometry)
                    if inert is not None:
                        inertial = createInertial(obj)
                        inertial['mass'] = mass
                        inertial['inertia'] = inert
            else:
                createInertial(obj)
    # compose inertial object for link
    if not empty:
        mass, com, inert = fuseInertiaData(selectionUtils.getImmediateChildren(link, ['inertial']))
        if mass and com and inert:
            inertial = createInertial(link)
            com_translate = mathutils.Matrix.Translation(com)
            inertial.matrix_local = com_translate
            bpy.ops.transform.translate(value=(0, 0, 0))  # FIXME: this is a trick to force Blender to apply matrix_local
            inertial['inertial/mass'] = mass
            inertial['inertial/inertia'] = inertiaMatrixToList(inert)
    else:
        createInertial(link)
Exemple #52
0
def disconnectInterfaces(parentinterface, childinterface, transform=None):
    """

    Args:
      parentinterface: 
      childinterface: 
      transform: (Default value = None)

    Returns:

    """
    # unparent the child
    sUtils.selectObjects(objects=[childinterface], clear=True, active=0)
    bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')

    # select the former parent of the interface as new root
    if childinterface.children and len(childinterface.children) > 0:
        # prefer submodel instances
        for child in childinterface.children:
            if child.phobostype == 'submodel':
                root = child
                break
        # otherwise just use the first child
        else:
            root = childinterface.children[0]

    # restructure the kinematic tree to make the interface child of the submodel again
    sUtils.selectObjects(objects=[root], clear=True, active=0)
    bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
    parentObjectsTo(childinterface, root)

    # apply additional transform
    if transform:
        childinterface.matrix_world = root.matrix_world * transform

    # make the interfaces active again
    parentinterface.show_name = True
    childinterface.show_name = True
Exemple #53
0
def disconnectInterfaces(parentinterface, childinterface, transform=None):
    """

    Args:
      parentinterface: 
      childinterface: 
      transform: (Default value = None)

    Returns:

    """
    # unparent the child
    sUtils.selectObjects(objects=[childinterface], clear=True, active=0)
    bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')

    # select the former parent of the interface as new root
    if childinterface.children and len(childinterface.children) > 0:
        # prefer submodel instances
        for child in childinterface.children:
            if child.phobostype == 'submodel':
                root = child
                break
        # otherwise just use the first child
        else:
            root = childinterface.children[0]

    # restructure the kinematic tree to make the interface child of the submodel again
    sUtils.selectObjects(objects=[root], clear=True, active=0)
    bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
    parentObjectsTo(childinterface, root)

    # apply additional transform
    if transform:
        childinterface.matrix_world = root.matrix_world @ transform

    # make the interfaces active again
    parentinterface.show_name = True
    childinterface.show_name = True
Exemple #54
0
def deriveLinkfromObject(obj,
                         scale=0.2,
                         parenting=True,
                         parentobjects=False,
                         namepartindices=[],
                         separator='_',
                         prefix='link'):
    """Derives a link from an object that defines a joint through its position, orientation and parent-child relationships.

    :param obj: The object you want to derive your link from.
    :type obj: bpy_types.Object
    :param scale: The scale you want to apply to the link.
    :type scale: float
    :param parenting: Whether you want to automate the parenting of the new link or not.
    :type parenting: bool.
    :param parentobjects: Whether you want to parent all the objects to the new link or not.
    :type parentobjects: bool.
    :param namepartindices: Parts of the objects name you want to reuse in the links name.
    :type namepartindices: list with two elements.
    :param separator: The separator you want to use to separate the links name with. Its '_' per default
    :type separator: str
    :param prefix: The prefix you want to use for the new links name. Its 'link' per default.
    :type prefix: str

    """
    print('Deriving link from', namingUtils.getObjectName(obj))
    nameparts = namingUtils.getObjectName(obj).split('_')
    rotation = obj.matrix_world.to_euler()
    if 'invertAxis' in obj and obj['invertAxis'] == 1:
        rotation.x += math.pi if rotation.x < 0 else -math.pi
    tmpname = namingUtils.getObjectName(obj)
    if namepartindices:
        try:
            tmpname = separator.join([nameparts[p] for p in namepartindices])
        except IndexError:
            print('Wrong name segment indices given for obj',
                  namingUtils.getObjectName(obj))
    if prefix != '':
        tmpname = prefix + separator + tmpname
    if tmpname == namingUtils.getObjectName(obj):
        obj.name += '*'
    link = createLink(scale, obj.matrix_world.to_translation(),
                      obj.matrix_world.to_euler(), tmpname)
    if parenting:
        if obj.parent:
            selectionUtils.selectObjects([link, obj.parent], True, 1)
            if obj.parent.phobostype == 'link':
                bpy.ops.object.parent_set(type='BONE_RELATIVE')
            else:
                bpy.ops.object.parent_set(type='OBJECT')
        children = selectionUtils.getImmediateChildren(obj)
        if parentobjects:
            children.append(obj)
        for child in children:
            selectionUtils.selectObjects([child], True, 0)
            bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
            selectionUtils.selectObjects([child, link], True, 1)
            bpy.ops.object.parent_set(type='BONE_RELATIVE')
Exemple #55
0
def storePose(root, posename):
    """Stores the current pose of all of a model's selected joints.
    
    Existing poses of the same name will be overwritten.

    Args:
      root(bpy_types.Object): root of the model the pose belongs to
      posename(str): name the pose will be stored under

    Returns:
      : Nothing.

    """
    if root:
        filename = nUtils.getModelName(root) + '::poses'
        posedict = yaml.load(bUtils.readTextFile(filename))
        if not posedict:
            posedict = {posename: {'name': posename, 'joints': {}}}
        else:
            posedict[posename] = {'name': posename, 'joints': {}}
        links = sUtils.getChildren(root, ('link', ), True, False)
        sUtils.selectObjects([root] + links, clear=True, active=0)
        bpy.ops.object.mode_set(mode='POSE')
        for link in (link for link in links if 'joint/type' in link
                     and link['joint/type'] not in ['fixed', 'floating']):
            link.pose.bones['Bone'].rotation_mode = 'XYZ'
            posedict[posename]['joints'][nUtils.getObjectName(
                link, 'joint')] = link.pose.bones['Bone'].rotation_euler.y
        bpy.ops.object.mode_set(mode='OBJECT')
        posedict = gUtils.roundFloatsInDict(
            posedict,
            ioUtils.getExpSettings().decimalPlaces)
        bUtils.updateTextFile(filename,
                              yaml.dump(posedict, default_flow_style=False))
    else:
        log("No model root provided to store the pose for", "ERROR")
Exemple #56
0
def createInertial(parentname,
                   inertialdict,
                   parentobj=None,
                   effectiveParent=None):
    """Creates the Blender representation of a given inertial provided a dictionary.

    :param parentname: inertial object's parent's name
    :type parentname: str
    :param inertialdict: intertial data
    :type inertialdict: dict
    :param parentobj: link or visual/collision with which the inertial obj is associated
    :type parentobj: bpy.types.Object
    :param helper: whether or not the object is a helper inertial
    :type helper: bool

    :return: the newly created blender inertial object.
    :rtype: bpy_types.Object
    """
    size = 0.03

    try:
        origin = mathutils.Vector(inertialdict['pose']['translation'])
    except KeyError:
        origin = mathutils.Vector()

    # Check the inertia data for consistency
    if checkInertiaData(inertialdict):
        material = 'phobos_inertial'
    elif not checkInertiaData(inertialdict):
        log(
            'Inconsistent inertia data found for object {}!'.format(
                parentname), "WARNING")
        material = 'phobos_error'

    inertialobject = bUtils.createPrimitive('inertial_' + parentname,
                                            'box', (size, ) * 3,
                                            defs.layerTypes["inertial"],
                                            pmaterial=material,
                                            phobostype='inertial')
    sUtils.selectObjects((inertialobject, ), clear=True, active=0)
    bpy.ops.object.transform_apply(scale=True)
    if parentobj:
        inertialobject.matrix_world = parentobj.matrix_world
        parent = parentobj if parentobj.phobostype == 'link' else parentobj.parent
        sUtils.selectObjects((inertialobject, parent), clear=True, active=1)

        # Create the inertial object relative to the link / joint
        bpy.ops.object.parent_set(type='BONE_RELATIVE')
        inertialobject.matrix_local = mathutils.Matrix.Translation(origin)
        sUtils.selectObjects((inertialobject, ), clear=True, active=0)
        bpy.ops.object.transform_apply(scale=True)  # force matrix_world update

    # set properties
    for prop in ('mass', 'inertia'):
        inertialobject[prop] = inertialdict[prop]
    return inertialobject
Exemple #57
0
def parentObjectsTo(objects, parent, clear=False):
    """Parents the specified objects to the parent object.
    
    Depending on their phobostype the objects are parented either *bone relative* or *object*.
    
    If *clear* is set, the parenting of the objects will be cleared (keeping the transform), before
    parenting.

    Args:
      objects(list(bpy.types.Object): objects to set parent of
      parent(bpy.types.Object): parent object
      clear(bool, optional): if True, the parenting of the objects will be cleared (Default value = False)

    Returns:

    """
    if not isinstance(objects, list):
        objects = [objects]

    # Store original layers
    #originallayers = list(bpy.context.scene.layers)
    # Select all layers
    #bpy.context.scene.layers = [True for i in range(20)]
    # Restore original layers
    #bpy.context.scene.layers = originallayers

    if clear:
        sUtils.selectObjects(objects, active=0, clear=True)
        bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')

    sUtils.selectObjects([parent] + objects, active=0, clear=True)

    if parent.phobostype == 'link':
        bpy.ops.object.parent_set(type='BONE_RELATIVE')
    else:
        bpy.ops.object.parent_set(type='OBJECT')
Exemple #58
0
def deriveLinkfromObject(obj,
                         scale=0.2,
                         parent_link=True,
                         parent_objects=False,
                         nameformat=''):
    """Derives a link from an object using its name, transformation and parenting.

    Args:
      obj(bpy_types.Object): object to derive a link from
      scale(float, optional): scale factor for bone size (Default value = 0.2)
      parent_link(bool, optional): whether to automate the parenting of the new link or not. (Default value = True)
      parent_objects(bool, optional): whether to parent all the objects to the new link or not (Default value = False)
      nameformat(str, optional): re-formatting template for obj names (Default value = '')

    Returns:
      newly created link

    """
    log('Deriving link from ' + nUtils.getObjectName(obj), level="INFO")
    try:
        nameparts = [
            p for p in re.split('[^a-zA-Z]', nUtils.getObjectName(obj))
            if p != ''
        ]
        linkname = nameformat.format(*nameparts)
    except IndexError:
        log(
            'Invalid name format (indices) for naming: ' +
            nUtils.getObjectName(obj), 'WARNING')
        linkname = 'link_' + nUtils.getObjectName(obj)
    link = createLink({
        'scale': scale,
        'name': linkname,
        'matrix': obj.matrix_world
    })

    # parent link to object's parent
    if parent_link:
        if obj.parent:
            sUtils.selectObjects([link, obj.parent], True, 1)
            if obj.parent.phobostype == 'link':
                bpy.ops.object.parent_set(type='BONE_RELATIVE')
            else:
                bpy.ops.object.parent_set(type='OBJECT')
    # parent children of object to link
    if parent_objects:
        children = [obj] + sUtils.getImmediateChildren(obj)
        sUtils.selectObjects(children, True, 0)
        bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
        sUtils.selectObjects([link] + children, True, 0)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')
    return link