예제 #1
0
double signedDistanceInsideConvexHull(
    const Ref<const Matrix<double, 2, Dynamic>> &pts,
    const Ref<const Vector2d> &q) {
  std::vector<Point> hull_pts = convexHull(eigenToPoints(pts));
  double d_star = std::numeric_limits<double>::infinity();

  Matrix2d R;
  R << 0, 1, -1, 0;

  for (int i = 0; i < (static_cast<int>(hull_pts.size()) - 1); ++i) {
    Vector2d ai = R * Vector2d(hull_pts[i + 1].x - hull_pts[i].x,
                               hull_pts[i + 1].y - hull_pts[i].y);
    double b = ai.transpose() * Vector2d(hull_pts[i].x, hull_pts[i].y);
    double n = ai.norm();
    if (std::isnormal(n)) {
      ai = ai.array() / n;
      b = b / n;
      double d = b - ai.transpose() * q;
      // std::cout << "pt0: " << hull_pts[i].x << " " << hull_pts[i].y <<
      // std::endl;
      // std::cout << "pt1: " << hull_pts[i+1].x << " " << hull_pts[i+1].y <<
      // std::endl;
      // std::cout << "ai: " << ai.transpose() << std::endl;
      // std::cout << "b: " << b << std::endl;
      // std::cout << "d: " << d << std::endl;
      if (d < d_star) {
        d_star = d;
      }
    }
  }
  return d_star;
}
예제 #2
0
void StringElement::buildParticlesAndSprings() {
	Vector2d xAxis = getEndPosition() - getStartPosition();
	double length = xAxis.norm();
	int requiredMasses = static_cast<int>(ceil(length / stdMaxMassDistance) + 1.0);
	double massDistance = length / requiredMasses;

	xAxis.normalize();

	for (int i = 0; i < requiredMasses; i++) {
		Vector2d massPosition = getStartPosition() + (xAxis * (i * massDistance));
		particles.push_back(createParticle(stdMassValue, stdMassRadius, massPosition));
	}

	for (int i = 0; i < requiredMasses - 1; i++) {
		springs.push_back(new Spring(*particles[i], *particles[i + 1], stdK));
	}

	if (getFromConnectionPoint().isConnected()) {
		ConnectionPoint::particle_list connectionParticles = getFromConnectionPoint().getConnectionParticles();
		for (ConnectionPoint::particle_list::iterator it = connectionParticles.begin(); it != connectionParticles.end(); ++it) {
			springs.push_back(new Spring(*particles[0], **it, stdK));
		}
	}

	if (getToConnectionPoint().isConnected()) {
		ConnectionPoint::particle_list connectionParticles = getToConnectionPoint().getConnectionParticles();
		for (ConnectionPoint::particle_list::iterator it = connectionParticles.begin(); it != connectionParticles.end(); ++it) {
			springs.push_back(new Spring(*particles[particles.size() - 1], **it, stdK));
		}
	}

}
예제 #3
0
Line::Line(const Point2d& p, const Point2d& q)

