Exemple #1
0
    def expand_wpts(self):
        n = 5 # number of pts per orig pt
        dz = 1 / n
        o_line = self.waypoints[:, 0:2]
        # o_ss = self.ss
        o_vs = self.waypoints[:, 2]
        new_line = []
        # new_ss = []
        new_vs = []
        for i in range(len(self.waypoints)-1):
            dd = lib.sub_locations(o_line[i+1], o_line[i])
            for j in range(n):
                pt = lib.add_locations(o_line[i], dd, dz*j)
                new_line.append(pt)

                # ds = o_ss[i+1] - o_ss[i]
                # new_ss.append(o_ss[i] + dz*j*ds)

                dv = o_vs[i+1] - o_vs[i]
                new_vs.append(o_vs[i] + dv * j * dz)

        wpts = np.array(new_line)
        # self.ss = np.array(new_ss)
        vs = np.array(new_vs)
        self.waypoints = np.concatenate([wpts, vs[:, None]], axis=-1)
Exemple #2
0
 def print_update(self, plot_reward=True):
     if self.reward_ptr < 5:
         return
     mean = np.mean(self.ep_rewards[max(0, self.reward_ptr-101):self.reward_ptr-1])
     print(f"Run: {self.step_counter} --> 100 ep Mean: {mean:.2f}  ")
     
     if plot_reward:
         lib.plot(self.ep_rewards[0:self.reward_ptr], 20, figure_n=2)
Exemple #3
0
def convert_pts_s_th(pts):
    N = len(pts)
    s_i = np.zeros(N - 1)
    th_i = np.zeros(N - 1)
    for i in range(N - 1):
        s_i[i] = lib.get_distance(pts[i], pts[i + 1])
        th_i[i] = lib.get_bearing(pts[i], pts[i + 1])

    return s_i, th_i
    def print_update(self, plot_reward=True):
        if self.ptr < 5:
            return
        mean = np.mean(self.rewards[0:self.ptr])
        score = self.rewards[-1]
        print(
            f"Run: {self.t_counter} --> Score: {score:.2f} --> Mean: {mean:.2f}  "
        )

        if plot_reward:
            lib.plot(self.rewards[0:self.ptr], figure_n=2)
    def expand_wpts(self):
        n = 5  # number of pts per orig pt
        dz = 1 / n
        o_line = self.wpts
        new_line = []
        for i in range(len(self.wpts) - 1):
            dd = lib.sub_locations(o_line[i + 1], o_line[i])
            for j in range(n):
                pt = lib.add_locations(o_line[i], dd, dz * j)
                new_line.append(pt)

        self.wpts = np.array(new_line)
Exemple #6
0
    def get_target_obs(self):
        target = self.env_map.end_goal
        pos = np.array([self.car.x, self.car.y])
        base_angle = lib.get_bearing(pos, target)
        # angle = base_angle - self.car.theta
        angle = lib.sub_angles_complex(base_angle, self.car.theta)
        # angle = lib.add_angles_complex(base_angle, self.car.theta)
        # distance = lib.get_distance(pos, target)

        em = self.env_map
        s = calculate_progress(pos, em.ref_pts, em.diffs, em.l2s, em.ss_normal)

        return [angle, s]
Exemple #7
0
    def check_done_reward_track_train(self):
        """
        Checks if the race lap is complete

        Returns
            Done flag
        """
        self.reward = 0  # normal
        if self.env_map.check_scan_location([self.car.x, self.car.y]):
            self.done = True
            self.colission = True
            self.reward = -1
            self.done_reason = f"Crash obstacle: [{self.car.x:.2f}, {self.car.y:.2f}]"
        # horizontal_force = self.car.mass * self.car.th_dot * self.car.velocity
        # self.y_forces.append(horizontal_force)
        # if horizontal_force > self.car.max_friction_force:
        # self.done = True
        # self.reward = -1
        # self.done_reason = f"Friction limit reached: {horizontal_force} > {self.car.max_friction_force}"
        if self.steps > self.max_steps:
            self.done = True
            self.done_reason = f"Max steps"

        car = [self.car.x, self.car.y]
        cur_end_dis = lib.get_distance(car, self.env_map.start_pose[0:2])
        if cur_end_dis < self.end_distance and self.steps > 800:
            self.done = True
            self.reward = 1
            self.done_reason = f"Lap complete, d: {cur_end_dis}"

        return self.done
