Exemplo n.º 1
0
void QuadrotorPropulsion::update(double dt)
{
  if (dt <= 0.0) return;

//  std::cout << "u = [ ";
//  for(std::size_t i = 0; i < propulsion_model_->u.size(); ++i)
//    std::cout << propulsion_model_->u[i] << " ";
//  std::cout << "]" << std::endl;

  checknan(propulsion_model_->u, "propulsion model input");
  checknan(propulsion_model_->x, "propulsion model state");

  // update propulsion model
  f(propulsion_model_->x.data(), propulsion_model_->u.data(), dt, propulsion_model_->y.data(), propulsion_model_->x_pred.data());
  propulsion_model_->x = propulsion_model_->x_pred;

  checknan(propulsion_model_->y, "propulsion model output");

  //  std::cout << "y = [ ";
  //  for(std::size_t i = 0; i < propulsion_model_->y.size(); ++i)
  //    std::cout << propulsion_model_->y[i] << " ";
  //  std::cout << "]" << std::endl;

  wrench_.force.x  =  propulsion_model_->y[0];
  wrench_.force.y  = -propulsion_model_->y[1];
  wrench_.force.z  =  propulsion_model_->y[2];
  wrench_.torque.x =  propulsion_model_->y[3];
  wrench_.torque.y = -propulsion_model_->y[4];
  wrench_.torque.z = -propulsion_model_->y[5];

  motor_status_.voltage[0] = propulsion_model_->u[6];
  motor_status_.voltage[1] = propulsion_model_->u[7];
  motor_status_.voltage[2] = propulsion_model_->u[8];
  motor_status_.voltage[3] = propulsion_model_->u[9];

  motor_status_.frequency[0] = propulsion_model_->y[6];
  motor_status_.frequency[1] = propulsion_model_->y[7];
  motor_status_.frequency[2] = propulsion_model_->y[8];
  motor_status_.frequency[3] = propulsion_model_->y[9];
  motor_status_.running = motor_status_.frequency[0] > 1.0 && motor_status_.frequency[1] > 1.0 && motor_status_.frequency[2] > 1.0 && motor_status_.frequency[3] > 1.0;

  motor_status_.current[0] = propulsion_model_->y[10];
  motor_status_.current[1] = propulsion_model_->y[11];
  motor_status_.current[2] = propulsion_model_->y[12];
  motor_status_.current[3] = propulsion_model_->y[13];
}
Exemplo n.º 2
0
double PID::getFilteredControlError(double& filtered_error, double time_constant, const ros::Duration& dt)
{
    double dt_sec = dt.toSec();
    filtered_error = checknan(filtered_error);
    if (dt_sec + time_constant > 0.0) {
        filtered_error = filtered_error + dt_sec * state_.p - (dt_sec / (dt_sec + time_constant)) * filtered_error;
    }
    return filtered_error;
}
void QuadrotorPropulsion::update(double dt)
{
  if (dt <= 0.0) return;

  ROS_DEBUG_STREAM_NAMED("quadrotor_propulsion", "propulsion.twist:   " << PrintVector<double>(propulsion_model_->u.begin(), propulsion_model_->u.begin() + 6));
  ROS_DEBUG_STREAM_NAMED("quadrotor_propulsion", "propulsion.voltage: " << PrintVector<double>(propulsion_model_->u.begin() + 6, propulsion_model_->u.begin() + 10));
  ROS_DEBUG_STREAM_NAMED("quadrotor_propulsion", "propulsion.x_prior: " << PrintVector<double>(propulsion_model_->x.begin(), propulsion_model_->x.end()));

  checknan(propulsion_model_->u, "propulsion model input");
  checknan(propulsion_model_->x, "propulsion model state");

  // update propulsion model
  f(propulsion_model_->x.data(), propulsion_model_->u.data(), dt, propulsion_model_->y.data(), propulsion_model_->x_pred.data());
  propulsion_model_->x = propulsion_model_->x_pred;

  ROS_DEBUG_STREAM_NAMED("quadrotor_propulsion", "propulsion.x_post:  " << PrintVector<double>(propulsion_model_->x.begin(), propulsion_model_->x.end()));
  ROS_DEBUG_STREAM_NAMED("quadrotor_propulsion", "propulsion.force:   " << PrintVector<double>(propulsion_model_->y.begin() + 0, propulsion_model_->y.begin() + 3) << " " <<
                                                 "propulsion.torque:  " << PrintVector<double>(propulsion_model_->y.begin() + 3, propulsion_model_->y.begin() + 6));

  checknan(propulsion_model_->y, "propulsion model output");

  wrench_.force.x  =  propulsion_model_->y[0];
  wrench_.force.y  = -propulsion_model_->y[1];
  wrench_.force.z  =  propulsion_model_->y[2];
  wrench_.torque.x =  propulsion_model_->y[3];
  wrench_.torque.y = -propulsion_model_->y[4];
  wrench_.torque.z = -propulsion_model_->y[5];

  motor_status_.voltage[0] = propulsion_model_->u[6];
  motor_status_.voltage[1] = propulsion_model_->u[7];
  motor_status_.voltage[2] = propulsion_model_->u[8];
  motor_status_.voltage[3] = propulsion_model_->u[9];

  motor_status_.frequency[0] = propulsion_model_->y[6];
  motor_status_.frequency[1] = propulsion_model_->y[7];
  motor_status_.frequency[2] = propulsion_model_->y[8];
  motor_status_.frequency[3] = propulsion_model_->y[9];
  motor_status_.running = motor_status_.frequency[0] > 1.0 && motor_status_.frequency[1] > 1.0 && motor_status_.frequency[2] > 1.0 && motor_status_.frequency[3] > 1.0;

  motor_status_.current[0] = propulsion_model_->y[10];
  motor_status_.current[1] = propulsion_model_->y[11];
  motor_status_.current[2] = propulsion_model_->y[12];
  motor_status_.current[3] = propulsion_model_->y[13];
}
void QuadrotorAerodynamics::update(double dt)
{
  if (dt <= 0.0) return;
  boost::mutex::scoped_lock lock(mutex_);

  // fill input vector u for drag model
  drag_model_->u[0] =  (twist_.linear.x - wind_.x);
  drag_model_->u[1] = -(twist_.linear.y - wind_.y);
  drag_model_->u[2] = -(twist_.linear.z - wind_.z);
  drag_model_->u[3] =  twist_.angular.x;
  drag_model_->u[4] = -twist_.angular.y;
  drag_model_->u[5] = -twist_.angular.z;

  // We limit the input velocities to +-100. Required for numeric stability in case of collisions,
  // where velocities returned by Gazebo can be very high.
  limit(drag_model_->u, -100.0, 100.0);

  // convert input to body coordinates
  Eigen::Quaterniond orientation(orientation_.w, orientation_.x, orientation_.y, orientation_.z);
  Eigen::Matrix<double,3,3> rotation_matrix(orientation.toRotationMatrix());
  Eigen::Map<Eigen::Vector3d> linear(&(drag_model_->u[0]));
  Eigen::Map<Eigen::Vector3d> angular(&(drag_model_->u[3]));
  linear  = rotation_matrix * linear;
  angular = rotation_matrix * angular;

  ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.twist:  " << PrintVector<double>(drag_model_->u.begin(), drag_model_->u.begin() + 6));
  checknan(drag_model_->u, "drag model input");

  // update drag model
  f(drag_model_->u.data(), dt, drag_model_->y.data());

  ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.force:  " << PrintVector<double>(drag_model_->y.begin() + 0, drag_model_->y.begin() + 3));
  ROS_DEBUG_STREAM_NAMED("quadrotor_aerodynamics", "aerodynamics.torque: " << PrintVector<double>(drag_model_->y.begin() + 3, drag_model_->y.begin() + 6));
  checknan(drag_model_->y, "drag model output");

  // drag_model_ gives us inverted vectors!
  wrench_.force.x  = -( drag_model_->y[0]);
  wrench_.force.y  = -(-drag_model_->y[1]);
  wrench_.force.z  = -(-drag_model_->y[2]);
  wrench_.torque.x = -( drag_model_->y[3]);
  wrench_.torque.y = -(-drag_model_->y[4]);
  wrench_.torque.z = -(-drag_model_->y[5]);
}
Exemplo n.º 5
0
double PID::update(double error, double dx, const ros::Duration& dt)
{
    if (!parameters_.enabled) return 0.0;
    if (std::isnan(error)) return 0.0;
    double dt_sec = dt.toSec();

    // integral error
    state_.i += error * dt_sec;
    if (parameters_.limit_i > 0.0)
    {
        if (state_.i >  parameters_.limit_i) state_.i =  parameters_.limit_i;
        if (state_.i < -parameters_.limit_i) state_.i = -parameters_.limit_i;
    }

    // differential error
    if (dt_sec > 0.0 && !std::isnan(state_.p) && !std::isnan(state_.dx)) {
        state_.d = (error - state_.p) / dt_sec + state_.dx - dx;
    } else {
        state_.d = -dx;
    }
    state_.dx = dx;

    // proportional error
    state_.p = error;

    // calculate output...
    double output = parameters_.k_p * state_.p + parameters_.k_i * state_.i + parameters_.k_d * state_.d;
    int antiwindup = 0;
    if (parameters_.limit_output > 0.0)
    {
        if (output >  parameters_.limit_output) {
            output =  parameters_.limit_output;
            antiwindup =  1;
        }
        if (output < -parameters_.limit_output) {
            output = -parameters_.limit_output;
            antiwindup = -1;
        }
    }
    if (antiwindup && (error * dt_sec * antiwindup > 0.0)) state_.i -= error * dt_sec;

    checknan(output);
    return output;
}
////////////////////////////////////////////////////////////////////////////////
// Update the controller
void GazeboQuadrotorAerodynamics::Update()
{
  Vector3 force, torque;
  boost::mutex::scoped_lock lock(command_mutex_);

  // Get simulator time
  Time current_time = world->GetSimTime();
  double dt = (current_time - last_time_).Double();
  last_time_ = current_time;
  if (dt <= 0.0) return;

  // Get new commands/state
  // callback_queue_.callAvailable();

  while(1) {
    if (!new_motor_voltages_.empty()) {
      hector_uav_msgs::MotorPWMConstPtr new_motor_voltage = new_motor_voltages_.front();
      Time new_time = Time(new_motor_voltage->header.stamp.sec, new_motor_voltage->header.stamp.nsec);
      if (new_time == Time() || (new_time >= current_time - control_delay_ - control_tolerance_ && new_time <= current_time - control_delay_ + control_tolerance_)) {
        motor_voltage_ = new_motor_voltage;
        new_motor_voltages_.pop_front();
        last_control_time_ = current_time - control_delay_;
        ROS_DEBUG_STREAM("Using motor command valid at " << new_time << " for simulation step at " << current_time << " (dt = " << (current_time - new_time) << ")");
        break;
      } else if (new_time < current_time - control_delay_ - control_tolerance_) {
        ROS_DEBUG("[quadrotor_aerodynamics] command received was too old: %f s", (new_time  - current_time).Double());
        new_motor_voltages_.pop_front();
        continue;
      }
    }

    if (new_motor_voltages_.empty() && motor_status_.on &&  control_period_ > 0 && current_time > last_control_time_ + control_period_ + control_tolerance_) {
      ROS_WARN("[quadrotor_aerodynamics] waiting for command...");
      if (command_condition_.timed_wait(lock, (ros::Duration(control_period_.sec, control_period_.nsec) * 100.0).toBoost())) continue;
      ROS_ERROR("[quadrotor_aerodynamics] command timed out.");
      motor_status_.on = false;
    }

    break;
  }

  // fill input vector u for propulsion model
  velocity = model->GetRelativeLinearVel();
  rate = model->GetRelativeAngularVel();
  propulsion_model_->u[0] = velocity.x;
  propulsion_model_->u[1] = -velocity.y;
  propulsion_model_->u[2] = -velocity.z;
  propulsion_model_->u[3] = rate.x;
  propulsion_model_->u[4] = -rate.y;
  propulsion_model_->u[5] = -rate.z;
  if (motor_voltage_ && motor_voltage_->pwm.size() >= 4) {
    propulsion_model_->u[6] = motor_voltage_->pwm[0] * 14.8 / 255.0;
    propulsion_model_->u[7] = motor_voltage_->pwm[1] * 14.8 / 255.0;
    propulsion_model_->u[8] = motor_voltage_->pwm[2] * 14.8 / 255.0;
    propulsion_model_->u[9] = motor_voltage_->pwm[3] * 14.8 / 255.0;
  } else {
    propulsion_model_->u[6] = 0.0;
    propulsion_model_->u[7] = 0.0;
    propulsion_model_->u[8] = 0.0;
    propulsion_model_->u[9] = 0.0;
  }

//  std::cout << "u = [ ";
//  for(std::size_t i = 0; i < propulsion_model_->u.size(); ++i)
//    std::cout << propulsion_model_->u[i] << " ";
//  std::cout << "]" << std::endl;

  checknan(propulsion_model_->u, "propulsion model input");
  checknan(propulsion_model_->x, "propulsion model state");

  // update propulsion model
  quadrotorPropulsion(propulsion_model_->x.data(), propulsion_model_->u.data(), propulsion_model_->parameters_, dt, propulsion_model_->y.data(), propulsion_model_->x_pred.data());
  propulsion_model_->x = propulsion_model_->x_pred;
  force  = force  + checknan(Vector3(propulsion_model_->y[0], -propulsion_model_->y[1], propulsion_model_->y[2]), "propulsion model force");
  torque = torque + checknan(Vector3(propulsion_model_->y[3], -propulsion_model_->y[4], -propulsion_model_->y[5]), "propulsion model torque");

//  std::cout << "y = [ ";
//  for(std::size_t i = 0; i < propulsion_model_->y.size(); ++i)
//    std::cout << propulsion_model_->y[i] << " ";
//  std::cout << "]" << std::endl;

  // publish wrench
  if (wrench_publisher_) {
    wrench_.force.x = force.x;
    wrench_.force.y = force.y;
    wrench_.force.z = force.z;
    wrench_.torque.x = torque.x;
    wrench_.torque.y = torque.y;
    wrench_.torque.z = torque.z;
    wrench_publisher_.publish(wrench_);
  }

  // fill input vector u for drag model
  drag_model_->u[0] =  (velocity.x - wind_.x);
  drag_model_->u[1] = -(velocity.y - wind_.y);
  drag_model_->u[2] = -(velocity.z - wind_.z);
  drag_model_->u[3] =  rate.x;
  drag_model_->u[4] = -rate.y;
  drag_model_->u[5] = -rate.z;

//  std::cout << "u = [ ";
//  for(std::size_t i = 0; i < drag_model_->u.size(); ++i)
//    std::cout << drag_model_->u[i] << " ";
//  std::cout << "]" << std::endl;

  checknan(drag_model_->u, "drag model input");

  // update drag model
  quadrotorDrag(drag_model_->u.data(), drag_model_->parameters_, dt, drag_model_->y.data());
  force  = force  - checknan(Vector3(drag_model_->y[0], -drag_model_->y[1], -drag_model_->y[2]), "drag model force");
  torque = torque - checknan(Vector3(drag_model_->y[3], -drag_model_->y[4], -drag_model_->y[5]), "drag model torque");

  if (motor_status_publisher_ && current_time >= last_motor_status_time_ + control_period_) {
    motor_status_.header.stamp = ros::Time(current_time.sec, current_time.nsec);
    motor_status_.running = propulsion_model_->x[0] > 0.0 && propulsion_model_->x[1] > 0.0 && propulsion_model_->x[2] > 0.0 && propulsion_model_->x[3] > 0.0;
    motor_status_.frequency.resize(4);
    motor_status_.frequency[0] = propulsion_model_->x[0];
    motor_status_.frequency[1] = propulsion_model_->x[1];
    motor_status_.frequency[2] = propulsion_model_->x[2];
    motor_status_.frequency[3] = propulsion_model_->x[3];
    motor_status_publisher_.publish(motor_status_);
    last_motor_status_time_ = current_time;
  }

  // set force and torque in gazebo
  model->GetLink()->AddRelativeForce(force);
  model->GetLink()->AddRelativeTorque(torque);
}
Exemplo n.º 7
0
void plotylms()
{
  gStyle->SetOptStat(1000000001);
  TIter gdiriter(gDirectory->GetListOfKeys());
  TObject *cur;
  char *buf;
  char  suff[500];
  char  lbuf[500];
  char  nbuf[500];
  suff[0] = '\0';

  while (cur = gdiriter()) {
    buf = cur->GetName();
    if (strstr(buf, "CfnReYlm00")) {
      cout << "Found suffix " << buf+10 << endl;
      strcpy(suff, buf+10);
      break;
    }
  }

  if (!suff[0]) {
    cout << "Did not find suffix" << endl;
    return;
  }

  int maxl = 0;
  gdiriter->Reset();
  while (cur = gdiriter()) {
    buf = cur->GetName();
    if ((strstr(buf, "CfnReYlm")) && (strstr(buf, suff))){
      cout << "Found l " << buf+8 << endl;
      strncpy(lbuf, buf+8,1);
      lbuf[1] = '\0';
      int lcur = atoi(lbuf);
      cout << "Found l " << lcur << endl;
      if (lcur > maxl) maxl = lcur;
    }
  }
  cout << "Maximum l " << maxl << endl;
  

  int ilmcount= 0;
  TH1D **cfnsr;
  cfnsr = malloc(sizeof(TH1D *) * (maxl+1)*(maxl+1));
  TH1D **cfnsi;
  cfnsi = malloc(sizeof(TH1D *) * (maxl+1)*(maxl+1));
  for (int il=0; il<=maxl; il++)
    for (int im=0; im<=il; im++) {
      sprintf(nbuf, "CfnReYlm%i%i%s", il, im, suff);
      cfnsr[ilmcount] = new TH1D(*((TH1D *) gDirectory->Get(nbuf)));
      checknan(cfnsr[ilmcount]);

      sprintf(nbuf, "CfnImYlm%i%i%s", il, im, suff);
      cfnsi[ilmcount] = new TH1D(*((TH1D *) gDirectory->Get(nbuf)));
      checknan(cfnsi[ilmcount]);

      ilmcount++;
    }

  TLine *l1 = new TLine(0.0, 1.0, cfnsr[0]->GetXaxis()->GetXmax(), 1.0);
  l1->SetLineColor(14);
  l1->SetLineStyle(2);
  
  TLine *l0 = new TLine(0.0, 0.0, cfnsr[0]->GetXaxis()->GetXmax(), 0.0);
  l0->SetLineColor(14);
  l0->SetLineStyle(2);
  
  TCanvas *canylm = new TCanvas("canylm","canylm",1600,800);
  gPad->SetFillColor(0);
  gPad->SetFillStyle(4000);
  canylm->Divide(5, 2, 0.0001, 0.0001);
  for (int ilm=0; ilm<(maxl+1)*(maxl+2)/2; ilm++) {
    cout << "Drawing " << ilm << endl;

    canylm->cd(ilm+1);
    gPad->SetFillColor(0);
    gPad->SetFillStyle(4000);
    gPad->SetTopMargin(0.01);
    gPad->SetRightMargin(0.01);

    cfnsr[ilm]->SetTitle("");
    cfnsr[ilm]->SetMarkerColor(2);
    cfnsr[ilm]->SetMarkerSize(0.8);
    cfnsr[ilm]->SetMarkerStyle(8);
    cfnsr[ilm]->Draw();

    cout << "Drawn " << ilm << endl;
    
    cfnsi[ilm]->SetTitle("");
    cfnsi[ilm]->SetMarkerColor(4);
    cfnsi[ilm]->SetMarkerSize(0.8);
    cfnsi[ilm]->SetMarkerStyle(8);
    cfnsi[ilm]->Draw("SAME");
    
    cout << "Drawn " << ilm << endl;
    if (ilm)
      l0->Draw();
    else
      l1->Draw();

  }
  
  TLatex lat;
  lat.SetTextSize(0.12);

  TCanvas *canylms = new TCanvas("canylms","canylms",1100,900);
  gPad->SetFillColor(0);
  gPad->SetFillStyle(4000);
  canylms->Divide(1, 4, 0.0001, 0.0001);
  
  int el = 0;
  int em = 0;
  for (int ilm=0; ilm<(maxl+1)*(maxl+2)/2; ilm++) {
    TPad *curpad;
    
    canylms->cd(el+1);
    curpad = gPad;
    cout << "Drawing " << ilm << " " << el << " " << em << " " << curpad << endl;
    if (em == 0) {
      if (el==0)
	gPad->Divide(2,1,0.0001,0.0001);
      if (el == 1)
	gPad->Divide(2,1,0.0001,0.0001);
      if (el == 2)
	gPad->Divide(3,1,0.0001,0.0001);
      if (el == 3)
	gPad->Divide(4,1,0.0001,0.0001);

      if ((el==0) && (em==0)) {
	curpad->cd(2);
	lat.DrawLatex(0.2, 0.8, "C_{0}^{0}");
	lat.DrawLatex(0.2, 0.6, "C_{1}^{0}");
	lat.DrawLatex(0.5, 0.6, "C_{1}^{1}");
	lat.DrawLatex(0.2, 0.4, "C_{2}^{0}");
	lat.DrawLatex(0.4, 0.4, "C_{2}^{1}");
	lat.DrawLatex(0.6, 0.4, "C_{2}^{2}");
	lat.DrawLatex(0.2, 0.2, "C_{3}^{0}");
	lat.DrawLatex(0.35, 0.2, "C_{3}^{1}");
	lat.DrawLatex(0.5, 0.2, "C_{3}^{2}");
	lat.DrawLatex(0.65, 0.2, "C_{3}^{3}");
	lat.SetTextColor(2);
	lat.DrawLatex(0.35, 0.8, "real part");
	lat.SetTextColor(4);
	lat.DrawLatex(0.6, 0.8, "imaginary part");
      }
    }
    
    cout << "Drawing " << ilm << " " << curpad << endl;
    curpad->cd(em+1);
    

    //    canylms->cd(ilm+1);
    gPad->SetFillColor(0);
    gPad->SetFillStyle(4000);
    gPad->SetTopMargin(0.01);
    gPad->SetRightMargin(0.01);

    cfnsr[ilm]->SetTitle("");
    cfnsr[ilm]->SetMarkerColor(2);
    cfnsr[ilm]->SetMarkerSize(0.8);
    cfnsr[ilm]->SetMarkerStyle(8);
    cfnsr[ilm]->Draw();

    cout << "Drawn " << ilm << endl;
    
    cfnsi[ilm]->SetTitle("");
    cfnsi[ilm]->SetMarkerColor(4);
    cfnsi[ilm]->SetMarkerSize(0.8);
    cfnsi[ilm]->SetMarkerStyle(8);
    cfnsi[ilm]->Draw("SAME");
    
    cout << "Drawn " << ilm << endl;
    if (ilm)
      l0->Draw();
    else
      l1->Draw();

    em++;
    if (em>el) {
      el++;
      em = 0;
    }
  }
  
//   canylms->SaveAs("canylms.eps");
//   canylms->SaveAs("canylms.png");
}