def deriveChainEntry(obj):
    """Derives a phobos dict entry for a kinematic chain ending in the provided object.

    :param obj:
    :return:
    """
    returnchains = []
    if 'endChain' in obj:
        chainlist = obj['endChain']
    for chainName in chainlist:
        chainclosed = False
        parent = obj
        chain = {
            'name': chainName,
            'start': '',
            'end': nUtils.getObjectName(obj),
            'elements': []
        }
        while not chainclosed:
            if parent.parent is None:  # FIXME: use effectiveParent
                log("Unclosed chain, aborting parsing chain " + chainName,
                    "ERROR", "deriveChainEntry")
                chain = None
                break
            chain['elements'].append(parent.name)
            parent = parent.parent  # FIXME: use effectiveParent
            if 'startChain' in parent:
                startchain = parent['startChain']
                if chainName in startchain:
                    chain['start'] = nUtils.getObjectName(parent)
                    chain['elements'].append(nUtils.getObjectName(parent))
                    chainclosed = True
        if chain is not None:
            returnchains.append(chain)
    return returnchains
def deriveDictEntry(obj):
    """Derives a phobos dictionary entry from the provided object.

    :param obj: The object to derive the dict entry (phobos data structure) from.
    :type obj: bpy_types.Object
    :return: tuple

    """
    try:
        if obj.phobostype == 'inertial':
            props = deriveInertial(obj)
        elif obj.phobostype == 'visual':
            props = deriveVisual(obj)
        elif obj.phobostype == 'collision':
            props = deriveCollision(obj)
        elif obj.phobostype == 'approxsphere':
            props = deriveApproxsphere(obj)
        elif obj.phobostype == 'sensor':
            props = deriveSensor(obj)
        elif obj.phobostype == 'controller':
            props = deriveController(obj)
        elif obj.phobostype == 'light':
            props = deriveLight(obj)
    except KeyError:
        log("A KeyError occurred due to unspecifiable missing model data.",
            "DEBUG", "deriveDictEntry")
        return None, None
    return props
def storePose(modelname, posename):
    """
    Stores the current pose of all of a robot's selected joints.
    Existing poses of the same name will be overwritten.

    :param modelname: The robot the pose belongs to.
    :type modelname: str.
    :param posename: The name the pose will be stored under.
    :type posename: str.
    :return: Nothing.
    """
    rootlink = None
    for root in sUtils.getRoots():
        if root['modelname'] == modelname:
            rootlink = root
    if rootlink:
        filename = modelname + '::poses'
        posedict = yaml.load(bUtils.readTextFile(filename))
        if not posedict:
            posedict = {posename: {'name': posename, 'joints': {}}}
        else:
            posedict[posename] = {'name': posename, 'joints': {}}
        bpy.ops.object.mode_set(mode='POSE')
        links = sUtils.getChildren(rootlink, ('link', ), True, False)
        for link in (link for link in links if 'joint/type' in link
                     and link['joint/type'] not in ['fixed', 'floating']):
            link.pose.bones['Bone'].rotation_mode = 'XYZ'
            posedict[posename]['joints'][nUtils.getObjectName(
                link, 'joint')] = link.pose.bones['Bone'].rotation_euler.y
        bUtils.updateTextFile(filename,
                              yaml.dump(posedict, default_flow_style=False))
    else:
        log("No model root could be found to store the pose for", "ERROR",
            "storePose")
Beispiel #4
0
def deriveDictEntry(obj):
    """Derives a phobos dictionary entry from the provided object.

    :param obj: The object to derive the dict entry (phobos data structure) from.
    :type obj: bpy_types.Object
    :return: tuple

    """
    try:
        if obj.phobostype == 'inertial':
            props = deriveInertial(obj)
        elif obj.phobostype == 'visual':
            props = deriveVisual(obj)
        elif obj.phobostype == 'collision':
            props = deriveCollision(obj)
        elif obj.phobostype == 'approxsphere':
            props = deriveApproxsphere(obj)
        elif obj.phobostype == 'sensor':
            props = deriveSensor(obj)
        elif obj.phobostype == 'controller':
            props = deriveController(obj)
        elif obj.phobostype == 'light':
            props = deriveLight(obj)
    except KeyError:
        log("A KeyError occurred due to unspecifiable missing model data.", "DEBUG", "deriveDictEntry")
        return None, None
    return props
Beispiel #5
0
def getRoot(obj=None):
    """
    Returns the root of an object, i.e. the first going up the tree containing a
    model name or entity name. If there is no such object up the tree, the
    tree's top-most object is returned.
    If no object is given, find root of the active object. If there is no
    active object, throw an error.

    :param obj: The object to find the root for.
    :type obj: bpy.types.Object.
    :return: The root object.
    """
    if not obj:
        for anobj in bpy.context.scene.objects:
            if bpy.context.scene.objects.active == anobj:
                obj = anobj
                break
        else:
            log("No root object found! Check your object selection", "ERROR")
            return None
    child = obj
    while child.parent and not ('modelname' in child
                                or 'entity/name' in child):
        child = child.parent
    return child
