Bugfixing monte carlo
This commit is contained in:
parent
9b98bd4db7
commit
d3e128e010
@ -13,6 +13,8 @@ boundary_lines = [
|
|||||||
width = 1500
|
width = 1500
|
||||||
height = 1500
|
height = 1500
|
||||||
|
|
||||||
|
# need to state clearly the orientation of the heading
|
||||||
|
# if coordinates 0, 0 is bottom left, then heading 0 is right, with heading increasing anticlockwise.
|
||||||
|
|
||||||
def point_is_inside_arena(x, y):
|
def point_is_inside_arena(x, y):
|
||||||
"""Return True if the point is inside the arena.
|
"""Return True if the point is inside the arena.
|
||||||
@ -46,7 +48,7 @@ def get_ray_distance_to_segment_squared(ray, segment):
|
|||||||
# calculate the x value of the intersection point
|
# calculate the x value of the intersection point
|
||||||
intersection_x = ray_x + (segment_y1 - ray_y) / math.tan(ray_heading)
|
intersection_x = ray_x + (segment_y1 - ray_y) / math.tan(ray_heading)
|
||||||
# is the intersection point on the segment?
|
# is the intersection point on the segment?
|
||||||
if intersection_x < segment_x1 or intersection_x > segment_x2:
|
if intersection_x > max(segment_x1, segment_x2) or intersection_x < min(segment_x1, segment_x2):
|
||||||
return None
|
return None
|
||||||
# calculate the distance from the ray origin to the intersection point
|
# calculate the distance from the ray origin to the intersection point
|
||||||
return (intersection_x - ray_x) ** 2 + (segment_y1 - ray_y) ** 2
|
return (intersection_x - ray_x) ** 2 + (segment_y1 - ray_y) ** 2
|
||||||
@ -55,13 +57,13 @@ def get_ray_distance_to_segment_squared(ray, segment):
|
|||||||
# if the ray is vertical, it will never intersect the segment
|
# if the ray is vertical, it will never intersect the segment
|
||||||
if ray_heading == math.pi / 2:
|
if ray_heading == math.pi / 2:
|
||||||
return None
|
return None
|
||||||
# calculate the y value of the intersection point
|
# calculate the y value of the intersection point
|
||||||
intersection_y = ray_y + (segment_x1 - ray_x) * math.tan(ray_heading)
|
intersection_y = ray_y + (segment_x1 - ray_x) * math.tan(ray_heading)
|
||||||
# is the intersection point on the segment?
|
# is the intersection point on the segment?
|
||||||
if intersection_y < segment_y1 or intersection_y > segment_y2:
|
if intersection_y > max(segment_y1, segment_y2) or intersection_y < min(segment_y1, segment_y2):
|
||||||
return None
|
return None
|
||||||
# calculate the distance from the ray origin to the intersection point
|
# calculate the distance from the ray origin to the intersection point
|
||||||
return (segment_x1 - ray_x) ** 2 + (intersection_y - ray_y) ** 2
|
return (intersection_y - ray_y) ** 2 + (segment_x1 - ray_x) ** 2
|
||||||
else:
|
else:
|
||||||
raise Exception("Segment is not horizontal or vertical")
|
raise Exception("Segment is not horizontal or vertical")
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@ class Simulation:
|
|||||||
self.population_size = 200
|
self.population_size = 200
|
||||||
self.left_distance = 100
|
self.left_distance = 100
|
||||||
self.right_distance = 100
|
self.right_distance = 100
|
||||||
self.occupancy_grid = arena.get_binary_occupancy_grid()
|
|
||||||
self.time_step = 0.1
|
self.time_step = 0.1
|
||||||
# Poses - each an array of [x, y, heading]
|
# Poses - each an array of [x, y, heading]
|
||||||
self.poses = np.array(
|
self.poses = np.array(
|
||||||
@ -33,7 +32,7 @@ class Simulation:
|
|||||||
self.turn_pid = pid_controller.PIDController(0.1, 0.01, 0.01)
|
self.turn_pid = pid_controller.PIDController(0.1, 0.01, 0.01)
|
||||||
self.distance_aim = 100
|
self.distance_aim = 100
|
||||||
|
|
||||||
def apply_sensor_model(self, distance_left, distance_right):
|
def apply_sensor_model(self):
|
||||||
# Based on vl53l1x sensor readings, create weight for each pose.
|
# Based on vl53l1x sensor readings, create weight for each pose.
|
||||||
# vl53l1x standard dev is +/- 5 mm. Each distance is a mean reading
|
# vl53l1x standard dev is +/- 5 mm. Each distance is a mean reading
|
||||||
# we will first determine sensor positions based on poses
|
# we will first determine sensor positions based on poses
|
||||||
@ -42,12 +41,13 @@ class Simulation:
|
|||||||
# and weight accordingly
|
# and weight accordingly
|
||||||
|
|
||||||
# distance sensor positions projected forward. left_x, left_y, right_x, right_y
|
# distance sensor positions projected forward. left_x, left_y, right_x, right_y
|
||||||
distance_sensor_positions = np.array(
|
distance_sensor_positions = np.zeros(
|
||||||
(self.poses.shape[0], 6), dtype=np.float)
|
(self.poses.shape[0], 4), dtype=np.float)
|
||||||
# sensors - they are facing forward, either side of the robot. Project them out to the sides
|
# sensors - they are facing forward, either side of the robot. Project them out to the sides
|
||||||
# based on each poses heading
|
# based on each poses heading
|
||||||
# left sensor
|
# left sensor
|
||||||
poses_left_90 = np.radians(self.poses[:, 2] + 90)
|
poses_left_90 = np.radians(self.poses[:, 2] + 90)
|
||||||
|
# print("poses_left_90_shape:",poses_left_90.shape, "distance_sensor_positions_shape:",distance_sensor_positions.shape, "poses_shape:",self.poses.shape)
|
||||||
distance_sensor_positions[:, 0] = self.poses[:, 0] + np.cos(poses_left_90) * robot.distance_sensor_from_middle
|
distance_sensor_positions[:, 0] = self.poses[:, 0] + np.cos(poses_left_90) * robot.distance_sensor_from_middle
|
||||||
distance_sensor_positions[:, 1] = self.poses[:, 1] + np.sin(poses_left_90) * robot.distance_sensor_from_middle
|
distance_sensor_positions[:, 1] = self.poses[:, 1] + np.sin(poses_left_90) * robot.distance_sensor_from_middle
|
||||||
# right sensor
|
# right sensor
|
||||||
@ -56,8 +56,8 @@ class Simulation:
|
|||||||
distance_sensor_positions[:, 3] = self.poses[:, 1] + np.sin(poses_right_90) * robot.distance_sensor_from_middle
|
distance_sensor_positions[:, 3] = self.poses[:, 1] + np.sin(poses_right_90) * robot.distance_sensor_from_middle
|
||||||
# for each sensor position, find the distance to the nearest obstacle
|
# for each sensor position, find the distance to the nearest obstacle
|
||||||
distance_sensor_standard_dev = 5
|
distance_sensor_standard_dev = 5
|
||||||
dl_squared = distance_left ** 2
|
dl_squared = self.left_distance ** 2
|
||||||
dr_squared = distance_right ** 2
|
dr_squared = self.right_distance ** 2
|
||||||
|
|
||||||
# weighted poses a numpy array of weights for each pose
|
# weighted poses a numpy array of weights for each pose
|
||||||
weights = np.empty(self.poses.shape[0], dtype=np.float)
|
weights = np.empty(self.poses.shape[0], dtype=np.float)
|
||||||
@ -69,15 +69,21 @@ class Simulation:
|
|||||||
weights[index] = 0
|
weights[index] = 0
|
||||||
continue
|
continue
|
||||||
# left sensor
|
# left sensor
|
||||||
left_ray = sensor_position[0], sensor_position[1], self.poses[index, 2]
|
left_ray = sensor_position[0], sensor_position[1], np.radians(self.poses[index, 2])
|
||||||
noise = get_gaussian_sample(0, distance_sensor_standard_dev)
|
noise = get_gaussian_sample(0, distance_sensor_standard_dev)
|
||||||
left_actual = arena.get_ray_distance_squared_to_nearest_boundary_segment(left_ray) + noise
|
left_actual = arena.get_ray_distance_squared_to_nearest_boundary_segment(left_ray)
|
||||||
left_error = abs(left_actual - dl_squared) # error
|
if left_actual is None:
|
||||||
|
print("left_actual is None. Ray was ", left_ray)
|
||||||
|
left_actual = 100
|
||||||
|
left_error = abs(left_actual - dl_squared + noise) # error
|
||||||
# right sensor
|
# right sensor
|
||||||
right_ray = sensor_position[2], sensor_position[3], self.poses[index, 2]
|
right_ray = sensor_position[2], sensor_position[3], np.radians(self.poses[index, 2])
|
||||||
noise = get_gaussian_sample(0, distance_sensor_standard_dev)
|
noise = get_gaussian_sample(0, distance_sensor_standard_dev)
|
||||||
right_actual = arena.get_ray_distance_squared_to_nearest_boundary_segment(right_ray) + noise
|
right_actual = arena.get_ray_distance_squared_to_nearest_boundary_segment(right_ray)
|
||||||
right_error = abs(right_actual - dr_squared) #error
|
if right_actual is None:
|
||||||
|
print("right_actual is None. Ray was ", right_ray)
|
||||||
|
right_actual = 100
|
||||||
|
right_error = abs(right_actual - dr_squared + noise) #error
|
||||||
# weight is the inverse of the error
|
# weight is the inverse of the error
|
||||||
weights[index] = 1 / (left_error + right_error)
|
weights[index] = 1 / (left_error + right_error)
|
||||||
|
|
||||||
|
|||||||
30
ch-13/full-version/robot/test_arena.py
Normal file
30
ch-13/full-version/robot/test_arena.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
import math
|
||||||
|
import arena
|
||||||
|
|
||||||
|
class TestArena(TestCase):
|
||||||
|
def test_get_ray_distance_to_segment_squared_is_not_none(self):
|
||||||
|
"""Use an example ray, test we get a distance squared (not none)"""
|
||||||
|
ray = (253.415, 85.2855, 0.479889)
|
||||||
|
segment = arena.boundary_lines[4]
|
||||||
|
distance_squared = arena.get_ray_distance_to_segment_squared(ray, segment)
|
||||||
|
self.assertIsNotNone(distance_squared)
|
||||||
|
|
||||||
|
def test_get_distance_squared_for_vertical_ray(self):
|
||||||
|
"""Make a vertical ray, say at y=1000, x=500, heading=pi/2, and test we get the correct distance squared"""
|
||||||
|
ray = (500, 1000, math.pi / 2)
|
||||||
|
segment = arena.boundary_lines[1]
|
||||||
|
distance_squared = arena.get_ray_distance_to_segment_squared(ray, segment)
|
||||||
|
self.assertEqual(distance_squared, 500 ** 2)
|
||||||
|
|
||||||
|
def test_get_distance_squared_for_vertical_with_nearest_segment(self):
|
||||||
|
"""Make a vertical ray, say at y=1000, x=500, heading=pi/2, and test we get the correct distance squared"""
|
||||||
|
ray = (500, 1000, math.pi / 2)
|
||||||
|
distance_squared = arena.get_ray_distance_squared_to_nearest_boundary_segment(ray)
|
||||||
|
self.assertEqual(distance_squared, 500 ** 2)
|
||||||
|
|
||||||
|
def test_get_distance_squared_for_horizontal_ray(self):
|
||||||
|
"""Make a horizontal ray, say at y=500, x=1000, heading=0, and test we get the correct distance squared"""
|
||||||
|
ray = (500, 250, 0)
|
||||||
|
distance_squared = arena.get_ray_distance_squared_to_nearest_boundary_segment(ray)
|
||||||
|
self.assertEqual(distance_squared, 500 ** 2)
|
||||||
Loading…
x
Reference in New Issue
Block a user