ó
°ÉúWc           @   s   d  d l  Z  d  d l Z d  d l Z d  d l m Z d  d l m Z m Z d e f d     YZ	 d d d  Z
 d   Z d	   Z d S(
   iÿÿÿÿN(   t   LandmarkMap(   t   angle_betweent   get2dRotmatFromYawt	   Localizerc           B   s>   e  Z d    Z d   Z d   Z d   Z d   Z d   Z RS(   c         C   s   t  |  |  _ d  S(   N(   R    t   landmarkMap(   t   selft   mapFilename(    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyt   __init__   s    c         C   s«   t  |  j j  d k rQ t j d d t } |  j j d | d *t j d } n: t j |  j j d d t } t j d d d d g  } d | | f d | d	 d f g S(
   Ni   i   t   dtypei   i    i   gëQžÕ?gq=
×£på?i   (   t   lenR   t   sizet   npt   onest   floatt   pit   array(   R   t   seenLandmarkst   positiont   orientation(    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyt   localize   s    c      	   C   sh   d } d } d } d } d Gt  |  Gd GHt  |  | k  rF d GHd  S|  j | t t t | | | |  S(   Ni   i   t   sawt	   landmarkss%   not enough landmarks seen to localize(   R	   t   Nonet   ransacLocalizet   getModelFromPlaneWorldMatchest   isPlaneWorldInliert   computePlaneWorldError(   R   R   t   nt   mt   kt   d(    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyt   planeWorldLocalize   s    c         C   s[   | d  } g  | D]" } | |  j  j |  d f ^ q } t |  \ } } d | | f g S(   Ni   i    i   (   R   t   getLandmarkMatchesR   (   R   R   t   usingLandmarkst   lt   usingMatchest   camPost   camYaw(    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyt   exact2dLocalize,   s
    
,c	         C   s\  d }	 g  }
 d } d } x|	 | k  r/|	 d 7}	 t |
  d k ret j | |  } g  | D]! } | |  j j | |  f ^ q\ } g  t |  D] } | f ^ q } xK t | d  D]9 } g  t |  D]  } | D] } | | f ^ qÓ qÉ } q¶ Wt | d t d t	 } xW | D]L } g  t
 |  D]& \ } \ } } | | | | f ^ q%} |
 j |  qWn  |
 j   } | |  } t |  t | d  } g  | D]! } | | | | |  j  f ^ q} t d   |  } t |  | k r | | } | | |  } | d k s| | k  r,| } | } q,q q W| d k rDd GHn  d | d | d f g S(   so  
        The "data points" selected for ransac are matches between objects         in seenLandmarks and objects in the map.

        seenLandmarks: the collection of observed landmarks to fit to the map.
        getModelFromMatches: a function that computes a transform from a set         of point matches.
        isInlier: a function that determines whether a landmark should or         should not be considered an "inlier" given a model transform and a map.
        computeError: measures the error of a set of matches given a model.
        n: number of landmarks to assume are inliers from seenLandmarks.         n = 2 for the 2D and 2D+scale case, n = 4 in full 3D.
        m: number of best matches of seen landmarks to consider from the map.
        k: number of iterations before terminating.
        d: number of inliers that a model must have to be considered
        i    i   t   keyt   reversec         S   s   |  d t  k	 S(   Ni   (   t   False(   R   (    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyt   <lambda>c   s    s   no good model found!N(   R   R	   t   randomt   sampleR   R    t   ranget   sortedt   sumt   Truet	   enumeratet   appendt   popt   sett   filter(   R   R   t   getModelFromMatchest   isInliert   computeErrorR   R   R   R   t   it   consideredMatchest	   bestErrort	   bestModelt
   nLandmarksR"   t	   matchSetst   jt   tuplest   _t   tt   sortedTuplest
   indexTuplet   mst   newMatchSett   testMatchest   modelt   seenLandmarksToCheckt   slt   foundMatchest   inlierMatchest   error(    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyR   3   sB    
+"76+
c         C   s   d  S(   N(    (   R   R   R6   (    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyt   qualityLocalizes   s    (   t   __name__t
   __module__R   R   R   R&   R   RN   (    (    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyR      s   					@i   c         C   s   | \ } } |  j  | |  } | j } | j | |  }	 | j | |  }
 g  |	 D] } | |
 k rR | ^ qR } t |  d k r t S| d Sd S(   s>   How do we decide what is and is not an inlier?
    it should be a function of the distances to the nearest point
    that is, both in space and in the distance between their feature vectors
    we could make the inlier status be:
    is the physically-closest landmark the same as the best match in the map?
    This is rigourous, maybe too rigourous.  Could be top-N closest and/or
    top-N matches?  So if the best match is in the top N closest, or if the

    closest is in the top N matches...or if at least one of the top N
    closest is in the top M matches...
    i    N(   t   getLandmarkInWorldCoordsR   t   getClosestLandmarksR    R	   R)   (   t   seenLandmarkRH   R   t   nClosestt   nBestR$   R%   t   mapSeenLandmarkt
   mapSeenPost   closestLandmarkst   bestMatchest   lmt   bestInClosest(    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyR   z   s    	%c         C   sy  |  d  \ \ } } \ } } | j  | j  } t j j |  } | j  | j  } t | | j   } t | j  | j   }	 | t j |  t j |	  }
 t j d t j j | j    } |
 t j |  } t j | d | d  } | j  | j  } t j | d | d  } | | } t |  } | j	 |  } | j  | } | j  | } t j
 | d | d | g  } | | f S(   s  
    Given a pair of matches between landmarks in the image and in the map,
    finds the transform between the world coordinate frame and the camera's
    coordinate frame.  It assumes fixed roll and pitch, so it just returns the
    x and y coordinates, the height above the map, and the yaw.

    A few notes on notation:
    a and b represent the locations of the two landmarks
    c represents the position of the camera in world coordinates
    Ci represents the projection of the camera along z onto the world plane
      (that is, Ci.x = c.x, Ci.y = c.y, and Ci.z = 0)
    angle_xyz represents the angle between lines from points x to y and y to z
    angle_vVsu represents the angle between vectors v and u
    x2y represents a line from point x to point y
    i   i   i    (   R   R   t   linalgt   normR   t   sint   arctan2t   tanR   t   getRotatedLandmarkR   (   t   matchest   aCamt   aMapt   bCamt   bMapt	   a2bVecMapt
   a2bDistMapt	   b2aVecCamt
   angle_abCit
   angle_aCibt   a2CiDistMapt
   angle_Ciact   camAltitudet   angle_a2bVsMapXt	   a2bVecCamt   angle_a2bVsCamXR%   t   rotmatt   aCamRott
   a2CiVecMapt   CiPosR$   (    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyR      s&     !
 c         C   sc   d } xL |  D]D \ } } | j  | |  } t j j | j | j  } | | 7} q W| t |   S(   Ni    (   RQ   R   R\   R]   R   R	   (   Rb   R$   t   camOrientationt
   totalErrort   seenLmt   mapLmt   worldSeenLmRM   (    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyR   Ç   s    (   t   pdbR+   t   numpyR   R    t   geometryUtilsR   R   t   objectR   R   R   R   (    (    (    sB   /home/andrew/catkin_ws/src/landmark_localizer/scripts/Localizer.pyt   <module>   s   n	.