def loadPose(modelname, posename):
    """
    Load and apply a robot's stored pose.

    :param modelname: The model's name.
    :type modelname: str.
    :param posename: The name the pose is stored under.
    :type posename: str.
    :return Nothing.
    """
    load_file = bUtils.readTextFile(modelname + '::poses')
    if load_file == '':
        log('No poses stored.', 'ERROR', 'loadPose')
        return
    poses = yaml.load(load_file)
    try:
        pose = poses[posename]
        prev_mode = bpy.context.mode
        bpy.ops.object.mode_set(mode='POSE')
        for obj in sUtils.getObjectsByPhobostypes(['link']):
            if nUtils.getObjectName(obj, 'joint') in pose['joints']:
                obj.pose.bones['Bone'].rotation_mode = 'XYZ'
                obj.pose.bones['Bone'].rotation_euler.y = pose['joints'][
                    nUtils.getObjectName(obj, 'joint')]
        bpy.ops.object.mode_set(mode=prev_mode)
    except KeyError:
        log('No pose with name ' + posename + ' stored for model ' + modelname,
            'ERROR', "loadPose")
Beispiel #7
0
def addNamespace(obj):
    """This function namespaces a given blender object.

    :param obj: The object to namespace.
    :type obj: bpy.types.Object

    """
    types = defs.subtypes
    name = obj.name
    root = selection.getRoot(obj)
    namespace = root[
        "entity/name"] if root != None and "entity/name" in root else None
    if not namespace:
        log(
            "The obj " + getObjectName(obj) +
            "has no namespace to append to. Aborting.", "ERROR")
        return
    obj.name = namespace + "::" + name
    for ptype in types:
        typetag = ptype + "/type"
        nametag = ptype + "/name"
        if (typetag in obj or
            ("phobostype" in obj
             and obj.phobostype == ptype)) and nametag not in obj:
            obj[nametag] = name
Beispiel #8
0
def storePose(modelname, posename):
    """
    Stores the current pose of all of a robot's selected joints.
    Existing poses of the same name will be overwritten.

    :param modelname: The robot the pose belongs to.
    :type modelname: str.
    :param posename: The name the pose will be stored under.
    :type posename: str.
    :return: Nothing.
    """
    rootlink = None
    for root in sUtils.getRoots():
        if root['modelname'] == modelname:
            rootlink = root
    if rootlink:
        filename = modelname + '::poses'
        posedict = yaml.load(bUtils.readTextFile(filename))
        if not posedict:
            posedict = {posename: {'name': posename, 'joints': {}}}
        else:
            posedict[posename] = {'name': posename, 'joints': {}}
        bpy.ops.object.mode_set(mode='POSE')
        links = sUtils.getChildren(rootlink, ('link',), True, False)
        for link in (link for link in links if 'joint/type' in link
                     and link['joint/type'] not in ['fixed', 'floating']):
            link.pose.bones['Bone'].rotation_mode = 'XYZ'
            posedict[posename]['joints'][nUtils.getObjectName(link, 'joint')] = link.pose.bones['Bone'].rotation_euler.y
        bUtils.updateTextFile(filename, yaml.dump(posedict, default_flow_style=False))
    else:
        log("No model root could be found to store the pose for", "ERROR", "storePose")
Beispiel #9
0
def loadPose(modelname, posename):
    """
    Load and apply a robot's stored pose.

    :param modelname: The model's name.
    :type modelname: str.
    :param posename: The name the pose is stored under.
    :type posename: str.
    :return Nothing.
    """
    load_file = bUtils.readTextFile(modelname + '::poses')
    if load_file == '':
        log('No poses stored.', 'ERROR', 'loadPose')
        return
    poses = yaml.load(load_file)
    try:
        pose = poses[posename]
        prev_mode = bpy.context.mode
        bpy.ops.object.mode_set(mode='POSE')
        for obj in sUtils.getObjectsByPhobostypes(['link']):
            if nUtils.getObjectName(obj, 'joint') in pose['joints']:
                obj.pose.bones['Bone'].rotation_mode = 'XYZ'
                obj.pose.bones['Bone'].rotation_euler.y = pose['joints'][nUtils.getObjectName(obj, 'joint')]
        bpy.ops.object.mode_set(mode=prev_mode)
    except KeyError:
        log('No pose with name ' + posename + ' stored for model ' + modelname, 'ERROR', "loadPose")
Beispiel #10
0
 def execute(self, context):
     startLog(self)
     objlist = context.selected_objects
     if self.complete:
         roots = list(
             set([sUtils.getRoot(obj) for obj in context.selected_objects]))
         if None in roots:
             roots.remove(None)
         objlist = [
             elem
             for sublist in [sUtils.getChildren(root) for root in roots]
             for elem in sublist
         ]
     objnames = [o.name for o in bpy.data.objects]
     for obj in objlist:
         if "::" in obj.name:
             if nUtils.namesAreExplicit({obj.name.split("::")[-1]},
                                        objnames):
                 nUtils.removeNamespace(obj)
             else:
                 log(
                     "Cannot remove namespace from " + obj.name +
                     ". Name wouldn't be explicit", "ERROR")
         else:
             nUtils.addNamespace(obj)
     endLog()
     return {'FINISHED'}
Beispiel #11
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'}
Beispiel #12
0
def deriveMotor(obj, joint):
    """This function derives a motor from an object and joint.

    :param obj: The blender object to derive the motor from.
    :type obj: bpy_types.Object
    :param joint: The phobos joint to derive the constraints from.
    :type joint: dict
    :return: dict

    """
    props = initObjectProperties(obj, phobostype='motor', ignoretypes=['link', 'joint'])
    if len(props) > 1:  # if there are any 'motor' tags and not only a name
        props['joint'] = obj['joint/name'] if 'joint/name' in obj else obj.name
        try:
            if props['type'] == 'PID':
                if 'limits' in joint:
                    props['minValue'] = joint['limits']['lower']
                    props['maxValue'] = joint['limits']['upper']
            elif props['type'] == 'DC':
                props['minValue'] = 0
                props['maxValue'] = props["maxSpeed"]
        except KeyError:
            log("Missing data in motor " + obj.name + '. No motor created.', "WARNING", "deriveMotor")
            return None
        return props
    else:
        return None  # return None if no motor is attached
