Lab 10
Functions
def compute_control(cur_pose, prev_pose):
""" Given the current and previous odometry poses, this function extracts
the control information based on the odometry motion model.
Args:
cur_pose ([Pose]): Current Pose
prev_pose ([Pose]): Previous Pose
Returns:
[delta_rot_1]: Rotation 1 (degrees)
[delta_trans]: Translation (meters)
[delta_rot_2]: Rotation 2 (degrees)
"""
delta_rot_1 = mapper.normalize_angle(np.degrees(np.arctan2(np.radians(cur_pose[1] - prev_pose[1]),np.radians(cur_pose[0]-prev_pose[0]))-np.radians(cur_pose[2])))
delta_trans = np.sqrt((cur_pose[0] - prev_pose[0])**2 + (cur_pose[1] - prev_pose[1])**2)
delta_rot_2 = mapper.normalize_angle(cur_pose[2] - prev_pose[2] - delta_rot_1)
return delta_rot_1, delta_trans, delta_rot_2
def odom_motion_model(cur_pose, prev_pose, u):
""" Odometry Motion Model
Args:
cur_pose ([Pose]): Current Pose
prev_pose ([Pose]): Previous Pose
(rot1, trans, rot2) (float, float, float): A tuple with control data in the format
format (rot1, trans, rot2) with units (degrees, meters, degrees)
Returns:
prob [float]: Probability p(x'|x, u)
"""
delta_rot_1, delta_trans, delta_rot_2 = compute_control(cur_pose, prev_pose)
prob_rot_1 = loc.gaussian(delta_rot_1, u[0], loc.odom_rot_sigma)
prob_trans = loc.gaussian(delta_trans, u[1], loc.odom_trans_sigma)
prob_rot_2 = loc.gaussian(delta_rot_2, u[2], loc.odom_rot_sigma)
prob = prob_rot_1 * prob_trans * prob_rot_2
return prob
def prediction_step(cur_odom, prev_odom):
""" Prediction step of the Bayes Filter.
Update the probabilities in loc.bel_bar based on loc.bel from the previous time step and the odometry motion model.
Args:
cur_odom ([Pose]): Current Pose
prev_odom ([Pose]): Previous Pose
"""
u = compute_control(cur_odom, prev_odom)
for x_prev in range(mapper.MAX_CELLS_X):
for y_prev in range(mapper.MAX_CELLS_Y):
for th_prev in range(mapper.MAX_CELLS_A):
if(loc.bel_bar[x_prev,y_prev,th_prev] < 0.0001): # skip loop if belief too low
continue
for x in range(mapper.MAX_CELLS_X):
for y in range(mapper.MAX_CELLS_Y):
for th in range(mapper.MAX_CELLS_A):
prev_pose = mapper.from_map(x_prev, y_prev, th_prev)
cur_pose = mapper.from_map(x, y, th)
trans_prob = odom_motion_model(cur_pose, prev_pose, u)
loc.bel_bar[x, y, th] += trans_prob*loc.bel[x_prev, y_prev, th_prev]
# normalize
loc.bel_bar = loc.bel_bar/np.sum(loc.bel_bar)
def sensor_model(obs):
""" This is the equivalent of p(z|x).
Args:
obs ([ndarray]): A 1D array consisting of the true observations for a specific robot pose in the map
Returns:
[ndarray]: Returns a 1D array of size 18 (=loc.OBS_PER_CELL) with the likelihoods of each individual sensor measurement
"""
prob_array = np.zeros(18)
for i in range(0,mapper.OBS_PER_CELL):
prob_array[i] = loc.gaussian(lc.obs_range_data[i], obs[i], loc.sensor_sigma)
return prob_array
def update_step():
""" Update step of the Bayes Filter.
Update the probabilities in loc.bel based on loc.bel_bar and the sensor model.
"""
obs = np.empty((mapper.MAX_CELLS_X, mapper.MAX_CELLS_Y, mapper.MAX_CELLS_A, mapper.OBS_PER_CELL))
obs[:,:,:] = loc.obs_range_data.flatten()
p = np.prod(loc.gaussian(mapper.obs_views, obs, loc.sensor_sigma), axis = 3)
prods = np.multiply(p, loc.bel_bar)
loc.bel = prods/np.sum(prods)
loc.bel = loc.bel/np.sum(loc.bel)
Conclusion
The bayes filter probably works best in more open or structured regions where the robot likely has strong sensor observations or landmarks to match to. Belief deteriorates in areas with fewer unique features, or in the end when there is an accumulation of heading drift. Overall the belief of the robots position is pretty accurate. The odometry, however, is completely off.
Resources Used:
Back to Home