void AgentCore::control() {
  Eigen::VectorXd stats_error = statsMsgToVector(target_statistics_) - statsMsgToVector(estimated_statistics_);
  // update non constant values of the jacobian of phi(p) = [px, py, pxx, pxy, pyy]
  jacob_phi_(2,0) = 2*pose_virtual_.position.x;
  jacob_phi_(3,0) = pose_virtual_.position.y;
  jacob_phi_(3,1) = pose_virtual_.position.x;
  jacob_phi_(4,1) = 2*pose_virtual_.position.y;

  // twist_virtual = inv(B + Jphi'*lambda*Jphi) * Jphi' * gamma * stats_error
  Eigen::VectorXd control_law = (b_ + jacob_phi_.transpose()*lambda_*jacob_phi_).inverse()
                                *jacob_phi_.transpose()*gamma_*stats_error;

  // control command saturation
  double current_velocity_virtual = std::sqrt(std::pow(control_law(0),2) + std::pow(control_law(1),2));
  if (current_velocity_virtual > velocity_virtual_threshold_) {
    control_law *= velocity_virtual_threshold_ / current_velocity_virtual;
  }

  geometry_msgs::Pose pose_old = pose_virtual_;
  pose_virtual_.position.x = integrator(pose_virtual_.position.x, twist_virtual_.linear.x, control_law(0), 1);
  pose_virtual_.position.y = integrator(pose_virtual_.position.y, twist_virtual_.linear.y, control_law(1), 1);
  setTheta(pose_virtual_.orientation, std::atan2(control_law(1), control_law(0)));
  twist_virtual_.linear.x = control_law(0);
  twist_virtual_.linear.y = control_law(1);

  std::stringstream s;
  s << "Statistics error (" << (Eigen::RowVectorXd)stats_error << ").";
  console(__func__, s, DEBUG_V);
  s << "Control commands (" << (Eigen::RowVectorXd)control_law << ").";
  console(__func__, s, DEBUG_VV);
  s << "Virtual pose (" << pose_virtual_.position.x << ", " << pose_virtual_.position.y << ").";
  console(__func__, s, DEBUG_VVV);
  s << "Virtual twist (" << twist_virtual_.linear.x << ", " << twist_virtual_.linear.y << ").";
  console(__func__, s, DEBUG_VVV);

  broadcastPose(pose_virtual_, agent_virtual_frame_);
  broadcastPath(pose_virtual_, pose_old, agent_virtual_frame_);
}
示例#2
0
int testBelugaBoundaryControlLaw()
{
    const char* bad_file_x = "bad_file.txt";
    const char* bad_file_y = "bad_file.txt";
    const char* good_file_x = "../src/Boundary_ForcesX.txt";
    const char* good_file_y = "../src/Boundary_ForcesY.txt";

    BelugaBoundaryControlLaw control_law(good_file_x, good_file_y);

    /* should fail to load bad files */
    DO_TEST("Checking for failure on loading bad files (x)",
            control_law.loadForceFiles(bad_file_x, good_file_y),
            "Didn't return false for " << bad_file_x);
    DO_TEST("Checking for failure on loading bad files (y)",
            control_law.loadForceFiles(good_file_x, bad_file_y),
            "Didn't return false for " << bad_file_y);
    DO_TEST("Checking for success on loading good files",
            !control_law.loadForceFiles(good_file_x, good_file_y),
            "Unable to load files " << good_file_x << " and " << good_file_y);
	
    std::string err_msg;
	
    mt_dVector_t u_in, u_out, state;
    u_in.resize(BELUGA_CONTROL_SIZE, 0.0);
    state.resize(BELUGA_NUM_STATES, 0.0);
	
	/* the output should have BELUGA_CONTROL_SIZE elements */
    START_TEST("Checking output vector size");
    u_out = control_law.doControl(state, u_in);
    if (u_out.size() != BELUGA_CONTROL_SIZE)
        RETURN_ERROR_ELSE_OK("Incorrect size " << u_out.size());
	
	/* robot speed should not change at origin */
	START_TEST("Checking origin");
	state[BELUGA_STATE_X] = 0.0;
	state[BELUGA_STATE_Y] = 0.0;
	double u_speed = u_in[BELUGA_CONTROL_FWD_SPEED];
    double u_vert = u_in[BELUGA_CONTROL_VERT_SPEED];
    double u_turn = u_in[BELUGA_CONTROL_STEERING];
	u_out = control_law.doControl(state, u_in);
	double d_speed = fabs(u_speed - u_out[BELUGA_CONTROL_FWD_SPEED]);
	double d_vert = fabs(u_vert - u_out[BELUGA_CONTROL_VERT_SPEED]);
	double d_turn = fabs(u_turn - u_out[BELUGA_CONTROL_STEERING]);
	if (!eq_wf(d_speed, 0.0))
		RETURN_ERROR_ELSE_OK("Forward speed not zero, was " << u_out[BELUGA_CONTROL_FWD_SPEED]);
	if (!eq_wf(d_vert, 0.0))
		RETURN_ERROR_ELSE_OK("Vertical speed not zero, was " << u_out[BELUGA_CONTROL_VERT_SPEED]);
	if (!eq_wf(d_turn, 0.0))
		RETURN_ERROR_ELSE_OK("Steering not zero, was " << u_out[BELUGA_CONTROL_STEERING]);
	
	/* check robot's response to boundaries in x and y (up to buffer zone), along the respective axes */
	double minDist = 0.5;
	double step = 0.1;
	double boundary = DEFAULT_TANK_RADIUS/sqrt((double) 2.0);
	double buffer = 0.25;
	
	/* robot speed should decrease in x and not change in y the closer it gets to the +x boundary */
	START_TEST("Checking +x boundary");
	state[BELUGA_STATE_Y] = 0.0;
	state[BELUGA_STATE_THETA] = 0.0;
	double th = state[BELUGA_STATE_THETA];
	u_speed = u_in[BELUGA_CONTROL_FWD_SPEED];
    u_turn = u_in[BELUGA_CONTROL_STEERING];
	double prev_vx = u_speed*cos(th) - u_turn*sin(th);
	double prev_vy = u_speed*sin(th) + u_turn*cos(th);
	double dist = minDist;
	while (dist < boundary - buffer)
	{
		state[BELUGA_STATE_X] = dist;
		u_out = control_law.doControl(state, u_in);
		double vr = u_out[BELUGA_CONTROL_FWD_SPEED];
		double vth = u_out[BELUGA_CONTROL_STEERING];
		double vx = vr*cos(th) - vth*sin(th);
		double vy = vr*sin(th) + vth*cos(th);
		if (vx > prev_vx)
			RETURN_ERROR_ELSE_OK("Speed did not decrease in x, was " << vx);
		double dvy = fabs(vy - prev_vy);
		if (!eq_wf(dvy, 0.0))
			RETURN_ERROR_ELSE_OK("Y-speed changed, d_vy was " << dvy);
		prev_vx = vx;
		prev_vy = vy;
		dist += step;
	}
	
	/* robot speed should increase in x and not change in y the closer it gets to the -x boundary */
	START_TEST("Checking -x boundary");
	state[BELUGA_STATE_Y] = 0.0;
	state[BELUGA_STATE_THETA] = PI;
	th = state[BELUGA_STATE_THETA];
	u_speed = u_in[BELUGA_CONTROL_FWD_SPEED];
    u_turn = u_in[BELUGA_CONTROL_STEERING];
	prev_vx = u_speed*cos(th) - u_turn*sin(th);
	prev_vy = u_speed*sin(th) + u_turn*cos(th);
	dist = -minDist;
	while (dist > -(boundary - buffer))
	{
		state[BELUGA_STATE_X] = dist;
		u_out = control_law.doControl(state, u_in);
		double vr = u_out[BELUGA_CONTROL_FWD_SPEED];
		double vth = u_out[BELUGA_CONTROL_STEERING];
		double vx = vr*cos(th) - vth*sin(th);
		double vy = vr*sin(th) + vth*cos(th);
		if (vx < prev_vx)
			RETURN_ERROR_ELSE_OK("Speed did not increase in x, was " << vx);
		double dvy = fabs(vy - prev_vy);
		if (!eq_wf(dvy, 0.0))
			RETURN_ERROR_ELSE_OK("Y-speed changed, d_vy was " << dvy);
		prev_vx = vx;
		prev_vy = vy;
		dist -= step;
	}
	
	/* robot speed should decrease in y and not change in x the closer it gets to the +y boundary */
	START_TEST("Checking +y boundary");
	state[BELUGA_STATE_X] = 0.0;
	state[BELUGA_STATE_THETA] = PI/2;
	th = state[BELUGA_STATE_THETA];
	u_speed = u_in[BELUGA_CONTROL_FWD_SPEED];
    u_turn = u_in[BELUGA_CONTROL_STEERING];
	prev_vx = u_speed*cos(th) - u_turn*sin(th);
	prev_vy = u_speed*sin(th) + u_turn*cos(th);
	dist = minDist;
	while (dist < boundary - buffer)
	{
		state[BELUGA_STATE_Y] = dist;
		u_out = control_law.doControl(state, u_in);
		double vr = u_out[BELUGA_CONTROL_FWD_SPEED];
		double vth = u_out[BELUGA_CONTROL_STEERING];
		double vx = vr*cos(th) - vth*sin(th);
		double vy = vr*sin(th) + vth*cos(th);
		if (vy > prev_vy)
			RETURN_ERROR_ELSE_OK("Speed did not decrease in y, was " << vy);
		double dvx = fabs(vx - prev_vx);
		if (!eq_wf(dvx, 0.0))
			RETURN_ERROR_ELSE_OK("X-speed changed, d_vy was " << dvx);
		prev_vx = vx;
		prev_vy = vy;
		dist += step;
	}
	
	/* robot speed should increase in y and not change in x the closer it gets to the -y boundary */
	START_TEST("Checking -y boundary");
	state[BELUGA_STATE_X] = 0.0;
	state[BELUGA_STATE_THETA] = (3/2)*PI;
	th = state[BELUGA_STATE_THETA];
	u_speed = u_in[BELUGA_CONTROL_FWD_SPEED];
    u_turn = u_in[BELUGA_CONTROL_STEERING];
	prev_vx = u_speed*cos(th) - u_turn*sin(th);
	prev_vy = u_speed*sin(th) + u_turn*cos(th);
	dist = -minDist;
	while (dist > -(boundary - buffer))
	{
		state[BELUGA_STATE_Y] = dist;
		u_out = control_law.doControl(state, u_in);
		double vr = u_out[BELUGA_CONTROL_FWD_SPEED];
		double vth = u_out[BELUGA_CONTROL_STEERING];
		double vx = vr*cos(th) - vth*sin(th);
		double vy = vr*sin(th) + vth*cos(th);
		if (vy < prev_vy)
			RETURN_ERROR_ELSE_OK("Speed did not increase in y, was " << vy);
		double dvx = fabs(vx - prev_vx);
		if (!eq_wf(dvx, 0.0))
			RETURN_ERROR_ELSE_OK("X-speed changed, d_vy was " << dvx);
		prev_vx = vx;
		prev_vy = vy;
		dist -= step;
	}
	
    return OK;
}