def execute(self, context): objlist = [] for obj in bpy.data.objects: if obj.phobostype == self.seltype: objlist.append(obj) selectionUtils.selectObjects(objlist, True) return {'FINISHED'}
def bakeModel(objlist, path, modelname): visuals = [o for o in objlist if ("phobostype" in o and o.phobostype == "visual")] selectionUtils.selectObjects(visuals, active=0) log("Copying objects for joining...", "INFO") print("Copying objects for joining...") bpy.ops.object.duplicate(linked=False, mode='TRANSLATION') log("joining...", "INFO") print("joining...") bpy.ops.object.join() obj = bpy.context.active_object log("Deleting vertices...", "INFO") print("Deleting vertices...") bpy.ops.object.editmode_toggle() bpy.ops.mesh.select_all(action='TOGGLE') bpy.ops.mesh.select_all(action='TOGGLE') bpy.ops.mesh.remove_doubles() bpy.ops.object.editmode_toggle() log("Adding modifier...", "INFO") print("Adding modifier...") bpy.ops.object.modifier_add(type='DECIMATE') bpy.context.object.modifiers["Decimate"].decimate_type = 'DISSOLVE' log("Applying modifier...", "INFO") print("Applying modifier...") bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Decimate") name = "bake.stl" obj.name = name bpy.ops.export_mesh.stl(filepath=os.path.join(path, name)) obj.select = True bpy.ops.object.delete() log("Done baking...", "INFO") print("Done baking...")
def deriveStoredPoses(): """ """ poses_dict = {} if len(bpy.data.actions) == 0: return {} pose_lib_name = bpy.data.actions.keys()[0] some_obj = bpy.context.scene.objects.active bpy.ops.object.mode_set(mode='OBJECT') for pose_name, i in zip(bpy.data.actions[pose_lib_name].pose_markers.keys(), range(len(bpy.data.actions[pose_lib_name].pose_markers.keys()))): selectionUtils.selectObjects([selectionUtils.getRoot(some_obj)], clear=True, active=0) pose_dict = {} bpy.ops.object.mode_set(mode='POSE') bpy.ops.poselib.apply_pose(pose_index=i) bpy.ops.object.mode_set(mode='OBJECT') for obj in bpy.context.scene.objects: if obj.phobostype == 'link': selectionUtils.selectObjects([obj], clear=True, active=0) bpy.ops.object.mode_set(mode='POSE') obj.pose.bones['Bone'].rotation_mode = 'XYZ' y_angle = obj.pose.bones['Bone'].rotation_euler.y bpy.ops.object.mode_set(mode='OBJECT') pose_dict[obj.name] = y_angle poses_dict[pose_name] = pose_dict return poses_dict
def execute(self, context): """ Args: context: Returns: """ root = sUtils.getRoot(context.selected_objects[0]) modelsPosesColl = bUtils.getPhobosPreferences().models_poses activeModelPoseIndex = bpy.context.scene.active_ModelPose selected_robot = modelsPosesColl[bpy.data.images[activeModelPoseIndex].name] objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False) sUtils.selectObjects([root] + objectlist, clear=True, active=0) models.loadPose(selected_robot.robot_name, selected_robot.label) parameter = self.decimate_ratio if self.decimate_type == 'UNSUBDIV': parameter = self.decimate_iteration elif self.decimate_type == 'DISSOLVE': parameter = self.decimate_angle_limit exporter.bakeModel( objectlist, root['model/name'], selected_robot.label, decimate_type=self.decimate_type, decimate_parameter=parameter, ) sUtils.selectObjects([root] + objectlist, clear=True, active=0) bpy.ops.scene.reload_models_and_poses_operator() return {'FINISHED'}
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
def execute(self, context): """ Args: context: Returns: """ log("Jumping to object " + self.objectname + ".", 'DEBUG') # switch the scene if the object is anywhere else scene = None if self.objectname not in context.scene: for sce in bpy.data.scenes: if self.objectname in sce.objects: scene = sce break else: log("Could not find scene of object {}. Aborted.".format(self.objectname), 'ERROR') return {'CANCELLED'} bUtils.switchToScene(scene.name) # toggle layer to make object visible bUtils.setObjectLayersActive(scene.objects[self.objectname], extendlayers=True) sUtils.selectObjects([scene.objects[self.objectname]], clear=True, active=0) return {'FINISHED'}
def execute(self, context): """ Args: context: Returns: """ objects = context.selected_objects annotation = defs.definitions[self.annotationtype][self.devicetype] # add annotation (objects) to the selected objects annot_objects = [] for obj in objects: if self.asObject: annot_objects.append( eUtils.addAnnotationObject( obj, annotation, name=obj.name + '_annotation', namespace=self.annotationtype.rstrip('s'), ) ) else: eUtils.addAnnotation(obj, annotation, namespace=self.annotationtype.rstrip('s')) # reselect the original objects and additional annotation objects sUtils.selectObjects(objects + annot_objects, clear=True) bUtils.toggleLayer(defs.layerTypes['annotation'], value=True) return {'FINISHED'}
def execute(self, context): """ Args: context: Returns: """ selection = [] if self.modelname: log("phobos: Selecting model" + self.modelname, "INFO") roots = sUtils.getRoots() for root in roots: if nUtils.getModelName(root) == self.modelname: selection = sUtils.getChildren(root) else: log("No model name provided, deriving from selection...", "INFO") roots = set() for obj in bpy.context.selected_objects: roots.add(sUtils.getRoot(obj)) for root in list(roots): selection.extend(sUtils.getChildren(root)) sUtils.selectObjects(list(selection), True) return {'FINISHED'}
def execute(self, context): """ Args: context: Returns: """ roots = set() # add root object of each selected object for obj in context.selected_objects: roots.add(sUtils.getRoot(obj)) # select all found root objects if roots: # toggle layer to make objects visible for root in roots: bUtils.setObjectLayersActive(root, extendlayers=True) # select objects sUtils.selectObjects(list(roots), True) context.scene.objects.active = list(roots)[0] else: log("Couldn't find any root object.", 'ERROR') return {'FINISHED'}
def createInertials(link, empty=False, preserve_children=False): """Creates inertial representations for visual and collision objects in link. :param link: The link you want to create the inertial for. :type link: bpy_types.Object :param empty: If set to True the new inertial object will contain no information. :type empty: bool :param preserve_children: If set to False already existent inertial objects will be deleted. :type preserve_children: bool """ # viscols = getInertiaRelevantObjects(link) # clean existing data if not preserve_children: oldinertials = selectionUtils.getImmediateChildren(link, ['inertial']) else: try: oldinertials = [bpy.data.objects['inertial_'+link.name]] except KeyError: oldinertials = None if oldinertials: selectionUtils.selectObjects(oldinertials, clear=True, active=0) bpy.ops.object.delete() if not preserve_children: for obj in viscols: if not empty: mass = obj['mass'] if 'mass' in obj else None geometry = robotdictionary.deriveGeometry(obj) if mass is not None: if geometry['type'] == 'mesh': selectionUtils.selectObjects([obj]) bpy.context.scene.objects.active = obj inert = calculateMeshInertia(obj.data, mass) #print('mesh:', inert) #print('ellipsoid:', calculateEllipsoidInertia(mass, geometry['size'])) #print('box:', calculateBoxInertia(mass, geometry['size'])) else: inert = calculateInertia(mass, geometry) if inert is not None: inertial = createInertial(obj) inertial['mass'] = mass inertial['inertia'] = inert else: createInertial(obj) # compose inertial object for link if not empty: mass, com, inert = fuseInertiaData(selectionUtils.getImmediateChildren(link, ['inertial'])) if mass and com and inert: inertial = createInertial(link) com_translate = mathutils.Matrix.Translation(com) inertial.matrix_local = com_translate bpy.ops.transform.translate(value=(0, 0, 0)) # FIXME: this is a trick to force Blender to apply matrix_local inertial['inertial/mass'] = mass inertial['inertial/inertia'] = inertiaMatrixToList(inert) else: createInertial(link)
def execute(self, context): """ Args: context: Returns: """ phobos_dict = ioUtils.getDictFromYamlDefs( self.phobostype, self.preset_name, self.obj_name ) selected_objs = context.selected_objects # store collected object data properties in the props dictionary for i in range(len(self.phobos_data)): if self.phobos_data[i].name[0] == 'b': store = '$' + str(bool(self.phobos_data[i]['boolProp'])).lower() elif self.phobos_data[i].name[0] == 'i': store = self.phobos_data[i]['intProp'] elif self.phobos_data[i].name[0] == 's': store = self.phobos_data[i]['stringProp'] elif self.phobos_data[i].name[0] == 'f': store = self.phobos_data[i]['floatProp'] phobos_dict['props'][self.phobos_data[i].name[2:]] = store annotations = {} # add annotation objects for other categories for custom_anno in self.annotation_checks: if custom_anno.boolProp: # parse object dictionaries if "$selected_objects:..." syntax is found annot = defs.definitions[self.phobostype + 's'][self.preset_name][ custom_anno.name[2:] ] annotations[custom_anno.name[2:]] = linkObjectLists(annot, selected_objs) # let the exectute function handle the object creation new_objs, annot_objs, otherobjs = execute_func( phobos_dict, annotations, selected_objs, context.active_object, *args ) # select the newly added objects sUtils.selectObjects(new_objs + annot_objs + otherobjs, clear=True, active=0) bUtils.toggleLayer(defs.layerTypes[self.phobostype], value=True) if annot_objs: bUtils.toggleLayer(defs.layerTypes['annotation'], value=True) # toggle layers for generic objects if otherobjs: for obj in otherobjs: bUtils.toggleLayer(defs.layerTypes[obj.phobostype], value=True) return {'FINISHED'}
def execute(self, context): """ Args: context: Returns: """ phobos_dict = ioUtils.getDictFromYamlDefs( self.phobostype, self.preset_name, self.obj_name ) selected_objs = context.selected_objects # store collected object data properties in the props dictionary for i in range(len(self.phobos_data)): if self.phobos_data[i].name[0] == 'b': store = '$' + str(bool(self.phobos_data[i]['boolProp'])).lower() elif self.phobos_data[i].name[0] == 'i': store = self.phobos_data[i]['intProp'] elif self.phobos_data[i].name[0] == 's': store = self.phobos_data[i]['stringProp'] elif self.phobos_data[i].name[0] == 'f': store = self.phobos_data[i]['floatProp'] phobos_dict['props'][self.phobos_data[i].name[2:]] = store annotations = {} # add annotation objects for other categories for custom_anno in self.annotation_checks: if custom_anno.boolProp: # parse object dictionaries if "$selected_objects:..." syntax is found annot = defs.definitions[self.phobostype + 's'][self.preset_name][ custom_anno.name[2:] ] annotations[custom_anno.name[2:]] = linkObjectLists(annot, selected_objs) # let the exectute function handle the object creation new_objs, annot_objs, otherobjs = execute_func( phobos_dict, annotations, selected_objs, context.active_object, *args ) # select the newly added objects sUtils.selectObjects(new_objs + annot_objs + otherobjs, clear=True, active=0) bUtils.toggleLayer(self.phobostype, value=True) if annot_objs: bUtils.toggleLayer('annotation', value=True) # toggle layers for generic objects if otherobjs: for obj in otherobjs: bUtils.toggleLayer(obj.phobostype, value=True) return {'FINISHED'}
def createJoint(joint, linkobj=None): """Adds joint data to 'link' object. Args: joint (dict): dictionary containing the joint definition linkobj (bpy.types.Object): the obj of phobostype 'link' that receives the joint Returns: """ # add joint information if not linkobj: linkobj = sUtils.getObjectByName(joint['child']) if isinstance(linkobj, list): log( "Could not identify object to define joint '{0}'.".format( joint['name']), 'ERROR') return if joint['name'] != linkobj.name: linkobj['joint/name'] = joint['name'] # get hold of object bUtils.toggleLayer(list(linkobj.layers).index(True), True) # any layer containing the object sUtils.selectObjects([linkobj], clear=True, active=0) # set axis if 'axis' in joint: if mathutils.Vector(tuple(joint['axis'])).length == 0.: log('Axis of joint {0} is of zero length: '.format(joint['name']), 'ERROR') else: bpy.ops.object.mode_set(mode='EDIT') editbone = linkobj.data.edit_bones[0] length = editbone.length axis = mathutils.Vector(tuple(joint['axis'])) editbone.tail = editbone.head + axis.normalized() * length # add constraints for param in ['effort', 'velocity']: try: if 'limits' in joint: linkobj['joint/max' + param] = joint['limits'][param] except KeyError: log("Joint limits incomplete for joint {0}".format(joint['name']), 'ERROR') try: lower = joint['limits']['lower'] upper = joint['limits']['upper'] except KeyError: lower = 0.0 upper = 0.0 setJointConstraints(linkobj, joint['type'], lower, upper) for prop in joint: if prop.startswith('$'): for tag in joint[prop]: linkobj['joint/' + prop[1:] + '/' + tag] = joint[prop][tag]
def addLight(light_dict): # DOCU add some docstring if light_dict['type'] == 'spotlight': light_type = 'SPOT' elif light_dict['type'] == 'omnilight': light_type = 'POINT' position = light_dict['pose']['translation'] rotation = light_dict['pose']['rotation_euler'] bpy.ops.object.lamp_add(type=light_type, location=position, rotation=rotation) light = bpy.context.active_object if 'parent' in light_dict: sUtils.selectObjects([light, bpy.data.objects[light_dict['parent']]], clear=True, active=1) bpy.ops.object.parent_set(type='BONE_RELATIVE') light_data = light.data light.name = light_dict['name'] colour_vals = ['r', 'g', 'b'] colour_data = light_dict['color']['diffuse'] light_data.color = [colour_data[v] for v in colour_vals] for v in colour_vals: if light_dict['color']['specular'][v] > 0: light_data.use_specular = True break if type == 'SPOT': light_data.spot_size = light_dict['angle'] # TODO delete me? #if light_dict['attenuation']['constant'] > 0: light_data.energy = light_dict['attenuation']['constant'] falloff = 'CONSTANT' if light_dict['attenuation']['linear'] > 0: light_data.linear_attenuation = light_dict['attenuation']['linear'] falloff = 'INVERSE_LINEAR' if light_dict['attenuation']['quadratic'] > 0: light_data.quadratic_attenuation = light_dict['attenuation'][ 'quadratic'] if falloff == 'INVERSE_LINEAR': falloff = 'LINEAR_QUADRATIC_WEIGHTED' else: falloff = 'INVERSE_SQUARE' light_data.falloff_type = falloff light.phobostype = 'light' light['light/exponent'] = light_dict['exponent'] light.phobostype = 'light' light['light/directional'] = light_dict['directional'] return light
def dissolveLink(obj, delete_other=False): """Remove the selected link and reparent all links, inertia, visual and collisions to its effective Parent. Args: obj(bpy.types.Object): the link to dissolve delete_other: (Default value = False) Returns: """ # Store original layers and show all layers originallayers = {} for name, coll in bpy.context.window.view_layer.layer_collection.children.items( ): originallayers[name] = coll.exclude coll.exclude = False if not obj.phobostype == 'link': log('Selected object {} is not a link!'.format(obj.name), 'ERROR') return else: delete = [obj] # Get all children children = sUtils.getRecursiveChildren(obj, phobostypes=('link', 'inertial', 'visual', 'collision'), include_hidden=True) if delete_other: other_children = sUtils.getRecursiveChildren( obj, recursion_depth=2, phobostypes=('motor', 'controller', 'sensor', 'submodel'), include_hidden=True, ) delete += [ child for child in other_children if child not in children ] # Get the parent parent = obj.parent # If parent is not None ( Root ) if obj.parent: # Reparent parentObjectsTo(children, parent, clear=True) # Delete the objects sUtils.selectObjects(delete, clear=True, active=-1) bpy.ops.object.delete() # Restore original layers for key, value in originallayers.items(): bpy.context.window.view_layer.layer_collection.children[ key].exclude = value
def execute(self, context): """ Args: context: Returns: """ sUtils.selectObjects(sUtils.getObjectsByPhobostypes([self.seltype]), True) return {'FINISHED'}
def execute(self, context): roots = set() for obj in bpy.context.selected_objects: roots.add(sUtils.getRoot(obj)) if len(roots) > 0: sUtils.selectObjects(list(roots), True) bpy.context.scene.objects.active = list(roots)[0] else: # bpy.ops.error.message('INVOKE_DEFAULT', type="ERROR", message="Couldn't find any root object.") log("Couldn't find any root object.", "ERROR") return {'FINISHED'}
def execute(self, context): master = context.active_object slaves = context.selected_objects to_cadorigin = self.cursor_location - master.matrix_world.to_translation() com_shift_world = to_cadorigin + self.com_shift for s in slaves: selectionUtils.selectObjects([s], True, 0) context.scene.cursor_location = s.matrix_world.to_translation() + com_shift_world bpy.ops.object.origin_set(type='ORIGIN_CURSOR') selectionUtils.selectObjects(slaves, True, slaves.index(master)) context.scene.cursor_location = self.cursor_location.copy() return {'FINISHED'}
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
def calculateInertia(obj, mass, geometry_dict=None, errors=None, adjust=False, logging=False): """Calculates the inertia of an object using the specified mass and optionally geometry. Args: obj(bpy.types.Object): object to calculate inertia from mass(float): mass of object geometry_dict(dict, optional): geometry part of the object dictionary Returns(tuple): (Default value = None) geometry_dict(dict, optional): geometry part of the object dictionary Returns(tuple): tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None) errors: (Default value = None) adjust: (Default value = False) logging: (Default value = False) Returns: """ if errors and not adjust: if logging: log("Can not calculate inertia from object.", 'ERROR') return None inertia = None if not geometry_dict: geometry = deriveGeometry(obj) # Get the rotation of the object object_rotation = obj.rotation_euler.to_matrix() if geometry['type'] == 'box': inertia = calculateBoxInertia(mass, geometry['size']) elif geometry['type'] == 'cylinder': inertia = calculateCylinderInertia(mass, geometry['radius'], geometry['length']) elif geometry['type'] == 'sphere': inertia = calculateSphereInertia(mass, geometry['radius']) elif geometry['type'] == 'mesh': sUtils.selectObjects((obj, ), clear=True, active=0) inertia = calculateMeshInertia(mass, obj.data, scale=obj.scale) # Correct the inertia orientation to account for Cylinder / mesh orientation issues inertia = object_rotation * inertiaListToMatrix( inertia) * object_rotation.transposed() return inertiaMatrixToList(inertia)
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'}
def dissolveLink(obj, delete_other=False): """Remove the selected link and reparent all links, inertia, visual and collisions to its effective Parent. Args: obj(bpy.types.Object): the link to dissolve delete_other: (Default value = False) Returns: """ # Store original layers originallayers = list(bpy.context.scene.layers) # Select all layers which contain bpy.context.scene.layers = [True for i in range(20)] if not obj.phobostype == 'link': log('Selected object {} is not a link!'.format(obj.name), 'ERROR') return else: delete = [obj] # Get all children children = sUtils.getRecursiveChildren(obj, phobostypes=('link', 'inertial', 'visual', 'collision'), include_hidden=True) if delete_other: other_children = sUtils.getRecursiveChildren( obj, recursion_depth=2, phobostypes=('motor', 'controller', 'sensor', 'submodel'), include_hidden=True, ) delete += [ child for child in other_children if child not in children ] # Get the parent parent = obj.parent # If parent is not None ( Root ) if obj.parent: # Reparent parentObjectsTo(children, parent, clear=True) # Delete the objects sUtils.selectObjects(delete, clear=True, active=-1) bpy.ops.object.delete() # Restore original layers bpy.context.scene.layers = originallayers
def addLight(light_dict): if light_dict['type'] == 'spotlight': light_type = 'SPOT' elif light_dict['type'] == 'omnilight': light_type = 'POINT' position = light_dict['pose']['translation'] rotation = light_dict['pose']['rotation_euler'] bpy.ops.object.lamp_add(type=light_type, location=position, rotation=rotation) light = bpy.context.active_object if 'parent' in light_dict: selectionUtils.selectObjects([light, bpy.data.objects[light_dict['parent']]], clear=True, active=1) bpy.ops.object.parent_set(type='BONE_RELATIVE') light_data = light.data light.name = light_dict['name'] colour_vals = ['r', 'g', 'b'] colour_data = light_dict['color']['diffuse'] light_data.color = [colour_data[v] for v in colour_vals] for v in colour_vals: if light_dict['color']['specular'][v] > 0: light_data.use_specular = True break if type == 'SPOT': light_data.spot_size = light_dict['angle'] #if light_dict['attenuation']['constant'] > 0: light_data.energy = light_dict['attenuation']['constant'] falloff = 'CONSTANT' if light_dict['attenuation']['linear'] > 0: light_data.linear_attenuation = light_dict['attenuation']['linear'] falloff = 'INVERSE_LINEAR' if light_dict['attenuation']['quadratic'] > 0: light_data.quadratic_attenuation = light_dict['attenuation']['quadratic'] if falloff == 'INVERSE_LINEAR': falloff = 'LINEAR_QUADRATIC_WEIGHTED' else: falloff = 'INVERSE_SQUARE' light_data.falloff_type = falloff light.phobostype = 'light' light['light/exponent'] = light_dict['exponent'] light.phobostype = 'light' light['light/directional'] = light_dict['directional'] return light
def cameraRotLock(object): selectionUtils.selectObjects([object], active=0) bpy.ops.transform.rotate(value=-1.5708, axis=(-1, 0, 0), constraint_axis=(False, False, True), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) bpy.ops.transform.rotate(value=1.5708, axis=(0, -1, 0), constraint_axis=(True, False, False), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) bpy.ops.object.constraint_add(type='LIMIT_ROTATION') object.constraints["Limit Rotation"].use_limit_x = True object.constraints["Limit Rotation"].use_limit_y = True object.constraints["Limit Rotation"].use_limit_z = True object.constraints["Limit Rotation"].min_x = object.rotation_euler[0] object.constraints["Limit Rotation"].max_x = object.rotation_euler[0] object.constraints["Limit Rotation"].min_y = object.rotation_euler[1] object.constraints["Limit Rotation"].max_y = object.rotation_euler[1] object.constraints["Limit Rotation"].min_z = object.rotation_euler[2] object.constraints["Limit Rotation"].max_z = object.rotation_euler[2]
def execute(self, context): roots = set() # add root object of each selected object for obj in bpy.context.selected_objects: roots.add(sUtils.getRoot(obj)) # select all found root objects if len(roots) > 0: sUtils.selectObjects(list(roots), True) bpy.context.scene.objects.active = list(roots)[0] else: log("Couldn't find any root object.", "ERROR") return {'FINISHED'}
def execute(self, context): startLog(self) objs = context.selected_objects root = sUtils.getRoot(context.selected_objects[0]) model = robotdictionary.buildModelDictionary(root) sUtils.selectObjects(objs) if bpy.data.worlds[0].relativePath: outpath = exporter.securepath(os.path.expanduser(os.path.join(bpy.path.abspath("//"), bpy.data.worlds[0].path))) else: outpath = exporter.securepath(os.path.expanduser(bpy.data.worlds[0].path)) exporter.bakeModel(objs, outpath, model["modelname"]) with open(os.path.join(outpath, "info.bake"), "w") as f: f.write(yaml.dump({"name": model["modelname"]})) endLog() return {'FINISHED'}
def createJoint(joint, linkobj=None): # TODO add some docstring # add joint information if not linkobj: linkobj = bpy.data.objects[joint['child']] # TODO: Make this generic? if joint['name'] != linkobj.name: linkobj['joint/name'] = joint['name'] # get hold of object bUtils.toggleLayer(defs.layerTypes['link'], True) sUtils.selectObjects([linkobj], clear=True, active=0) # set axis if 'axis' in joint: # Providing a zero axis joint will size the editbone to zero scale if mathutils.Vector(tuple(joint['axis'])).length == 0.: log( 'Faulty joint definition ({0}): Axis is of zero length.'. format(joint['name']), 'ERROR') else: bpy.ops.object.mode_set(mode='EDIT') editbone = linkobj.data.edit_bones[0] #oldaxis = editbone.vector length = editbone.length axis = mathutils.Vector(tuple(joint['axis'])) #oldaxis.cross(axis) # rotation axis editbone.tail = editbone.head + axis.normalized() * length # add constraints for param in ['effort', 'velocity']: try: if 'limits' in joint: linkobj['joint/max' + param] = joint['limits'][param] except KeyError: # TODO more details log("Key Error in adding joint constraints for joint", joint['name']) try: lower = joint['limits']['lower'] upper = joint['limits']['upper'] except KeyError: lower = 0.0 upper = 0.0 setJointConstraints(linkobj, joint['type'], lower, upper) for prop in joint: if prop.startswith('$'): for tag in joint[prop]: linkobj['joint/' + prop[1:] + '/' + tag] = joint[prop][tag]
def dissolveLink(obj, delete_other=False): """Remove the selected link and reparent all links, inertia, visual and collisions to its effective Parent. Args: obj(bpy.types.Object): the link to dissolve delete_other: (Default value = False) Returns: """ # Store original layers originallayers = list(bpy.context.scene.layers) # Select all layers which contain bpy.context.scene.layers = [True for i in range(20)] if not obj.phobostype == 'link': log('Selected object {} is not a link!'.format(obj.name), 'ERROR') return else: delete = [obj] # Get all children children = sUtils.getRecursiveChildren( obj, phobostypes=('link', 'inertial', 'visual', 'collision'), include_hidden=True ) if delete_other: other_children = sUtils.getRecursiveChildren( obj, recursion_depth=2, phobostypes=('motor', 'controller', 'sensor', 'submodel'), include_hidden=True, ) delete += [child for child in other_children if child not in children] # Get the parent parent = obj.parent # If parent is not None ( Root ) if obj.parent: # Reparent parentObjectsTo(children, parent, clear=True) # Delete the objects sUtils.selectObjects(delete, clear=True, active=-1) bpy.ops.object.delete() # Restore original layers bpy.context.scene.layers = originallayers
def execute(self, context): startLog(self) objs = context.selected_objects robot = robotdictionary.buildRobotDictionary() selectionUtils.selectObjects(objs) outpath = "" if bpy.data.worlds[0].relativePath: outpath = exporter.securepath(os.path.expanduser(os.path.join(bpy.path.abspath("//"), bpy.data.worlds[0].path))) else: outpath = exporter.securepath(os.path.expanduser(bpy.data.worlds[0].path)) #expPath = os.path.join(outpath, robot["modelname"] + "_bake") #exporter.export(path=expPath, robotmodel=robot) exporter.bakeModel(objs, outpath, robot["modelname"]) with open(os.path.join(outpath, "info.bake"), "w") as f: f.write(yaml.dump({"name": robot["modelname"]})) endLog() return {'FINISHED'}
def execute(self, context): if self.bakeObj == "None": return {"FINISHED"} with open(os.path.join(os.path.dirname(defs.__file__), "RobotLib.yml"), "r") as f: robot_lib = yaml.load(f.read()) root = links.createLink(1.0, name=self.robName + "::" + self.bakeObj) root["modelname"] = self.bakeObj root["entityname"] = self.robName root["isInstance"] = True bpy.ops.import_mesh.stl(filepath=os.path.join(robot_lib[self.bakeObj], "bake.stl")) bpy.ops.view3d.snap_selected_to_cursor(use_offset=False) obj = context.active_object obj.name = self.robName + "::visual" obj.phobostype = "visual" selectionUtils.selectObjects([root, obj], clear=True, active=0) bpy.ops.object.parent_set(type='BONE_RELATIVE') return {"FINISHED"}
def execute(self, context): selection = [] if self.modelname: log("phobos: Selecting model" + self.modelname, "INFO") roots = sUtils.getRoots() for root in roots: if root["modelname"] == self.modelname: selection = sUtils.getChildren(root) else: log("No model name provided, deriving from selection...", "INFO") roots = set() for obj in bpy.context.selected_objects: roots.add(sUtils.getRoot(obj)) for root in list(roots): selection.extend(sUtils.getChildren(root)) sUtils.selectObjects(list(selection), True) return {'FINISHED'}
def calculateInertia(obj, mass, geometry_dict=None, errors=None, adjust=False, logging=False): """Calculates the inertia of an object using the specified mass and optionally geometry. Args: obj(bpy.types.Object): object to calculate inertia from mass(float): mass of object geometry_dict(dict, optional): geometry part of the object dictionary Returns(tuple): (Default value = None) geometry_dict(dict, optional): geometry part of the object dictionary Returns(tuple): tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None) errors: (Default value = None) adjust: (Default value = False) logging: (Default value = False) Returns: """ if errors and not adjust: if logging: log("Can not calculate inertia from object.", 'ERROR') return None inertia = None if not geometry_dict: geometry = deriveGeometry(obj) # Get the rotation of the object object_rotation = obj.rotation_euler.to_matrix() if geometry['type'] == 'box': inertia = calculateBoxInertia(mass, geometry['size']) elif geometry['type'] == 'cylinder': inertia = calculateCylinderInertia(mass, geometry['radius'], geometry['length']) elif geometry['type'] == 'sphere': inertia = calculateSphereInertia(mass, geometry['radius']) elif geometry['type'] == 'mesh': sUtils.selectObjects((obj,), clear=True, active=0) inertia = calculateMeshInertia(mass, obj.data) # Correct the inertia orientation to account for Cylinder / mesh orientation issues inertia = object_rotation * inertiaListToMatrix(inertia) * object_rotation.transposed() return inertiaMatrixToList(inertia)
def execute(self, context): selection = [] if self.modelname: print("phobos: Selecting model", self.modelname) roots = selectionUtils.getRoots() for root in roots: if root["modelname"] == self.modelname: selection = selectionUtils.getChildren(root) else: print("phobos: No model name provided, deriving from selection...") roots = set() for obj in bpy.context.selected_objects: print("Selecting", selectionUtils.getRoot(obj).name) roots.add(selectionUtils.getRoot(obj)) for root in list(roots): selection.extend(selectionUtils.getChildren(root)) selectionUtils.selectObjects(list(selection), True) return {'FINISHED'}
def execute(self, context): if self.bakeObj == "None": return {"FINISHED"} with open(os.path.join(os.path.dirname(defs.__file__), "RobotLib.yml"), "r") as f: robot_lib = yaml.load(f.read()) root = links.createLink(1.0, name=self.robName + "::" + self.bakeObj) root["modelname"] = self.bakeObj root["entity/name"] = self.robName root["isInstance"] = True bpy.ops.import_mesh.stl(filepath=os.path.join( robot_lib[self.bakeObj], "bake.stl")) bpy.ops.view3d.snap_selected_to_cursor(use_offset=False) obj = context.active_object obj.name = self.robName + "::visual" obj.phobostype = "visual" sUtils.selectObjects([root, obj], clear=True, active=0) bpy.ops.object.parent_set(type='BONE_RELATIVE') return {"FINISHED"}
def calculateInertia(obj, mass, geometry_dict=None, errors=None, adjust=False, logging=False): """Calculates the inertia of an object using the specified mass and optionally geometry. Args: obj(bpy.types.Object): object to calculate inertia from mass(float): mass of object geometry_dict(dict, optional): geometry part of the object dictionary Returns(tuple): (Default value = None) geometry_dict(dict, optional): geometry part of the object dictionary Returns(tuple): tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None) errors: (Default value = None) adjust: (Default value = False) logging: (Default value = False) Returns: """ if errors and not adjust: if logging: log("Can not calculate inertia from object.", 'ERROR') return None inertia = None if not geometry_dict: geometry = deriveGeometry(obj) if geometry['type'] == 'box': inertia = calculateBoxInertia(mass, geometry['size']) elif geometry['type'] == 'cylinder': inertia = calculateCylinderInertia(mass, geometry['radius'], geometry['length']) elif geometry['type'] == 'sphere': inertia = calculateSphereInertia(mass, geometry['radius']) elif geometry['type'] == 'mesh': sUtils.selectObjects((obj, ), clear=True, active=0) inertia = calculateMeshInertia(mass, obj.data) return inertia
def execute(self, context): startLog(self) objs = context.selected_objects root = sUtils.getRoot(context.selected_objects[0]) model = robotdictionary.buildModelDictionary(root) sUtils.selectObjects(objs) if bpy.data.worlds[0].relativePath: outpath = exporter.securepath( os.path.expanduser( os.path.join(bpy.path.abspath("//"), bpy.data.worlds[0].path))) else: outpath = exporter.securepath( os.path.expanduser(bpy.data.worlds[0].path)) exporter.bakeModel(objs, outpath, model["modelname"]) with open(os.path.join(outpath, "info.bake"), "w") as f: f.write(yaml.dump({"name": model["modelname"]})) endLog() return {'FINISHED'}
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
def cameraRotLock(object): """TODO: PLEASE ADD PYDOC. What should this do exactly? :param object: The object to lock the rotation for :type object: bpy_types.Object """ selectionUtils.selectObjects([object], active=0) bpy.ops.transform.rotate(value=-1.5708, axis=(-1, 0, 0), constraint_axis=(False, False, True), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) bpy.ops.transform.rotate(value=1.5708, axis=(0, -1, 0), constraint_axis=(True, False, False), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) bpy.ops.object.constraint_add(type='LIMIT_ROTATION') object.constraints["Limit Rotation"].use_limit_x = True object.constraints["Limit Rotation"].use_limit_y = True object.constraints["Limit Rotation"].use_limit_z = True object.constraints["Limit Rotation"].min_x = object.rotation_euler[0] object.constraints["Limit Rotation"].max_x = object.rotation_euler[0] object.constraints["Limit Rotation"].min_y = object.rotation_euler[1] object.constraints["Limit Rotation"].max_y = object.rotation_euler[1] object.constraints["Limit Rotation"].min_z = object.rotation_euler[2] object.constraints["Limit Rotation"].max_z = object.rotation_euler[2]
def execute(self, context): roots = ioUtils.getExportModels() if not roots: log("No properly defined models selected or present in scene.", 'ERROR') return {'CANCELLED'} elif not self.exportall: roots = [ root for root in roots if root['modelname'] == self.modelname ] if len(roots) > 1: log( "Ambiguous model definitions: " + self.modelname + " exists " + str(len(roots)) + " times.", "ERROR") return {'CANCELLED'} for root in roots: # setup paths exportpath = ioUtils.getExportPath() if not securepath(exportpath): log("Could not secure path to export to.", "ERROR") continue log("Export path: " + exportpath, "DEBUG") ioUtils.exportModel(models.deriveModelDictionary(root), exportpath) # select all exported models after export is done if ioUtils.getExpSettings().selectedOnly: for root in roots: objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False) sUtils.selectObjects(objectlist, clear=False) else: bpy.ops.object.select_all(action='DESELECT') for root in roots: sUtils.selectObjects(list([root]), False) bpy.ops.phobos.select_model() # report success to user log("Export successful.", "INFO") return {'FINISHED'}
def execute(self, context): startLog(self) objs = context.selected_objects robot = robotdictionary.buildRobotDictionary() selectionUtils.selectObjects(objs) outpath = "" if bpy.data.worlds[0].relativePath: outpath = exporter.securepath( os.path.expanduser( os.path.join(bpy.path.abspath("//"), bpy.data.worlds[0].path))) else: outpath = exporter.securepath( os.path.expanduser(bpy.data.worlds[0].path)) #expPath = os.path.join(outpath, robot["modelname"] + "_bake") #exporter.export(path=expPath, robotmodel=robot) exporter.bakeModel(objs, outpath, robot["modelname"]) with open(os.path.join(outpath, "info.bake"), "w") as f: f.write(yaml.dump({"name": robot["modelname"]})) endLog() return {'FINISHED'}
def placeLinkSubelements(link): """Finds all subelements for a given link and sets the appropriate relations. In this case subelements are interials, visuals and collisions. :param link: The parent link you want to set the subelements for :type link: dict """ elements = getGeometricElements(link) + ([link['inertial']] if 'inertial' in link else []) bpy.context.scene.layers = bUtils.defLayers( [defs.layerTypes[t] for t in defs.layerTypes]) parentlink = bpy.data.objects[link['name']] log( 'Placing subelements for link: ' + link['name'] + ': ' + ', '.join([elem['name'] for elem in elements]), 'DEBUG') for element in elements: if 'pose' in element: log('Pose detected for element: ' + element['name'], 'DEBUG') location = mathutils.Matrix.Translation( element['pose']['translation']) rotation = mathutils.Euler( tuple(element['pose']['rotation_euler']), 'XYZ').to_matrix().to_4x4() else: log('No pose in element: ' + element['name'], 'DEBUG') location = mathutils.Matrix.Identity(4) rotation = mathutils.Matrix.Identity(4) try: obj = bpy.data.objects[element['name']] except KeyError: log('Missing link element for placement: ' + element['name'], 'ERROR') continue sUtils.selectObjects([obj, parentlink], True, 1) bpy.ops.object.parent_set(type='BONE_RELATIVE') obj.matrix_local = location * rotation try: obj.scale = mathutils.Vector(element['geometry']['scale']) except KeyError: log('No scale defined for element ' + element['name'], 'DEBUG')
def importBlenderModel(filepath, namespace='', prefix=False): """Imports an existing Blender model into the current .blend scene Args: filepath(str): Path of the .blend file namespace: (Default value = '') prefix: (Default value = False) Returns: """ if os.path.exists(filepath) and os.path.isfile(filepath) and filepath.endswith('.blend'): log("Importing Blender model" + filepath, "INFO") objects = [] with bpy.data.libraries.load(filepath) as (data_from, data_to): for objname in data_from.objects: objects.append({'name': objname}) bpy.ops.wm.append(directory=filepath + "/Object/", files=objects) imported_objects = bpy.context.selected_objects resources = [obj for obj in imported_objects if obj.name.startswith('resource::')] new_objects = [obj for obj in imported_objects if not obj.name.startswith('resource::')] if resources: if 'resources' not in bpy.data.scenes.keys(): bpy.data.scenes.new('resources') sUtils.selectObjects(resources) bpy.ops.object.make_links_scene(scene='resources') bpy.ops.object.delete(use_global=False) sUtils.selectObjects(new_objects) bpy.ops.view3d.view_selected(use_all_regions=False) # allow the use of both prefixes and namespaces, thus truly merging # models or keeping them separate for export if namespace != '': if prefix: for obj in bpy.context.selected_objects: # set prefix instead of namespace obj.name = namespace + '__' + obj.name # make sure no internal name-properties remain for key in obj.keys(): try: if obj[key].endswidth("/name"): del obj[key] except AttributeError: # prevent exceptions from non-string properties pass else: for obj in bpy.context.selected_objects: nUtils.addNamespace(obj, namespace) submechanism_roots = [ obj for obj in bpy.data.objects if obj.phobostype == 'link' and 'submechanism/spanningtree' in obj ] for root in submechanism_roots: partlist = [root] + root['submechanism/spanningtree'] if 'submechanism/freeloader' in root: partlist += root['submechanism/freeloader'] sUtils.selectObjects(partlist, active=0) bpy.ops.group.create(name='submechanism:' + root['submechanism/name']) return True else: return False
def execute(self, context): root = sUtils.getRoot(context.selected_objects[0]) objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False) sUtils.selectObjects(objectlist) poses = models.getPoses(root['modelname']) i = 1 for pose in poses: sUtils.selectObjects([root] + objectlist, clear=True, active=0) models.loadPose(root['modelname'], pose) parameter = self.decimate_ratio if self.decimate_type == 'UNSUBDIV': parameter = self.decimate_iteration elif self.decimate_type == 'DISSOLVE': parameter = self.decimate_angle_limit exporter.bakeModel(objectlist, root['modelname'], pose, decimate_type=self.decimate_type, decimate_parameter=parameter) display.setProgress(i / len(poses)) i += 1 sUtils.selectObjects([root] + objectlist, clear=True, active=0) bpy.ops.scene.reload_models_and_poses_operator() return {'FINISHED'}
def execute(self, context): """ Args: context: Returns: """ root = sUtils.getRoot(context.selected_objects[0]) objectlist = sUtils.getChildren(root, selected_only=True, include_hidden=False) sUtils.selectObjects(objectlist) poses = models.getPoses(root['model/name']) i = 1 for pose in poses: sUtils.selectObjects([root] + objectlist, clear=True, active=0) models.loadPose(root['model/name'], pose) parameter = self.decimate_ratio if self.decimate_type == 'UNSUBDIV': parameter = self.decimate_iteration elif self.decimate_type == 'DISSOLVE': parameter = self.decimate_angle_limit exporter.bakeModel( objectlist, root['model/name'], pose, decimate_type=self.decimate_type, decimate_parameter=parameter, ) display.setProgress(i / len(poses)) i += 1 sUtils.selectObjects([root] + objectlist, clear=True, active=0) bpy.ops.scene.reload_models_and_poses_operator() return {'FINISHED'}
def placeChildLinks(model, parent): """Creates parent-child-relationship for a given parent and all existing children in Blender. :param parent: This is the parent link you want to set the children for. :type: dict """ bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes['link']) children = [] for l in model['links']: if 'parent' in model['links'][l] and model['links'][l][ 'parent'] == parent['name']: children.append(model['links'][l]) for child in children: # 1: set parent relationship (this makes the parent inverse the inverse of the parents world transform) parentLink = bpy.data.objects[parent['name']] childLink = bpy.data.objects[child['name']] sUtils.selectObjects([childLink, parentLink], True, 1) bpy.ops.object.parent_set(type='BONE_RELATIVE') # 2: move to parents origin by setting the world matrix to the parents world matrix # removing this line does not seem to make a difference (TODO delete me?) childLink.matrix_world = parentLink.matrix_world # TODO delete me? # #bpy.context.scene.objects.active = childLink # if 'pivot' in child: # pivot = child['pivot'] # cursor_location = bpy.context.scene.cursor_location # bpy.context.scene.cursor_location = mathutils.Vector((-pivot[0]*0.3, -pivot[1]*0.3, -pivot[2]*0.3)) # bpy.ops.object.origin_set(type='ORIGIN_CURSOR') # bpy.context.scene.cursor_location = cursor_location # 3: apply local transform as saved in model (changes matrix_local) location = mathutils.Matrix.Translation(child['pose']['translation']) rotation = mathutils.Euler(tuple(child['pose']['rotation_euler']), 'XYZ').to_matrix().to_4x4() transform_matrix = location * rotation childLink.matrix_local = transform_matrix # 4: be happy, as world and basis are now the same and local is the transform to be exported to urdf # 5: take care of the rest of the tree placeChildLinks(model, child)
def mergeLinks(links, targetlink, movetotarget=False): """ Args: links: targetlink: movetotarget: (Default value = False) Returns: """ for link in links: if movetotarget: link.matrix_world = targetlink.matrix_world sUtils.selectObjects([link], clear=True, active=0) bpy.ops.object.select_grouped(type='CHILDREN') bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') try: parentObjectsTo(bpy.context.selected_objects, targetlink) except RuntimeError as e: log("Cannot resolve new parent hierarchy: " + str(e), 'ERROR') del link
def execute(self, context): root = sUtils.getRoot(context.selected_objects[0]) modelsPosesColl = bUtils.getPhobosPreferences().models_poses activeModelPoseIndex = bpy.context.scene.active_ModelPose selected_robot = modelsPosesColl[ bpy.data.images[activeModelPoseIndex].name] objectlist = sUtils.getChildren( root, selected_only=True, include_hidden=False) sUtils.selectObjects([root] + objectlist, clear=True, active=0) models.loadPose(selected_robot.robot_name, selected_robot.label) parameter = self.decimate_ratio if self.decimate_type == 'UNSUBDIV': parameter = self.decimate_iteration elif self.decimate_type == 'DISSOLVE': parameter = self.decimate_angle_limit exporter.bakeModel(objectlist, root['modelname'], selected_robot.label, decimate_type=self.decimate_type, decimate_parameter=parameter) sUtils.selectObjects([root] + objectlist, clear=True, active=0) bpy.ops.scene.reload_models_and_poses_operator() return {'FINISHED'}
def createInertials(link, empty=False, preserve_children=False): # create inertial representations for visual and collision objects in link viscols = getInertiaRelevantObjects(link) # clean existing data if not preserve_children: oldinertials = selectionUtils.getImmediateChildren(link, ['inertial']) else: try: oldinertials = [bpy.data.objects['inertial_'+link.name]] except KeyError: oldinertials = None if oldinertials: selectionUtils.selectObjects(oldinertials, clear=True, active=0) bpy.ops.object.delete() if not preserve_children: for obj in viscols: if not empty: mass = obj['mass'] if 'mass' in obj else None geometry = robotdictionary.deriveGeometry(obj) if mass is not None: inert = calculateInertia(mass, geometry) if inert is not None: inertial = createInertial(obj) inertial['mass'] = mass inertial['inertia'] = inert else: createInertial(obj) # compose inertial object for link if not empty: mass, com, inert = fuseInertiaData(selectionUtils.getImmediateChildren(link, ['inertial'])) if mass and com and inert: inertial = createInertial(link) com_translate = mathutils.Matrix.Translation(com) inertial.matrix_local = com_translate bpy.ops.transform.translate(value=(0, 0, 0)) # FIXME: this is a trick to force Blender to apply matrix_local inertial['inertial/mass'] = mass inertial['inertial/inertia'] = inertiaMatrixToList(inert) else: createInertial(link)
def disconnectInterfaces(parentinterface, childinterface, transform=None): """ Args: parentinterface: childinterface: transform: (Default value = None) Returns: """ # unparent the child sUtils.selectObjects(objects=[childinterface], clear=True, active=0) bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') # select the former parent of the interface as new root if childinterface.children and len(childinterface.children) > 0: # prefer submodel instances for child in childinterface.children: if child.phobostype == 'submodel': root = child break # otherwise just use the first child else: root = childinterface.children[0] # restructure the kinematic tree to make the interface child of the submodel again sUtils.selectObjects(objects=[root], clear=True, active=0) bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') parentObjectsTo(childinterface, root) # apply additional transform if transform: childinterface.matrix_world = root.matrix_world * transform # make the interfaces active again parentinterface.show_name = True childinterface.show_name = True
def disconnectInterfaces(parentinterface, childinterface, transform=None): """ Args: parentinterface: childinterface: transform: (Default value = None) Returns: """ # unparent the child sUtils.selectObjects(objects=[childinterface], clear=True, active=0) bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') # select the former parent of the interface as new root if childinterface.children and len(childinterface.children) > 0: # prefer submodel instances for child in childinterface.children: if child.phobostype == 'submodel': root = child break # otherwise just use the first child else: root = childinterface.children[0] # restructure the kinematic tree to make the interface child of the submodel again sUtils.selectObjects(objects=[root], clear=True, active=0) bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') parentObjectsTo(childinterface, root) # apply additional transform if transform: childinterface.matrix_world = root.matrix_world @ transform # make the interfaces active again parentinterface.show_name = True childinterface.show_name = True
def deriveLinkfromObject(obj, scale=0.2, parenting=True, parentobjects=False, namepartindices=[], separator='_', prefix='link'): """Derives a link from an object that defines a joint through its position, orientation and parent-child relationships. :param obj: The object you want to derive your link from. :type obj: bpy_types.Object :param scale: The scale you want to apply to the link. :type scale: float :param parenting: Whether you want to automate the parenting of the new link or not. :type parenting: bool. :param parentobjects: Whether you want to parent all the objects to the new link or not. :type parentobjects: bool. :param namepartindices: Parts of the objects name you want to reuse in the links name. :type namepartindices: list with two elements. :param separator: The separator you want to use to separate the links name with. Its '_' per default :type separator: str :param prefix: The prefix you want to use for the new links name. Its 'link' per default. :type prefix: str """ print('Deriving link from', namingUtils.getObjectName(obj)) nameparts = namingUtils.getObjectName(obj).split('_') rotation = obj.matrix_world.to_euler() if 'invertAxis' in obj and obj['invertAxis'] == 1: rotation.x += math.pi if rotation.x < 0 else -math.pi tmpname = namingUtils.getObjectName(obj) if namepartindices: try: tmpname = separator.join([nameparts[p] for p in namepartindices]) except IndexError: print('Wrong name segment indices given for obj', namingUtils.getObjectName(obj)) if prefix != '': tmpname = prefix + separator + tmpname if tmpname == namingUtils.getObjectName(obj): obj.name += '*' link = createLink(scale, obj.matrix_world.to_translation(), obj.matrix_world.to_euler(), tmpname) if parenting: if obj.parent: selectionUtils.selectObjects([link, obj.parent], True, 1) if obj.parent.phobostype == 'link': bpy.ops.object.parent_set(type='BONE_RELATIVE') else: bpy.ops.object.parent_set(type='OBJECT') children = selectionUtils.getImmediateChildren(obj) if parentobjects: children.append(obj) for child in children: selectionUtils.selectObjects([child], True, 0) bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') selectionUtils.selectObjects([child, link], True, 1) bpy.ops.object.parent_set(type='BONE_RELATIVE')
def storePose(root, posename): """Stores the current pose of all of a model's selected joints. Existing poses of the same name will be overwritten. Args: root(bpy_types.Object): root of the model the pose belongs to posename(str): name the pose will be stored under Returns: : Nothing. """ if root: filename = nUtils.getModelName(root) + '::poses' posedict = yaml.load(bUtils.readTextFile(filename)) if not posedict: posedict = {posename: {'name': posename, 'joints': {}}} else: posedict[posename] = {'name': posename, 'joints': {}} links = sUtils.getChildren(root, ('link', ), True, False) sUtils.selectObjects([root] + links, clear=True, active=0) bpy.ops.object.mode_set(mode='POSE') for link in (link for link in links if 'joint/type' in link and link['joint/type'] not in ['fixed', 'floating']): link.pose.bones['Bone'].rotation_mode = 'XYZ' posedict[posename]['joints'][nUtils.getObjectName( link, 'joint')] = link.pose.bones['Bone'].rotation_euler.y bpy.ops.object.mode_set(mode='OBJECT') posedict = gUtils.roundFloatsInDict( posedict, ioUtils.getExpSettings().decimalPlaces) bUtils.updateTextFile(filename, yaml.dump(posedict, default_flow_style=False)) else: log("No model root provided to store the pose for", "ERROR")
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
def parentObjectsTo(objects, parent, clear=False): """Parents the specified objects to the parent object. Depending on their phobostype the objects are parented either *bone relative* or *object*. If *clear* is set, the parenting of the objects will be cleared (keeping the transform), before parenting. Args: objects(list(bpy.types.Object): objects to set parent of parent(bpy.types.Object): parent object clear(bool, optional): if True, the parenting of the objects will be cleared (Default value = False) Returns: """ if not isinstance(objects, list): objects = [objects] # Store original layers #originallayers = list(bpy.context.scene.layers) # Select all layers #bpy.context.scene.layers = [True for i in range(20)] # Restore original layers #bpy.context.scene.layers = originallayers if clear: sUtils.selectObjects(objects, active=0, clear=True) bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') sUtils.selectObjects([parent] + objects, active=0, clear=True) if parent.phobostype == 'link': bpy.ops.object.parent_set(type='BONE_RELATIVE') else: bpy.ops.object.parent_set(type='OBJECT')
def deriveLinkfromObject(obj, scale=0.2, parent_link=True, parent_objects=False, nameformat=''): """Derives a link from an object using its name, transformation and parenting. Args: obj(bpy_types.Object): object to derive a link from scale(float, optional): scale factor for bone size (Default value = 0.2) parent_link(bool, optional): whether to automate the parenting of the new link or not. (Default value = True) parent_objects(bool, optional): whether to parent all the objects to the new link or not (Default value = False) nameformat(str, optional): re-formatting template for obj names (Default value = '') Returns: newly created link """ log('Deriving link from ' + nUtils.getObjectName(obj), level="INFO") try: nameparts = [ p for p in re.split('[^a-zA-Z]', nUtils.getObjectName(obj)) if p != '' ] linkname = nameformat.format(*nameparts) except IndexError: log( 'Invalid name format (indices) for naming: ' + nUtils.getObjectName(obj), 'WARNING') linkname = 'link_' + nUtils.getObjectName(obj) link = createLink({ 'scale': scale, 'name': linkname, 'matrix': obj.matrix_world }) # parent link to object's parent if parent_link: if obj.parent: sUtils.selectObjects([link, obj.parent], True, 1) if obj.parent.phobostype == 'link': bpy.ops.object.parent_set(type='BONE_RELATIVE') else: bpy.ops.object.parent_set(type='OBJECT') # parent children of object to link if parent_objects: children = [obj] + sUtils.getImmediateChildren(obj) sUtils.selectObjects(children, True, 0) bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') sUtils.selectObjects([link] + children, True, 0) bpy.ops.object.parent_set(type='BONE_RELATIVE') return link