def validate_predicted_measurements():
    # Load pickle
    validation_run = load_pickle(EKF_PICKLE)
    validation_pf = load_pickle(PF_PICKLE)
    x0 = validation_pf['x0']
    xs_input = validation_pf['x_input']
    dt = validation_run['t'][1] - validation_run['t'][0]
    ground_truth_hs = validation_pf['predicted_measurements_validation']

    # Initialize MC localization
    np.random.seed(1234)
    mcl = MonteCarloLocalization(xs_input,
                                 10. * NoiseParams['R'],
                                 params.MapParams,
                                 validation_run['tf_base_to_camera'],
                                 NoiseParams['g'])

    hs = mcl.compute_predicted_measurements()

    if np.linalg.norm(hs - ground_truth_hs, axis=1).sum() >= 1e-2:
        print("Got MonteCarloLocalization.compute_predicted_measurements() output:\n")
        print(hs)
        print("\nvs. the expected values\n")
        print(ground_truth_hs)
        return False

    print("MonteCarloLocalization.compute_predicted_measurements() seems to be correct")
    return True
def validate_transition_model():
    # Load pickle
    validation_run = load_pickle(EKF_PICKLE)
    validation_pf = load_pickle(PF_PICKLE)
    x0 = validation_pf['x0']
    xs_validation = validation_pf['transition_model_validation']
    dt = validation_run['t'][1] - validation_run['t'][0]

    # Initialize MC localization
    np.random.seed(1234)
    mcl = MonteCarloLocalization(validation_pf['x0'],
                                 10. * NoiseParams['R'],
                                 params.MapParams,
                                 validation_run['tf_base_to_camera'],
                                 NoiseParams['g'])

    xs = mcl.transition_model(np.random.multivariate_normal(validation_run['controls'][0],
                                                            10. * dt * NoiseParams['R'],
                                                            (x0.shape[0],)), dt)

    if np.linalg.norm(xs_validation - xs, axis=1).sum() >= 1e-6:
        print("Got MonteCarloLocalization.transition_model() particles:\n")
        print(xs)
        print("\nvs. the expected particles\n")
        print(xs_validation)
        return False

    print("MonteCarloLocalization.transition_model() seems to be correct")
    return True
def validate_resample():
    # Load pickle
    validation_run = load_pickle(EKF_PICKLE)
    validation_pf = load_pickle(PF_PICKLE)
    x0 = validation_pf['x0']
    xs_input = validation_pf['x_input']
    ws_input = validation_pf['w_input']
    xs_validation = validation_pf['resample_validation']['xs']
    ws_validation = validation_pf['resample_validation']['ws']

    # Initialize MC localization
    np.random.seed(1234)
    mcl = MonteCarloLocalization(x0,
                                 10. * NoiseParams['R'],
                                 params.MapParams,
                                 validation_run['tf_base_to_camera'],
                                 NoiseParams['g'])

    mcl.resample(xs_input, ws_input)

    if np.linalg.norm(xs_validation - mcl.xs, axis=1).sum() >= 1e-6:
        print("Got MonteCarloLocalization.resample() particles:\n")
        print(mcl.xs)
        print("\nvs. the expected particles\n")
        print(xs_validation)
        return False
    if np.linalg.norm(ws_validation - mcl.ws) >= 1e-6:
        print("Got MonteCarloLocalization.resample() weights:\n")
        print(mcl.ws)
        print("\nvs. the expected weights\n")
        print(ws_validation)
        return False

    print("MonteCarloLocalization.resample() seems to be correct")
    return True