Beispiel #13
0
def deriveChainEntry(obj):
    """Derives a phobos dict entry for a kinematic chain ending in the provided object.

    :param obj:
    :return:
    """
    returnchains = []
    if 'endChain' in obj:
        chainlist = obj['endChain']
    for chainName in chainlist:
        chainclosed = False
        parent = obj
        chain = {'name': chainName, 'start': '', 'end': nUtils.getObjectName(obj), 'elements': []}
        while not chainclosed:
            if parent.parent is None:  # FIXME: use effectiveParent
                log("Unclosed chain, aborting parsing chain " + chainName, "ERROR", "deriveChainEntry")
                chain = None
                break
            chain['elements'].append(parent.name)
            parent = parent.parent  # FIXME: use effectiveParent
            if 'startChain' in parent:
                startchain = parent['startChain']
                if chainName in startchain:
                    chain['start'] = nUtils.getObjectName(parent)
                    chain['elements'].append(nUtils.getObjectName(parent))
                    chainclosed = True
        if chain is not None:
            returnchains.append(chain)
    return returnchains
def deriveMotor(obj, joint):
    """This function derives a motor from an object and joint.

    :param obj: The blender object to derive the motor from.
    :type obj: bpy_types.Object
    :param joint: The phobos joint to derive the constraints from.
    :type joint: dict
    :return: dict

    """
    props = initObjectProperties(obj,
                                 phobostype='motor',
                                 ignoretypes=['link', 'joint'])
    if len(props) > 1:  # if there are any 'motor' tags and not only a name
        props['joint'] = obj['joint/name'] if 'joint/name' in obj else obj.name
        try:
            if props['type'] == 'PID':
                if 'limits' in joint:
                    props['minValue'] = joint['limits']['lower']
                    props['maxValue'] = joint['limits']['upper']
            elif props['type'] == 'DC':
                props['minValue'] = 0
                props['maxValue'] = props["maxSpeed"]
        except KeyError:
            log("Missing data in motor " + obj.name + '. No motor created.',
                "WARNING", "deriveMotor")
            return None
        return props
    else:
        return None  # return None if no motor is attached
def deriveTextData(modelname):
    """
    Collect additional data stored for a specific model.

    :param modelname: Name of the model for which data should be derived.
    :return: A dictionary containing additional data.
    """
    datadict = {}
    datatextfiles = [
        text for text in bpy.data.texts
        if text.name.startswith(modelname + '::')
    ]
    for text in datatextfiles:
        try:
            dataname = text.name.split('::')[-1]
        except IndexError:
            log("Possibly invalidly named model data text file: " + modelname,
                "WARNING", "deriveTextData")
        try:
            data = yaml.load(bUtils.readTextFile(text.name))
        except yaml.scanner.ScannerError:
            log("Invalid formatting of data file: " + dataname, "ERROR",
                "deriveTextData")
        if data:
            datadict[dataname] = data
    return datadict
def deriveCollision(obj):
    """This function derives the collision information from an object.

    :param obj: The blender object to derive the collision information from.
    :type obj: bpy_types.Object
    :return: dict

    """
    try:
        collision = initObjectProperties(obj,
                                         phobostype='collision',
                                         ignoretypes='geometry')
        collision['geometry'] = deriveGeometry(obj)
        collision['pose'] = deriveObjectPose(obj)
        # the bitmask is cut to length = 16 and reverted for int parsing
        try:
            collision['bitmask'] = int(
                ''.join([
                    '1' if group else '0'
                    for group in obj.rigid_body.collision_groups[:16]
                ])[::-1], 2)
        except AttributeError:
            pass
    except KeyError:
        log("Missing data in collision object " + obj.name, "ERROR",
            "deriveCollision")
        return None
    return collision
Beispiel #17
0
def openScriptInEditor(scriptname):
    if scriptname in bpy.data.texts:
        for area in bpy.context.screen.areas:
            if area.type == "TEXT_EDITOR":
                area.spaces.active.text = bpy.data.texts[scriptname]
    else:
        log("There is no script named " + scriptname + "!", "ERROR")
