Ejemplo n.º 1
0
	def draw(rs, distance, remaining, is_explored=False):
		start_edge_idx = rs.distance_to_edge(distance, return_idx=True)
		for edge_idx in xrange(start_edge_idx, len(rs.edges)):
			edge = rs.edges[edge_idx]
			edge_distance = distance - rs.edge_distances[edge.id]

			start_edge_pos = graph.EdgePos(edge, edge_distance)
			start = start_edge_pos.point()

			if edge_distance + remaining < edge.segment().length():
				end_edge_pos = graph.EdgePos(edge, edge_distance + remaining)
				end = end_edge_pos.point()
			else:
				end = edge.dst.point

			if not is_explored:
				for p in geom.draw_line(start.sub(origin), end.sub(origin), geom.Point(window_size, window_size)):
					p_small = p.scale(128.0 / window_size)
					tile[p_small.x, p_small.y] = 1.0

			remaining -= edge.segment().length() - edge_distance
			distance = rs.edge_distances[edge.id] + edge.segment().length() + 0.001
			if remaining <= 0:
				return

		for next_rs in rs.out_rs(path.gc.edge_to_rs):
			if rs == next_rs or next_rs.is_opposite(rs):
				continue
			draw(next_rs, 0, remaining, is_explored=path.is_explored(next_rs.edges[0]))
Ejemplo n.º 2
0
def vector_to_action(extension_vertex, angle_outputs, threshold):
    # mask out buckets that are similar to existing edges
    blacklisted_buckets = set()
    for edge in extension_vertex.out_edges:
        angle = geom.Point(1, 0).signed_angle(edge.segment().vector())
        bucket = int((angle + math.pi) * 64.0 / math.pi / 2)
        for offset in range(6):
            clockwise_bucket = (bucket + offset) % 64
            counterclockwise_bucket = (bucket + 64 - offset) % 64
            blacklisted_buckets.add(clockwise_bucket)
            blacklisted_buckets.add(counterclockwise_bucket)

    seen_vertices = set()
    search_queue = []
    nearby_points = {}
    seen_vertices.add(extension_vertex)
    for edge in extension_vertex.out_edges:
        search_queue.append((graph.EdgePos(edge, 0), 0))
    while len(search_queue) > 0:
        edge_pos, distance = search_queue[0]
        search_queue = search_queue[1:]
        if distance > 0:
            nearby_points[edge_pos.point()] = distance
        if distance >= 4 * SEGMENT_LENGTH:
            continue

        edge = edge_pos.edge
        l = edge.segment().length()
        if edge_pos.distance + SEGMENT_LENGTH < l:
            search_queue.append(
                (graph.EdgePos(edge, edge_pos.distance + SEGMENT_LENGTH),
                 distance + SEGMENT_LENGTH))
        elif edge.dst not in seen_vertices:
            seen_vertices.add(edge.dst)
            for edge in edge.dst.out_edges:
                search_queue.append(
                    (graph.EdgePos(edge, 0), distance + l - edge_pos.distance))

    # any leftover targets above threshold?
    best_bucket = None
    best_value = None
    for bucket in range(64):
        if bucket in blacklisted_buckets:
            continue
        next_point = model_utils.get_next_point(extension_vertex.point, bucket,
                                                SEGMENT_LENGTH)
        bad = False
        for nearby_point, distance in nearby_points.items():
            if nearby_point.distance(next_point) < 0.5 * (SEGMENT_LENGTH +
                                                          distance):
                bad = True
                break
        if bad:
            continue

        value = angle_outputs[bucket]
        if value > threshold and (best_bucket is None or value > best_value):
            best_bucket = bucket
            best_value = value

    x = numpy.zeros((64, ), dtype='float32')
    if best_bucket is not None:
        x[best_bucket] = best_value
    return x
