Exemple #1
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''
    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    #0-----associate/match-----[alpha]-----ambiguous-----[beta]-----new_landmark-----
    #pdb.set_trace()
    alpha = chi2.ppf(0.95, df=2)
    beta = chi2.ppf(0.999, df=2)

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    measurements = np.array(measurements)[:, 0:2]
    zhat = np.zeros([ekf_state["num_landmarks"], 2])
    S = np.zeros([ekf_state["num_landmarks"], 2, 2])
    Q = np.diag(
        np.array([
            sigmas['range'] * sigmas['range'],
            sigmas['bearing'] * sigmas['bearing']
        ]))
    for j in range(ekf_state["num_landmarks"]):
        zhat[j], H = laser_measurement_model(ekf_state, j)
        S[j] = np.matmul(np.matmul(H, ekf_state['P']), H.T) + Q.T

    M = alpha * np.ones((measurements.shape[0],
                         ekf_state["num_landmarks"] + measurements.shape[0]))
    for i in range(measurements.shape[0]):
        residuals = measurements[i] - zhat
        for j in range(ekf_state["num_landmarks"]):
            mahalanobis_dist = np.matmul(
                residuals[j], np.matmul(np.linalg.inv(S[j]), residuals[j].T))
            M[i, j] = mahalanobis_dist

    matches = slam_utils.solve_cost_matrix_heuristic(np.copy(M))
    matches.sort()
    assoc = list(range(measurements.shape[0]))
    for k in range(measurements.shape[0]):
        if (matches[k][1] >= ekf_state['num_landmarks']):
            if (np.amin(M[k, 0:ekf_state['num_landmarks']]) >
                    beta):  #new landmark
                assoc[matches[k][0]] = -1
            else:  #ambiguous
                assoc[matches[k][0]] = -2
        else:  #matched
            assoc[matches[k][0]] = matches[k][1]
    return assoc
Exemple #2
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    m = len(measurements)
    n = ekf_state['num_landmarks']

    if m > n:
        M = np.full((m, n + m), 6.1)
    else:
        M = np.zeros((m, n))

    Q = np.diag([sigmas['range']**2, sigmas['bearing']**2])
    sigma = ekf_state['P']

    for i in range(m):
        z = np.zeros((2, 1))
        z[0, 0] = measurements[i][0]
        z[1, 0] = measurements[i][1]
        for j in range(n):
            zhat, H = laser_measurement_model(ekf_state, j)
            r = z - zhat
            S = np.matmul(H, np.matmul(sigma, H.T)) + Q
            M[i, j] = np.matmul(r.T, np.matmul(np.linalg.inv(S), r))

    pairs = slam_utils.solve_cost_matrix_heuristic(np.copy(M))
    assoc = [0] * len(measurements)

    for i, j in pairs:
        if j >= n:
            min_element = np.amin(M[i, 0:n - 1])
            #13.8
            if (min_element > 18.2):  #chi(0.9999)
                assoc[i] = -1
            else:
                assoc[i] = -2
        else:
            if M[i, j] > 6:
                if M[i, j] > 18.2:
                    assoc[i] = -1
                else:
                    assoc[i] = -2
            else:
                assoc[i] = j

    return assoc
