Beispiel #1
0
    controller = PurePursuitControl()
    controller.set_path(path)

    while(True):
        print("\rState: "+car.state_str(), end="\t")

        # ================= Control Algorithm ================= 
        # PID Longitude Control
        end_dist = np.hypot(path[-1,0]-car.x, path[-1,1]-car.y)
        target_v = 40 if end_dist > 265 else 0
        next_a = 0.1*(target_v - car.v)

        # Pure Pursuit Lateral Control
        state = {"x":car.x, "y":car.y, "yaw":car.yaw, "v":car.v}
        next_delta, target = controller.feedback(state)
        car.control(next_a,next_delta)
        # =====================================================
        
        # Update & Render
        car.update()
        img = img_path.copy()
        cv2.circle(img,(int(target[0]),int(target[1])),3,(1,0.3,0.7),2) # target points
        img = car.render(img)
        img = cv2.flip(img, 0)
        cv2.imshow("Pure-Pursuit Control Test", img)
        k = cv2.waitKey(1)
        if k == ord('r'):
            car.init_state(start)
        if k == 27:
            print()
            break
Beispiel #2
0
pos = (100, 200, 0)
car.x = pos[0]
car.y = pos[1]
car.yaw = pos[2]

while (True):
    print("\rState: " + car.state_str(), end="\t")
    car.update()
    pos = (car.x, car.y, car.yaw)
    sdata, plist = lmodel.measure_2d(pos)
    img_ = img.copy()
    for pts in plist:
        cv2.line(img_, (int(1 * pos[0]), int(1 * pos[1])),
                 (int(1 * pts[0]), int(1 * pts[1])), (0.0, 1.0, 0.0), 1)

    img_ = car.render(img_)
    img_ = cv2.flip(img_, 0)

    #Collision
    p1, p2, p3, p4 = car.car_box
    l1 = Bresenham(p1[0], p2[0], p1[1], p2[1])
    l2 = Bresenham(p2[0], p3[0], p2[1], p3[1])
    l3 = Bresenham(p3[0], p4[0], p3[1], p4[1])
    l4 = Bresenham(p4[0], p1[0], p4[1], p1[1])
    check = l1 + l2 + l3 + l4
    collision = False
    for pts in check:
        if m[int(pts[1]), int(pts[0])] < 0.5:
            collision = True
            car.redo()
            car.v = -0.5 * car.v