Ejemplo n.º 3
0
def get_example(traintest='train'):
    while True:
        if traintest == 'train':
            tile = random.choice(train_tiles)
        elif traintest == 'test':
            tile = random.choice(val_tiles)

        edge_ids, edge_probs = get_tile_edgeprobs(tile)
        if len(edge_ids) > 80 or len(edge_ids) > 0:
            break

    # determine rotation factor
    rotation = None
    if ENABLE_ROTATION:
        rotation = random.random() * 2 * math.pi

    rect = get_tile_rect(tile)
    small_rect = rect.add_tol(-WINDOW_SIZE * FETCH_FACTOR / 2)

    # get random edge position
    edge_id = numpy.random.choice(edge_ids, p=edge_probs)
    gc = tiles.get_gc(tile.region)
    edge = gc.graph.edges[edge_id]
    distance = random.random() * edge.segment().length()

    # convert to point and add noise
    point = graph.EdgePos(edge, distance).point()
    if random.random() < PROB_FROM_ROAD:
        if random.random() < 0.2:
            noise_amount = 10 * SEGMENT_LENGTH
        else:
            noise_amount = ROAD_WIDTH / 1.5
        noise = geom.Point(random.random() * 2 * noise_amount - noise_amount,
                           random.random() * 2 * noise_amount - noise_amount)
        point = point.add(noise)
        point = small_rect.clip(point)
    else:
        point = geom.Point(random.randint(0,
                                          small_rect.lengths().x - 1),
                           random.randint(0,
                                          small_rect.lengths().y - 1))
        point = point.add(small_rect.start)
        point = small_rect.clip(point)

    # match point to edge if possible
    threshold = ROAD_WIDTH
    closest_edge = None
    closest_distance = None
    for edge in gc.edge_index.search(point.bounds().add_tol(threshold)):
        d = edge.segment().distance(point)
        if d < threshold and (closest_edge is None or d < closest_distance):
            closest_edge = edge
            closest_distance = d
    closest_pos = None
    if closest_edge is not None:
        closest_pos = closest_edge.closest_pos(point)

    # generate input
    origin = point.sub(geom.Point(WINDOW_SIZE / 2, WINDOW_SIZE / 2))
    tile_origin = origin.sub(rect.start)
    fetch_rect = geom.Rectangle(
        tile_origin,
        tile_origin.add(geom.Point(WINDOW_SIZE, WINDOW_SIZE))).add_tol(
            WINDOW_SIZE * (FETCH_FACTOR - 1) / 2)
    big_ims = tiles.cache.get_window(tile.region, rect, fetch_rect)
    input = big_ims['input'].astype('float32') / 255.0
    if rotation:
        input = scipy.ndimage.interpolation.rotate(input,
                                                   rotation * 180 / math.pi,
                                                   reshape=False,
                                                   order=0)
        input = input[WINDOW_SIZE / 2:3 * WINDOW_SIZE / 2,
                      WINDOW_SIZE / 2:3 * WINDOW_SIZE / 2, :]

    # compute targets
    if closest_edge is not None:
        angle_targets = compute_targets(gc, point, closest_pos)
        if rotation:
            shift = int(rotation * 32 / math.pi)
            new_targets = numpy.zeros((64, ), 'float32')
            for i in xrange(64):
                new_targets[(i + shift) % 64] = angle_targets[i]
            angle_targets = new_targets
    else:
        angle_targets = numpy.zeros((64, ), 'float32')

    detect_targets = numpy.zeros((64 * FETCH_FACTOR, 64 * FETCH_FACTOR, 1),
                                 dtype='float32')
    if not NO_DETECT:
        fetch_rect = geom.Rectangle(
            origin, origin.add(geom.Point(WINDOW_SIZE, WINDOW_SIZE))).add_tol(
                WINDOW_SIZE * (FETCH_FACTOR - 1) / 2)
        for edge in gc.edge_index.search(fetch_rect.add_tol(32)):
            start = edge.src.point.sub(fetch_rect.start).scale(
                float(64) / WINDOW_SIZE)
            end = edge.dst.point.sub(fetch_rect.start).scale(
                float(64) / WINDOW_SIZE)
            for p in geom.draw_line(
                    start, end, geom.Point(64 * FETCH_FACTOR,
                                           64 * FETCH_FACTOR)):
                detect_targets[p.x, p.y, 0] = 1
        if rotation:
            detect_targets = scipy.ndimage.interpolation.rotate(detect_targets,
                                                                rotation *
                                                                180 / math.pi,
                                                                reshape=False,
                                                                order=0)
            detect_targets = detect_targets[32:96, 32:96, :]

    info = {
        'region': tile.region,
        'point': point,
        'origin': origin,
        'closest_pos': closest_pos,
        'rotation': rotation,
    }

    return info, input, angle_targets, detect_targets
