def set_service_callback(self, cb): """ Sets the callback function that is to be invoked when the current request completes. This is automatically set by the @async_service decorator and should not usually be directly called. """ if self.on_completion: # A callback is already registered -> a service is running old_cb = self.on_completion if not hasattr(old_cb.service, "_morse_service_interruptible"): # No policy (interruptible/noninterruptible) set for # the service currently running. We throw an exception # to be caught by the middleware. Up to it to define # the default policy. raise MorseServiceAlreadyRunningError(old_cb.service, "A service (" + \ old_cb.service.__name__ + ") is already running. I do not know what to do.") interruptible = old_cb.service._morse_service_interruptible if interruptible: self.interrupt() else: raise MorseRPCInvokationError("A non-interruptible service (" + old_cb.service.__name__ + ") is already running") self.on_completion = cb
def set_rotations(self, rotations): """ Sets in one call the rotations of the revolute joints in this armature. Has the same effect as applying `set_rotation` on each of the joints independantly. Rotations must be ordered from the root to the tip of the armature. Use the service ``get_joints()`` to retrieve the list of joints in the correct order. If more rotations are provided than the number of joints, the remaining ones are discarded. If less rotations are provided, the maximum are applied. .. important:: If a prismatic joint is encountered while applying the rotation, an exception is thrown, and **no** rotation is applied. :sees: `set_rotation` :param rotations: a set of absolute rotations, in radians """ armature = self.bge_object nb_rot = min(len(rotations), len(armature.channels)) channels = [c for c in armature.channels] for i in range(nb_rot): if self._is_prismatic(channels[i]): msg = "Joint %s is not a revolute joint! Can not apply the rotation set" % joint raise MorseRPCInvokationError(msg) for rot, channel in zip(rotations[:nb_rot], channels[:nb_rot]): self.set_rotation(channel.name, rot)
def set_translations(self, translations): """ Sets in one call the translations of the prismatic joints in this armature. Has the same effect as applying `set_translation` on each of the joints independantly. Translations must be ordered from the root to the tip of the armature. If more translations are provided than the number of joints, the remaining ones are discarded. If less translations are provided, the maximum are applied. .. important:: If a revolute joint is encountered while applying the translations, an exception is thrown, and **no** translation is applied. :sees: `set_translation` :param translations: a set of absolute translations, in meters """ armature = self.bge_object nb_trans = min(len(translations), len(armature.channels)) channels = [c for c in armature.channels] for i in range(nb_trans): if not self._is_prismatic(channels[i]): msg = "Joint %s is not a prismatic joint! Can not apply the translation set" % joint raise MorseRPCInvokationError(msg) for trans, channel in zip(translations[:nb_trans], channels[:nb_trans]): self.set_translation(channel.name, trans)
def get_victim_severity(self): if self._nearest_victim: return self._nearest_victim['Severity'] else: message = "No victim within range (%.2f m)" % self.blender_obj[ 'Heal_range'] raise MorseRPCInvokationError(message)
def distance_and_view(self, robot1, robot2): """ Return the distance between the two robots, and a boolean which described if one can view the other. """ r1 = _robot_exists(robot1) r2 = _robot_exists(robot2) if not r1: raise MorseRPCInvokationError(robot1 + " does not exist in the simulation ") if not r2: raise MorseRPCInvokationError(robot2 + " does not exist in the simulation ") dist = r1.position_3d.distance(r2.position_3d) closest_obj = r1.bge_object.rayCastTo(r2.bge_object) return dist, closest_obj == r2.bge_object
def get_victim_severity(self): """ Returns the integer indicating the victim healing priority """ if self._nearest_victim: return self._nearest_victim['Severity'] else: message = "No victim within range (%.2f m)" % self._detect_distance raise MorseRPCInvokationError(message)
def get_victim_requirements(self): """ Returns the list describing the type of injuries sustained by the victim """ if self._nearest_victim: return self._nearest_victim['Requirements'] else: message = "No victim within range (%.2f m)" % self._detect_distance raise MorseRPCInvokationError(message)
def _get_revolute(self, joint): """ Checks a given revolute joint name exist in the armature, and returns it. """ channel, is_prismatic = self._get_joint(joint) if is_prismatic: msg = "Joint %s is not a revolute joint! Can not set the rotation" % joint raise MorseRPCInvokationError(msg) return channel
def _get_prismatic(self, joint): """ Checks a given prismatic joint name exist in the armature, and returns it. """ channel, is_prismatic = self._get_joint(joint) if not is_prismatic: msg = "Joint %s is not a prismatic joint! Can not set the translation" % joint raise MorseRPCInvokationError(msg) return channel
def get_stream_port(self, name): """ Get stream port for stream name. """ port = -1 try: port = self._component_nameservice[name] except KeyError: pass if port < 0: raise MorseRPCInvokationError("Stream unavailable for component %s" % name) return port
def set_property(self, prop_name, prop_val): """ Modify one property on a component :param prop_name: the name of the property to modify (as shown the documentation) :param prop_val: the new value of the property. Note that there is no checking about the type of the value so be careful :return: nothing """ props = self.fetch_properties() if prop_name in props: setattr(self, props[prop_name][3], prop_val) else: raise MorseRPCInvokationError( "Property %s does not exist for object %s" % (prop_name, self.name()))
def _get_joint(self, joint): """ Checks a given joint name exist in the armature, and returns it as a tuple (Blender channel, is_prismatic?) If the joint does not exist, throw an exception. """ armature = self.bge_object if joint not in [c.name for c in armature.channels]: msg = "Joint <%s> does not exist in armature %s" % (joint, armature.name) raise MorseRPCInvokationError(msg) channel = armature.channels[joint] if self._is_prismatic(channel): return channel, True else: return channel, False
def _normalize_IK_transformation(self, target_name, translation, euler_rotation=None, relative=True): armature = self.bge_object target = [ ik for ik in self._ik_targets.keys() if ik.name == target_name ] if not target: raise MorseRPCInvokationError( "IK target <%s> does not exist for armature %s" % (target_name, armature.name)) target = target[0] if relative: currentPos = target.worldPosition translation = [ translation[0] + currentPos[0], translation[1] + currentPos[1], translation[2] + currentPos[2] ] if euler_rotation: current_orientation = target.worldOrientation.to_quaternion( ).normalized() rotation = mathutils.Euler( euler_rotation).to_quaternion().normalized() if relative: # computes the final IK target orientation by rotating the # current orientation by `rotation` final_orientation = current_orientation.copy() final_orientation.rotate(rotation) else: final_orientation = rotation else: final_orientation = None return target, translation, final_orientation
def set_target(self, x, y, z): """ Sets a target position for the armature's tip. MORSE uses inverse kinematics to find the joint angles/positions in order to get the armature tip as close as possible to the target. .. important:: No obstacle avoidance takes place: while moving the armature may hit objects. .. warning:: Not implemented yet! Only as a placeholder! :param x: X coordinate of the IK target :param y: Y coordinate of the IK target :param z: Z coordinate of the IK target """ raise MorseRPCInvokationError("Not implemented yet!")