def validate_compute_innovations():
    # Load pickle
    validation_run = load_pickle(EKF_PICKLE)
    validation_pf = load_pickle(PF_PICKLE)
    x0 = validation_pf['x0']
    xs_input = validation_pf['x_input']
    dt = validation_run['t'][1] - validation_run['t'][0]
    scans = validation_run['scans']
    ground_truth_vs = validation_pf['predicted_compute_innovations']

    # Initialize MC localization
    np.random.seed(1234)
    mcl = MonteCarloLocalization(xs_input,
                                 10. * NoiseParams['R'],
                                 params.MapParams,
                                 validation_run['tf_base_to_camera'],
                                 NoiseParams['g'])

    alpha, r, Q_raw, _, _ = ExtractLines(scans[0,-1,:],
                                         scans[1,-1,:],
                                         LineExtractionParams,
                                         NoiseParams['var_theta'],
                                         NoiseParams['var_rho'])
    z_raw = np.vstack((alpha, r))
    vs = mcl.compute_innovations(z_raw, np.array(Q_raw))

    if np.linalg.norm(vs - ground_truth_vs, axis=1).sum() >= 1e-3:
        print("Got MonteCarloLocalization.compute_innovations() output:\n")
        print(vs)
        print("\nvs. the expected values\n")
        print(ground_truth_vs)
        return False

    print("MonteCarloLocalization.compute_innovations() seems to be correct")
    return True
예제 #5
0
    def run(self):
        rate = rospy.Rate(100)

        particles = PointCloud()
        particles.header.stamp = self.EKF_time
        particles.header.frame_id = "world"
        particles.points = [
            Point32(0., 0., 0.) for _ in range(self.params.num_particles)
        ]
        particle_intensities = ChannelFloat32()
        particle_intensities.name = "intensity"
        particle_intensities.values = [
            0. for _ in range(self.params.num_particles)
        ]
        particles.channels.append(particle_intensities)

        while not self.latest_pose:
            rate.sleep()

        x0 = np.array([
            self.latest_pose.position.x, self.latest_pose.position.y,
            get_yaw_from_quaternion(self.latest_pose.orientation)
        ])
        self.EKF_time = self.latest_pose_time
        if self.params.mc:
            x0s = np.tile(np.expand_dims(x0, 0),
                          (self.params.num_particles, 1))
            from HW4.particle_filter import MonteCarloLocalization
            self.EKF = MonteCarloLocalization(x0s, 10. * NoiseParams["R"],
                                              MapParams, self.base_to_camera,
                                              NoiseParams["g"])
            self.OLC = EkfLocalization(x0, NoiseParams["Sigma0"],
                                       NoiseParams["R"], MapParams,
                                       self.base_to_camera, NoiseParams["g"])
        else:
            self.EKF = EkfLocalization(x0, NoiseParams["Sigma0"],
                                       NoiseParams["R"], MapParams,
                                       self.base_to_camera, NoiseParams["g"])
            self.OLC = EkfLocalization(x0, NoiseParams["Sigma0"],
                                       NoiseParams["R"], MapParams,
                                       self.base_to_camera, NoiseParams["g"])

        while True:
            if not self.scans:
                rate.sleep()
                continue

            while self.controls and self.controls[0][0] <= self.scans[0][0]:
                next_timestep, next_control = self.controls.popleft()
                if next_timestep < self.EKF_time:  # guard against time weirdness (msgs out of order)
                    continue
                self.EKF.transition_update(
                    self.current_control,
                    next_timestep.to_time() - self.EKF_time.to_time())
                self.OLC.transition_update(
                    self.current_control,
                    next_timestep.to_time() - self.EKF_time.to_time())
                self.EKF_time, self.current_control = next_timestep, next_control
                label = "EKF" if not self.params.mc else "MCL"
                self.tfBroadcaster.sendTransform(
                    create_transform_msg(
                        (self.EKF.x[0], self.EKF.x[1], 0),
                        tf.transformations.quaternion_from_euler(
                            0, 0,
                            self.EKF.x[2]), label, "world", self.EKF_time))
                self.tfBroadcaster.sendTransform(
                    create_transform_msg(
                        (self.OLC.x[0], self.OLC.x[1], 0),
                        tf.transformations.quaternion_from_euler(
                            0, 0, self.OLC.x[2]), "open_loop", "world",
                        self.EKF_time))

                if self.params.mc:
                    particles.header.stamp = self.EKF_time
                    for m in range(self.params.num_particles):
                        x = self.EKF.xs[m]
                        w = self.EKF.ws[m]
                        particles.points[m].x = x[0]
                        particles.points[m].y = x[1]
                        particles.channels[0].values[m] = w
                    self.particles_pub.publish(particles)

            scan_time, theta, rho = self.scans.popleft()
            if scan_time < self.EKF_time:
                continue
            self.EKF.transition_update(
                self.current_control,
                scan_time.to_time() - self.EKF_time.to_time())
            self.OLC.transition_update(
                self.current_control,
                scan_time.to_time() - self.EKF_time.to_time())
            self.EKF_time = scan_time
            alpha, r, C_AR, _, _ = ExtractLines(theta, rho,
                                                LineExtractionParams,
                                                NoiseParams["var_theta"],
                                                NoiseParams["var_rho"])
            Z = np.vstack((alpha, r))
            self.EKF.measurement_update(Z, C_AR)

            if self.params.mc:
                particles.header.stamp = self.EKF_time
                for m in range(self.params.num_particles):
                    x = self.EKF.xs[m]
                    w = self.EKF.ws[m]
                    particles.points[m].x = x[0]
                    particles.points[m].y = x[1]
                    particles.channels[0].values[m] = w
                self.particles_pub.publish(particles)

            while len(
                    self.scans
            ) > 1:  # keep only the last element in the queue, if we're falling behind
                self.scans.popleft()