Exemple #3
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    ###
    # Implement this function.
    ###
    Q = np.eye(2, 2)
    Q[0][0] = sigmas['range']**2
    Q[1][1] = sigmas['bearing']**2
    xv, yv, phi = ekf_state['x'][:3]
    landmark_state = ekf_state['x'][3:]
    landmarks = np.zeros((2, ekf_state['num_landmarks']))
    landmarks[0:] = landmark_state[::2]
    landmarks[1:] = landmark_state[1::2]
    landmark_rb = np.zeros((2, ekf_state['num_landmarks']))
    landmark_rb[0, :] = np.sqrt((landmarks[0, :] - xv)**2 +
                                (landmarks[1, :] - yv)**2)
    landmark_rb[1, :] = np.arctan2(landmarks[1, :] - yv,
                                   landmarks[0, :] - xv) - phi + np.pi / 2
    M = np.zeros((len(measurements), ekf_state['num_landmarks']))
    # r = measurements - landmark_rb
    # H = np.zeros((2, 3+2*ekf_state['num_landmarks']))
    r = np.zeros((2, ))
    for i in range(len(measurements)):
        for j in range(ekf_state['num_landmarks']):
            zhat, H = laser_measurement_model(ekf_state, j)
            Sinv = np.linalg.inv(
                np.matmul(np.matmul(H, ekf_state['P']), H.T) + Q)
            r[0] = measurements[i][0] - zhat[0]
            r[1] = measurements[i][1] - zhat[1]
            dist = np.matmul(np.matmul(r.T, Sinv), r)
            M[i, j] = dist
    assoc = [-2] * len(measurements)
    padding = np.zeros(
        (len(measurements), len(measurements))) + chi2.ppf(0.95, df=2)
    cost = np.hstack((M, padding))
    result = slam_utils.solve_cost_matrix_heuristic(cost.copy())

    for index, (i, j) in enumerate(result):
        if j < ekf_state['num_landmarks']:
            assoc[i] = j
        elif np.min(M[i, :ekf_state['num_landmarks']]) > chi2.ppf(0.99, df=2):
            assoc[i] = -1
    return assoc
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    ###
    # Implement this function.
    ###
    trees = measurements

    append_M = np.ones(
        (len(measurements), len(measurements))) * chi2.ppf(0.95, df=2)

    measurements = [(tree[0], tree[1]) for tree in trees]
    assoc = -1 * np.ones((len(measurements), ))
    Q = np.eye(2, 2)
    Q[0][0] = sigmas['range'] * sigmas['range']
    Q[1][1] = sigmas['bearing'] * sigmas['bearing']
    M = np.zeros((len(measurements), ekf_state['num_landmarks']))

    for i in range(len(measurements)):
        m = np.asarray(measurements[i])
        for j in range(ekf_state['num_landmarks']):
            z_hat, H = laser_measurement_model(ekf_state, j)

            each_r = (m - z_hat).T
            S = np.matmul(np.matmul(H, ekf_state['P']), H.T) + Q.T
            mahal = np.matmul(np.matmul(each_r.T, np.linalg.inv(S)), each_r)
            M[i][j] = mahal

    M = np.hstack((M, append_M))
    result = slam_utils.solve_cost_matrix_heuristic(M.copy())

    assoc = [-2] * len(measurements)
    for (i, j) in result:
        if j < ekf_state['num_landmarks']:
            assoc[i] = j
        else:
            if np.min(M[i, :ekf_state['num_landmarks']]) > chi2.ppf(0.99,
                                                                    df=2):
                assoc[i] = -1

    return assoc
Exemple #5
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    ###
    # Implement this function.
    ###
    # print(ekf_state["num_landmarks"])

    P = ekf_state['P']
    R = np.diag([sigmas['range']**2, sigmas['bearing']**2])

    A = np.full((len(measurements), len(measurements)), chi2.ppf(0.96, df=2))
    cost_mat = np.full((len(measurements), ekf_state['num_landmarks']),
                       chi2.ppf(0.96, df=2))

    for k in range(0, len(measurements)):
        for j in range(0, ekf_state['num_landmarks']):
            z_hat, H = laser_measurement_model(ekf_state, j)
            # print(measurements[k][0:2])
            r = np.array(np.array(measurements[k][0:2]) - np.array(z_hat))
            S_inv = np.linalg.inv(
                np.matmul(np.matmul(H, P), np.transpose(H)) + R)
            MD = np.matmul(np.matmul(np.transpose(r), S_inv), r)
            cost_mat[k, j] = MD

    cost_mat_conc = np.concatenate((cost_mat, A), axis=1)
    temp1 = np.copy(cost_mat)
    results = slam_utils.solve_cost_matrix_heuristic(temp1)

    assoc = np.zeros(len(measurements), dtype=np.int32)
    for k in range(0, len(results)):
        # print(cost_mat[results[k][0],results[k][1]])
        if cost_mat_conc[results[k][0], results[k][1]] > chi2.ppf(0.99, df=2):
            assoc[results[k][0]] = -1
        elif cost_mat_conc[results[k][0], results[k][1]] >= chi2.ppf(0.95,
                                                                     df=2):
            assoc[results[k][0]] = -2
        else:
            assoc[results[k][0]] = results[k][1]

    return assoc
