def plane(self,fmts=['png'],out1=50.,out2=15.,**kwds): """ Fit ground plane to data Inputs fmts - [str,...] - list of figure formats to export out1,out2 - float - magic numbers for outlier rejection Usage >> d.shape # raw data, N samples of M markers with 3 coordinates (x,y,z) (N, M, 3) >> c = np.dot(d, R.T) - t # rectified data Effects - generates fi+'_cal.py' file containing dict of R,t,n """ # unpack data t = self.t; d = self.d; g = self.g; hz=self.hz di,fi = os.path.split(self.fi) nn = np.logical_not( np.any( np.isnan(d[:,:,0]), axis=1) ).nonzero()[0] assert nn.size > 0 N,M,_ = d.shape # swap axes in mocap hardware-dependent way if self.dev == 'opti': R0 = np.array([[0,0,1],[1,0,0],[0,1,0]]) elif self.dev == 'vicon': R0 = np.identity(3) # R0 in SO(3) assert ( ( np.all(np.dot(R0,R0.T) == np.identity(3)) ) and ( np.linalg.det(R0) == 1.0 ) ) d = np.dot(d, R0.T) # collect non-nan data x = d[...,0]; y = d[...,1]; z = d[...,2] nn = np.logical_not(np.isnan(x.flatten())).nonzero() p = np.vstack((x.flatten()[nn], y.flatten()[nn], z.flatten()[nn])).T m = p.mean(axis=0) p -= m # remove outliers p = p[np.abs(p[:,2]) < out1,:] # fit plane to data (n is normal vec) n = geom.plane(p) # rotate normal vertical R = geom.orient(n) p = np.dot(p,R.T) # save plane data s = util.Struct(R=np.dot(R,R0),t=np.dot(m,R.T),n=n) s.write( os.path.join(di,ddir,fi+'_cal.py') )
def geom(self,**kwds): """ Fit rigid body geometry Effects: - assigns self.g - saves g to fi+'_geom.npz' """ # unpack data di,fi = os.path.split(self.fi) d = self.d N,M,D = d.shape # samples where all features appear nn = np.logical_not( np.any(np.isnan(d[:,:,0]),axis=1) ).nonzero()[0] #assert nn.size > 0 # fit geometry to pairwise distance data pd0 = []; ij0 = [] for i,j in zip(*[list(a) for a in np.triu(np.ones((M,M)),1).nonzero()]): ij0.append([i,j]) pd0.append(np.sqrt(np.sum((d[:,i,:] - d[:,j,:])**2,axis=1))) pd0 = np.array(pd0).T; d0 = num.nanmean(pd0,axis=0); ij0 = np.array(ij0) self.pd0 = pd0; self.d0 = d0 g0 = d[nn[0],:,:] # TODO: fix geometry fitting if 1: g = g0.copy() else: print 'fitting geom'; ti = time() g,info,flag = geom.fit( g0, ij0, d0 ) print '%0.1f sec' % (time() - ti) pd = []; pd0 = [] for i,j in zip(*[list(a) for a in np.triu(np.ones((M,M)),1).nonzero()]): pd.append( np.sqrt( np.sum((g[i,:] - g[j,:])**2) ) ) pd0.append( np.sqrt( np.sum((g0[i,:] - g0[j,:])**2) ) ) pd = np.array(pd).T; pd0 = np.array(pd0).T; # center and rotate geom flat m = np.mean(g,axis=0) g = g - m n = geom.plane(g) R = geom.orient(n) g = np.dot(g,R.T) self.g = g # save data dir = os.path.join(di,ddir) if not os.path.exists( dir ): os.mkdir( dir ) np.savez(os.path.join(dir,fi+'_geom.npz'),g=g,pd0=pd0,d0=d0)