Beispiel #3
0
def main():
    # Parameters
    N_PARTICLES = 40  # Number of Particles
    N_LANDMARKS = 80  # Number of Landmarks
    PERCEPTUAL_RANGE = 120  # Landmark Detection Range
    MOTION_NOISE = np.array([1e-5, 1e-2, 1e-5, 1e-2, 1e-5,
                             1e-2])  # Motion Noise
    Qt_sim = np.diag([4, np.deg2rad(4)])**2  # Observation Noise

    # Create landmarks
    landmarks = []
    for i in range(N_LANDMARKS):
        rx = np.random.randint(10, 490)
        ry = np.random.randint(10, 490)
        landmarks.append((rx, ry))

    # Initialize environment
    window_name = "Fast-SLAM Demo"
    cv2.namedWindow(window_name)
    img = np.ones((500, 500, 3))
    init_pos = (250, 100, 0)
    car = KinematicModel(motion_noise=MOTION_NOISE)
    car.init_state(init_pos)
    car.v = 24
    car.w = np.deg2rad(10)
    path_odometry = [(init_pos)]

    # Create particle filter
    pf = ParticleFilter((car.x, car.y, car.yaw),
                        Qt_sim,
                        MOTION_NOISE,
                        psize=N_PARTICLES)
    while (True):
        ###################################
        # Simulate Controlling
        ###################################
        u = (car.v, car.w, car.dt)
        car.update()
        # TODO(Lab-4): Remove the comment after complete the motion model.
        #'''
        pos_odometry = motion_model(path_odometry[-1], u)
        path_odometry.append(pos_odometry)
        #'''
        print("\rState: " + car.state_str() + " | Neff:" + str(pf.Neff)[0:7],
              end="\t")

        ###################################
        # Simulate Observation
        ###################################
        rvec = np.array(landmarks) - np.array((car.x, car.y))
        dist = np.hypot(rvec[:, 0], rvec[:, 1])
        landmarks_id = np.where(
            dist < PERCEPTUAL_RANGE)[0]  # Detected Landmark ids
        landmarks_detect = np.array(landmarks)[
            landmarks_id]  # Detected Landmarks
        z = []
        for i in range(landmarks_detect.shape[0]):
            lm = landmarks_detect[i]
            r = dist[landmarks_id[i]]
            phi = np.arctan2(lm[1] - car.y, lm[0] - car.x) - car.yaw
            # Add Observation Noise
            r = r + np.random.randn() * Qt_sim[0, 0]**0.5
            phi = phi + np.random.randn() * Qt_sim[1, 1]**0.5
            phi = normalize_angle(phi)
            z.append((r, phi))

        ###################################
        # SLAM Algorithm
        ###################################
        # TODO(Lab-0): Remove the comment after complete the class.
        #'''
        pf.sample(u)
        pf.update(z, landmarks_id)
        pf.resample()
        #'''

        ###################################
        # Render Canvas
        ###################################
        img_ = img.copy()
        # Draw landmark
        for lm in landmarks:
            cv2.circle(img_, lm, 3, (0.1, 0.7, 0.1), 1)
        for i in range(landmarks_detect.shape[0]):
            lm = landmarks_detect[i]
            cv2.line(img_, (int(car.x), int(car.y)), (int(lm[0]), int(lm[1])),
                     (0, 1, 0), 1)
        # Draw path
        for i in range(N_PARTICLES):
            draw_path(img_, pf.particles[i].path, 100, (1, 0.7, 0.7))
        bid = np.argmax(np.array(pf.weights))
        draw_path(img_, pf.particles[bid].path, 1000,
                  (1, 0, 0))  # Draw Best Path
        draw_path(img_, path_odometry, 1000, (0, 0, 0))  # Draw Odometry Path
        # Draw particle pose
        for i in range(N_PARTICLES):
            cv2.circle(
                img_,
                (int(pf.particles[i].pos[0]), int(pf.particles[i].pos[1])), 2,
                (1, 0, 0), 1)
            # Draw maps of particles
            '''
            for lm in pf.particles[i].landmarks:
                lx = pf.particles[i].landmarks[lm]["mu"][0,0]
                ly = pf.particles[i].landmarks[lm]["mu"][1,0]
                cv2.circle(img_, (int(lx),int(ly)), 2, (1,0,0), 1)
            '''
        # Draw map of best particle
        for lid in pf.particles[bid].landmarks:
            mean = pf.particles[bid].landmarks[lid]["mu"].reshape(2)
            cov = pf.particles[bid].landmarks[lid]["sig"]
            draw_ellipse(img_, mean, cov, (0, 0, 1))

        cv2.circle(img_, (int(car.x), int(car.y)), PERCEPTUAL_RANGE, (0, 1, 0),
                   1)  # Draw Detect Range
        img_ = car.render(img_)  # Render Car
        img_ = cv2.flip(img_, 0)
        cv2.imshow(window_name, img_)

        ###################################
        # Keyboard
        ###################################
        k = cv2.waitKey(1)  #1
        if k == ord("w"):
            car.v += 4
        elif k == ord("s"):
            car.v += -4
        if k == ord("a"):
            car.w += 5
        elif k == ord("d"):
            car.w += -5
        elif k == ord("r"):
            car.init_state(init_pos)
            pf = ParticleFilter((car.x, car.y, car.yaw),
                                Qt_sim,
                                MOTION_NOISE,
                                psize=N_PARTICLES)
            path_odometry = [(init_pos)]
            print("Reset!!")
        if k == 27:
            print()
            break