Exemple #6
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        # assoc = np.zeros((len(measurements),1))
        # assoc = np.asarray([-1])
        return [-1 for m in measurements]

    ###
    # Implement this function.
    ###

    Qt = np.diag([sigmas['range']**2, sigmas['bearing']**2])
    zk = np.asarray(measurements)

    n_landmarks = ekf_state['num_landmarks']
    n_measurements = zk.shape[0]
    M = np.zeros((n_measurements, n_landmarks))

    # Thresholds for classifying as New or Ambiguous Landmarks
    alpha = chi2.ppf(0.95, 2)
    beta = chi2.ppf(0.99, 2)

    for k in range(n_landmarks):
        zhat, H = laser_measurement_model(ekf_state, k)
        S = np.matmul(H, np.matmul(ekf_state['P'], H.T)) + Qt
        Sinv = slam_utils.invert_2x2_matrix(S)
        innovation = zk[:, :2] - zhat.T
        M[:, k] = np.sum(innovation.T * np.matmul(Sinv, innovation.T), axis=0)

    # Augmented Matrix with Cost Matrix
    pairs = slam_utils.solve_cost_matrix_heuristic(
        np.hstack((M, alpha * np.ones((n_measurements, n_measurements)))))
    pairs.sort()
    pairs = np.asarray(pairs)
    assoc = pairs[:, 1]
    assoc = np.where(assoc >= n_landmarks, -1, assoc)

    for i in range(assoc.shape[0]):
        if assoc[i] == -1 and np.any(M[i, :] < beta):
            assoc[i] = -2

    return assoc
Exemple #7
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]
    ###
    # Implement this function.
    ###
    assoc = [-1 for m in measurements]

    n = ekf_state['num_landmarks']
    m = len(measurements)

    M = np.zeros([m, n])
    Q = np.eye(2)
    Q[0, 0] = sigmas['range']**2
    Q[1, 1] = sigmas['bearing']**2
    for j in range(n):
        zhat, H = laser_measurement_model(ekf_state, j)
        S = multi_dot([H, ekf_state['P'], H.T]) + Q
        for i, item in enumerate(measurements):
            r = np.array([item[0], item[1]]).reshape((2, 1)) - zhat
            M[i, j] = multi_dot([r.T, np.linalg.inv(S), r])

    alpha = chi2.ppf(0.95, df=2)
    K = alpha * np.ones([m, m])
    Mk = np.hstack([M, K])

    result = slam_utils.solve_cost_matrix_heuristic(Mk)
    beta = chi2.ppf(0.99, df=2)
    for i, j in result:
        if j < n:
            assoc[i] = j
        else:
            assoc[i] = -2
            if min(M[i, :]) > beta:
                assoc[i] = -1

    return assoc
