tutorials/tut04_inertia_coriolis.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 The Board of Trustees of The Leland Stanford Junior University. All rights reserved.
00003  *
00004  * Author: Roland Philippsen
00005  *         http://cs.stanford.edu/group/manips/
00006  *
00007  * This program is free software: you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation, either version 3 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this program.  If not, see
00019  * <http://www.gnu.org/licenses/>
00020  */
00021 
00039 #include "tutsim.hpp"
00040 #include <opspace/Task.hpp>
00041 #include <jspace/test/sai_util.hpp>
00042 #include <boost/shared_ptr.hpp>
00043 #include <err.h>
00044 
00045 
00046 namespace tut04 {
00047   
00048   class JTask : public opspace::Task {
00049   public:
00050     JTask()
00051       : opspace::Task("tut04::JTask"),
00052   initialized_(false),
00053   inertia_compensation_(true),
00054   coriolis_compensation_(true)
00055     {
00056     }
00057     
00058     virtual jspace::Status init(jspace::Model const & model)
00059     {
00061       // The Jacobian is not really required for pure jspace control,
00062       // but will become very important for operational-space control.
00063       
00064       jacobian_ = jspace::Matrix::Identity(model.getNDOF(), model.getNDOF());
00065       
00067       // Initialize our PD parameters.
00068       
00069       kp_ = 100.0;
00070       kd_ = 20.0;
00071       
00073       // Initialize our goal to the current state.
00074       
00075       goalpos_ = model.getState().position_;
00076       goalvel_ = model.getState().velocity_;
00077       
00079       // No initialization problems to report: the default constructor
00080       // of jspace::Status yields an instance that signifies success.
00081       
00082       initialized_ = true;
00083       jspace::Status ok;
00084       return ok;
00085     }
00086     
00087     
00088     virtual jspace::Status update(jspace::Model const & model)
00089     {
00091       // Lazy init...
00092       
00093       if ( ! initialized_ ) {
00094   init(model);
00095       }
00096       
00098       // Update the state of our task. Again, this is not critical
00099       // here, but important later when we want to integrate several
00100       // operational space tasks into a hierarchy.
00101       
00102       actual_ = model.getState().position_;
00103       
00105       // Compute PD control torques and store them in command_ for
00106       // later retrieval. Add feed-forward inertia decoupling terms as
00107       // requested by compensation_mode_. Gravity compensation is
00108       // always on.
00109       
00110       jspace::Vector gamma;
00111       gamma = kp_ * (goalpos_ - actual_) + kd_ * (goalvel_ - model.getState().velocity_);
00112       
00113       if (inertia_compensation_) {
00114   jspace::Matrix aa;
00115   if ( ! model.getMassInertia(aa)) {
00116     return jspace::Status(false, "failed to retrieve inertia");
00117   }
00118   command_ = aa * gamma;
00119       }
00120       else {
00121   command_ = gamma;
00122       }
00123       
00124       if (coriolis_compensation_) {
00125   jspace::Vector cc;
00126   if ( ! model.getCoriolisCentrifugal(cc)) {
00127     return jspace::Status(false, "failed to retrieve coriolis");
00128   }
00129   command_ += cc;
00130       }
00131       
00132       jspace::Vector gg;
00133       if ( ! model.getGravity(gg)) {
00134   return jspace::Status(false, "failed to retrieve gravity torque");
00135       }
00136       command_ += gg;
00137       
00138       jspace::Status ok;
00139       return ok;
00140     }
00141 
00142     bool initialized_;    
00143     bool inertia_compensation_;
00144     bool coriolis_compensation_;
00145     double kp_, kd_;
00146     jspace::Vector goalpos_, goalvel_;
00147   };
00148   
00149 }
00150 
00151 
00152 static std::string model_filename(TUTROB_XML_PATH_STR);
00153 static boost::shared_ptr<jspace::Model> model;
00154 static boost::shared_ptr<tut04::JTask> jtask;
00155 
00156 
00157 static bool servo_cb(size_t toggle_count,
00158          double wall_time_ms,
00159          double sim_time_ms,
00160          jspace::State & state,
00161          jspace::Vector & command)
00162 {
00164   // Update the model to reflect the current robot state.
00165   
00166   model->update(state);
00167 
00169   // Compute goal position and velocity to follow a sinusoidal joint
00170   // space motion.
00171   
00172   jtask->goalpos_.resize(state.position_.rows());
00173   jtask->goalvel_.resize(state.position_.rows());
00174   for (int ii(0); ii < state.position_.rows(); ++ii) {
00175     static double const amplitude(0.9 * M_PI);
00176     double const omega(0.5 + 0.3 * ii);
00177     double const phase(omega * 1e-3 * wall_time_ms);
00178     jtask->goalpos_[ii] =         amplitude * sin(phase);
00179     jtask->goalvel_[ii] = omega * amplitude * cos(phase);
00180   }
00181   
00183   // Cycle through inertia/coriolis compensation modes.
00184   
00185   switch (toggle_count % 3) {
00186   case 0:
00187     jtask->inertia_compensation_ = false;
00188     jtask->coriolis_compensation_ = false;
00189     break;
00190   case 1:
00191     jtask->inertia_compensation_ = true;
00192     jtask->coriolis_compensation_ = false;
00193     break;
00194   case 2:
00195   default:
00196     jtask->inertia_compensation_ = true;
00197     jtask->coriolis_compensation_ = true;
00198   }
00199   
00201   // Compute the command using jtask... as usual.
00202   
00203   jtask->update(*model);
00204   command = jtask->getCommand();
00205   
00207   // Print debug info from time to time.
00208   
00209   static size_t iteration(0);
00210   if (0 == (iteration % 100)) {
00211     if (jtask->inertia_compensation_) {
00212       std::cerr << "inertia compensation is ON\n";
00213     }
00214     else {
00215       std::cerr << "inertia compensation is off\n";
00216     }
00217     if (jtask->coriolis_compensation_) {
00218       std::cerr << "coriolis compensation is ON\n";
00219       jspace::Vector cc;
00220       model->getCoriolisCentrifugal(cc);
00221       jspace::pretty_print(cc, std::cerr, "  Coriolis/centrifugal torques", "    ");
00222     }
00223     else {
00224       std::cerr << "coriolis compensation is off\n";
00225     }
00226     jspace::pretty_print(jtask->goalpos_, std::cerr, "  goalpos", "    ");
00227     jspace::pretty_print(state.position_, std::cerr, "  jpos", "    ");
00228     jspace::pretty_print(jtask->goalvel_, std::cerr, "  goalvel", "    ");
00229     jspace::pretty_print(state.velocity_, std::cerr, "  jvel", "    ");
00230     jspace::pretty_print(command, std::cerr, "  command", "    ");
00231   }
00232   ++iteration;
00233   
00234   return true;
00235 }
00236 
00237 
00238 static void draw_cb(double x0, double y0, double scale)
00239 {
00240   if (0 != jtask->goalpos_.rows()) {
00241     tutsim::draw_robot(jtask->goalpos_, 1, 100, 255, 100, x0, y0, scale);
00242   }
00243 }
00244 
00245 
00246 int main(int argc, char ** argv)
00247 {
00248   try {
00249     model.reset(jspace::test::parse_sai_xml_file(model_filename, true));
00250     jtask.reset(new tut04::JTask());
00251   }
00252   catch (std::runtime_error const & ee) {
00253     errx(EXIT_FAILURE, "%s", ee.what());
00254   }
00255   tutsim::set_draw_cb(draw_cb);
00256   return tutsim::run(servo_cb);
00257 }

Generated on Fri Aug 26 01:31:18 2011 for Stanford Whole-Body Control Framework by  doxygen 1.5.4