Example #1
0
 def ball_angles(self, ball, angle):
     ''' Determines which angle to kick the ball along. '''
     htc = self.homothetic_centre(ball)
     tangent1, tangent2 = self.tangent_points(htc)
     target = self.position + self.size*angle_position(angle)
     if norm(tangent1 - target) < norm(tangent2 - target):
         return angle_between(htc, tangent1)
     else:
         return angle_between(htc, tangent2)
Example #2
0
 def decollide(self, other):
     ''' Shift overlapping entities apart. '''
     overlap = (self.size + other.size - self.distance(other))/2
     theta1 = angle_between(self.position, other.position)
     theta2 = angle_between(other.position, self.position)
     self.position += overlap * angle_position(theta2)
     other.position += overlap * angle_position(theta1)
     self.velocity *= -1
     other.velocity *= -1
Example #3
0
 def closestWall(self, pos, direction):
     # Find closest wall to an edge in the rectangle
     dists = torch.tensor([self.width, self.height]).reshape(2, 1) / 2 - pos.abs()
     min_dist, ax = dists.min(dim=0)
     signs = pos[ax, torch.arange(pos.shape[1])] > 0
     angle = (3 - 2 * signs.float()) * pi / 2 - (1 - ax.float()) * pi / 2
     return min_dist, angle_between(direction, unit_vector(angle))
Example #4
0
def update_xz_rocket(n_intervals):
    data_query = Data.query
    try:
        df = pd.read_sql(data_query.statement, data_query.session.bind)
        x = float(df[df['title'] == 'X'].iloc[-1]['data_v'])
        y = float(df[df['title'] == 'Y'].iloc[-1]['data_v'])
        z = float(df[df['title'] == 'Z'].iloc[-1]['data_v'])
        angle_x = angle_between((1, 0), (z, x))
        angle_y = angle_between((1, 0), (z, y))
        if angle_x > angle_y:
            angle = angle_x
        else:
            angle = angle_y
        return orientation.get_style(angle)
    except:
        return orientation.get_style(0)
Example #5
0
 def control_update(self):
     ''' Uses input from the keyboard to control the player. '''
     keys_pressed = pygame.key.get_pressed()
     mousex, mousey = pygame.mouse.get_pos()
     mousex = mousex / SCALE_FACTOR
     mousey = mousey / SCALE_FACTOR - PITCH_WIDTH/2
     position = vector(mousex, mousey)
     theta = angle_between(self.simulator.player.position, position)
     action_map = {
         pygame.K_SPACE: ('kick', (100, theta)),
         pygame.K_w: ('dash', (10,)),
         pygame.K_s: ('dash', (-10,)),
         pygame.K_a: ('turn', (np.pi/32,)),
         pygame.K_d: ('turn', (-np.pi/32,)),
         pygame.K_b: ('toball', None),
         pygame.K_g: ('shootgoal', (mousey,)),
         pygame.K_t: ('turnball', (theta,)),
         pygame.K_p: ('dribble', position),
         pygame.K_k: ('kickto', position)
     }
     action = None
     for key in action_map:
         if keys_pressed[key]:
             action = action_map[key]
             break
     reward, end_episode = self.simulator.update(action)
     if end_episode:
         if reward == 50:
             print "GOAL"
         else:
             print "OUT"
         self.simulator = Simulator()
Example #6
0
 def take_action(self, action):
     ''' Take a full, stabilised update. '''
     steps = 0
     self.time += 1
     if self.time == 100:
         reward = - self.ball.goal_distance()
         end_episode = True
         state = self.get_state()
         return state, reward, end_episode, steps
     end_episode = False
     run = True
     while run:
         steps += 1
         reward, end_episode = self.update(action)
         run = not end_episode
         if action and run:
             act, params = action
             run = not self.player.can_kick(self.ball)
             if act == "dribble":
                 run = not self.ball.close_to(params) or run
             elif act == "kickto":
                 run = norm(self.ball.velocity) > 0.1 or run
             elif act == "turnball":
                 theta = angle_between(self.player.position, self.ball.position)
                 run = not angle_close(theta, params[0]) or run
             elif act == "shootgoal":
                 run = not end_episode
             else:
                 run = False
     state = self.get_state()
     return state, reward, end_episode, steps
