train-arm.C

Go to the documentation of this file.
00001 /*! @file ArmControl/train-arm.C  train the arm */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ArmControl/train-arm.C $
00035 // $Id: train-arm.C 10794 2009-02-08 06:21:09Z itti $
00036 //
00037 
00038 
00039 #include "Component/ModelManager.H"
00040 #include "Image/Image.H"
00041 #include "Image/Transforms.H"
00042 #include "Image/DrawOps.H"
00043 #include "Image/Rectangle.H"
00044 #include "Image/MathOps.H"
00045 #include "Image/MatrixOps.H"
00046 #include "Image/Layout.H"
00047 #include "Media/FrameSeries.H"
00048 #include "Transport/FrameInfo.H"
00049 #include "Raster/GenericFrame.H"
00050 #include "Raster/Raster.H"
00051 #include "Neuro/BeoHeadBrain.H"
00052 #include "Util/Timer.H"
00053 #include "GUI/GeneralGUI.H"
00054 #include "GUI/ImageDisplayStream.H"
00055 #include "GUI/DebugWin.H"
00056 #include "GUI/XWinManaged.H"
00057 #include "RCBot/Motion/MotionEnergy.H"
00058 #include "ArmControl/ArmSim.H"
00059 #include "ArmControl/RobotArm.H"
00060 #include "ArmControl/ArmController.H"
00061 #include "Devices/DeviceOpts.H"
00062 #include "Util/MathFunctions.H"
00063 #include <unistd.h>
00064 #include <stdio.h>
00065 #include <signal.h>
00066 
00067 #define USE_EXPAT
00068 #include <lwpr/lwpr.h>
00069 #include <lwpr/lwpr_xml.h>
00070 
00071 
00072 ModelManager *mgr;
00073 nub::soft_ref<ArmSim> armSim;
00074 nub::soft_ref<ArmController> armControllerArmSim;
00075 
00076 //generate a random target location
00077 void getTargetPos(double* desiredPos)
00078 {
00079   desiredPos[0] = -1.214/2+0.145 + randomDouble()*0.20;
00080   desiredPos[1] = -0.75/2+0.12 + randomDouble()*0.20;
00081   desiredPos[2] = 0.05; //0.60207 + randomDouble()*0.10;
00082 
00083   LDEBUG("New target: %0.2f %0.2f %0.2f",
00084       desiredPos[0],
00085       desiredPos[1],
00086       desiredPos[2]);
00087 
00088 }
00089 
00090 //Predict the joint angle required for this position
00091 ArmController::JointPos getIK(LWPR_Model& ik_model, const double* desiredPos)
00092 {
00093   double joints[5];
00094   lwpr_predict(&ik_model, desiredPos, 0.001, joints, NULL, NULL);
00095 
00096   ArmController::JointPos jointPos;
00097 
00098   jointPos.base = (int)joints[0];
00099   jointPos.sholder = (int)joints[1];
00100   jointPos.elbow = (int)joints[2];
00101   jointPos.wrist1 = (int)joints[3];
00102   jointPos.wrist2 = (int)joints[4];
00103   jointPos.gripper = 0;
00104 
00105   LDEBUG("Mapping %0.2f %0.2f %0.2f => %i %i %i %i %i",
00106       desiredPos[0], desiredPos[1], desiredPos[2],
00107       jointPos.base, jointPos.sholder, jointPos.elbow,
00108       jointPos.wrist1, jointPos.wrist2);
00109   return jointPos;
00110 }
00111 
00112 double getDistance(const double* pos, const double* desiredPos)
00113 {
00114   double sum=0;
00115   for(int i=0; i<3; i++)
00116     sum += (pos[i]-desiredPos[i])*(pos[i]-desiredPos[i]);
00117   return sqrt(sum);
00118 
00119 }
00120 
00121 
00122 void trainArm(LWPR_Model& ik_model, const double* armPos, const ArmController::JointPos& jointPos)
00123 {
00124 
00125   double joints[5];
00126   double pJoints[5];
00127   LDEBUG("Training => %0.2f,%0.2f,%0.2f => %i %i %i %i %i",
00128       armPos[0], armPos[1], armPos[2],
00129       jointPos.base, jointPos.sholder, jointPos.elbow,
00130       jointPos.wrist1, jointPos.wrist2);
00131 
00132   joints[0] = jointPos.base;
00133   joints[1] = jointPos.sholder;
00134   joints[2] = jointPos.elbow;
00135   joints[3] = jointPos.wrist1;
00136   joints[4] = jointPos.wrist2;
00137 
00138   lwpr_update(&ik_model, armPos, joints, pJoints, NULL);
00139 
00140 }
00141 
00142 ArmController::JointPos calcGradient(const double* desiredPos)
00143 {
00144 
00145   ArmController::JointPos jointPos = armControllerArmSim->getJointPos();
00146   ArmController::JointPos tmpJointPos = jointPos;
00147 
00148   double dist1, dist2;
00149   double baseGrad, sholderGrad, elbowGrad;
00150   double err = getDistance(armSim->getEndPos(), desiredPos);
00151 
00152   //get the base gradient
00153   tmpJointPos.base = jointPos.base + 100;
00154   armControllerArmSim->setJointPos(tmpJointPos);
00155   dist1 = getDistance(armSim->getEndPos(), desiredPos);
00156 
00157   tmpJointPos.base = jointPos.base - 100;
00158   armControllerArmSim->setJointPos(tmpJointPos);
00159   dist2 = getDistance(armSim->getEndPos(), desiredPos);
00160   baseGrad = dist1 - dist2;
00161   tmpJointPos.base = jointPos.base;
00162 
00163   //get the base gradient
00164   tmpJointPos.sholder = jointPos.sholder + 100;
00165   armControllerArmSim->setJointPos(tmpJointPos);
00166   dist1 = getDistance(armSim->getEndPos(), desiredPos);
00167   tmpJointPos.sholder = jointPos.sholder - 100;
00168   armControllerArmSim->setJointPos(tmpJointPos);
00169   dist2 = getDistance(armSim->getEndPos(), desiredPos);
00170   sholderGrad = dist1 - dist2;
00171   tmpJointPos.sholder = jointPos.sholder;
00172 
00173   //get the elbow gradient
00174   tmpJointPos.elbow = jointPos.elbow + 100;
00175   armControllerArmSim->setJointPos(tmpJointPos);
00176   dist1 = getDistance(armSim->getEndPos(), desiredPos);
00177   tmpJointPos.elbow = jointPos.elbow - 100;
00178   armControllerArmSim->setJointPos(tmpJointPos);
00179   dist2 = getDistance(armSim->getEndPos(), desiredPos);
00180   elbowGrad = dist1 - dist2;
00181   tmpJointPos.elbow = jointPos.elbow;
00182 
00183   int moveThresh = (int)(err*100000);
00184   jointPos.base -= (int)(randomUpToIncluding(moveThresh)*baseGrad);
00185   jointPos.sholder -= (int)(randomUpToIncluding(moveThresh)*sholderGrad);
00186   jointPos.elbow -= (int)(randomUpToIncluding(moveThresh)*elbowGrad);
00187 
00188   return jointPos;
00189 }
00190 
00191 
00192 //! Signal handler (e.g., for control-C)
00193 void terminate(int s)
00194 {
00195         LERROR("*** INTERRUPT ***");
00196         exit(0);
00197 }
00198 
00199 Point2D<int> getClick(nub::soft_ref<OutputFrameSeries> &ofs)
00200 {
00201   const nub::soft_ref<ImageDisplayStream> ids =
00202     ofs->findFrameDestType<ImageDisplayStream>();
00203 
00204   const rutz::shared_ptr<XWinManaged> uiwin =
00205     ids.is_valid()
00206     ? ids->getWindow("Output")
00207     : rutz::shared_ptr<XWinManaged>();
00208   return uiwin->getLastMouseClick();
00209 }
00210 
00211 
00212 int getKey(nub::soft_ref<OutputFrameSeries> &ofs)
00213 {
00214   const nub::soft_ref<ImageDisplayStream> ids =
00215     ofs->findFrameDestType<ImageDisplayStream>();
00216 
00217   const rutz::shared_ptr<XWinManaged> uiwin =
00218     ids.is_valid()
00219     ? ids->getWindow("Output")
00220     : rutz::shared_ptr<XWinManaged>();
00221   return uiwin->getLastKeyPress();
00222 }
00223 
00224 int main(const int argc, const char **argv)
00225 {
00226   MYLOGVERB = LOG_INFO;
00227   LWPR_Model ik_model;
00228 
00229   initRandomNumbers();
00230   mgr = new ModelManager("Test ObjRec");
00231   armSim = nub::soft_ref<ArmSim>(new ArmSim(*mgr));
00232   armControllerArmSim = nub::soft_ref<ArmController>(new ArmController(*mgr,
00233         "ArmControllerArmSim", "ArmControllerArmSim", armSim));
00234   mgr->addSubComponent(armControllerArmSim);
00235 
00236   nub::soft_ref<OutputFrameSeries> ofs(new OutputFrameSeries(*mgr));
00237   mgr->addSubComponent(ofs);
00238 
00239   nub::soft_ref<GeneralGUI> armSimGUI(new GeneralGUI(*mgr));
00240   mgr->addSubComponent(armSimGUI);
00241 
00242   mgr->exportOptions(MC_RECURSE);
00243 
00244   if (mgr->parseCommandLine(
00245         (const int)argc, (const char**)argv, "", 0, 0) == false)
00246     return 1;
00247   // catch signals and redirect them to terminate for clean exit:
00248   signal(SIGHUP, terminate); signal(SIGINT, terminate);
00249   signal(SIGQUIT, terminate); signal(SIGTERM, terminate);
00250   signal(SIGALRM, terminate);
00251 
00252 
00253   ////INit the lwpr model
00254   //lwpr_init_model(&ik_model,3,5,"Arm_IK");
00255 
00256   ///* Set initial distance metric to 50*(identity matrix) */
00257   //lwpr_set_init_D_spherical(&ik_model,50);
00258 
00259   ///* Set init_alpha to 250 in all elements */
00260   //lwpr_set_init_alpha(&ik_model,250);
00261 
00262   ///* Set w_gen to 0.2 */
00263   //ik_model.w_gen = 0.2;
00264 
00265   int numWarnings = 0;
00266   lwpr_read_xml(&ik_model, "ik_model.xml", &numWarnings);
00267 
00268   mgr->start();
00269 
00270   initRandomNumbers();
00271 
00272   armControllerArmSim->setMotorsOn(true);
00273   armControllerArmSim->setPidOn(true);
00274 
00275   //set The min-max joint pos
00276   ArmController::JointPos jointPos;
00277   jointPos.base = 3000;
00278   jointPos.sholder = 3000;
00279   jointPos.elbow = 2000;
00280   jointPos.wrist1 = 0;
00281   jointPos.wrist2 = 0;
00282   armControllerArmSim->setMaxJointPos(jointPos);
00283 
00284   jointPos.base = -8000;
00285   jointPos.sholder = -1500;
00286   jointPos.elbow = -3000;
00287   jointPos.wrist1 = 0;
00288   jointPos.wrist2 = 0;
00289   armControllerArmSim->setMinJointPos(jointPos);
00290 
00291 
00292   //Move the arm to 0 pos
00293   jointPos.base = 0;
00294   jointPos.sholder = 0;
00295   jointPos.elbow = 0;
00296   jointPos.wrist1 = 0;
00297   jointPos.wrist2 = 0;
00298   jointPos.gripper = 0;
00299   armControllerArmSim->setJointPos(jointPos);
00300 
00301   bool reachComplete = true;
00302   int numReaches = 0;
00303   int numTries = 0;
00304   double desiredPos[3] = {0,0,0.4};
00305   while(1)
00306   {
00307     armSim->simLoop();
00308     Image<PixRGB<byte> > armCam = flipVertic(armSim->getFrame(-1));
00309 
00310     ofs->writeRGB(armCam, "Output", FrameInfo("Output", SRC_POS));
00311 
00312     //generate a random target location
00313     //if (reachComplete || numTries > 500)
00314     {
00315       Point2D<int> clickLoc = getClick(ofs);
00316       if (clickLoc.isValid())
00317       {
00318         //getTargetPos(desiredPos);
00319         armSim->getObjLoc(clickLoc.i, clickLoc.j, desiredPos);
00320         reachComplete = false;
00321         numTries = 0;
00322 
00323         //Predict the joint angle required for this position
00324         ArmController::JointPos jointPos = getIK(ik_model, desiredPos);
00325 
00326         //move the arm
00327         armControllerArmSim->setJointPos(jointPos);
00328       }
00329     }
00330 
00331     numTries++;
00332 
00333     //get the arm end effector position
00334     double *armPos = armSim->getEndPos();
00335     LDEBUG("Pos %f %f %f", armPos[0], armPos[1], armPos[2]);
00336 
00337     //compute the error
00338     double err = getDistance(armPos, desiredPos);
00339     if (!reachComplete)
00340       LINFO("Err %f tries %i: reaches=%i", err, numTries, numReaches);
00341 
00342     if (err > 0.01)
00343     {
00344       //Learn by following the gradient
00345       jointPos = calcGradient(desiredPos);
00346 
00347       armControllerArmSim->setJointPos(jointPos);
00348 
00349       jointPos =  armControllerArmSim->getJointPos();
00350       armPos = armSim->getEndPos();
00351 
00352       trainArm(ik_model, armPos, jointPos);
00353     } else {
00354       reachComplete = true;
00355       numReaches++;
00356       //write the network to a file
00357       //lwpr_write_xml(&ik_model, "ik_model.xml");
00358     }
00359 
00360   }
00361   mgr->stop();
00362 
00363   return 0;
00364 
00365 }
00366 
Generated on Sun May 8 08:40:11 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3