Example #1
0
    def predict(self, motion_model_transform, command, noise):
        sigma_points, w_m, w_c = compute_sigma_points(self.mean, self.cov,
                                                      self.lambd, self.alpha,
                                                      self.beta)
        # Normalize
        for i in range(sigma_points.shape[1]):
            sigma_points[2, i] = normalize_angle(sigma_points[2, i])

        # Angles are normalized in motion model
        sigma_points = motion_model_transform(sigma_points, command)

        # TODO: rewrite to normalize differences
        self.mean, self.cov = recover_gaussian(sigma_points, w_m, w_c)

        # fix angles
        average_theta = 0
        avg_x = avg_y = 0
        for i in range(sigma_points.shape[1]):
            avg_x = avg_x + w_m[i] * math.cos(sigma_points[2, i])
            avg_y = avg_y + w_m[i] * math.sin(sigma_points[2, i])
        average_theta = normalize_angle(np.arctan2(avg_y, avg_x))
        self.mean[2] = average_theta

        # fix angles in covariance matrix too
        for i in range(self.cov.shape[1]):
            self.cov[2, i] = normalize_angle(self.cov[2, i])

        Rt = np.diag(noise)
        self.cov = self.cov + Rt

        return self.mean, self.cov
    def correct(self, measurements, sensor_noise, landmark_map):
        normalizer = 0
        for i, particle in enumerate(self.particles):
            weight, pose = particle
            rx = pose.item(0)
            ry = pose.item(1)
            rtheta = pose.item(2)

            vrange, vbearing = sensor_noise

            # Matrix of measurement differences
            Zdiff = np.matrix([])
            for reading in measurements:
                lid, srange, sbearing = reading
                # Sensor measurement
                z_measured = np.matrix([srange, sbearing]).T

                lx, ly = landmark_map.get(lid)

                dx = lx - rx
                dy = ly - ry

                delta = np.matrix([dx, dy]).T
                q = delta.T * delta
                # Expected (predicted) measurement
                z_expected = np.matrix([
                    math.sqrt(q),
                    normalize_angle(np.arctan2(dy, dx) - rtheta)
                ]).T

                # Difference between measured and expected
                diff = z_expected - z_measured
                diff[1] = normalize_angle(diff.item(1))
                # Collect all measurement differences
                Zdiff = np.concatenate(
                    (Zdiff, diff)) if Zdiff.size else np.copy(diff)

            # Making sensor noise matrix with different diagonal elements
            Qdiag = np.array([[vrange, vbearing]
                              for i in range(len(measurements))])
            # Flatten the array
            Qdiag.shape = (len(sensor_noise) * len(measurements), )
            Qt = np.diag(Qdiag)
            # Qt = np.eye(Zdiff.shape[0]) * 0.1

            # Normal distribution is probably a good idea
            # Highest weight when (z_expected - z_measured) is 0
            denom = 1 / math.sqrt(np.linalg.det(2 * math.pi * Qt))
            new_weight = denom * math.exp(
                -1 / 2 * Zdiff.T * np.linalg.pinv(Qt) * Zdiff)

            normalizer = normalizer + new_weight
            self.particles[i] = (new_weight, np.copy(pose))

        self.particles = [(weight / normalizer, pose)
                          for weight, pose in self.particles]
def odometry_command(pose, command):
    rot1, trans, rot2 = command
    theta_old = normalize_angle(pose.item(2))

    normalized = normalize_angle(theta_old + rot1)
    update_vec = np.matrix([
        trans * math.cos(normalized),
        trans * math.sin(normalized),
        normalize_angle(rot1 + rot2)
    ]).T

    pose = pose + update_vec
    pose[2] = normalize_angle(pose.item(2))

    return np.copy(pose)