Exemple #8
0
    def update_kinematic_state(self, a, d_dot, dt):
        """
        Updates the internal state of the vehicle according to the kinematic equations for a bicycle model

        Args:
            a: acceleration
            d_dot: rate of change of steering angle
            dt: timestep in seconds

        """
        self.x = self.x + self.velocity * np.sin(self.theta) * dt
        self.y = self.y + self.velocity * np.cos(self.theta) * dt
        theta_dot = self.velocity / self.wheelbase * np.tan(self.steering)
        self.th_dot = theta_dot
        dth = theta_dot * dt
        self.theta = lib.add_angles_complex(self.theta, dth)

        a = np.clip(a, -self.max_a, self.max_a)
        d_dot = np.clip(d_dot, -self.max_d_dot, self.max_d_dot)

        self.steering = self.steering + d_dot * dt
        self.velocity = self.velocity + a * dt

        self.steering = np.clip(self.steering, -self.max_steer, self.max_steer)
        self.velocity = np.clip(self.velocity, -self.max_v, self.max_v)
Exemple #9
0
    def expand_wpts(self):
        n = 5  # number of pts per orig pt
        dz = 1 / n
        o_line = self.waypoints
        o_vs = self.vs
        new_line = []
        new_vs = []
        for i in range(len(o_line) - 1):
            dd = lib.sub_locations(o_line[i + 1], o_line[i])
            for j in range(n):
                pt = lib.add_locations(o_line[i], dd, dz * j)
                new_line.append(pt)

                dv = o_vs[i + 1] - o_vs[i]
                new_vs.append(o_vs[i] + dv * j * dz)

        self.waypoints = np.array(new_line)
        self.vs = np.array(new_vs)
Exemple #10
0
    def transform_obs(self, obs):
        observation = obs['state']
        cur_v = [observation[3]/self.max_v]
        cur_d = [observation[4]/self.max_steer]
        angle = [lib.get_bearing(observation[0:2], [1, 21])/self.max_steer]
        scan = np.array(obs['scan']) / self.range_finder_scale

        nn_obs = np.concatenate([cur_v, cur_d, angle, scan])

        return nn_obs
    def add_obstacles(self):
        obs_img = np.zeros_like(self.obs_img)
        obs_size_m = np.array([self.obs_size, self.obs_size])
        obs_size_px = obs_size_m / self.resolution

        rands = np.random.uniform(size=(self.n_obs, 2))
        idx_rands = rands[:, 0] * len(self.ws)
        w_rands = (rands[:, 1] * 2 - np.ones_like(rands[:, 1]))
        w_rands = w_rands * np.mean(
            self.ws
        ) * 0.3  # x average length, adjusted to be both sides of track
        # magic 0.8 is to keep the obstacles closer to the center of the track

        obs_locations = []
        for i in range(self.n_obs):
            idx = idx_rands[i]
            w = w_rands[i]

            int_idx = int(idx)  # note that int always rounds down

            # start with using just int_idx
            n = self.nvecs[i]
            offset = np.array([n[0] * w, n[1] * w])
            location = lib.add_locations(self.t_pts[int_idx], offset)
            if lib.get_distance(location, self.start_pose[0:2]) < 1:
                continue
            # location = np.flip(location)
            # location = self.t_pts[int_idx]
            rc_location = self.xy_to_row_column(location)
            location = np.array(location, dtype=int)
            obs_locations.append(rc_location)

        obs_locations = np.array(obs_locations)
        for location in obs_locations:
            x, y = location[0], location[1]
            for i in range(0, int(obs_size_px[0])):
                for j in range(0, int(obs_size_px[1])):
                    if x + i < self.map_width and y + j < self.map_height:
                        # obs_img[x+i, y+j] = 255
                        obs_img[y + j, x + i] = 255

        self.obs_img = obs_img
