Ejemplo n.º 1
0
  def ground(self,random=False):
    '''
    This function finds the nearest beam to the robot that is connected 
    to the xy-plane (ground). It returns that beam and its direction from the 
    robot. If random = True, the function picks a random beam from those connected
    to the xy-plane.
    '''
    # Get local boxes
    boxes = self.structure.get_boxes(self.location)

    # Initializations
    distances = {}
    vectors = {}

    # Cycle through boxes
    for box in boxes:
      # Cycle through beams in each box
      for name in box:

        # So e1 is in the form (x,y,z)
        e1, e2 = box[name].endpoints 
        # beam is lying on the ground (THIS IS NOT FUNCTIONAL)
        
        if helpers.compare(e1[2],0) and helpers.compare(e2[0],0):
          # pdb.set_trace()
          vectors[name] = helpers.vector_to_line(e1,e2,self.location)
          distances[name] = helpers.length(vectors[name])
        
        # Only one point is on the ground
        if helpers.compare(e1[2],0):
          vectors[name] = helpers.make_vector(self.location, e1)
          distances[name] = helpers.distance(e1, self.location)
        elif helpers.compare(e2[2],0):
          vectors[name] = helpers.make_vector(self.location, e2)
          distances[name] = helpers.distance(e2, self.location)

        # No points on the ground
        else:
          pass

    # get name of beam at the minimum distance if one exists
    if distances == {}:
      return None
    else:
      # Random key
      if random: name = choice(list(distances.keys()))
      # This returns the key (ie, name) of the minimum value in distances
      else: name = min(distances, key=distances.get)

      # So far away that we can't "see it"      
      if distances[name] > ROBOT['local_radius']:
        return None
      else:
        # All the same beans 
        beams = [box[name] for box in boxes if name in box]

        return {  'beam'  : beams[0],
                  'distance' : distances[name],
                  'direction' : vectors[name]}
Ejemplo n.º 2
0
    def ground(self):
        '''
    This function finds the nearest beam to the robot that is connected 
    to the xy-plane (ground). It returns that beam and its direction from the 
    robot.
    '''
        # Get local boxes
        boxes = self.structure.get_boxes(self.location)

        # Initializations
        distances = {}
        vectors = {}

        # Cycle through boxes
        for box in boxes:
            # Cycle through beams in each box
            for name in box:

                # So e1 is in the form (x,y,z)
                e1, e2 = box[name].endpoints
                # beam is lying on the ground (THIS IS NOT FUNCTIONAL)
                if helpers.compare(e1[2], 0) and helpers.compare(e2[0], 0):
                    # pdb.set_trace()
                    vectors[name] = helpers.vector_to_line(
                        e1, e2, self.location)
                    distances[name] = helpers.length(vectors[name])

                # Only one point is on the ground
                elif helpers.compare(e1[2], 0):
                    vectors[name] = helpers.make_vector(self.location, e1)
                    distances[name] = helpers.distance(e1, self.location)
                elif helpers.compare(e2[2], 0):
                    vectors[name] = helpers.make_vector(self.location, e2)
                    distances[name] = helpers.distances(e2, self.location)

                # No points on the ground
                else:
                    pass

        # get name of beam at the minimum distance if one exists
        if distances == {}:
            return None
        else:
            # This returns the key (ie, name) of the minimum value in distances
            name = min(distances, key=distances.get)

            # So far away that we can't "see it"
            if distances[name] > ROBOT['local_radius']:
                return None
            else:
                # All the same beans
                beams = [box[name] for box in boxes if name in box]

                return {
                    'beam': beams[0],
                    'distance': distances[name],
                    'direction': vectors[name]
                }
Ejemplo n.º 3
0
    def get_preferred_direction(self, beam):
        # Obtain the moment vector
        u1, u2, u3 = beam.global_default_axes()
        m11, m22, m33 = self.get_moment_magnitudes(beam.name)

        # Quick debugging - making sure the torsion doesn't get too high
        if not helpers.compare(m11, 0, 4):
            #pdb.set_trace()
            pass

        # Sum m22 and m33 (m11 is torsion, which doesn't play a role in the direction)
        moment_vector = helpers.sum_vectors(helpers.scale(m22, u2),
                                            helpers.scale(m33, u3))
        '''
    Cross axis-1 with the moment vector to obtain the positive clockwise direction
    This keeps the overall magnitude of moment_vector since u1 is a unit vector
      We are always attempting to repair further up the broken beam (closer to 
      the j-end). The cross will always give us the vector in the right direction
      if we do it this way.
    '''
        twist_direction = helpers.cross(moment_vector, u1)

        # Project the twist direction onto the xy-plane and normalize to have a
        # maximum of 45 degree approach (or, as specified in the variables.py)
        # depending on the ratio of moment magnitude to max_magnitude
        xy_change = (twist_direction[0], twist_direction[1], 0)

        # The rotation is parallel to the z-axis, so we don't add disturbance
        if helpers.compare(helpers.length(xy_change), 0):
            # Return the normal direction - which way is the beam leaning???
            return super(MomentAwareBuilder,
                         self).get_preferred_direction(beam)

        # We know the direction in which the beam is turning
        else:
            # Get direction of travel (this is a unit vector)
            travel = super(MomentAwareBuilder,
                           self).get_preferred_direction(beam)

            # Normalize twist to the maximum moment of force -- structure_check
            normal = helpers.normalize(xy_change,
                                       BConstants.beam['structure_check'])

            # The beam is vertical - check to see how large the normalized moment is
            if travel is None:
                # The change is relatively small, so ignore it
                if helpers.length(normal) <= helpers.ratio(
                        BConstants.beam['verticality_angle']):
                    return travel
                else:
                    return helpers.make_unit(normal)

            else:
                scalar = 1 / helpers.ratio(BConstants.beam['moment_angle_max'])
                scaled_travel = helpers.scale(scalar, travel)
                return helpesr.make_unit(
                    helpers.sum_vectors(normal, scaled_travel))
Ejemplo n.º 4
0
    def decide(self):
        '''
    Overwritting to allow for repair work to take place
    '''
        if self.search_mode and self.repair_mode:
            self.pre_decision()

            # We have moved off the structure entirely, so wander
            if self.beam is None:
                self.ground_support()

            # We've moved off the beam, so run the search support routine
            elif (self.memory['broken_beam_name'] != self.beam.name
                  and self.search_mode
                  and self.memory['broken_beam_name'] != ''):

                # Remember the beam we moved onto right after the broken one
                if self.memory['previous_beam'] is None:
                    self.memory['previous_beam'] = self.beam.name

                # We have found a support beam, so return to construct mode (the support beam is vertical)
                if (self.memory['previous_beam'] != self.beam.name
                        and (self.memory['previous_direction'] is None
                             or self.memory['previous_direction'][1][2] > 0
                             or helpers.compare(
                                 self.memory['previous_direction'][1][2], 0))):
                    self.construction_mode()

                    # Decide again since we're out of repair mode
                    self.decide()

                else:
                    self.find_support()
                    # Move (don't check construction)
                    self.movable_decide()

            # Simply move
            else:
                self.movable_decide()

        # We found a support beam and are on it, planning on construction. If
        # we reach the endpoint of the beam (the support beam), then construct.
        elif self.repair_mode:
            if (helpers.compare(
                    helpers.distance(self.location, self.beam.endpoints.j),
                    self.step / 2)):
                self.start_contruction = True
                self.memory['broken'] = []

        # Build Mode
        else:
            super(DumbRepairer, self).decide()
Ejemplo n.º 5
0
  def decide(self):
    '''
    Overwritting to allow for repair work to take place
    '''
    if self.search_mode and self.repair_mode:
      self.pre_decision()

      # We have moved off the structure entirely, so wander
      if self.beam is None:
        self.ground_support()

      # We've moved off the beam, so run the search support routine
      elif (self.memory['broken_beam_name'] != self.beam.name and 
        self.search_mode and self.memory['broken_beam_name'] != ''):

        # Remember the beam we moved onto right after the broken one
        if self.memory['previous_beam'] is None:
          self.memory['previous_beam'] = self.beam.name

        # We have found a support beam, so return to construct mode (the support beam is vertical)
        if (self.memory['previous_beam'] != self.beam.name and (
          self.memory['previous_direction'] is None or 
          self.memory['previous_direction'][1][2] > 0 or helpers.compare(
            self.memory['previous_direction'][1][2],0))):
          self.construction_mode()

          # Decide again since we're out of repair mode
          self.decide()

        else:
          self.find_support()
          # Move (don't check construction)
          self.movable_decide()

      # Simply move
      else:
        self.movable_decide()

    
    # We found a support beam and are on it, planning on construction. If 
    # we reach the endpoint of the beam (the support beam), then construct.
    elif self.repair_mode:
      if (helpers.compare(helpers.distance(self.location,
          self.beam.endpoints.j),self.step / 2)):
        self.start_contruction = True
        self.memory['broken'] = []

    # Build Mode
    else:
      super(DumbRepairer,self).decide()