Example #7
0
 def dribble(self, ball, target):
     ''' Dribble the ball to a position. '''
     angle = angle_between(self.position, ball.position)
     theta = angle_between(self.position, target)
     if not self.can_kick(ball):
         self.to_ball(ball)
     elif ball.close_to(target):
         pass
     elif not angle_close(angle, theta):
         self.turn_ball(ball, theta)
     elif not self.facing_angle(theta):
         self.face_angle(theta)
     elif self.distance(ball) < (KICKABLE + self.size + ball.size)/2:
         self.kick_towards(ball, 1.5, theta)
     else:
         self.dash(10)
Example #8
0
    def __init__(self):
        ''' The entities are set up and added to a space. '''
        initial_player = vector(0, uniform(-PITCH_WIDTH/2, PITCH_WIDTH/2))
        angle = angle_between(initial_player, vector(PITCH_LENGTH/2, 0))
        self.player = Player(initial_player, angle)

        initial_ball = initial_player + KICKABLE * angle_position(angle)
        self.ball = Ball(initial_ball)

        initial_goalie = keeper_target(initial_ball)
        angle2 = angle_between(initial_goalie, initial_ball)
        self.goalie = Goalie(initial_goalie, angle2)

        self.entities = [self.player, self.goalie, self.ball]
        self.states = []

        self.time = 0
Example #9
0
    def move(self, ball, player):
        ''' This moves the goalie. '''
        ball_end = ball.position + ball.velocity / (1 - ball.decay)
        diff = ball_end - ball.position
        grad = diff[1] / diff[0]
        yint = ball.position[1] - grad * ball.position[0]
        goal_y = grad * PITCH_LENGTH/2 + yint
        if ball_end[0] > PITCH_LENGTH/2 and -GOAL_WIDTH/2 - CATCHABLE <= goal_y <= GOAL_WIDTH/2 + CATCHABLE and grad != 0:
	    grad2 = -1/grad
	    yint2 = self.position[1] - grad2 * self.position[0]
	    ballx = (yint2 - yint) / (grad - grad2)
	    bally = grad * ballx + yint
	    target = vector(ballx, bally)
	    self.move_towards(20, target)
            self.orientation = angle_between(self.position, target)
        else:
            self.orientation = angle_between(self.position, ball_end)
            self.move_towards(8, ball_end)
Example #10
0
    def closestWall(self, position, direction):
        # closest wall on a circle lies on a line through the origin
        theta = torch.atan2(position[1], position[0]).float()
        wall = self.radius * unit_vector(theta)

        min_dist = torch.norm(wall.abs() - position.abs(), p=2, dim=0)

        angle = angle_between(position, direction)
        return min_dist, angle
Example #11
0
def wear_glasses(image, glasses, face_num, landmark4):
    for i in range(face_num):
        landmark = landmark4[i]
        lmk0 = np.array(landmark[0])  # right eye center
        lmk1 = np.array(landmark[1])  # left eye center
        # for j in range(len(landmark))[:2]:
        #     cv2.circle(image, (landmark[j][0], landmark[j][1]), 1, (0, 255, 0), 2)

        glasses_center = np.mean([lmk0, lmk1],
                                 axis=0)  # put glasses's center to this center
        glasses_size = np.linalg.norm(lmk0 -
                                      lmk1) * 2  # the width of glasses mask
        angle = -util.angle_between(lmk0, lmk1)

        glasses_h, glasses_w = glasses.shape[:2]
        glasses_c = (glasses_w / 2, glasses_h / 2)
        M = cv2.getRotationMatrix2D(glasses_c, angle, 1)
        cos = np.abs(M[0, 0])
        sin = np.abs(M[0, 1])

        # compute the new bounding dimensions of the image
        nW = int((glasses_h * sin) + (glasses_w * cos))
        nH = int((glasses_h * cos) + (glasses_w * sin))

        # adjust the rotation matrix to take into account translation
        M[0, 2] += (nW / 2) - glasses_c[0]
        M[1, 2] += (nH / 2) - glasses_c[1]

        rotated_glasses = cv2.warpAffine(glasses, M, (nW, nH))
        # cv2.imwrite("blog/images/rotate_glasses.png", rotated_glasses)
        try:
            image = util.overlay_transparent(
                image,
                rotated_glasses,
                glasses_center[0],
                glasses_center[1],
                overlay_size=(int(glasses_size),
                              int(rotated_glasses.shape[0] * glasses_size /
                                  rotated_glasses.shape[1])))
        except:
            print('failed overlay image')
    return image
