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