Example #4
0
    def predict(self, command):
        self._mean = self.motion_command(self.mean, command)

        # TODO: Put in motion model
        theta_n = normalize_angle(self.mean.item(2))
        rot1, trans, rot2 = command

        ang = normalize_angle(theta_n + rot1)
        Gt = np.matrix([
            [1, 0, -trans * math.sin(ang)],
            [0, 1, trans * math.cos(ang)],
            [0, 0, 1],
        ])

        # motion noise
        Rt = np.matrix([[0.1, 0, 0], [0, 0.1, 0], [0, 0, 0.01]])

        self._cov = Gt * self.cov * Gt.T + Rt

        return self._mean, self._cov
Example #5
0
    def correct(self, measurements, local_map):
        # measurement noise
        Qt = np.eye(self._mean.size - 1) * 0.01

        rx = self._mean.item(0)
        ry = self._mean.item(1)
        rtheta = normalize_angle(self._mean.item(2))

        # TODO: Fix kalman gain calculation
        for reading in measurements:
            # TODO: Put in measurement model
            lid, srange, sbearing = reading
            z_measured = np.matrix([srange, normalize_angle(sbearing)]).T

            # Expected observation
            lx, ly = local_map.get(lid)
            dx = lx - rx
            dy = ly - ry
            delta = np.matrix([dx, dy]).T
            q = delta.T * delta
            z_expected = np.matrix(
                [math.sqrt(q),
                 normalize_angle(np.arctan2(dy, dx) - rtheta)]).T
            # Jacobian
            Ht = np.matrix([[-math.sqrt(q) * dx, -math.sqrt(q) * dy, 0],
                            [dy, -dx, -q]])
            Ht = np.multiply((1.0 / q), Ht)

            Kgain = self._cov * Ht.T * np.linalg.inv(Ht * self._cov * Ht.T +
                                                     Qt)

            diff = z_measured - z_expected
            diff[1] = normalize_angle(diff.item(1))

            self._mean = self._mean + Kgain * diff
            self._cov = (np.eye(self._mean.size) - Kgain * Ht) * self._cov

        self.mean = np.copy(self._mean)
        self.cov = np.copy(self._cov)

        return self.mean, self.cov
Example #6
0
def measurement_model_transform(points, measurement, landmark_map):
    z_points = np.zeros((points.shape[0] - 1, points.shape[1]))
    for i in range(points.shape[1]):
        rx = points[0, i]
        ry = points[1, i]
        rtheta = points[2, i]

        lid, srange, sbearing = measurement
        z_measured = np.matrix([srange, normalize_angle(sbearing)]).T

        lx, ly = landmark_map.get(lid)

        dx = lx - rx
        dy = ly - ry
        delta = np.matrix([dx, dy]).T
        q = delta.T * delta
        z_expected = np.matrix(
            [math.sqrt(q),
             normalize_angle(np.arctan2(dy, dx) - rtheta)]).T

        z_points[:, [i]] = z_expected
    return z_points
def odometry_sample(pose, command, noise, sample=None):
    if not sample:
        raise ValueError("Provide a sampler")

    rot1, trans, rot2 = command
    r1_noise, t_noise, r2_noise = noise
    theta_old = normalize_angle(pose.item(2))

    rot1_h = rot1 - sample(r1_noise)
    trans_h = trans - sample(t_noise)
    rot2_h = rot2 - sample(r2_noise)

    normalized = normalize_angle(theta_old + rot1_h)
    update_vec = np.matrix([
        trans_h * math.cos(normalized),
        trans_h * math.sin(normalized),
        normalize_angle(rot1_h + rot2_h)
    ]).T

    temp = pose + update_vec
    temp[2] = normalize_angle(temp.item(2))

    return np.copy(temp)
