Пример #1
0
/** This method returns the angle that will form a straight line from position a to position b. a and b are [x, y] vectors. */
const double Utility::findAngleFromAToB(const std::vector<double> a, const std::vector<double> b) const 
{
  double result;

  // If the positions are the same, return the orientation the robot already has
  if(fabs(positionDistance(a, b)) < 0.01 && a.size() > 2)
  {
    return a.at(2);
  }

  // Find the distances in x,y directions and Euclidean distance
  double d_x = b.at(0) - a.at(0);
  double d_y = b.at(1) - a.at(1);

  // Fails when vector from a to be is in 3rd quadrant
  //result = atan(d_y / d_x);
  
  double euc_dist = sqrt( pow(d_x,2) + pow(d_y,2) );
  // If the positions are the same,
  // Set the result to the starting orientation if one is provided
  // Or to 0 if no starting orientation is provided
  if(euc_dist <= 0.0001) 
  {
    result = 0;
  }

  // If b is in the 1st or 2nd quadrants
  else if(d_y > 0) 
  {
    result = acos(d_x / euc_dist);
  }

  // If b is in the 3rd quadrant, d_y<0 & d_x<0
  else if(d_x < 0) 
  {
    result = -PI - asin(d_y / euc_dist);
  }

  // If b is in the 4th quadrant, d_y<=0 & d_x>=0
  else 
  {
    result = asin(d_y / euc_dist); 
  }

  return result;
} // End findAngleFromAToB
// Cluster the existent clusters into well defined bins method (needed by grid-based filters)
void poseEstimationSV::clusterClusters(std::vector<cluster> & clusters)
{
	//std::cout << "clusters before:" << clusters.size() << std::endl;
	bool newMerge=true;
	int it=0;
 	while(newMerge)
	{
		//std::cout << "cycle number: " << ++it << std::endl;
		newMerge=false;
		for(std::vector<cluster>::iterator c1=clusters.begin(); c1 < clusters.end(); ++c1)
		{
			for(std::vector<cluster>::iterator c2=c1+1; c2 < clusters.end();)
			{
					if( ( orientationDistance(*c1,*c2) >= pointPair::angleStepCos ) && ( positionDistance(*c1, *c2)) <= (model->maxModelDistSquared*0.05*0.05 ) )
					{
						if(isnan(acos(orientationDistance(*c1, *c2))))
						{
							std::cout << c1->meanPose.transform.rotation.w() << " " << c1->meanPose.transform.rotation.x() << " " << c1->meanPose.transform.rotation.y() << " " << c1->meanPose.transform.rotation.z() << std::endl;
							std::cout << c2->meanPose.transform.rotation.w() << " " << c2->meanPose.transform.rotation.x() << " " << c2->meanPose.transform.rotation.y() << " " << c2->meanPose.transform.rotation.z() << std::endl;
							std::cout << orientationDistance(*c1, *c2) << std::endl;
							exit(1);
						}
						if(positionDistance(*c1, *c2) <= (model->maxModelDistSquared*0.05*0.05 ))
						{
							//  average orientation
							Eigen::Quaternion<float> q((c1->meanPose.transform.rotation.w()*c1->meanPose.votes)+(c2->meanPose.transform.rotation.w()*c2->meanPose.votes),
							(c1->meanPose.transform.rotation.x()*c1->meanPose.votes)+(c2->meanPose.transform.rotation.x()*c2->meanPose.votes),
							(c1->meanPose.transform.rotation.y()*c1->meanPose.votes)+(c2->meanPose.transform.rotation.y()*c2->meanPose.votes),
							(c1->meanPose.transform.rotation.z()*c1->meanPose.votes)+(c2->meanPose.transform.rotation.z()*c2->meanPose.votes));
							// normalize quaternion
							q.normalize();

							c1->meanPose.transform.rotation=q;

							// average position
							float votationSumInv=1/(c1->meanPose.votes+c2->meanPose.votes);
							Eigen::Translation3f transAux;
							transAux.x()=( (c1->meanPose.transform.translation.x()*c1->meanPose.votes) + (c2->meanPose.transform.translation.x()*c2->meanPose.votes) )*votationSumInv;
							transAux.y()=( (c1->meanPose.transform.translation.y()*c1->meanPose.votes) + (c2->meanPose.transform.translation.y()*c2->meanPose.votes) )*votationSumInv;
							transAux.z()=( (c1->meanPose.transform.translation.z()*c1->meanPose.votes) + (c2->meanPose.transform.translation.z()*c2->meanPose.votes) )*votationSumInv;
							/*transAux.x()=( c1->meanPose.transform.translation.x() + c2->meanPose.transform.translation.x() )*0.5;
							transAux.y()=( c1->meanPose.transform.translation.y() + c2->meanPose.transform.translation.y() )*0.5;
							transAux.z()=( c1->meanPose.transform.translation.z() + c2->meanPose.transform.translation.z() )*0.5;*/
							//std::cout << "VERRR ISTO:" << positionDistance(*c1, *c2) << " "<<acos(orientationDistance(*c1,*c2))*RAD_TO_DEG << std::endl;
							//std::cout << "TRANS BEFORE:" << c1->meanPose.transform.translation.x() << " " << c1->meanPose.transform.translation.y()  << " " << c1->meanPose.transform.translation.z() << std::endl;
							c1->meanPose.transform.translation=transAux;
							//std::cout << "TRANS AFTER:" << c1->meanPose.transform.translation.x() << " " << c1->meanPose.transform.translation.y()  << " " << c1->meanPose.transform.translation.z() << std::endl;
							c1->meanPose.votes+=c2->meanPose.votes;


						}
						// remove cluster 2	
						c2=clusters.erase(c2);
						newMerge=true;
					}
					else
						++c2;
			}
		}

	}
	//std::cout << "clusters after:" << clusters.size() << std::endl;
}
// CLUSTERING METHOD
std::vector<poseEstimationSI::clusterPtr> poseEstimationSI::poseClustering(std::vector < posePtr > & bestPoses)
{
	// Sort clusters
	std::sort(bestPoses.begin(), bestPoses.end(), pose::compare);

	std::vector< boost::shared_ptr<poseCluster> > centroids;
	std::vector< boost::shared_ptr<cluster> > transformations;    

	float _orientationDistance;	
	float _positionDistance;
	float _scaleDistance;

	bool found;
	
	int nearestCentroid;

	///////////////////////////////
	// Initialize first centroid //
	///////////////////////////////

	// If there are no poses, return
	if(bestPoses.empty())
		return transformations;


	centroids.push_back(boost::shared_ptr<poseCluster> (new poseCluster(0,bestPoses[0])));
	//centroids.back()->poses.push_back(bestPoses[0]);

	Tic();	
	// For each pose
	for(size_t p=1; p< bestPoses.size(); ++p)
	{
		found=false;
		for(size_t c=0; c < centroids.size(); ++c)
		{
			//std::cout << std::endl << "\tcheck if centroid:" << std::endl;
			// Compute (squared) distance to the cluster center
			_orientationDistance=orientationDistance(bestPoses[p],bestPoses[centroids[c]->poseIndex]);
			_positionDistance=positionDistance(bestPoses[p],bestPoses[centroids[c]->poseIndex]);
			_scaleDistance=scaleDistance(bestPoses[p],bestPoses[centroids[c]->poseIndex]);
			// If the cluster is nearer than a threshold add current pose to the cluster
			//if((_orientationDistance>=poseAngleStepCos) && _positionDistance<=((model->maxModelDistSquared)*0.05*0.05))
			//if((_orientationDistance>=cos(acos(poseAngleStepCos)) ) && _positionDistance<=((model->maxModelDistSquared)*0.1*0.1))
			if((_orientationDistance>=pointPair::angleStepCos) && (_positionDistance<=model->halfDistanceStepSquared) &&(equalFloat(_scaleDistance,0.0))) // VER ISTO
			{

				nearestCentroid=c;
				found=true;
				break;
			}		
		}			
			
		if(found)
		{
			centroids[nearestCentroid]->update(bestPoses[p]);
		}
		else
		{
			boost::shared_ptr<poseCluster> clus(new poseCluster(p,bestPoses[p]));
			centroids.push_back(clus);
		}
	}
	Tac();	

	//////////////////////
	// Compute clusters //
	//////////////////////
	std::sort(centroids.begin(), centroids.end(), poseCluster::compare);
	//std::cout << std::endl << "Number of poses:" <<bestPoses.size() << std::endl << std::endl;
	//std::cout << std::endl << "Best pose votes:" <<bestPoses[0]->votes << std::endl << std::endl;
	//for(size_t c=0; c < centroids.size(); ++c)
	if(filterOn)
	{
		for(size_t c=0; c < centroids.size(); ++c)
		//for(size_t c=0; c < 1; ++c)
		{
			//std::cout << centroids[c]->votes << std::endl;
			transformations.push_back(boost::shared_ptr<cluster> (new cluster( boost::shared_ptr<pose> (new pose (centroids[c]->votes, boost::shared_ptr<transformation>( new transformation(centroids[c]->rotation(),centroids[c]->translation(),centroids[c]->scaling() ) ) ) ),centroids[c]->poses ) ) );
		}
	}
	else
	{
		transformations.push_back(boost::shared_ptr<cluster> (new cluster( boost::shared_ptr<pose> (new pose (centroids[0]->votes, boost::shared_ptr<transformation>( new transformation(centroids[0]->rotation(),centroids[0]->translation(),centroids[0]->scaling() ) ) ) ),centroids[0]->poses ) ) );
	}

	return transformations;
}
// CLUSTERING METHOD
std::vector<cluster> poseEstimationSV::poseClustering(std::vector<pose> & bestPoses)
{
	// Sort clusters
	std::sort(bestPoses.begin(), bestPoses.end(), pose::compare);

	std::vector<poseCluster> centroids;
	std::vector<cluster> clusters;    

	float _orientationDistance;	
	float _positionDistance;
	bool found;
	
	int nearestCentroid;

	///////////////////////////////
	// Initialize first centroid //
	///////////////////////////////

	// If there are no poses, return
	if(bestPoses.empty())
		return clusters;

    centroids.reserve(bestPoses.size());

	centroids.push_back(poseCluster(0,bestPoses[0]));

	// For each pose
	for(size_t p=1; p< bestPoses.size(); ++p)	
	{

		found=false;
		for(size_t c=0; c < centroids.size(); ++c)
		{
			// Compute (squared) distance to the cluster center

			_positionDistance=positionDistance(bestPoses[p],bestPoses[centroids[c].poseIndex]);
			if(_positionDistance<=model->halfDistanceStepSquared)
				continue;
			_orientationDistance=orientationDistance(bestPoses[p],bestPoses[centroids[c].poseIndex]);

			// If the cluster is nearer than a threshold add current pose to the cluster
			if(_orientationDistance>=pointPair::angleStepCos) // VER ISTO
			{
				nearestCentroid=c;
				found=true;
				break;
			}		
		}			
			
		if(found)
		{
			//std::cout << " yes:" << "pose:"<< p <<"nearest centroid:" << nearestCentroid << " " << 2*acos(_orientationDistance)*RAD_TO_DEG << " "<< _positionDistance << " " << bestPoses[p].votes << std::endl;
			centroids[nearestCentroid].update(bestPoses[p]);
		}
		else
		{
			//if(2*acos(_orientationDistance)*RAD_TO_DEG< 6.000 && _positionDistance<model->halfDistanceStepSquared)
			//	std::cout << "angle:" << pointPair::angleStep*RAD_TO_DEG  << "angle threshold: " <<2*acos(pointPair::angleStepCos)*RAD_TO_DEG<< " no:" << 2*acos(_orientationDistance)*RAD_TO_DEG << " "<< _positionDistance << std::endl;
			centroids.push_back(poseCluster(p,bestPoses[p]));
		}
		//std::cout << p << std::endl;
	}

	//////////////////////
	// Compute clusters //
	//////////////////////
	//std::sort(centroids.begin(), centroids.end(), poseCluster::compare);

	// Normalize centroids
	float totalModelVotes=static_cast<float>(model->modelCloud->size()*(model->modelCloud->size()-1));
	//std::cout << totalModelVotes << " " << model->totalSurfaceArea << std::endl;
	//std::cout << "Best centroid score before: " << centroids[0].votes << std::endl;


	//std::cout << "Best centroid score after: " << centroids[0].votes << std::endl;
	// end normalize centroids
	//std::cout << std::endl << "Number of poses:" <<bestPoses.size() << std::endl << std::endl;
	//std::cout << std::endl << "Best pose votes:" <<bestPoses[0].votes << std::endl << std::endl;
	if(filterOn)
	{

        std::cout << "Best centroid score: " << centroids[0].votes << std::endl;
        std::cout << "Best centroid score(normalized): " << (float) centroids[0].votes/totalModelVotes << std::endl;
		clusters.reserve(centroids.size());
		for(size_t c=0; c < centroids.size(); ++c)
		//for(size_t c=0; c < 1; ++c)
		{

			clusters.push_back(cluster(pose (centroids[c].votes, transformation(centroids[c].rotation(),centroids[c].translation() ) ),centroids[c].poses ) );
		}
		clusterClusters(clusters);
		std::sort(clusters.begin(), clusters.end(), cluster::compare);
	}
	else
	{
		std::sort(centroids.begin(), centroids.end(), poseCluster::compare);
		//clusters.push_back(cluster(pose (centroids[0].votes, transformation(centroids[0].rotation(),centroids[0].translation() ) ),centroids[0].poses )); //METER
		for(size_t c=0; c < centroids.size(); ++c) //TIRAR DEPOIS DOS TESTS
		//for(size_t c=0; c < 1; ++c)
		{

			clusters.push_back(cluster(pose (centroids[c].votes, transformation(centroids[c].rotation(),centroids[c].translation() ) ),centroids[c].poses ) );
		}
	}

	for(size_t c=0; c < clusters.size(); ++c)
	{
		clusters[c].normalizeVotes(model->totalSurfaceArea/totalModelVotes); // normalize votes weighs by the argument factor
		//std::cout << "centroid poses:" << centroids[c].poses.size()<< "centroid score after: " << centroids[c].votes << std::endl;
	}


	/*for(size_t p=0; p< 1; ++p)
	{
		Eigen::Vector3f eulerAngles;
		objectModel::quaternionToEuler(clusters[p].meanPose.transform.rotation, eulerAngles[0], eulerAngles[1], eulerAngles[2]);
		float x,y,z;
		std::cout << "1. EULER ANGLES: "<< std::endl << eulerAngles.transpose()*RAD_TO_DEG << std::endl;
		pcl::getTranslationAndEulerAngles (clusters[p].meanPose.getTransformation(), x, y, z, eulerAngles[0], eulerAngles[1], eulerAngles[2]);
		std::cout << "2. EULER ANGLES: "<< std::endl << eulerAngles.transpose()*RAD_TO_DEG << std::endl << std::endl;

	}*/

	return clusters;
}