Exemple #8
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    ###
    P = ekf_state["P"].copy()
    n = ekf_state['num_landmarks']

    m = len(measurements)
    cost_matrix = np.zeros([m, n + 1])
    cost_matrix[:, n] = chi2.ppf(0.99, 2)

    R = np.diag([sigmas['range']**2, sigmas['bearing']**2])

    for i in range(n):
        zhat, H = laser_measurement_model(ekf_state, i)

        S = np.dot(np.dot(H, P), H.transpose()) + R
        inv_S = slam_utils.invert_2x2_matrix(S)
        for j in range(m):
            update = np.asarray(measurements[j][0:2]) - zhat.flatten()
            cost_matrix[j, i] = np.dot(np.dot(update.transpose(), inv_S),
                                       update)

    result = slam_utils.solve_cost_matrix_heuristic(cost_matrix)

    assoc = [0] * m
    for i, j in result:
        if j < ekf_state["num_landmarks"]:
            assoc[i] = j
        else:
            if min(cost_matrix[i, 0:]) < chi2.ppf(0.99, 2):
                assoc[i] = -2
            else:
                assoc[i] = -1

    return assoc
Exemple #9
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        return [-1 for m in measurements]

    n_lmark = ekf_state['num_landmarks']
    n_scans = len(measurements)
    M = np.zeros((n_scans, n_lmark))
    Q_t = np.array([[sigmas['range']**2, 0], [0, sigmas['bearing']**2]])

    alpha = chi2.ppf(0.95, 2)
    beta = chi2.ppf(0.99, 2)
    A = alpha*np.ones((n_scans, n_scans))

    for i in range(n_lmark):
        zhat, H = laser_measurement_model(ekf_state, i)
        S = np.matmul(H, np.matmul(ekf_state['P'],H.T)) + Q_t
        Sinv = slam_utils.invert_2x2_matrix(S)
        for j in range(n_scans):
            temp_z = measurements[j][:2]
            res = temp_z - np.squeeze(zhat)
            M[j, i] = np.matmul(res.T, np.matmul(Sinv, res))

    M_new = np.hstack((M, A))
    pairs = slam_utils.solve_cost_matrix_heuristic(M_new)
    pairs.sort()

    pairs = list(map(lambda x:(x[0],-1) if x[1]>=n_lmark else (x[0],x[1]),pairs))
    assoc = list(map(lambda x:x[1],pairs))

    for i in range(len(assoc)):
        if assoc[i] == -1:
            for j in range(M.shape[1]):
                if M[i, j] < beta:
                    assoc[i] = -2
                    break

    return assoc
Exemple #10
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''
    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurement
        return [-1 for m in measurements]
    R = np.array([[sigmas['range'] ** 2, 0], [0, sigmas['bearing'] ** 2]])
    m = ekf_state['num_landmarks']
    measurement_size = len(measurements)
    # To hold the cost. rows are old measurements and columns are new ones
    M = np.zeros((measurement_size, m))
    # todo vectorize this
    measurements_np = np.array(measurements)[:, :2]
    for j in range(m):
        curr_pos, H = laser_measurement_model(ekf_state, j)
        S = np.matmul(np.matmul(H, ekf_state['P']), H.T) + R
        for i in range(measurement_size):
            # x_L, y_L = slam_utils.tree_to_global_xy(measurements_np[np.newaxis, i], ekf_state)
            # x, y = slam_utils.tree_to_global_xy(curr_pos[np.newaxis,:], ekf_state)
            # M[i,j] = np.sqrt((x_L - x)**2 + (y_L - y)**2)
            r = measurements_np[i] - curr_pos
            M[i, j] = np.matmul(np.matmul(r.T, np.linalg.inv(S)), r)
    matches = slam_utils.solve_cost_matrix_heuristic(M.copy())
    assoc = [-1] * measurement_size
    for i in matches:
        if M[i] > 15:
            assoc[i[0]] = -1
        elif M[i] > chi2.ppf(.995, df=2):
            assoc[i[0]] = -2
        else:
            assoc[i[0]] = i[1]
    return assoc