Beispiel #18
0
def deriveMaterial(mat):
    """This function takes a blender material and creates a phobos representation from it

    :param mat: The blender material to derive a phobos material from
    :type mat: bpy.types.Material
    :return: dict

    """
    material = initObjectProperties(mat, 'material')
    material['name'] = mat.name
    material['diffuseColor'] = dict(zip(['r', 'g', 'b'],
                                        [mat.diffuse_intensity * num for num in list(mat.diffuse_color)]))
    material['ambientColor'] = dict(zip(['r', 'g', 'b'],
                                        [mat.ambient * mat.diffuse_intensity * num for num in list(mat.diffuse_color)]))
    material['specularColor'] = dict(zip(['r', 'g', 'b'],
                                         [mat.specular_intensity * num for num in list(mat.specular_color)]))
    if mat.emit > 0:
        material['emissionColor'] = dict(zip(['r', 'g', 'b'],
                                             [mat.emit * mat.specular_intensity * num for num in list(mat.specular_color)]))
    material['shininess'] = mat.specular_hardness/2
    if mat.use_transparency:
        material['transparency'] = 1.0-mat.alpha
    for tex in mat.texture_slots:  # there are always 18 slots, regardless of whether they are filled or not
        if tex is not None:
            try:
                if tex.use_map_color_diffuse:  # regular diffuse color texture
                    material['diffuseTexture'] = mat.texture_slots[0].texture.image.filepath.replace('//', '') # grab the first texture
                if tex.use_map_normal:  # normal map
                    material['normalTexture'] = mat.texture_slots[0].texture.image.filepath.replace('//', '') # grab the first texture
                if tex.use_map_displacement:  # displacement map
                    material['displacementTexture'] = mat.texture_slots[0].texture.image.filepath.replace('//', '') # grab the first texture
            except (KeyError, AttributeError):
                log("None or incomplete texture data for material " + nUtils.getObjectName(mat, 'material'),
                    "WARNING", "deriveMaterial")
    return material
Beispiel #19
0
 def execute(self, context):
     startLog(self)
     self.distance, self.distVector = generalUtils.distance(
         bpy.context.selected_objects)
     log("distance: " + str(self.distance) + ", " + str(self.distVector),
         "INFO")
     endLog()
     return {'FINISHED'}
Beispiel #20
0
    def execute(self, context):
        startLog(self)
        selectionUtils.selectByName(self.errorObj)
        for message in defs.checkMessages[self.errorObj]:
            log(message, 'INFO')
        endLog()

        return {'FINISHED'}
Beispiel #21
0
    def execute(self, context):
        startLog(self)
        selectionUtils.selectByName(self.errorObj)
        for message in defs.checkMessages[self.errorObj]:
            log(message, 'INFO')
        endLog()

        return {'FINISHED'}
Beispiel #22
0
 def execute(self, context):
     startLog(self)
     for obj in bpy.context.selected_objects:
         if obj.phobostype == 'collision' or obj.phobostype == 'visual':
             obj['geometry/type'] = self.geomType
         else:
             log("The object '" + obj.name + "' is no collision or visual")
     endLog()
     return {'FINISHED'}
Beispiel #23
0
 def execute(self, context):
     startLog(self)
     root = selectionUtils.getRoot(bpy.context.active_object)
     if root == None:
         log("Could not set modelname due to missing root link. No name was set.", "ERROR")
         return {'FINISHED'}
     root["modelname"] = self.modelname
     endLog()
     return {'FINISHED'}
Beispiel #24
0
def calculateSum(objects, numeric_prop):
    """Returns sum of *numeric_prop* in *objects*."""
    numsum = 0
    for obj in objects:
        try:
            numsum += obj[numeric_prop]
        except KeyError:
            log("The object '" + getObjectName(obj) + "' has not property '" + numeric_prop + "'")
    return numsum
Beispiel #25
0
 def execute(self, context):
     startLog(self)
     file = self.filepath.split("/")[-1]
     if self.filepath.endswith(".bake"):
         zipF = zipfile.ZipFile(self.filepath, mode="r")
         zipF.extractall(path=os.path.join(self.libpath, file.split(".")[0]))
     else:
         log("This is no robot bake!", "ERROR")
     endLog()
     return {"FINISHED"}
Beispiel #26
0
 def execute(self, context):
     startLog(self)
     root = sUtils.getRoot(context.selected_objects[0])
     if root.phobostype != 'link':
         log("Selection includes objects not parented to any model root, please adapt selection.", "ERROR", "ExportModelOperator")
     else:
         model, objectlist = robotdictionary.buildModelDictionary(root)
         exporter.export(model, objectlist)
         endLog()
     return {'FINISHED'}
Beispiel #27
0
 def execute(self, context):
     startLog(self)
     root = sUtils.getRoot(context.active_object)
     if root == None:
         log(
             "Could not set modelname due to missing root link. No name was set.",
             "ERROR")
         return {'FINISHED'}
     root["modelname"] = self.modelname
     endLog()
     return {'FINISHED'}
Beispiel #28
0
def deriveJointType(joint, adjust=False):
    """ Derives the type of the joint defined by the armature object 'joint' based on the constraints defined in the joint.

    :param joint: The joint you want to derive its type from.
    :type joint: bpy_types.Object
    :param adjust: Decides whether or not the type of the joint is adjusted after detecting (without checking whether
    the property "type" was previously defined in the armature or not).
    :type adjust: bool.
    :return: tuple(2) -- jtype, crot

    """
    jtype = 'floating'  # 'universal' in MARS nomenclature
    cloc = None
    crot = None
    limrot = None
    # we pick the first bone in the armature as there is only one
    for c in joint.pose.bones[0].constraints:
        if c.type == 'LIMIT_LOCATION':
            cloc = [
                c.use_min_x and c.min_x == c.max_x, c.use_min_y
                and c.min_y == c.max_y, c.use_min_z and c.min_z == c.max_z
            ]
        elif c.type == 'LIMIT_ROTATION':
            limrot = c
            crot = [
                c.use_limit_x and (c.min_x != 0 or c.max_x != 0), c.use_limit_y
                and (c.min_y != 0 or c.max_y != 0), c.use_limit_z
                and (c.min_z != 0 or c.max_z != 0)
            ]
    ncloc = sum(cloc) if cloc else None
    ncrot = sum((
        limrot.use_limit_x,
        limrot.use_limit_y,
        limrot.use_limit_z,
    )) if limrot else None
    if cloc:  # = if there is any constraint at all, as all joints but floating ones have translation limits
        if ncloc == 3:  # fixed or revolute
            if ncrot == 3:
                if sum(crot) > 0:
                    jtype = 'revolute'
                else:
                    jtype = 'fixed'
            elif ncrot == 2:
                jtype = 'continuous'
        elif ncloc == 2:
            jtype = 'prismatic'
        elif ncloc == 1:
            jtype = 'planar'
    if adjust:
        joint['joint/type'] = jtype
        log(
            "Set type of joint '" + namingUtils.getObjectName(joint) +
            "'to '" + jtype + "'.", "INFO")
    return jtype, crot
