test-heli.C

Go to the documentation of this file.
00001 /*!@file Robots/HeliBot/test-heli.C Test the heli */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // 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/Robots/HeliBot/test-heli.C $
00035 // $Id: test-heli.C 13901 2010-09-09 15:12:26Z lior $
00036 //
00037 
00038 #include "Robots/HeliBot/HeliPose.H"
00039 #include "Component/ModelManager.H"
00040 #include "Image/Image.H"
00041 #include "Image/DrawOps.H"
00042 #include "Image/ColorOps.H"
00043 #include "Image/FilterOps.H"
00044 #include "GUI/ImageDisplayStream.H"
00045 #include "GUI/XWinManaged.H"
00046 #include "Devices/Serial.H"
00047 #include "Devices/WiiMote.H"
00048 #include "Util/CpuTimer.H"
00049 #include "Util/Timer.H"
00050 #include "Image/MathOps.H"
00051 #include "Image/Transforms.H"
00052 #include "Image/Layout.H"
00053 #include "Media/FrameSeries.H"
00054 #include "Transport/FrameInfo.H"
00055 #include "Raster/GenericFrame.H"
00056 #include "Raster/Raster.H"
00057 #include "GUI/XWinManaged.H"
00058 #include "GUI/DebugWin.H"
00059 #include "Controllers/PID.H"
00060 #include "Devices/IMU_SFE_Atomic.H"
00061 
00062 #include <pthread.h>
00063 
00064 #define KEY_UP 98
00065 #define KEY_DOWN 104
00066 #define KEY_LEFT 100
00067 #define KEY_RIGHT 102
00068 
00069 int getKey(nub::ref<OutputFrameSeries> &ofs)
00070 {
00071   const nub::soft_ref<ImageDisplayStream> ids =
00072     ofs->findFrameDestType<ImageDisplayStream>();
00073 
00074   const rutz::shared_ptr<XWinManaged> uiwin =
00075     ids.is_valid()
00076     ? ids->getWindow("Output")
00077     : rutz::shared_ptr<XWinManaged>();
00078   return uiwin->getLastKeyPress();
00079 }
00080 
00081 Point2D<int> getMouseClick(nub::ref<OutputFrameSeries> &ofs, const char* wname)
00082 {
00083   const nub::soft_ref<ImageDisplayStream> ids =
00084     ofs->findFrameDestType<ImageDisplayStream>();
00085 
00086   const rutz::shared_ptr<XWinManaged> uiwin =
00087     ids.is_valid()
00088     ? ids->getWindow(wname)
00089     : rutz::shared_ptr<XWinManaged>();
00090 
00091   if (uiwin.is_valid())
00092     return uiwin->getLastMouseClick();
00093   else
00094     return Point2D<int>(-1,-1);
00095 }
00096 
00097 struct RadioStatus
00098 {
00099   int thr;
00100   int elevator;
00101   int aileron;
00102   int yaw;
00103 
00104   bool pushButton;
00105   bool rightSwitch;
00106   bool leftSwitch;
00107 };
00108 
00109 
00110 void drawWorld(float x, float y, float z, float rot, nub::ref<OutputFrameSeries>& ofs)
00111 {
00112 
00113   Image<PixRGB<byte> > world(255, 255, ZEROS);
00114   Point2D<int> loc(128+(int)(x/4.0), 128+(int)(y/4.0));
00115 
00116   float heliLength = 30;
00117   int headX = int(cos(rot)*heliLength/2);
00118   int headY = int(sin(rot)*heliLength/2);
00119 
00120   drawCircle(world, Point2D<int>(loc.i + headX, loc.j - headY), 6, PixRGB<byte>(0,255,0), 3);
00121   drawLine(world, loc, rot, heliLength, PixRGB<byte>(0,255,0), 3);
00122 
00123   ofs->writeRGB(world, "world", FrameInfo("world", SRC_POS));
00124 }
00125 
00126 RadioStatus getRadioStatus(nub::ref<Serial>& serial)
00127 {
00128   RadioStatus radioStatus;
00129 
00130   std::vector<unsigned char> data = serial->readFrame(0, 255); //start frame 0 end frame 255
00131 
00132   if(data.size() == 9)
00133   {
00134 
00135     radioStatus.thr        = (data[0]) | (data[1] << 8);
00136     radioStatus.elevator   = (data[2]) | (data[3] << 8);
00137     radioStatus.aileron    = (data[4]) | (data[5] << 8);
00138     radioStatus.yaw        = (data[6]) | (data[7] << 8);
00139     unsigned char switches = data[8];
00140 
00141     radioStatus.pushButton = switches & 0x04;
00142     radioStatus.rightSwitch = switches & 0x08;
00143     radioStatus.leftSwitch = switches & 0x10;
00144   } else {
00145     LERROR("BAD RADIO FRAME SIZE!");
00146     radioStatus.thr = -1;
00147     radioStatus.elevator = -1;
00148     radioStatus.aileron = -1;
00149     radioStatus.yaw = -1;
00150   }
00151 
00152 
00153   return radioStatus;
00154 
00155 }
00156 
00157 void sendRadioStatus(const RadioStatus& radioStatus, nub::ref<Serial>& serial)
00158 {
00159   unsigned char data[10];
00160 
00161   data[0] = 255;
00162   data[1] = 255;
00163 
00164   data[2] = (radioStatus.thr >> 8);
00165   data[3] = radioStatus.thr;
00166 
00167   data[4] = (radioStatus.elevator >> 8);
00168   data[5] = radioStatus.elevator;
00169 
00170   data[6] = (radioStatus.aileron >> 8);
00171   data[7] = radioStatus.aileron;
00172 
00173   data[8] = (radioStatus.yaw >> 8);
00174   data[9] = radioStatus.yaw;
00175 
00176   serial->write(data, 10);
00177 }
00178 
00179 void tunePID(const RadioStatus& radioStatus, PID<float>& pid)
00180 {
00181     ///Set the pid gains according to the switches
00182     if (!radioStatus.pushButton)
00183     {
00184       if (radioStatus.leftSwitch)
00185         pid.setPIDPgain(pid.getPIDPgain() + 0.0001);
00186       else
00187       {
00188         float gain = pid.getPIDPgain() - 0.0001;
00189         if (gain > 0)
00190           pid.setPIDPgain(gain);
00191       }
00192       LINFO("PID p gain %f", pid.getPIDPgain());
00193     }
00194 }
00195 
00196 int main(int argc, const char **argv)
00197 {
00198   // Instantiate a ModelManager:
00199   ModelManager manager("Test wiimote");
00200 
00201   nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00202   manager.addSubComponent(ofs);
00203 
00204   nub::ref<Serial> serial(new Serial(manager));
00205   manager.addSubComponent(serial);
00206 
00207   nub::ref<InputFrameSeries> ifs(new InputFrameSeries(manager));
00208   //manager.addSubComponent(ifs);
00209 
00210   nub::ref<HeliPose> heliPose(new HeliPose(manager, ifs, ofs));
00211   manager.addSubComponent(heliPose);
00212 
00213   PID<float> yawPid(0.0010, 0.01, 0.0, -1, 1, 0, 0, 0, 1.0, -1.0);
00214   PID<float> posXPid(0.0010, 0.0, 0.0, -1, 1, 0, 0, 0, 1.0, -1.0);
00215   PID<float> posYPid(0.00270, 0.0, 0.0, -1, 1, 0, 0, 0, 1.0, -1.0);
00216 
00217   serial->configure("/dev/ttyUSB1", 115200, "8N1", false, false, 0);
00218 
00219   // Parse command-line:
00220   if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1);
00221 
00222   manager.start();
00223 
00224   Timer timer;
00225   timer.reset();
00226 
00227   LINFO("Press enter to calculate the mean/std of the IMU");
00228   getchar();
00229   heliPose->getIMUBias();
00230   LINFO("Done");
00231 
00232   float frame = 0;
00233   float currentYaw = 0;
00234   while(1)
00235   {
00236 
00237     //draw world
00238     HeliPose::Pose pose = heliPose->getPose();
00239 
00240     drawWorld(pose.translation.x,pose.translation.y,pose.translation.z,pose.rotation.z, ofs);
00241 
00242     RadioStatus radioStatus; // = getRadioStatus(serial);
00243 
00244     //Raw data out
00245     printf("%f %i %i %i %i %f %f %f %f %f %f\n",
00246         timer.getSecs(),
00247         radioStatus.thr, radioStatus.elevator, radioStatus.aileron, radioStatus.yaw,
00248         pose.accelX, pose.accelY, pose.accelZ,
00249         pose.roll, pose.pitch, pose.yaw);
00250 
00251 
00252     //printf("acc %f velocity = %f Translation.x = %f\n",
00253     //    pose.accelX, pose.velocity.x, pose.translation.x);
00254     fflush(stdout);
00255 
00256     tunePID(radioStatus, yawPid);
00257 
00258     //float elevatorInput = posYPid.update(0, -1*pose.translation.y);
00259     //float aileronInput = posXPid.update(0, pose.translation.x);
00260     if (frame > 500)
00261     {
00262       frame = 0;
00263       currentYaw = pose.rotation.z*180/M_PI;
00264     } else {
00265       frame++;
00266     }
00267 
00268     if (pose.valid)
00269     {
00270       float yawInput = -1*yawPid.update(currentYaw, pose.rotation.z*180/M_PI);
00271 
00272     //  radioStatus.elevator += (int)(elevatorInput*(1523-510));
00273     //  radioStatus.aileron += (int)(aileronInput*(1523-510));
00274         radioStatus.yaw += (int)(yawInput*(1523-510));
00275 
00276        // LINFO("YawInput(d%0.f) %f,%f,%i",currentYaw, pose.rotation.z*180/M_PI,
00277        //     yawInput, radioStatus.yaw);
00278     }
00279 
00280   //  LINFO("ElevatorInput %f,%f,%i",pose.translation.y, elevatorInput, radioStatus.elevator);
00281   //  LINFO("AileronInput %f,%f,%i",pose.translation.x, aileronInput, radioStatus.aileron);
00282 
00283     sendRadioStatus(radioStatus, serial);
00284 
00285     ofs->updateNext();
00286     frame++;
00287   }
00288 
00289   // stop all our ModelComponents
00290   manager.stop();
00291 
00292   // all done!
00293   return 0;
00294 }
00295 
00296 // ######################################################################
00297 /* So things look consistent in everyone's emacs... */
00298 /* Local Variables: */
00299 /* indent-tabs-mode: nil */
00300 /* End: */
Generated on Sun May 8 08:41:22 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3