{

	Vector2d t = q - p;
	Real len = t.norm();
	a =   t.y / len;
	b = - t.x / len;
	c = -(a*p.x + b*p.y);
}
예제 #4
0
HexagonalNet::HexagonalNet(const Vector2d & a)
{
	m_a = a.norm();
	m_a1 = a;
	m_a2 = a;
	/*the second basis vector is rotated by 120 degrees*/
	m_a2.Rotate(2 * M_PI / 3);

	/*rho = 2/3 a1 + 1/3 a2*/
	m_rho = m_a1 * 1.0 / 3 + m_a2 * 2.0 / 3;
}
예제 #5
0
bool StringElement::containsPoint(const Vector2d &point) const {
	if (this->isErased()) return false;
	Vector2d axis = getEndPosition() - getStartPosition();
	Vector2d translation = -getStartPosition();
	double angle = -(Vector2d(1, 0).angleTo(axis));

	Vector2d translatedPoint = translation + point;
	double transformedX = cos(angle) * translatedPoint.getX() - sin(angle) * translatedPoint.getY();
	double transformedY = sin(angle) * translatedPoint.getX() + cos(angle) * translatedPoint.getY();

	return transformedX >= 0 && transformedX <= axis.norm() && fabs(transformedY) <= (getStringWidth() / 2);
}
예제 #6
0
파일: homography.cpp 프로젝트: zangel/uquad
size_t Homography::
computeMatchesInliers()
{
  inliers.clear(); inliers.resize(fts_c1.size());
  size_t n_inliers = 0;
  for(size_t i=0; i<fts_c1.size(); i++)
  {
    Vector2d projected = project2d(H_c2_from_c1 * unproject2d(fts_c1[i]));
    Vector2d e = fts_c2[i] - projected;
    double e_px = error_multiplier2 * e.norm();
    inliers[i] = (e_px < thresh);
    n_inliers += inliers[i];
  }
  return n_inliers;

}
예제 #7
0
Vector2d HexagonalNetRandomSources::displacement(const Vector2d& r)
{
	static Vector2d u, dr, drdir;
	static double drnorm;

	/*sum over all sources of displacements*/
	u = Vector2d(0, 0);
	for(size_t i = 0; i < m_sources.size(); ++i)
	{
		dr = (r - m_sources[i].m_r0);
		drnorm = dr.norm();
		drdir = dr / drnorm;
		/*every source creates the field of type alpha/r^k, where r - is a distance from the source measured in hexagon radii */
		u += drdir / gsl_pow_uint(drnorm / m_a, m_k) * m_sources[i].m_amplitude;
	}

	return u;
}
예제 #8
0
void
Frame2d::set_angle( const Vector2d & vec )
{
    double norm = vec.norm();

    if ( norm == 0.0 )
    {
        //this is consistent with vec.arg() == 0.0 if vec.norm() == 0.0
        n_x = 1.0 * scale;
        n_y = 0.0;
        return;
    }

    norm = scale / norm;

    n_x = vec.x * norm;
    n_y = vec.y * norm;
    //f1.n_y= sqrt(1-f1.n_x*f1.n_x);
}
예제 #9
0
    Circle2d::Circle(
        double radius,
        WindingDirection windingDirection,
        const Point2d& firstPoint,
        const Point2d& secondPoint
    ) : _radius(radius) {

        if (radius <= Zero()) {
            throw Error(new PlaceholderError());
        }

        Vector2d displacementVector = secondPoint - firstPoint;
        double halfDistance = displacementVector.norm() / 2;

        if (halfDistance == Zero()) {
            // Points are coincident
            throw Error(new PlaceholderError());
        }

        if (halfDistance - radius > Zero()) {
            // Points are too far apart
            throw Error(new PlaceholderError());
        }

        Vector2d sidewaysDirection = displacementVector.unitOrthogonal();
        if (windingDirection == COUNTERCLOCKWISE) {
            sidewaysDirection = -sidewaysDirection;
        }

        double sidewaysDistance = 0.0;
        if (halfDistance - radius == Zero()) {
            sidewaysDistance = radius;
        } else {
            sidewaysDistance = sqrt(halfDistance * halfDistance - radius * radius);
        }

        _centerPoint = firstPoint + displacementVector / 2 + sidewaysDistance * sidewaysDirection;
    }
