예제 #1
0
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        self.resolution = np.array([0.25, 0.25, 0.25])
        self.margin = 0.5

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.
        self.path = graph_search(world,
                                 self.resolution,
                                 self.margin,
                                 start,
                                 goal,
                                 astar=True)

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        self.points = np.zeros((1, 3))  # shape=(n_pts,3)

        # Finally, you must compute a trajectory through the waypoints similar
        # to your task in the first project. One possibility is to use the
        # WaypointTraj object you already wrote in the first project. However,
        # you probably need to improve it using techniques we have learned this
        # semester.

        # STUDENT CODE HERE
        self.world = world
        self.max_sparse_dist = 1  # 1.8
        self.max_speed = 2.3  # 2.5
        self.points = self.get_sparse_points(self.path)
        self.time_param = self.get_time_segment(self.points)
        self.coefficients = self.get_spline_coeff(self.points,
                                                  self.time_param[0])
예제 #2
0
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        self.resolution = np.array([0.25, 0.25, 0.25])
        self.margin = 0.25

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.
        self.graphpath = graph_search(world,
                                      self.resolution,
                                      self.margin,
                                      start,
                                      goal,
                                      astar=True)

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        # self.points = np.zeros((1,3)) # shape=(n_pts,3)
        self.Start = start
        self.Goal = goal
        self.points = self.graphpath
        self.path = self.graphpath
        self.path_length = float(
            round(np.sum(np.linalg.norm(np.diff(self.path, axis=0), axis=1)),
                  3))
        self.v_av = 2.0
        self.Time_list = self.get_time_list(self.v_av, self.path,
                                            self.path_length)
        self.K = self.get_coeff_5order(self.Time_list, self.path)
예제 #3
0
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        self.resolution = np.array([0.2, 0.2, 0.2])
        self.margin = 0.3

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.
        self.path = graph_search(world,
                                 self.resolution,
                                 self.margin,
                                 start,
                                 goal,
                                 astar=True)

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        self.points = np.zeros((1, 3))  # shape=(n_pts,3)
        # self.points = self.path

        self.points = np.array(self.path[0])
        for i in range(self.path.shape[0]):
            if i != 0 and i != (self.path.shape[0] - 1):
                segment_1 = (self.path[i] - self.path[i - 1])
                segment_2 = (self.path[i + 1] - self.path[i - 1])
                linear_segment = np.round(np.cross(segment_1, segment_2), 5)
                if np.array_equal(linear_segment, [0, 0, 0]):
                    pass
                else:
                    self.points = np.vstack((self.points, self.path[i]))
                    print('added point')

        self.points = np.vstack((self.points, self.path[-1]))
        print(self.points.shape)

        # Finally, you must compute a trajectory through the waypoints similar
        # to your task in the first project. One possibility is to use the
        # WaypointTraj object you already wrote in the first project. However,
        # you probably need to improve it using techniques we have learned this
        # semester.

        # STUDENT CODE HERE
        self.v = 2.5  # m/s
        self.t = np.zeros(len(self.points), )
        for i in range(len(self.t) - 1):
            self.t[(i + 1)] = np.linalg.norm(
                (self.points[(i + 1)] - self.points[i])) / self.v

        self.point_t = np.zeros(len(self.points), )
        for i in range(int(len(self.t) - 1)):
            self.point_t[(i + 1)] = self.point_t[i] + self.t[i + 1]

        # self.f = CubicSpline(self.point_t, self.points, axis=0)
        self.f = interp1d(self.point_t, self.points, axis=0)
