00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 import mongo_ros as mr
00038 import logging
00039 import semanticmodel.msg as msg
00040 import numpy as np
00041 import semanticmodel.plane_data_association as pd
00042 import semanticmodel.db as sdb
00043 import math
00044
00045 log = logging.getLogger('world_model.diffs')
00046 TOL = 0.1
00047
00048 def generate_diffs(run1, run2, db):
00049 """
00050 Generate diffs between run1 and run2, which must have been
00051 produced by the blob storage system.
00052
00053 @type run1: string
00054 @type run2: string
00055 @param db: the name of the overall database
00056 """
00057 log.debug("Getting diffs between {0} and {1}".format(run1, run2))
00058 matches = []
00059 nonmatches = []
00060 for run in (run1, run2):
00061 other = run1 if run is run2 else run2
00062 log.debug("Processing {0}, and looking for matches in {1}".
00063 format(run, other))
00064 c1 = mr.MessageCollection(db, sdb.collection_name(run, 'blobs'),
00065 msg.BlobMessage)
00066 c2 = mr.MessageCollection(db, sdb.collection_name(other, 'blobs'),
00067 msg.BlobMessage)
00068 for cluster, meta in c1.query({}):
00069 log.debug("Considering cluster {0[id]} at {0[x]}, {0[y]}".
00070 format(meta))
00071 match = find_matching_cluster(cluster, meta, c2)
00072 if match and run is run1:
00073 log.debug(" Found match {0[id]} at {0[x]}, {0[y]}".
00074 format(match[1]))
00075 matches.append((meta['id'], match[1]['id']))
00076 else:
00077 nearby = next(nearby_clusters(meta, c2), None)
00078 if nearby and run is run1:
00079 nonmatches.append((meta['id'], nearby[1]['id']))
00080
00081 return {'matches': matches, 'nonmatches': nonmatches}
00082
00083 def nearby_clusters(m, c2):
00084 x = m['x']
00085 y = m['y']
00086 return c2.query({'x': {'$gt': x-1.0, '$lt': x+1.0},
00087 'y': {'$gt': y-1.0, '$lt': y+1.0}})
00088
00089
00090 def find_matching_cluster(cluster, meta, c2):
00091 possible_matches = nearby_clusters(meta, c2)
00092 hull = get_hull_polygon(cluster)
00093
00094
00095 for m in possible_matches:
00096 if pd.polygons_intersect(hull, get_hull_polygon(m[0])):
00097 return m
00098
00099 return None
00100
00101
00102 def get_hull_polygon(cluster):
00103 return np.array([(p.x,p.y) for p in cluster.hull])
00104
00105
00106 def dist(p, q):
00107 return math.sqrt(pow(q[0]-p[0],2) + pow(q[1]-p[1],2))
00108
00109
00110 def nearest_nonmatch(cluster, img_coll, max_distance=2.0, max_angle=1.0):
00111 """
00112 A crude and inefficient way to find the nearest nonmatching image.
00113 """
00114 loc = (cluster['x'], cluster['y'])
00115 for img in img_coll.query({}, True):
00116 vp = (img['x'], img['y'])
00117 if dist(vp, loc) < max_distance:
00118 disp = (loc[0]-vp[0], loc[1]-vp[1])
00119 angle = math.atan2(disp[1], disp[0])
00120 if (abs(angle-img['theta'])<max_angle):
00121 return img