function [T_lcEST T_crEST errEST infoEST T_lcOPT T_crOPT errOPT infoOPT]=...
 Estimate3CamExtrinsic(TL,TC,TR,CalibInfo,Points,OPT,MAXERROR)


if ~exist('OPT','var');OPT=0;end
if ~exist('CalibInfo','var')
 CalibInfo=struct('left',[],'right',[],'center',[]);
end
if ~exist('Points','var')
 Points=struct('left',[],'right',[],'center',[]);
end
if ~exist('MAXERROR','var');MAXERROR=0;end
if isempty(MAXERROR);MAXERROR=0;end

%%

% left camera
[CamEST_left infoEST.left errEST.left CamOPT_left infoOPT.left errOPT.left]=...
 RealCamEstimation(TL,[CalibInfo.left],[Points.left],OPT);

% center camera
[CamEST_center infoEST.center errEST.center CamOPT_center infoOPT.center errOPT.center]=...
 RealCamEstimation(TC,[CalibInfo.center],[Points.center],OPT);

% right camera
[CamEST_right infoEST.right errEST.right CamOPT_right infoOPT.right errOPT.right]=...
 RealCamEstimation(TR,[CalibInfo.right],[Points.right],OPT);

% verify if any rep-error is higher that MAXERROR (unless MAXERROR=0)
if ((errEST.left.errMAX>MAXERROR) || (errEST.center.errMAX>MAXERROR) || ...
  (errEST.right.errMAX>MAXERROR)) && MAXERROR~=0
 T_lcEST=zeros(4);
 T_crEST=zeros(4);
 errEST.left.ERR=[];errEST.center.ERR=[];errEST.right.ERR=[];
else
 % use \ is the same as inv()*
 T_lcEST=CamEST_center\CamEST_left;
 T_crEST=CamEST_right\CamEST_center;
end

T_lcOPT=[];
T_crOPT=[];
if OPT
 if ((errOPT.left.errMAX>MAXERROR) || (errOPT.center.errMAX>MAXERROR) || ...
   (errOPT.right.errMAX>MAXERROR)) && MAXERROR~=0
  T_lcOPT=zeros(4);
  T_crOPT=zeros(4);
  errOPT.left.ERR=[];errOPT.center.ERR=[];errOPT.right.ERR=[];
 else
  T_lcOPT=CamOPT_center\CamOPT_left;
  T_crOPT=CamOPT_right\CamOPT_center;
 end
end