Exemple #12
0
    def __init__(self, map_name, sim_conf=None):
        """
        Init function

        Args:
            map_name: name of forest map to use.
            sim_conf: config file for simulation
        """
        if sim_conf is None:
            path = os.path.dirname(__file__)
            sim_conf = lib.load_conf(path, "std_config")

        env_map = ForestMap(map_name)
        BaseSim.__init__(self, env_map, self.check_done_forest, sim_conf)
Exemple #13
0
    def __init__(self, map_name, sim_conf=None):
        """
        Init function

        Args:
            map_name: name of map to use.
            sim_conf: config file for simulation

        """
        if sim_conf is None:
            path = os.path.dirname(__file__)
            sim_conf = lib.load_conf(path, "std_config")

        env_map = TrackMap(map_name)
        BaseSim.__init__(self, env_map, self.check_done_reward_track_train,
                         sim_conf)
        self.end_distance = sim_conf.end_distance
Exemple #14
0
def find_true_widths(pts, nvecs, ws, check_scan_location):
    tx = pts[:, 0]
    ty = pts[:, 1]
    onws = ws[:, 0]
    opws = ws[:, 1]

    stp_sze = 0.1
    sf = 0.5  # safety factor
    N = len(pts)
    nws, pws = [], []
    for i in range(N):
        pt = [tx[i], ty[i]]
        nvec = nvecs[i]

        if not check_scan_location(pt):
            j = stp_sze
            s_pt = lib.add_locations(pt, nvec, j)
            while not check_scan_location(s_pt) and j < opws[i]:
                j += stp_sze
                s_pt = lib.add_locations(pt, nvec, j)
            pws.append(j * sf)

            j = stp_sze
            s_pt = lib.sub_locations(pt, nvec, j)
            while not check_scan_location(s_pt) and j < onws[i]:
                j += stp_sze
                s_pt = lib.sub_locations(pt, nvec, j)
            nws.append(j * sf)
            # print(f"Pt added without being adjusted")
        else:
            print(f"Obs in way of pt: {i}")

            for j in np.linspace(0, onws[i], 10):
                p_pt = lib.add_locations(pt, nvec, j)
                n_pt = lib.sub_locations(pt, nvec, j)
                if not check_scan_location(p_pt):
                    nws.append(-j * (1 + sf))
                    pws.append(opws[i])
                    print(f"PosPt NewW: [{-j*(1+sf)}, {opws[i]}]")
                    break
                elif not check_scan_location(n_pt):
                    pws.append(-j * (1 + sf))
                    nws.append(onws[i])
                    print(f"PosPt NewW: [{-j*(1+sf)}, {onws[i]}]")
                    break
                if j == onws[i]:
                    print(f"Problem - no space found")

    nws, pws = np.array(nws), np.array(pws)
    ws = np.concatenate([nws[:, None], pws[:, None]], axis=-1)

    return ws
Exemple #15
0
    def transform_obs(self, obs, pp_action):
        """
        Transforms the observation received from the environment into a vector which can be used with a neural network.
    
        Args:
            obs: observation from env
            pp_action: [steer, speed] from pure pursuit controller

        Returns:
            nn_obs: observation vector for neural network
        """
        state = obs['state']
        cur_v = [state[3] / self.max_v]
        cur_d = [state[4] / self.max_steer]
        # vr_scale = [(pp_action[1])/self.max_v]
        angle = [lib.get_bearing(state[0:2], [1, 21]) / self.max_steer]
        dr_scale = [pp_action[0] / self.max_steer]

        scan = np.array(obs['scan']) / self.range_finder_scale

        nn_obs = np.concatenate([cur_v, cur_d, dr_scale, angle, scan])

        return nn_obs
