$search
00001 # Software License Agreement (BSD License) 00002 # 00003 # Copyright (c) 2008, Willow Garage, Inc. 00004 # All rights reserved. 00005 # 00006 # Redistribution and use in source and binary forms, with or without 00007 # modification, are permitted provided that the following conditions 00008 # are met: 00009 # 00010 # * Redistributions of source code must retain the above copyright 00011 # notice, this list of conditions and the following disclaimer. 00012 # * Redistributions in binary form must reproduce the above 00013 # copyright notice, this list of conditions and the following 00014 # disclaimer in the documentation and/or other materials provided 00015 # with the distribution. 00016 # * Neither the name of Willow Garage, Inc. nor the names of its 00017 # contributors may be used to endorse or promote products derived 00018 # from this software without specific prior written permission. 00019 # 00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 # POSSIBILITY OF SUCH DAMAGE. 00032 # 00033 # Author: Bhaskara Marthi 00034 00035 # Generation of diffs between two world models 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 # Check if hulls overlap 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