Ejemplo n.º 6
0
  def executeStrategy1(self):
    if self.Body.num_beams == 0:
      if helpers.compare(self.Body.getLocation()[2],0):
        self.go_home_and_pick_up_beam()
      else:
        self.climb_down()
    
    elif self.Body.num_beams > 0 and self.Body.beam == None:
      wandering = self.Body.readFromMemory('wandering')
      if not self.Body.at_construction_site() and wandering == -1:
        self.go_to_construction_site()
      else:
        if self.Body.readFromMemory('wandering') < BConstants.robot['wander']:
          wandering+=1
          self.Body.addToMemory('wandering', wandering)
          self.move()
        elif self.Body.ground() != None:
          self.go_to_beam()
        else:
          self.build_base() if random() <= BConstants.prob['add_base'] else self.move()

    elif self.Body.num_beams > 0 and self.Body.beam != None:
      if self.Body.readFromMemory('climbing_back') != 0:
        self.climb_down(self.Body.readFromMemory('climbing_back'))
      elif self.Body.atTop(): 
        print('At TOP of beam', self.Body.beam.name)
        self.place_beam('center')  
      else:
        self.climb_up() if random() > BConstants.prob['random_beam'] else self.place_beam('center')

    else:
      print('Hmm, what to do?')
Ejemplo n.º 7
0
    def climb_down(self, num_beams=0):
        # We want to go in available direction with largest negative delta z
        # self.Body.model.SetModelIsLocked(False)
        if num_beams != 0:
            #print(self.Body.readFromMemory('climbing_back'), self.Body.readFromMemory('prev_beam'), self.Body.readFromMemory('current_beam'))
            if helpers.compare(self.Body.getLocation()[2], 0):
                self.Body.addToMemory('climbing_back', 0)
                self.Body.addToMemory('wandering', 0)
                return True
            beams_back = self.Body.readFromMemory('climbing_back')
            if self.Body.beam.name != self.Body.readFromMemory('prev_beam'):
                self.Body.addToMemory('climbing_back', beams_back - 1)

        info = self.Body.getAvailableDirections()
        direction = (0, 0, 0)
        beam = None
        steepest = float('Inf')
        for beam_name, loc in info['directions'].items():
            for (x, y, z) in loc:
                if z <= steepest:
                    direction = (x, y, z)
                    steepest = z
                    beam = self.Body.structure.find_beam(beam_name)
        self.climb(direction, beam)
        return True
Ejemplo n.º 8
0
        def crawl(point):
            # get the current box boundaries (bottom left corner-(0,0,0) is starting)
            # and coordinates
            xi, yi, zi = self.__get_indeces(point)
            bounds = xi * self.box_size[0], yi * self.box_size[
                1], zi * self.box_size[2]

            # This is defined here to have access to the above signs and bounds
            def closest(p):
                '''
        Returns which coordinate in p is closest to the boundary of a box 
        (x = 0, y = 1, z = 2) if moving along the line, and the absolute change
        in that coordinate.
        '''
                def distance(i):
                    '''
          i is 0,1,2 for x,y,z
          '''
                    if signs[i] == None:
                        # This will never be the minimum. Makes later code easier
                        return None
                    elif signs[i]:
                        return abs(p[i] - (bounds[i] + self.box_size[i]))
                    else:
                        return abs(p[i] - bounds[i])

                # Find the shortest time distance (ie, distance/velocity)
                index = None
                for i in range(3):
                    dist, vel = distance(i), abs(line[i])
                    if dist is not None and vel != 0:
                        if index is None:
                            index = i
                        else:
                            min_time = distance(index) / abs(line[index])
                            index = i if dist / vel < min_time else index

                return index, distance(index)

            # In crawl, we obtain the coordinate closests to an edge (index), and its
            # absolute distance from that edge
            index, distance = closest(point)

            # The change is the line scaled so that the right coordinate changes the
            # amount necessary to cross into the next box. This means that we scale it
            # and also add a teeny bit so as to push it into the right box. This is
            # the scaled version, exactly the distance we need to move
            move = helpers.scale(distance / abs(line[index]), line)
            # Here we scale the line again by epsilon/2. This is our push
            push = helpers.scale(PROGRAM['epsilon'] / 2, line)
            # The total change is the addition of these two
            change = helpers.sum_vectors(move, push)

            # make sure we are changing the right amount
            assert helpers.compare(abs(move[index]), distance)

            # The new initial coordinate in the next box
            new_point = helpers.sum_vectors(point, change)

            return new_point
Ejemplo n.º 9
0
    def remove_specific(self, dirs):
        '''
    We don't want to move UP along our own beam when we are repairing and at a
    joint.
    '''
        new_dirs = {}
        if self.at_joint() and self.repair_mode:
            # Access items
            for beam, vectors in dirs.items():
                # If the directions is about our beam, remove references to up.
                # Also do this for our broken beam (we don't want to get stuck climbing
                # onto it again and again in a cycle)
                if beam == self.beam.name or beam == self.memory[
                        'broken_beam_name']:
                    vectors = [
                        v for v in vectors
                        if v[2] < 0 or helpers.compare(v[2], 0)
                    ]
                    if vectors != []:
                        new_dirs[beam] = vectors
                else:
                    new_dirs[beam] = vectors

            return super(Repairer, self).remove_specific(new_dirs)

        return super(Repairer, self).remove_specific(dirs)
Ejemplo n.º 10
0
  def climb_down(self, num_beams=0):
    # We want to go in available direction with largest negative delta z 
    # self.Body.model.SetModelIsLocked(False)
    if num_beams != 0:
      #print(self.Body.readFromMemory('climbing_back'), self.Body.readFromMemory('prev_beam'), self.Body.readFromMemory('current_beam'))
      if helpers.compare(self.Body.getLocation()[2],0):
        self.Body.addToMemory('climbing_back', 0)
        self.Body.addToMemory('wandering', 0)
        return True
      beams_back = self.Body.readFromMemory('climbing_back')
      if self.Body.beam.name != self.Body.readFromMemory('prev_beam'):
        self.Body.addToMemory('climbing_back', beams_back-1)

    info = self.Body.getAvailableDirections()
    direction = (0,0,0)
    beam = None
    steepest = float('Inf')
    for beam_name, loc in info['directions'].items():
      for (x,y,z) in loc:
        if z <= steepest: 
          direction = (x,y,z)
          steepest = z
          beam = self.Body.structure.find_beam(beam_name) 
    self.climb(direction,beam)
    return True
Ejemplo n.º 11
0
    def crawl(point):
      # get the current box boundaries (bottom left corner-(0,0,0) is starting)
      # and coordinates
      xi, yi, zi = self.__get_indeces(point)
      bounds = xi*self.box_size[0], yi*self.box_size[1], zi*self.box_size[2]

      # This is defined here to have access to the above signs and bounds
      def closest(p):
        '''
        Returns which coordinate in p is closest to the boundary of a box 
        (x = 0, y = 1, z = 2) if moving along the line, and the absolute change
        in that coordinate.
        '''
        def distance(i):
          '''
          i is 0,1,2 for x,y,z
          '''
          if signs[i] == None:
            # This will never be the minimum. Makes later code easier
            return None
          elif signs[i]:
            return abs(p[i] - (bounds[i] + self.box_size[i]))
          else:
            return abs(p[i] - bounds[i])

        # Find the shortest time distance (ie, distance/velocity)
        index = None
        for i in range(3):
          dist, vel = distance(i), abs(line[i])
          if dist is not None and vel != 0:
            if index is None:
              index = i
            else:
              min_time = distance(index) / abs(line[index])
              index = i if dist / vel < min_time else index

        return index, distance(index)

      # In crawl, we obtain the coordinate closests to an edge (index), and its 
      # absolute distance from that edge
      index, distance = closest(point)

      # The change is the line scaled so that the right coordinate changes the 
      # amount necessary to cross into the next box. This means that we scale it
      # and also add a teeny bit so as to push it into the right box. This is 
      # the scaled version, exactly the distance we need to move
      move = helpers.scale(distance / abs(line[index]), line)
      # Here we scale the line again by epsilon/2. This is our push
      push = helpers.scale(PROGRAM['epsilon'] / 2, line)
      # The total change is the addition of these two
      change = helpers.sum_vectors(move,push)

      # make sure we are changing the right amount
      assert helpers.compare(abs(move[index]), distance)

      # The new initial coordinate in the next box
      new_point = helpers.sum_vectors(point,change)

      return new_point
Ejemplo n.º 12
0
 def at_joint(self):
     '''
 Updating to return true when we are on a beam AND on the ground. We want to
 consider this a joint so that the robot treats it as one and checks that 
 limit instead of another.
 '''
     return ((self.beam is not None
              and helpers.compare(self.location[2], 0))
             or super(NormalRepairer, self).at_joint())