예제 #4
0
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        self.resolution = np.array([0.125, 0.125, 0.125])
        self.margin = 0.3

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.
        self.path = graph_search(world,
                                 self.resolution,
                                 self.margin,
                                 start,
                                 goal,
                                 astar=True)

        #self.margin = 0.4

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        self.points = np.zeros((1, 3))  # shape=(n_pts,3)
        self.points = [self.path[0]]

        # loop through and check if points can be removed from path without issue
        path_index = 2
        point_index = 0

        # have 2 indexes, one for the looping through the path, the other for the points being kept
        while path_index < len(self.path):
            # check if there is a collision when you remove a point
            if world.path_collisions(
                    np.vstack(
                        (self.path[path_index], self.points[point_index])),
                    self.margin).size == 0:
                # if there isnt, check the next point
                path_index += 1
            else:
                # if there is add the point skipped to the kept points
                point_index += 1
                path_index += 1
                self.points.append(self.path[path_index - 1])
        # append the final point to the list
        self.points.append(self.path[-1])
        # Finally, you must compute a trajectory through the waypoints similar
        # to your task in the first project. One possibility is to use the
        # WaypointTraj object you already wrote in the first project. However,
        # you probably need to improve it using techniques we have learned this
        # semester.

        # STUDENT CODE HERE
        # Waypoint Traj is Bang Bang with non zero endpoint velocities based on a heuristic that is a function of the
        # angle between the lines
        self.traj = WaypointTraj(self.points)