Exemple #11
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''
    # print('assoc')
    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]
    else:
        B = 5.991 * np.ones((len(measurements), len(measurements)))
        M = np.zeros((len(measurements), ekf_state['num_landmarks']))
        Q = np.diag([sigmas['range']**2, sigmas['bearing']**2])
        P = ekf_state['P']
        Zm = np.array(measurements)[:, 0:2]
        for i in range(ekf_state['num_landmarks']):
            zhat, H = laser_measurement_model(ekf_state, i)
            Sinv = np.linalg.inv(np.matmul(np.matmul(H, P), H.T) + Q.T)
            r = Zm - zhat
            M[:, i] = mahalanobisDist(r, Sinv)

        Mpad = np.concatenate((M, B), axis=1)
        C = slam_utils.solve_cost_matrix_heuristic(Mpad)
        assoc = [-2] * len(measurements)
        for c in C:
            if c[1] < ekf_state['num_landmarks']:
                assoc[c[0]] = c[1]
            elif np.min(M[c[0], :]) > 9.21:  # 9.21
                assoc[c[0]] = -1

    return assoc
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from 
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    ###
    # Implement this function.
    ###
    cor = ekf_state['P']
    num_obs = len(measurements)
    measurements = np.array(measurements)[:, :2]
    assoc = np.full([
        num_obs,
    ], -2)
    num_mark = ekf_state['num_landmarks']
    M = np.zeros([num_obs, num_mark])
    Q = np.diag([sigmas['range']**2, sigmas['bearing']**2])
    for i in range(num_mark):

        zhat, H = laser_measurement_model(ekf_state, i)
        S = H.dot(cor).dot(H.T) + Q.T
        for j in range(num_obs):
            r = (measurements[j, :] - zhat).reshape([2, 1])
            M[j, i] = r.T.dot(slam_utils.invert_2x2_matrix(S)).dot(r)
    if num_mark >= num_obs:
        pos = np.array(slam_utils.solve_cost_matrix_heuristic(M.copy()))
        posx = pos[:, 0]
        posy = pos[:, 1]
        value = M[posx, posy]
        ind_update = np.where(value >= 9.2103)
        ind_discard = np.where((value > 5.9915) & (value < 9.2103))
        pos[ind_update, 1] = -1
        pos[ind_discard, 1] = -2
        assoc[pos[:, 0]] = pos[:, 1]
    else:
        A1 = np.full([num_obs, num_obs], 5.99)
        A2 = np.full([num_obs, num_obs], 9.21)

        M_exp1 = np.concatenate([M, A1], axis=1)
        M_exp2 = np.concatenate([M, A2], axis=1)
        pos1 = np.array(slam_utils.solve_cost_matrix_heuristic(M_exp1.copy()))
        pos2 = np.array(slam_utils.solve_cost_matrix_heuristic(M_exp2.copy()))
        posx1 = pos1[:, 0]
        posy1 = pos1[:, 1]
        posx2 = pos2[:, 0]
        posy2 = pos2[:, 1]
        assoc[posx1[posy1 < num_mark]] = posy1[posy1 < num_mark]
        assoc[posx2[posy2 >= num_mark]] = -1

    # assoc=slam.compute_data_association(ekf_state, measurements, sigmas, params)

    return assoc
