Esempio n. 1
0
PIDOutput wholeBodyPID(NewQPControllerData *pdata, double t, const Ref<const VectorXd> &q, const Ref<const VectorXd> &qd, const Ref<const VectorXd> &q_des, WholeBodyParams *params) {
  // Run a PID controller on the whole-body state to produce desired accelerations and reference posture
  PIDOutput out;
  double dt = 0;
  int nq = pdata->r->num_positions;
  assert(q.size() == nq);
  assert(qd.size() == pdata->r->num_velocities);
  assert(q_des.size() == params->integrator.gains.size());
  if (nq != pdata->r->num_velocities) {
    mexErrMsgTxt("this function will need to be rewritten when num_pos != num_vel");
  }
  if (pdata->state.t_prev != 0) {
    dt = t - pdata->state.t_prev;
  }
  pdata->state.q_integrator_state = params->integrator.eta * pdata->state.q_integrator_state + params->integrator.gains.cwiseProduct(q_des - q) * dt;
  pdata->state.q_integrator_state = pdata->state.q_integrator_state.array().max(-params->integrator.clamps.array());
  pdata->state.q_integrator_state = pdata->state.q_integrator_state.array().min(params->integrator.clamps.array());
  out.q_ref = q_des + pdata->state.q_integrator_state;
  out.q_ref = out.q_ref.array().max((pdata->r->joint_limit_min - params->integrator.clamps).array());
  out.q_ref = out.q_ref.array().min((pdata->r->joint_limit_max + params->integrator.clamps).array());

  pdata->state.q_integrator_state = pdata->state.q_integrator_state.array().max(-params->integrator.clamps.array());
  pdata->state.q_integrator_state = pdata->state.q_integrator_state.array().min(params->integrator.clamps.array());

  VectorXd err_q;
  err_q.resize(nq);
  err_q.head(3) = q_des.head(3) - q.head(3);
  for (int j = 3; j < nq; j++) {
    err_q(j) = angleDiff(q(j), q_des(j));
  }
  out.qddot_des = params->Kp.cwiseProduct(err_q) - params->Kd.cwiseProduct(qd);
  out.qddot_des = out.qddot_des.array().max(params->qdd_bounds.min.array());
  out.qddot_des = out.qddot_des.array().min(params->qdd_bounds.max.array());
  return out;
}
Esempio n. 2
0
float angleDiffDeg(float a, float b)
{
	/*float diff = fmod(b - a + 180.f, 360.f);
	if(diff < 0.f) diff += 380.f;
	return diff - 180.f;*/

	return toDegrees(angleDiff(toRadians(a), toRadians(b)));
}
Esempio n. 3
0
File: Car.cpp Progetto: genail/gear
void Car::applyCollision(const CL_LineSegment2f &p_seg)
{
	static const float DAMAGE_MULT = 0.2f;

	const float side = -p_seg.point_right_of_line(m_impl->m_position);

	const CL_Vec2f segVec = p_seg.q - p_seg.p;

	// need front normal (crash side)
	CL_Vec2f fnormal(segVec.y, -segVec.x); // right side normal
	fnormal.normalize();

	if (side < 0) {
		fnormal *= -1;
	}

	// move away
	m_impl->m_position += (fnormal * fabs(m_impl->m_speed));

	// calculate collision angle to estaminate speed reduction
	CL_Angle angleDiff(m_impl->m_phyMoveRot - m_impl->vecToAngle(fnormal));
	Workarounds::clAngleNormalize180(&angleDiff);

	const float colAngleDeg = fabs(angleDiff.to_degrees()) - 90.0f;
	const float reduction = fabs(1.0f - fabs(colAngleDeg - 90.0f) / 90.0f);

	// calculate and apply damage
	const float damage = m_impl->m_speed * reduction * DAMAGE_MULT;
	m_impl->m_damage =
			Math::Float::reduce(m_impl->m_damage + damage, 0.0f, 1.0f);

	cl_log_event(LOG_DEBUG, "damage: %1, total: %2", damage, m_impl->m_damage);

	// reduce speed
	m_impl->m_speed -= m_impl->m_speed * reduction;

	// bounce movement vector and angle away

	// get mirror point
	if (m_impl->m_phyMoveVec.length() > 0.01f) {
		m_impl->m_phyMoveVec.normalize();

		const float lengthProj = m_impl->m_phyMoveVec.length() * cos(segVec.angle(m_impl->m_phyMoveVec).to_radians());
		const CL_Vec2f mirrorPoint(segVec * (lengthProj / segVec.length()));

		// invert move vector by mirror point
		const CL_Vec2f mirrorVec = (m_impl->m_phyMoveVec - mirrorPoint) * -1;
		m_impl->m_phyMoveVec = mirrorPoint + mirrorVec;

		// update physics angle
		m_impl->m_phyMoveRot = m_impl->vecToAngle(m_impl->m_phyMoveVec);

	}

}
void SpaceObjectShip :: update(qint64 time)
{
  if (mTargetX != -1 && mTargetY != -1)
  {
    double tAngle = angle(mCoordX, mCoordY, mTargetX, mTargetY);
    double dist = distance(mCoordX, mCoordY, mTargetX, mTargetY) / 4;
    double diff = angleDiff(mRotation, tAngle);

    mDirection = turnDirection(mRotation, tAngle);

    if (diff > -dist && diff < dist)
      mTrust = true;
    else
      mTrust = false;

    if (dist < 2)
    {
      mTargetX = -1;
      mTargetY = -1;
      mTrust = false;
      mDirection = 0;
    }
  }


  /* normal calculation of rotation / thrust */
  mRotation += mDirection * (time / 1000.0) * ROT_PER_SEC;

  if (mRotation < 0) mRotation += 360;
  if (mRotation >= 360) mRotation -= 360;

  if (mTrust)
  {
    mCoordX += qCos( DEG2RAD(mRotation) ) * (time / 1000.0) * SPEED_PER_SEC;
    mCoordY += qSin( DEG2RAD(mRotation) ) * (time / 1000.0) * SPEED_PER_SEC;
  }
}
Esempio n. 5
0
Vector6d bodyMotionPD(RigidBodyManipulator *r, Map<VectorXd> &q, Map<VectorXd> &qd, const int body_index, const Ref<const Vector6d> &body_pose_des, const Ref<const Vector6d> &body_v_des, const Ref<const Vector6d> &body_vdot_des, const Ref<const Vector6d> &Kp, const Ref<const Vector6d> &Kd) {

  r->doKinematics(q,false,qd);

  // TODO: this must be updated to use quaternions/spatial velocity
  Vector6d body_pose;
  MatrixXd J = MatrixXd::Zero(6,r->num_positions);
  Vector4d zero = Vector4d::Zero();
  zero(3) = 1.0;
  r->forwardKin(body_index,zero,1,body_pose);
  r->forwardJac(body_index,zero,1,J);

  Vector6d body_error;
  body_error.head<3>()= body_pose_des.head<3>()-body_pose.head<3>();

  Vector3d error_rpy,pose_rpy,des_rpy;
  pose_rpy = body_pose.tail<3>();
  des_rpy = body_pose_des.tail<3>();
  angleDiff(pose_rpy,des_rpy,error_rpy);
  body_error.tail(3) = error_rpy;

  Vector6d body_vdot = (Kp.array()*body_error.array()).matrix() + (Kd.array()*(body_v_des-J*qd).array()).matrix() + body_vdot_des;
  return body_vdot;
}
Esempio n. 6
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  if (nrhs<1) mexErrMsgTxt("usage: ptr = pelvisMotionControlmex(0,robot_obj,alpha,nominal_pelvis_height,Kp,Kd); y=pelvisMotionControlmex(ptr,x)");
  if (nlhs<1) mexErrMsgTxt("take at least one output... please.");
  
  struct PelvisMotionControlData* pdata;

  if (mxGetScalar(prhs[0])==0) { // then construct the data object and return
    pdata = new struct PelvisMotionControlData;
    
    // get robot mex model ptr
    if (!mxIsNumeric(prhs[1]) || mxGetNumberOfElements(prhs[1])!=1)
      mexErrMsgIdAndTxt("DRC:pelvisMotionControlmex:BadInputs","the second argument should be the robot mex ptr");
    memcpy(&(pdata->r),mxGetData(prhs[1]),sizeof(pdata->r));
        
    if (!mxIsNumeric(prhs[2]) || mxGetNumberOfElements(prhs[2])!=1)
    mexErrMsgIdAndTxt("DRC:pelvisMotionControlmex:BadInputs","the third argument should be alpha");
    memcpy(&(pdata->alpha),mxGetPr(prhs[2]),sizeof(pdata->alpha));

    if (!mxIsNumeric(prhs[3]) || mxGetNumberOfElements(prhs[3])!=1)
    mexErrMsgIdAndTxt("DRC:pelvisMotionControlmex:BadInputs","the fourth argument should be nominal_pelvis_height");
    memcpy(&(pdata->nominal_pelvis_height),mxGetPr(prhs[3]),sizeof(pdata->nominal_pelvis_height));

    if (!mxIsNumeric(prhs[4]) || mxGetM(prhs[4])!=6 || mxGetN(prhs[4])!=1)
    mexErrMsgIdAndTxt("DRC:pelvisMotionControlmex:BadInputs","the fifth argument should be Kp");
    memcpy(&(pdata->Kp),mxGetPr(prhs[4]),sizeof(pdata->Kp));

    if (!mxIsNumeric(prhs[5]) || mxGetM(prhs[5])!=6 || mxGetN(prhs[5])!=1)
    mexErrMsgIdAndTxt("DRC:pelvisMotionControlmex:BadInputs","the sixth argument should be Kd");
    memcpy(&(pdata->Kd),mxGetPr(prhs[5]),sizeof(pdata->Kd));

    
    mxClassID cid;
    if (sizeof(pdata)==4) cid = mxUINT32_CLASS;
    else if (sizeof(pdata)==8) cid = mxUINT64_CLASS;
    else mexErrMsgIdAndTxt("Drake:pelvisMotionControlmex:PointerSize","Are you on a 32-bit machine or 64-bit machine??");
     
    pdata->pelvis_height_previous = -1;

    pdata->pelvis_body_index = pdata->r->findLinkInd("pelvis", 0);
    pdata->rfoot_body_index = pdata->r->findLinkInd("r_foot", 0);
    pdata->lfoot_body_index = pdata->r->findLinkInd("l_foot", 0);

    plhs[0] = mxCreateNumericMatrix(1,1,cid,mxREAL);
    memcpy(mxGetData(plhs[0]),&pdata,sizeof(pdata));
     
    return;
  }
  
  // first get the ptr back from matlab
  if (!mxIsNumeric(prhs[0]) || mxGetNumberOfElements(prhs[0])!=1)
    mexErrMsgIdAndTxt("DRC:pelvisMotionControlmex:BadInputs","the first argument should be the ptr");
  memcpy(&pdata,mxGetData(prhs[0]),sizeof(pdata));

  int nq = pdata->r->num_dof;
  int narg = 1;
  double *q = mxGetPr(prhs[narg++]);
  double *qd = &q[nq];
  Map<VectorXd> qdvec(qd,nq);
  double lfoot_yaw = mxGetScalar(prhs[narg++]);
  double rfoot_yaw = mxGetScalar(prhs[narg++]);
 
  pdata->r->doKinematics(q,false,qd);

  // TODO: this must be updated to use quaternions/spatial velocity
  Vector6d pelvis_pose,rfoot_pose,lfoot_pose;
  MatrixXd Jpelvis = MatrixXd::Zero(6,pdata->r->num_dof);
  Vector4d zero = Vector4d::Zero();
  zero(3) = 1.0;
  pdata->r->forwardKin(pdata->pelvis_body_index,zero,1,pelvis_pose);
  pdata->r->forwardJac(pdata->pelvis_body_index,zero,1,Jpelvis);
  pdata->r->forwardKin(pdata->rfoot_body_index,zero,1,rfoot_pose);
  pdata->r->forwardKin(pdata->lfoot_body_index,zero,1,lfoot_pose);

  if (pdata->pelvis_height_previous<0) {
    pdata->pelvis_height_previous = pelvis_pose(2);
  }

  double min_foot_z = std::min(lfoot_pose(2),rfoot_pose(2));
  double mean_foot_yaw = angleAverage(lfoot_yaw,rfoot_yaw);

  double pelvis_height_desired = pdata->alpha*pdata->pelvis_height_previous + (1.0-pdata->alpha)*(min_foot_z + pdata->nominal_pelvis_height); 
  pdata->pelvis_height_previous = pelvis_height_desired;
      
  Vector6d body_des;
  double nan = std::numeric_limits<double>::quiet_NaN();
  body_des << nan,nan,pelvis_height_desired,0,0,mean_foot_yaw; 
  Vector6d error;
  error.head<3>()= body_des.head<3>()-pelvis_pose.head<3>();

  Vector3d error_rpy,pose_rpy,des_rpy;
  pose_rpy = pelvis_pose.tail<3>();
  des_rpy = body_des.tail<3>();
  angleDiff(pose_rpy,des_rpy,error_rpy);
  error.tail(3) = error_rpy;

  Vector6d body_vdot = (pdata->Kp.array()*error.array()).matrix() - (pdata->Kd.array()*(Jpelvis*qdvec).array()).matrix();
  
  plhs[0] = eigenToMatlab(body_vdot);
}
void ADynamicCarController::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	if (play) {
		float deltaSec = GWorld->GetWorld()->GetDeltaSeconds();

		updateTarget();

		if (first) {
			first = false;
			FRotator rotation = agent->GetActorRotation();
			rotation.Yaw = getRotation(agent->GetActorLocation(), target);
			agent->SetActorRotation(rotation);

			if (followPath) {
				waypoints = DubinsPath::getPath(waypoints, to2D(agent->GetActorLocation()), rotation.Yaw, maxAngle, L, graph, errorTolerance);

				writeWaypointsToFile("Waypoints2.txt");

				if (waypoints.Num() > 0) {
					target = waypoints[0];
				}
			}
		}

		if (waypointReached()) {
			bool t35 = followPath && waypointsIndex >= waypoints.Num();
			bool t4 = avoidAgents && !followPath;

			if (t35 || t4) {
				play = false;
				GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::Green, FString::Printf(TEXT("Time: %f\r\n"), totalTime));
			}

			return;
		}

		float a = getAcceleration(deltaSec);

		v += a;

		v = UKismetMathLibrary::FClamp(v, -vMax, vMax);

		float rotation = rotate(deltaSec);

		FVector vPref = FVector(v * UKismetMathLibrary::DegCos(rotation) * deltaSec, v * UKismetMathLibrary::DegSin(rotation) * deltaSec, 0);

		vPref = vPref.GetClampedToMaxSize2D(UKismetMathLibrary::FMin(v * deltaSec, FVector2D::Distance(to2D(agent->GetActorLocation()), target)));

		FVector oldVel = velocity;

		if (avoidAgents) {
			adjustVelocity(to2D(vPref), deltaSec);
			//velocity = vPref;
		} else {
			velocity = vPref;
		}

		FVector2D q = to2D(velocity - oldVel);
		float dv = FMath::Sqrt(FVector2D::DotProduct(q, q));

		if (dv > aMax * deltaSec) {
			float f = aMax * deltaSec / dv;
			velocity = (1 - f) * oldVel + f * velocity;
		}

		float rot = agent->GetActorRotation().Yaw;

		if (velocity.Size2D() != 0) {
			if (angleDiff(rot, velocity.Rotation().Yaw) > 90) {
				velocity = -velocity;
				setRotation();
				velocity = -velocity;
			} else {
				setRotation();
			}
		}

		/*
		if (UKismetMathLibrary::Abs(angleDiff(rot, agent->GetActorRotation().Yaw)) / deltaSec > maxAngle * (v / L) + 5) {
			GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::Red, FString::Printf(TEXT("rot: %f yaw: %f -> %f (%f)      %d   %s -> %s"), rot, agent->GetActorRotation().Yaw, angleDiff(rot, agent->GetActorRotation().Yaw), UKismetMathLibrary::Abs(angleDiff(rot, agent->GetActorRotation().Yaw)) / deltaSec, vPref.Equals(velocity), *to2D(vPref).ToString(), *to2D(velocity).ToString()));
			DrawDebugLine(GWorld->GetWorld(), FVector(to2D(agent->GetActorLocation()), 20), FVector(to2D(agent->GetActorLocation()), 30), FColor::Red, false, 0.5, 0, 1);
			GEngine->DeferredCommands.Add(TEXT("pause"));
		}*/

		agent->SetActorLocation(agent->GetActorLocation() + velocity);

		/*
		DrawDebugLine(GWorld->GetWorld(), to3D(target), to3D(target) + collisionSize, collisionColor, false, 0.1, 0, 1);

		float a = getAcceleration(deltaSec);

		v += a;

		v = UKismetMathLibrary::FClamp(v, -vMax, vMax);

		float rotation = rotate(deltaSec);

		acceleration.X = a * UKismetMathLibrary::DegCos(rotation);
		acceleration.Y = a * UKismetMathLibrary::DegSin(rotation);

		drawLine(2 * acceleration / deltaSec, accelerationColor);

		velocity = FVector(v * UKismetMathLibrary::DegCos(rotation) * deltaSec, v * UKismetMathLibrary::DegSin(rotation) * deltaSec, 0);

		float rot = agent->GetActorRotation().Yaw;

		setRotation();

		GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::Red, FString::Printf(TEXT("%f"), UKismetMathLibrary::Abs(rot - agent->GetActorRotation().Yaw) / deltaSec));

		agent->SetActorLocation(agent->GetActorLocation() + velocity);

		DrawDebugLine(GWorld->GetWorld(), agent->GetActorLocation(), agent->GetActorLocation() + collisionSize, FColor::Green, false, 0.1, 0, 1);
		*/
	}
}
inline double unwrap(double previousAngle, double newAngle) {
	return previousAngle - angleDiff(newAngle, angleConv(previousAngle));
}
Esempio n. 9
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  if (nrhs<1) mexErrMsgTxt("usage: ptr = bodyMotionControlmex(0,robot_obj,Kp,Kd,body_index); y=bodyMotionControlmex(ptr,x,body_pose_des,body_v_des,body_vdot_des)");
  if (nlhs<1) mexErrMsgTxt("take at least one output... please.");
  
  struct BodyMotionControlData* pdata;

  if (mxGetScalar(prhs[0])==0) { // then construct the data object and return
    pdata = new struct BodyMotionControlData;
    
    // get robot mex model ptr
    if (!mxIsNumeric(prhs[1]) || mxGetNumberOfElements(prhs[1])!=1)
      mexErrMsgIdAndTxt("DRC:bodyMotionControlmex:BadInputs","the second argument should be the robot mex ptr");
    memcpy(&(pdata->r),mxGetData(prhs[1]),sizeof(pdata->r));
        
    if (!mxIsNumeric(prhs[2]) || mxGetM(prhs[2])!=6 || mxGetN(prhs[2])!=1)
    mexErrMsgIdAndTxt("DRC:bodyMotionControlmex:BadInputs","the third argument should be Kp");
    memcpy(&(pdata->Kp),mxGetPrSafe(prhs[2]),sizeof(pdata->Kp));

    if (!mxIsNumeric(prhs[3]) || mxGetM(prhs[3])!=6 || mxGetN(prhs[3])!=1)
    mexErrMsgIdAndTxt("DRC:bodyMotionControlmex:BadInputs","the fourth argument should be Kd");
    memcpy(&(pdata->Kd),mxGetPrSafe(prhs[3]),sizeof(pdata->Kd));

    pdata->body_index = (int) mxGetScalar(prhs[4]) -1;

    mxClassID cid;
    if (sizeof(pdata)==4) cid = mxUINT32_CLASS;
    else if (sizeof(pdata)==8) cid = mxUINT64_CLASS;
    else mexErrMsgIdAndTxt("Drake:bodyMotionControlmex:PointerSize","Are you on a 32-bit machine or 64-bit machine??");
     
    plhs[0] = mxCreateNumericMatrix(1,1,cid,mxREAL);
    memcpy(mxGetData(plhs[0]),&pdata,sizeof(pdata));
     
    return;
  }
  
  // first get the ptr back from matlab
  if (!mxIsNumeric(prhs[0]) || mxGetNumberOfElements(prhs[0])!=1)
    mexErrMsgIdAndTxt("DRC:bodyMotionControlmex:BadInputs","the first argument should be the ptr");

  memcpy(&pdata,mxGetData(prhs[0]),sizeof(pdata));

  int nq = pdata->r->num_positions;
  int nv = pdata->r->num_velocities;

  int narg = 1;
  
  Map<VectorXd> q(mxGetPrSafe(prhs[narg]), nq);
  Map<VectorXd> qd(mxGetPrSafe(prhs[narg++]) + nq, nv);

  assert(mxGetM(prhs[narg])==6); assert(mxGetN(prhs[narg])==1);
  Map< Vector6d > body_pose_des(mxGetPrSafe(prhs[narg++]));

  assert(mxGetM(prhs[narg])==6); assert(mxGetN(prhs[narg])==1);
  Map< Vector6d > body_v_des(mxGetPrSafe(prhs[narg++]));

  assert(mxGetM(prhs[narg])==6); assert(mxGetN(prhs[narg])==1);
  Map< Vector6d > body_vdot_des(mxGetPrSafe(prhs[narg++]));

  pdata->r->doKinematics(q, qd);

  // TODO: this must be updated to use quaternions/spatial velocity
  auto body_pose_gradientvar = pdata->r->forwardKin(Vector3d::Zero().eval(), pdata->body_index, 0, 1, 1);
  const auto& body_pose = body_pose_gradientvar.value();
  const auto& J = body_pose_gradientvar.gradient().value();

  Vector6d body_error;
  body_error.head<3>()= body_pose_des.head<3>()-body_pose.head<3>();

  Vector3d error_rpy,pose_rpy,des_rpy;
  pose_rpy = body_pose.tail<3>();
  des_rpy = body_pose_des.tail<3>();
  angleDiff(pose_rpy,des_rpy,error_rpy);
  body_error.tail(3) = error_rpy;

  Vector6d body_vdot = (pdata->Kp.array()*body_error.array()).matrix() + (pdata->Kd.array()*(body_v_des-J*qd).array()).matrix() + body_vdot_des;
  
  plhs[0] = eigenToMatlab(body_vdot);
}
Esempio n. 10
0
void localizerGVG::handleOdom(const nav_msgs::Odometry::ConstPtr& odom) {
  double x=odom->pose.pose.position.x;
  double y=odom->pose.pose.position.y;
  tf::Pose pose;
  tf::poseMsgToTF(odom->pose.pose, pose);
  double yaw=tf::getYaw(pose.getRotation());
  ROS_DEBUG("IN [x=%f, y=%f, yaw=%f]",x,y,yaw);
  if(std::isnan(yaw) || std::isnan(x) || std::isnan(y)){
    ROS_WARN("Odom read nan, skipping iteration of publishing and hoping for recovery.");
    return;
  }
  if(!initOdom) {
    oldX=x;
    oldY=y;
    oldYaw=yaw;
    initOdom=true;
    oldStamp=odom->header.stamp;
    Vector3d odomVector(x, y, yaw);
    X.segment(0, 3) = odomVector;
    return;
  }
  if(this->filterOn) {
    if((oldX==x)&&(oldY==y)&&(oldYaw==yaw)){
      oldStamp=odom->header.stamp;
      return;
    }
    // Calculate the measurement
    double dx=x-oldX;
    double dy=y-oldY;
    double dYaw=angleDiff(yaw,oldYaw);
    double dt=odom->header.stamp.toSec()-oldStamp.toSec();
    if(dt==0) {
      ROS_DEBUG("dt in localizer equal to zero, will lead to nan. skipping and hoping for recovery");
      return;
    }
    double Vm=sqrt(dx*dx+dy*dy)/dt;
    double Wm=dYaw/dt;
    X(0)=X(0)+Vm*dt*cos(X(2));
    X(1)=X(1)+Vm*dt*sin(X(2));
    X(2)=thetapp(X(2)+Wm*dt);
    propagate(Vm,Wm,dt);
    // Publish the odometry with covariance topic
    geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(X(2));
    nav_msgs::Odometry outputPose;
    outputPose.header.frame_id = "odom";
    outputPose.header.stamp =odom->header.stamp;
    outputPose.pose.pose.position.x = X(0);
    outputPose.pose.pose.position.y = X(1);
    outputPose.pose.pose.position.z = 0;
    outputPose.pose.pose.orientation=odom_quat;

    if(std::isnan(X(0)),std::isnan(X(1)))
    {
      ROS_WARN("Filter made something nan, skipping publishing and hoping for recovery.");
      return;
    }
    for (unsigned int i=0; i<2; i++)
      for (unsigned int j=0; j<2; j++)
    	outputPose.pose.covariance[6*i+j] = P(i,j);
    posePub.publish(outputPose);
  }
  oldX=x;
  oldY=y;
  oldYaw=yaw;
  oldStamp=odom->header.stamp;
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
File: hsm.c Progetto: abachrach/csm
void hsm_match(struct hsm_params*p, hsm_buffer b1, hsm_buffer b2) {
	sm_log_push("hsm_match");
	/* Let's measure the time */
	clock_t hsm_match_start = clock();
	
	assert(b1->num_angular_cells == b2->num_angular_cells);
	assert(p->max_translation > 0);
	assert(b1->linear_cell_size > 0);

	b1->num_valid_results = 0;

	/* Compute cross-correlation of spectra */
	hsm_circular_cross_corr_stupid(b1->num_angular_cells, b2->hs, b1->hs, b1->hs_cross_corr);

	/* Find peaks in cross-correlation */
	int peaks[p->num_angular_hypotheses], npeaks;
	hsm_find_peaks_circ(b1->num_angular_cells, b1->hs_cross_corr, p->angular_hyp_min_distance_deg, 0, p->num_angular_hypotheses, peaks, &npeaks);

	sm_debug("Found %d peaks (max %d) in cross correlation.\n", npeaks, p->num_angular_hypotheses);

	if(npeaks == 0) {
		sm_error("Cross correlation of spectra has 0 peaks.\n");
		sm_log_pop();
		return;
	}

	sm_log_push("loop on theta hypotheses");
	/* lag e' quanto 2 si sposta a destra rispetto a 1 */
	for(int np=0;np<npeaks;np++) {
		int lag = peaks[np];
		double theta_hypothesis = lag * (2*M_PI/b1->num_angular_cells);

		sm_debug("Theta hyp#%d: lag %d, angle %fdeg\n", np, lag, rad2deg(theta_hypothesis));

		/* Superimpose the two spectra */
		double mult[b1->num_angular_cells];
		for(int r=0;r<b1->num_angular_cells;r++)
			mult[r] = b1->hs[r] * b2->hs[pos_mod(r-lag, b1->num_angular_cells)];

		/* Find directions where both are intense */
		int directions[p->xc_ndirections], ndirections;
		hsm_find_peaks_circ(b1->num_angular_cells, b1->hs_cross_corr, p->xc_directions_min_distance_deg, 1, p->xc_ndirections, directions, &ndirections);

		if(ndirections<2) {
			sm_error("Too few directions.\n");
		}
		
		struct {
			/* Direction of cross correlation */
			double angle;
			int nhypotheses;
			struct {
				double delta;
				double value;
			} hypotheses[p->linear_xc_max_npeaks];
		} dirs[ndirections];


		sm_debug("Using %d (max %d) correlations directions.\n", ndirections, p->xc_ndirections);

		int max_lag = (int) ceil(p->max_translation / b1->linear_cell_size);
		int min_lag = -max_lag;
		sm_debug("Max lag: %d cells (max t: %f, cell size: %f)\n",
			max_lag, p->max_translation, b1->linear_cell_size);

		sm_log_push("loop on xc direction");
		/* For each correlation direction */
		for(int cd=0;cd<ndirections;cd++) {

 			dirs[cd].angle =  theta_hypothesis + (directions[cd]) * (2*M_PI/b1->num_angular_cells);

			printf(" cd %d angle = %d deg\n", cd, (int) rad2deg(dirs[cd].angle));

			/* Do correlation */
			int    lags  [2*max_lag + 1];
			double xcorr [2*max_lag + 1];

			int i1 = pos_mod(directions[cd]        , b1->num_angular_cells);
			int i2 = pos_mod(directions[cd] + lag  , b1->num_angular_cells);
			double *f1 = b1->ht[i1];
			double *f2 = b2->ht[i2];

			hsm_linear_cross_corr_stupid(
				b2->num_linear_cells,f2,
				b1->num_linear_cells,f1,
				xcorr, lags, min_lag, max_lag);

			/* Find peaks of cross-correlation */
			int linear_peaks[p->linear_xc_max_npeaks], linear_npeaks;

			hsm_find_peaks_linear(
				2*max_lag + 1, xcorr, p->linear_xc_peaks_min_distance/b1->linear_cell_size,
				p->linear_xc_max_npeaks, linear_peaks, &linear_npeaks);

			sm_debug("theta hyp #%d: Found %d (max %d) peaks for correlation.\n",
				cd, linear_npeaks, p->linear_xc_max_npeaks);

			dirs[cd].nhypotheses = linear_npeaks;
			sm_log_push("Considering each peak of linear xc");
			for(int lp=0;lp<linear_npeaks;lp++) {
				int linear_xc_lag = lags[linear_peaks[lp]];
				double value = xcorr[linear_peaks[lp]];
				double linear_xc_lag_m = linear_xc_lag * b1->linear_cell_size;
				sm_debug("lag: %d  delta: %f  value: %f \n", linear_xc_lag, linear_xc_lag_m, value);
				dirs[cd].hypotheses[lp].delta = linear_xc_lag_m;
				dirs[cd].hypotheses[lp].value = value;
			}
			sm_log_pop();
			
			if(p->debug_true_x_valid) {
				double true_delta = cos(dirs[cd].angle) * p->debug_true_x[0] + 
					sin(dirs[cd].angle) * p->debug_true_x[1];
				sm_debug("true_x    delta = %f \n", true_delta );
			}

		} /* xc direction */
		sm_log_pop();

		sm_debug("Now doing all combinations. How many are there?\n");
		int possible_choices[ndirections];
		int num_combinations = 1;
		for(int cd=0;cd<ndirections;cd++) {
			possible_choices[cd] = dirs[cd].nhypotheses;
			num_combinations *= dirs[cd].nhypotheses;
		}
		sm_debug("Total: %d combinations\n", num_combinations);
		sm_log_push("For each combination..");
		for(int comb=0;comb<num_combinations;comb++) {
			int choices[ndirections];
			hsm_generate_combinations(ndirections, possible_choices, comb, choices);

			/* Linear least squares */
			double M[2][2]={{0,0},{0,0}}; double Z[2]={0,0};
			/* heuristic quality value */
			double sum_values = 0;
			for(int cd=0;cd<ndirections;cd++) {
				double angle = dirs[cd].angle;
				double c = cos(angle), s = sin(angle);
				double w = dirs[cd].hypotheses[choices[cd]].value;
				double y = dirs[cd].hypotheses[choices[cd]].delta;

				M[0][0] += c * c * w;
				M[1][0] += c * s * w;
				M[0][1] += c * s * w;
				M[1][1] += s * s * w;
				Z[0] += w * c * y;
				Z[1] += w * s * y;

				sum_values += w;
			}

			double det = M[0][0]*M[1][1]-M[0][1]*M[1][0];
			double Minv[2][2];
			Minv[0][0] = M[1][1] * (1/det);
			Minv[1][1] = M[0][0] * (1/det);
			Minv[0][1] = -M[0][1] * (1/det);
			Minv[1][0] = -M[1][0] * (1/det);

			double t[2] = {
				Minv[0][0]*Z[0] + Minv[0][1]*Z[1],
				Minv[1][0]*Z[0] + Minv[1][1]*Z[1]};

			/* copy result in results slot */

			int k = b1->num_valid_results;
			b1->results[k][0] = t[0];
			b1->results[k][1] = t[1];
			b1->results[k][2] = theta_hypothesis;
			b1->results_quality[k] = sum_values;
			b1->num_valid_results++;
		}
		sm_log_pop();

	} /* theta hypothesis */
	sm_log_pop();

/*	for(int i=0;i<b1->num_valid_results;i++) {
		printf("#%d %.0fdeg %.1fm %.1fm  quality %f \n",i,
			rad2deg(b1->results[i][2]),
			b1->results[i][0],
			b1->results[i][1],
			b1->results_quality[i]);
	}*/


	/* Sorting based on values */
	int indexes[b1->num_valid_results];
	for(int i=0;i<b1->num_valid_results;i++)
		indexes[i] = i;

	qsort_descending(indexes, (size_t) b1->num_valid_results, b1->results_quality);

	/* copy in the correct order*/
	double*results_tmp[b1->num_valid_results];
	double results_quality_tmp[b1->num_valid_results];
	for(int i=0;i<b1->num_valid_results;i++) {
		results_tmp[i] = b1->results[i];
		results_quality_tmp[i] = b1->results_quality[i];
	}

	for(int i=0;i<b1->num_valid_results;i++) {
		b1->results[i] = results_tmp[indexes[i]];
		b1->results_quality[i] = results_quality_tmp[indexes[i]];
	}

	for(int i=0;i<b1->num_valid_results;i++) {
		char near[256]="";
		double *x = b1->results[i];
		if(p->debug_true_x_valid) {
			double err_th = rad2deg(fabs(angleDiff(p->debug_true_x[2],x[2])));
			double err_m = hypot(p->debug_true_x[0]-x[0],
				p->debug_true_x[1]-x[1]);
			const char * ast = (i == 0) && (err_th > 2) ? "   ***** " : "";
			sprintf(near, "th err %4d  err_m  %5f %s",(int)err_th ,err_m,ast);
		}
		if(i<10)
		printf("after #%d %3.1fm %.1fm %3.0fdeg quality %5.0f \t%s\n",i,
			x[0],
			x[1], rad2deg(x[2]), b1->results_quality[i], near);
	}
	
	
	/* How long did it take? */
	clock_t hsm_match_stop = clock();
	int ticks = hsm_match_stop-hsm_match_start;
	double ctime = ((double)ticks) / CLOCKS_PER_SEC;
	sm_debug("Time: %f sec (%d ticks)\n", ctime, ticks);
	
	sm_log_pop();
}
Esempio n. 13
0
double
GeomHelper::angle2D(const Position& p1, const Position& p2) {
    return angleDiff(atan2(p1.y(), p1.x()), atan2(p2.y(), p2.x()));
}