Beispiel #1
0
 def __init__(self, raytracer='raytracer2', world=None,
             min_num_aux=1, aux_per_deg=1):
     """ 
     sensor_type:   choose between ImageRangeSensor.RangeFinder, Optics
     """
     self.raytracer = TexturedRaytracer(raytracer=raytracer)
     self.directions = []
     self.spatial_sigma = []
     self.sigma = []
     self.num_photoreceptors = 0
     if world is not None:
         self.set_map(world)
     
     self.min_num_aux = min_num_aux
     self.aux_per_deg = aux_per_deg
     
     # these are filled in by get_raw_sensor()
     self.compiled = False
     self.aux_directions = None
     self.aux_indices = None
Beispiel #2
0
class ImageRangeSensor:
    """ This class implements both a rangefinder and a vision sensor
        (much of the code is the same). 
        
        Dont' use this class directly in the simulations -- use the two
        subclasses Optics and Rangefinder
    """
    
    def __init__(self, raytracer='raytracer2', world=None,
                min_num_aux=1, aux_per_deg=1):
        """ 
        sensor_type:   choose between ImageRangeSensor.RangeFinder, Optics
        """
        self.raytracer = TexturedRaytracer(raytracer=raytracer)
        self.directions = []
        self.spatial_sigma = []
        self.sigma = []
        self.num_photoreceptors = 0
        if world is not None:
            self.set_map(world)
        
        self.min_num_aux = min_num_aux
        self.aux_per_deg = aux_per_deg
        
        # these are filled in by get_raw_sensor()
        self.compiled = False
        self.aux_directions = None
        self.aux_indices = None
    
    def num_sensels(self):
        return self.num_photoreceptors
    
    def render(self, object_state):
        self.make_sure_compiled()
        position = object_state.get_2d_position()
        orientation = object_state.get_2d_orientation()
        raw_data = self.raytracer.query_sensor(position, orientation)
        proc_data = self.process_raw_data(raw_data)
        return proc_data
  
    def add_photoreceptors(self, directions, spatial_sigma, sigma):
        n = len(directions)
        
        if not isinstance(spatial_sigma, list):
            spatial_sigma = [spatial_sigma] * n
        if not isinstance(sigma, list):
            sigma = [sigma] * n
        
        self.directions.extend(directions)
        self.spatial_sigma.extend(spatial_sigma)
        self.sigma.extend(sigma)
        
        # re-order everything according to direction
        def permutation_indices(data):
            return sorted(range(len(data)), key=data.__getitem__)
        
        self.indices = permutation_indices(self.directions)
        self.directions = [self.directions[i]    for i in self.indices]
        self.spatial_sigma = [self.spatial_sigma[i] for i in self.indices]
        self.sigma = [self.sigma[i]         for i in self.indices]
        
        self.num_photoreceptors = len(self.directions)
        self.num_readings = len(self.directions)
        
        # force reconfiguration of raw sensor
        self.compiled = False
        
    def make_sure_compiled(self):
        """ We finished composing the sensor """
        if not self.compiled:
            if len(self.directions) == 0:
                raise BVException('You did not specify any receptors for the sensor.')
            self.raytracer.set_sensor(self.get_raw_sensor())
            self.compiled = True
        
    def get_raw_sensor(self):
        # list of list of indices
        self.aux_indices = []
        self.aux_directions = []
        for i, direction in enumerate(self.directions):
            spatial_sigma = self.spatial_sigma[i] 
            
            num_aux = int(max(ceil(rad2deg(spatial_sigma / self.aux_per_deg)),
                              self.min_num_aux)) 
            # enforce odd to have a centered ray
            if num_aux % 2 == 0: 
                num_aux += 1
            if num_aux == 1:
                aux_dirs = [direction]
                # special case: linspace(a,b,1) == a
            else:
                aux_dirs = linspace(-spatial_sigma + direction,
                                     + spatial_sigma + direction, num_aux)
            num_so_far = len(self.aux_directions)
            self.aux_directions.extend(aux_dirs)
            self.aux_indices.append(range(num_so_far, num_so_far + num_aux))
        
        return {'class': 'sensor', 'directions': self.aux_directions }
        
    def process_raw_data(self, data):
        # example {"luminance": [1.0, -1.0, -1.0, -1.0, 1.0], "normal":
        # [1.5707960000000001, 3.1415929999999999, 0.0, 3.1415929999999999, 
        #4.7123889999999999], "region": [0, 0, 0, 0, 0], "surface": [0, 0, 0, 0, 0], 
        #"readings": [1.0, 1.406641, 1.0, 1.406641, 1.0], "valid": [1, 1, 1, 1, 1], 
        #"curvilinear_coordinate": [6.9992039999999998, 5.9892620000000001, 5.0, 
        #4.0107379999999999, 3.0007959999999998]}
        proc_data = data.copy()
        proc_data['original'] = proc_data['luminance']
#        proc_data = {} # if you want to be clean
        aux_valid = data['valid']
        
        assert(len(proc_data['luminance']) == len(self.aux_directions))
        assert(len(proc_data['valid']) == len(self.aux_directions))
        
        valid = []
        for attribute in ['luminance', 'readings']:
            values = []
            try:
                aux_values = array(data[attribute])
            except ValueError, e:
                print attribute, data[attribute]
                raise e
                
            for indices in self.aux_indices:
                valid_indices = [ k for k in indices if aux_valid[k] ]
                if len(valid_indices) == 0:
                    values.append(float('nan'))
                    valid.append(0)
                else:
                    average = aux_values[valid_indices].mean()
                    values.append(average)
                    valid.append(1)
                    
            proc_data[attribute] = values
        
        proc_data['valid'] = valid
        return proc_data