Ejemplo n.º 4
0
def compute_targets_by_best(path, extension_vertex, segment_length):
	angle_targets = numpy.zeros((64,), 'float32')
	allow_reconnect = False

	def best_angle_to_pos(pos):
		angle_points = [get_next_point(extension_vertex.point, angle_bucket, segment_length) for angle_bucket in xrange(64)]
		distances = [angle_point.distance(pos.point()) for angle_point in angle_points]
		point_angle = numpy.argmin(distances) * math.pi * 2 / 64.0 - math.pi
		edge_angle = geom.Point(1, 0).signed_angle(pos.edge.segment().vector())
		avg_vector = vector_from_angle(point_angle).add(vector_from_angle(edge_angle))
		avg_angle = geom.Point(1, 0).signed_angle(avg_vector)
		return int((avg_angle + math.pi) * 64.0 / math.pi / 2)

	def set_angle_bucket_soft(target_bucket):
		for offset in xrange(31):
			clockwise_bucket = (target_bucket + offset) % 64
			counterclockwise_bucket = (target_bucket + 64 - offset) % 64
			for bucket in [clockwise_bucket, counterclockwise_bucket]:
				angle_targets[bucket] = max(angle_targets[bucket], pow(0.75, offset))

	def set_by_positions(positions):
		# get existing angle buckets, don't use any that are within 3 buckets
		bad_buckets = set()
		for edge in extension_vertex.out_edges:
			edge_angle = geom.Point(1, 0).signed_angle(edge.segment().vector())
			edge_bucket = int((edge_angle + math.pi) * 64.0 / math.pi / 2)
			for offset in xrange(3):
				clockwise_bucket = (edge_bucket + offset) % 64
				counterclockwise_bucket = (edge_bucket + 64 - offset) % 64
				bad_buckets.add(clockwise_bucket)
				bad_buckets.add(counterclockwise_bucket)

		for pos in positions:
			best_angle_bucket = best_angle_to_pos(pos)
			if best_angle_bucket in bad_buckets:
				continue
			set_angle_bucket_soft(best_angle_bucket)

	if extension_vertex.edge_pos is not None:
		cur_edge = extension_vertex.edge_pos.edge
		cur_rs = path.gc.edge_to_rs[cur_edge.id]
		prev_rs = None

		if len(extension_vertex.in_edges) >= 1:
			prev_vertex = extension_vertex.in_edges[0].src
			if prev_vertex.edge_pos is not None:
				prev_edge = prev_vertex.edge_pos.edge
				prev_rs = path.gc.edge_to_rs[prev_edge.id]

		def get_potential_rs(segment_length, allow_backwards):
			potential_rs = []
			if cur_rs.edge_distances[cur_edge.id] + extension_vertex.edge_pos.distance + segment_length < cur_rs.length():
				potential_rs.append(cur_rs)
			else:
				for rs in cur_rs.out_rs(path.gc.edge_to_rs):
					if rs == cur_rs or rs.is_opposite(cur_rs):
						continue
					potential_rs.append(rs)
			if allow_backwards and cur_rs.edge_distances[cur_edge.id] + extension_vertex.edge_pos.distance < segment_length / 2 and prev_rs is not None:
				for rs in cur_rs.in_rs(path.gc.edge_to_rs):
					if rs == cur_rs or rs.is_opposite(cur_rs) or rs == prev_rs or rs.is_opposite(prev_rs):
						continue

					# add the opposite of this rs so that we are going away from extension_vertex
					opposite_rs = path.gc.edge_to_rs[rs.edges[0].get_opposite_edge().id]
					potential_rs.append(opposite_rs)

			# at very beginning of path, we can go in either direction
			if len(path.graph.edges) == 0:
				# TODO: fix get_opposite_rs for loops
				# currently, if there is a loop, then the rs corresponding to the loop may start at
				#   any point along the loop, and get_opposite_rs will fail
				# I think it may be okay if the loop isn't completely isolated (circle with no
				#   intersections), but definitely it fails for isolated loops
				#potential_rs.append(cur_rs.get_opposite_rs(path.gc.edge_to_rs))
				opposite_rs1 = cur_rs.get_opposite_rs(path.gc.edge_to_rs)
				opposite_rs2 = path.gc.edge_to_rs[cur_rs.edges[-1].get_opposite_edge().id]
				potential_rs.append(opposite_rs2)
				if opposite_rs1 != opposite_rs2:
					if opposite_rs1 is None:
						print 'warning: using opposite_rs2 for rs {}'.format(opposite_rs2.id)
					else:
						raise Exception('opposite_rs1 ({}) != opposite_rs2 ({})'.format(opposite_rs1.id, opposite_rs2.id))

			return potential_rs

		potential_rs = get_potential_rs(segment_length, True)
		potential_far_rs = get_potential_rs(3 * segment_length, False)

		# reconnect if there is a nearby path vertex such that:
		# (1) extension_vertex and the nearby vertex are far in the path graph
		# (2) but close in the ground truth graph
		# (3) and rs is either same as current one, or outgoing from a ground truth vertex that we are entering

		if len(extension_vertex.in_edges) <= 1:
			# first, get outgoing road segments from potential_far_rs
			reconnectable_rs = set([rs for rs in potential_far_rs if path.is_explored(graph.EdgePos(rs.edges[0], 0)) and rs != cur_rs and not cur_rs.is_opposite(rs)])
			reconnectable_rs.add(cur_rs)
			reconnectable_rs.add(path.gc.edge_to_rs[cur_rs.edges[-1].get_opposite_edge().id])

			# now, satisfy 1 and 2, while using set above to satisfy 3
			nearby_path_vertices = set(graph.get_nearby_vertices(extension_vertex, 6))
			gt_distances = graph.shortest_distances_from_source(cur_edge.dst, max_distance=3*segment_length)
			r = extension_vertex.point.bounds().add_tol(3*segment_length)
			for nearby_edge_id in path.edge_rtree.intersection((r.start.x, r.start.y, r.end.x, r.end.y)):
				nearby_edge = path.graph.edges[nearby_edge_id]
				for nearby_vertex in [nearby_edge.src, nearby_edge.dst]:
					if nearby_vertex.edge_pos is None:
						continue
					elif nearby_vertex.point.distance(extension_vertex.point) > 3*segment_length:
						continue
					elif nearby_vertex in nearby_path_vertices:
						continue
					elif path.gc.edge_to_rs[nearby_vertex.edge_pos.edge.id] not in reconnectable_rs:
						continue
					gt_distance = min(
						gt_distances.get(nearby_vertex.edge_pos.edge.src.id, 99999) + nearby_vertex.edge_pos.distance,
						gt_distances.get(nearby_vertex.edge_pos.edge.dst.id, 99999) + nearby_vertex.edge_pos.reverse().distance
					)
					if gt_distance < 3*segment_length:
						allow_reconnect = True

		if len(potential_rs) + 1 > len(extension_vertex.out_edges):
			if DEBUG: print '... compute_targets_by_best: potential_rs={}'.format([rs.id for rs in potential_rs])
			expected_positions = []
			for rs in potential_rs:
				pos = rs.closest_pos(extension_vertex.point)
				if path.is_explored(pos):
					continue
				rs_follow_positions = graph.follow_graph(pos, segment_length, explored_node_pairs=path.explored_pairs)
				if DEBUG: print '... compute_targets_by_best: rs {}: closest pos to extension point {} is on edge {}@{} at {}'.format(rs.id, extension_vertex.point, pos.edge.id, pos.distance, pos.point())
				for rs_follow_pos in rs_follow_positions:
					if DEBUG: print '... compute_targets_by_best: rs {}: ... {}@{} at {}'.format(rs.id, rs_follow_pos.edge.id, rs_follow_pos.distance, rs_follow_pos.point())
				expected_positions.extend(rs_follow_positions)
			set_by_positions(expected_positions)
		else:
			if DEBUG: print '... compute_targets_by_best: found {} potential rs but already have {} outgoing edges'.format(len(potential_rs), len(extension_vertex.out_edges))
	else:
		if DEBUG: print '... compute_targets_by_best: edge_pos is None'

	return angle_targets, allow_reconnect