test-ScorbotIK.C

00001 #include <Ice/Ice.h>
00002 #include "Ice/Scorbot.ice.H"
00003 #include "Image/Point2D.H"
00004 #include "Image/DrawOps.H"
00005 #include "Image/MathOps.H"
00006 #include "Image/ColorOps.H"
00007 #include <signal.h>
00008 #include "Component/ModelManager.H"
00009 #include "Raster/Raster.H"
00010 #include "Util/MathFunctions.H"
00011 #include "Util/Types.H"
00012 #include "Util/log.H"
00013 #include "Media/FrameSeries.H"
00014 #include "Transport/FrameInfo.H"
00015 #include "Raster/GenericFrame.H"
00016 #include "GUI/XWinManaged.H"
00017 #include "GUI/ImageDisplayStream.H"
00018 #include "GUI/PrefsWindow.H"
00019 #include "GUI/DebugWin.H"
00020 
00021 
00022 Robots::ScorbotIcePrx scorbot;
00023 
00024 // ######################################################################
00025 void cleanupAndExit()
00026 {
00027   std::cerr <<
00028     std::endl << "*** EXITING - STOPPING SCORBOT ***" << std::endl;
00029   scorbot->stopAllMotors();
00030   sleep(1);
00031   exit(0);
00032 }
00033 
00034 // ######################################################################
00035 void terminate(int s)
00036 {
00037   cleanupAndExit();
00038 }
00039 
00040 int getKey(nub::ref<OutputFrameSeries> &ofs)
00041 {
00042         const nub::soft_ref<ImageDisplayStream> ids =
00043                 ofs->findFrameDestType<ImageDisplayStream>();
00044 
00045         const rutz::shared_ptr<XWinManaged> uiwin =
00046                 ids.is_valid()
00047                 ? ids->getWindow("Output")
00048                 : rutz::shared_ptr<XWinManaged>();
00049         return uiwin->getLastKeyPress();
00050 }
00051 
00052 
00053 
00054 Point2D<double> getTargetPos()
00055 {
00056   double x, y;
00057 
00058   std::cout << "----------------------------------------" << std::endl;
00059   std::cout << "Enter a target point in mm: (x y): ";
00060   std::cin >> x >> y;
00061   return Point2D<double>(x,y);
00062 }
00063 
00064 // ######################################################################
00065 // Point the camera at a 2D position on the board at a given angle (camera to board angle, in radians), with the camera
00066 // 'camDist' mm away from the target, and the linear slide set xOffset mm to the side of the target.
00067 Robots::ArmPos calcArmPos(Point2D<double> targetPos, double xOffset, double angle, double camDist)
00068 {
00069   //////////////////////////////////////////////////////////////////////// 
00070   // CONSTANTS
00071   double armSlideXoffset = 0.0; // The x-offset from origin to the arm's home slide position
00072   double armSlideYoffset = 0.0; // The y-offset from the origin to the arm's slide traversal axis (this should be a neg. number)
00073   double armZoffset      = 0.0; // The distance from the arm's origin to the table surface
00074 
00075   //These offsets assume that when the wrist is pointed straight out, the x-axis points through the tip of the gripper,
00076   //and the y-axis points towards the ceiling. 
00077   double camToWristX     = 0.0; // The distance from the cam center to the wrist along the x-axis if the wrist is straight out
00078   double camToWristY     = 0.0; // The distance from the cam center to the wrist along the y-axis if the wrist is straight out
00079   //
00080   //////////////////////////////////////////////////////////////////////// 
00081 
00082   double targetX = targetPos.i;
00083   double targetY = targetPos.j;
00084 
00085   // Distance from the arm center to the target in the x-y (tabletop) plane
00086   double d_t = sqrt(pow(xOffset,2) + pow(targetY+armSlideYoffset,2));
00087 
00088   // Relative position of the camera center from the target
00089   double x_hat_cam = cos(angle)*camDist;
00090   double y_hat_cam = sin(angle)*camDist;
00091 
00092   // Position of the camera relative to the robot origin.
00093   // This position is in an artificial coord. system created by assuming the
00094   // arm is already at it's proper slide offset, and the base has been rotated
00095   // to the target
00096   double x_cam = d_t - x_hat_cam;
00097   double y_cam = y_hat_cam - armZoffset;
00098 
00099   // Rotate the camera-to-wrist offsets according to the desired angle
00100   double cam_x_off = camToWristX * cos(-angle) - camToWristY*sin(-angle);
00101   double cam_y_off = camToWristX * sin(-angle) + camToWristY*cos(-angle);
00102 
00103   // Absolute wrist position (in our artificial coord. system)
00104   double wrist_x = x_cam + cam_x_off;
00105   double wrist_y = y_cam + cam_y_off;
00106 
00107   // Absolute global slider position
00108   double sliderPos =  targetX + xOffset - armSlideXoffset;
00109 
00110   // Base angle
00111   double baseAngle = atan2(xOffset, targetY+armSlideYoffset);
00112 
00113   // Get the inverse kinematics from the scorbot
00114   Robots::ArmPos ik = scorbot->getIK(0, wrist_x, wrist_y); 
00115 
00116   // Force the slide position and base angle
00117   ik.ex1  = scorbot->mm2enc(sliderPos); 
00118   ik.base = scorbot->ang2enc(baseAngle);
00119 
00120   std::cout << "---IK---" << std::endl;
00121   std::cout << "base:     " << ik.base << std::endl;
00122   std::cout << "shoulder: " << ik.shoulder << std::endl;
00123   std::cout << "elbow:    " << ik.elbow << std::endl;
00124   std::cout << "wrist1:   " << ik.wrist1 << std::endl;
00125   std::cout << "wrist2:   " << ik.wrist2 << std::endl;
00126   std::cout << "ex1:      " << ik.ex1 << std::endl;
00127   std::cout << "--------" << std::endl;
00128 
00129   return ik;
00130 }
00131 
00132 
00133 
00134 std::vector<Robots::ArmPos> getArmPositions()
00135 {
00136 
00137         std::vector<Robots::ArmPos> positions;
00138         Robots::ArmPos armpos;
00139         armpos.base = 0;
00140         armpos.shoulder = 0;
00141         armpos.elbow = 0;
00142         armpos.wrist1 = 0;
00143         armpos.wrist2 = 0;
00144         armpos.ex1 = 0;
00145         armpos.ex2 = 0;
00146         armpos.duration = 500;
00147 
00148         armpos.base=-823; armpos.shoulder=1594; armpos.elbow=-26751; armpos.wrist1=224; armpos.wrist2=-125; armpos.gripper=0; armpos.ex1=49; 
00149         positions.push_back(armpos); 
00150         armpos.base=-707; armpos.shoulder=1292; armpos.elbow=-27673; armpos.wrist1=1143; armpos.wrist2=-918; armpos.gripper=0; armpos.ex1=49;
00151         positions.push_back(armpos); 
00152 
00153 
00154 
00155 /*
00156   //armpos.base=-4253; armpos.shoulder=-1204; armpos.elbow=413; armpos.wrist1=618; armpos.wrist2=-937; armpos.gripper=0; armpos.ex1=4915; 
00157   armpos.ex1=4915; 
00158         positions.push_back(armpos); 
00159   //armpos.base=590; armpos.shoulder=-1205; armpos.elbow=857; armpos.wrist1=615; armpos.wrist2=-795; armpos.gripper=0; armpos.ex1=95684; 
00160   armpos.ex1=95684; 
00161         positions.push_back(armpos); 
00162   //armpos.base=3140; armpos.shoulder=-1204; armpos.elbow=856; armpos.wrist1=615; armpos.wrist2=-795; armpos.gripper=0; armpos.ex1=141287;
00163   armpos.ex1=141287;
00164         positions.push_back(armpos); 
00165   //armpos.base=3322; armpos.shoulder=-9856; armpos.elbow=1556; armpos.wrist1=348; armpos.wrist2=-332; armpos.gripper=0; armpos.ex1=141271;
00166   armpos.ex1=141271;
00167         positions.push_back(armpos); 
00168   //armpos.base=-1418; armpos.shoulder=-8198; armpos.elbow=6136; armpos.wrist1=1152; armpos.wrist2=-1106; armpos.gripper=0; armpos.ex1=58362;
00169   armpos.ex1=58362;
00170         positions.push_back(armpos); 
00171   //armpos.base=-4147; armpos.shoulder=-11764; armpos.elbow=101; armpos.wrist1=489; armpos.wrist2=-584; armpos.gripper=0; armpos.ex1=4931; 
00172   armpos.ex1=4931; 
00173         positions.push_back(armpos); 
00174 */
00175 
00176   return positions;
00177 
00178 }
00179 
00180 void setWrist(Robots::ArmPos &armPos, float ang)
00181 {
00182    armPos.wrist1 = (ang*(2568.0*2.0)/M_PI);
00183    armPos.wrist2 = -1*ang*(2568.0*2.0)/M_PI;
00184 }
00185 
00186 // ######################################################################
00187 int main(int argc, char* argv[])
00188 {
00189         signal(SIGHUP, terminate); signal(SIGINT, terminate);
00190         signal(SIGQUIT, terminate); signal(SIGTERM, terminate);
00191         signal(SIGALRM, terminate);
00192 
00193 
00194         ModelManager manager("Test Model for Scorbot robot arm controller");
00195 
00196         nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00197         manager.addSubComponent(ofs);
00198 
00199   nub::ref<InputFrameSeries> ifs(new InputFrameSeries(manager));
00200   manager.addSubComponent(ifs);
00201 
00202 
00203         // Parse command-line:
00204         if (manager.parseCommandLine(argc, argv, "FileName", 0, 1) == false) return(1);
00205 
00206         std::string fileName = manager.getExtraArg(0);
00207 
00208         // let's get all our ModelComponent instances started:
00209         manager.start();
00210 
00211   ifs->startStream();
00212   while(1)
00213   {
00214           GenericFrame input = ifs->readFrame();
00215           if (!input.initialized())
00216                   break;
00217 
00218 
00219           Image<PixRGB<byte> > inImage = input.asRgb();
00220           Point2D<int> center(inImage.getWidth()/2, inImage.getHeight()/2);
00221           Dims winSize(512,512);
00222 
00223           Image<PixRGB<byte> > objImg = crop(inImage, Rectangle::centerDims(center, winSize));
00224           drawCircle(objImg, Point2D<int>(256,256), 3, PixRGB<byte>(255,0,0), 3);
00225 
00226           drawCircle(inImage, Point2D<int>(inImage.getWidth()/2,inImage.getHeight()/2), 3, PixRGB<byte>(255,0,0), 3);
00227 
00228           ofs->writeRGB(inImage, "Output", FrameInfo("output", SRC_POS));
00229 
00230   }
00231 
00232 /*
00233   try {
00234     ic = Ice::initialize(argc, argv);
00235     Ice::ObjectPrx base = ic->stringToProxy(
00236         "ScorbotServer:default -p 10000 -h ihead");
00237     scorbot = Robots::ScorbotIcePrx::checkedCast(base);
00238     if(!scorbot)
00239       throw "Invalid Proxy!";
00240 
00241 
00242                 std::vector<Robots::ArmPos> armPos =  getArmPositions();
00243                 Robots::ArmPos homePos = armPos[0];
00244     //homePos.base = 0; homePos.shoulder = 0; homePos.elbow = 0; homePos.wrist1 = 0; homePos.wrist2 = 0; homePos.ex1 = 0; homePos.ex2 = 0;
00245     //homePos.duration = 1000;
00246 
00247         
00248  
00249                 LINFO("Move robot %i %i", homePos.wrist1, homePos.wrist2);
00250                 //scorbot->setArmPos(homePos);
00251                 //getchar();
00252         
00253                 scorbot->setArmPos(armPos[0]);
00254                 sleep(2);
00255     LINFO("Done");
00256 
00257     uint currentArmPos = 0;
00258           bool motorsOn = false;
00259                 bool clearToShoot = false;
00260                 bool startSequance = false;
00261      
00262                 Image<PixRGB<byte> > lastInput;
00263 
00264     while(1)
00265                 {
00266                         const FrameState is = ifs->updateNext();
00267                         if (is == FRAME_COMPLETE)
00268                                 break;
00269 
00270                         GenericFrame input = ifs->readFrame();
00271                         if (!input.initialized())
00272                                 break;
00273 
00274 
00275                         Image<PixRGB<byte> > inImage = input.asRgb();
00276                         Point2D<int> center(inImage.getWidth()/2, inImage.getHeight()/2);
00277                         Dims winSize(512,512);
00278 
00279                         Image<PixRGB<byte> > objImg = crop(inImage, Rectangle::centerDims(center, winSize));
00280 
00281 
00282                         double imgSum = 1e10;
00283                         if (lastInput.initialized())
00284                         {
00285                                 Image<float> lum1 = luminance(objImg);
00286                                 Image<float> lum2 = luminance(lastInput);
00287                                 Image<float> diffImg = lum1 - lum2;
00288                                 imgSum = sum(diffImg);
00289                         }
00290                         if (!(ifs->frame()%10))
00291                         {
00292                                 lastInput = objImg;
00293                                 double diff = fabs(imgSum)/(512*512); 
00294 
00295                                 int time = scorbot->getMovementTime(); 
00296                                 //LINFO("Going to pos %i at %i/%i", currentArmPos, time, armPos[currentArmPos].duration);
00297 
00298                                 if (diff < 0.5 && time >= armPos[currentArmPos].duration)
00299                                         clearToShoot = true;
00300                         }               
00301 
00302                         
00303 
00304                         drawRect(inImage, Rectangle::centerDims(center, winSize), PixRGB<byte>(0,255,0));
00305                         drawCircle(inImage, center, 3, PixRGB<byte>(254,0,0), 3);
00306 
00307 
00308 
00309 
00310                         if (startSequance)
00311                         {
00312                                 if (clearToShoot)
00313                                 {
00314                                         char file[255];
00315                                         sprintf(file, "%s/pos%i.ppm", fileName.c_str(), currentArmPos); //This is the previus position
00316                                         //LINFO("Capture image to %s", file);
00317                                         sleep(2);
00318                                         //Raster::WriteRGB(objImg, file);
00319                                         //SHOWIMG(objImg);
00320                                 
00321                                         clearToShoot = false;
00322 
00323                                         Robots::ArmPos curArmPos = scorbot->getArmPos();
00324                                         Robots::ArmPos desArmPos = armPos[currentArmPos];
00325                                         LINFO ("armpos.base=%i/%i; armpos.shoulder=%i/%i; armpos.elbow=%i/%i; armpos.wrist1=%i/%i; armpos.wrist2=%i/%i;",
00326                                                 curArmPos.base, desArmPos.base,
00327                                                 curArmPos.shoulder, desArmPos.shoulder,
00328                                                 curArmPos.elbow, desArmPos.elbow,
00329                                                 curArmPos.wrist1, desArmPos.wrist1,
00330                                                 curArmPos.wrist2, desArmPos.wrist2);
00331 
00332                                         scorbot->setArmPos(armPos[currentArmPos]);
00333                                         currentArmPos++;
00334                                         if (currentArmPos > armPos.size())
00335                                         {
00336                                                 currentArmPos = 0;
00337                                                 startSequance = true;
00338                                                 scorbot->setArmPos(armPos[currentArmPos]);
00339                                         }
00340                                 }
00341 
00342                         }
00343 
00344 
00345                         drawCircle(objImg, Point2D<int>(256,256), 3, PixRGB<byte>(255,0,0), 3);
00346                         ofs->writeRGB(objImg, "Output", FrameInfo("output", SRC_POS));
00347 
00348 
00349                         int key = getKey(ofs);
00350 
00351                         if (key != -1)
00352                         {
00353                                 LINFO("Key %i", key);
00354                                 switch(key)
00355                                 {
00356                                                 case 36: //enter
00357                                                         startSequance = true;
00358                                                         break;
00359                                                 case 43: //h home
00360                                                         LINFO("Going home\n");
00361                                                         scorbot->setArmPos(homePos);
00362                                                         break;
00363                                                 case 33: //p getPositions
00364                                                         {
00365                                                                 Robots::ArmPos armpos = scorbot->getArmPos();
00366                                                                 LINFO ("armpos.base=%i; armpos.shoulder=%i; armpos.elbow=%i; armpos.wrist1=%i; armpos.wrist2=%i; armpos.gripper=%i; armpos.ex1=%i; armpos.ex2=%i;",
00367                                                                 armpos.base, armpos.shoulder, armpos.elbow , armpos.wrist1, armpos.wrist2, armpos.gripper, armpos.ex1, armpos.ex2);
00368                                                         }
00369                                                         break;
00370                                                 case 58: //m
00371                                                         motorsOn = !motorsOn;
00372                                                         if (motorsOn)
00373                                                                 scorbot->motorsOn();
00374                                                         else
00375                                                                 scorbot->motorsOff();
00376                                                         break;
00377                                 }
00378                         }
00379 
00380                 }
00381     //mainLoop();
00382 
00383   } catch(const Ice::Exception& ex) {
00384     std::cerr << ex << std::endl;
00385     status = 1;
00386   } catch(const char* msg) {
00387     std::cerr << msg << std::endl;
00388     status = 1;
00389   }
00390 
00391   if(ic)
00392     ic->destroy();
00393 
00394   cleanupAndExit();
00395   return status;
00396 */
00397 return 0;
00398 }
Generated on Sun May 8 08:40:07 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3