Ejemplo n.º 13
0
    def executeStrategy2(self):
        if self.Body.num_beams == 0:
            if helpers.compare(self.Body.getLocation()[2], 0):
                self.go_home_and_pick_up_beam()
            else:
                self.climb_down()

        elif self.Body.num_beams > 0 and self.Body.beam == None:
            wandering = self.Body.readFromMemory('wandering')
            radius = self.Body.readFromMemory('base_radius')
            if not self.Body.at_construction_site() and wandering == -1:
                self.go_to_construction_site()
            elif self.Body.at_construction_site() and wandering == -1:
                self.move('random', radius + 60)
                self.Body.addToMemory('wandering', 0)
            else:
                if self.Body.ground() != None:
                    self.go_to_beam()
                elif self.Body.at_construction_site():
                    self.move('random', radius + 60)
                else:
                    self.go_to_construction_site()

        elif self.Body.num_beams > 0 and self.Body.beam != None:

            if self.Body.readFromMemory('climbing_back') != 0:
                self.climb_down(self.Body.readFromMemory('climbing_back'))
            elif self.Body.getLocation()[2] <= BConstants.robot['ground']:
                self.climb_up() if random(
                ) > BConstants.prob['ground_beam'] and not self.Body.atTop(
                ) else self.place_beam('ground')

            elif self.on_tripod():
                if self.Body.atTop():
                    self.Body.discardBeams()
                elif random() <= BConstants.prob['tripod']:
                    self.climb_up()
                else:
                    if self.Body.getLocation(
                    )[2] <= BConstants.robot['ground']:
                        self.place_beam('ground')
                    else:
                        self.place_beam('outward')

            elif self.Body.atTop():
                print('At TOP of beam', self.Body.beam.name)
                if self.Body.getLocation()[2] <= BConstants.robot['ground']:
                    self.place_beam('ground')
                else:
                    self.place_beam('center')
            else:
                self.climb_up() if random(
                ) > BConstants.prob['random_beam'] else self.place_beam(
                    'center')

        else:
            print('Hmm, what to do?')
Ejemplo n.º 14
0
  def atJoint(self):
    '''
    Returns whether or not the robot is at a joint
    '''
    if self.onStructure() and helpers.compare(self.location[2],0):
      return True

    # super section
    elif self.onStructure():

      for joint in self.beam.joints:
        # If we're at a joint to another beam
        if helpers.compare(helpers.distance(self.location,joint),0):
          return True
      
      return helpers.compare(self.location[2],0)
    
    else:
      return False
Ejemplo n.º 15
0
    def atJoint(self):
        '''
    Returns whether or not the robot is at a joint
    '''
        if self.onStructure() and helpers.compare(self.location[2], 0):
            return True

        # super section
        elif self.onStructure():

            for joint in self.beam.joints:
                # If we're at a joint to another beam
                if helpers.compare(helpers.distance(self.location, joint), 0):
                    return True

            return helpers.compare(self.location[2], 0)

        else:
            return False
Ejemplo n.º 16
0
   def compensate_change(coord, change=PROGRAM['epsilon']):
       '''
 Returns a random direction that is the right sign so that it compensates 
 for the sign of change
 '''
       if helpers.compare(coord, 0):
           return random.uniform(-1 * change, change)
       elif coord < 0:
           return random.uniform(0, change)
       else:
           return random.uniform(-1 * change, 0)
Ejemplo n.º 17
0
    def removeload(location):
      '''
      Removes the load assigned to a specific location based on where the robot 
      existed (assumes the robot is on a beams
      '''
      # Sanity check
      assert not self.model.GetModelIsLocked()

      # obtain current values.
      # values are encapsulated in a list as follows: ret, number_items, 
      # frame_names, loadpat_names, types, coordinates, directions, rel_dists, 
      # dists, loads
      data = self.model.FrameObj.GetLoadPoint(self.beam.name)
     
      # Sanity check with data
      assert data[0] == 0 
      if data[1] == 0:
        helpers.check(1,self,"getting loads",beam=self.beam.name,
          return_data=data,state=self.current_state())
        return;

      # Find location of load
      i, j = self.beam.endpoints
      curr_dist = helpers.distance(i,self.location)

      # Loop through distances to find our load (the one in self.location) and 
      # remove all reference to it. Additionally remove loads not related to our
      # load pattern
      indeces = []
      index = 0
      for ab_dist in data[8]:  # this provides acces to the absolute_distance 
        if ((helpers.compare(ab_dist,curr_dist) and PROGRAM['robot_load_case'] == 
          data[3][index]) or data[3][index] != PROGRAM['robot_load_case']):
          indeces.append(index)
        index += 1

      # Delete the loads off the beam
      ret = self.model.FrameObj.DeleteLoadPoint(self.beam.name,
        PROGRAM['robot_load_case'])
      helpers.check(ret,self,"deleting loads",return_val=ret,
        beam=self.beam.name,distance=curr_dist,previous_loads=data,
        state=self.current_state())

      # add the loads we want back to the frame (automatically deletes all 
      # previous loads)
      for i in range(data[1]):
        if i not in indeces:
          ret = self.model.FrameObj.SetLoadPoint(self.beam.name, 
            data[3][i], data[4][i], data[6][i], data[7][i], data[9][i],"Global",
            True,False)
          helpers.check(ret,self,"adding back loads",return_val=ret,
            beam=self.beam.name,load_pat=data[3][i],type=data[4][i],
            direction=data[6][i],rel_dist=data[7][i],load_val=data[9][i],
            state=self.current_state())
Ejemplo n.º 18
0
    def at_joint(self):
        """
    Returns whether or not the robot is at a joint
    """
        if self.on_structure():

            for joint in self.beam.joints:
                # If we're at a joint to another beam
                if helpers.compare(helpers.distance(self.location, joint), 0):
                    return True

        return False
Ejemplo n.º 19
0
    def beam_check(self, name):
        '''
    Checks a beam to see whether it is in a state that requires repair
    '''
        moment = self.get_moment(name)
        e1, e2 = self.structure.get_endpoints(name, self.location)
        xy_dist = helpers.distance((e1[0], e1[1], 0), (e2[0], e2[1], 0))
        limit = BConstants.beam['beam_limit'] + (
            xy_dist / BConstants.beam['length']
        ) * BConstants.beam['horizontal_beam_limit']

        return (moment < limit or helpers.compare(moment, limit))
Ejemplo n.º 20
0
    def global_default_axes(self):
        '''
    Returns the default local axes. Later on we might incorporate the ability to return
    rotated axes.
    '''
        axis_1 = helpers.make_unit(
            helpers.make_vector(self.endpoints.i, self.endpoints.j))
        vertical = (math.sin(
            math.radians(helpers.smallest_angle(axis_1, (0, 0, 1)))) <= 0.001)

        # Break up axis_1 into unit component vectors on 1-2 plane, along with
        # their maginitudes
        u1, u2 = (axis_1[0], axis_1[1], 0), (0, 0, axis_1[2])
        l1, l2 = helpers.length(u1), helpers.length(u2)
        u1 = helpers.make_unit(u1) if not helpers.compare(l1, 0) else (1, 1, 0)
        u2 = helpers.make_unit(u2) if not helpers.compare(l2, 0) else (0, 0, 1)

        # Calculate axis_2 by negating and flipping componenet vectors of axis_1
        axis_2 = (1, 0, 0) if vertical else helpers.make_unit(
            helpers.sum_vectors(helpers.scale(-1 *
                                              l2, u1), helpers.scale(l1, u2)))

        # Make it have a positive z-component
        axis_2 = axis_2 if axis_2[2] > 0 else helpers.scale(-1, axis_2)

        # Calculate axis_3 by crossing axis 1 with axis 2 (according to right hand
        # rule)
        axis_3 = helpers.cross(axis_1, axis_2)
        axis_3 = helpers.make_unit(
            (axis_3[0], axis_3[1], 0)) if vertical else axis_3

        # Sanity checks
        # Unit length
        assert helpers.compare(helpers.length(axis_3), 1)

        # On the x-y plane
        assert helpers.compare(axis_3[2], 0)

        return axis_1, axis_2, axis_3
Ejemplo n.º 21
0
    def below(beams):
      '''
      Returns whether all of the beams are below us
      '''
      for beam in beams:
        for endpoint in beam.endpoints:

          # If the beam is not close to us and it is greater than our location
          if (not helpers.compare(helpers.distance(self.location,endpoint),0)
            and endpoint[2] > self.location[2]):
            return False

      return True
Ejemplo n.º 22
0
        def set_dir(string, coord):
            '''
      Figures out what pos_var should be in order to travel in that direction
      
      NO LONGER USED

      '''
            if helpers.compare(coord, 0):
                self.memory[string] = None
            if coord > 0:
                self.memory[string] = True
            else:
                self.memory[string] = False
