Ejemplo n.º 1
0
 def execute(self, context):
     startLog(self)
     global sensors
     global motors
     location = bpy.context.scene.cursor_location
     objects = []
     controllers = []
     for obj in bpy.context.selected_objects:
         if obj.phobostype == "controller":
             controllers.append(obj)
         else:
             objects.append(obj)
     if len(controllers) <= 0:
         blenderUtils.createPrimitive(self.controller_name, "sphere",
                                      self.controller_scale,
                                      defs.layerTypes["sensor"],
                                      "phobos_controller", location)
         bpy.context.scene.objects.active.phobostype = "controller"
         bpy.context.scene.objects.active.name = self.controller_name
         controllers.append(bpy.context.scene.objects.active)
     #empty index list so enable robotupdate of controller
     for ctrl in controllers:
         ctrl['controller/sensors'] = sorted(sensors, key=str.lower)
         ctrl['controller/motors'] = sorted(motors, key=str.lower)
         ctrl['controller/rate'] = self.controller_rate
     print("Added joints/motors to (new) controller(s).")
     #for prop in defs.controllerProperties[self.controller_type]:
     #    for ctrl in controllers:
     #        ctrl[prop] = defs.controllerProperties[prop]
     endLog()
     return {'FINISHED'}
Ejemplo n.º 2
0
 def execute(self, context):
     location = bpy.context.scene.cursor_location
     objects = []
     controllers = []
     for obj in bpy.context.selected_objects:
         if obj.phobostype == "controller":
             controllers.append(obj)
         else:
             objects.append(obj)
     if len(controllers) <= 0:
         bUtils.createPrimitive("controller", "sphere",
                                self.controller_scale,
                                defs.layerTypes["sensor"], "controller",
                                location)
         bpy.context.scene.objects.active.phobostype = "controller"
         bpy.context.scene.objects.active.name = "controller"
         controllers.append(bpy.context.scene.objects.active)
     #empty index list so enable robotupdate of controller
     for ctrl in controllers:
         for key in ctrl.keys():
             if key.find("index") >= 0:
                 del ctrl[key]
                 log("Deleting " + str(key) + " in " + ctrl.name, "INFO")
         i = 1
         for obj in objects:
             if obj.phobostype == "link":
                 ctrl["index" + (str(i) if i >= 10 else "0" +
                                 str(i))] = nUtils.getObjectName(obj)
                 i += 1
     log("Added joints to (new) controller(s).", "INFO")
     #for prop in defs.controllerProperties[self.controller_type]:
     #    for ctrl in controllers:
     #        ctrl[prop] = defs.controllerProperties[prop]
     return {'FINISHED'}
Ejemplo n.º 3
0
 def execute(self, context):
     startLog(self)
     location = bpy.context.scene.cursor_location
     objects = []
     controllers = []
     for obj in bpy.context.selected_objects:
         if obj.phobostype == "controller":
             controllers.append(obj)
         else:
             objects.append(obj)
     if len(controllers) <= 0:
         blenderUtils.createPrimitive("controller", "sphere", self.controller_scale, defs.layerTypes["sensor"], "controller", location)
         bpy.context.scene.objects.active.phobostype = "controller"
         bpy.context.scene.objects.active.name = "controller"
         controllers.append(bpy.context.scene.objects.active)
     #empty index list so enable robotupdate of controller
     for ctrl in controllers:
         for key in ctrl.keys():
             if key.find("index") >= 0:
                 del ctrl[key]
                 log("Deleting " + str(key) + " in " + ctrl.name, "INFO")
         i = 1
         for obj in objects:
             if obj.phobostype == "link":
                 ctrl["index"+(str(i) if i >= 10 else "0"+str(i))] = namingUtils.getObjectName(obj)
                 i += 1
     log("Added joints to (new) controller(s).", "INFO")
     #for prop in defs.controllerProperties[self.controller_type]:
     #    for ctrl in controllers:
     #        ctrl[prop] = defs.controllerProperties[prop]
     endLog()
     return {'FINISHED'}
Ejemplo n.º 4
0
 def execute(self, context):
     startLog(self)
     global sensors
     global motors
     location = bpy.context.scene.cursor_location
     objects = []
     controllers = []
     for obj in bpy.context.selected_objects:
         if obj.phobostype == "controller":
             controllers.append(obj)
         else:
             objects.append(obj)
     if len(controllers) <= 0:
         blenderUtils.createPrimitive(self.controller_name, "sphere", self.controller_scale, defs.layerTypes["sensor"], "phobos_controller", location)
         bpy.context.scene.objects.active.phobostype = "controller"
         bpy.context.scene.objects.active.name = self.controller_name
         controllers.append(bpy.context.scene.objects.active)
     #empty index list so enable robotupdate of controller
     for ctrl in controllers:
         ctrl['controller/sensors'] = sorted(sensors, key=str.lower)
         ctrl['controller/motors'] = sorted(motors, key=str.lower)
         ctrl['controller/rate'] = self.controller_rate
     print("Added joints/motors to (new) controller(s).")
     #for prop in defs.controllerProperties[self.controller_type]:
     #    for ctrl in controllers:
     #        ctrl[prop] = defs.controllerProperties[prop]
     endLog()
     return {'FINISHED'}
Ejemplo n.º 5
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
Ejemplo n.º 6
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: bpy_types.Object
    :return: bpy_types.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_' + namingUtils.getObjectName(obj, phobostype="link"), '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
Ejemplo n.º 7
0
def exportMesh(obj, path, meshtype):
    # DOCU add some docstring
    objname = nUtils.getObjectName(obj)
    tmpobjname = obj.name
    # OPT: surely no one will ever name an object like so, better solution?
    obj.name = 'tmp_export_666'
    tmpobject = bUtils.createPrimitive(objname, 'box', (1.0, 1.0, 1.0))
    # copy the mesh here
    tmpobject.data = obj.data
    outpath = os.path.join(path, obj.data.name + "." + meshtype)
    if meshtype == 'obj':
        axis_forward = ioUtils.getExpSettings().obj_axis_forward
        axis_up = ioUtils.getExpSettings().obj_axis_up
        bpy.ops.export_scene.obj(filepath=outpath,
                                 use_selection=True,
                                 use_normals=True,
                                 use_materials=False,
                                 use_mesh_modifiers=True,
                                 axis_forward=axis_forward,
                                 axis_up=axis_up)
    elif meshtype == 'stl':
        bpy.ops.export_mesh.stl(filepath=outpath,
                                use_selection=True,
                                use_mesh_modifiers=True)
    elif meshtype == 'dae':
        bpy.ops.wm.collada_export(filepath=outpath, selected=True)
    bpy.ops.object.select_all(action='DESELECT')
    tmpobject.select = True
    bpy.ops.object.delete()
    obj.name = tmpobjname
Ejemplo n.º 8
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
Ejemplo n.º 9
0
def exportMesh(obj, path, meshtype):
    objname = nUtils.getObjectName(obj)
    tmpobjname = obj.name
    obj.name = 'tmp_export_666'  # surely no one will ever name an object like so
    tmpobject = bUtils.createPrimitive(objname, 'box', (1.0, 1.0, 1.0))
    tmpobject.data = obj.data  # copy the mesh here
    outpath = os.path.join(path, obj.data.name + "." + meshtype)
    if meshtype == 'obj':
        bpy.ops.export_scene.obj(filepath=outpath,
                                 use_selection=True,
                                 use_normals=True,
                                 use_materials=False,
                                 use_mesh_modifiers=True)
    elif meshtype == 'stl':
        if bpy.app.version[0] * 100 + bpy.app.version[1] >= 277:
            bpy.ops.export_mesh.stl(filepath=outpath,
                                    use_selection=True,
                                    use_mesh_modifiers=True)
        else:
            bpy.ops.export_mesh.stl(filepath=outpath, use_mesh_modifiers=True)
    elif meshtype == 'dae':
        bpy.ops.wm.collada_export(filepath=outpath, selected=True)
    bpy.ops.object.select_all(action='DESELECT')
    tmpobject.select = True
    bpy.ops.object.delete()
    obj.name = tmpobjname
Ejemplo n.º 10
0
def createInertialFromDictionary(name, inertial):
    """Creates the Blender representation of a given intertial provided a dictionary.

    :param name: The intertials name.
    :param type: str
    :param inertial: The intertial you want to create in blender form.
    :type intertial: dict
    :return: bpy_types.Object -- the newly created blender inertial object.

    """
    # FIXME: this needs work to get rid of duplicate code
    bpy.ops.object.select_all(action='DESELECT')
    inert = bUtils.createPrimitive('inertial_' + name,
                                   'box', [0.06, 0.06, 0.06],
                                   player='inertial')
    inert.select = True
    bpy.ops.object.transform_apply(scale=True)
    for prop in inertial:
        if prop not in ['pose'] and inertial[prop] is not None:
            if not prop.startswith('$'):
                inert[prop] = inertial[prop]
            else:
                for tag in inertial[prop]:
                    inert[prop[1:] + '/' + tag] = inertial[prop][tag]
    inert.phobostype = 'inertial'
    assignMaterial(inert, 'phobos_inertial')
    return inert