예제 #5
0
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        # self.resolution = np.array([0.25, 0.25, 0.25])
        self.resolution = np.array([0.2, 0.2, 0.2])
        self.margin = 0.3

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.
        self.path = graph_search(world,
                                 self.resolution,
                                 self.margin,
                                 start,
                                 goal,
                                 astar=True)
        # print("origin length: {}".format(self.path.shape[0]))
        # remove unnecessary points:
        self.path = np.delete(self.path, 1, axis=0)
        # self.path = np.delete(self.path, 2, axis=0)
        self.path = np.delete(self.path, -2, axis=0)
        self.path = rm_inter_pt(self.path)
        # print("new length: {}".format(self.path.shape[0]))

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        # self.points = np.zeros((1,3)) # shape=(n_pts,3)
        self.points = np.delete(self.path, 1, axis=0)
        # self.path = np.delete(self.path, 2, axis=0)
        self.points = np.delete(self.path, -2, axis=0)
        self.points = rm_inter_pt(self.path)
        # Finally, you must compute a trajectory through the waypoints similar
        # to your task in the first project. One possibility is to use the
        # WaypointTraj object you already wrote in the first project. However,
        # you probably need to improve it using techniques we have learned this
        # semester.
        self.start = start
        self.goal = goal
        # STUDENT CODE HERE
        self.velo = 2.5
        self.T_finish = 0.0
        self.Length = 0.0
        self.new_range = 0
        self.traj_x, self.traj_y, self.traj_z, \
        self.velo_x, self.velo_y, self.velo_z, \
        self.acc_x, self.acc_y, self.acc_z, \
        self.jerk_x, self.jerk_y, self.jerk_z = self.get_traj()
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        # self.resolution = np.array([0.25, 0.25, 0.25])
        # self.margin = 0.5

        # for lab:
        self.resolution = np.array([0.125, 0.125, 0.125])
        self.margin = 0.3

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        # self.points = np.zeros((1,3)) # shape=(n_pts,3)
        self.path = graph_search(world,
                                 self.resolution,
                                 self.margin,
                                 start,
                                 goal,
                                 astar=True)
        print(self.path)
        exit()
        self.points = self.path.copy()

        # print('points:\n', self.points)
        print(type(self.points))
        print(self.points.shape)

        if np.array_equal(self.points[0, :], self.points[1, :]):
            self.points = np.delete(self.points, 1, 0)
        # ------------------------------------------------------------------------
        # p_curr1 = 0
        # p_curr2 = 1
        # p_check = 2
        # v_curr = (self.points[p_curr2, :] - self.points[p_curr1, :]) / np.sqrt((np.square(self.points[p_curr2, :] - self.points[p_curr1, :])).sum())
        # v_check = (self.points[p_check, :] - self.points[p_curr1, :]) / np.sqrt((np.square(self.points[p_check, :] - self.points[p_curr1, :])).sum())
        #
        # while True:
        #     if np.linalg.norm(v_check - v_curr) < 0.00001:
        #         self.points = np.delete(self.points, p_curr2, 0)
        #         if p_check == self.points.shape[0] - 1:
        #             break
        #     else:
        #         p_curr1 = p_check - 1
        #         p_curr2 = p_curr1 + 1
        #         p_check = p_curr2 + 1
        #         v_curr = (self.points[p_curr2, :] - self.points[p_curr1, :]) / np.sqrt(
        #             (np.square(self.points[p_curr2, :] - self.points[p_curr1, :])).sum())
        #         if p_check == self.points.shape[0] - 1:
        #             break
        #
        #     v_check = (self.points[p_check, :] - self.points[p_curr1, :]) / np.sqrt(
        #         (np.square(self.points[p_check, :] - self.points[p_curr1, :])).sum())
        #
        # print('new points:\n', self.points)
        # print(self.points.shape)
        # self.Ps = self.points
        # ------------------------------------------------------------------------
        ph = 0
        pch = 1
        i = 0
        while True:
            i += 1
            # print(i)
            pathtmp = np.vstack((self.points[ph, :], self.points[pch, :]))
            # flag = world.path_collisions(pathtmp, margin)
            # print(flag.shape)
            # print('flag:', flag)
            if world.path_collisions(pathtmp,
                                     self.margin + 0.05).shape[0] == 0:
                self.points = np.delete(self.points, pch, 0)
                # pch = pch + 1
            else:
                ph = pch
                pch = pch + 1
            if pch == self.points.shape[0] - 1:
                break

        print('after points:\n', self.points)
        self.Ps = self.points
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        self.resolution = np.array([0.25, 0.25, 0.25])
        self.margin = 0.5

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.
        self.path = graph_search(world,
                                 self.resolution,
                                 self.margin,
                                 start,
                                 goal,
                                 astar=True)

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        self.points = np.zeros((1, 3))  # shape=(n_pts,3)

        # Finally, you must compute a trajectory through the waypoints similar
        # to your task in the first project. One possibility is to use the
        # WaypointTraj object you already wrote in the first project. However,
        # you probably need to improve it using techniques we have learned this
        # semester.

        # STUDENT CODE HERE

        # trim the path into sparse waypoint combination
        n, d = self.path.shape
        path = self.path
        removeList = []
        for i in range(n - 2):
            if path[i + 2][0] - path[i + 1][0] == path[i + 1][0] - path[i][0] and path[i + 2][1] - path[i + 1][1] == \
                    path[i + 1][1] - path[i][1] and path[i + 2][2] - path[i + 1][2] == path[i + 1][2] - path[i][2]:
                removeList.append(i + 1)
        self.points = np.delete(path, removeList, axis=0)

        self.num_pt, d = self.points.shape
        self.maxVel = 2.57

        self.x_int_pt = self.points[0:self.num_pt - 1, 0]
        self.x_fin_pt = self.points[1:self.num_pt, 0]

        self.y_int_pt = self.points[0:self.num_pt - 1, 1]
        self.y_fin_pt = self.points[1:self.num_pt, 1]

        self.z_int_pt = self.points[0:self.num_pt - 1, 2]
        self.z_fin_pt = self.points[1:self.num_pt, 2]

        self.t_spend = []
        self.t_spend.append(0)

        # estimate time spent on each path
        for i in range(self.num_pt - 1):
            x_dist = np.abs(self.x_fin_pt[i] - self.x_int_pt[i])
            y_dist = np.abs(self.y_fin_pt[i] - self.y_int_pt[i])
            z_dist = np.abs(self.z_fin_pt[i] - self.z_int_pt[i])

            t_x = x_dist / self.maxVel
            t_y = y_dist / self.maxVel
            t_z = z_dist / self.maxVel

            t_max = np.max([t_x, t_y, t_z])
            self.t_spend.append(t_max + self.t_spend[-1])