Beispiel #29
0
def assignMaterial(obj, materialname):
    if materialname not in bpy.data.materials:
        if materialname in defs.defaultmaterials:
            materials.createPhobosMaterials()
        else:
            # print("###ERROR: material to be assigned does not exist.")
            log("Material to be assigned does not exist.", "ERROR")
            return None
    obj.data.materials.append(bpy.data.materials[materialname])
    if bpy.data.materials[materialname].use_transparency:
        obj.show_transparent = True
Beispiel #30
0
def calculateSum(objects, numeric_prop):
    """Returns sum of *numeric_prop* in *objects*.

    """
    numsum = 0
    for obj in objects:
        try:
            numsum += obj[numeric_prop]
        except KeyError:
            log("The object '" + namingUtils.getObjectName(obj) +
                "' has not property '" + numeric_prop + "'")
    return numsum
Beispiel #31
0
 def execute(self, context):
     startLog(self)
     root = sUtils.getRoot(context.selected_objects[0])
     if root.phobostype != 'link':
         log(
             "Selection includes objects not parented to any model root, please adapt selection.",
             "ERROR", "ExportModelOperator")
     else:
         model, objectlist = robotdictionary.buildModelDictionary(root)
         exporter.export(model, objectlist)
         endLog()
     return {'FINISHED'}
Beispiel #32
0
def calculateSum(objects, numeric_prop):
    """Returns sum of *numeric_prop* in *objects*.

    """
    numsum = 0
    for obj in objects:
        try:
            numsum += obj[numeric_prop]
        except KeyError:
            log(obj.phobostype + " object " + obj.name + " does not contain '" + numeric_prop
                + "'", "WARNING", "calculateSum")
    return numsum
Beispiel #33
0
def find_in_list(alist, prop, value):
    """Returns the index of the first object in a list which has a field
    named *prop* with value *value*. If no such object is found, returns -1."""
    n = -1
    for i in range(len(alist)):
        try:
            if alist[i][prop] == value:
                n = i
                break
        except KeyError:
            log("The object at index " + str(i) + " has no property " + str(prop))
    return n
def deriveMaterial(mat):
    """This function takes a blender material and creates a phobos representation from it

    :param mat: The blender material to derive a phobos material from
    :type mat: bpy.types.Material
    :return: dict

    """
    material = initObjectProperties(mat, 'material')
    material['name'] = mat.name
    material['diffuseColor'] = dict(
        zip(['r', 'g', 'b'],
            [mat.diffuse_intensity * num for num in list(mat.diffuse_color)]))
    material['ambientColor'] = dict(
        zip(['r', 'g', 'b'], [
            mat.ambient * mat.diffuse_intensity * num
            for num in list(mat.diffuse_color)
        ]))
    material['specularColor'] = dict(
        zip(['r', 'g', 'b'],
            [mat.specular_intensity * num
             for num in list(mat.specular_color)]))
    if mat.emit > 0:
        material['emissionColor'] = dict(
            zip(['r', 'g', 'b'], [
                mat.emit * mat.specular_intensity * num
                for num in list(mat.specular_color)
            ]))
    material['shininess'] = mat.specular_hardness / 2
    if mat.use_transparency:
        material['transparency'] = 1.0 - mat.alpha
    for tex in mat.texture_slots:  # there are always 18 slots, regardless of whether they are filled or not
        if tex is not None:
            try:
                if tex.use_map_color_diffuse:  # regular diffuse color texture
                    material['diffuseTexture'] = mat.texture_slots[
                        0].texture.image.filepath.replace(
                            '//', '')  # grab the first texture
                if tex.use_map_normal:  # normal map
                    material['normalTexture'] = mat.texture_slots[
                        0].texture.image.filepath.replace(
                            '//', '')  # grab the first texture
                if tex.use_map_displacement:  # displacement map
                    material['displacementTexture'] = mat.texture_slots[
                        0].texture.image.filepath.replace(
                            '//', '')  # grab the first texture
            except (KeyError, AttributeError):
                log(
                    "None or incomplete texture data for material " +
                    nUtils.getObjectName(mat, 'material'), "WARNING",
                    "deriveMaterial")
    return material
Beispiel #35
0
def readTextFile(textfilename):
    """This function returns the content of a specified text file.

    :param textfilename: The blender textfiles name.
    :type textfilename: str
    :return: str - the textfiles content.

    """
    try:
        return "\n".join([l.body for l in bpy.data.texts[textfilename].lines])
    except KeyError:
        log("No text file " + textfilename + " found. Setting", "INFO")
        return ""