Ejemplo n.º 23
0
    def atTrueTop(self):
        '''
    Returns if we really are at the top
    '''
        def below(beams):
            '''
      Returns whether all of the beams are below us
      '''
            for beam in beams:
                for endpoint in beam.endpoints:

                    # If the beam is not close to us and it is greater than our location
                    if (not helpers.compare(
                            helpers.distance(self.location, endpoint), 0)
                            and endpoint[2] > self.location[2]):
                        return False

            return True

        if self.beam is not None:
            if (helpers.compare(
                    helpers.distance(self.location, self.beam.endpoints.i), 0)
                    and self.beam.endpoints.i[2] > self.beam.endpoints.j[2]):
                close = self.beam.endpoints.i
            elif (helpers.compare(
                    helpers.distance(self.location, self.beam.endpoints.j), 0)
                  and self.beam.endpoints.j[2] > self.beam.endpoints.i[2]):
                close = self.beam.endpoints.j
            else:
                close = None

            if close is not None:
                try:
                    beams = self.beam.joints[self.beam.endpoints.i]
                    return below(beams)
                except KeyError:
                    return True

        return False
Ejemplo n.º 24
0
    def set_dir(string,coord):
      '''
      Figures out what pos_var should be in order to travel in that direction
      
      NO LONGER USED

      '''
      if helpers.compare(coord,0):
        self.memory[string] = None
      if coord > 0:
        self.memory[string] = True
      else:
        self.memory[string] = False
Ejemplo n.º 25
0
    def move(self, direction, beam):
        '''
    Moves the robot in direction passed in and onto the beam specified
    '''
        length = helpers.length(direction)

        # The direction is smaller than the determined step, so move exactly by
        # direction
        if length < self.step:
            new_location = helpers.sum_vectors(self.location, direction)
            self.change_location(new_location, beam)

            # call do_action again since we still have some distance left, and update
            # step to reflect how much distance is left to cover
            self.step = self.step - length

            # Reset step in preparation for next timestep
            if helpers.compare(self.step, 0):
                self.step == ROBOT['step_length']

            # We still have steps to go, so run an analysis if necessary
            elif self.beam is not None:
                # Run analysis before deciding to get the next direction
                if not self.model.GetModelIsLocked() and self.need_data():
                    errors = helpers.run_analysis(self.model)
                    if errors != '':
                        # pdb.set_trace()
                        pass

                # Get next direction
                self.next_direction_info = self.get_direction()

                # Unlock the results so that we can actually move
                if self.model.GetModelIsLocked():
                    self.model.SetModelIsLocked(False)

                # Move
                self.do_action()

            # We climbed off
            else:
                assert not self.model.GetModelIsLocked()

                self.do_action()

        # The direction is larger than the usual step, so move only the step in the
        # specified direction
        else:
            movement = helpers.scale(self.step, helpers.make_unit(direction))
            new_location = helpers.sum_vectors(self.location, movement)
            self.change_location(new_location, beam)
Ejemplo n.º 26
0
  def move(self, direction, beam):
    '''
    Moves the robot in direction passed in and onto the beam specified
    '''
    length = helpers.length(direction)

    # The direction is smaller than the determined step, so move exactly by 
    # direction
    if length < self.step:
      new_location = helpers.sum_vectors(self.location, direction)
      self.change_location(new_location, beam)

      # call do_action again since we still have some distance left, and update
      # step to reflect how much distance is left to cover
      self.step = self.step - length

      # Reset step in preparation for next timestep
      if helpers.compare(self.step,0):
        self.step == ROBOT['step_length']

      # We still have steps to go, so run an analysis if necessary
      elif self.beam is not None:
        # Run analysis before deciding to get the next direction
        if not self.model.GetModelIsLocked() and self.need_data():
          errors = helpers.run_analysis(self.model)
          if errors != '':
            # pdb.set_trace()
            pass

        # Get next direction
        self.next_direction_info = self.get_direction()

        # Unlock the results so that we can actually move
        if self.model.GetModelIsLocked():
          self.model.SetModelIsLocked(False)

        # Move
        self.do_action()

      # We climbed off
      else:
        assert not self.model.GetModelIsLocked()
        
        self.do_action()

    # The direction is larger than the usual step, so move only the step in the 
    # specified direction
    else:
      movement = helpers.scale(self.step, helpers.make_unit(direction))
      new_location = helpers.sum_vectors(self.location, movement)
      self.change_location(new_location, beam)
Ejemplo n.º 27
0
  def local_rules(self):
    '''
    Overriding so we can build support beam
    '''
    # If we ran our course with the support, construct it
    if (((self.beam is not None and self.memory['new_beam_steps'] == 0) or (
      helpers.compare(self.location[2],0) and 
      self.memory['new_beam_ground_steps'] == 0)) and 
      self.memory['construct_support']):
      return True

    # Local rules as before
    else:
      return super(DumbRepairer,self).local_rules()
Ejemplo n.º 28
0
 def climb(self, location, beam):
   length = helpers.length(location)
   if length <= self.Body.step:
     new_location = helpers.sum_vectors(self.Body.getLocation(), location)
     if helpers.compare(new_location[2], 0): 
       beam = None
     else: print('climbing beam', beam.name)
   else:
     new_location = helpers.sum_vectors(self.Body.getLocation(), helpers.scale( \
                    self.Body.step, helpers.make_unit(location)))
     print('climbing beam', beam.name)
   self.Body.model.SetModelIsLocked(False)
   self.Body.changeLocationOnStructure(new_location, beam)
   return True
Ejemplo n.º 29
0
    def local_rules(self):
        '''
    Overriding so we can build support beam
    '''
        # If we ran our course with the support, construct it
        if (((self.beam is not None and self.memory['new_beam_steps'] == 0) or
             (helpers.compare(self.location[2], 0)
              and self.memory['new_beam_ground_steps'] == 0))
                and self.memory['construct_support']):
            return True

        # Local rules as before
        else:
            return super(DumbRepairer, self).local_rules()
Ejemplo n.º 30
0
  def global_default_axes(self):
    '''
    Returns the default local axes. Later on we might incorporate the ability to return
    rotated axes.
    '''
    axis_1 = helpers.make_unit(helpers.make_vector(self.endpoints.i,
      self.endpoints.j))
    vertical = (math.sin(math.radians(helpers.smallest_angle(axis_1,(0,0,1)))) 
      <= 0.001)

    # Break up axis_1 into unit component vectors on 1-2 plane, along with 
    # their maginitudes
    u1, u2 = (axis_1[0],axis_1[1],0),(0,0,axis_1[2])
    l1,l2 = helpers.length(u1), helpers.length(u2)
    u1 = helpers.make_unit(u1) if not helpers.compare(l1,0) else (1,1,0) 
    u2 = helpers.make_unit(u2) if not helpers.compare(l2,0) else (0,0,1)

    # Calculate axis_2 by negating and flipping componenet vectors of axis_1
    axis_2 = (1,0,0) if vertical else helpers.make_unit(helpers.sum_vectors(
      helpers.scale(-1 * l2,u1),helpers.scale(l1,u2)))

    # Make it have a positive z-component
    axis_2 = axis_2 if axis_2[2] > 0 else helpers.scale(-1,axis_2)

    # Calculate axis_3 by crossing axis 1 with axis 2 (according to right hand
    # rule)
    axis_3 = helpers.cross(axis_1,axis_2)
    axis_3 = helpers.make_unit((axis_3[0],axis_3[1],0)) if vertical else axis_3

    # Sanity checks
    # Unit length
    assert helpers.compare(helpers.length(axis_3),1)

    # On the x-y plane
    assert helpers.compare(axis_3[2],0)

    return axis_1,axis_2,axis_3
Ejemplo n.º 31
0
  def executeStrategy2(self):
    if self.Body.num_beams == 0:
      if helpers.compare(self.Body.getLocation()[2],0):
        self.go_home_and_pick_up_beam()
      else:
        self.climb_down()
    
    elif self.Body.num_beams > 0 and self.Body.beam == None:
      wandering = self.Body.readFromMemory('wandering')
      radius = self.Body.readFromMemory('base_radius')
      if not self.Body.at_construction_site() and wandering == -1:
        self.go_to_construction_site()
      elif self.Body.at_construction_site() and wandering == -1:
        self.move('random', radius + 60)
        self.Body.addToMemory('wandering', 0)
      else:
        if self.Body.ground() != None:
          self.go_to_beam()
        elif self.Body.at_construction_site():
          self.move('random', radius + 60)
        else:
          self.go_to_construction_site()
          
    elif self.Body.num_beams > 0 and self.Body.beam != None:
      
      if self.Body.readFromMemory('climbing_back') != 0:
        self.climb_down(self.Body.readFromMemory('climbing_back'))
      elif self.Body.getLocation()[2] <= BConstants.robot['ground']:
        self.climb_up() if random() > BConstants.prob['ground_beam'] and not self.Body.atTop() else self.place_beam('ground')
      
      elif self.on_tripod():
        if self.Body.atTop():
          self.Body.discardBeams()
        elif random() <= BConstants.prob['tripod']:
          self.climb_up() 
        else:
          if self.Body.getLocation()[2] <= BConstants.robot['ground']:
            self.place_beam('ground')
          else: self.place_beam('outward')
      
      elif self.Body.atTop(): 
        print('At TOP of beam', self.Body.beam.name)
        if self.Body.getLocation()[2] <= BConstants.robot['ground']: self.place_beam('ground')
        else: self.place_beam('center')
      else:
        self.climb_up() if random() > BConstants.prob['random_beam'] else self.place_beam('center')

    else:
      print('Hmm, what to do?')