Example #8
0
    def predict(self, command):
        robot_pose = self.mean[:self.rsize, :]
        self.mean[:self.rsize, :] = self.motion_command(robot_pose, command)

        # TODO: Put in motion model
        theta_n = normalize_angle(self.mean.item(2))
        rot1, trans, rot2 = command

        ang = normalize_angle(theta_n + rot1)
        Gtx = np.matrix([
            [1, 0, -trans * math.sin(ang)],
            [0, 1, trans * math.cos(ang)],
            [0, 0, 1],
        ])

        lmsize = self.mean.shape[0] - self.rsize

        r1zeros = np.zeros((self.rsize, lmsize))
        r2zeros = np.copy(r1zeros.T)

        gr1 = np.concatenate((Gtx, r1zeros), axis=1)
        gr2 = np.concatenate((r2zeros, np.eye(lmsize)), axis=1)
        Gt = np.concatenate((gr1, gr2))

        # motion noise
        Rtx = np.matrix([[0.1, 0, 0], [0, 0.1, 0], [0, 0, 0.01]])

        rr1zeros = np.zeros((self.rsize, lmsize))
        rr2zeros = np.copy(rr1zeros.T)

        rr1 = np.concatenate((Rtx, rr1zeros), axis=1)
        rr2 = np.concatenate((rr2zeros, np.zeros((lmsize, lmsize))), axis=1)
        Rt = np.concatenate((rr1, rr2))

        self.cov = Gt * self.cov * Gt.T + Rt

        return self.mean, self.cov
Example #9
0
    def update_map(self):
        with self.lock:
            if not self.last_scan_msg or not self.last_tf_msg:
                return

            rx = self.last_tf_msg.transform.translation.x
            ry = self.last_tf_msg.transform.translation.y

            quat = (
                self.last_tf_msg.transform.rotation.x,
                self.last_tf_msg.transform.rotation.y,
                self.last_tf_msg.transform.rotation.z,
                self.last_tf_msg.transform.rotation.w,
            )
            (roll, pitch, yaw) = tf.transformations.euler_from_quaternion(quat)

            rtheta = normalize_angle(yaw)
            rob_pose = np.matrix([rx, ry, rtheta]).T

            # TODO: Calculate laser offset
            range_scan = {
                'ranges': np.array(self.last_scan_msg.ranges,
                                   dtype=np.float32),
                'maximum_range': self.last_scan_msg.range_max,
                'start_angle': self.last_scan_msg.angle_min,
                'angular_resolution': self.last_scan_msg.angle_increment,
                'laser_offset': np.matrix([0, 0, 0])
            }
            s_angle = range_scan['start_angle']
            ang_res = range_scan['angular_resolution']
            num_beams = len(range_scan['ranges'])
            print(s_angle, ang_res, s_angle + ang_res * num_beams)
            print(
                self.last_scan_msg.angle_min,
                self.last_scan_msg.angle_increment,
                self.last_scan_msg.angle_max,
            )
            rospy.loginfo('Updating map')

            self.gridmap.update(rob_pose, range_scan)

            self.gridmap_msg.header.stamp = rospy.Time.now()
            prob_map = self.gridmap.get_prob_map() * 100
            self.gridmap_msg.data = prob_map.flatten()
            self.map_pub.publish(self.gridmap_msg)