Example #12
0
    def __init__(self, nissl_level, matches, ransac_results, extra_data):
        self.nissl_level = nissl_level
        self.matches = matches
        self.ransac_results = ransac_results
        self.extra_data = extra_data

        # Ransac Result Parsing
        self.H = ransac_results['homography']
        self.inlier_count = ransac_results['inlier_count']
        self.metric = ransac_results['metric']
        self.homography_det = np.linalg.det(self.H)
        self.cond_num = np.linalg.cond(self.H)

        # Variable Parsing
        self.matches_count = len(matches)
        self.inlier_ratio = self.inlier_count / self.matches_count * 100

        # Extra Data Parsing
        self.im_results = extra_data['images']
        self.is_convex = extra_data['is_convex']

        # Linear Combination Vectors
        self.vec1 = self.H[0][0:2]
        self.vec2 = self.H[1][0:2]

        self.vec1_mag = np.linalg.norm(self.vec1)
        self.vec2_mag = np.linalg.norm(self.vec2)
        self.angle = np.rad2deg(util.angle_between(self.vec1, self.vec2))

        self.vec_arr = np.array([[self.H[0][0], self.H[0][1]],
                                 [self.H[1][0], self.H[1][1]]])
        self.vec_arr_cond = np.linalg.cond(self.vec_arr)

        # Linear combination
        self.a0 = (self.inlier_count / 1000)
        self.a1 = (self.inlier_count / self.matches_count)
        self.a2 = min(self.vec1_mag / self.vec2_mag,
                      self.vec2_mag / self.vec1_mag)
        self.a3 = np.abs(np.sin(self.angle))
        self.linear = ransac_results['metric']
Example #13
0
 def kick_power(self, ball):
     ''' Determines the kick power weighting given ball position. '''
     angle = angle_between(self.position, ball.position)
     dir_diff = abs(angle_difference(angle, self.orientation))
     dist = self.distance(ball)
     return (1 - 0.25*dir_diff/np.pi - 0.25*dist/KICKABLE)
Example #14
0
 def move_towards(self, power, target):
     ''' Move towards target position. '''
     theta = angle_between(self.position, target)
     self.accelerate(power, theta)
Example #15
0
 def face_ball(self, ball):
     ''' Turn the player towards the ball. '''
     theta = angle_between(self.position, ball.position)
     self.face_angle(theta)
Example #16
0
 def facing_ball(self, ball):
     ''' Determines whether the player is facing the ball. '''
     angle = angle_between(self.position, ball.position)
     return self.facing_angle(angle)