Beispiel #36
0
def readTextFile(textfilename):
    """This function returns the content of a specified text file.

    :param textfilename: The blender textfiles name.
    :type textfilename: str
    :return: str - the textfiles content.

    """
    try:
        return "\n".join([l.body for l in bpy.data.texts[textfilename].lines])
    except KeyError:
        log("No text file " + textfilename + " found. Setting", "ERROR")
        return ""
Beispiel #37
0
def getRoots():
    """
    Returns a list of all of the current scene's root links, i.e. links containing a model
    name or entity name.

    :return: List of all root links.
    """
    roots = [obj for obj in bpy.context.scene.objects if isModelRoot(obj)]
    if not roots:
        log("Phobos: No root objects found.", "WARNING", "getRoots")
    else:
        log("Phobos: Found " + str(len(roots)) + " root object(s)", "INFO", "getRoots")
    return roots  # TODO: Should we change this and all other list return values in a tuple or generator expression?
Beispiel #38
0
 def execute(self, context):
     startLog(self)
     roots = set()
     for obj in bpy.context.selected_objects:
         roots.add(selectionUtils.getRoot(obj))
     if len(roots) > 0:
         selectionUtils.selectObjects(list(roots), True)
         bpy.context.scene.objects.active = list(roots)[0]
     else:
         # bpy.ops.error.message('INVOKE_DEFAULT', type="ERROR", message="Couldn't find any root object.")
         log("Couldn't find any root object.", "ERROR")
     endLog()
     return {'FINISHED'}
Beispiel #39
0
def deriveController(obj):
    """This function derives a controller from a given blender object

    :param obj: The blender object to derive the controller from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        props = initObjectProperties(obj, phobostype='controller')
    except KeyError:
        log("Missing data in controller  " + obj.name, "ERROR", "deriveController")
        return None
    return props
Beispiel #40
0
    def execute(self, context):

        startLog(self)
        messages = {}
        dic = robotdictionary.buildRobotDictionary()
        validator.check_dict(dic, defs.dictConstraints, messages)
        defs.checkMessages = messages if len(list(messages.keys())) > 0 else {"NoObject": []}
        for entry in messages:
            log("Errors in object " + entry + ":", 'INFO')
            for error in messages[entry]:
                log(error, 'INFO')
        endLog()
        return {'FINISHED'}
Beispiel #41
0
def getRoot(obj=None):
    """Finds the root object of a model given one of the model elements is selected or provided"""
    if obj == None:
        for anobj in bpy.data.objects:  # TODO: this is not the best list to iterate over (there might be multiple scenes)
            if (anobj.select):
                obj = anobj
    child = obj
    if child == None:
        log("No root object found! Check your object selection", "ERROR")
        return None
    while child.parent != None:
        child = child.parent
    return child
Beispiel #42
0
 def execute(self, context):
     startLog(self)
     roots = set()
     for obj in bpy.context.selected_objects:
         roots.add(getRoot(obj))
     if len(roots) > 0:
         selectObjects(list(roots), True)
         bpy.context.scene.objects.active = list(roots)[0]
     else:
         # bpy.ops.error.message('INVOKE_DEFAULT', type="ERROR", message="Couldn't find any root object.")
         log("Couldn't find any root object.", "ERROR")
     endLog()
     return {'FINISHED'}
Beispiel #43
0
def deriveSensor(obj):
    """This function derives a sensor from a given blender object

    :param obj: The blender object to derive the sensor from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        props = initObjectProperties(obj, phobostype='sensor')
        props['link'] = nUtils.getObjectName(sUtils.getEffectiveParent(obj))
    except KeyError:
        log("Missing data in sensor " + obj.name, "ERROR", "deriveSensor")
        return None
    return props
Beispiel #44
0
def getRoots():
    """
    Returns a list of all of the current scene's root links, i.e. links containing a model
    name or entity name.

    :return: List of all root links.
    """
    roots = [obj for obj in bpy.context.scene.objects if isModelRoot(obj)]
    if not roots:
        log("Phobos: No root objects found.", "WARNING", "getRoots")
    else:
        log("Phobos: Found " + str(len(roots)) + " root object(s)", "INFO",
            "getRoots")
    return roots  # TODO: Should we change this and all other list return values in a tuple or generator expression?
Beispiel #45
0
    def execute(self, context):

        startLog(self)
        messages = {}
        root = sUtils.getRoot(context.selected_objects[0])
        model, objectlist = robotdictionary.buildModelDictionary(root)
        validator.check_dict(model, defs.dictConstraints, messages)
        defs.checkMessages = messages if len(list(messages.keys())) > 0 else {"NoObject": []}
        for entry in messages:
            log("Errors in object " + entry + ":", 'INFO')
            for error in messages[entry]:
                log(error, 'INFO')
        endLog()
        return {'FINISHED'}
Beispiel #46
0
def calculateSum(objects, numeric_prop):
    """Returns sum of *numeric_prop* in *objects*.

    """
    numsum = 0
    for obj in objects:
        try:
            numsum += obj[numeric_prop]
        except KeyError:
            log(
                obj.phobostype + " object " + obj.name +
                " does not contain '" + numeric_prop + "'", "WARNING",
                "calculateSum")
    return numsum