void Draw() {
	if (leftPressed) for (Particle &p : w.particles) {
		tmp = (Vector2d(mx, my) - p.pos);
		if (tmp * tmp < 10000)
			p.a += tmp.norm() * 100;
	}

	w.step(0.1);

	Drawer::clear();
	//Drawer::drawCircle(0, 0, i);
	for (Particle &p : w.particles) {
		Drawer::drawCircle(p.pos.x, p.pos.y, p.r);
	}
	for (Connection &c : w.connections) {
		Drawer::drawLine(c.p1->pos.x, c.p1->pos.y, c.p2->pos.x, c.p2->pos.y);
	}
	for (Connection &c : w.lenConnections) {
		if (!(c.broken))
			Drawer::drawLine(c.p1->pos.x, c.p1->pos.y, c.p2->pos.x, c.p2->pos.y);
	}
	Drawer::update();
	glutPostRedisplay();
}
예제 #11
0
void optimizeGaussNewton(
    const double reproj_thresh,
    const size_t n_iter,
    const bool verbose,
    FramePtr& frame,
    double& estimated_scale,
    double& error_init,
    double& error_final,
    size_t& num_obs)
{
  // init
  double chi2(0.0);
  vector<double> chi2_vec_init, chi2_vec_final;
  vk::robust_cost::TukeyWeightFunction weight_function;
  SE3d T_old(frame->T_f_w_);
  Matrix6d A;
  Vector6d b;

  // compute the scale of the error for robust estimation
  std::vector<float> errors; errors.reserve(frame->fts_.size());
  for(auto it=frame->fts_.begin(); it!=frame->fts_.end(); ++it)
  {
    if((*it)->point == NULL)
      continue;
    Vector2d e = vk::project2d((*it)->f)
               - vk::project2d(frame->T_f_w_ * (*it)->point->pos_);
    e *= 1.0 / (1<<(*it)->level);
    errors.push_back(e.norm());
  }
  if(errors.empty())
    return;
  vk::robust_cost::MADScaleEstimator scale_estimator;
  estimated_scale = scale_estimator.compute(errors);

  num_obs = errors.size();
  chi2_vec_init.reserve(num_obs);
  chi2_vec_final.reserve(num_obs);
  double scale = estimated_scale;
  for(size_t iter=0; iter<n_iter; iter++)
  {
    // overwrite scale
    if(iter == 5)
      scale = 0.85/frame->cam_->errorMultiplier2();

    b.setZero();
    A.setZero();
    double new_chi2(0.0);

    // compute residual
    for(auto it=frame->fts_.begin(); it!=frame->fts_.end(); ++it)
    {
      if((*it)->point == NULL)
        continue;
      Matrix26d J;
      Vector3d xyz_f(frame->T_f_w_ * (*it)->point->pos_);
      Frame::jacobian_xyz2uv(xyz_f, J);
      Vector2d e = vk::project2d((*it)->f) - vk::project2d(xyz_f);
      double sqrt_inv_cov = 1.0 / (1<<(*it)->level);
      e *= sqrt_inv_cov;
      if(iter == 0)
        chi2_vec_init.push_back(e.squaredNorm()); // just for debug
      J *= sqrt_inv_cov;
      double weight = weight_function.value(e.norm()/scale);
      A.noalias() += J.transpose()*J*weight;
      b.noalias() -= J.transpose()*e*weight;
      new_chi2 += e.squaredNorm()*weight;
    }

    // solve linear system
    const Vector6d dT(A.ldlt().solve(b));

    // check if error increased
    if((iter > 0 && new_chi2 > chi2) || (bool) std::isnan((double)dT[0]))
    {
      if(verbose)
        std::cout << "it " << iter
                  << "\t FAILURE \t new_chi2 = " << new_chi2 << std::endl;
      frame->T_f_w_ = T_old; // roll-back
      break;
    }

    // update the model
    SE3d T_new = SE3d::exp(dT)*frame->T_f_w_;
    T_old = frame->T_f_w_;
    frame->T_f_w_ = T_new;
    chi2 = new_chi2;
    if(verbose)
      std::cout << "it " << iter
                << "\t Success \t new_chi2 = " << new_chi2
                << "\t norm(dT) = " << vk::norm_max(dT) << std::endl;

    // stop when converged
    if(vk::norm_max(dT) <= EPS)
      break;
  }

  // Set covariance as inverse information matrix. Optimistic estimator!
  const double pixel_variance=1.0;
  frame->Cov_ = pixel_variance*(A*std::pow(frame->cam_->errorMultiplier2(),2)).inverse();

  // Remove Measurements with too large reprojection error
  double reproj_thresh_scaled = reproj_thresh / frame->cam_->errorMultiplier2();
  size_t n_deleted_refs = 0;
  for(Features::iterator it=frame->fts_.begin(); it!=frame->fts_.end(); ++it)
  {
    if((*it)->point == NULL)
      continue;
    Vector2d e = vk::project2d((*it)->f) - vk::project2d(frame->T_f_w_ * (*it)->point->pos_);
    double sqrt_inv_cov = 1.0 / (1<<(*it)->level);
    e *= sqrt_inv_cov;
    chi2_vec_final.push_back(e.squaredNorm());
    if(e.norm() > reproj_thresh_scaled)
    {
      // we don't need to delete a reference in the point since it was not created yet
      (*it)->point = NULL;
      ++n_deleted_refs;
    }
  }

  error_init=0.0;
  error_final=0.0;
  if(!chi2_vec_init.empty())
    error_init = sqrt(vk::getMedian(chi2_vec_init))*frame->cam_->errorMultiplier2();
  if(!chi2_vec_final.empty())
    error_final = sqrt(vk::getMedian(chi2_vec_final))*frame->cam_->errorMultiplier2();

  estimated_scale *= frame->cam_->errorMultiplier2();
  if(verbose)
    std::cout << "n deleted obs = " << n_deleted_refs
              << "\t scale = " << estimated_scale
              << "\t error init = " << error_init
              << "\t error end = " << error_final << std::endl;
  num_obs -= n_deleted_refs;
}
예제 #12
0
void Odometry::Ransac()
{
    assert(observationVec.size() == cloud.size());
    int numPoints = observationVec.size();
    
    inlierMask.resize(numPoints);
    
    const int numIterMax = 25;
    const Transformation<double> initialPose = TorigBase;
    int bestInliers = 0;
    //TODO add a termination criterion
    for (unsigned int iteration = 0; iteration < numIterMax; iteration++)
    {
        Transformation<double> pose = initialPose;
        int maxIdx = observationVec.size();
        //choose three points at random
	    int idx1m = rand() % maxIdx;
	    int idx2m, idx3m;
	    do 
	    {
		    idx2m = rand() % maxIdx;
	    } while (idx2m == idx1m);
	
	    do 
	    {
		    idx3m = rand() % maxIdx;
	    } while (idx3m == idx1m or idx3m == idx2m);
        
        
        //solve an optimization problem 
        
        Problem problem;
        for (auto i : {idx1m, idx2m, idx3m})
        {
            CostFunction * costFunc = new OdometryError(cloud[i],
                                        observationVec[i], TbaseCam, camera);
            problem.AddResidualBlock(costFunc, NULL,
                        pose.transData(), pose.rotData());
        }
        
        Solver::Options options;
        options.linear_solver_type = ceres::DENSE_SCHUR;
        Solver::Summary summary;
        options.max_num_iterations = 5;
        Solve(options, &problem, &summary);
            
        //count inliers
        vector<Vector3d> XcamVec(numPoints);
        Transformation<double> TorigCam = pose.compose(TbaseCam);
        TorigCam.inverseTransform(cloud, XcamVec);
        vector<Vector2d> projVec(numPoints);
        camera.projectPointCloud(XcamVec, projVec);
        vector<bool> currentInlierMask(numPoints, false);
        
        int countInliers = 0;
        for (unsigned int i = 0; i < numPoints; i++)
        {   
            Vector2d err = observationVec[i] - projVec[i];
            if (err.norm() < 2)
            {
                currentInlierMask[i] = true;
                countInliers++;
            }
        }
        //keep the best hypothesis
        if (countInliers > bestInliers)
        {
            //TODO copy in a bettegit lor way
            inlierMask = currentInlierMask;
            bestInliers = countInliers;
            TorigBase = pose;
        }        
    }
}