def hinge_energy(input_vector, trimesh, gradient_mode, NUM_VERTS):
    """
    The covariance energy for minimizing Gaussian
    curvature and its gradient

    Its expected that you curry this method into a function
    of a single variable `input_vector` to make it optimizable
    see `hinge_energy_and_grad`
    
    input_vector: a 1D array representing a flattened list
    of positions

    trimesh: a TriMesh object (see local trimesh.py) containing
    all the immutable topology of the mesh. This object
    can be muted with updated vertices and used to recompute
    normals and areas.
    
    gradient_mode sets the return value and gates gradient computation:
      0: return energy
      1: return grad
      2: return (energy, grad)

    NUM_VERTS: how many vertices are in the mesh total
    """
    assert_shape(input_vector, (NUM_VERTS * 3, ))

    # reshape input vector into a list of points
    verts = input_vector.reshape(NUM_VERTS, 3)

    # mutate the trimesh w/ the new verts
    # and update the normals and areas (
    # these are the non-topological properties
    # that change w/ vertices)
    trimesh.vs = verts
    trimesh.update_face_normals_and_areas()
    face_areas = trimesh.get_face_areas()
    face_normals = trimesh.get_face_normals()

    energy = []

    jacobian = np.zeros((NUM_VERTS, 3))

    # for every vertex compute an energy
    for v_index in range(0, len(verts)):

        normal_covariance_matrix = np.zeros((3, 3))

        # for every face touching our vertex (vertex star)
        for f_index in trimesh.vertex_face_neighbors(v_index):
            face = trimesh.faces[f_index]

            # get the indices of the face in proper ijk
            # order where is is the center of the vertex star
            fi_index = v_index
            fj_index, fk_index = [j for j in face if fi_index != j]

            fi = verts[fi_index]
            fj = verts[fj_index]
            fk = verts[fk_index]

            # theta is the angle of the corner
            # of the face at a
            eij = np.subtract(fj, fi)
            eik = np.subtract(fk, fi)
            theta = util.angle_between(eij, eik)

            # the normal of the face
            N = face_normals[f_index]

            # NN^T gives us a 3x3 covariance matrix
            # of the vector. Scale it by Theta
            # and add it to the running covariance matrix
            # being built up for every normal
            normal_covariance_matrix += theta * np.outer(N, N)

        # now you have the covariance matrix for every face
        # normal surrounding this vertex star.
        # the first eigenvalue of this matrix is our energy
        #
        #
        # ``` (eq 4)
        # Since Equation 3 is just the
        # variational form of an eigenvalue problem, λi can also be expressed
        # as the smallest eigenvalue of the 3 × 3 normal covariance matrix
        # ```
        eigenvalues, eigenvectors = \
            eigendecomp(normal_covariance_matrix)

        smallest_eigenvalue = eigenvalues[0]
        associated_eigenvector = eigenvectors[:, 0]

        # the first eigenvalue is the smallest one
        energy.append(smallest_eigenvalue)

        # start computing the gradient if it's needed
        if gradient_mode == 1 or gradient_mode == 2:

            x = associated_eigenvector

            # for every face touching our vertex (vertex star)
            for f_index in trimesh.vertex_face_neighbors(v_index):
                face = trimesh.faces[f_index]

                # fi is v
                fi_index = v_index
                fj_index, fk_index = [j for j in face if fi_index != j]

                # the three vertices of the current face
                fi = verts[fi_index]
                fj = verts[fj_index]
                fk = verts[fk_index]

                # theta is the angle of the corner
                # of the face at fi
                eij = np.subtract(fj, fi)
                eik = np.subtract(fk, fi)
                theta = util.angle_between(eij, eik)

                # the face normal
                N = face_normals[f_index]

                # scalar, double the area
                A = face_areas[f_index] * 2

                # oriented edges
                ejk = np.subtract(fk, fj)
                eki = np.subtract(fi, fk)
                eij = np.subtract(fj, fi)
                assert_shape(ejk, (3, ))

                # derivatives of the normal
                dNdi = np.outer(np.cross(ejk, N), N) / A
                dNdj = np.outer(np.cross(eki, N), N) / A
                dNdk = np.outer(np.cross(eij, N), N) / A
                assert_shape(dNdi, (3, 3))

                # derivatives of the angle
                dThetadj = -1 * np.cross(N, eij / norm(eij))
                dThetadk = -1 * np.cross(N, eki / norm(eki))
                dThetadi = np.cross(N, eij + eki)
                assert_shape(dThetadj, (3, ))

                xdotN = x.dot(N)
                assert_shape(xdotN, ())

                # a 3 vector pointing in the directly the i vertex should move
                jacobian[
                    fi_index] += xdotN * xdotN * dThetadi + 2 * theta * xdotN * x.dot(
                        dNdi)
                jacobian[
                    fj_index] += xdotN * xdotN * dThetadj + 2 * theta * xdotN * x.dot(
                        dNdj)
                jacobian[
                    fk_index] += xdotN * xdotN * dThetadk + 2 * theta * xdotN * x.dot(
                        dNdk)

    # squared sum of the energies is our final cost value
    K = np.sum(energy)**2

    # return energy, gradient or both
    if gradient_mode == 0:
        return K
    elif gradient_mode == 1:
        return jacobian.reshape(NUM_VERTS * 3)
    elif gradient_mode == 2:
        return (K, jacobian.reshape(NUM_VERTS * 3))