예제 #8
0
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        self.resolution = np.array([0.25, 0.25, 0.25])
        self.margin = 0.5
        yita = 2.2
        #maze
        if np.array_equal(np.array(world.world['goal']),
                          np.array([9.0, 7.0, 1.5])):
            yita = 2.6
        #under over
        if np.array_equal(np.array(world.world['goal']),
                          np.array([19.0, 2.5, 5.5])):
            yita = 2.3
        #window
        if np.array_equal(np.array(world.world['goal']),
                          np.array([8.0, 18.0, 3.0])):
            yita = 2.55
        #if np.linalg.norm(np.array(world.world['goal'])-np.array(world.world['start']))>35:
        #yita = 2.5
        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.

        self.points = graph_search(world,
                                   self.resolution,
                                   self.margin,
                                   start,
                                   goal,
                                   astar=True)
        self.points = list(self.points)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        for point in range(len(self.points) - 1):
            if math.sqrt(sum(
                (self.points[point + 1] - self.points[point])**2)) > 3:
                self.points.insert(
                    point + 1,
                    (self.points[point + 1] + self.points[point]) / 2)
        self.points = np.array(self.points)
        print(self.points)
        # Finally, you must compute a trajectory through the waypoints similar
        # to your task in the first project. One possibility is to use the
        # WaypointTraj object you already wrote in the first project. However,
        # you probably need to improve it using techniques we have learned this
        # semester.

        # STUDENT CODE HERE

        m = len(self.points) - 1
        # the length of each segment
        segments_len = np.array([
            np.linalg.norm(self.points[i + 1] - self.points[i])
            for i in range(m)
        ])  #shape=(m,)
        # the time cost for each segment: [0:t0],[0,t1],..
        t = segments_len / yita  #shape= (m,)
        C = np.zeros((6 * m, 3))  #coefficients for x, y and z
        for j in range(3):  #x,y,z direction
            A = np.zeros((1, 6 * m))
            # position constraints: start & end constraint for each segment
            for i in range(m):
                start = np.zeros((1, 6 * m))
                start[0, 6 * i] = 1
                A = np.vstack((A, start))
                end = np.zeros((1, 6 * m))
                end[0, 6 * i:6 * (i + 1)] = np.array(
                    [1, t[i], t[i]**2, t[i]**3, t[i]**4, t[i]**5])
                A = np.vstack((A, end))
            #currently, A.shape=(2m,6m)
            #add derivative constraints: 2 for each inter-point: 2(m-1)
            for i in range(m - 1):
                #velocity continuity
                v = np.zeros((1, 6 * m))
                v[0, 6 * i:6 * (i + 1)] = np.array(
                    [0, 1, 2 * t[i], 3 * t[i]**2, 4 * t[i]**3, 5 * t[i]**4])
                v[0, 6 * (i + 1) + 1] = -1
                A = np.vstack((A, v))
                #acceleration continuity
                a = np.zeros((1, 6 * m))
                a[0, 6 * i:6 * (i + 1)] = np.array(
                    [0, 0, 2, 6 * t[i], 12 * t[i]**2, 20 * t[i]**3])
                a[0, 6 * (i + 1) + 2] = -2
                A = np.vstack((A, a))
                #add arbitrary constraints
                jerk = np.zeros((1, 6 * m))
                jerk[0, 6 * i:6 * (i + 1)] = np.array(
                    [0, 0, 0, 6, 24 * t[i], 60 * t[i]**2])
                jerk[0, 6 * (i + 1) + 3] = -6
                A = np.vstack((A, jerk))
                snap = np.zeros((1, 6 * m))
                snap[0, 6 * i:6 * (i + 1)] = np.array(
                    [0, 0, 0, 0, 24, 120 * t[i]])
                jerk[0, 6 * (i + 1) + 4] = -24
                A = np.vstack((A, snap))
            #add 4 derivative boundary conditions:
            start_v = np.zeros((1, 6 * m))
            start_v[0, 1] = 1
            A = np.vstack((A, start_v))
            start_a = np.zeros((1, 6 * m))
            start_a[0, 2] = 2
            A = np.vstack((A, start_a))
            end_v = np.zeros((1, 6 * m))
            end_v[0, 6 * (m - 1):6 * m] = np.array(
                [0, 1, 2 * t[-1], 3 * t[-1]**2, 4 * t[-1]**3, 5 * t[-1]**4])
            A = np.vstack((A, end_v))
            end_a = np.zeros((1, 6 * m))
            end_a[0, 6 * (m - 1):6 * m] = np.array(
                [0, 0, 2, 6 * t[-1], 12 * t[-1]**2, 20 * t[-1]**3])
            A = np.vstack((A, end_a))
            A = A[1:]
            b = np.zeros(6 * m)
            for i in range(m):
                b[2 * i:2 * (i + 1)] = np.array(
                    [self.points[i, j], self.points[i + 1, j]])
            #currently, A.shape = (4m+2,6m)
            #ge the matrix form of the quatratic function
            # H = np.zeros((6*m,6*m))
            # for i in range(m-1):
            #     a = 36*t[m,j]
            #     b_ = 24**2/3*t[m,j]**3
            #     c = 3600/5*t[m,j]**5
            #     d = 2*24*6/2*t[m,j]**2
            #     e = 2*60*6/3*t[m,j]**3
            #     f = 120*24/3*t[m,j]**3
            #     H[6*m+3:6*(m+1),6*m+3:6*(m+1)] = np.array([[a,d/2,e/2],[d/2,b_,f/2],[e/2,f/2,c]])
            # #CVXOPT
            # sol = solvers.qp(H,0,G=None,h=None,A=A,b=b)
            # C[:,j] = sol['x']
            # print('b.shape=',b.shape)
            C[:, j] = np.linalg.inv(A) @ b
        self.C = C
        self.m = m
        self.t = t
