Go to the documentation of this file.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 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 import numpy
00046 from numpy import reshape, array, zeros, diag, matrix, real
00047 import roslib; roslib.load_manifest('calibration_estimation')
00048 import rospy
00049 from calibration_estimation.full_chain import FullChainRobotParams
00050 from sensor_msgs.msg import JointState
00051 
00052 class ChainBundler:
00053     def __init__(self, valid_configs):
00054         self._valid_configs = valid_configs
00055 
00056     
00057     def build_blocks(self, M_robot):
00058         sensors = []
00059         for cur_config in self._valid_configs:
00060             if cur_config["sensor_id"] == M_robot.chain_id and \
00061                 cur_config["sensor_id"] in [ x.chain_id  for x in M_robot.M_chain ]:
00062                 M_chain = [x for x in M_robot.M_chain if cur_config["sensor_id"] == x.chain_id][0]
00063                 cur_sensor = ChainSensor(cur_config, M_chain, M_robot.target_id)
00064                 sensors.append(cur_sensor)
00065             else:
00066                 rospy.logdebug("  Didn't find block")
00067         return sensors
00068 
00069 class ChainSensor:
00070     def __init__(self, config_dict, M_chain, target_id):
00071 
00072         self.sensor_type = "chain"
00073         self.sensor_id   = config_dict["sensor_id"]
00074 
00075         self._config_dict = config_dict
00076         self._M_chain = M_chain
00077         self._target_id = target_id
00078 
00079         self._full_chain = FullChainRobotParams(self.sensor_id, self.sensor_id+"_cb_link")
00080 
00081         self.terms_per_sample = 3
00082 
00083     def update_config(self, robot_params):
00084         self._full_chain.update_config(robot_params)
00085         self._checkerboard = robot_params.checkerboards[ self._target_id ]
00086 
00087     def compute_residual(self, target_pts):
00088         h_mat = self.compute_expected(target_pts)
00089         z_mat = self.get_measurement()
00090         assert(h_mat.shape == z_mat.shape)
00091         assert(h_mat.shape[0] == 4)
00092         r_mat = h_mat[0:3,:] - z_mat[0:3,:]
00093         r = array(reshape(r_mat.T, [-1,1]))[:,0]
00094         return r
00095 
00096     def compute_residual_scaled(self, target_pts):
00097         r = self.compute_residual(target_pts)
00098         gamma_sqrt = self.compute_marginal_gamma_sqrt(target_pts)
00099         r_scaled = gamma_sqrt * matrix(r).T
00100         return array(r_scaled.T)[0]
00101 
00102     def compute_marginal_gamma_sqrt(self, target_pts):
00103         import scipy.linalg
00104         
00105         cov = self.compute_cov(target_pts)
00106         gamma = matrix(zeros(cov.shape))
00107         num_pts = self.get_residual_length()/3
00108 
00109         for k in range(num_pts):
00110             
00111             first = 3*k
00112             last = 3*k+3
00113             sub_cov = matrix(cov[first:last, first:last])
00114             sub_gamma_sqrt_full = matrix(scipy.linalg.sqrtm(sub_cov.I))
00115             sub_gamma_sqrt = real(sub_gamma_sqrt_full)
00116             assert(scipy.linalg.norm(sub_gamma_sqrt_full - sub_gamma_sqrt) < 1e-6)
00117             gamma[first:last, first:last] = sub_gamma_sqrt
00118         return gamma
00119 
00120     def compute_cov(self, target_pts):
00121         epsilon = 1e-8
00122 
00123         num_joints = len(self._M_chain.chain_state.position)
00124         Jt = zeros([num_joints, self.get_residual_length()])
00125 
00126         x = JointState()
00127         x.position = self._M_chain.chain_state.position[:]
00128 
00129         f0 = reshape(array(self._calc_fk_target_pts(x)[0:3,:].T), [-1])
00130         for i in range(num_joints):
00131             x.position = list(self._M_chain.chain_state.position[:])
00132             x.position[i] += epsilon
00133             fTest = reshape(array(self._calc_fk_target_pts(x)[0:3,:].T), [-1])
00134             Jt[i] = (fTest - f0)/epsilon
00135         cov_angles = [x*x for x in self._full_chain.calc_block._chain._cov_dict['joint_angles']]
00136         cov = matrix(Jt).T * matrix(diag(cov_angles)) * matrix(Jt)
00137         
00138         if ( self._full_chain.calc_block._chain._cov_dict.has_key('translation') ):
00139             translation_var = self._full_chain.calc_block._chain._cov_dict['translation'];
00140             translation_cov = numpy.diag(translation_var*(self.get_residual_length()/3))
00141             cov = cov + translation_cov
00142 
00143         return cov
00144 
00145     def get_residual_length(self):
00146         pts = self._checkerboard.generate_points()
00147         N = pts.shape[1]
00148         return N*3
00149 
00150     def get_measurement(self):
00151         '''
00152         Returns a 4xN matrix with the locations of the checkerboard points in homogenous coords,
00153         as per the forward kinematics of the chain
00154         '''
00155         return self._calc_fk_target_pts(self._M_chain.chain_state)
00156 
00157     def _calc_fk_target_pts(self, chain_state):
00158         
00159         target_pts_tip = self._checkerboard.generate_points()
00160 
00161         
00162         target_pose_root = self._full_chain.calc_block.fk(chain_state)
00163 
00164         
00165         target_pts_root = target_pose_root * target_pts_tip
00166 
00167         return target_pts_root
00168 
00169     def compute_expected(self, target_pts):
00170         return target_pts
00171 
00172     
00173     def build_sparsity_dict(self):
00174         sparsity = self._full_chain.build_sparsity_dict()
00175         sparsity['checkerboards'] = {}
00176         sparsity['checkerboards'][self._target_id] = { 'spacing_x': 1, 'spacing_y': 1 }
00177         return sparsity
00178