Ejemplo n.º 32
0
  def at_top(self):
    '''
    Returns if we really are at the top
    '''
    def below(beams):
      '''
      Returns whether all of the beams are below us
      '''
      for beam in beams:
        for endpoint in beam.endpoints:

          # If the beam is not close to us and it is greater than our location
          if (not helpers.compare(helpers.distance(self.location,endpoint),0)
            and endpoint[2] > self.location[2]):
            return False

      return True

    if self.beam is not None:
      if (helpers.compare(helpers.distance(self.location,self.beam.endpoints.i),0)
        and self.beam.endpoints.i[2] > self.beam.endpoints.j[2]):
        close = self.beam.endpoints.i
      elif (helpers.compare(helpers.distance(self.location,self.beam.endpoints.j),0)
        and self.beam.endpoints.j[2] > self.beam.endpoints.i[2]):
        close = self.beam.endpoints.j
      else:
        close = None

      if close is not None:
        try:
          beams = self.beam.joints[self.beam.endpoints.i]
          return below(beams)
        except KeyError:
          return True

    return False
Ejemplo n.º 33
0
  def get_preferred_direction(self,beam):
    '''
    Returns the preferred direction - this is the direction towards which the 
    robot wants to move when looking for an already set support tube.
    The direction is a unit vector
    '''
    # Calculate direction of repair (check 0 dist, which means it is perfectly
    # vertical!)
    i, j = beam.endpoints.i, beam.endpoints.j
    v1 = helpers.make_vector(self.location,j)
    v2 = helpers.make_vector(i,self.location)
    l1,l2 = helpers.length(v1), helpers.length(v2)

    # v1 is non-zero and it is not vertical
    if not (helpers.compare(l1,0) or helpers.is_vertical(v1)):
      return helpers.make_unit(v1)

    # v2 is non-zero and it is not vertical
    elif not (helpers.compare(l2,0) or helpers.is_vertical(v2)):
      return helpers.make_unit(v2)

    # No preferred direction because the beam is perfectly vertical
    else:
      return None
Ejemplo n.º 34
0
    def get_preferred_direction(self, beam):
        '''
    Returns the preferred direction - this is the direction towards which the 
    robot wants to move when looking for an already set support tube.
    The direction is a unit vector
    '''
        # Calculate direction of repair (check 0 dist, which means it is perfectly
        # vertical!)
        i, j = beam.endpoints.i, beam.endpoints.j
        v1 = helpers.make_vector(self.location, j)
        v2 = helpers.make_vector(i, self.location)
        l1, l2 = helpers.length(v1), helpers.length(v2)

        # v1 is non-zero and it is not vertical
        if not (helpers.compare(l1, 0) or helpers.is_vertical(v1)):
            return helpers.make_unit(v1)

        # v2 is non-zero and it is not vertical
        elif not (helpers.compare(l2, 0) or helpers.is_vertical(v2)):
            return helpers.make_unit(v2)

        # No preferred direction because the beam is perfectly vertical
        else:
            return None
Ejemplo n.º 35
0
 def climb(self, location, beam):
     length = helpers.length(location)
     if length <= self.Body.step:
         new_location = helpers.sum_vectors(self.Body.getLocation(),
                                            location)
         if helpers.compare(new_location[2], 0):
             beam = None
         else:
             print('climbing beam', beam.name)
     else:
         new_location = helpers.sum_vectors(self.Body.getLocation(), helpers.scale( \
                        self.Body.step, helpers.make_unit(location)))
         print('climbing beam', beam.name)
     self.Body.model.SetModelIsLocked(False)
     self.Body.changeLocationOnStructure(new_location, beam)
     return True
Ejemplo n.º 36
0
  def decide(self):
    # Tell each robot to make the decion
    for repairer in self.repairers:
      self.repairers[repairer].decide()

      # Add location data for visualization of simulation
      loc = self.repairers[repairer].get_true_location()
      location = (loc[0], loc[1], 0) if helpers.compare(loc[2],0) else loc
      self.visualization_data += "{}:{}<>".format(repairer,str(
        helpers.round_tuple(location,3)))

      # Get color data based on what the robot is doing
      color = (1,0,1) if not self.repairers[repairer].repair_mode else (0,1,0)
      self.color_data += "{}:{}<>".format(repairer,str(color))

    self.visualization_data += "\n"
    self.color_data += "\n"
Ejemplo n.º 37
0
   def addpoint(p):
       """
 Adds a point object to our model. The object is retrained in all 
 directions if on the ground (including rotational and translational 
 motion. Returns the name of the added point.
 """
       # Add to SAP Program
       name = self.program.point_objects.addcartesian(p)
       # Check Coordinates
       if helpers.compare(p[2], 0):
           DOF = (True, True, True, True, True, True)
           if self.program.point_objects.restraint(name, DOF):
               return name
           else:
               print("Something went wrong adding ground point {}.".format(str(p)))
       else:
           return name
Ejemplo n.º 38
0
   def addpoint(p):
       '''
 Adds a point object to our model. The object is retrained in all 
 directions if on the ground (including rotational and translational 
 motion. Returns the name of the added point.
 '''
       # Add to SAP Program
       name = self.program.point_objects.addcartesian(p)
       # Check Coordinates
       if helpers.compare(p[2], 0):
           DOF = (True, True, True, True, True, True)
           if self.program.point_objects.restraint(name, DOF):
               return name
           else:
               print(
                   "Something went wrong adding ground point {}.".format(
                       str(p)))
       else:
           return name
Ejemplo n.º 39
0
  def change_location_local(self,new_location, first_beam = None):
    '''
    Moves the robot about locally (ie, without worrying about the structure, 
    except for when it moves onto the first beam)
    '''
    # When we move onto our first beam, add the load
    if first_beam != None:
      self.__addload(first_beam,new_location,self.weight)
    self.location = new_location

    # Check that we are on the first octant
    assert self.location[0] >= 0
    assert self.location[1] >= 0

    # Verify that we are still on the xy plane
    if helpers.compare(self.location[2], 0):
      loc = list(self.location)
      loc[2] = 0
      self.location = tuple(loc)
Ejemplo n.º 40
0
    def change_location_local(self, new_location, first_beam=None):
        '''
    Moves the robot about locally (ie, without worrying about the structure, 
    except for when it moves onto the first beam)
    '''
        # When we move onto our first beam, add the load
        if first_beam != None:
            self.__addload(first_beam, new_location, self.weight)
        self.location = new_location

        # Check that we are on the first octant
        assert self.location[0] >= 0
        assert self.location[1] >= 0

        # Verify that we are still on the xy plane
        if helpers.compare(self.location[2], 0):
            loc = list(self.location)
            loc[2] = 0
            self.location = tuple(loc)
Ejemplo n.º 41
0
    def random_direction():
      '''
      Returns a random, new location (direction)
      '''
      # obtain a random direction
      direction = (random.uniform(-1 * self.step, self.step), random.uniform(
        -1 * self.step, self.step), 0)

      # The they can't all be zero!
      if helpers.compare(helpers.length(direction),0):
        return random_direction()
      else:
        step = helpers.scale(self.step,helpers.make_unit(direction))
        predicted_location = helpers.sum_vectors(step, self.location)

        # Check the location
        if helpers.check_location(predicted_location):
          return direction
        else:
          return random_direction()
Ejemplo n.º 42
0
        def random_direction():
            '''
      Returns a random, new location (direction)
      '''
            # obtain a random direction
            direction = (random.uniform(-1 * self.step, self.step),
                         random.uniform(-1 * self.step, self.step), 0)

            # The they can't all be zero!
            if helpers.compare(helpers.length(direction), 0):
                return random_direction()
            else:
                step = helpers.scale(self.step, helpers.make_unit(direction))
                predicted_location = helpers.sum_vectors(step, self.location)

                # Check the location
                if helpers.check_location(predicted_location):
                    return direction
                else:
                    return random_direction()
Ejemplo n.º 43
0
  def decide(self):
    # Tell each robot to make the decion
    for repairer in self.repairers:
      self.repairers[repairer].performDecision()

      # Add location data for visualization of simulation
      loc = self.repairers[repairer].Body.getGenuineLocation()
      location = (loc[0], loc[1], 0) if helpers.compare(loc[2],0) else loc
      self.visualization_data += "{}:{}<>".format(repairer,str(
        helpers.round_tuple(location,3)))

      # Get color data based on what the robot is doing
      try:
        color = (1,0,1) if not self.repairers[repairer].Body.readFromMemory('repair_mode') else (0,1,0)
      except:
        color = (0,1,0)\

      self.color_data += "{}:{}<>".format(repairer,str(color))

    self.visualization_data += "\n"
    self.color_data += "\n"
