bool localizerGVG::processMeetpoint(localizer::UpdateFilter::Request &req, localizer::UpdateFilter::Response &res) { ROS_INFO("processMeetpoint received meetpoint %d [%lf,%lf,%lf]", req.id, req.x, req.y,req.yaw); ROS_INFO("processMeetpoint robot pose [%lf,%lf,%lf]",X(0),X(1),X(2)); if(nL==0) { //Reset the odometry covariance. P=MatrixXd::Zero(3,3); } // Propagate the cross-corelation between robot and the // existing landmarks up to now propagateRL(); // For the new landmark Vector3d xl; //the coordinates of the landmark (meetpoint) in World Frame Vector3d z; // Vector representation of the measurment z<<req.x, req.y, req.yaw; xl.segment(0,2)=X.segment(0,2)+C(X(2))*z.segment(0,2); xl(2)=X(2)+z(2); // Create the measurment matrices MatrixXd Hr(3,3); Vector2d dx; dx=xl.segment(0,2)-X.segment(0,2); double _c=cos(X(2)); double _s=sin(X(2)); Hr<<-_c, -_s, + _c*dx(1)-_s*dx(0), _s, -_c, - _s*dx(1)-_c*dx(0), 0, 0, -1; Matrix3d Hl; // Hl is a 2 by 2 Matrix Hl=MatrixXd::Zero(3,3); Hl.block(0,0,2,2)=CT(X(2)); Hl(2,2)=1; if(newLandmark(req.id)) { // If pre-fix on loaded map, need to mark that this new node is in current frame if (!mapLoadLocalization) preFixIdList.push_back(req.id); // New Landmark idList.push_back(req.id); P.conservativeResize(P.rows()+3,P.cols()+3); X.conservativeResize(X.size()+3); X.segment(3+nL*3,3)=xl; // Create new Pllcv matrices describing the cross corelation // between the old landmarks and the new Landmark. Page 79 eq. 5.73 for (int count = 0; count < nL; count++) { Matrix3d newPllcv; newPllcv = -P.block(3 + count*3, 0, 3, 3)*Hr.transpose()*Hl; P.block(3 + count*3, 3 + nL*3, 3, 3) = newPllcv; P.block(3 + nL*3, 3 + count*3, 3, 3) = newPllcv.transpose(); } // Create new Prl matrix describing the cross corelation // between the Robot and the new Landmark. Page 79 eq. 5.73 MatrixXd newPrl(3,3); newPrl=-P.block(0,0,3,3)*Hr.transpose()*Hl; P.block(0,3+nL*3,3,3)=newPrl; P.block(3+nL*3,0,3,3)=newPrl.transpose(); // Create the new Pll matrix describing the covariance of the landmark // page 79 eq. 5.74 Matrix3d newPll; newPll=Hl.transpose()*(Hr*P.block(0,0,3,3)*Hr.transpose()+R)*Hl; P.block(3+nL*3,3+nL*3,3,3)=newPll; nL++; } else { // Find which landmark it is: int id=-1; for(unsigned int i=0; i<idList.size(); i++) { if(idList[i] == req.id) id=i; } //Sanity check: if(id < 0) { cerr<<"Not able to find id:"<<req.id<< "in the list of ids"<<endl; for(unsigned int i=0; i<idList.size(); i++){ cerr<<idList[i]<<" "; } cerr<<endl; } // Check if the revisited node was one from previous map or current map // If from current map, don't use this node to compute transformation between old/new map bool oldMapNode = true; for (vector<int>::iterator it = preFixIdList.begin(); it != preFixIdList.end(); ++it){ if((*it)==id) { oldMapNode = false; break; } } if (!mapLoadLocalization && oldMapNode) { // Copy the covariance information to Prr and also Xr Vector3d offset; offset(2) = X(2)-bearing_angle; Vector2d v; v(0) = X(3*id+3); v(1) = X(3*id+4); Vector2d rotated_mp; rotated_mp = C(offset(2))*v; offset(0) = X(0)-rotated_mp(0); offset(1) = X(1)-rotated_mp(1); /*P.block(0,0,3,3) = P_init.block(3*id+3, 3*id+3, 3, 3); // Copying information to Prl P.block(0,3,3,3*nL) = P.block(3*id+3, 3, 3, 3*nL); P.block(3,0,3*nL,3) = P.block(3, 3*id+3, 3*nL, 3);*/ mapLoadLocalization = true; // Calculate translation between current frame and loaded map frame for (unsigned int i = 0; i < nL; i++) { bool corrected = false; for (vector<int>::iterator it = preFixIdList.begin(); it != preFixIdList.end(); ++it){ if((*it)==i) { corrected = true; break; } } if (!corrected) { Vector2d v; v(0) = X(3*i+3); v(1) = X(3*i+4); Vector2d result; result = C(offset(2))*v; X(3*i+3) = result(0); X(3*i+4) = result(1); X(3*i+3) = X(3*i+3) + offset(0); X(3*i+4) = X(3*i+4) + offset(1); X(3*i+5) = thetapp(X(3*i+5) + offset(2)); } } P = P_init; X = X_init; } else { // perform update ROS_INFO("localizerGVG::processMeetpoint id %d %d",req.id, id); Vector3d z_est; z_est.segment(0,2)=CT(X(2))*(X.segment(3+3*id,2)-X.segment(0,2)); z_est(2)=X(3+3*id+2)-X(2); Vector3d r; r.segment(0,2)=z.segment(0,2)-z_est.segment(0,2); r(2)=angleDiff(z(2),z_est(2)); MatrixXd H(3,3+3*nL); H=MatrixXd::Zero(3,3+3*nL); H.block(0,0,3,3)=Hr; H.block(0,3+3*id,3,3)=Hl; MatrixXd S(3,3); S=H*P*H.transpose()+R; MatrixXd K(3,3+3*nL); K=P*H.transpose()*S.inverse(); X=X+K*r; X(2)=thetapp(X(2)); P=(MatrixXd::Identity(3+nL*3,3+nL*3)-K*H)*P*(MatrixXd::Identity(3+nL*3,3+nL*3)-K*H).transpose()+K*R*K.transpose(); } } // publish the odometry with covariance topic // Publish the Map localizer::GVGmap theMap; for(unsigned int i=0; i<X.size(); i++) { theMap.state.push_back(X[i]); res.X.push_back(X[i]); } for(unsigned int i=0; i<P.rows(); i++) { for(unsigned int j=0; j<P.cols(); j++) { theMap.cov.push_back(P(i,j)); res.P.push_back(P(i,j)); } } mapPub.publish(theMap); return(true); }