/**
 * @brief Moves a virtual copy of the robot along the road checking for enough free space around it
 * 
 * @param innermodel ...
 * @param road ...
 * @param laserData ...
 * @param robotRadius ...
 * @return bool
 */
 bool ElasticBand::checkCollisionAlongRoad(InnerModel *innermodel, const RoboCompLaser::TLaserData& laserData, WayPoints &road,  WayPoints::const_iterator robot,
                                            WayPoints::const_iterator target, float robotRadius)
 {
	//Simplify laser polyline using Ramer-Douglas-Peucker algorithm
	std::vector<Point> points, res;
	QVec wd;
	for( auto &ld : laserData)
	{
		wd = innermodel->laserTo("world", "laser", ld.dist, ld.angle);      //OPTIMIZE THIS FOR ALL CLASS METHODS
		points.push_back(Point(wd.x(), wd.z()));
	}
	res = simPath.simplifyWithRDP(points, 70);
	qDebug() << __FUNCTION__ << "laser polygon after simp" << res.size();

	// Create a QPolygon so we can check if robot outline falls inside
	QPolygonF polygon;
	for (auto &p: res)
		polygon << QPointF(p.x, p.y);

	// Move the robot along the road
	QVec memo = innermodel->transform6D("world","robot");
	bool free = false;
	for( WayPoints::const_iterator it = robot; it != target; ++it)
	{
		if( it->isVisible == false)
			break;
		// compute orientation of the robot at the point

		innermodel->updateTransformValues("robot", it->pos.x(), it->pos.y(), it->pos.z(), 0, it->rot.y(), 0);
		//get Robot transformation matrix
		QMat m = innermodel->getTransformationMatrix("world", "robot");
		// Transform all points at one
		qDebug() << __FUNCTION__ << "hello2";
		m.print("m");
		pointsMat.print("pointsMat");
		QMat newPoints = m * pointsMat;
		qDebug() << __FUNCTION__ << "hello3";

		//Check if they are inside the laser polygon
		for( int i=0; i<newPoints.nRows(); i++)
			if( polygon.containsPoint(QPointF(pointsMat(i,0)/pointsMat(i,3), pointsMat(i,2)/pointsMat(i,3)), Qt::OddEvenFill ) == false)
			{
				free = false;
				break;
			}
		free = true;
	}
	 qDebug() << __FUNCTION__ << "hello";

	 // Set the robot back to its original state
	innermodel->updateTransformValues("robot", memo.x(), memo.y(), memo.z(), 0, memo.ry(), 0);
	return free ? true : false;
 }