Ejemplo n.º 44
0
    def climb_off(self, loc):
        """
    Returns whether or not the robot should climb off the structure. Additionally,
    sets some special variables
    """
        # On the xy-plane with no beams OR repairing
        if helpers.compare(loc[2], 0) and (self.num_beams == 0 or self.search_mode):

            # Not repairing, so calculate direction
            if not self.search_mode:
                direction = helpers.make_vector(self.location, HOME["center"])
                direction = (direction[0], direction[1], 0)
                self.ground_direction = direction

            return True

        else:

            # Resetting to None if not in search_mode
            self.ground_direction = None if not self.search_mode else self.ground_direction

            return False
Ejemplo n.º 45
0
  def remove_specific(self,dirs):
    '''
    We don't want to move UP along our own beam when we are repairing and at a
    joint.
    '''
    new_dirs = {}
    if self.at_joint() and self.repair_mode:
      # Access items
      for beam, vectors in dirs.items():
        # If the directions is about our beam, remove references to up.
        # Also do this for our broken beam (we don't want to get stuck climbing
        # onto it again and again in a cycle)
        if beam == self.beam.name or beam == self.memory['broken_beam_name']:
          vectors = [v for v in vectors if v[2] < 0 or helpers.compare(v[2],0)]
          if vectors != []:
            new_dirs[beam] = vectors
        else:
          new_dirs[beam] = vectors

      return super(Repairer,self).remove_specific(new_dirs)

    return super(Repairer,self).remove_specific(dirs)
Ejemplo n.º 46
0
    def executeStrategy1(self):
        if self.Body.num_beams == 0:
            if helpers.compare(self.Body.getLocation()[2], 0):
                self.go_home_and_pick_up_beam()
            else:
                self.climb_down()

        elif self.Body.num_beams > 0 and self.Body.beam == None:
            wandering = self.Body.readFromMemory('wandering')
            if not self.Body.at_construction_site() and wandering == -1:
                self.go_to_construction_site()
            else:
                if self.Body.readFromMemory(
                        'wandering') < BConstants.robot['wander']:
                    wandering += 1
                    self.Body.addToMemory('wandering', wandering)
                    self.move()
                elif self.Body.ground() != None:
                    self.go_to_beam()
                else:
                    self.build_base() if random(
                    ) <= BConstants.prob['add_base'] else self.move()

        elif self.Body.num_beams > 0 and self.Body.beam != None:
            if self.Body.readFromMemory('climbing_back') != 0:
                self.climb_down(self.Body.readFromMemory('climbing_back'))
            elif self.Body.atTop():
                print('At TOP of beam', self.Body.beam.name)
                self.place_beam('center')
            else:
                self.climb_up() if random(
                ) > BConstants.prob['random_beam'] else self.place_beam(
                    'center')

        else:
            print('Hmm, what to do?')
Ejemplo n.º 47
0
 def climb_off(self, loc):
   '''
   Decides whether or not the robot should climb off the structure
   '''
   return helpers.compare(loc[2],0) and random.int(0,1) == 1
Ejemplo n.º 48
0
  def get_walkable_directions(self,box):
    '''
    Finds all of the beams in box which intersect the robots location or 
    to which the robot can walk onto. Returns delta x, delta y, and delta z
    of the change necessary to arrive at either the joint or to move along
    the current beam by current_step.
    '''
    # Get all joints within a time-step
    # Remember that beams DOES NOT include the current beam, only others
    crawlable = {}
    for joint in self.beam.joints:
      dist = helpers.distance(self.location,joint)
      
      # If we are at the joint, return the possible directions of other beams
      if helpers.compare(dist,0):
        for beam in self.beam.joints[joint]:
      
          # The index error should never happen, but this provides nice error 
          # support
          try:
            # Get endpoints of beam and find direction vector to those endpoints
            e1, e2 = beam.endpoints
            v1, v2 = helpers.make_vector(self.location,e1), helpers.make_vector(
              self.location,e2)

            # We don't want to include zero-vectors
            bool_v1,bool_v2 = (not helpers.compare(helpers.length(v1),0),
              not helpers.compare(helpers.length(v2),0))

            # Checking for zero_vectors
            if bool_v1 and bool_v2:
              crawlable[beam.name] = ([helpers.make_vector(self.location,e1), 
                helpers.make_vector(self.location,e2)])
            elif bool_v1:
              crawlable[beam.name] = [helpers.make_vector(self.location,e1)]
            elif bool_v2:
              crawlable[beam.name] = [helpers.make_vector(self.location,e2)]
            else:
              raise Exception("All distances from beam were zero-length.")

            # Include distances to nearby joints (on the beam moving out from our
            # current joint)
            for coord in beam.joints:
              # Direction vecotrs
              v = helpers.make_vector(self.location,coord)
              length = helpers.length(v)

              # If further than our step, or zero, pass
              if ((length < self.step or helpers.compare(length, self.step))
                and not helpers.compare(length,0)):
                try:
                  # Only add if it is not already accounted for
                  if v not in crawlable[beam.name]:
                    crawlable[beam.name].append(v)
                except IndexError:
                  raise Exception("Adding nearby joints failed because \
                    endpoints were ignored.")

          except IndexError:
            print ("The beam {} seems to have a joint with {}, but it is not in\
              the box?".format(name,self.beam.name))
      
      # For all joints within the timestep, return a direction that is exactly 
      # the change from current to that point.
      elif dist <= self.step:
        if self.beam.name in crawlable:
          crawlable[self.beam.name].append(helpers.make_vector(self.location,
            joint))
        else:
          crawlable[self.beam.name] = [helpers.make_vector(self.location,joint)]
      # The joint is too far, so no point in considering it as a walkable direction
      else:
        pass

    # The joints never include our own beam, so now add directions pertaining to
    # our own beam
    v1, v2 = (helpers.make_vector(self.location,self.beam.endpoints.i), 
      helpers.make_vector(self.location,self.beam.endpoints.j))

    # Check to make sure directions are non-zero
    b_v1 = not helpers.compare(helpers.length(v1),0)
    b_v2 = not helpers.compare(helpers.length(v2),0)

    # If we haven't already accounted for our beam
    if self.beam.name not in crawlable:
      # Add the non-zero directions
      if b_v1 and b_v2:
        crawlable[self.beam.name] = [v1,v2]
      elif b_v1:
        crawlable[self.beam.name] = [v1]
      elif b_v2:
        crawlable[self.beam.name] = [v2]

    # Add directions that might not have been entered by joints
    else:
      bool_v1, bool_v2 = True, True
      for direct in crawlable[self.beam.name]:
        # Don't add directions which are basically the same.
        if helpers.parallel(direct,v1) and helpers.dot(direct,v1) > 0:
          bool_v1 = False
        if helpers.parallel(direct,v2) and helpers.dot(direct,v2) > 0:
          bool_v2 = False

      # Add the non-zero non-parallel direction
      if bool_v2 and b_v2:
        crawlable[self.beam.name].append(v2)
      if bool_v1 and b_v1:
        crawlable[self.beam.name].append(v1)

    return crawlable
Ejemplo n.º 49
0
        def add_angles(box, dictionary):
            for name, beam in box.items():

                # Ignore the beam you're on.
                if self.beam == None or self.beam.name != name:

                    # Base vector (from which angles are measured)
                    base_vector = helpers.make_vector(pivot, endpoint)

                    # Get the closest points between the beam we want to construct and the
                    # current beam
                    points = helpers.closest_points(beam.endpoints,
                                                    (pivot, endpoint))
                    if points != None:

                        # Endpoints (e1 is on a vertical beam, e2 is on the tilted one)
                        e1, e2 = points

                        # If we can actually reach the second point from vertical
                        if (not helpers.compare(helpers.distance(pivot, e2), 0)
                                and
                                helpers.distance(pivot, e2) <= BEAM['length']):

                            # Distance between the two endpoints
                            dist = helpers.distance(e1, e2)

                            # Vector of beam we want to construct and angle from base_vector
                            construction_vector = helpers.make_vector(
                                pivot, e2)
                            angle = helpers.smallest_angle(
                                base_vector, construction_vector)

                            # Add to dictionary
                            if e2 in dictionary:
                                assert helpers.compare(dictionary[e2], angle)
                            else:
                                dictionary[e2] = angle

                    # Get the points at which the beam intersects the sphere created by
                    # the vertical beam
                    sphere_points = helpers.sphere_intersection(
                        beam.endpoints, pivot, BEAM['length'])
                    if sphere_points != None:

                        # Cycle through intersection points (really, should be two, though
                        # it is possible for it to be one, in
                        # which case, we would have already taken care of this). Either way,
                        # we just cycle
                        for point in sphere_points:

                            # Vector to the beam we want to construct
                            construction_vector = helpers.make_vector(
                                pivot, point)
                            angle = helpers.smallest_angle(
                                base_vector, construction_vector)

                            # Add to dictionary
                            if point in dictionary:
                                assert helpers.compare(dictionary[point],
                                                       angle)
                            else:
                                dictionary[point] = angle

                    # Endpoints are also included
                    for e in beam.endpoints:
                        v = helpers.make_vector(pivot, e)
                        l = helpers.length(v)
                        if (e not in dictionary and not helpers.compare(l, 0)
                                and (helpers.compare(l, BEAM['length'])
                                     or l < BEAM['length'])):
                            angle = helpers.smallest_angle(base_vector, v)
                            dictionary[e] = angle

            return dictionary