def deriveSensor(obj):
    """This function derives a sensor from a given blender object

    :param obj: The blender object to derive the sensor from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        props = initObjectProperties(obj, phobostype='sensor')
        props['link'] = nUtils.getObjectName(sUtils.getEffectiveParent(obj))
    except KeyError:
        log("Missing data in sensor " + obj.name, "ERROR", "deriveSensor")
        return None
    return props
Beispiel #48
0
def addNamespace(obj):
    types = defs.subtypes
    name = obj.name
    root = selection.getRoot(obj)
    namespace = root["modelname"] if root != None and "modelname" in root else None
    if not namespace:
        log("The obj " + getObjectName(obj) + "has no namespace to append to. Aborting.", "ERROR")
        return
    obj.name = namespace + "::" + name
    for pType in types:
        typeTag = pType + "/type"
        nameTag = pType + "/name"
        if (typeTag in obj or ("phobostype" in obj and obj.phobostype == pType)) and nameTag not in obj:
            obj[nameTag] = name
def deriveController(obj):
    """This function derives a controller from a given blender object

    :param obj: The blender object to derive the controller from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        props = initObjectProperties(obj, phobostype='controller')
    except KeyError:
        log("Missing data in controller  " + obj.name, "ERROR",
            "deriveController")
        return None
    return props
Beispiel #50
0
def openScriptInEditor(scriptname):
    """This function opens a script/textfile in an open blender text window. Nothing happens if there is no
    available text window.

    :param scriptname: The scripts name.
    :type scriptname: str

    """
    if scriptname in bpy.data.texts:
        for area in bpy.context.screen.areas:
            if area.type == 'TEXT_EDITOR':
                area.spaces.active.text = bpy.data.texts[scriptname]
    else:
        log("There is no script named " + scriptname + "!", "ERROR")
Beispiel #51
0
def openScriptInEditor(scriptname):
    """This function opens a script/textfile in an open blender text window. Nothing happens if there is no
    available text window.

    :param scriptname: The scripts name.
    :type scriptname: str

    """
    if scriptname in bpy.data.texts:
        for area in bpy.context.screen.areas:
            if area.type == 'TEXT_EDITOR':
                area.spaces.active.text = bpy.data.texts[scriptname]
    else:
        log("There is no script named " + scriptname + "!", "ERROR")
Beispiel #52
0
def createPrimitive(pname, ptype, psize, player=0, pmaterial="None", plocation=(0, 0, 0), protation=(0, 0, 0),
                    verbose=False):
    """Generates the primitive specified by the input parameters

    :param pname: The primitives new name.
    :type pname: str
    :param ptype: The new primitives type. Can be one of *box, sphere, cylinder, cone, disc*
    :type ptype: str
    :param psize: The new primitives size. Depending on the ptype it can be either a single float or a tuple.
    :type psize: float or list
    :param player: The layer bitmask for the new blender object.
    :param pmaterial: The new primitives material.
    :param plocation: The new primitives location.
    :type plocation: tuple
    :param protation: The new primitives rotation.
    :type protation: tuple
    :return: bpy.types.Object - the new blender object.

    """
    if verbose:
        log(ptype + psize, "INFO", "createPrimitive")
    try:
        # n_layer = bpy.context.scene.active_layer
        n_layer = int(player)
    except ValueError:
        n_layer = defs.layerTypes[player]
    players = defLayers([n_layer])
    bpy.context.scene.layers[n_layer] = True  # the layer has to be active to prevent problems with object placement
    if ptype == "box":
        bpy.ops.mesh.primitive_cube_add(layers=players, location=plocation, rotation=protation)
        obj = bpy.context.object
        obj.dimensions = psize
    if ptype == "sphere":
        bpy.ops.mesh.primitive_uv_sphere_add(size=psize, layers=players, location=plocation, rotation=protation)
    elif ptype == "cylinder":
        bpy.ops.mesh.primitive_cylinder_add(vertices=32, radius=psize[0], depth=psize[1], layers=players,
                                            location=plocation, rotation=protation)
    elif ptype == "cone":
        bpy.ops.mesh.primitive_cone_add(vertices=32, radius=psize[0], depth=psize[1], cap_end=True, layers=players,
                                        location=plocation, rotation=protation)
    elif ptype == 'disc':
        bpy.ops.mesh.primitive_circle_add(vertices=psize[1], radius=psize[0], fill_type='TRIFAN', location=plocation,
                                          rotation=protation, layers=players)
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    obj = bpy.context.object
    obj.name = pname
    if pmaterial != 'None':
        assignMaterial(obj, pmaterial)
    return obj
Beispiel #53
0
def deriveJointType(joint, adjust=False):
    """ Derives the type of the joint defined by the armature object 'joint' based on the constraints defined in the joint.

    :param joint: The joint you want to derive its type from.
    :type joint: bpy_types.Object
    :param adjust: Decides whether or not the type of the joint is adjusted after detecting (without checking whether
    the property "type" was previously defined in the armature or not).
    :type adjust: bool.
    :return: tuple(2) -- jtype, crot

    """
    jtype = "floating"  # 'universal' in MARS nomenclature
    cloc = None
    crot = None
    limrot = None
    # we pick the first bone in the armature as there is only one
    for c in joint.pose.bones[0].constraints:
        if c.type == "LIMIT_LOCATION":
            cloc = [
                c.use_min_x and c.min_x == c.max_x,
                c.use_min_y and c.min_y == c.max_y,
                c.use_min_z and c.min_z == c.max_z,
            ]
        elif c.type == "LIMIT_ROTATION":
            limrot = c
            crot = [
                c.use_limit_x and (c.min_x != 0 or c.max_x != 0),
                c.use_limit_y and (c.min_y != 0 or c.max_y != 0),
                c.use_limit_z and (c.min_z != 0 or c.max_z != 0),
            ]
    ncloc = sum(cloc) if cloc else None
    ncrot = sum((limrot.use_limit_x, limrot.use_limit_y, limrot.use_limit_z)) if limrot else None
    if cloc:  # = if there is any constraint at all, as all joints but floating ones have translation limits
        if ncloc == 3:  # fixed or revolute
            if ncrot == 3:
                if sum(crot) > 0:
                    jtype = "revolute"
                else:
                    jtype = "fixed"
            elif ncrot == 2:
                jtype = "continuous"
        elif ncloc == 2:
            jtype = "prismatic"
        elif ncloc == 1:
            jtype = "planar"
    if adjust:
        joint["joint/type"] = jtype
        log("Set type of joint '" + namingUtils.getObjectName(joint) + "'to '" + jtype + "'.", "INFO")
    return jtype, crot