Exemple #16
0
    def min_render(self, wait=False):
        """
        TODO: deprecate
        """
        fig = plt.figure(4)
        plt.clf()

        ret_map = self.env_map.scan_map
        plt.imshow(ret_map)

        # plt.xlim([0, self.env_map.width])
        # plt.ylim([0, self.env_map.height])

        s_x, s_y = self.env_map.convert_to_plot(self.env_map.start)
        plt.plot(s_x, s_y, '*', markersize=12)

        c_x, c_y = self.env_map.convert_to_plot([self.car.x, self.car.y])
        plt.plot(c_x, c_y, '+', markersize=16)

        for i in range(self.scan_sim.number_of_beams):
            angle = i * self.scan_sim.dth + self.car.theta - self.scan_sim.fov / 2
            fs = self.scan_sim.scan_output[
                i] * self.scan_sim.n_searches * self.scan_sim.step_size
            dx = [np.sin(angle) * fs, np.cos(angle) * fs]
            range_val = lib.add_locations([self.car.x, self.car.y], dx)
            r_x, r_y = self.env_map.convert_to_plot(range_val)
            x = [c_x, r_x]
            y = [c_y, r_y]

            plt.plot(x, y)

        for pos in self.action_memory:
            p_x, p_y = self.env_map.convert_to_plot(pos)
            plt.plot(p_x, p_y, 'x', markersize=6)

        text_start = self.env_map.width + 10
        spacing = int(self.env_map.height / 10)

        s = f"Reward: [{self.reward:.1f}]"
        plt.text(text_start, spacing * 1, s)
        s = f"Action: [{self.action[0]:.2f}, {self.action[1]:.2f}]"
        plt.text(text_start, spacing * 2, s)
        s = f"Done: {self.done}"
        plt.text(text_start, spacing * 3, s)
        s = f"Pos: [{self.car.x:.2f}, {self.car.y:.2f}]"
        plt.text(text_start, spacing * 4, s)
        s = f"Vel: [{self.car.velocity:.2f}]"
        plt.text(text_start, spacing * 5, s)
        s = f"Theta: [{(self.car.theta * 180 / np.pi):.2f}]"
        plt.text(text_start, spacing * 6, s)
        s = f"Delta x100: [{(self.car.steering*100):.2f}]"
        plt.text(text_start, spacing * 7, s)
        s = f"Theta Dot: [{(self.car.th_dot):.2f}]"
        plt.text(text_start, spacing * 8, s)

        s = f"Steps: {self.steps}"
        plt.text(100, spacing * 9, s)

        plt.pause(0.0001)
        if wait:
            plt.show()
