def createInertialFromDictionary(name, inertial): """Creates the Blender representation of a given intertial provided a dictionary. :param name: The intertials name. :param type: str :param inertial: The intertial you want to create in blender form. :type intertial: dict :return: bpy_types.Object -- the newly created blender inertial object. """ # FIXME: this needs work to get rid of duplicate code bpy.ops.object.select_all(action='DESELECT') inert = bUtils.createPrimitive('inertial_' + name, 'box', [0.06, 0.06, 0.06], player='inertial') inert.select = True bpy.ops.object.transform_apply(scale=True) for prop in inertial: if prop not in ['pose'] and inertial[prop] is not None: if not prop.startswith('$'): inert[prop] = inertial[prop] else: for tag in inertial[prop]: inert[prop[1:] + '/' + tag] = inertial[prop][tag] inert.phobostype = 'inertial' assignMaterial(inert, 'phobos_inertial') return inert
def createPrimitive(pname, ptype, psize, player=0, pmaterial=None, plocation=(0, 0, 0), protation=(0, 0, 0), phobostype=None): """Generates the primitive specified by the input parameters Args: pname(str): The primitives new name. ptype(str): The new primitives type. Can be one of *box, sphere, cylinder, cone, disc* psize(float or list): The new primitives size. Depending on the ptype it can be either a single float or a tuple. player: The layer bitmask for the new blender object. (Default value = 0) pmaterial: The new primitives material. (Default value = None) plocation(tuple, optional): The new primitives location. (Default value = (0) protation(tuple): The new primitives rotation. phobostype(str): phobostype of object to be created 0: Returns: bpy.types.Object - the new blender object. """ # TODO: allow placing on currently active layer? try: n_layer = int(player) except ValueError: n_layer = defs.layerTypes[player] players = defLayers([n_layer]) # the layer has to be active to prevent problems with object placement bpy.context.scene.layers[n_layer] = True 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 if phobostype: obj.phobostype = phobostype nUtils.safelyName(obj, pname, phobostype) if pmaterial: materials.assignMaterial(obj, pmaterial) return obj
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': materials.assignMaterial(obj, pmaterial) return obj
def createGeometry(viscol, geomsrc): """Creates geometrical Blender object for visual or collision objects. :param viscol: The visual/collision dictionary element you want to create the geometry for. :type viscol: dict :param geomsrc: The new viscols phobostype. :type geomsrc: str """ if 'geometry' not in viscol or viscol['geometry'] is {}: return None bpy.ops.object.select_all(action='DESELECT') geom = viscol['geometry'] geomtype = geom['type'] # create the Blender object if geomtype == 'mesh': bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc]) meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1]) if not os.path.isfile(geom['filename']): log(geom['filename'] + " is no file. Object " + viscol['name'] + " will have empty mesh!", "ERROR") bpy.data.meshes.new(meshname) if meshname in bpy.data.meshes: log('Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO') bpy.ops.object.add(type='MESH') newgeom = bpy.context.object newgeom.data = bpy.data.meshes[meshname] else: log('Importing mesh for link element ' + viscol['name'], 'INFO') filetype = geom['filename'].split('.')[-1].lower() newgeom = meshes.importMesh(geom['filename'], filetype) newgeom.data.name = meshname if not newgeom: log('Failed to import mesh file ' + geom['filename'], 'ERROR') return # scale imported object if 'scale' in geom: sUtils.selectObjects((newgeom,), clear=True) newgeom.scale = geom['scale'] else: if geomtype == 'box': dimensions = geom['size'] elif geomtype == 'cylinder': dimensions = (geom['radius'], geom['length']) elif geomtype == 'sphere': dimensions = geom['radius'] else: log("Could not determine geometry type of " + geomsrc + viscol['name'] + '. Placing empty coordinate system.', "ERROR") bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2) bpy.context.active_object.name = viscol['name'] return None log('Creating primtive for obj ' + viscol['name'], 'INFO') newgeom = bUtils.createPrimitive(viscol['name'], geomtype, dimensions, player=geomsrc) newgeom.select = True bpy.ops.object.transform_apply(scale=True) # from here it's the same for both meshes and primitives newgeom.phobostype = geomsrc newgeom['geometry/type'] = geomtype if geomsrc == 'visual': try: if 'name' in viscol['material']: assignMaterial(newgeom, viscol['material']['name']) else: assignMaterial(newgeom, viscol['material']) except KeyError: log('No material for obj ' + viscol['name'], 'DEBUG') # FIXME: place empty coordinate system and return...what? Error handling of file import! for prop in viscol: if prop.startswith('$'): for tag in viscol[prop]: newgeom[prop[1:]+'/'+tag] = viscol[prop][tag] newgeom.name = viscol['name'] newgeom[geomsrc+"/name"] = viscol['name'] return newgeom
def createGeometry(viscol, geomsrc, linkobj=None): """Creates Blender object for visual or collision objects. Returns reference to new object or None if creation failed. Args: viscol(dict): visual/collision dictionary element geomsrc(str): new object's phobostype linkobj(bpy.types.Object): link object Returns: bpy.types.Object or None """ if 'geometry' not in viscol or viscol['geometry'] is {}: return None bpy.ops.object.select_all(action='DESELECT') geom = viscol['geometry'] # create the Blender object if geom['type'] == 'mesh': bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc]) meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1]) if not os.path.isfile(geom['filename']): log(geom['filename'] + " is no file. Object " + viscol['name'] + " will have empty mesh!", "ERROR") #bpy.data.meshes.new(meshname) bpy.ops.object.add(type='MESH') newgeom = bpy.context.active_object nUtils.safelyName(newgeom, viscol['name'], phobostype=geomsrc) else: if meshname in bpy.data.meshes: log('Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO') bpy.ops.object.add(type='MESH') newgeom = bpy.context.object newgeom.data = bpy.data.meshes[meshname] else: log("Importing mesh for {0} element: '{1}".format(geomsrc, viscol['name']), 'INFO') filetype = geom['filename'].split('.')[-1].lower() newgeom = meshes.importMesh(geom['filename'], filetype) newgeom.data.name = meshname if not newgeom: log('Failed to import mesh file ' + geom['filename'], 'ERROR') return # scale imported object if 'scale' in geom: newgeom.scale = geom['scale'] else: if geom['type'] == 'box': dimensions = geom['size'] elif geom['type'] == 'cylinder': dimensions = (geom['radius'], geom['length']) elif geom['type'] == 'sphere': dimensions = geom['radius'] else: log("Unknown geometry type of " + geomsrc + viscol['name'] + '. Placing empty coordinate system.', "ERROR") bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2) obj = bpy.context.object obj.phobostype = geomsrc nUtils.safelyName(bpy.context.active_object, viscol['name'], phobostype=geomsrc) return None log('Creating primtive for {0}: {1}'.format(geomsrc, viscol['name']), 'INFO') newgeom = bUtils.createPrimitive(viscol['name'], geom['type'], dimensions, phobostype=geomsrc) newgeom.select = True bpy.ops.object.transform_apply(scale=True) # from here it's the same for both meshes and primitives newgeom['geometry/type'] = geom['type'] if geomsrc == 'visual': try: assignMaterial(newgeom, viscol['material']) except KeyError: log('No material for visual ' + viscol['name'], 'DEBUG') for prop in viscol: if prop.startswith('$'): for tag in viscol[prop]: newgeom[prop[1:]+'/'+tag] = viscol[prop][tag] nUtils.safelyName(newgeom, viscol['name']) newgeom[geomsrc+"/name"] = viscol['name'] newgeom.phobostype = geomsrc # place geometric object relative to its parent link if linkobj: if 'pose' in viscol: log('Setting transformation of element: ' + viscol['name'], 'DEBUG') location = mathutils.Matrix.Translation(viscol['pose']['translation']) rotation = mathutils.Euler(tuple(viscol['pose']['rotation_euler']), 'XYZ').to_matrix().to_4x4() else: log('No pose in element: ' + viscol['name'], 'DEBUG') location = mathutils.Matrix.Identity(4) rotation = mathutils.Matrix.Identity(4) sUtils.selectObjects([newgeom, linkobj], True, 1) bpy.ops.object.parent_set(type='BONE_RELATIVE') newgeom.matrix_local = location * rotation if 'scale' in viscol['geometry']: newgeom.scale = mathutils.Vector(viscol['geometry']['scale']) return newgeom
def createGeometry(viscol, geomsrc, linkobj=None): """Creates Blender object for visual or collision objects. If the creation fails, nothing is returned. These entries in the dictionary are mandatory: | **geometry**: | **type**: type of geometry (mesh, box, cylinder, sphere) Depending on the geometry type other values are required: `size`, `radius`, `length` These entries are optional: | **geometry**: | **scale**: scale for the new geometry | **material**: material name to assign to the visual | **pose**: specifies the placement of the new object relative to the optional linkobj | **translation**: position vector for the new object | **rotation_euler**: rotation for the new object Furthermore any generic properties, prepended by a ``$`` will be added as custom properties to the visual/collision object. E.g. ``$test/etc`` would be put to visual/test/etc for a visual object. However, these properties are extracted only in the first layer of hierarchy. Args: viscol(dict): visual/collision model dictionary representation geomsrc(str): phobostype of the new object linkobj(bpy.types.Object, optional): link object to attach the visual/collision object to (Default value = None) Returns: bpy.types.Object or None: the new geometry object or nothing """ if 'geometry' not in viscol or viscol['geometry'] is {}: log("Could not create {}. Geometry information not defined!".format(geomsrc), 'ERROR') return None bpy.ops.object.select_all(action='DESELECT') geom = viscol['geometry'] # create the Blender object if geom['type'] == 'mesh': bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc]) meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1]) if not os.path.isfile(geom['filename']): log( "This path " + geom['filename'] + " is no file. Object " + viscol['name'] + " will have empty mesh!", 'ERROR', ) bpy.ops.object.add(type='MESH') newgeom = bpy.context.active_object nUtils.safelyName(newgeom, viscol['name'], phobostype=geomsrc) else: if meshname in bpy.data.meshes: log('Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO') bpy.ops.object.add(type='MESH') newgeom = bpy.context.object newgeom.data = bpy.data.meshes[meshname] else: log("Importing mesh for {0} element: '{1}".format(geomsrc, viscol['name']), 'INFO') filetype = geom['filename'].split('.')[-1].lower() newgeom = meshes.importMesh(geom['filename'], filetype) # bpy.data.meshes[newgeom].name = meshname if not newgeom: log('Failed to import mesh file ' + geom['filename'], 'ERROR') return else: if geom['type'] == 'box': dimensions = geom['size'] elif geom['type'] == 'cylinder': dimensions = (geom['radius'], geom['length']) elif geom['type'] == 'sphere': dimensions = geom['radius'] # TODO add support for heightmap, image, plane and polyline geometries (see sdf!) else: log( "Unknown geometry type of " + geomsrc + viscol['name'] + '. Placing empty coordinate system.', "ERROR", ) bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2) obj = bpy.context.object obj.phobostype = geomsrc nUtils.safelyName(bpy.context.active_object, viscol['name'], phobostype=geomsrc) return None log("Creating primtive for {0}: {1}".format(geomsrc, viscol['name']), 'INFO') newgeom = bUtils.createPrimitive( viscol['name'], geom['type'], dimensions, phobostype=geomsrc ) newgeom.select = True bpy.ops.object.transform_apply(scale=True) # from here it's the same for both meshes and primitives newgeom['geometry/type'] = geom['type'] if geomsrc == 'visual': if 'material' in viscol: assignMaterial(newgeom, viscol['material']) else: log('No material for visual {}.'.format(viscol['name']), 'WARNING') # write generic custom properties for prop in viscol: if prop.startswith('$'): for tag in viscol[prop]: newgeom[prop[1:] + '/' + tag] = viscol[prop][tag] nUtils.safelyName(newgeom, viscol['name']) newgeom[geomsrc + '/name'] = viscol['name'] newgeom.phobostype = geomsrc # place geometric object relative to its parent link if linkobj: if 'pose' in viscol: log("Setting transformation of element: " + viscol['name'], 'DEBUG') location = mathutils.Matrix.Translation(viscol['pose']['translation']) rotation = ( mathutils.Euler(tuple(viscol['pose']['rotation_euler']), 'XYZ').to_matrix().to_4x4() ) else: log("No pose in element: " + viscol['name'], 'DEBUG') location = mathutils.Matrix.Identity(4) rotation = mathutils.Matrix.Identity(4) eUtils.parentObjectsTo(newgeom, linkobj) newgeom.matrix_local = location * rotation # scale imported object if 'scale' in geom: newgeom.scale = geom['scale'] # make object smooth eUtils.smoothen_surface(newgeom) return newgeom
def createPrimitive( pname, ptype, psize, player=0, pmaterial=None, plocation=(0, 0, 0), protation=(0, 0, 0), phobostype=None, ): """Generates the primitive specified by the input parameters Args: pname(str): The primitives new name. ptype(str): The new primitives type. Can be one of *box, sphere, cylinder, cone, disc* psize(float or list): The new primitives size. Depending on the ptype it can be either a single float or a tuple. player: The layer bitmask for the new blender object. (Default value = 0) pmaterial: The new primitives material. (Default value = None) plocation(tuple, optional): The new primitives location. (Default value = (0) protation(tuple, optional): The new primitives rotation. (Default value = (0) phobostype(str, optional): phobostype of object to be created (Default value = None) 0: 0): Returns: : bpy.types.Object - the new blender object. """ # TODO: allow placing on currently active layer? try: n_layer = int(player) except ValueError: n_layer = defs.layerTypes[player] players = defLayers([n_layer]) # the layer has to be active to prevent problems with object placement bpy.context.scene.layers[n_layer] = True if ptype == "box": bpy.ops.mesh.primitive_cube_add(layers=players, location=plocation, rotation=protation) obj = bpy.context.object obj.dimensions = psize elif 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, end_fill_type='TRIFAN', ) 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, end_fill_type='TRIFAN', ) elif ptype == 'disc': bpy.ops.mesh.primitive_circle_add( vertices=psize[1], radius=psize[0], fill_type='TRIFAN', location=plocation, rotation=protation, layers=players, ) elif ptype == 'ico': bpy.ops.mesh.primitive_ico_sphere_add( size=psize, layers=players, location=plocation, rotation=protation ) else: log("Primitive type not found: " + ptype + ". Adding default cube instead.", 'WARNING') bpy.ops.mesh.primitive_cube_add(layers=players, location=plocation, rotation=protation) obj = bpy.context.object obj.dimensions = psize bpy.ops.object.transform_apply(location=False, rotation=False, scale=True) obj = bpy.context.object if phobostype: obj.phobostype = phobostype nUtils.safelyName(obj, pname, phobostype) if pmaterial: materials.assignMaterial(obj, pmaterial) return obj
def createGeometry(viscol, geomsrc): """Creates geometrical Blender object for visual or collision objects. :param viscol: The visual/collision dictionary element you want to create the geometry for. :type viscol: dict :param geomsrc: The new viscols phobostype. :type geomsrc: str """ if 'geometry' not in viscol or viscol['geometry'] is {}: return None newgeom = None bpy.ops.object.select_all(action='DESELECT') geom = viscol['geometry'] geomtype = geom['type'] # create the Blender object if geomtype == 'mesh': # if hasattr(self, 'zipped') and self.zipped: # if not os.path.isdir(os.path.join(self.tmp_path, tmp_dir_name)): # os.mkdir(os.path.join(self.tmp_path, tmp_dir_name)) # archive = zipfile.ZipFile(self.filepath) # archive.extract(geom['filename'], path=os.path.join(self.tmp_path, tmp_dir_name)) # geom_path = os.path.join(os.path.abspath(os.path.join(self.tmp_path, tmp_dir_name)), geom['filename']) # else: if 'sourcefilepath' in geom: geom_path = os.path.normpath( os.path.join(os.path.dirname(geom['sourcefilepath']), geom['filename'])) log('sourcefilepath: ' + geom_path, 'DEBUG', 'createGeometry') else: geom_path = geom['filename'] # Remove 'urdf/package://{package_name}' to workaround the lack # of rospack here. This supposes that the urdf file is in the # urdf folder and that the meshes are in the meshes folder at # the same level as the urdf folder. if 'package://' in geom_path: geom_path = re.sub(r'(.*)urdf/package://([^/]+)/(.*)', '\\1\\3', geom_path) bpy.context.scene.layers = bUtils.defLayers(defs.layerTypes[geomsrc]) meshname = "".join(os.path.basename(geom["filename"]).split(".")[:-1]) if not os.path.isfile(geom_path): log( geom_path + " is no file. Object " + viscol['name'] + " will have empty mesh!", "ERROR", "createGeometry") bpy.data.meshes.new(meshname) if meshname in bpy.data.meshes: log( 'Assigning copy of existing mesh ' + meshname + ' to ' + viscol['name'], 'INFO', 'createGeometry') bpy.ops.object.add(type='MESH') newgeom = bpy.context.object newgeom.data = bpy.data.meshes[meshname] else: log('Importing mesh for link element ' + viscol['name'], 'INFO', 'createGeometry') filetype = geom['filename'].split('.')[-1].lower() newgeom = meshes.importMesh(geom_path, filetype) newgeom.data.name = meshname if not newgeom: log('Failed to import mesh file ' + geom['filename'], 'ERROR', 'createGeometry') return # scale imported object if 'scale' in geom: sUtils.selectObjects((newgeom, ), clear=True) newgeom.scale = geom['scale'] else: if geomtype == 'box': dimensions = geom['size'] elif geomtype == 'cylinder': dimensions = (geom['radius'], geom['length']) elif geomtype == 'sphere': dimensions = geom['radius'] else: log( "Could not determine geometry type of " + geomsrc + viscol['name'] + '. Placing empty coordinate system.', "ERROR") bpy.ops.object.empty_add(type='PLAIN_AXES', radius=0.2) bpy.context.active_object.name = viscol['name'] return None log('Creating primitve for obj ' + viscol['name'], 'INFO', 'createGeometry') newgeom = bUtils.createPrimitive(viscol['name'], geomtype, dimensions, player=geomsrc) newgeom.select = True bpy.ops.object.transform_apply(scale=True) # from here it's the same for both meshes and primitives newgeom.phobostype = geomsrc newgeom['geometry/type'] = geomtype if geomsrc == 'visual': try: if 'name' in viscol['material']: assignMaterial(newgeom, viscol['material']['name']) else: assignMaterial(newgeom, viscol['material']) except KeyError: log('No material for obj', viscol['name'], 'DEBUG', 'createGeometry') #FIXME: place empty coordinate system and return...what? Error handling of file import! for prop in viscol: if prop.startswith('$'): for tag in viscol[prop]: newgeom[prop[1:] + '/' + tag] = viscol[prop][tag] newgeom.name = viscol['name'] newgeom[geomsrc + "/name"] = viscol['name'] return newgeom