예제 #9
0
    def __init__(self, world, start, goal):
        """
        This is the constructor for the trajectory object. A fresh trajectory
        object will be constructed before each mission. For a world trajectory,
        the input arguments are start and end positions and a world object. You
        are free to choose the path taken in any way you like.

        You should initialize parameters and pre-compute values such as
        polynomial coefficients here.

        Parameters:
            world, World object representing the environment obstacles
            start, xyz position in meters, shape=(3,)
            goal,  xyz position in meters, shape=(3,)

        """

        # You must choose resolution and margin parameters to use for path
        # planning. In the previous project these were provided to you; now you
        # must chose them for yourself. Your may try these default values, but
        # you should experiment with them!
        self.resolution = np.array([0.2, 0.2, 0.2])
        self.margin = 0.4

        # You must store the dense path returned from your Dijkstra or AStar
        # graph search algorithm as an object member. You will need it for
        # debugging, it will be used when plotting results.
        self.path = graph_search(world,
                                 self.resolution,
                                 self.margin,
                                 start,
                                 goal,
                                 astar=True)

        # You must generate a sparse set of waypoints to fly between. Your
        # original Dijkstra or AStar path probably has too many points that are
        # too close together. Store these waypoints as a class member; you will
        # need it for debugging and it will be used when plotting results.
        self.points = np.zeros((1, 3))  # shape=(n_pts,3)
        self.points = self.path

        # Finally, you must compute a trajectory through the waypoints similar
        # to your task in the first project. One possibility is to use the
        # WaypointTraj object you already wrote in the first project. However,
        # you probably need to improve it using techniques we have learned this
        # semester.

        # STUDENT CODE HERE
        occ_map = OccupancyMap(world, self.resolution, self.margin)

        def check_collision(p1, p2):
            """
            This function check whether the connection of two waypoints collides with each other
            Args:
                p1: coordinates of point 1, a shape(3,) array
                p2: coordinates of point 2, a shape(3,) array
            Returns:
                1: The connection of two waypoint collide
                0: The connection of two waypoint does not collide
            """
            seg_length = 0.1
            distance = np.linalg.norm(p2 - p1)
            unit_vec = (p2 - p1) / distance
            segment = ceil(distance / seg_length)
            seg_length = distance / segment  # re-define the length of each segment

            # store segment points
            for i in range(1, segment):
                seg_point = p1 + i * seg_length * unit_vec
                seg_point_x = seg_point[0]
                seg_point_y = seg_point[1]
                seg_point_z = seg_point[2]
                seg_point = (seg_point_x, seg_point_y, seg_point_z)
                is_valid = occ_map.is_valid_metric(seg_point)
                is_occupied = occ_map.is_occupied_metric(seg_point)
                if is_valid and not (is_occupied):
                    bool_collide = 0
                else:
                    bool_collide = 1
                    break

            return bool_collide

        # optimize path
        check_point = start
        check_point_idx = 0
        check_goal = goal
        idx = len(self.path) - 1
        goal_idx = idx
        new_path = np.array([start])
        while not (check_point == goal).all():
            while check_collision(check_point,
                                  check_goal) and idx - check_point_idx > 1:
                idx = idx - 1
                check_goal = self.path[idx]
            check_point = check_goal
            check_point_idx = idx
            check_goal = goal
            idx = goal_idx
            new_path = np.r_[new_path, [check_point]]

        self.path = new_path

        # quint trajectory starts here
        self.pt = self.path  # type: np.array
        self.num_pts = len(self.pt)
        self.acc_mean = 3.8  # the mean acceleartion
        self.t_segment = [0]
        self.t_between_pt = []
        time_diff = 0
        for i in range(0, self.num_pts - 1):
            time_diff = 2 * np.sqrt(
                np.linalg.norm(self.pt[i + 1] - self.pt[i])) / self.acc_mean
            self.t_segment.append(
                time_diff + self.t_segment[i])  # time for waypoint to reach
            self.t_between_pt.append(
                time_diff)  # time different between two points

        tg = self.t_between_pt[-1]

        A = np.zeros((6 * (self.num_pts - 1), 6 * (self.num_pts - 1)))

        # boundary constrain
        A[0, 5] = 1
        A[1, 4] = 1
        A[2, 3] = 2

        A[-3, -6:] = np.array([tg**5, tg**4, tg**3, tg**2, tg, 1])
        A[-2, -6:] = np.array([5 * tg**4, 4 * tg**3, 3 * tg**2, 2 * tg, 1, 0])
        A[-1, -6:] = np.array([20 * tg**3, 12 * tg**2, 6 * tg, 2, 0, 0])

        # continuous constrain
        for i in range(self.num_pts - 2):
            tg = self.t_between_pt[i]

            # position constrain
            A[2 * i + 3, i * 6:(i + 1) * 6] = np.array(
                [tg**5, tg**4, tg**3, tg**2, tg, 1])
            A[2 * i + 4, (i + 2) * 6 - 1] = 1

            # velosity constrain
            A[3 + (self.num_pts - 2) * 2 + i, i * 6:(i + 1) * 6] = np.array(
                [5 * tg**4, 4 * tg**3, 3 * tg**2, 2 * tg, 1, 0])
            A[3 + (self.num_pts - 2) * 2 + i, (i + 2) * 6 - 2] = -1

            # acceleration constrain
            A[3 + (self.num_pts - 2) * 3 + i, i * 6:(i + 1) * 6] = np.array(
                [20 * tg**3, 12 * tg**2, 6 * tg, 2, 0, 0])
            A[3 + (self.num_pts - 2) * 3 + i, (i + 2) * 6 - 3] = -2

            # jerk constrain
            A[3 + (self.num_pts - 2) * 4 + i,
              i * 6:(i + 1) * 6] = np.array([60 * tg**2, 24 * tg, 6, 0, 0, 0])
            A[3 + (self.num_pts - 2) * 4 + i, (i + 2) * 6 - 4] = -6

            # snap constrain
            A[3 + (self.num_pts - 2) * 5 + i,
              i * 6:(i + 1) * 6] = np.array([120 * tg, 24, 0, 0, 0, 0])
            A[3 + (self.num_pts - 2) * 5 + i, (i + 2) * 6 - 5] = -24

        # P vector
        px = np.zeros((6 * (self.num_pts - 1), 1))
        py = np.zeros((6 * (self.num_pts - 1), 1))
        pz = np.zeros((6 * (self.num_pts - 1), 1))

        px[0, 0] = start[0]
        py[0, 0] = start[1]
        pz[0, 0] = start[2]

        px[-3, 0] = goal[0]
        py[-3, 0] = goal[1]
        pz[-3, 0] = goal[2]

        for i in range(self.num_pts - 2):
            px[2 * i + 3, 0] = new_path[i + 1, 0]
            px[2 * i + 4, 0] = new_path[i + 1, 0]

            py[2 * i + 3, 0] = new_path[i + 1, 1]
            py[2 * i + 4, 0] = new_path[i + 1, 1]

            pz[2 * i + 3, 0] = new_path[i + 1, 2]
            pz[2 * i + 4, 0] = new_path[i + 1, 2]

        self.Cx = np.linalg.inv(A) @ px
        self.Cy = np.linalg.inv(A) @ py
        self.Cz = np.linalg.inv(A) @ pz