epos_driver.cpp
Go to the documentation of this file.
00001 #include "epos_driver/epos_driver.hpp"
00002 
00003 //                       ____       _                
00004 //   ___ _ __   ___  ___|  _ \ _ __(_)_   _____ _ __ 
00005 //  / _ \ '_ \ / _ \/ __| | | | '__| \ \ / / _ \ '__|
00006 // |  __/ |_) | (_) \__ \ |_| | |  | |\ V /  __/ |   
00007 //  \___| .__/ \___/|___/____/|_|  |_| \_/ \___|_|   
00008 //      |_|                                          
00019 eposdriver::eposdriver(ros::NodeHandle parameters){
00020   parameters.param<std::string>("port",port,"/dev/usb0");
00021   parameters.param<bool>("use_radps",useRadps,true);  
00022   parameters.param<double>("max_velocity_radps",pMaxVelocityRadps,0.4);
00023   parameters.param<double>("accel_radpss",pAccelRadpss,0.02);
00024   parameters.param<double>("deccel_radpss",pDeccelRadpss,0.02);
00025   parameters.param<int>("max_velocity_rpm",pMaxVelocityRpm,57);
00026   parameters.param<int>("accel_rpmps",pAccelRpmps,2);
00027   parameters.param<int>("deccel_rpmps",pDeccelRpmps,2);
00028   parameters.param<bool>("use_trapezoidal",useTrapezoidal,false);
00029   parameters.param<double>("topic_frequency",topicFrequency,20);
00030   parameters.param<std::string>("my_frame_id", myFrameId, "maxon");
00031   parameters.param<std::string>("parent_frame_id", parentFrameId, "base");
00032   parameters.param<double>("sensor_pose_x", sensorPoseX, 0.0);
00033   parameters.param<double>("sensor_pose_y", sensorPoseY, 0.0);
00034   parameters.param<double>("sensor_pose_z", sensorPoseZ, 0.0);
00035   parameters.param<int>("treshold_ticks",tresholdTicks,10);
00036   parameters.param<int>("time_shift",timeShift,6); //ms
00037 
00038   if(useRadps){
00039     maxVelocity=Radps2rpm(pMaxVelocityRadps);
00040     accel=Radps2rpm(pAccelRadpss);
00041     deccel=Radps2rpm(pAccelRadpss);
00042   }
00043   else{
00044     maxVelocity=pMaxVelocityRpm;
00045     accel=pAccelRpmps;
00046     deccel=pAccelRpmps;
00047   }
00048 }
00049 
00050 //   ___        
00051 //  / _ \ _ __  
00052 // | | | | '_ \ 
00053 // | |_| | | | |
00054 //  \___/|_| |_|
00062 // todo Is this return enough or should we return speciffic error code?
00063 
00064 
00065 int eposdriver::On(){
00066   WORD eposStatus=0x0;
00067   int eposState=0;
00068   char deviceName[128];
00069   int functionReturns;
00070   unsigned long win;// position window
00071   long pos = -99;// position of the EPOS
00072   ROS_INFO("*** EPOS driver initialising ***");
00073   ROS_INFO("Openning the device. Port: %s",port.c_str());
00074   if(openEPOS(const_cast<char *>(port.c_str()))<0){
00075     ROS_ERROR("Could not open EPOS on port: %s.",port.c_str());
00076     ROS_ERROR("EXITING NODE");
00077     ros::shutdown();
00078   }
00079   else{
00080     ROS_INFO("EPOS on port %s opened.",port.c_str());
00081   }
00082   //todo Do we need to read the device name?
00083   if(readDeviceName(deviceName)<0){ //reading the name of the connected device
00084     ROS_ERROR("Could not read the device name");
00085   }
00086   else{
00087     ROS_INFO("Connected device name is: %s",deviceName);
00088   }
00089   //todo Do we need to read the software version?
00090   functionReturns=readSWversion();
00091   if(functionReturns<0){
00092     ROS_ERROR("Could not read the software version");
00093   }
00094   else{
00095     ROS_INFO("Software version is is: %x",functionReturns);
00096   }
00097   //todo Do we need to read the RS232 timeout?
00098   functionReturns=readRS232timeout();
00099   if(functionReturns<0){
00100     ROS_ERROR("Could not read the RS232 timeout");
00101     EposError();
00102   }
00103   else{
00104     ROS_INFO("RS232 timeout is: %d ms\n", functionReturns);
00105   }
00106 
00107   ROS_INFO("*** Checking EPOS status ***");
00108   functionReturns = readStatusword(&eposStatus);
00109   if (functionReturns<0){
00110     ROS_ERROR("Could not check EPOS status");
00111     EposError();
00112   }
00113   else{
00114     ROS_INFO("EPOS status is: %#06x \n",eposStatus);
00115   }
00116   ROS_INFO("*** Switching on EPOS ***");
00117   eposState=checkEPOSstate();
00118   ROS_INFO("EPOS state; %d:",eposState);
00119   if (eposState==11){
00120     ROS_INFO("EPOS is in FAULT state, doing FAULT RESET.");
00121     changeEPOSstate(6);// reset FAULT
00122     eposState=checkEPOSstate();// check status again
00123     if(eposState==11){
00124       ROS_ERROR("EPOS still in FAULT state, quit!");
00125       EposError();
00126       return -1;//exit(1);
00127     }
00128     else{
00129       ROS_INFO("Success! (Now in state %d)", eposState);
00130     }
00131   }
00132   if(eposState!=4 && eposState!=7) { // EPOS not running, issue a quick stop
00133     ROS_INFO("EPOS is in FAULT state, doing FAULT RESET.");
00134     changeEPOSstate(3);
00135     eposState=checkEPOSstate();// EPOS should now be in 'switch on disabled' (2)
00136     if (eposState!=2){
00137       ROS_ERROR("EPOS is NOT in 'switch on disabled' state, quit!");
00138       return -1; //exit(1);
00139     }
00140     else {  // EPOS is in 'switch on disabled'
00141       ROS_INFO("EPOS is in 'switch on disabled' state, doing shutdown.");
00142       changeEPOSstate(0); // issue a 'shutdown'
00143     }
00144     ROS_INFO("Switching on EPOS");
00145     changeEPOSstate(1);
00146     ROS_INFO("Enable operation" );
00147     changeEPOSstate(5);
00148   }
00149   EposState();
00150   readPositionWindow(&win);
00151   ROS_INFO("EPOS position window is %lu.", win);  
00152   readActualPosition(&pos);   // actual position
00153   ROS_INFO("Please wait until homing complete...");
00154   if (setHomePolarity(1)) {// filter wheel home switch is low-active; THIS IS NOT THE DEFAULT! what does it mean????
00155     ROS_ERROR(" *** UNABLE TO SET HomeSwitch TO low-active!!! ***");
00156   }
00157   while ((functionReturns= doHoming(18,0))!=0){
00158     ROS_ERROR("#### doHoming() returned %d ####", functionReturns);
00159     changeEPOSstate(5);
00160   }
00161   if(setOpMode(1)){ // Set Profile Position Mode once, to avoid having to dot at each call to moveAbsolute().
00162     ROS_ERROR("Error with setOpMode(1)");
00163     return(-1);
00164   }
00165   EposState();
00166   readActualPosition(&pos);
00167   ROS_INFO("EPOS position is %ld.", pos);
00168   motorState=1;
00169   moduleCount=1;
00170   ROS_INFO("Prameters %d %d %d", maxVelocity,accel,deccel);
00171   set_speed_profile(maxVelocity,accel,deccel,useTrapezoidal);
00172   ROS_INFO("EPOS driver is reday");
00173   return(0);
00174 }
00175 
00176 //   ___   __  __ 
00177 //  / _ \ / _|/ _|
00178 // | | | | |_| |_ 
00179 // | |_| |  _|  _|
00180 //  \___/|_| |_|  
00182 int eposdriver::Off(){
00183   ROS_INFO("Shutting EPOS driver down");
00184   if(closeEPOS()<0){
00185     ROS_ERROR("Failure druing shooting down");
00186     return -1;
00187   }
00188   else{
00189     ROS_INFO("EPOS driver has been shutdown");
00190   }
00191   return 0;
00192 }
00193 
00194 //  __  __       _       
00195 // |  \/  | __ _(_)_ __  
00196 // | |\/| |/ _` | | '_ \ 
00197 // | |  | | (_| | | | | |
00198 // |_|  |_|\__,_|_|_| |_|
00203  // todo Check if all converions are corret.
00204  
00205 int eposdriver::Main(){
00206   long rawPosition;
00207   double pos;
00208   long rawSpeed;
00209   double speed;
00210   double acceleration;
00211   short current;
00212   long oldSpeed;
00213   float deltaSpeed;
00214   bool validDeltaSpeed(false);
00215   moveSingle=true;
00216   synchronize=true;
00217   epos_driver::EPOSState msg;
00218   ros::Time then;
00219   ros::Time now;
00220   ros::Duration elapsedTime;
00221   static const double mradPerTick=0.000209;//1000.0*0.000209;
00222   //  ros::Rate loopRate(topicFrequency);
00223   statePublisher=nodeHandler.advertise<epos_driver::EPOSState>("EPOSState",1000);
00224   ros::ServiceServer MoveToService=nodeHandler.advertiseService("MoveTo",&eposdriver::MoveTo,this);
00225   ros::ServiceServer MoveCycleService=nodeHandler.advertiseService("MoveCycle",&eposdriver::MoveCycle,this);
00226   tf::Transform transform;
00227   static tf::TransformBroadcaster tfPublisher;
00228 
00229   ros::Time time_framerate_start;
00230   ros::Time time_framerate_end;
00231   ros::Time time_realtime_start;
00232   ros::Time time_realtime_end;
00233   
00234   time_framerate_start=ros::Time::now();
00235   time_realtime_start=time_framerate_start;
00236 
00237   while(ros::ok()){
00238     time_realtime_end=ros::Time::now();
00239     //  long real_elapsed=time_realtime_start.toNsec()-time_realtime_end.toNsec();
00240     time_realtime_start=ros::Time::now();
00241 
00242     oldSpeed=speed;
00243     then=now;
00244     now=ros::Time::now();
00245     readActualVelocity(&rawSpeed);
00246     readActualPosition(&rawPosition);
00247     readActualCurrent(&current);
00248     pos=mradPerTick*static_cast<double>(rawPosition);
00249     speed=mradPerTick*static_cast<double>(rawSpeed);
00250     if(validDeltaSpeed){
00251       deltaSpeed=speed-oldSpeed;
00252       elapsedTime=now-then;
00253       acceleration=deltaSpeed/elapsedTime.toSec(); 
00254     }
00255     else{
00256       acceleration=0;
00257     }
00258     if(!validDeltaSpeed)
00259       validDeltaSpeed=true;
00260     msg.header.stamp=ros::Time::now();
00261     msg.raw_position=rawPosition;
00262     msg.position=pos;
00263     msg.raw_speed=rawSpeed;
00264     msg.speed=speed;
00265     msg.acceleration=acceleration;
00266     msg.current=current;
00267     if(moveSingle){
00268       if(speed==0.0)
00269         synchronize=true;
00270       else
00271         synchronize=false;
00272     }
00273     if(!moveSingle){
00274       if(moveDown){
00275         synchronize=false;
00276         if(rawPosition>=int(highLimit/mradPerTick)-tresholdTicks){
00277           synchronize=true;
00278           moveAbsolute(lowLimit/mradPerTick);
00279           moveUp=true;
00280           moveDown=false;
00281         }
00282       }
00283       else if(moveUp){
00284         synchronize=false;
00285         if(rawPosition<=int(lowLimit/mradPerTick)+tresholdTicks){
00286           synchronize=true;
00287           moveAbsolute(highLimit/mradPerTick);
00288           moveUp=false;
00289           moveDown=true;
00290         }
00291       }
00292     }
00293     msg.sync=synchronize;
00294     transform.setOrigin(tf::Vector3(sensorPoseX,sensorPoseY,sensorPoseZ)); 
00295     transform.setRotation(tf::createQuaternionFromRPY(0.0,0.0,pos));
00296     tfPublisher.sendTransform(tf::StampedTransform(transform,ros::Time::now()+ros::Duration(0,timeShift), parentFrameId, myFrameId));   
00297     statePublisher.publish(msg);
00298     time_framerate_end=ros::Time::now();
00299     ros::Duration elapsed=time_framerate_end-time_framerate_start;
00300     ros::Duration sleep_;
00301     if (ros::Duration(1/topicFrequency)-elapsed<ros::Duration(0))
00302       sleep_= ros::Duration(0);
00303     else
00304       sleep_= ros::Duration(1/topicFrequency)-elapsed;
00305     ros::Duration(sleep_).sleep();
00306     time_framerate_start=ros::Time::now();
00307     ros::spinOnce();
00308     //  loopRate.sleep(); 
00309   }
00310   return 0;
00311 }
00312 
00313 //  ____           _     ____                       
00314 // |  _ \ __ _  __| |___|___ \ _ __ _ __  _ __ ___  
00315 // | |_) / _` |/ _` / __| __) | '__| '_ \| '_ ` _ \ 
00316 // |  _ < (_| | (_| \__ \/ __/| |  | |_) | | | | | |
00317 // |_| \_\__,_|\__,_|___/_____|_|  | .__/|_| |_| |_|
00318 //                                 |_|              
00325  //todo check what is doing which variable
00326  
00327 unsigned int eposdriver::Radps2rpm(double radps){
00328   static const double mradPerTick=1000.0*0.000209;
00329   static const double radpsToRpm = 3.0*10.0*100.0*1000.0/mradPerTick/1000.0;
00330   ROS_INFO("value %f -> %d",radps*radpsToRpm,int(radps*radpsToRpm));
00331   return int(radps*radpsToRpm);
00332 }
00333 
00334 //  _____                 _____                     
00335 // | ____|_ __   ___  ___| ____|_ __ _ __ ___  _ __ 
00336 // |  _| | '_ \ / _ \/ __|  _| | '__| '__/ _ \| '__|
00337 // | |___| |_) | (_) \__ \ |___| |  | | | (_) | |   
00338 // |_____| .__/ \___/|___/_____|_|  |_|  \___/|_|   
00339 //       |_|                                        
00345 int eposdriver::EposError(){
00346   switch(E_error) {
00347     case E_NOERR: 
00348       return(0);
00349     case E_ONOTEX:
00350       ROS_ERROR("EPOS responds with error: requested object does not exist!"); break;
00351     case E_SUBINEX:
00352       ROS_ERROR("EPOS responds with error: requested subindex does not exist!"); break;
00353     case E_OUTMEM:
00354       ROS_ERROR("EPOS responds with error: out of memory!"); break;
00355     case E_NOACCES:
00356       ROS_ERROR("EPOS responds with error: unsupported access to an object!"); break;
00357     case E_WRITEONLY:
00358       ROS_ERROR("EPOS responds with error: attempt to read a write-only object!"); break;
00359     case E_READONLY:
00360       ROS_ERROR("EPOS responds with error: attempt to write a read-only object!"); break;
00361     case E_PARAMINCOMP:
00362       ROS_ERROR("EPOS responds with error: general parameter incompatibility!"); break;
00363     case E_INTINCOMP:
00364       ROS_ERROR("EPOS responds with error: general internal incompatibility in the device!"); break;
00365     case E_HWERR:
00366       ROS_ERROR("EPOS responds with error: access failed due to an HARDWARE ERROR!"); break;
00367     case E_PRAGNEX:
00368       ROS_ERROR("EPOS responds with error: value range of parameter exeeded!"); break;
00369     case E_PARHIGH:
00370       ROS_ERROR("EPOS responds with error: value of parameter written is too high!"); break;
00371     case E_PARLOW:
00372       ROS_ERROR("EPOS responds with error: value of parameter written is too low!"); break;
00373     case E_PARREL:
00374       ROS_ERROR("EPOS responds with error: maximum value is less than minimum value!"); break;
00375     case E_NMTSTATE:
00376       ROS_ERROR("EPOS responds with error: wrong NMT state!"); break;
00377     case E_RS232:
00378       ROS_ERROR("EPOS responds with error: rs232 command illegeal!"); break;
00379     case E_PASSWD:
00380       ROS_ERROR("EPOS responds with error: password incorrect!"); break;
00381     case E_NSERV:
00382       ROS_ERROR("EPOS responds with error: device not in service mode!"); break;
00383     case E_NODEID:
00384       ROS_ERROR("EPOS responds with error: error in Node-ID!"); break;
00385     default:
00386       ROS_ERROR("EPOS responds with error: unknown EPOS error code: %#lx",E_error); break;
00387   }
00388   return(-1);
00389 }
00390 
00391 //  _____                 ____  _        _       
00392 // | ____|_ __   ___  ___/ ___|| |_ __ _| |_ ___ 
00393 // |  _| | '_ \ / _ \/ __\___ \| __/ _` | __/ _ \
00394 // | |___| |_) | (_) \__ \___) | || (_| | ||  __/
00395 // |_____| .__/ \___/|___/____/ \__\__,_|\__\___|
00396 //       |_|                                     
00402 int eposdriver::EposState(){
00403   switch(checkEPOSstate()){
00404     case 0: ROS_INFO("EPOS is in state: start"); break;
00405     case 1: ROS_INFO("EPOS is in state: Not ready to switch on."); break;
00406     case 2: ROS_INFO("EPOS is in state: Switch on disabled."); break;
00407     case 3: ROS_INFO("EPOS is in state: Ready to switch on."); break;
00408     case 4: ROS_INFO("EPOS is in state: Switched on."); break;
00409     case 5: ROS_INFO("EPOS is in state: Refresh."); break;
00410     case 6: ROS_INFO("EPOS is in state: Measure init."); break;
00411     case 7: ROS_INFO("EPOS is in state: Operation enable."); break;
00412     case 8: ROS_INFO("EPOS is in state: Quick stop active"); break;
00413     case 9: ROS_INFO("EPOS is in state: Fault reaction active (disabled)"); break;
00414     case 10: ROS_INFO("EPOS is in state: Fault reaction active (enabled)"); break;
00415     case 11: ROS_INFO("EPOS is in state: FAULT\n"); break;
00416     default: 
00417       ROS_INFO("EPOS is in state: UNKNOWN!\n");
00418       return(-1);
00419   }
00420   return(0);
00421 }
00422 
00423 //  __  __               _____     
00424 // |  \/  | _____   ____|_   _|__  
00425 // | |\/| |/ _ \ \ / / _ \| |/ _ \ 
00426 // | |  | | (_) \ V /  __/| | (_) |
00427 // |_|  |_|\___/ \_/ \___||_|\___/ 
00432 bool eposdriver::MoveTo(epos_driver::MoveTo::Request  &req,epos_driver::MoveTo::Response  &res){
00433   static const float radPerTick = 0.000209;
00434   moveAbsolute(req.pose/radPerTick);
00435   moveSingle=true;
00436   return true;
00437 }
00438 
00439 //  __  __                 ____           _      
00440 // |  \/  | _____   _____ / ___|   _  ___| | ___ 
00441 // | |\/| |/ _ \ \ / / _ \ |  | | | |/ __| |/ _ \
00442 // | |  | | (_) \ V /  __/ |__| |_| | (__| |  __/
00443 // |_|  |_|\___/ \_/ \___|\____\__, |\___|_|\___|
00444 //                             |___/             
00449 bool eposdriver::MoveCycle(epos_driver::MoveCycle::Request  &req,epos_driver::MoveCycle::Response &res){
00450   static const float radPerTick = 0.000209;
00451   long rawSpeed;
00452   highLimit=req.pose_top;
00453   lowLimit=req.pose_bottom;
00454   moveAbsolute(highLimit/radPerTick);
00455   if(highLimit>lowLimit){
00456     do{
00457       readActualVelocity(&rawSpeed);
00458       ros::Duration(0.1).sleep();
00459     }while(rawSpeed!=0);
00460     moveSingle=false;
00461     moveUp=false;
00462     moveDown=true;
00463   }
00464   else {
00465     ROS_ERROR("Limits of motion wrongly setted!");
00466   }
00467   return true;
00468 }
00469 


epos_driver
Author(s): Tomasz Kucner , Martin Magnusson , Hakan Almqvist , Marcus Hauser
autogenerated on Fri Aug 28 2015 10:38:28