Ejemplo n.º 50
0
        def add_angles(box, dictionary):
            for name, beam in box.items():

                # Ignore the beam you're on.
                if self.beam == None or self.beam.name != name:

                    # Base vector (from which angles are measured)
                    base_vector = helpers.make_vector(pivot, endpoint)

                    # Get the closest points between the beam we want to construct and the
                    # current beam
                    points = helpers.closest_points(beam.endpoints, (pivot, endpoint))
                    if points != None:

                        # Endpoints (e1 is on a vertical beam, e2 is on the tilted one)
                        e1, e2 = points

                        # If we can actually reach the second point from vertical
                        if (
                            not helpers.compare(helpers.distance(pivot, e2), 0)
                            and helpers.distance(pivot, e2) <= BEAM["length"]
                        ):

                            # Distance between the two endpoints
                            dist = helpers.distance(e1, e2)

                            # Vector of beam we want to construct and angle from base_vector
                            construction_vector = helpers.make_vector(pivot, e2)
                            angle = helpers.smallest_angle(base_vector, construction_vector)

                            # Add to dictionary
                            if e2 in dictionary:
                                assert helpers.compare(dictionary[e2], angle)
                            else:
                                dictionary[e2] = angle

                    # Get the points at which the beam intersects the sphere created by
                    # the vertical beam
                    sphere_points = helpers.sphere_intersection(beam.endpoints, pivot, BEAM["length"])
                    if sphere_points != None:

                        # Cycle through intersection points (really, should be two, though
                        # it is possible for it to be one, in
                        # which case, we would have already taken care of this). Either way,
                        # we just cycle
                        for point in sphere_points:

                            # Vector to the beam we want to construct
                            construction_vector = helpers.make_vector(pivot, point)
                            angle = helpers.smallest_angle(base_vector, construction_vector)

                            # Add to dictionary
                            if point in dictionary:
                                assert helpers.compare(dictionary[point], angle)
                            else:
                                dictionary[point] = angle

                    # Endpoints are also included
                    for e in beam.endpoints:
                        v = helpers.make_vector(pivot, e)
                        l = helpers.length(v)
                        if (
                            e not in dictionary
                            and not helpers.compare(l, 0)
                            and (helpers.compare(l, BEAM["length"]) or l < BEAM["length"])
                        ):
                            angle = helpers.smallest_angle(base_vector, v)
                            dictionary[e] = angle

            return dictionary
Ejemplo n.º 51
0
 def climb_off(self, loc):
     '''
 Decides whether or not the robot should climb off the structure
 '''
     return helpers.compare(loc[2], 0) and random.int(0, 1) == 1
Ejemplo n.º 52
0
    def build(self):
        """
    This functions sets down a beam. This means it "wiggles" it around in the 
    air until it finds a connection (programatically, it just finds the 
    connection which makes the smallest angle). Returns false if something went 
    wrong, true otherwise.
    """

        def check(i, j):
            """
      Checks the endpoints and returns two that don't already exist in the 
      structure. If they do already exist, then it returns two endpoints that 
      don't. It does this by changing the j-endpoint. This function also takes 
      into account making sure that the returned value is still within the 
      robot's tendency to build up. (ie, it does not return a beam which would 
      build below the limit angle_constraint)
      """
            # There is already a beam here, so let's move our current beam slightly to
            # some side
            if not self.structure.available(i, j):

                # Create a small disturbace
                lim = BEAM["random"]
                f = random.uniform
                disturbance = (f(-1 * lim, lim), f(-1 * lim, lim), f(-1 * lim, lim))

                # find the new j-point for the beam
                new_j = helpers.beam_endpoint(i, helpers.sum_vectors(j, disturbance))

                return check(i, new_j)

            else:

                # Calculate the actual endpoint of the beam (now that we now direction
                # vector)
                return (i, helpers.beam_endpoint(i, j))

        # Sanitiy check
        assert self.num_beams > 0

        # Default pivot is our location
        pivot = self.location

        if self.beam is not None:

            # Obtain any nearby joints, and insert the i/j-end if needed
            all_joints = [coord for coord in self.beam.joints if not helpers.compare(coord[2], 0)]
            if self.beam.endpoints.j not in all_joints and not helpers.compare(self.beam.endpoints.j[2], 0):
                all_joints.append(self.beam.endpoints.j)
            if self.beam.endpoints.i not in all_joints and not helpers.compare(self.beam.endpoints.i[2], 0):
                all_joints.append(self.beam.endpoints.i)

            # Find the nearest one
            joint_coord, dist = min(
                [(coord, helpers.distance(self.location, coord)) for coord in all_joints], key=lambda t: t[1]
            )

            # If the nearest joint is within our error, then use it as the pivot
            if dist <= BConstants.beam["joint_error"]:
                pivot = joint_coord

        # Default vertical endpoint (the ratios are measured from the line created
        # by pivot -> vertical_endpoint)
        vertical_endpoint = helpers.sum_vectors(
            pivot, helpers.scale(BEAM["length"], helpers.make_unit(BConstants.beam["vertical_dir_set"]))
        )

        # Get the ratios
        sorted_angles = self.local_angles(pivot, vertical_endpoint)

        # Find the most vertical position
        final_coord = self.find_nearby_beam_coord(sorted_angles, pivot)

        # Obtain the default endpoints
        default_endpoint = self.get_default(final_coord, vertical_endpoint)
        i, j = check(pivot, default_endpoint)

        # Sanity check
        assert helpers.compare(helpers.distance(i, j), BConstants.beam["length"])

        return self.addbeam(i, j)
Ejemplo n.º 53
0
    def get_walkable_directions(self, box):
        '''
    Finds all of the beams in box which intersect the robots location or 
    to which the robot can walk onto. Returns delta x, delta y, and delta z
    of the change necessary to arrive at either the joint or to move along
    the current beam by current_step.
    '''
        # Get all joints within a time-step
        # Remember that beams DOES NOT include the current beam, only others
        crawlable = {}
        for joint in self.beam.joints:
            dist = helpers.distance(self.location, joint)

            # If we are at the joint, return the possible directions of other beams
            if helpers.compare(dist, 0):
                for beam in self.beam.joints[joint]:

                    # The index error should never happen, but this provides nice error
                    # support
                    try:
                        # Get endpoints of beam and find direction vector to those endpoints
                        e1, e2 = beam.endpoints
                        v1, v2 = helpers.make_vector(self.location,
                                                     e1), helpers.make_vector(
                                                         self.location, e2)

                        # We don't want to include zero-vectors
                        bool_v1, bool_v2 = (
                            not helpers.compare(helpers.length(v1), 0),
                            not helpers.compare(helpers.length(v2), 0))

                        # Checking for zero_vectors
                        if bool_v1 and bool_v2:
                            crawlable[beam.name] = ([
                                helpers.make_vector(self.location, e1),
                                helpers.make_vector(self.location, e2)
                            ])
                        elif bool_v1:
                            crawlable[beam.name] = [
                                helpers.make_vector(self.location, e1)
                            ]
                        elif bool_v2:
                            crawlable[beam.name] = [
                                helpers.make_vector(self.location, e2)
                            ]
                        else:
                            raise Exception(
                                "All distances from beam were zero-length.")

                        # Include distances to nearby joints (on the beam moving out from our
                        # current joint)
                        for coord in beam.joints:
                            # Direction vecotrs
                            v = helpers.make_vector(self.location, coord)
                            length = helpers.length(v)

                            # If further than our step, or zero, pass
                            if ((length < self.step
                                 or helpers.compare(length, self.step))
                                    and not helpers.compare(length, 0)):
                                try:
                                    # Only add if it is not already accounted for
                                    if v not in crawlable[beam.name]:
                                        crawlable[beam.name].append(v)
                                except IndexError:
                                    raise Exception(
                                        "Adding nearby joints failed because \
                    endpoints were ignored.")

                    except IndexError:
                        print(
                            "The beam {} seems to have a joint with {}, but it is not in\
              the box?".format(name, self.beam.name))

            # For all joints within the timestep, return a direction that is exactly
            # the change from current to that point.
            elif dist <= self.step:
                if self.beam.name in crawlable:
                    crawlable[self.beam.name].append(
                        helpers.make_vector(self.location, joint))
                else:
                    crawlable[self.beam.name] = [
                        helpers.make_vector(self.location, joint)
                    ]
            # The joint is too far, so no point in considering it as a walkable direction
            else:
                pass

        # The joints never include our own beam, so now add directions pertaining to
        # our own beam
        v1, v2 = (helpers.make_vector(self.location, self.beam.endpoints.i),
                  helpers.make_vector(self.location, self.beam.endpoints.j))

        # Check to make sure directions are non-zero
        b_v1 = not helpers.compare(helpers.length(v1), 0)
        b_v2 = not helpers.compare(helpers.length(v2), 0)

        # If we haven't already accounted for our beam
        if self.beam.name not in crawlable:
            # Add the non-zero directions
            if b_v1 and b_v2:
                crawlable[self.beam.name] = [v1, v2]
            elif b_v1:
                crawlable[self.beam.name] = [v1]
            elif b_v2:
                crawlable[self.beam.name] = [v2]

        # Add directions that might not have been entered by joints
        else:
            bool_v1, bool_v2 = True, True
            for direct in crawlable[self.beam.name]:
                # Don't add directions which are basically the same.
                if helpers.parallel(direct,
                                    v1) and helpers.dot(direct, v1) > 0:
                    bool_v1 = False
                if helpers.parallel(direct,
                                    v2) and helpers.dot(direct, v2) > 0:
                    bool_v2 = False

            # Add the non-zero non-parallel direction
            if bool_v2 and b_v2:
                crawlable[self.beam.name].append(v2)
            if bool_v1 and b_v1:
                crawlable[self.beam.name].append(v1)

        return crawlable