Ejemplo n.º 11
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: bpy_types.Object
    :return: bpy_types.Object -- the newly created inertia.

    """
    if obj.phobostype == 'link':
        parent = obj
        size = (0.06, 0.06, 0.06)
    else:
        parent = obj.parent
        size = (0.015, 0.015, 0.015)
    rotation = obj.matrix_world.to_euler()
    center = obj.matrix_world.to_translation()
    inertial = bUtils.createPrimitive(
        'inertial_' + nUtils.getObjectName(obj, phobostype="link"), '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")
    sUtils.selectObjects((inertial, parent), clear=True, active=1)
    bpy.ops.object.parent_set(type='BONE_RELATIVE')
    return inertial
Ejemplo n.º 12
0
def addAnnotationObject(obj, annotation, name=None, size=0.1, namespace=None):
    """Add a new annotation object with the specified annotations to the object.
    
    The annotation object will receive 'annotation_object' as its default name, unless a name is
    provided. Naming is done using :func:`phobos.utils.naming.safelyName`.
    
    The annotation object will be scaled according to the **size** parameter.
    
    If ``namespace`` is provided, the annotations will be saved with this string prepended.
    This is done using :func:`addAnnotation`.

    Args:
      obj(bpy.types.Object): object to add annotation object to
      annotation(dict): annotations that will be added
      name(str, optional): name for the new annotation object (Default value = None)
      size(int/float, optional): size of the new annotation object (Default value = 0.1)
      namespace(str, optional): namespace that will be prepended to the annotations (Default value = None)

    Returns:
      : bpy.types.Object - the new annotation object

    """
    loc = obj.matrix_world.to_translation()
    if not name:
        name = obj.name + '_annotation_object'

    annot_obj = bUtils.createPrimitive(
        name,
        'box',
        [1, 1, 1],
        defs.layerTypes['annotation'],
        plocation=loc,
        phobostype='annotation',
    )
    annot_obj.scale = (size, ) * 3

    resource = ioUtils.getResource(['annotation', namespace.split('/')[-1]])
    if resource:
        annot_obj.data = resource.data
    else:
        annot_obj.data = ioUtils.getResource(['annotation', 'default']).data

    # make sure all layers are enabled for parenting
    originallayers = {}
    for name, coll in bpy.context.window.view_layer.layer_collection.children.items(
    ):
        originallayers[name] = coll.exclude
        coll.exclude = False

    # parent annotation object
    parentObjectsTo(annot_obj, obj)

    # Restore original layers
    for key, value in originallayers.items():
        bpy.context.window.view_layer.layer_collection.children[
            key].exclude = value

    addAnnotation(annot_obj, annotation, namespace=namespace)
    return annot_obj
Ejemplo n.º 13
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
Ejemplo n.º 14
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
Ejemplo n.º 15
0
def addAnnotationObject(obj, annotation, name=None, size=0.1, namespace=None):
    """Add a new annotation object with the specified annotations to the object.
    
    The annotation object will receive 'annotation_object' as its default name, unless a name is
    provided. Naming is done using :func:`phobos.utils.naming.safelyName`.
    
    The annotation object will be scaled according to the **size** parameter.
    
    If ``namespace`` is provided, the annotations will be saved with this string prepended.
    This is done using :func:`addAnnotation`.

    Args:
      obj(bpy.types.Object): object to add annotation object to
      annotation(dict): annotations that will be added
      name(str, optional): name for the new annotation object (Default value = None)
      size(int/float, optional): size of the new annotation object (Default value = 0.1)
      namespace(str, optional): namespace that will be prepended to the annotations (Default value = None)

    Returns:
      : bpy.types.Object - the new annotation object

    """
    loc = obj.matrix_world.to_translation()
    if not name:
        name = obj.name + '_annotation_object'

    annot_obj = bUtils.createPrimitive(
        name,
        'box',
        [1, 1, 1],
        defs.layerTypes['annotation'],
        plocation=loc,
        phobostype='annotation',
    )
    annot_obj.scale = (size,) * 3

    resource = ioUtils.getResource(['annotation', namespace.split('/')[-1]])
    if resource:
        annot_obj.data = resource.data
    else:
        annot_obj.data = ioUtils.getResource(['annotation', 'default']).data

    # make sure all layers are enabled for parenting
    originallayers = list(bpy.context.scene.layers)
    bpy.context.scene.layers = [True for i in range(20)]

    # parent annotation object
    parentObjectsTo(annot_obj, obj)

    bpy.context.scene.layers = originallayers

    addAnnotation(annot_obj, annotation, namespace=namespace)
    return annot_obj
Ejemplo n.º 16
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
Ejemplo n.º 17
0
def createInterface(ifdict, parent=None):
    """Create an interface object and optionally parent to existing object.
    
    ifdict is expected as:
    
    | **type**: str
    | **direction**: str
    | **model**: str
    | **name**: str
    | **parent**: bpy.types.Object (optional)
    | **scale**: float (optional)

    Args:
      ifdict(dict): interface data
      parent(bpy.types.Object, optional): designated parent object (Default value = None)

    Returns:
      bpy.data.Object: newly created interface object

    """
    if not parent:
        try:
            parent = ifdict['parent']
            assert isinstance(parent, bpy.types.Object)
        except (AttributeError, AssertionError, KeyError):
            parent = None
    location = parent.matrix_world.translation if parent else mathutils.Vector(
    )
    rotation = parent.matrix_world.to_euler() if parent else mathutils.Euler()

    model = ifdict['model'] if 'model' in ifdict else 'default'
    templateobj = ioUtils.getResource(
        ('interface', model, ifdict['direction']))
    scale = ifdict['scale'] if 'scale' in ifdict else 1.0
    ifobj = bUtils.createPrimitive(
        ifdict['name'],
        'box',
        (1.0, 1.0, 1.0),
        defs.layerTypes['interface'],
        plocation=location,
        protation=rotation,
        phobostype='interface',
    )
    nUtils.safelyName(ifobj, ifdict['name'], 'interface')
    ifobj.data = templateobj.data
    ifobj.scale = (scale, ) * 3
    ifobj['interface/type'] = ifdict['type']
    ifobj['interface/direction'] = ifdict['direction']
    if parent is not None:
        ifobj['interface/parent'] = parent.name
        parentObjectsTo(ifobj, parent)
    bpy.ops.object.make_single_user(object=True, obdata=True)
Ejemplo n.º 18
0
def createInterface(ifdict, parent=None):
    """Create an interface object and optionally parent to existing object.
    
    ifdict is expected as:
    
    | **type**: str
    | **direction**: str
    | **model**: str
    | **name**: str
    | **parent**: bpy.types.Object (optional)
    | **scale**: float (optional)

    Args:
      ifdict(dict): interface data
      parent(bpy.types.Object, optional): designated parent object (Default value = None)

    Returns:
      bpy.data.Object: newly created interface object

    """
    if not parent:
        try:
            parent = ifdict['parent']
            assert isinstance(parent, bpy.types.Object)
        except (AttributeError, AssertionError, KeyError):
            parent = None
    location = parent.matrix_world.translation if parent else mathutils.Vector()
    rotation = parent.matrix_world.to_euler() if parent else mathutils.Euler()

    model = ifdict['model'] if 'model' in ifdict else 'default'
    templateobj = ioUtils.getResource(('interface', model, ifdict['direction']))
    scale = ifdict['scale'] if 'scale' in ifdict else 1.0
    ifobj = bUtils.createPrimitive(
        ifdict['name'],
        'box',
        (1.0, 1.0, 1.0),
        defs.layerTypes['interface'],
        plocation=location,
        protation=rotation,
        phobostype='interface',
    )
    nUtils.safelyName(ifobj, ifdict['name'], 'interface')
    ifobj.data = templateobj.data
    ifobj.scale = (scale,) * 3
    ifobj['interface/type'] = ifdict['type']
    ifobj['interface/direction'] = ifdict['direction']
    bpy.ops.object.make_single_user(object=True, obdata=True)
Ejemplo n.º 19
0
def exportMesh(obj, path, meshtype):
    """

    Args:
      obj: 
      path: 
      meshtype: 

    Returns:

    """
    import phobos.utils.io as ioUtils

    # DOCU add some docstring
    objname = nUtils.getObjectName(obj)
    tmpobjname = obj.name
    # OPT: surely no one will ever name an object like so, better solution?
    obj.name = 'tmp_export_666'
    tmpobject = bUtils.createPrimitive(objname, 'box', (1.0, 1.0, 1.0))
    # copy the mesh here
    tmpobject.data = obj.data
    outpath = os.path.join(path, obj.data.name + "." + meshtype)
    if meshtype == 'obj':
        axis_forward = bpy.context.scene.phobosexportsettings.obj_axis_forward
        axis_up = bpy.context.scene.phobosexportsettings.obj_axis_up
        bpy.ops.export_scene.obj(
            filepath=outpath,
            use_selection=True,
            use_normals=True,
            use_materials=False,
            use_mesh_modifiers=True,
            axis_forward=axis_forward,
            axis_up=axis_up,
        )
    elif meshtype == 'stl':
        bpy.ops.export_mesh.stl(filepath=outpath, use_selection=True, use_mesh_modifiers=True)
    elif meshtype == 'dae':
        bpy.ops.wm.collada_export(filepath=outpath, selected=True)
    bpy.ops.object.select_all(action='DESELECT')
    tmpobject.select = True
    bpy.ops.object.delete()
    obj.name = tmpobjname
Ejemplo n.º 20
0
def exportObj(path, obj):
    """This function exports a specific object to a chosen path as an .obj

    :param path: The path you want the object export to. *without the filename!*
    :type path: String
    :param obj: The blender object you want to export.
    :type obj: bpy.types.Object
    :return: Nothing.

    """
    objname = namingUtils.getObjectName(obj)
    oldBlenderObjName = obj.name
    obj.name = 'tmp_export_666'  # surely no one will ever name an object like so
    tmpobject = blenderUtils.createPrimitive(objname, 'box', (2.0, 2.0, 2.0))
    tmpobject.data = obj.data  # copy the mesh here
    outpath = determineMeshOutpath(obj, objname, 'obj', path)
    bpy.ops.export_scene.obj(filepath=outpath, use_selection=True, use_normals=True, use_materials=False)
    bpy.ops.object.select_all(action='DESELECT')
    tmpobject.select = True
    bpy.ops.object.delete()
    obj.name = oldBlenderObjName
Ejemplo n.º 21
0
def createInertial(parentname, inertialdict, parentobj=None, helper=False):
    """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: bpy_types.Object -- the newly created blender inertial object.
    """
    size = 0.015 if helper else 0.06
    try:
        origin = mathutils.Vector(inertialdict['pose']['translation'])
    except KeyError:
        origin = mathutils.Vector()
    inertialobject = bUtils.createPrimitive('inertial_' + parentname, 'box',
                                            (size, ) * 3,
                                            defs.layerTypes["inertial"],
                                            'phobos_inertial')
    sUtils.selectObjects((inertialobject, ), clear=True, active=0)
    bpy.ops.object.transform_apply(scale=True)
    inertialobject.phobostype = 'inertial'
    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)
        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'):
        if helper:
            inertialobject[prop] = inertialdict[prop]
        else:
            inertialobject['inertial/' + prop] = inertialdict[prop]
    return inertialobject
Ejemplo n.º 22
0
def createInertial(inertialdict, obj=None):
    """Creates the Blender representation of a given inertial provided a dictionary.

    Args:
        inertialdict(dict): intertial data
        obj(bpy.types.Object): link or visual/collision reference object
    Returns:
        bpy_types.Object: newly created blender inertial object
    """
    size = 0.03

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

    if not isInertiaDataValid(inertialdict):
        return None

    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)
    if obj:
        inertialobject.matrix_world = obj.matrix_world
        parent = obj if obj.phobostype == 'link' else obj.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['inertia/' + prop] = inertialdict[prop]
    return inertialobject
Ejemplo n.º 23
0
def exportStl(path, obj):
    """This function exports a specific object to a chosen path as a .stl

    :param path: The path you want the object exported to. *without filename!*
    :type path: String
    :param obj: The blender object you want to export.
    :type obj: bpy.types.Object
    :return: Nothing.

    """
    objname = namingUtils.getObjectName(obj)
    oldBlenderObjectName = obj.name
    print("OBJNAME: " + objname)
    obj.name = 'tmp_export_666'  # surely no one will ever name an object like so
    tmpobject = blenderUtils.createPrimitive(objname, 'box', (1.0, 1.0, 1.0))
    tmpobject.data = obj.data  # copy the mesh here
    outpath = determineMeshOutpath(obj, objname, 'stl', path)
    bpy.ops.export_mesh.stl(filepath=outpath)
    bpy.ops.object.select_all(action='DESELECT')
    tmpobject.select = True
    bpy.ops.object.delete()
    obj.name = oldBlenderObjectName
Ejemplo n.º 24
0
def createGeometry(viscol, geomsrc):
    """Creates geometrical Blender object for visual or collision objects.

    :param viscol: The visual/collision dictionary element you want to create the geometry for.
    :type viscol: dict
    :param geomsrc: The new viscols phobostype.
    :type geomsrc: str

    """
    if 'geometry' not in viscol or viscol['geometry'] is {}:
        return None
    bpy.ops.object.select_all(action='DESELECT')
    geom = viscol['geometry']
    geomtype = geom['type']
    # create the Blender object
    if geomtype == 'mesh':
        bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc])
        meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1])
        if not os.path.isfile(geom['filename']):
            log(geom['filename'] + " is no file. Object " + viscol['name'] +
                " will have empty mesh!", "ERROR")
            bpy.data.meshes.new(meshname)
        if meshname in bpy.data.meshes:
            log('Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO')
            bpy.ops.object.add(type='MESH')
            newgeom = bpy.context.object
            newgeom.data = bpy.data.meshes[meshname]
        else:
            log('Importing mesh for link element ' + viscol['name'], 'INFO')
            filetype = geom['filename'].split('.')[-1].lower()
            newgeom = meshes.importMesh(geom['filename'], filetype)
            newgeom.data.name = meshname
            if not newgeom:
                log('Failed to import mesh file ' + geom['filename'], 'ERROR')
                return
            # scale imported object
            if 'scale' in geom:
                sUtils.selectObjects((newgeom,), clear=True)
                newgeom.scale = geom['scale']
    else:
        if geomtype == 'box':
            dimensions = geom['size']
        elif geomtype == 'cylinder':
            dimensions = (geom['radius'], geom['length'])
        elif geomtype == 'sphere':
            dimensions = geom['radius']
        else:
            log("Could not determine geometry type of " + geomsrc + viscol['name']
                + '. Placing empty coordinate system.', "ERROR")
            bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2)
            bpy.context.active_object.name = viscol['name']
            return None
        log('Creating primtive for obj ' + viscol['name'], 'INFO')
        newgeom = bUtils.createPrimitive(viscol['name'], geomtype, dimensions, player=geomsrc)
        newgeom.select = True
        bpy.ops.object.transform_apply(scale=True)

    # from here it's the same for both meshes and primitives
    newgeom.phobostype = geomsrc
    newgeom['geometry/type'] = geomtype
    if geomsrc == 'visual':
        try:
            if 'name' in viscol['material']:
                assignMaterial(newgeom, viscol['material']['name'])
            else:
                assignMaterial(newgeom, viscol['material'])
        except KeyError:
            log('No material for obj ' + viscol['name'], 'DEBUG')
    # FIXME: place empty coordinate system and return...what? Error handling of file import!
    for prop in viscol:
        if prop.startswith('$'):
            for tag in viscol[prop]:
                newgeom[prop[1:]+'/'+tag] = viscol[prop][tag]
    newgeom.name = viscol['name']
    newgeom[geomsrc+"/name"] = viscol['name']
    return newgeom
Ejemplo n.º 25
0
def createGeometry(viscol, geomsrc, linkobj=None):
    """Creates Blender object for visual or collision objects.
    Returns reference to new object or None if creation failed.

    Args:
      viscol(dict): visual/collision dictionary element
      geomsrc(str): new object's phobostype
      linkobj(bpy.types.Object): link object

    Returns:
      bpy.types.Object or None

    """
    if 'geometry' not in viscol or viscol['geometry'] is {}:
        return None
    bpy.ops.object.select_all(action='DESELECT')
    geom = viscol['geometry']
    # create the Blender object
    if geom['type'] == 'mesh':
        bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc])
        meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1])
        if not os.path.isfile(geom['filename']):
            log(geom['filename'] + " is no file. Object " + viscol['name'] + " will have empty mesh!", "ERROR")
            #bpy.data.meshes.new(meshname)
            bpy.ops.object.add(type='MESH')
            newgeom = bpy.context.active_object
            nUtils.safelyName(newgeom, viscol['name'], phobostype=geomsrc)
        else:
            if meshname in bpy.data.meshes:
                log('Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO')
                bpy.ops.object.add(type='MESH')
                newgeom = bpy.context.object
                newgeom.data = bpy.data.meshes[meshname]
            else:
                log("Importing mesh for {0} element: '{1}".format(geomsrc, viscol['name']), 'INFO')
                filetype = geom['filename'].split('.')[-1].lower()
                newgeom = meshes.importMesh(geom['filename'], filetype)
                newgeom.data.name = meshname
                if not newgeom:
                    log('Failed to import mesh file ' + geom['filename'], 'ERROR')
                    return
            # scale imported object
            if 'scale' in geom:
                newgeom.scale = geom['scale']
    else:
        if geom['type'] == 'box':
            dimensions = geom['size']
        elif geom['type'] == 'cylinder':
            dimensions = (geom['radius'], geom['length'])
        elif geom['type'] == 'sphere':
            dimensions = geom['radius']
        else:
            log("Unknown geometry type of " + geomsrc + viscol['name']
                + '. Placing empty coordinate system.', "ERROR")
            bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2)
            obj = bpy.context.object
            obj.phobostype = geomsrc
            nUtils.safelyName(bpy.context.active_object, viscol['name'], phobostype=geomsrc)
            return None
        log('Creating primtive for {0}: {1}'.format(geomsrc, viscol['name']), 'INFO')
        newgeom = bUtils.createPrimitive(viscol['name'], geom['type'], dimensions, phobostype=geomsrc)
        newgeom.select = True
        bpy.ops.object.transform_apply(scale=True)

    # from here it's the same for both meshes and primitives
    newgeom['geometry/type'] = geom['type']
    if geomsrc == 'visual':
        try:
            assignMaterial(newgeom, viscol['material'])
        except KeyError:
            log('No material for visual ' + viscol['name'], 'DEBUG')
    for prop in viscol:
        if prop.startswith('$'):
            for tag in viscol[prop]:
                newgeom[prop[1:]+'/'+tag] = viscol[prop][tag]
    nUtils.safelyName(newgeom, viscol['name'])
    newgeom[geomsrc+"/name"] = viscol['name']
    newgeom.phobostype = geomsrc

    # place geometric object relative to its parent link
    if linkobj:
        if 'pose' in viscol:
            log('Setting transformation of element: ' + viscol['name'], 'DEBUG')
            location = mathutils.Matrix.Translation(viscol['pose']['translation'])
            rotation = mathutils.Euler(tuple(viscol['pose']['rotation_euler']), 'XYZ').to_matrix().to_4x4()
        else:
            log('No pose in element: ' + viscol['name'], 'DEBUG')
            location = mathutils.Matrix.Identity(4)
            rotation = mathutils.Matrix.Identity(4)
        sUtils.selectObjects([newgeom, linkobj], True, 1)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')
        newgeom.matrix_local = location * rotation
        if 'scale' in viscol['geometry']:
            newgeom.scale = mathutils.Vector(viscol['geometry']['scale'])
    return newgeom
Ejemplo n.º 26
0
def createGeometry(viscol, geomsrc):
    """Creates geometrical Blender object for visual or collision objects.

    :param viscol: The visual/collision dictionary element you want to create the geometry for.
    :type viscol: dict
    :param geomsrc: The new viscols phobostype.
    :type geomsrc: str

    """
    if 'geometry' not in viscol or viscol['geometry'] is {}:
        return None
    newgeom = None
    bpy.ops.object.select_all(action='DESELECT')
    geom = viscol['geometry']
    geomtype = geom['type']
    # create the Blender object
    if geomtype == 'mesh':
        # if hasattr(self, 'zipped') and self.zipped:
        #     if not os.path.isdir(os.path.join(self.tmp_path, tmp_dir_name)):
        #         os.mkdir(os.path.join(self.tmp_path, tmp_dir_name))
        #     archive = zipfile.ZipFile(self.filepath)
        #     archive.extract(geom['filename'], path=os.path.join(self.tmp_path, tmp_dir_name))
        #     geom_path = os.path.join(os.path.abspath(os.path.join(self.tmp_path, tmp_dir_name)), geom['filename'])
        # else:
        if 'sourcefilepath' in geom:
            geom_path = os.path.normpath(
                os.path.join(os.path.dirname(geom['sourcefilepath']),
                             geom['filename']))
            log('sourcefilepath: ' + geom_path, 'DEBUG', 'createGeometry')
        else:
            geom_path = geom['filename']
        # Remove 'urdf/package://{package_name}' to workaround the lack
        # of rospack here. This supposes that the urdf file is in the
        # urdf folder and that the meshes are in the meshes folder at
        # the same level as the urdf folder.
        if 'package://' in geom_path:
            geom_path = re.sub(r'(.*)urdf/package://([^/]+)/(.*)', '\\1\\3',
                               geom_path)

        bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc])
        meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1])
        if not os.path.isfile(geom_path):
            log(
                geom_path + " is no file. Object " + viscol['name'] +
                " will have empty mesh!", "ERROR", "createGeometry")
            bpy.data.meshes.new(meshname)
        if meshname in bpy.data.meshes:
            log(
                'Assigning copy of existing mesh ' + meshname + ' to ' +
                viscol['name'], 'INFO', 'createGeometry')
            bpy.ops.object.add(type='MESH')
            newgeom = bpy.context.object
            newgeom.data = bpy.data.meshes[meshname]
        else:
            log('Importing mesh for link element ' + viscol['name'], 'INFO',
                'createGeometry')
            filetype = geom['filename'].split('.')[-1].lower()
            newgeom = meshes.importMesh(geom_path, filetype)
            newgeom.data.name = meshname
            if not newgeom:
                log('Failed to import mesh file ' + geom['filename'], 'ERROR',
                    'createGeometry')
                return
            # scale imported object
            if 'scale' in geom:
                sUtils.selectObjects((newgeom, ), clear=True)
                newgeom.scale = geom['scale']
    else:
        if geomtype == 'box':
            dimensions = geom['size']
        elif geomtype == 'cylinder':
            dimensions = (geom['radius'], geom['length'])
        elif geomtype == 'sphere':
            dimensions = geom['radius']
        else:
            log(
                "Could not determine geometry type of " + geomsrc +
                viscol['name'] + '. Placing empty coordinate system.', "ERROR")
            bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2)
            bpy.context.active_object.name = viscol['name']
            return None
        log('Creating primitve for obj ' + viscol['name'], 'INFO',
            'createGeometry')
        newgeom = bUtils.createPrimitive(viscol['name'],
                                         geomtype,
                                         dimensions,
                                         player=geomsrc)
        newgeom.select = True
        bpy.ops.object.transform_apply(scale=True)

    # from here it's the same for both meshes and primitives
    newgeom.phobostype = geomsrc
    newgeom['geometry/type'] = geomtype
    if geomsrc == 'visual':
        try:
            if 'name' in viscol['material']:
                assignMaterial(newgeom, viscol['material']['name'])
            else:
                assignMaterial(newgeom, viscol['material'])
        except KeyError:
            log('No material for obj', viscol['name'], 'DEBUG',
                'createGeometry')
    #FIXME: place empty coordinate system and return...what? Error handling of file import!
    for prop in viscol:
        if prop.startswith('$'):
            for tag in viscol[prop]:
                newgeom[prop[1:] + '/' + tag] = viscol[prop][tag]
    newgeom.name = viscol['name']
    newgeom[geomsrc + "/name"] = viscol['name']
    return newgeom
Ejemplo n.º 27
0
def createSensor(sensor, reference, origin=mathutils.Matrix()):
    """This function creates a new sensor specified by its parameters.

    :param sensor: The phobos representation of the new sensor.
    :type sensor: dict
    :param reference: This is an object to add a parent relationship to.
    :type reference: bpy_types.Object
    :param origin: The new sensors origin.
    :type origin: mathutils.Matrix
    :return: The newly created sensor object

    """
    blenderUtils.toggleLayer(defs.layerTypes['sensor'], value=True)
    # create sensor object
    if 'Camera' in sensor['type']:
        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, 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:
            selectionUtils.selectObjects([newsensor, reference], 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 sensor['type'] == 'Joint6DOF':
            pass #newsensor['sensor/nodes'] = nameUtils.getObjectName(reference)
        elif 'Node' in sensor['type']:
            newsensor['sensor/nodes'] = sorted([nameUtils.getObjectName(ref) for ref in reference])
        elif 'Joint' in sensor['type'] or 'Motor' in sensor['type']:
            newsensor['sensor/joints'] = sorted([nameUtils.getObjectName(ref) for ref in reference])
        if reference is not None:
            selectionUtils.selectObjects([newsensor, reference], 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 ['link', 'joint', 'links', 'joints', 'motors']:
    #    if prop in sensor:
    #        newsensor['sensor/'+prop] = sensor[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
Ejemplo n.º 28
0
def createSensor(sensor, reference, origin=mathutils.Matrix()):
    """This function creates a new sensor specified by its parameters.
    
    The sensor dictionary has to contain these keys:
        *name*: name of the new sensor
        *type*: type specifier of the sensor
        *shape*: a shape specifier for the sensor
        *props*: custom properties to be written to the sensor object

    Args:
      sensor(dict): phobos representation of the new sensor
      reference(bpy_types.Object): object to add a parent relationship to
      origin(mathutils.Matrix, optional): new sensors origin (Default value = mathutils.Matrix())

    Returns:
      : The newly created sensor object

    """
    layers = defs.layerTypes['sensor']
    bUtils.toggleLayer(layers, value=True)

    # create sensor object
    if sensor['shape'].startswith('resource'):
        newsensor = bUtils.createPrimitive(
            sensor['name'],
            'box',
            [1, 1, 1],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=sensor['material'],
            phobostype='sensor',
        )
        # use resource name provided as: "resource:whatever_name"
        resource_obj = ioUtils.getResource(['sensor'] + sensor['shape'].split('://')[1].split('_'))
        if resource_obj:
            log("Assigned resource mesh and materials to new sensor object.", 'DEBUG')
            newsensor.data = resource_obj.data
            newsensor.scale = (sensor['size'],) * 3
        else:
            log("Could not use resource mesh for sensor. Default cube used instead.", 'WARNING')
    else:
        newsensor = bUtils.createPrimitive(
            sensor['name'],
            sensor['shape'],
            sensor['size'],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=sensor['material'],
            phobostype='sensor',
        )

    # assign the parent if available
    if reference is not None:
        eUtils.parentObjectsTo(newsensor, reference)

    # TODO we need to deal with other types of parameters for sensors

    # TODO cameraRotLock() use or dispose?
    # contact, force and torque sensors (or unknown sensors)
    # else:
    #    newsensor = bUtils.createPrimitive(
    #        sensor['name'], 'ico', 0.05, layers, 'phobos_sensor',
    #        origin.to_translation(), protation=origin.to_euler())
    #    if sensor['name'] == 'Joint6DOF':
    #        # TODO delete me? handle this
    #        #newsensor['sensor/nodes'] = nUtils.getObjectName(reference)
    #        pass
    #    elif 'Node' in sensor['type']:
    #        newsensor['sensor/nodes'] = sorted([nUtils.getObjectName(ref) for ref in reference])
    #    elif 'Joint' in sensor['type'] or 'Motor' in sensor['type']:
    #        newsensor['sensor/joints'] = sorted([nUtils.getObjectName(ref) for ref in reference])
    #         elif sensor['type'] in ['Joint6DOF']:
    #             for obj in context.selected_objects:
    #                 if obj.phobostype == 'link':
    #                     sensor['name'] = "sensor_joint6dof_" + nUtils.getObjectName(obj, phobostype="joint")
    #                     sensors.createSensor(sensor, obj, obj.matrix_world)
    #         elif 'Node' in sensor['type']:
    #             sensors.createSensor(sensor, [obj for obj in context.selected_objects if obj.phobostype == 'collision'],
    #                          mathutils.Matrix.Translation(context.scene.cursor_location))
    #         elif 'Motor' in sensor['type'] or 'Joint' in sensor['type']:
    #             sensors.createSensor(sensor, [obj for obj in context.selected_objects if obj.phobostype == 'link'],
    #                          mathutils.Matrix.Translation(context.scene.cursor_location))

    # set sensor properties
    newsensor.phobostype = 'sensor'
    newsensor.name = sensor['name']
    newsensor['sensor/name'] = sensor['name']
    newsensor['sensor/type'] = sensor['type']

    # write the custom properties to the sensor
    eUtils.addAnnotation(newsensor, sensor['props'], namespace='sensor')

    # throw warning if type is not known
    # TODO we need to link this error to the sensor type specifications
    if sensor['type'] not in [key.lower() for key in defs.def_settings['sensors']]:
        log(
            "Sensor " + sensor['name'] + " is of unknown/custom type: " + sensor['type'] + ".",
            'WARNING',
        )

    # select the new sensor
    sUtils.selectObjects([newsensor], clear=True, active=0)
    return newsensor
Ejemplo n.º 29
0
    def execute(self, context):
        """Executes this blender operator and creates collision objects for the selected bodies.

        :param context: The blender context this function should work with.

        :return: set -- the blender specific return set.

        """

        startLog(self)
        visuals = []
        for obj in bpy.context.selected_objects:
            if obj.phobostype == "visual":
                visuals.append(obj)
            obj.select = False

        if not visuals:
            # bpy.ops.error.message('INVOKE_DEFAULT', type="CreateCollisions Error", message="Not enough bodies selected.")
            log("Not enough bodies selected.", "ERROR")
            return {'CANCELLED'}
        for vis in visuals:
            nameparts = vis.name.split('_')
            if nameparts[0] == 'visual':
                nameparts[0] = 'collision'
            collname = '_'.join(nameparts)
            materialname = vis.data.materials[0].name if len(vis.data.materials) > 0 else "None"
            bBox = vis.bound_box
            center = generalUtils.calcBoundingBoxCenter(bBox)
            rotation = mathutils.Matrix.Identity(4)
            size = list(vis.dimensions)
            if self.property_colltype in ['cylinder', 'capsule']:
                axes = ('X', 'Y', 'Z')
                long_side = axes[size.index(max(size))]
                # xyequal = (size[0] - size[1])
                length = max(size)
                radii = [s for s in size if s != length]
                radius = max(radii) / 2 if radii != [] else length / 2
                size = (radius, length)
                if long_side == 'X':
                    rotation = mathutils.Matrix.Rotation(math.pi / 2, 4, 'Y')
                elif long_side == 'Y':
                    rotation = mathutils.Matrix.Rotation(math.pi / 2, 4, 'X')
                    # FIXME: apply rotation for moved cylinder object?
            elif self.property_colltype == 'sphere':
                size = max(size) / 2
            rotation_euler = (vis.matrix_world * rotation).to_euler()
            center = vis.matrix_world.to_translation() + vis.matrix_world.to_quaternion() * center
            if self.property_colltype != 'capsule':
                ob = blenderUtils.createPrimitive(collname, self.property_colltype, size,
                                             defs.layerTypes['collision'], materialname, center,
                                             rotation_euler)
            elif self.property_colltype == 'capsule':
                length = max(length - 2 * radius, 0.001)  # prevent length from turning negative
                size = (radius, length)
                zshift = length / 2
                ob = blenderUtils.createPrimitive(collname, 'cylinder', size,
                                             defs.layerTypes['collision'], materialname, center,
                                             rotation_euler)
                sph1 = blenderUtils.createPrimitive('tmpsph1', 'sphere', radius,
                                               defs.layerTypes['collision'], materialname,
                                               center + rotation * mathutils.Vector((0, 0, zshift)),
                                               rotation_euler)
                sph2 = blenderUtils.createPrimitive('tmpsph2', 'sphere', radius,
                                               defs.layerTypes['collision'], materialname,
                                               center - rotation * mathutils.Vector((0, 0, zshift)),
                                               rotation_euler)
                selectionUtils.selectObjects([ob, sph1, sph2], True, 0)
                bpy.ops.object.join()
                ob['length'] = length
                ob['radius'] = radius
            elif self.property_colltype == 'mesh':
                pass
                # TODO: copy mesh!!
            ob.phobostype = 'collision'
            ob['geometry/type'] = self.property_colltype
            if vis.parent:
                ob.select = True
                bpy.ops.object.transform_apply(scale=True)
                vis.parent.select = True
                bpy.context.scene.objects.active = vis.parent
                bpy.ops.object.parent_set(type='BONE_RELATIVE')
                # ob.parent_type = vis.parent_type
                # ob.parent_bone = vis.parent_bone
        endLog()
        return {'FINISHED'}
Ejemplo n.º 30
0
def createMotor(motor,
                parentobj,
                origin=mathutils.Matrix(),
                addcontrollers=False):
    """This function creates a new motor specified by its parameters.

    If *addcontrollers* is set, a controller object will be created from the controller definition
    which is specified in the motor dictionary (key *controller*).

    Args:
      motor(dict): phobos representation of the new motor.
      parentobj(bpy_types.Object): object to parent new motor to
      origin(mathutils.Matrix, optional): new motors origin (Default value = mathutils.Matrix())
      addcontrollers(bool, optional): whether to add the defined controller as object (Default value = False)

    Returns:
      bpy.types.Object: new motor object or a list of the new motor_object and the new controller object

    """
    bUtils.toggleLayer('motor', value=True)

    primitive_name = ''

    # create name if not given by motor dict
    if not 'name' in motor or len(motor['name']) == 0:
        motor['name'] = parentobj.name
        primitive_name = "motor_" + motor['name']
    else:
        primitive_name = motor['name']

    primitive_name = ''

    # create name if not given by motor dict
    if not 'name' in motor or len(motor['name']) == 0:
        motor['name'] = parentobj.name
        primitive_name = "motor_" + motor['name']
    else:
        primitive_name = motor['name']

    # create motor object
    if motor['shape'].startswith('resource'):
        newmotor = bUtils.createPrimitive(
            primitive_name,
            'box',
            [1, 1, 1],
            [],
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=motor['material'],
            phobostype='motor',
        )
        # use resource name provided as: "resource:whatever_name"
        resource_obj = ioUtils.getResource(
            ['motor'] + motor['shape'].split('://')[1].split('_'))
        if resource_obj:
            log("Assigned resource mesh and materials to new motor object.",
                'DEBUG')
            newmotor.data = resource_obj.data
            newmotor.scale = (motor['size'], ) * 3
        else:
            log(
                "Could not use resource mesh for motor. Default cube used instead.",
                'WARNING')
    else:
        newmotor = bUtils.createPrimitive(
            primitive_name,
            motor['shape'],
            motor['size'],
            [],
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=motor['material'],
            phobostype='motor',
        )

    # assign the parent if available
    if parentobj is not None:
        sUtils.selectObjects([newmotor, parentobj], clear=True, active=1)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')

    # set motor properties
    newmotor.phobostype = 'motor'
    # should not be nessaccary: newmotor.name = motor['name']
    defname = motor['defname']

    # write the custom properties to the motor
    eUtils.addAnnotation(newmotor,
                         motor['props'],
                         namespace='motor',
                         ignore=['defname'])
    # fix motor name since it can differe from object name
    newmotor['motor/name'] = motor['name']

    if 'controller' in defs.definitions['motors'][defname] and addcontrollers:
        import phobos.model.controllers as controllermodel

        motorcontroller = defs.definitions['motors'][defname]['controller']
        controllerdefs = ioUtils.getDictFromYamlDefs(
            'controller', motorcontroller, newmotor.name + '_controller')
        newcontroller = controllermodel.createController(
            controllerdefs,
            newmotor,
            origin=newmotor.matrix_world,
            annotations='all')
    else:
        newcontroller = None

    # select the new motor
    sUtils.selectObjects(
        [newmotor] if not newcontroller else [newmotor, newcontroller],
        clear=True,
        active=0)
    return newmotor if not newcontroller else [newmotor, newcontroller]
Ejemplo n.º 31
0
def createController(controller, reference, origin=mathutils.Matrix(), annotations=None):
    """This function creates a new controller specified by its parameters.
    
    If an annotation category or the keyword 'all' is specified, the respective annotations for the
    controller will be added as objects.

    Args:
      controller(dict): phobos representation of the new controller
      reference(bpy_types.Object): object to add a parent relationship to
      origin(mathutils.Matrix, optional): new controllers origin (Default value = mathutils.Matrix())
      annotations(list(str, optional): list of annotation keys or 'all' to add to as annotation
    objects (Default value = None)

    Returns:
      : bpy.types.Object -- new created controller object

    """
    layers = defs.layerTypes['controller']
    bUtils.toggleLayer(layers, value=True)

    # create controller object
    if controller['shape'].startswith('resource'):
        newcontroller = bUtils.createPrimitive(
            controller['name'],
            'box',
            [1, 1, 1],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=controller['material'],
            phobostype='controller',
        )
        # use resource name provided as: "resource:whatever_name"
        resource_obj = ioUtils.getResource(
            ['controller'] + controller['shape'].split('://')[1].split('_')
        )
        if resource_obj:
            log("Assigned resource mesh and materials to new controller object.", 'DEBUG')
            newcontroller.data = resource_obj.data
            newcontroller.scale = (controller['size'],) * 3
        else:
            log("Could not use resource mesh for controller. Default cube used instead.", 'WARNING')
    else:
        newcontroller = bUtils.createPrimitive(
            controller['name'],
            controller['shape'],
            controller['size'],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=controller['material'],
            phobostype='controller',
        )

    newcontroller.name = controller['name']
    newcontroller['controller/type'] = controller['type']

    # write the custom properties to the controller
    eUtils.addAnnotation(newcontroller, controller['props'], namespace='controller')

    if controller['annotations'] and annotations:
        if annotations == 'all':
            keys = controller['annotations'].keys()
        elif isinstance(annotations, list):
            keys = [key for key in annotations if key in controller['annotations']]
        else:
            keys = []
        for key in keys:
            eUtils.addAnnotationObject(
                newcontroller, controller['annotations'][key], namespace='controller/' + key
            )

    # assign the parent if available
    if reference is not None:
        sUtils.selectObjects([newcontroller, reference], clear=True, active=1)

        if reference.phobostype == 'link':
            bpy.ops.object.parent_set(type='BONE_RELATIVE')
        else:
            bpy.ops.object.parent_set(type='OBJECT')

    return newcontroller
Ejemplo n.º 32
0
def createSensor(sensor, reference, origin=mathutils.Matrix()):
    """This function creates a new sensor specified by its parameters.
    
    The sensor dictionary has to contain these keys:
        *name*: name of the new sensor
        *type*: type specifier of the sensor
        *shape*: a shape specifier for the sensor
        *props*: custom properties to be written to the sensor object

    Args:
      sensor(dict): phobos representation of the new sensor
      reference(bpy_types.Object): object to add a parent relationship to
      origin(mathutils.Matrix, optional): new sensors origin (Default value = mathutils.Matrix())

    Returns:
      : The newly created sensor object

    """
    layers = defs.layerTypes['sensor']
    bUtils.toggleLayer(layers, value=True)

    # create sensor object
    if sensor['shape'].startswith('resource'):
        newsensor = bUtils.createPrimitive(
            sensor['name'],
            'box',
            [1, 1, 1],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=sensor['material'],
            phobostype='sensor',
        )
        # use resource name provided as: "resource:whatever_name"
        resource_obj = ioUtils.getResource(
            ['sensor'] + sensor['shape'].split('://')[1].split('_'))
        if resource_obj:
            log("Assigned resource mesh and materials to new sensor object.",
                'DEBUG')
            newsensor.data = resource_obj.data
            newsensor.scale = (sensor['size'], ) * 3
        else:
            log(
                "Could not use resource mesh for sensor. Default cube used instead.",
                'WARNING')
    else:
        newsensor = bUtils.createPrimitive(
            sensor['name'],
            sensor['shape'],
            sensor['size'],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=sensor['material'],
            phobostype='sensor',
        )

    # assign the parent if available
    if reference is not None:
        eUtils.parentObjectsTo(newsensor, reference)

    # TODO we need to deal with other types of parameters for sensors

    # TODO cameraRotLock() use or dispose?
    # contact, force and torque sensors (or unknown sensors)
    # else:
    #    newsensor = bUtils.createPrimitive(
    #        sensor['name'], 'ico', 0.05, layers, 'phobos_sensor',
    #        origin.to_translation(), protation=origin.to_euler())
    #    if sensor['name'] == 'Joint6DOF':
    #        # TODO delete me? handle this
    #        #newsensor['sensor/nodes'] = nUtils.getObjectName(reference)
    #        pass
    #    elif 'Node' in sensor['type']:
    #        newsensor['sensor/nodes'] = sorted([nUtils.getObjectName(ref) for ref in reference])
    #    elif 'Joint' in sensor['type'] or 'Motor' in sensor['type']:
    #        newsensor['sensor/joints'] = sorted([nUtils.getObjectName(ref) for ref in reference])
    #         elif sensor['type'] in ['Joint6DOF']:
    #             for obj in context.selected_objects:
    #                 if obj.phobostype == 'link':
    #                     sensor['name'] = "sensor_joint6dof_" + nUtils.getObjectName(obj, phobostype="joint")
    #                     sensors.createSensor(sensor, obj, obj.matrix_world)
    #         elif 'Node' in sensor['type']:
    #             sensors.createSensor(sensor, [obj for obj in context.selected_objects if obj.phobostype == 'collision'],
    #                          mathutils.Matrix.Translation(context.scene.cursor_location))
    #         elif 'Motor' in sensor['type'] or 'Joint' in sensor['type']:
    #             sensors.createSensor(sensor, [obj for obj in context.selected_objects if obj.phobostype == 'link'],
    #                          mathutils.Matrix.Translation(context.scene.cursor_location))

    # set sensor properties
    newsensor.phobostype = 'sensor'
    newsensor.name = sensor['name']
    newsensor['sensor/name'] = sensor['name']
    newsensor['sensor/type'] = sensor['type']

    # write the custom properties to the sensor
    eUtils.addAnnotation(newsensor, sensor['props'], namespace='sensor')

    # throw warning if type is not known
    # TODO we need to link this error to the sensor type specifications
    if sensor['type'] not in [
            key.lower() for key in defs.def_settings['sensors']
    ]:
        log(
            "Sensor " + sensor['name'] + " is of unknown/custom type: " +
            sensor['type'] + ".",
            'WARNING',
        )

    # select the new sensor
    sUtils.selectObjects([newsensor], clear=True, active=0)
    return newsensor
Ejemplo n.º 33
0
def createGeometry(viscol, geomsrc, linkobj=None):
    """Creates Blender object for visual or collision objects.
    
    If the creation fails, nothing is returned.
    
    These entries in the dictionary are mandatory:
    
    |   **geometry**:
    |       **type**: type of geometry (mesh, box, cylinder, sphere)
    
    Depending on the geometry type other values are required: `size`, `radius`, `length`
    
    These entries are optional:
    
    |   **geometry**:
    |       **scale**: scale for the new geometry
    |   **material**: material name to assign to the visual
    |   **pose**: specifies the placement of the new object relative to the optional linkobj
    |       **translation**: position vector for the new object
    |       **rotation_euler**: rotation for the new object
    
    Furthermore any generic properties, prepended by a ``$`` will be added as custom properties to
    the visual/collision object. E.g. ``$test/etc`` would be put to visual/test/etc for a visual
    object. However, these properties are extracted only in the first layer of hierarchy.

    Args:
      viscol(dict): visual/collision model dictionary representation
      geomsrc(str): phobostype of the new object
      linkobj(bpy.types.Object, optional): link object to attach the visual/collision object to
    (Default value = None)

    Returns:
      bpy.types.Object or None: the new geometry object or nothing

    """
    if 'geometry' not in viscol or viscol['geometry'] is {}:
        log("Could not create {}. Geometry information not defined!".format(geomsrc), 'ERROR')
        return None

    bpy.ops.object.select_all(action='DESELECT')
    geom = viscol['geometry']

    # create the Blender object
    if geom['type'] == 'mesh':
        bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc])
        meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1])
        if not os.path.isfile(geom['filename']):
            log(
                "This path "
                + geom['filename']
                + " is no file. Object "
                + viscol['name']
                + " will have empty mesh!",
                'ERROR',
            )
            bpy.ops.object.add(type='MESH')
            newgeom = bpy.context.active_object
            nUtils.safelyName(newgeom, viscol['name'], phobostype=geomsrc)
        else:
            if meshname in bpy.data.meshes:
                log('Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO')
                bpy.ops.object.add(type='MESH')
                newgeom = bpy.context.object
                newgeom.data = bpy.data.meshes[meshname]
            else:
                log("Importing mesh for {0} element: '{1}".format(geomsrc, viscol['name']), 'INFO')
                filetype = geom['filename'].split('.')[-1].lower()
                newgeom = meshes.importMesh(geom['filename'], filetype)
                # bpy.data.meshes[newgeom].name = meshname
                if not newgeom:
                    log('Failed to import mesh file ' + geom['filename'], 'ERROR')
                    return
    else:
        if geom['type'] == 'box':
            dimensions = geom['size']
        elif geom['type'] == 'cylinder':
            dimensions = (geom['radius'], geom['length'])
        elif geom['type'] == 'sphere':
            dimensions = geom['radius']
        # TODO add support for heightmap, image, plane and polyline geometries (see sdf!)
        else:
            log(
                "Unknown geometry type of "
                + geomsrc
                + viscol['name']
                + '. Placing empty coordinate system.',
                "ERROR",
            )
            bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2)
            obj = bpy.context.object
            obj.phobostype = geomsrc
            nUtils.safelyName(bpy.context.active_object, viscol['name'], phobostype=geomsrc)
            return None
        log("Creating primtive for {0}: {1}".format(geomsrc, viscol['name']), 'INFO')
        newgeom = bUtils.createPrimitive(
            viscol['name'], geom['type'], dimensions, phobostype=geomsrc
        )
        newgeom.select = True
        bpy.ops.object.transform_apply(scale=True)

    # from here it's the same for both meshes and primitives
    newgeom['geometry/type'] = geom['type']
    if geomsrc == 'visual':
        if 'material' in viscol:
            assignMaterial(newgeom, viscol['material'])
        else:
            log('No material for visual {}.'.format(viscol['name']), 'WARNING')

    # write generic custom properties
    for prop in viscol:
        if prop.startswith('$'):
            for tag in viscol[prop]:
                newgeom[prop[1:] + '/' + tag] = viscol[prop][tag]

    nUtils.safelyName(newgeom, viscol['name'])
    newgeom[geomsrc + '/name'] = viscol['name']
    newgeom.phobostype = geomsrc

    # place geometric object relative to its parent link
    if linkobj:
        if 'pose' in viscol:
            log("Setting transformation of element: " + viscol['name'], 'DEBUG')
            location = mathutils.Matrix.Translation(viscol['pose']['translation'])
            rotation = (
                mathutils.Euler(tuple(viscol['pose']['rotation_euler']), 'XYZ').to_matrix().to_4x4()
            )
        else:
            log("No pose in element: " + viscol['name'], 'DEBUG')
            location = mathutils.Matrix.Identity(4)
            rotation = mathutils.Matrix.Identity(4)
        eUtils.parentObjectsTo(newgeom, linkobj)
        newgeom.matrix_local = location * rotation

    # scale imported object
    if 'scale' in geom:
        newgeom.scale = geom['scale']

    # make object smooth
    eUtils.smoothen_surface(newgeom)

    return newgeom
Ejemplo n.º 34
0
def createController(controller,
                     reference,
                     origin=mathutils.Matrix(),
                     annotations=None):
    """This function creates a new controller specified by its parameters.
    
    If an annotation category or the keyword 'all' is specified, the respective annotations for the
    controller will be added as objects.

    Args:
      controller(dict): phobos representation of the new controller
      reference(bpy_types.Object): object to add a parent relationship to
      origin(mathutils.Matrix, optional): new controllers origin (Default value = mathutils.Matrix())
      annotations(list(str, optional): list of annotation keys or 'all' to add to as annotation
    objects (Default value = None)

    Returns:
      : bpy.types.Object -- new created controller object

    """
    bUtils.toggleLayer('controller', value=True)

    # create controller object
    if controller['shape'].startswith('resource'):
        newcontroller = bUtils.createPrimitive(
            controller['name'],
            'box',
            [1, 1, 1],
            [],
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=controller['material'],
            phobostype='controller',
        )
        # use resource name provided as: "resource:whatever_name"
        resource_obj = ioUtils.getResource(
            ['controller'] + controller['shape'].split('://')[1].split('_'))
        if resource_obj:
            log(
                "Assigned resource mesh and materials to new controller object.",
                'DEBUG')
            newcontroller.data = resource_obj.data
            newcontroller.scale = (controller['size'], ) * 3
        else:
            log(
                "Could not use resource mesh for controller. Default cube used instead.",
                'WARNING')
    else:
        newcontroller = bUtils.createPrimitive(
            controller['name'],
            controller['shape'],
            controller['size'],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=controller['material'],
            phobostype='controller',
        )

    newcontroller.name = controller['name']
    newcontroller['controller/type'] = controller['type']

    # write the custom properties to the controller
    eUtils.addAnnotation(newcontroller,
                         controller['props'],
                         namespace='controller')

    if controller['annotations'] and annotations:
        if annotations == 'all':
            keys = controller['annotations'].keys()
        elif isinstance(annotations, list):
            keys = [
                key for key in annotations if key in controller['annotations']
            ]
        else:
            keys = []
        for key in keys:
            eUtils.addAnnotationObject(newcontroller,
                                       controller['annotations'][key],
                                       namespace='controller/' + key)

    # assign the parent if available
    if reference is not None:
        sUtils.selectObjects([newcontroller, reference], clear=True, active=1)

        if reference.phobostype == 'link':
            bpy.ops.object.parent_set(type='BONE_RELATIVE')
        else:
            bpy.ops.object.parent_set(type='OBJECT')

    return newcontroller
Ejemplo n.º 35
0
def createGeometry(viscol, geomsrc, linkobj=None):
    """Creates Blender object for visual or collision objects.
    
    If the creation fails, nothing is returned.
    
    These entries in the dictionary are mandatory:
    
    |   **geometry**:
    |       **type**: type of geometry (mesh, box, cylinder, sphere)
    
    Depending on the geometry type other values are required: `size`, `radius`, `length`
    
    These entries are optional:
    
    |   **geometry**:
    |       **scale**: scale for the new geometry
    |   **material**: material name to assign to the visual
    |   **pose**: specifies the placement of the new object relative to the optional linkobj
    |       **translation**: position vector for the new object
    |       **rotation_euler**: rotation for the new object
    
    Furthermore any generic properties, prepended by a ``$`` will be added as custom properties to
    the visual/collision object. E.g. ``$test/etc`` would be put to visual/test/etc for a visual
    object. However, these properties are extracted only in the first layer of hierarchy.

    Args:
      viscol(dict): visual/collision model dictionary representation
      geomsrc(str): phobostype of the new object
      linkobj(bpy.types.Object, optional): link object to attach the visual/collision object to
    (Default value = None)

    Returns:
      bpy.types.Object or None: the new geometry object or nothing

    """
    if 'geometry' not in viscol or viscol['geometry'] is {}:
        log("Could not create {}. Geometry information not defined!".format(geomsrc), 'ERROR')
        return None

    bpy.ops.object.select_all(action='DESELECT')
    geom = viscol['geometry']

    # create the Blender object
    if geom['type'] == 'mesh':
        bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc])
        meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1])
        if not os.path.isfile(geom['filename']):
            log(
                "This path "
                + geom['filename']
                + " is no file. Object "
                + viscol['name']
                + " will have empty mesh!",
                'ERROR',
            )
            bpy.ops.object.add(type='MESH')
            newgeom = bpy.context.active_object
            nUtils.safelyName(newgeom, viscol['name'], phobostype=geomsrc)
        else:
            if meshname in bpy.data.meshes:
                log('Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO')
                bpy.ops.object.add(type='MESH')
                newgeom = bpy.context.object
                newgeom.data = bpy.data.meshes[meshname]
            else:
                log("Importing mesh for {0} element: '{1}".format(geomsrc, viscol['name']), 'INFO')
                filetype = geom['filename'].split('.')[-1].lower()
                newgeom = meshes.importMesh(geom['filename'], filetype)
                # bpy.data.meshes[newgeom].name = meshname
                if not newgeom:
                    log('Failed to import mesh file ' + geom['filename'], 'ERROR')
                    return
    else:
        if geom['type'] == 'box':
            dimensions = geom['size']
        elif geom['type'] == 'cylinder':
            dimensions = (geom['radius'], geom['length'])
        elif geom['type'] == 'sphere':
            dimensions = geom['radius']
        # TODO add support for heightmap, image, plane and polyline geometries (see sdf!)
        else:
            log(
                "Unknown geometry type of "
                + geomsrc
                + viscol['name']
                + '. Placing empty coordinate system.',
                "ERROR",
            )
            bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2)
            obj = bpy.context.object
            obj.phobostype = geomsrc
            nUtils.safelyName(bpy.context.active_object, viscol['name'], phobostype=geomsrc)
            return None
        log("Creating primtive for {0}: {1}".format(geomsrc, viscol['name']), 'INFO')
        newgeom = bUtils.createPrimitive(
            viscol['name'], geom['type'], dimensions, phobostype=geomsrc
        )
        newgeom.select = True
        bpy.ops.object.transform_apply(scale=True)

    # from here it's the same for both meshes and primitives
    newgeom['geometry/type'] = geom['type']
    if geomsrc == 'visual':
        if 'material' in viscol:
            assignMaterial(newgeom, viscol['material'])
        else:
            log('No material for visual {}.'.format(viscol['name']), 'WARNING')

    # write generic custom properties
    for prop in viscol:
        if prop.startswith('$'):
            for tag in viscol[prop]:
                newgeom[prop[1:] + '/' + tag] = viscol[prop][tag]

    nUtils.safelyName(newgeom, viscol['name'])
    newgeom[geomsrc + '/name'] = viscol['name']
    newgeom.phobostype = geomsrc

    # place geometric object relative to its parent link
    if linkobj:
        if 'pose' in viscol:
            log("Setting transformation of element: " + viscol['name'], 'DEBUG')
            location = mathutils.Matrix.Translation(viscol['pose']['translation'])
            rotation = (
                mathutils.Euler(tuple(viscol['pose']['rotation_euler']), 'XYZ').to_matrix().to_4x4()
            )
        else:
            log("No pose in element: " + viscol['name'], 'DEBUG')
            location = mathutils.Matrix.Identity(4)
            rotation = mathutils.Matrix.Identity(4)
        eUtils.parentObjectsTo(newgeom, linkobj)
        newgeom.matrix_local = location * rotation

    # scale imported object
    if 'scale' in geom:
        newgeom.scale = geom['scale']

    # make object smooth
    eUtils.smoothen_surface(newgeom)

    return newgeom
Ejemplo n.º 36
0
def createSensor(sensor, reference, origin=mathutils.Matrix()):
    """This function creates a new sensor specified by its parameters.

    :param sensor: The phobos representation of the new sensor.
    :type sensor: dict
    :param reference: This is an object to add a parent relationship to.
    :type reference: bpy_types.Object
    :param origin: The new sensors origin.
    :type origin: mathutils.Matrix
    :return: The newly created sensor object

    """
    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)
    # set sensor properties
    newsensor.phobostype = 'sensor'
    newsensor.name = sensor['name']
    newsensor['sensor/type'] = sensor['type']

    #for prop in ['link', 'joint', 'links', 'joints', 'motors']:
    #    if prop in sensor:
    #        newsensor['sensor/'+prop] = sensor[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
Ejemplo n.º 37
0
def createSensor(sensor, reference, origin=mathutils.Matrix()):
    """This function creates a new sensor specified by its parameters.

    Args:
      sensor(dict): The phobos representation of the new sensor.
      reference(bpy_types.Object): This is an object to add a parent relationship to.
      origin(mathutils.Matrix, optional): The new sensors origin. (Default value = mathutils.Matrix()

    Returns:
      The newly created sensor object

    """
    bUtils.toggleLayer(defs.layerTypes['sensor'], value=True)
    # create sensor object
    if 'Camera' in sensor['type']:
        bpy.ops.object.add(type='CAMERA',
                           location=origin.to_translation(),
                           rotation=origin.to_euler(),
                           layers=bUtils.defLayers([defs.layerTypes['sensor']
                                                    ]))
        newsensor = bpy.context.active_object
        if reference is not None:
            sUtils.selectObjects([newsensor, 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 = bUtils.createPrimitive(sensor['name'],
                                           'disc', (0.5, 36),
                                           defs.layerTypes['sensor'],
                                           'phobos_laserscanner',
                                           origin.to_translation(),
                                           protation=origin.to_euler())
        if reference is not None:
            sUtils.selectObjects([newsensor, reference], clear=True, active=1)
            bpy.ops.object.parent_set(type='BONE_RELATIVE')
    # contact, force and torque sensors (or unknown sensors)
    else:
        newsensor = bUtils.createPrimitive(sensor['name'],
                                           'sphere',
                                           0.05,
                                           defs.layerTypes['sensor'],
                                           'phobos_sensor',
                                           origin.to_translation(),
                                           protation=origin.to_euler())
        if sensor['type'] == 'Joint6DOF':
            # TODO delete me? handle this
            #newsensor['sensor/nodes'] = nUtils.getObjectName(reference)
            pass
        elif 'Node' in sensor['type']:
            newsensor['sensor/nodes'] = sorted(
                [nUtils.getObjectName(ref) for ref in reference])
        elif 'Joint' in sensor['type'] or 'Motor' in sensor['type']:
            newsensor['sensor/joints'] = sorted(
                [nUtils.getObjectName(ref) for ref in reference])
        if reference is not None:
            sUtils.selectObjects([newsensor, reference], 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']

    # TODO delete me?
    #for prop in ['link', 'joint', 'links', 'joints', 'motors']:
    #    if prop in sensor:
    #        newsensor['sensor/'+prop] = sensor[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.")
    sUtils.selectObjects([newsensor], clear=False, active=0)
    return newsensor
Ejemplo n.º 38
0
    def execute(self, context):
        visuals = []
        collisions = []

        # find all selected visual objects
        for obj in context.selected_objects:
            if obj.phobostype == "visual":
                visuals.append(obj)
            obj.select = False

        if not visuals:
            log("No visual objects selected.", "ERROR", self)
            return {'CANCELLED'}

        # create collision objects for each visual
        for vis in visuals:
            # build object names
            nameparts = vis.name.split('_')
            if nameparts[0] == 'visual':
                nameparts[0] = 'collision'
            collname = '_'.join(nameparts)
            materialname = vis.data.materials[0].name if len(
                vis.data.materials) > 0 else "None"

            # get bounding box
            bBox = vis.bound_box
            center = gUtils.calcBoundingBoxCenter(bBox)
            rotation = mathutils.Matrix.Identity(4)
            size = list(vis.dimensions)

            # calculate size for cylinder, capsule or sphere
            if self.property_colltype in ['cylinder', 'capsule']:
                axes = ('X', 'Y', 'Z')
                long_side = axes[size.index(max(size))]
                length = max(size)
                radii = [s for s in size if s != length]
                radius = max(radii) / 2 if radii != [] else length / 2
                size = (radius, length)

                # rotate cylinder/capsule to match longest side
                if long_side == 'X':
                    rotation = mathutils.Matrix.Rotation(math.pi / 2, 4, 'Y')
                elif long_side == 'Y':
                    rotation = mathutils.Matrix.Rotation(math.pi / 2, 4, 'X')
                    # FIXME: apply rotation for moved cylinder object?

            elif self.property_colltype == 'sphere':
                size = max(size) / 2

            # calculate rotation and center coordinates
            rotation_euler = (vis.matrix_world * rotation).to_euler()
            center = vis.matrix_world.to_translation(
            ) + vis.matrix_world.to_quaternion() * center

            # create Mesh
            if self.property_colltype != 'capsule' and self.property_colltype != 'mesh':
                ob = bUtils.createPrimitive(collname, self.property_colltype,
                                            size, defs.layerTypes['collision'],
                                            materialname, center,
                                            rotation_euler)
            elif self.property_colltype == 'capsule':
                # TODO reimplement capsules
                # prevent length from turning negative
                length = max(length - 2 * radius, 0.001)
                size = (radius, length)
                zshift = length / 2
                tmpsph1_location = center + rotation_euler.to_matrix().to_4x4(
                ) * mathutils.Vector((0, 0, zshift))
                tmpsph2_location = center - rotation_euler.to_matrix().to_4x4(
                ) * mathutils.Vector((0, 0, zshift))

                # create cylinder and spheres and join them
                ob = bUtils.createPrimitive(collname, 'cylinder', size,
                                            defs.layerTypes['collision'],
                                            materialname, center,
                                            rotation_euler)
                sph1 = bUtils.createPrimitive('tmpsph1', 'sphere', radius,
                                              defs.layerTypes['collision'],
                                              materialname, tmpsph1_location,
                                              rotation_euler)
                sph2 = bUtils.createPrimitive('tmpsph2', 'sphere', radius,
                                              defs.layerTypes['collision'],
                                              materialname, tmpsph2_location,
                                              rotation_euler)
                sUtils.selectObjects([ob, sph1, sph2], True, 0)
                bpy.ops.object.join()

                # assign capsule properties
                ob['geometry/length'] = length
                ob['geometry/radius'] = radius
                ob['sph1_location'] = tmpsph1_location
                ob['sph2_location'] = tmpsph2_location
            elif self.property_colltype == 'mesh':
                # FIXME: simply turn this into object.duplicate?
                bpy.ops.object.duplicate_move(
                    OBJECT_OT_duplicate={
                        "linked": False,
                        "mode": 'TRANSLATION'
                    },
                    TRANSFORM_OT_translate={"value": (0, 0, 0)})
                # TODO: copy mesh!!

            # set properties of new collision object
            ob.phobostype = 'collision'
            ob['geometry/type'] = self.property_colltype
            collisions.append(ob)

            # make collision object relative if visual object has a parent
            if vis.parent:
                ob.select = True
                bpy.ops.object.transform_apply(scale=True)
                vis.parent.select = True
                context.scene.objects.active = vis.parent
                bpy.ops.object.parent_set(type='BONE_RELATIVE')
                # TODO delete these lines?
                # ob.parent_type = vis.parent_type
                # ob.parent_bone = vis.parent_bone

            # select created collision objects
            sUtils.selectObjects(collisions)
        return {'FINISHED'}
Ejemplo n.º 39
0
def createMotor(motor, parentobj, origin=mathutils.Matrix(), addcontrollers=False):
    """This function creates a new motor specified by its parameters.
    
    If *addcontrollers* is set, a controller object will be created from the controller definition
    which is specified in the motor dictionary (key *controller*).

    Args:
      motor(dict): phobos representation of the new motor.
      parentobj(bpy_types.Object): object to parent new motor to
      origin(mathutils.Matrix, optional): new motors origin (Default value = mathutils.Matrix())
      addcontrollers(bool, optional): whether to add the defined controller as object (Default value = False)

    Returns:
      bpy.types.Object: new motor object or a list of the new motor_object and the new controller object

    """
    layers = defs.layerTypes['motor']
    bUtils.toggleLayer(layers, value=True)

    # create motor object
    if motor['shape'].startswith('resource'):
        newmotor = bUtils.createPrimitive(
            motor['name'],
            'box',
            [1, 1, 1],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=motor['material'],
            phobostype='motor',
        )
        # use resource name provided as: "resource:whatever_name"
        resource_obj = ioUtils.getResource(['motor'] + motor['shape'].split('://')[1].split('_'))
        if resource_obj:
            log("Assigned resource mesh and materials to new motor object.", 'DEBUG')
            newmotor.data = resource_obj.data
            newmotor.scale = (motor['size'],) * 3
        else:
            log("Could not use resource mesh for motor. Default cube used instead.", 'WARNING')
    else:
        newmotor = bUtils.createPrimitive(
            motor['name'],
            motor['shape'],
            motor['size'],
            layers,
            plocation=origin.to_translation(),
            protation=origin.to_euler(),
            pmaterial=motor['material'],
            phobostype='motor',
        )

    # assign the parent if available
    if parentobj is not None:
        sUtils.selectObjects([newmotor, parentobj], clear=True, active=1)
        bpy.ops.object.parent_set(type='BONE_RELATIVE')

    # set motor properties
    newmotor.phobostype = 'motor'
    newmotor.name = motor['name']
    defname = motor['defname']

    # write the custom properties to the motor
    eUtils.addAnnotation(newmotor, motor['props'], namespace='motor', ignore=['defname'])

    if 'controller' in defs.definitions['motors'][defname] and addcontrollers:
        import phobos.model.controllers as controllermodel

        motorcontroller = defs.definitions['motors'][defname]['controller']
        controllerdefs = ioUtils.getDictFromYamlDefs(
            'controller', motorcontroller, newmotor.name + '_controller'
        )
        newcontroller = controllermodel.createController(
            controllerdefs, newmotor, origin=newmotor.matrix_world, annotations='all'
        )
    else:
        newcontroller = None

    # select the new motor
    sUtils.selectObjects(
        [newmotor] if not newcontroller else [newmotor, newcontroller], clear=True, active=0
    )
    return newmotor if not newcontroller else [newmotor, newcontroller]