def validate_mc_localization(show_plot=True):
    NUM_PARTICLES=100

    # Plot open loop
    validate_ekf_transition_update(False)

    # Load pickle
    validation_run = load_pickle(EKF_PICKLE)
    u = validation_run['controls']
    t = validation_run['t']
    T = t.shape[0]
    t_scans = validation_run['t_scans']
    T_scans = t_scans.shape[0]
    scans = validation_run['scans']
    x0 = np.tile(validation_run['states'][0], (NUM_PARTICLES, 1))

    # Initialize MC localization
    np.random.seed(1234)
    mcl = MonteCarloLocalization(x0,
                                 10. * NoiseParams['R'],
                                 params.MapParams,
                                 validation_run['tf_base_to_camera'],
                                 NoiseParams['g'])

    X = np.zeros((T, NUM_PARTICLES, 3))
    W = np.zeros((T, NUM_PARTICLES))

    # Iterate over states
    mcl_states = np.zeros((T, mcl.x.shape[0]))
    mcl_states[0] = mcl.x
    scan_states = np.zeros((T_scans, mcl.x.shape[0]))
    scan_idx = 0
    X[0] = mcl.xs
    W[0] = mcl.ws
    for i in range(T - 1):
        t1 = t[i+1]
        t0 = t[i]

        # Iterate over scans
        while scan_idx < T_scans and t_scans[scan_idx] < t1:
            # Transition update
            mcl.transition_update(u[i], t_scans[scan_idx] - t0)
            t0 = t_scans[scan_idx]

            # Measurement update
            alpha, r, Q_raw, _, _ = ExtractLines(scans[0,scan_idx,:],
                                                 scans[1,scan_idx,:],
                                                 LineExtractionParams,
                                                 NoiseParams['var_theta'],
                                                 NoiseParams['var_rho'])
            z_raw = np.vstack((alpha, r))
            mcl.measurement_update(z_raw, Q_raw)
            scan_states[scan_idx] = mcl.x
            scan_idx += 1

        # Transition update
        mcl.transition_update(u[i], t1 - t0)
        mcl_states[i+1] = mcl.x

        X[i+1] = mcl.xs
        W[i+1] = mcl.ws

    # Plot
    plt.plot(mcl_states[:,0], mcl_states[:,1], label="MCL", color="red")
    plt.scatter(scan_states[:,0], scan_states[:,1], marker = "x", label="measurement update", color="blue")
    if show_plot:
        plt.legend(loc=0)
        plt.savefig("mc_localization.png")
        print("Plot saved to mc_localization.png")