Example #18
0
def calc_angles(kick, pos_0, pos_1, angles_0, angles_1, vel_0, bounding_box, valid, fish_mapping, verbose=False):
    """Extracts features for a single kick and some timesteps before."""
    x_axis = np.array([1, 0]) # Used as a common reference for angles.
    dts = np.arange(start=0, stop=40, step=5)

    start, end, duration, gliding_duration = kick
    start, end = int(start), int(end)
    gliding_start = end - int(gliding_duration*100)

    # Check if we have enough information about the past.
    if start - dts[-1] < 0:
        return None

    # Discard entire kick if it would use information from invalid frames.
    if not np.all(valid[start-dts[-1]:end+1]):
        return None

    kick_information = None
    rows = []
    for dt in dts:
        pos_f0 = np.array([ pos_0[0][start - dt], pos_0[1][start - dt] ])
        pos_f1 = np.array([ pos_1[0][start - dt], pos_1[1][start - dt] ])

        # Kick information:
        # Extract this only for dt = 0.
        # Otherwise reuse same value - not tidy, but makes analysis easier.
        # These are the statistics about the kick itself.
        if dt == 0:
            traj_kick = np.array([ pos_0[0][end], pos_0[1][end] ]) - pos_f0
            kick_len = np.linalg.norm(traj_kick)
            kick_max_vel = np.max(vel_0[start:end])
            end_vel = vel_0[end]
            heading_change = sub_angles(angles_0[end], angles_0[start])
            heading_change_acc = sub_angles(angles_0[gliding_start], angles_0[start])

            kick_information = np.array( [ fish_mapping[0], heading_change, heading_change_acc, duration, gliding_duration, kick_len, kick_max_vel, end_vel] )

        if not valid[start - dt]:
            return None

        # Social information:
        # Vector connecting both fish, note that it is directed!
        dist = pos_f1 - pos_f0
        dist_norm = np.linalg.norm(dist)
        dist_angle = angle_between(x_axis, dist)

        # Calculate relevant angles. Note that the viewing angle is NOT symmetric.
        viewing_angle_0t1 = sub_angles(dist_angle, angles_0[start - dt])
        viewing_angle_1t0 = sub_angles(-dist_angle, angles_1[start - dt])

        # The focal fish is defined as the geometric leader, i.e. the fish with the larger viewing angle.
        # Corresponds to the fish which would need to turn more to look directly at the other fish.
        # The sign of the relative orientation depends on which fish is the focal one.
        if np.abs(viewing_angle_0t1) > np.abs(viewing_angle_1t0):
            geometric_leader = fish_mapping[0]
            rel_orientation = sub_angles(angles_1[start - dt], angles_0[start - dt])
            viewing_angle_leader, viewing_angle_follower = viewing_angle_0t1, viewing_angle_1t0
        else:
            geometric_leader = fish_mapping[1]
            rel_orientation = sub_angles(angles_0[start - dt], angles_1[start - dt])
            viewing_angle_leader, viewing_angle_follower = viewing_angle_1t0, viewing_angle_0t1

        # Receptive field model needs positions and angles of both fish
        rf_information = np.hstack((pos_f0, pos_f1, np.array([angles_0[start - dt], angles_1[start - dt]])))   

        social_information = np.array([ dist_norm, dist_angle, geometric_leader, viewing_angle_leader, viewing_angle_follower, rel_orientation ])
        social_information = np.hstack((social_information, rf_information))

        # Estimate wall information.
        wall_distance_0, wall_angle_0 = get_wall_influence(angles_0[start - dt], pos_f0, bounding_box)
        wall_distance_1, wall_angle_1 = get_wall_influence(angles_1[start - dt], pos_f1, bounding_box)

        wall_information = np.concatenate( (wall_distance_0, wall_angle_0, wall_distance_1, wall_angle_1) )

        row = np.concatenate(([dt], kick_information, social_information, wall_information))
        rows.append(row)

    return np.array(rows)