Example #10
0
    def correct(self, meas_model_transform, measurements, noise, landmark_map):
        sigma_points, w_m, w_c = compute_sigma_points(self.mean, self.cov,
                                                      self.lambd, self.alpha,
                                                      self.beta)
        # Normalize
        for i in range(sigma_points.shape[1]):
            sigma_points[2, i] = normalize_angle(sigma_points[2, i])

        for reading in measurements:
            # Real measurement
            lid, srange, sbearing = reading
            z_measured = np.matrix([srange, normalize_angle(sbearing)]).T

            # Predicted measurement
            # Transform points through measurment_model
            # Resulting matrix has 2 rows (range, bearing) and same number of columns
            z_points = meas_model_transform(sigma_points, reading,
                                            landmark_map)

            # Recover gaussian for predicted measurement
            # TODO: rewrite to normalize differences
            zt, St = recover_gaussian(z_points, w_m, w_c)

            # Normalize bearing
            average_bearing = 0
            avg_x = avg_y = 0
            for i in range(z_points.shape[1]):
                # normalize
                z_points[1, i] = normalize_angle(z_points[1, i])
                # weighted sums of cosines and sines of the angle
                avg_x = avg_x + w_m[i] * math.cos(z_points[1, i])
                avg_y = avg_y + w_m[i] * math.sin(z_points[1, i])
            average_bearing = normalize_angle(np.arctan2(avg_y, avg_x))
            zt[1] = average_bearing

            # normalize bearing in covariance matrix
            for i in range(St.shape[1]):
                St[1, i] = normalize_angle(St[1, i])

            # Measurement noise
            Qt = np.diag(noise)
            St = St + Qt

            sigma_x_z = np.zeros((self.mean.shape[0], zt.shape[0]))
            for i in range(z_points.shape[1]):
                s_diff = sigma_points[:, [i]] - self.mean
                z_diff = z_points[:, [i]] - zt

                # Normalize angles
                s_diff[2] = normalize_angle(s_diff[2])
                z_diff[1] = normalize_angle(z_diff[1])

                sigma_x_z = sigma_x_z + w_c[i] * s_diff * z_diff.T

            # Normalization time
            for i in range(sigma_x_z.shape[1]):
                sigma_x_z[2, i] = normalize_angle(sigma_x_z[2, i])

            # broadcasting error if not matrix
            sigma_x_z = np.matrix(sigma_x_z)

            # Kalman gain
            Kt = sigma_x_z * np.linalg.pinv(St)

            # Normalize
            z_diff = z_measured - zt
            z_diff[1] = normalize_angle(z_diff[1])

            self.mean = self.mean + Kt * (z_diff)
            self.cov = self.cov - Kt * St * Kt.T

            # normalize angle
            self.mean[2] = normalize_angle(self.mean[2])
            for i in range(self.cov.shape[1]):
                self.cov[2, i] = normalize_angle(self.cov[2, i])

        return self.mean, self.cov
Example #11
0
    def correct(self, measurements, local_map):
        rx = self.mean.item(0)
        ry = self.mean.item(1)
        rtheta = normalize_angle(self.mean.item(2))

        Htfull = np.matrix([])
        Zdiff = np.matrix([])
        for reading in measurements:
            # TODO: Put in measurement model
            lid, srange, sbearing = reading
            z_measured = np.matrix([srange, normalize_angle(sbearing)]).T

            mu_lid = self.get_mu_lid(lid)

            # Expected observation
            lx = 0
            ly = 0
            if not local_map.is_added(lid):
                lx = rx + srange * math.cos(sbearing + rtheta)
                ly = ry + srange * math.sin(sbearing + rtheta)
                local_map.add((lid, lx, ly))

                self.mean[mu_lid, :] = lx
                self.mean[mu_lid + 1, :] = ly
            else:
                lx = self.mean[mu_lid, :].item(0)
                ly = self.mean[mu_lid + 1, :].item(0)

            dx = lx - rx
            dy = ly - ry

            delta = np.matrix([dx, dy]).T
            q = delta.T * delta
            z_expected = np.matrix(
                [math.sqrt(q),
                 normalize_angle(np.arctan2(dy, dx) - rtheta)]).T
            qst = math.sqrt(q)
            # Measurement jacobian
            Htt = np.matrix([[-qst * dx, -qst * dy, 0, qst * dx, qst * dy],
                             [dy, -dx, -q, -dy, dx]])
            Htt = np.multiply((1.0 / q), Htt)

            F = np.zeros((5, self.mean.size))
            F[:self.rsize, :self.rsize] = np.eye(self.rsize)
            F[self.rsize:, mu_lid:mu_lid + self.lmsize] = np.eye(self.lmsize)

            Ht = Htt * F

            Htfull = np.concatenate(
                (Htfull, Ht)) if Htfull.size else np.copy(Ht)

            diff = z_measured - z_expected
            # Important to normalize_angles
            diff[1] = normalize_angle(diff.item(1))

            Zdiff = np.concatenate(
                (Zdiff, diff)) if Zdiff.size else np.copy(diff)

        # measurement noise
        Qt = np.eye(Zdiff.shape[0]) * 0.01

        Kgain = self.cov * Htfull.T * np.linalg.inv(Htfull * self.cov *
                                                    Htfull.T + Qt)

        self.mean = self.mean + Kgain * Zdiff
        self.cov = (np.eye(self.mean.size) - Kgain * Htfull) * self.cov

        return self.mean, self.cov