import numpy as np
import slam_utils
m = np.array([[1, 2, 4], [6, 7, 8], [6, 3, 9], [6, 3, 9], [6, 3, 9]])
print(np.argsort(m.min(axis=1)))
a = slam_utils.solve_cost_matrix_heuristic(m)
print(m)
Exemple #14
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    """
    Computes measurement data association.
    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from
    measurements to landmarks.
    :param ekf_state:
    :param measurements:
    :param sigmas:
    :param params:
    :return:
    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    """

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for _ in measurements]

    range_noise = sigmas['range']
    bearing_noise = sigmas['bearing']
    Q = np.diag((range_noise**2, bearing_noise**2))

    n_measurements = len(measurements)
    n_landmarks = ekf_state["num_landmarks"]
    P = ekf_state['P'].copy()
    assoc = [-2 for _ in range(n_measurements)]
    M = np.zeros((n_measurements, n_landmarks))

    for i in range(n_landmarks):
        z_t, H = laser_measurement_model(ekf_state, i)

        for j in range(n_measurements):

            z = np.asarray(measurements[j][0:2]).reshape((2, 1))
            r = z - z_t
            S = np.dot(np.dot(H, P), H.T) + Q
            d = np.dot(np.dot(r.T, slam_utils.invert_2x2_matrix(S)), r)
            M[j, i] = d

    # threshold for ambiguity
    alpha = chi2.ppf(0.95, df=2)
    A = alpha * np.ones((n_measurements, n_measurements))
    M_new = np.concatenate((M, A), axis=1)
    result = slam_utils.solve_cost_matrix_heuristic(M_new)
    result = np.asarray(result)

    update_index = result[:, 1] < n_landmarks
    result_update = result[update_index]

    for i in range(len(result_update)):
        assoc[result_update[i, 0]] = result_update[i, 1]

    remain_index = ~update_index

    for i in range(len(M)):
        if (remain_index[i]
                and np.min(M[result[i, 0], :]) >= chi2.ppf(0.9999999, df=2)):
            assoc[result[i, 0]] = -1
        elif (remain_index[i]
              and np.min(M[result[i, 0], :]) < chi2.ppf(0.9999999, df=2)):
            assoc[result[i, 0]] = -2

    return assoc
Exemple #15
0
def compute_data_association(ekf_state, measurements, sigmas, params):
    '''
    Computes measurement data association.

    Given a robot and map state and a set of (range,bearing) measurements,
    this function should compute a good data association, or a mapping from
    measurements to landmarks.

    Returns an array 'assoc' such that:
        assoc[i] == j if measurement i is determined to be an observation of landmark j,
        assoc[i] == -1 if measurement i is determined to be a new, previously unseen landmark, or,
        assoc[i] == -2 if measurement i is too ambiguous to use and should be discarded.
    '''

    if ekf_state["num_landmarks"] == 0:
        # set association to init new landmarks for all measurements
        return [-1 for m in measurements]

    ###
    # Implement this function.
    ###
    state = ekf_state['x']
    xv = state[0]
    yv = state[1]
    phi = state[2]

    R = np.eye(2)
    R[0, 0] = sigmas['range']**2
    R[1, 1] = sigmas['bearing']**2

    num_measurements = len(measurements)
    num_landmarks = ekf_state["num_landmarks"]
    M = np.ones(
        (num_measurements, num_measurements + num_landmarks)) * chi2.ppf(
            0.95, 2)
    for i, m in enumerate(measurements):
        for j in range(num_landmarks):
            zhat, full_H = laser_measurement_model(ekf_state, j)

            # P = np.zeros((5,5))
            # P[:3, :3] = ekf_state['P'][:3, :3]
            # P[3:, 3:] = ekf_state['P'][3+j*2:3+(j+1)*2, 3+j*2:3+(j+1)*2]
            # P[3:, :3] = ekf_state['P'][3+j*2:3+(j+1)*2, :3]
            # P[:3, 3:] = ekf_state['P'][:3, 3+j*2:3+(j+1)*2]
            P = ekf_state['P']

            # H = np.zeros((2,5))
            # H[:2, :3] = full_H[:2, :3]
            # H[:2, 3:] = full_H[:2, 3+j*2:3+(j+1)*2]
            H = full_H

            r = np.vstack([m[0], m[1]]) - zhat
            S = np.dot(np.dot(H, P), H.T) + R

            M[i, j] = np.dot(np.dot(r.T, np.linalg.inv(S)), r)

    matchings = slam_utils.solve_cost_matrix_heuristic(M.copy())
    # row_ind, col_ind = linear_sum_assignment(M.copy())
    # matchings = list(zip(row_ind, col_ind))
    assoc = [-2 for m in measurements]
    for m in matchings:
        if m[1] >= num_landmarks and np.min(
                M[m[0], :num_landmarks]) > chi2.ppf(0.99, 2):
            assoc[m[0]] = -1
        elif m[1] >= num_landmarks:
            continue
        else:
            assoc[m[0]] = m[1]

    return assoc