Source code for morse.actuators.gripper

import logging; logger = logging.getLogger("morse." + __name__)

######################################################
#
#    gripper.py        Blender 2.59
#
#    Gilberto Echeverria
#    13 / 10 / 2010
#
######################################################

import morse.core.actuator
from morse.core import blenderapi
from morse.core.services import service
from morse.helpers.components import add_data, add_property

[docs]class Gripper(morse.core.actuator.Actuator): """ Actuator capable of grabbing objects marked with the ``Graspable`` Game Property. Currently it only works using services: **grab** and **release**. When instructed to grab an object, it will check if it is within range, and if so, will parent the grabbed object to itself. .. note:: For objects to be detected and grabbed by the gripper, they must have the following settings in the **Physics Properties** panel: - **Actor** must be checked - **Collision Bounds** must be checked - **Physics Type** must be ``Rigid Body`` This will work even for Static objects .. warning:: This actuator does not simulate the physical interaction of the gripper fingers with the objects it grabs. Its purpose is to abstract the action of taking an object, for human-robot interaction experiments. """ _name = "Gripper" _short_desc = "Instruct the robot to move towards a given target" add_data('grab', False, "bool", "Currently not used") # These properties are not used directly in the logic, but are used # in the builder to create the radar properly. # These value cannot be changed dynamically in bge. add_property('_angle', 60.0, 'Angle', 'float', 'Aperture angle of the radar capable to detecting the \ graspable objects (in degree)') add_property('_distance', 0.5, 'Distance', 'float', 'Detection distance in meter. Graspable objects further \ way from the gripper than this distance cannot be \ held') def __init__(self, obj, parent=None): """ Constructor method. Receives the reference to the Blender object. """ logger.info('%s initialization' % obj.name) # Call the constructor of the parent class morse.core.actuator.Actuator.__init__(self, obj, parent) self._near_object = None self._grabbed_object = None # Variable to indicate whether the mesh should animate closing # or opening the gripper self._animation = '' # Get references to the Logic Bricks to play animations self._contr = self.bge_object.controllers[0] self._close_anim = self._contr.actuators['Close_anim'] self._open_anim = self._contr.actuators['Open_anim'] logger.info('Component initialized') logger.setLevel(logging.DEBUG)
[docs] def find_object(self): """ Store the object that is within reach of the gripper Uses a Blender Radar Sensor to detect objects with the 'Graspable' property in front of this component """ # Get reference to the Radar Blender sensor contr = blenderapi.controller() radar = contr.sensors['Radar'] self._near_object = None if radar.triggered and radar.positive: min_distance = 100 for test_obj in radar.hitObjectList: # Find the closest object and its distance new_distance = self.bge_object.getDistanceTo(test_obj) if new_distance < min_distance: self._near_object = test_obj min_distance = new_distance
[docs] @service def grab(self): """ Tries to grab an object close to the gripper. :returns: if successful (or if an object is already in hand), the name of the object, else None. """ # Check that no other object is being carried if not self._grabbed_object: # If the object is draggable if self._near_object is not None: logger.debug("Grabbing object: '%s'" % self._near_object) # Remove Physic simulation #self._near_object.suspendDynamics() # Parent the selected object to the gripper self._grabbed_object = self._near_object self._grabbed_object.setParent (self.bge_object) logger.debug("New parent: %s" % self._grabbed_object.parent) self._near_object = None # Execute the close grip animation: self._animation = 'close' return self._grabbed_object.name else: logger.debug("No 'Graspable' object within range of gripper") return None else: logger.debug("Already holding object %s" % self._grabbed_object ) return self._grabbed_object.name
[docs] @service def release(self): """ Free the grabbed object. Let it fall down after resetting its rotation. Does nothing if no object is held. :returns: True if an object has been released, else False (if no object was held). """ # Clear the previously selected object, if any if self._grabbed_object is not None: logger.debug("Releasing object: '%s'" % self._near_object) # Remove the parent self._grabbed_object.removeParent() # Place the object on the nearest surface #morse.helpers.place_object.do_place(previous_object) # Reset rotation of object #self._grabbed_object.worldOrientation = [0.0, 0.0, 0.0] # Restore Physics simulation #previous_object.restoreDynamics() #previous_object.setLinearVelocity([0, 0, 0]) #previous_object.setAngularVelocity([0, 0, 0]) # Clear the object from dragged status self._grabbed_object = None # Execute the open grip animation: self._animation = 'open' return True else: logger.debug("No object currently being held: nothing to release.") return False
[docs] def default_action(self): """ Check if an object is within reach of the hand """ self.find_object() # Play the animations when necessary if self._animation == 'close': self._contr.activate(self._close_anim) self._animation = '' logger.debug('Playing CLOSE animation') if self._animation == 'open': self._contr.activate(self._open_anim) self._animation = '' logger.debug('Playing OPEN animation')