def deriveEntity(primitive, outpath): """This function handles a primitive entity in a scene to export it # TODO is this even a heightmap? Args: smurf(bpy.types.Object): The heightmap root object. outpath(str): The path to export to. Not used for primitives savetosubfolder(bool): If True data will be exported into subfolders. Not used for primitives primitive: Returns: dict - An entry for the scenes entitiesList """ entity = models.initObjectProperties(primitive, 'entity', ['geometry']) pose = deriveObjectPose(primitive) entity['geometry'] = deriveGeometry(primitive) entity['position'] = {'x': pose['translation'][0], 'y': pose['translation'][1], 'z': pose['translation'][2]} entity['rotation'] = {'w': pose['rotation_quaternion'][0], 'x': pose['rotation_quaternion'][1], 'y': pose['rotation_quaternion'][2], 'z': pose['rotation_quaternion'][3]} if 'radius' in entity['geometry']: entity['radius'] = entity['geometry']['radius'] #entity['extend'] = {'x': entity['geometry']['size'][0], # 'y': entity['geometry']['size'][1], # 'z': entity['geometry']['size'][2]} entity['extend'] = {'x': primitive.dimensions[0], 'y': primitive.dimensions[1], 'z': primitive.dimensions[2]} return entity
def deriveInertial(obj, logging=True, **kwargs): """Returns a dictionary describing the inertial information represented by the provided object. Contains these keys: *mass*: float *inertia*: list *pose*: inertiapose containing: *translation*: center of mass of the objects *rotation*: [0., 0., 0.] Args: obj(bpy.types.Object): object of phobostype 'inertial' logging(bool, optional): whether to log information or not (Default value = True) **kwargs: Returns: """ if obj.phobostype != 'inertial': if logging: log("Object '{0}' is not of phobostype 'inertial'.".format(obj.name), 'ERROR') return None props = initObjectProperties(obj, phobostype='inertial') props['pose'] = deriveObjectPose(obj, logging=logging, **kwargs) return props
def deriveLight(obj): """This function derives a light from a given blender object :param obj: The blender object to derive the light from. :type obj: bpy_types.Object :return: tuple """ light = initObjectProperties(obj, phobostype='light') light_data = obj.data if light_data.use_diffuse: light['color_diffuse'] = list(light_data.color) if light_data.use_specular: light['color_specular'] = copy.copy(light['color_diffuse']) light['type'] = light_data.type.lower() if light['type'] == 'SPOT': light['size'] = light_data.size pose = deriveObjectPose(obj) light['position'] = pose['translation'] light['rotation'] = pose['rotation_euler'] try: light['attenuation_linear'] = float(light_data.linear_attenuation) except AttributeError: # TODO handle this somehow pass try: light['attenuation_quadratic'] = float( light_data.quadratic_attenuation) except AttributeError: pass if light_data.energy: light['attenuation_constant'] = float(light_data.energy) light['parent'] = nUtils.getObjectName(sUtils.getEffectiveParent(obj)) return light
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 + ioUtils.getOutputMeshtype() 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") return None return visual
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
def derive_link(linkobj, inertialobjs=None): """Derives a link from a blender object and creates its initial phobos data structure. If inertialobjs are provided, the inertia will be calculated from the specified list instead of the getInertiaChildren. The dictionary contains (besides any generic object properties) this information: *parent*: name of parent object or None *children*: list of names of the links child links *object*: bpy.types.Object which represents the link *pose*: deriveObjectPose of the linkobj *collision*: empty dictionary *visual*: empty dictionary *inertial*: derive_inertia of all child inertials of the link *approxcollision*: empty dictionary :param linkobj: blender object to derive the link from. :type linkobj: bpy.types.Object :param inertialobjs: override the link inertial objects :type inertialobjs: list of bpy.types.Object :return: representation of the link :rtype: dict .. seealso deriveObjectPose .. seealso deriveInertiaChildren .. seealso derive_inertia """ assert linkobj.phobostype == 'link', ("Wrong phobostype: " + linkobj.phobostype + " instead of link.") log("Deriving link from object " + linkobj.name + ".", 'DEBUG') props = initObjectProperties(linkobj, phobostype='link', ignoretypes=linkobjignoretypes - {'link'}) parent = sUtils.getEffectiveParent(linkobj) props['parent'] = nUtils.getObjectName(parent) if parent else None props['children'] = [ child.name for child in linkobj.children if child.phobostype == 'link' ] props['object'] = linkobj props['pose'] = deriveObjectPose(linkobj) props['collision'] = {} props['visual'] = {} props['inertial'] = {} props['approxcollision'] = [] if not inertialobjs: inertialobjs = inertiamodel.getInertiaChildren(linkobj) log(" Deriving inertial...", 'DEBUG') # add inertial information to link if inertialobjs: props['inertial'] = derive_inertia(inertialobjs) else: log( "No valid inertial data for link " + props['name'] + ". " + str(len(inertialobjs)) + " inertial objects selected.", 'WARNING') return props
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) for group in obj.rigid_body.collision_groups[16:]: if group: log(( 'Object {0} is on a collision layer higher than ' + '16. These layers are ignored when exporting.').format( obj.name), "WARNING") break except AttributeError: pass except KeyError: log("Missing data in collision object " + obj.name, "ERROR") return None return collision
def deriveCollision(obj): """Returns the collision information from the specified object. Args: obj(bpy.types.Object): object to derive the collision information from Returns: : dict -- phobos representation of the collision object """ 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 if 'collision_groups' in dir(obj.rigid_body): collision['bitmask'] = int( ''.join(['1' if group else '0' for group in obj.rigid_body.collision_groups[:16]])[ ::-1 ], 2, ) for group in obj.rigid_body.collision_groups[16:]: if group: log( ( "Object {0} is on a collision layer higher than 16. These layers are " + "ignored when exporting." ).format(obj.name), 'WARNING', ) break return collision
def get_link_information(linkobj): """Returns the full link information including joint and motor data from a blender object. The link information is derived according to :func:`derive_link`. Args: linkobj(bpy.types.Object): blender object to derive the link from Returns: dict: link representation of the object """ props = initObjectProperties(linkobj, phobostype='link', ignoretypes=['joint', 'motor', 'entity']) parent = sUtils.getEffectiveParent(linkobj) props['parent'] = parent.name if parent else None props['pose'] = deriveObjectPose(linkobj) props['joint'] = deriveJoint(linkobj, logging=False, adjust=False) del props['joint']['parent'] # collect collision objs for link collisionobjs = sUtils.getImmediateChildren(linkobj, phobostypes=('collision'), include_hidden=True) collisiondict = {} for colobj in collisionobjs: collisiondict[colobj.name] = colobj props['collision'] = collisiondict # collect visual objs for link visualobjects = sUtils.getImmediateChildren(linkobj, phobostypes=('visual'), include_hidden=True) visualdict = {} for visualobj in visualobjects: visualdict[visualobj.name] = visualobj props["visual"] = visualdict # collect inertial objects inertialdict = { nUtils.getObjectName(obj): obj for obj in linkobj.children if obj.phobostype == 'inertial' } props["inertial"] = inertialdict # collect sensor objects sensorobjects = sUtils.getImmediateChildren(linkobj, phobostypes=('sensor'), include_hidden=True) sensordict = {} for sensorobj in sensorobjects: sensordict[sensorobj.name] = sensorobj if sensordict: props["sensor"] = sensordict props['approxcollision'] = [] return props
def get_link_information(linkobj): """Returns the full link information including joint and motor data from a blender object. :param linkobj: blender object to derive the link from :type linkobj: bpy.types.Object :return: representation of the link including motor and joint data :rtype: dict .. seealso:: derive_link """ assert linkobj.phobostype == 'link', ("Wrong phobostype: " + linkobj.phobostype + " instead of link.") props = initObjectProperties(linkobj, phobostype='link', ignoretypes=['joint', 'motor', 'entity']) parent = sUtils.getEffectiveParent(linkobj) props['parent'] = parent.name if parent else None props['pose'] = deriveObjectPose(linkobj) props['joint'] = deriveJoint(linkobj, adjust=False) del props['joint']['parent'] # derive Motor if any(item.startswith('motor') for item in props): props['motor'] = deriveMotor(linkobj, props['joint']) # collect collision objs for link collisionobjs = sUtils.getImmediateChildren(linkobj, phobostypes=('collision'), include_hidden=True) collisiondict = {} for colobj in collisionobjs: collisiondict[colobj.name] = colobj props['collision'] = collisiondict # collect visual objs for link visualobjects = sUtils.getImmediateChildren(linkobj, phobostypes=('visual'), include_hidden=True) visualdict = {} for visualobj in visualobjects: visualdict[visualobj.name] = visualobj props["visual"] = visualdict # collect inertial objects inertialobjects = inertiamodel.getInertiaChildren(linkobj) inertialdict = {} for inertialobj in inertialobjects: inertialdict[inertialobj.name] = inertialobj props["inertial"] = inertialdict props['approxcollision'] = [] return props
def deriveCapsule(obj): """This function derives a capsule from a given blender object Args: obj(bpy_types.Object): The blender object to derive the capsule from. Returns: tuple """ viscol_dict = {} capsule_pose = poses.deriveObjectPose(obj) rotation = capsule_pose['rotation_euler'] capsule_radius = obj['geometry']['radius'] for part in ['sphere1', 'cylinder', 'sphere2']: viscol = initObjectProperties(obj, phobostype='collision', ignoretypes='geometry') viscol['name'] = nUtils.getObjectName(obj).split(':')[-1] + '_' + part geometry = {} pose = {} geometry['radius'] = capsule_radius if part == 'cylinder': geometry['length'] = obj['geometry']['length'] geometry['type'] = 'cylinder' pose = capsule_pose else: geometry['type'] = 'sphere' if part == 'sphere1': location = obj['sph1_location'] else: location = obj['sph2_location'] pose['translation'] = location pose['rotation_euler'] = rotation loc_mu = mathutils.Matrix.Translation(location) rot_mu = mathutils.Euler(rotation).to_quaternion() pose['rotation_quaternion'] = list(rot_mu) matrix = loc_mu * rot_mu.to_matrix().to_4x4() # TODO delete me? # print(list(matrix)) pose['matrix'] = [list(vector) for vector in list(matrix)] viscol['geometry'] = geometry viscol['pose'] = pose try: viscol['bitmask'] = int( ''.join([ '1' if group else '0' for group in obj.rigid_body.collision_groups ]), 2) except AttributeError: pass viscol_dict[part] = viscol return viscol_dict, obj.parent
def fuse_inertia_data(inertials): """Computes combined mass, center of mass and inertia given a list of inertial objects. If no inertials are found (None, None, None) is returned. If successful, the tuple contains this information: *mass*: float *com*: mathutils.Vector(3) *inertia*: mathutils.Matrix(3) :param inertials: the alist of objects relevant for the inertia of a link :type inertials: list :return: tuple of mass, COM and inertia or None(3) if no inertials are found :rtype: tuple(3) """ assert isinstance(inertials, (tuple, list)), "Inertials is not iterable." assert inertials, "No inertial objects to fuse." # collect objects which contain inertia objects = [] for inertia_object in inertials: objdict = None try: pose = deriveObjectPose(inertia_object) objdict = { 'name': inertia_object.name, 'mass': inertia_object['mass'], # FIXME: this is not nice, as we invert what is one when deriving the pose 'com': mathutils.Vector(pose['translation']), 'rot': pose['rawmatrix'].to_3x3(), 'inertia': list(inertia_object['inertia']) } except KeyError as e: log( 'Inertial object ' + inertia_object.name + ' is missing data: ' + str(e), 'WARNING') continue objects.append(objdict) # fuse inertias of objects if objects: log(" Fusing inertials: " + str([i.name for i in inertials]), 'DEBUG') mass, com, inertia = compound_inertia_analysis_3x3(objects) log(" Fused mass: " + str(mass), 'DEBUG') return mass, com, inertia log("No inertial found to fuse.", 'DEBUG') return (None, None, None)
def deriveLink(linkobj, objectlist=[]): """Derives a dictionary for the link represented by the provided obj. If objectlist is provided, only objects contained in the list are taken into account for creating the resulting dictionary. The dictionary contains (besides any generic object properties) this information: *parent*: name of parent object or None *children*: list of names of the links child links *object*: bpy.types.Object which represents the link *pose*: deriveObjectPose of the linkobj *collision*: empty dictionary *visual*: empty dictionary *inertial*: derive_inertia of all child inertials of the link *approxcollision*: empty dictionary Args: linkobj(bpy.types.Object): blender object to derive the link from objectlist: list of bpy.types.Object .. seealso deriveObjectPose .. seealso deriveInertial """ if not linkobj.phobostype == 'link': log( "Could not parse link from {0}. No valid link object.".format( linkobj.name), 'ERROR') return None if not objectlist: objectlist = list(bpy.data.objects) log("Deriving link from object " + linkobj.name + ".", 'DEBUG') props = initObjectProperties(linkobj, phobostype='link', ignoretypes=linkobjignoretypes - {'link'}) parent = sUtils.getEffectiveParent(linkobj, objectlist) props['parent'] = nUtils.getObjectName(parent) if parent else None props['parentobj'] = parent props['children'] = [ child.name for child in linkobj.children if child.phobostype == 'link' ] props['object'] = linkobj props['pose'] = deriveObjectPose(linkobj) props['collision'] = {} props['visual'] = {} props['inertial'] = {} props['approxcollision'] = [] 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") return None return props
def deriveVisual(obj, logging=True, **kwargs): """This function derives the visual information from an object. Contains these keys: *name*: name of the visual *geometry*: derived according to `deriveGeometry` *pose*: derived according to `deriveObjectPose` *lod*: (opt.) level of detail levels Args: obj(bpy.types.Object): object to derive the visual representation from logging: (Default value = True) **kwargs: Returns: : dict -- model representation of the visual object """ visual = initObjectProperties(obj, phobostype='visual', ignoretypes='geometry') visual['geometry'] = deriveGeometry(obj, logging=logging) visual['pose'] = deriveObjectPose(obj, logging=logging) # check for material of the visual material = deriveMaterial(obj.active_material, logging=logging) if material: visual['material'] = material['name'] 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 + ioUtils.getOutputMeshtype() lodlist.append({ 'start': obj.lod_levels[i].distance, 'end': maxdlist[i], 'filename': os.path.join('meshes', filename), }) visual['lod'] = lodlist return visual
def deriveJoint(obj, logging=False, adjust=False, errors=None): """Derives a joint from a blender object and creates its initial phobos data structure. Args: obj(bpy.types.Object): object to derive the joint from adjust(bool, optional): TODO (Default value = False) logging: (Default value = False) errors: (Default value = None) Returns: : dict """ joint_type, crot = jointmodel.deriveJointType(obj, adjust=adjust, logging=logging) props = initObjectProperties(obj, phobostype='joint', ignoretypes=linkobjignoretypes - {'joint'}) parent = sUtils.getEffectiveParent(obj) props['parent'] = nUtils.getObjectName(parent) props['child'] = nUtils.getObjectName(obj) axis, minmax = jointmodel.getJointConstraints(obj) if axis: props['axis'] = list(axis) limits = {} if minmax is not None: # prismatic or revolute joint, TODO: planar etc. if len(minmax) == 2: limits['lower'] = minmax[0] limits['upper'] = minmax[1] if 'maxvelocity' in props: limits['velocity'] = props['maxvelocity'] del props['maxvelocity'] if 'maxeffort' in props: limits['effort'] = props['maxeffort'] del props['maxeffort'] if limits != {}: props['limits'] = limits props['pose'] = deriveObjectPose(obj) # TODO: what about these? # - calibration # - dynamics # - mimic # - safety_controller return props
def deriveApproxsphere(obj): """This function derives an SRDF approximation sphere from a given blender object :param obj: The blender object to derive the approxsphere from. :type obj: bpy_types.Object :return: tuple """ try: sphere = initObjectProperties(obj) sphere['radius'] = obj.dimensions[0] / 2 pose = deriveObjectPose(obj) sphere['center'] = pose['translation'] except KeyError: log("Missing data in collision approximation object " + obj.name, "ERROR") return None return sphere
def fuseInertiaData(inertials): """Returns mass, center of mass and inertia of a link as a whole, taking a list of inertials. *mass*: double *com*: mathutils:Vector(3) *inertia*: mathutils:Matrix(3) :param inertials: The alist of objects relevant for the inertia of a link. :type inertials: list :return: tuple(3) -- see description for content. """ objects = [] for o in inertials: objdict = None try: pose = deriveObjectPose(o) # FIXME the following is really a short cut that points to a bigger problem inertia = o['inertia'] if 'inertia' in o else o['inertial/inertia'] mass = o['mass'] if 'mass' in o else o['inertial/mass'] objdict = { 'name': o.name, 'mass': mass, 'com': mathutils.Vector( pose['translation'] ), # FIXME: this is not nice, as we invert what is one when deriving the pose 'rot': pose['rawmatrix'].to_3x3(), 'inertia': inertia } except KeyError as e: log('Inertial object ' + o.name + ' is missing data: ' + str(e), "WARNING", "fuseInertiaData") if objdict: objects.append(objdict) if len(objects) > 0: log("Fusing inertials: " + str([i.name for i in inertials]), "DEBUG", "fuseInertiaData") mass, com, inertia = compound_inertia_analysis_3x3(objects) log("Fused mass: " + str(mass), "DEBUG", "fuseInertiaData") return mass, com, inertia else: log("No inertial found to fuse.", "DEBUG", "fuseInertiaData") return None, None, None
def deriveLink(obj): """This function derives a link from a blender object and creates its initial phobos data structure. :param obj: The blender object to derive the link from. :type obj: bpy_types.Object :return: dict """ props = initObjectProperties(obj, phobostype='link', ignoretypes=['joint', 'motor', 'entity']) parent = sUtils.getEffectiveParent(obj) props['parent'] = parent.name if parent else None props["pose"] = deriveObjectPose(obj) props["collision"] = {} props["visual"] = {} props["inertial"] = {} props['approxcollision'] = [] return props
def deriveFullLinkInformation(obj): """This function derives the full link information (including joint and motor data) from a blender object and creates its initial phobos data structure. :param obj: The blender object to derive the link from. :type obj: bpy_types.Object :return: dict """ props = initObjectProperties(obj, phobostype='link', ignoretypes=['joint', 'motor', 'entity']) parent = sUtils.getEffectiveParent(obj) props['parent'] = parent.name if parent else None props["pose"] = deriveObjectPose(obj) props["joint"] = deriveJoint(obj, adjust=False) del props["joint"]["parent"] if any(item.startswith('motor') for item in props.keys()): props["motor"] = deriveMotor(obj, props['joint']) collisionObjects = sUtils.getImmediateChildren(obj, phobostypes=('collision'), include_hidden=True) collisionDict = {} for colobj in collisionObjects: collisionDict[colobj.name] = colobj props["collision"] = collisionDict visualObjects = sUtils.getImmediateChildren(obj, phobostypes=('visual'), include_hidden=True) visualDict = {} for visualobj in visualObjects: visualDict[visualobj.name] = visualobj props["visual"] = visualDict inertialObjects = sUtils.getImmediateChildren(obj, phobostypes=('inertial'), include_hidden=True) inertialDict = {} for inertialobj in inertialObjects: inertialDict[inertialobj.name] = inertialobj props["inertial"] = inertialDict props['approxcollision'] = [] return props
def deriveInertial(obj): """Returns a dictionary describing the inertial information represented by the provided object. Contains these keys: *mass*: float *inertia*: list *pose*: inertiapose containing: *translation*: center of mass of the objects *rotation*: [0., 0., 0.] Args: obj(bpy.types.Object): object of phobostype 'inertial' """ if obj.phobostype != 'inertial': log("Object '{0}' is not of phobostype 'inertial'.".format(obj.name), 'ERROR') return None props = initObjectProperties(obj, phobostype='inertial') props['pose'] = deriveObjectPose(obj) return props
def deriveEntity(primitive, outpath): """This function handles a primitive entity in a scene to export it # TODO is this even a heightmap? Args: smurf(bpy.types.Object): The heightmap root object. outpath(str): The path to export to. Not used for primitives savetosubfolder(bool): If True data will be exported into subfolders. Not used for primitives primitive: Returns: : dict - An entry for the scenes entitiesList """ entity = models.initObjectProperties(primitive, 'entity', ['geometry']) pose = deriveObjectPose(primitive) entity['geometry'] = deriveGeometry(primitive) entity['position'] = { 'x': pose['translation'][0], 'y': pose['translation'][1], 'z': pose['translation'][2], } entity['rotation'] = { 'w': pose['rotation_quaternion'][0], 'x': pose['rotation_quaternion'][1], 'y': pose['rotation_quaternion'][2], 'z': pose['rotation_quaternion'][3], } if 'radius' in entity['geometry']: entity['radius'] = entity['geometry']['radius'] # entity['extend'] = {'x': entity['geometry']['size'][0], # 'y': entity['geometry']['size'][1], # 'z': entity['geometry']['size'][2]} entity['extend'] = { 'x': primitive.dimensions[0], 'y': primitive.dimensions[1], 'z': primitive.dimensions[2], } return entity
def deriveSensor(obj, names=False, objectlist=[], logging=False): """This function derives a sensor from a given blender object Args: obj(bpy_types.Object): The blender object to derive the sensor from. names(bool, optional): return the l object name instead of an object link. (Default value = False) objectlist(list(bpy.types.Object, optional): objectlist to which possible parents are restricted (Default value = []) logging(bool, optional): whether to write log messages or not (Default value = False) Returns: : dict -- phobos representation of the sensor """ from phobos.model.models import initObjectProperties from phobos.model.poses import deriveObjectPose if logging: log( "Deriving sensor from object " + nUtils.getObjectName(obj, phobostype='sensor') + ".", 'DEBUG', ) try: props = initObjectProperties(obj, phobostype='sensor', ignoretypes=('pose')) if names: props['link'] = nUtils.getObjectName(sUtils.getEffectiveParent( obj, objectlist=objectlist), phobostype='link') else: props['link'] = sUtils.getEffectiveParent(obj, objectlist=objectlist) except KeyError: if logging: log("Missing data in sensor " + obj.name, "ERROR") return None props['pose'] = deriveObjectPose(obj) return props
def deriveEntity(entity, outpath, savetosubfolder): """This function handles a primitive entity in a scene to export it :param smurf: The heightmap root object. :type smurf: bpy.types.Object :param outpath: The path to export to. Not used for primitives :type outpath: str :param savetosubfolder: If True data will be exported into subfolders. Not used for primitives :type savetosubfolder: bool :return: dict - An entry for the scenes entitiesList """ primitive = entity log( "Exporting " + nUtils.getObjectName(primitive, 'entity') + " as entity of type 'primitive", "INFO") entity = models.initObjectProperties(primitive, 'entity', ['geometry']) pose = deriveObjectPose(primitive) entity['geometry'] = deriveGeometry(primitive) entity['position'] = { 'x': pose['translation'][0], 'y': pose['translation'][1], 'z': pose['translation'][2] } entity['rotation'] = { 'w': pose['rotation_quaternion'][0], 'x': pose['rotation_quaternion'][1], 'y': pose['rotation_quaternion'][2], 'z': pose['rotation_quaternion'][3] } entity['extend'] = { 'x': entity['geometry']['size'][0], 'y': entity['geometry']['size'][1], 'z': entity['geometry']['size'][2] } return entity
def deriveEntity(primitive, outpath, savetosubfolder=True): """This function handles a primitive entity in a scene to export it :param smurf: The heightmap root object. :type smurf: bpy.types.Object :param outpath: The path to export to. Not used for primitives :type outpath: str :param savetosubfolder: If True data will be exported into subfolders. Not used for primitives :type savetosubfolder: bool :return: dict - An entry for the scenes entitiesList """ entity = models.initObjectProperties(primitive, 'entity', ['geometry']) pose = deriveObjectPose(primitive) entity['geometry'] = deriveGeometry(primitive) entity['position'] = { 'x': pose['translation'][0], 'y': pose['translation'][1], 'z': pose['translation'][2] } entity['rotation'] = { 'w': pose['rotation_quaternion'][0], 'x': pose['rotation_quaternion'][1], 'y': pose['rotation_quaternion'][2], 'z': pose['rotation_quaternion'][3] } if 'radius' in entity['geometry']: entity['radius'] = entity['geometry']['radius'] #entity['extend'] = {'x': entity['geometry']['size'][0], # 'y': entity['geometry']['size'][1], # 'z': entity['geometry']['size'][2]} entity['extend'] = { 'x': primitive.dimensions[0], 'y': primitive.dimensions[1], 'z': primitive.dimensions[2] } return entity
def deriveSensor(obj, names=False, objectlist=[], logging=False): """This function derives a sensor from a given blender object Args: obj(bpy_types.Object): The blender object to derive the sensor from. names(bool, optional): return the l object name instead of an object link. (Default value = False) objectlist(list(bpy.types.Object, optional): objectlist to which possible parents are restricted (Default value = []) logging(bool, optional): whether to write log messages or not (Default value = False) Returns: : dict -- phobos representation of the sensor """ from phobos.model.models import initObjectProperties from phobos.model.poses import deriveObjectPose if logging: log( "Deriving sensor from object " + nUtils.getObjectName(obj, phobostype='sensor') + ".", 'DEBUG', ) try: props = initObjectProperties(obj, phobostype='sensor', ignoretypes=('pose')) if names: props['link'] = nUtils.getObjectName( sUtils.getEffectiveParent(obj, objectlist=objectlist), phobostype='link' ) else: props['link'] = sUtils.getEffectiveParent(obj, objectlist=objectlist) except KeyError: if logging: log("Missing data in sensor " + obj.name, "ERROR") return None props['pose'] = deriveObjectPose(obj) return props
def deriveLink(linkobj, objectlist=[], logging=False, errors=None): """Derives a dictionary for the link represented by the provided obj. If objectlist is provided, only objects contained in the list are taken into account for creating the resulting dictionary. The dictionary contains (besides any generic object properties) this information: *parent*: name of parent object or None *children*: list of names of the links child links *object*: bpy.types.Object which represents the link *pose*: deriveObjectPose of the linkobj *collision*: empty dictionary *visual*: empty dictionary *inertial*: derive_inertia of all child inertials of the link *approxcollision*: empty dictionary Args: linkobj(bpy.types.Object): blender object to derive the link from objectlist: list of bpy.types.Object .. seealso deriveObjectPose .. seealso deriveInertial (Default value = []) logging: (Default value = False) errors: (Default value = None) Returns: """ # use scene objects if no objects are defined if not objectlist: objectlist = list(bpy.context.scene.objects) if logging: log("Deriving link from object " + linkobj.name + ".", 'DEBUG') props = initObjectProperties( linkobj, phobostype='link', ignoretypes=linkobjignoretypes - {'link'} ) parent = sUtils.getEffectiveParent(linkobj, objectlist) props['parent'] = nUtils.getObjectName(parent) if parent else None props['parentobj'] = parent props['children'] = [child.name for child in linkobj.children if child.phobostype == 'link'] props['object'] = linkobj props['pose'] = deriveObjectPose(linkobj) props['collision'] = {} props['visual'] = {} props['inertial'] = {} props['approxcollision'] = [] # gather all visual/collision objects for the link from the objectlist for obj in [ item for item in objectlist if item.phobostype in ['visual', 'collision', 'approxsphere'] ]: effectiveparent = sUtils.getEffectiveParent(obj) if effectiveparent == linkobj: if logging: log( " Adding " + obj.phobostype + " '" + nUtils.getObjectName(obj) + "' to link.", 'DEBUG', ) if obj.phobostype == 'approxsphere': props['approxcollision'].append(deriveDictEntry(obj)) else: props[obj.phobostype][nUtils.getObjectName(obj)] = deriveDictEntry(obj) # gather the inertials for fusing the link inertia inertials = inertiamodel.gatherInertialChilds(linkobj, objectlist) mass = None com = None inertia = None if len(inertials) > 0: # get inertia data mass, com, inertia = inertiamodel.fuse_inertia_data(inertials) if not any([mass, com, inertia]): if logging: log("No inertia information for link object " + linkobj.name + ".", 'DEBUG') else: # add inertia to link inertia = inertiamodel.inertiaMatrixToList(inertia) props['inertial'] = { 'mass': mass, 'inertia': list(inertia), 'pose': {'translation': list(com), 'rotation_euler': [0, 0, 0]}, } bitmask = 0 for collname in props['collision']: try: # bitwise OR to add all collision layers bitmask = bitmask | props['collision'][collname]['bitmask'] except KeyError: pass props['collision_bitmask'] = bitmask return props