Exemple #17
0
def MinCurvatureTrajectory(pts, nvecs, ws):
    """
    This function uses optimisation to minimise the curvature of the path
    """
    # w_min = ws[:, 0]
    w_min = -ws[:, 0]
    w_max = ws[:, 1]
    th_ns = [lib.get_bearing([0, 0], nvecs[i, 0:2]) for i in range(len(nvecs))]

    N = len(pts)

    n_f_a = ca.MX.sym('n_f', N)
    n_f = ca.MX.sym('n_f', N - 1)
    th_f = ca.MX.sym('n_f', N - 1)

    x0_f = ca.MX.sym('x0_f', N - 1)
    x1_f = ca.MX.sym('x1_f', N - 1)
    y0_f = ca.MX.sym('y0_f', N - 1)
    y1_f = ca.MX.sym('y1_f', N - 1)
    th1_f = ca.MX.sym('y1_f', N - 1)
    th2_f = ca.MX.sym('y1_f', N - 1)
    th1_f1 = ca.MX.sym('y1_f', N - 2)
    th2_f1 = ca.MX.sym('y1_f', N - 2)

    o_x_s = ca.Function('o_x', [n_f], [pts[:-1, 0] + nvecs[:-1, 0] * n_f])
    o_y_s = ca.Function('o_y', [n_f], [pts[:-1, 1] + nvecs[:-1, 1] * n_f])
    o_x_e = ca.Function('o_x', [n_f], [pts[1:, 0] + nvecs[1:, 0] * n_f])
    o_y_e = ca.Function('o_y', [n_f], [pts[1:, 1] + nvecs[1:, 1] * n_f])

    dis = ca.Function('dis', [x0_f, x1_f, y0_f, y1_f],
                      [ca.sqrt((x1_f - x0_f)**2 + (y1_f - y0_f)**2)])

    track_length = ca.Function('length', [n_f_a], [
        dis(o_x_s(n_f_a[:-1]), o_x_e(n_f_a[1:]), o_y_s(n_f_a[:-1]),
            o_y_e(n_f_a[1:]))
    ])

    real = ca.Function(
        'real', [th1_f, th2_f],
        [ca.cos(th1_f) * ca.cos(th2_f) + ca.sin(th1_f) * ca.sin(th2_f)])
    im = ca.Function(
        'im', [th1_f, th2_f],
        [-ca.cos(th1_f) * ca.sin(th2_f) + ca.sin(th1_f) * ca.cos(th2_f)])

    sub_cmplx = ca.Function('a_cpx', [th1_f, th2_f],
                            [ca.atan2(im(th1_f, th2_f), real(th1_f, th2_f))])

    get_th_n = ca.Function(
        'gth', [th_f],
        [sub_cmplx(ca.pi * np.ones(N - 1), sub_cmplx(th_f, th_ns[:-1]))])
    d_n = ca.Function('d_n', [n_f_a, th_f],
                      [track_length(n_f_a) / ca.tan(get_th_n(th_f))])

    # objective
    real1 = ca.Function(
        'real1', [th1_f1, th2_f1],
        [ca.cos(th1_f1) * ca.cos(th2_f1) + ca.sin(th1_f1) * ca.sin(th2_f1)])
    im1 = ca.Function(
        'im1', [th1_f1, th2_f1],
        [-ca.cos(th1_f1) * ca.sin(th2_f1) + ca.sin(th1_f1) * ca.cos(th2_f1)])

    sub_cmplx1 = ca.Function(
        'a_cpx1', [th1_f1, th2_f1],
        [ca.atan2(im1(th1_f1, th2_f1), real1(th1_f1, th2_f1))])

    # define symbols
    n = ca.MX.sym('n', N)
    th = ca.MX.sym('th', N - 1)

    nlp = {\
    'x': ca.vertcat(n, th),
    'f': ca.sumsqr(sub_cmplx1(th[1:], th[:-1])),
    # 'f': ca.sumsqr(track_length(n)),
    'g': ca.vertcat(
                # dynamic constraints
                n[1:] - (n[:-1] + d_n(n, th)),

                # boundary constraints
                n[0], #th[0],
                n[-1], #th[-1],
            ) \

    }

    # S = ca.nlpsol('S', 'ipopt', nlp, {'ipopt':{'print_level':5}})
    S = ca.nlpsol('S', 'ipopt', nlp, {'ipopt': {'print_level': 0}})

    ones = np.ones(N)
    n0 = ones * 0

    th0 = []
    for i in range(N - 1):
        th_00 = lib.get_bearing(pts[i, 0:2], pts[i + 1, 0:2])
        th0.append(th_00)

    th0 = np.array(th0)

    x0 = ca.vertcat(n0, th0)

    lbx = list(w_min) + [-np.pi] * (N - 1)
    ubx = list(w_max) + [np.pi] * (N - 1)

    r = S(x0=x0, lbg=0, ubg=0, lbx=lbx, ubx=ubx)

    x_opt = r['x']
    print(f"Sol Status (Optimal found?): {S.stats()['success']}")

    n_set = np.array(x_opt[:N])
    # thetas = np.array(x_opt[1*N:2*(N-1)])

    return n_set