Ejemplo n.º 54
0
        def removeload(location):
            '''
      Removes the load assigned to a specific location based on where the robot 
      existed (assumes the robot is on a beams
      '''
            # Sanity check
            assert not self.model.GetModelIsLocked()

            # obtain current values.
            # values are encapsulated in a list as follows: ret, number_items,
            # frame_names, loadpat_names, types, coordinates, directions, rel_dists,
            # dists, loads
            data = self.model.FrameObj.GetLoadPoint(self.beam.name)

            # Sanity check with data
            assert data[0] == 0
            if data[1] == 0:
                helpers.check(1,
                              self,
                              "getting loads",
                              beam=self.beam.name,
                              return_data=data,
                              state=self.current_state())
                return

            # Find location of load
            i, j = self.beam.endpoints
            curr_dist = helpers.distance(i, self.location)

            # Loop through distances to find our load (the one in self.location) and
            # remove all reference to it. Additionally remove loads not related to our
            # load pattern
            indeces = []
            index = 0
            for ab_dist in data[
                    8]:  # this provides acces to the absolute_distance
                if ((helpers.compare(ab_dist, curr_dist)
                     and PROGRAM['robot_load_case'] == data[3][index])
                        or data[3][index] != PROGRAM['robot_load_case']):
                    indeces.append(index)
                index += 1

            # Delete the loads off the beam
            ret = self.model.FrameObj.DeleteLoadPoint(
                self.beam.name, PROGRAM['robot_load_case'])
            helpers.check(ret,
                          self,
                          "deleting loads",
                          return_val=ret,
                          beam=self.beam.name,
                          distance=curr_dist,
                          previous_loads=data,
                          state=self.current_state())

            # add the loads we want back to the frame (automatically deletes all
            # previous loads)
            for i in range(data[1]):
                if i not in indeces:
                    ret = self.model.FrameObj.SetLoadPoint(
                        self.beam.name, data[3][i], data[4][i], data[6][i],
                        data[7][i], data[9][i], "Global", True, False)
                    helpers.check(ret,
                                  self,
                                  "adding back loads",
                                  return_val=ret,
                                  beam=self.beam.name,
                                  load_pat=data[3][i],
                                  type=data[4][i],
                                  direction=data[6][i],
                                  rel_dist=data[7][i],
                                  load_val=data[9][i],
                                  state=self.current_state())
Ejemplo n.º 55
0
 def at_construction_site(self):
     return helpers.compare(
         helpers.distance(self.location, CONSTRUCTION['center']), 0)
Ejemplo n.º 56
0
    def wander(self):
        """    
    When a robot is not on a structure, it wanders. The wandering in the working
    class works as follows. The robot moves around randomly with the following 
    restrictions:
      The robot moves towards the home location if it has no beams and 
        the home location is detected nearby.
      Otherwise, if it has beams for construction, it moves toward the base 
      specified construction site. If it finds another beam nearby, it has a 
      tendency to climb that beam instead.
    """
        # Check to see if robot is at home location and has no beams
        if self.at_home() and self.num_beams == 0:
            self.pickup_beams()

        # If we have no beams, set the ground direction to home (TEMP CODE)
        if self.num_beams == 0:
            vector = helpers.make_vector(self.location, HOME["center"])
            self.ground_direction = (
                vector if not helpers.compare(helpers.length(vector), 0) else self.non_zero_xydirection()
            )

        # Find nearby beams to climb on
        result = self.ground()

        # Either there are no nearby beams, we are on repair_mode/search_mode, our beams are 0, or
        # we are constructing a support - so don't mess with direction
        if (
            result == None
            or self.repair_mode
            or self.search_mode
            or self.num_beams == 0
            or self.memory["construct_support"]
        ):
            direction = self.get_ground_direction()
            new_location = helpers.sum_vectors(self.location, helpers.scale(self.step, helpers.make_unit(direction)))
            self.change_location_local(new_location)

        # Nearby beam, jump on it
        else:
            dist, close_beam, direction = (result["distance"], result["beam"], result["direction"])
            # If the beam is within steping distance, just jump on it
            if self.num_beams > 0 and dist <= self.step:
                # Set the ground direction to None (so we walk randomly if we do get off
                # the beam again)
                self.ground_direction = None

                # Then move on the beam
                self.move(direction, close_beam)

            # If we can "detect" a beam, change the ground direction to approach it
            elif self.num_beams > 0 and dist <= ROBOT["local_radius"]:
                self.ground_direction = direction
                new_location = helpers.sum_vectors(
                    self.location, helpers.scale(self.step, helpers.make_unit(direction))
                )
                self.change_location_local(new_location)

            # Local beams, but could not detect (this is redundant)
            else:
                direction = self.get_ground_direction()
                new_location = helpers.sum_vectors(
                    self.location, helpers.scale(self.step, helpers.make_unit(direction))
                )
                self.change_location_local(new_location)
Ejemplo n.º 57
0
    def filter_feasable(self, dirs):
        """
    Filters the set of dirs passed in to check that the beam can support a robot
    + beam load if the robot were to walk in the specified direction to the
    very tip of the beam.
    This function is only ever called if an analysis model exists.

    Additionally, this function stores information on the beams that need to be 
    repaired. This is stored in self.memory['broken'], which is originally set
    to none.
    """
        # Sanity check
        assert self.model.GetModelIsLocked()

        results = {}
        # If at a joint, cycle through possible directions and check that the beams
        # meet the joint_limit. If they do, keep them. If not, discard them.
        if self.at_joint():

            # Cycle through directions
            for name, directions in dirs.items():

                # If the name is our beam and we can read moment from beams,
                # do a structural check instead of a joint check
                if ROBOT["read_beam"] and (
                    (self.beam.name == name and self.beam_check(name))
                    or (self.beam.name != name and self.joint_check(name))
                ):
                    results[name] = directions

                # Otherwise, do a joint_check for all beams
                elif self.joint_check(name):
                    results[name] = directions

                # It joint check failed, only keep down directions
                else:

                    # Keep only the directions that take us down
                    new_directions = [
                        direction for direction in directions if helpers.compare(direction[2], 0) or direction[2] < 0
                    ]
                    if len(new_directions) > 0:
                        results[name] = new_directions

                    # Add beam to broken
                    beam = self.structure.get_beam(name, self.location)
                    if not any(beam in broken for broken in self.memory["broken"]):
                        moment = self.get_moment(name)
                        self.memory["broken"].append((beam, moment))

        # Not at joint, and can read beam moments
        elif ROBOT["read_beam"]:

            # Sanity check (there should only be one beam in the set of directions if
            # We are not at a joint)
            assert len(dirs) == 1

            # Check beam
            if self.beam_check(self.beam.name):
                results = dirs

            # Add the beam to the broken
            else:

                # Keep only the directions that take us down
                for name, directions in dirs.items():
                    new_directions = [
                        direction for direction in directions if helpers.compare(direction[2], 0) or direction[2] < 0
                    ]
                    if len(new_directions) > 0:
                        results[name] = new_directions

                # Beam is not already in broken
                if not any(self.beam in broken for broken in self.memory["broken"]):
                    moment = self.get_moment(name)
                    self.memory["broken"].append((self.beam, moment))

        # We aren't reading beams, so we keep all the directions if not at a joint
        else:
            results = dirs

        return results