Beispiel #4
0
def main():
    window_name = "Fast-SLAM Demo"
    cv2.namedWindow(window_name)
    img = np.ones((500, 500, 3))
    init_pos = (100, 200, 0)
    lsize = 60
    detect_dist = 150
    psize = 30
    landmarks = []
    for i in range(lsize):
        rx = np.random.randint(10, 490)
        ry = np.random.randint(10, 490)
        landmarks.append((rx, ry))

    # Simulation Model
    car = KinematicModel()
    car.init_state(init_pos)
    pf = ParticleFilter((car.x, car.y, car.yaw), psize=psize)

    while (True):
        ###################################
        # Simulate Control
        ###################################
        u = (car.v, car.w, car.dt)
        # Add Control Noise
        car.v += np.random.randn() * 0.00002 * u[0]**2 + 0.00002 * u[1]**2
        car.w += np.random.randn() * 0.00002 * u[0]**2 + 0.00002 * u[1]**2
        car.update()
        print("\rState: " + car.state_str() + "| Neff:" + str(pf.Neff),
              end="\t")

        ###################################
        # Simulate Observation
        ###################################
        r = np.array(landmarks) - np.array((car.x, car.y))
        dist = np.hypot(r[:, 0], r[:, 1])
        detect_ids = np.where(dist < detect_dist)[0]
        detect_lms = np.array(landmarks)[detect_ids]
        obs = []
        for i in range(detect_lms.shape[0]):
            lm = detect_lms[i]
            r = np.sqrt((car.x - lm[0])**2 + (car.y - lm[1])**2)
            phi = np.rad2deg(np.arctan2(lm[1] - car.y,
                                        lm[0] - car.x)) - car.yaw
            # Add Observaation Noise
            r = r + np.random.randn() * R_sim[0, 0]**0.5
            phi = phi + np.random.randn() * R_sim[1, 1]**0.5
            # Normalize Angle
            phi = phi % 360
            if phi > 180:
                phi -= 360
            obs.append((r, phi))

        ###################################
        # SLAM Algorithm
        ###################################
        pf.prediction(u)
        pf.update_obs(obs, detect_ids)
        pf.resample()

        ###################################
        # Render Canvas
        ###################################
        img_ = img.copy()
        # Draw Landmark
        for lm in landmarks:
            cv2.circle(img_, lm, 3, (0.2, 0.5, 0.2), 1)
        for i in range(detect_lms.shape[0]):
            lm = detect_lms[i]
            cv2.line(img_, (int(car.x), int(car.y)), (int(lm[0]), int(lm[1])),
                     (0, 1, 0), 1)
        # Draw Trajectory
        start_cut = 100
        for j in range(psize):
            path_size = len(pf.particles[j].path)
            start = 0 if path_size < start_cut else path_size - start_cut
            for i in range(start, path_size - 1):
                cv2.line(img_, (int(pf.particles[j].path[i][0]),
                                int(pf.particles[j].path[i][1])),
                         (int(pf.particles[j].path[i + 1][0]),
                          int(pf.particles[j].path[i + 1][1])), (1, 0.7, 0.7),
                         1)
        # Draw Best Trajectory
        start_cut = 1000
        bid = np.argmax(np.array(pf.weights))
        path_size = len(pf.particles[bid].path)
        start = 0 if path_size < start_cut else path_size - start_cut
        for i in range(start, path_size - 1):
            cv2.line(img_, (int(pf.particles[bid].path[i][0]),
                            int(pf.particles[bid].path[i][1])),
                     (int(pf.particles[bid].path[i + 1][0]),
                      int(pf.particles[bid].path[i + 1][1])), (1, 0, 0), 1)
        # Draw Particle
        for j in range(psize):
            cv2.circle(
                img_,
                (int(pf.particles[j].pos[0]), int(pf.particles[j].pos[1])), 2,
                (1, 0.0, 0.0), 1)
        cv2.circle(img_, (int(car.x), int(car.y)), detect_dist, (0, 1, 0), 1)
        # Render Car
        img_ = car.render(img_)
        img_ = cv2.flip(img_, 0)
        cv2.imshow(window_name, img_)

        ###################################
        # Keyboard
        ###################################
        k = cv2.waitKey(1)
        if k == ord("w"):
            car.v += 4
        elif k == ord("s"):
            car.v += -4
        if k == ord("a"):
            car.w += 5
        elif k == ord("d"):
            car.w += -5
        elif k == ord("r"):
            car.init_state(init_pos)
            pf.init_pf(init_pos)
            print("Reset!!")
        if k == 27:
            print()
            break
