Lab 7(a): Grid Localization using Bayes Filter
Objective
The purpose of this lab is to write a skeleton Bayes Filter algorithm that will be implemented in the next lab.
# In world coordinates
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 [x y theta]
prev_pose ([Pose]): Previous Pose [x y theta]
Returns:
[delta_rot_1]: Rotation 1 (degrees)
[delta_trans]: Translation (meters)
[delta_rot_2]: Rotation 2 (degrees)
"""
# calculating translation
delta_x = cur_pose[0] - prev_pose[0]
delta_y = cur_pose[1] - prev_pose[1]
delta_trans = np.sqrt(delta_x**2 + delta_y**2)
# calculating rotation 1 and 2
delta_rot_1 = np.arctan2(delta_y,delta_x) - cur_pose[2]
delta_rot_2 = cur_pose[2] - prev_pose[2] - delta_rot_1
return delta_rot_1, delta_trans, delta_rot_2
# In world coordinates
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)
"""
odom_motion = compute_control(cur_pose,prev_pose)
rot1_odom = odom_motion[0]
trans_odom = odom_motion[1]
rot2_odom = odom_motion[2]
rot1_rel = u[0]
trans_rel = u[1]
rot2_rel = u[2]
x1 = rot1_odom - rot1_rel #error in rot1
x2 = rot2_odom - trans_rel #error in trans
x3 = rot3_odom - rot2_rel #error in rot2
sigma1 = odom_rot_sigma #standard deviation for rot1
sigma2 = odom_trans_sigma #standard deviation for trans
sigma3 = odom_rot_sigma #standard deviation for rot2
rot1_prob = gaussian(x1,0,sigma1)
trans_prob = gaussian(x2,0,sigma2)
rot2_prob = gaussian(x3,0,sigma3)
prob = rot1_prob*trans_prob*rot2_prob
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 cur_x in range(MAX_CELLS_X-1): #iterate through current x
for cur_y in range(MAX_CELLS_Y-1): #iterate through current y
for cur_theta in range(MAX_CELLS_A-1): #iterate through current theta
for z in range(obs_views[x,y,theta,:]) #iterate through obs_views to add all the 18 x and y positions inside that grid
[xpos,ypos] += obs_views[cur_x,cur_y,cur_theta,z]
grid_pose = [xpos,ypos]/length(obs_views[x,y,theta,:]) #take the mean of that summed x and y position to find the position of that grid
for prev_x in range(MAX_CELLS_X-1): #iterate through previous x
for prev_y in range(MAX_CELLS_Y-1): #iterate through previous y
for prev_theta in range(MAX_CELLS_A-1): #iterate through previous theta
for z2 in range(obs_views[x,y,theta,:]) #iterate through obs_views to add all the 18 x and y positions inside that grid
[xpos2,ypos2] += obs_views[x,y,theta,z]
prev_pose = [xpos2,ypos2]/length(obs_views[prev_x,prev_y,prev_theta,:]) #take the mean of that summed x and y position to find the position of that grid
loc.bel_bar += odom_motion_model(grid_pose,prev_pose, u) * loc.bel[cur_x,cur_y,cur_theta]#use the given grid pose make prediction for each grid
def sensor_model(zt,xt):
""" This is the equivalent of p(z|x).
Args:
zt ([ndarray]): A 1D array consisting of the measurements made in rotation loop
xt: current state
Returns:
[ndarray]: Returns a 1D array of size 18 (=loc.OBS_PER_CELL) with the likelihood of each individual measurements
"""
for i in range(length(zt)): #iterate through all the measurements
error = zt-xt
prob_array[i] = gaussian(error,0,sigma) #find the probability of measurement given data
return prob_array
def update_step(zt,xt):
""" Update step of the Bayes Filter.
Update the probabilities in loc.bel based on loc.bel_bar and the sensor model.
"""
normalization = 1/(sum of all the bel_bar probabilities)
loc.bel = normalization*sensor_model(zt,,xt)*loc.bel_bar
Lab 7(b): Mapping
Objective
Purpose of this lab is to build a map of my room and to perform PID from last lab.
Procedure
- I allocated a space in my apartment for the robot to roam in.
- I checked if my robot could do a full rotation. I had some difficulty with PID last week, but I was able to manually pick motor speeds that allowed the robot to rotate. My sensor data had significant noise, but this is not unexpected since I was having difficulty with PID controller. I gathered the data and plotted the data points in the polar coordinates in MATLAB.
- I used transformation matrix to convert the data from polar coordinates to cartesian coordinates using the transformation matrix. Using the equation, I was able to get the xy coordinates as shown below.
- I collected data points through line scans and used known positions and orientation of robot. This allowed the transformation matrix to convert the data to cartesian coordinates with origin matched up with the left corner of the map. I drew what the map is supposed to look like with measurements in inches and plotted the collected data from line scans. The line scan did a good job capturing the features of the map, but may had some difficulty getting accurate dimensions. This may be due to the noise of the data.
- I saved the points from the scatter plot above and plotted it in the simulator using plotter.py.