Beispiel #54
0
 def execute(self, context):
     startLog(self)
     for obj in context.selected_objects:
         try:
             phobosType = obj.phobostype
             if phobosType != 'controller' and phobosType != 'undefined':
                 layers = 20 * [False]
                 layers[defs.layerTypes[phobosType]] = True
                 obj.layers = layers
             if phobosType == 'undefined':
                 log("The phobostype of the object '" + obj.name + "' is undefined")
         except AttributeError:
             log("The object '" + obj.name + "' has no phobostype", "ERROR")  # Handle this as error or warning?
     endLog()
     return {'FINISHED'}
Beispiel #55
0
def securepath(path):
    """This function checks whether a path exists or not.
    If it doesn't the functions creates the path.

    :param path: The path you want to check for existence *DIRECTORIES ONLY*
    :type path: str
    :return: String -- the path given as parameter, but secured by expanding ~ constructs.

    """
    if not os.path.exists(path):
        try:
            os.makedirs(path)
        except NotADirectoryError:
            log(path + " is not a valid directory", "ERROR", "securepath")
    return os.path.expanduser(path)
Beispiel #56
0
def find_in_list(alist, prop, value):
    """Returns the index of the first object in a list which has a field
    named *prop* with value *value*. If no such object is found, returns -1.

    """
    n = -1
    for i in range(len(alist)):
        try:
            if alist[i][prop] == value:
                n = i
                break
        except KeyError:
            log("The object at index " + str(i) + " has no property " +
                str(prop))
    return n
Beispiel #57
0
    def execute(self, context):

        startLog(self)
        messages = {}
        dic = robotdictionary.buildRobotDictionary()
        validator.check_dict(dic, defs.dictConstraints, messages)
        defs.checkMessages = messages if len(list(messages.keys())) > 0 else {
            "NoObject": []
        }
        for entry in messages:
            log("Errors in object " + entry + ":", 'INFO')
            for error in messages[entry]:
                log(error, 'INFO')
        endLog()
        return {'FINISHED'}
Beispiel #58
0
def deriveInertial(obj):
    """This function derives the inertial from the given object.

    :param obj: The object to derive the inertial from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        props = initObjectProperties(obj, phobostype='inertial')
        props['inertia'] = list(map(float, obj['inertial/inertia']))
        props['pose'] = deriveObjectPose(obj)
    except KeyError as e:
        log("Missing data in inertial object " + obj.name + str(e), "ERROR", "deriveInertial")
        return None
    return props
def deriveInertial(obj):
    """This function derives the inertial from the given object.

    :param obj: The object to derive the inertial from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        props = initObjectProperties(obj, phobostype='inertial')
        props['inertia'] = list(map(float, obj['inertial/inertia']))
        props['pose'] = deriveObjectPose(obj)
    except KeyError as e:
        log("Missing data in inertial object " + obj.name + str(e), "ERROR",
            "deriveInertial")
        return None
    return props
def deriveVisual(obj):
    """This function derives the visual information from an object.

    :param obj: The blender object to derive the visuals from.
    :type obj: bpy_types.Object
    :return: dict

    """
    try:
        visual = initObjectProperties(obj,
                                      phobostype='visual',
                                      ignoretypes='geometry')
        visual['geometry'] = deriveGeometry(obj)
        visual['pose'] = deriveObjectPose(obj)
        if obj.lod_levels:
            if 'lodmaxdistances' in obj:
                maxdlist = obj['lodmaxdistances']
            else:
                maxdlist = [
                    obj.lod_levels[i + 1].distance
                    for i in range(len(obj.lod_levels) - 1)
                ] + [100.0]
            lodlist = []
            for i in range(len(obj.lod_levels)):
                filename = obj.lod_levels[i].object.data.name
                if bpy.data.worlds[0].useObj:
                    filename += ".obj"
                elif bpy.data.worlds[0].useBobj:
                    filename += ".bobj"
                elif bpy.data.worlds[0].useStl:
                    filename += ".stl"
                elif bpy.data.worlds[0].useDae:
                    filename += ".dae"
                else:
                    filename += ".obj"
                lodlist.append({
                    'start': obj.lod_levels[i].distance,
                    'end': maxdlist[i],
                    'filename': os.path.join('meshes', filename)
                })
            visual['lod'] = lodlist
    except KeyError:
        log("Missing data in visual object " + obj.name, "ERROR",
            "deriveVisual")
        return None
    return visual