class NavigationEnv:
    def __init__(self, path="Maps/map.png"):
        # Read Map
        self.img = cv2.flip(cv2.imread(path), 0)
        self.img[self.img > 128] = 255
        self.img[self.img <= 128] = 0
        self.m = np.asarray(self.img)
        self.m = cv2.cvtColor(self.m, cv2.COLOR_RGB2GRAY)
        self.m = self.m.astype(float) / 255.
        self.img = self.img.astype(float) / 255.
        self.lmodel = LidarModel(self.m)

    def initialize(self):
        # Set Mobile Car
        self.car = KinematicModel(d=12,
                                  wu=12,
                                  wv=4,
                                  car_w=18,
                                  car_f=14,
                                  car_r=10,
                                  dt=0.1)
        #self.car = KinematicModel()
        self.car.x, self.car.y = self._search_target()
        self.car.yaw = 360 * np.random.random()
        self.pos = (self.car.x, self.car.y, self.car.yaw)

        # Set Navigation Target
        self.target = self._search_target()
        self.target_dist = np.sqrt((self.car.x - self.target[0])**2 +
                                   (self.car.y - self.target[1])**2)
        target_orien = np.arctan2(self.target[1] - self.car.y, self.target[0] -
                                  self.car.x) - np.deg2rad(self.car.yaw)
        target_rel = [
            self.target_dist * np.cos(target_orien),
            self.target_dist * np.sin(target_orien)
        ]

        # Initialize Measurement
        self.sdata, self.plist = self.lmodel.measure_2d(self.pos)
        state = self._construct_state(self.sdata, target_rel)
        return state

    def step(self, action):
        # Control and Update
        self.car.control((action[0] + 1) / 2 * self.car.v_range,
                         action[1] * self.car.w_range)
        self.car.update()

        # Collision Handling
        p1, p2, p3, p4 = self.car.car_box
        l1 = Bresenham(p1[0], p2[0], p1[1], p2[1])
        l2 = Bresenham(p1[0], p3[0], p1[1], p3[1])
        l3 = Bresenham(p3[0], p4[0], p3[1], p4[1])
        l4 = Bresenham(p4[0], p2[0], p4[1], p2[1])
        check = l1 + l2 + l3 + l4
        collision = False
        for pts in check:
            if self.m[int(pts[1]), int(pts[0])] < 0.5:
                collision = True
                self.car.redo()
                self.car.v = -0.5 * self.car.v
                break

        # Measure Lidar
        self.pos = (self.car.x, self.car.y, self.car.yaw)
        self.sdata, self.plist = self.lmodel.measure_2d(self.pos)

        # TODO(Lab-01): Reward Design
        # Distance Reward
        curr_target_dist = np.sqrt((self.car.x - self.target[0])**2 +
                                   (self.car.y - self.target[1])**2)
        reward_dist = self.target_dist - curr_target_dist
        # Orientation Reward
        orien = np.rad2deg(
            np.arctan2(self.target[1] - self.car.y,
                       self.target[0] - self.car.x))
        err_orien = (orien - self.car.yaw) % 360
        if err_orien > 180:
            err_orien = 360 - err_orien
        reward_orien = np.deg2rad(err_orien)
        # Action Panelty
        reward_act = 0.05 if action[0] < -0.5 else 0
        # Total
        reward = 0.6 * reward_dist - 0.3 * reward_orien - 0.1 * reward_act

        # Terminal State
        done = False
        if collision:
            reward = -1
            done = True
        if curr_target_dist < 20:
            reward = 5
            done = True

        # Relative Coordinate of Target
        self.target_dist = curr_target_dist
        target_orien = np.arctan2(self.target[1] - self.car.y, self.target[0] -
                                  self.car.x) - np.deg2rad(self.car.yaw)
        target_rel = [
            self.target_dist * np.cos(target_orien),
            self.target_dist * np.sin(target_orien)
        ]
        state_next = self._construct_state(self.sdata, target_rel)
        return state_next, reward, done

    def render(self, gui=True):
        img_ = self.img.copy()
        for pts in self.plist:
            cv2.line(img_, (int(1 * self.pos[0]), int(1 * self.pos[1])),
                     (int(1 * pts[0]), int(1 * pts[1])), (0.0, 1.0, 0.0), 1)

        cv2.circle(img_, (int(1 * self.target[0]), int(1 * self.target[1])),
                   10, (1.0, 0.5, 0.7), 3)
        img_ = self.car.render(img_)
        img_ = cv2.flip(img_, 0)
        if gui:
            cv2.imshow("Mapless Navigation", img_)
            k = cv2.waitKey(1)
        return img_.copy()

    def _search_target(self):
        im_h, im_w = self.m.shape[0], self.m.shape[1]
        tx = np.random.randint(0, im_w)
        ty = np.random.randint(0, im_h)

        kernel = np.ones((10, 10), np.uint8)
        m_dilate = 1 - cv2.dilate(1 - self.m, kernel, iterations=3)
        while (m_dilate[ty, tx] < 0.5):
            tx = np.random.randint(0, im_w)
            ty = np.random.randint(0, im_h)
        return tx, ty

    def _construct_state(self, sensor, target):
        state_s = [s / 200 for s in sensor]
        state_t = [t / 500 for t in target]
        return state_s + state_t