void ElasticBand::initialize( const RoboCompCommonBehavior::ParameterList& params )
{
	ROBOT_WIDTH = std::stof(params.at("RobotXWidth").value);
	ROBOT_LENGTH = std::stoi(params.at("RobotZLong").value);
	
	qDebug() << __FUNCTION__ << "Robot dimensions in ElasticBand: " << ROBOT_WIDTH  << ROBOT_LENGTH;
	
	
	////////////////////////////
	/// points if the frontal edge of the robot used to test robot's hypothetical positions in the laser field
	////////////////////////////

	pointsMat = QMat::zeros(3,4);

	//front edge
	pointsMat(0,0) = -ROBOT_WIDTH/2;
	pointsMat(0,2) =  ROBOT_LENGTH/2;
	pointsMat(0,3) =  1.f;
	pointsMat(1,0) =  ROBOT_WIDTH/2;
	pointsMat(1,2) =  ROBOT_LENGTH/2;
	pointsMat(1,3) =  1.f;
	pointsMat(2,0) =  0;
	pointsMat(2,2) =  ROBOT_LENGTH/2;
	pointsMat(2,3) =  1.f;

	//lower
	// 	pointsMat(3,0) = -xs/2;
	// 	pointsMat(3,2) = -zs/2;
	// 	pointsMat(3,3) =  1.f;
	// 	pointsMat(4,0) =  xs/2;
	// 	pointsMat(4,2) = -zs/2;
	// 	pointsMat(4,3) =  1.f; 
	// 	pointsMat(5,0) =  0;
	// 	pointsMat(5,2) = -zs/2;
	// 	pointsMat(5,3) =  1.f;
	//middle
	// 	pointsMat(6,0) = -xs/2;
	// 	pointsMat(6,2) =  0;
	// 	pointsMat(6,3) =  1.f;
	// 	pointsMat(7,0) =  xs/2;
	// 	pointsMat(7,2) =  0;
	// 	pointsMat(7,3) =  1.f;

	pointsMat = pointsMat.transpose();
}
//在points中找到离anchor最近的点
bool findNearestPoint(const vector<Point2f>& points, const Point2f& anchor, Point2f& nearestPt)
{
	int sz = points.size();
	if (sz == 0)
	{
		//	cout << "no color similar points." << endl;
		nearestPt = Point2f(-1.0, -1.0);
		return false;
	}

	//超过10000个点使用KDTree进行查找
	if (sz > 10000)
	{
		Mat pointsMat(sz,2,CV_32FC1);
		for (int i = 0; i < sz; ++i)
		{
			float * data = pointsMat.ptr<float>(i);
			data[0] = points[i].x;
			data[1] = points[i].y;
		}

		Mat anchorPt(1,2,CV_32FC1);
		anchorPt.at<float>(0,0) = anchor.x; 
		anchorPt.at<float>(0,1) = anchor.y;
		
		//使用Flann库
		cv::flann::Index flann_Idx(pointsMat, cv::flann::KDTreeIndexParams(4),cvflann::FLANN_DIST_EUCLIDEAN);
		//cout << "flann based KDTree have been done." << endl;

		//查找最近邻 
		Mat idx, dist;	
		flann_Idx.knnSearch(anchorPt, idx, dist, 1, cv::flann::SearchParams());
		nearestPt = points[idx.at<int>(0,0)];
		return true;
	}

	int  minIdx = 0;
	float minDis = sqrt( pow((points[0].x - anchor.x), 2) + pow((points[0].y - anchor.y), 2) );
	for (int i = 1; i < sz; ++i)
	{
		float dis = sqrt( pow((points[i].x - anchor.x), 2) + pow((points[i].y - anchor.y), 2) );
		if (dis < minDis)
		{
			minDis = dis;
			minIdx = i;
		}
	}
	nearestPt = points[minIdx];
	return true;
}
Example #4
0
vector<ofVec3f> findRectangle(const PCPtr& cloud, const pcl::ModelCoefficients& coefficients) 
{ 
	vector<Eigen::Vector3f> corners; 
	//saveCloudAsFile("toproject.pcd",*cloud);
	pcl::ModelCoefficients::Ptr coeff (new pcl::ModelCoefficients(coefficients));
	// Project points onto the table plane 

	PC projectedCloud = *cloud; 

	//saveCloudAsFile("projected.pcd",projectedCloud);

	PCXYZ pto = cloud->at(1);
	float val = coefficients.values[0] * pto.x + 
				coefficients.values[1] * pto.y + 
				coefficients.values[2] * pto.z + 
				coefficients.values[3]; 

	if(abs(val) < 0.009)
		;;

	// store the table top plane parameters 
	Eigen::Vector3f planeNormal; 
	planeNormal.x() = coeff->values[0]; 
	planeNormal.y() = coeff->values[1]; 
	planeNormal.z() = coeff->values[2]; 
	
	// compute an orthogonal normal to the plane normal 
	Eigen::Vector3f v = planeNormal.unitOrthogonal(); 
	
	// take the cross product of the two normals to get 
	// a thirds normal, on the plane 
	Eigen::Vector3f u = planeNormal.cross(v); 

	// project the 3D point onto a 2D plane 
	std::vector<cv::Point2f> points; 
	
	// choose a point on the plane 
	Eigen::Vector3f p0(projectedCloud.points[0].x, 
						projectedCloud.points[0].y, 
						projectedCloud.points[0].z); 
	
	for(unsigned int ii=0; ii<projectedCloud.points.size(); ii++) 
	{ 
		Eigen::Vector3f p3d(projectedCloud.points[ii].x, 
								projectedCloud.points[ii].y, 
								projectedCloud.points[ii].z); 

		// subtract all 3D points with a point in the plane 
		// this will move the origin of the 3D coordinate system 
		// onto the plane 
		p3d = p3d - p0; 

		cv::Point2f p2d; 
		p2d.x = p3d.dot(u); 
		p2d.y = p3d.dot(v); 
		points.push_back(p2d); 
	} 

	cv::Mat pointsMat(points); 
	cv::RotatedRect rrect = cv::minAreaRect(pointsMat); 
	cv::Point2f rrPts[4]; 
	rrect.points(rrPts); 

	//store the table top bounding points in a vector 
	for(unsigned int ii=0; ii<4; ii++) 
	{ 
		Eigen::Vector3f pbbx(rrPts[ii].x*u + rrPts[ii].y*v + p0); 
		corners.push_back(pbbx); 
	} 
	/*Eigen::Vector3f center(rrect.center.x*u + rrect.center.y*v + p0); 
	corners.push_back(center); */

	//Ver si se puede eliminar esto.
	vector<ofVec3f> vecCorners = projectPointsInPlane(corners,coefficients);

	//saveCloudAsFile("projectedrectangle.pcd",vecCorners);
	return vecCorners; 
}