def main():
    window_name = "EKF SLAM Demo"
    cv2.namedWindow(window_name)
    img = np.ones((500, 500, 3))
    init_pos = (100, 200, 0)
    landmarks = [(100, 80), (400, 100), (300, 450)]
    # Simulation Model
    car = KinematicModel()
    car.init_state(init_pos)

    #
    slam = EkfSLAM()
    slam.init_pos(init_pos)

    pos_now = init_pos
    path = [pos_now]
    while (True):
        car.update()
        img_ = img.copy()
        print("\rState: " + car.state_str(), end="\t")

        # Simulate Observation
        obs = []
        for lm in landmarks:
            r = np.sqrt((car.x - lm[0])**2 + (car.y - lm[1])**2)
            phi = np.rad2deg(np.arctan2(lm[1] - car.y,
                                        lm[0] - car.x)) - car.yaw
            obs.append((r, phi))

        slam.ekf_prediction(car.v, car.w, car.dt)
        print(slam.x[0:3])

        # Draw Landmark
        for lm in landmarks:
            cv2.circle(img_, lm, 3, (0.2, 0.2, 0.8), 2)
            cv2.line(img_, (int(car.x), int(car.y)), lm, (0, 1, 0), 1)
        # Draw Predict Path
        for i in range(len(path) - 1):
            cv2.line(img_, (int(path[i][0]), int(path[i][1])),
                     (int(path[i + 1][0]), int(path[i + 1][1])), (1, 0.5, 0.5),
                     1)

        img_ = car.render(img_)
        img_ = cv2.flip(img_, 0)
        cv2.imshow(window_name, img_)

        # Noise
        x_noise = np.random.randn() * Q_sim[0, 0]**0.5
        y_noise = np.random.randn() * Q_sim[1, 1]**0.5
        yaw_noise = np.random.randn() * Q_sim[2, 2]**0.5
        # Keyboard
        k = cv2.waitKey(1)
        car.x += x_noise
        car.y += y_noise
        car.yaw += yaw_noise
        if k == ord("w"):
            car.v += 4
        elif k == ord("s"):
            car.v += -4
        if k == ord("a"):
            car.w += 5
        elif k == ord("d"):
            car.w += -5
        elif k == ord("r"):
            car.init_state(init_pos)
            nav_pos = None
            path = None
            print("Reset!!")
        if k == 27:
            print()
            break
        pos_now = velocity_motion_model(pos_now, car.v, car.w, car.dt)
        path.append(pos_now)