main.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2013, JSK Lab at University of Tokyo
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/o2r other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the University of Tokyo nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <getopt.h>
00038 #include <map>
00039 #include "ros/ros.h"
00040 #include <execinfo.h>
00041 #include <signal.h>
00042 #include <sys/mman.h>
00043 #include <sys/types.h>
00044 #include <sys/stat.h>
00045 #include <unistd.h>
00046 #include <fcntl.h>
00047 #include <pthread.h>
00048 #include <boost/asio.hpp>
00049 #include <boost/bind.hpp>
00050 #include <boost/asio/io_service.hpp>
00051 #include <open_controllers_interface/open_controllers_interface.h>
00052 #include <std_srvs/Empty.h>
00053 #include <boost/shared_ptr.hpp>
00054 #include <boost/accumulators/accumulators.hpp>
00055 #include <boost/accumulators/statistics/stats.hpp>
00056 #include <boost/accumulators/statistics/max.hpp>
00057 #include <boost/accumulators/statistics/mean.hpp>
00058 #include <boost/thread.hpp>
00059 #include <boost/filesystem.hpp>
00060 #include <boost/pointer_cast.hpp>
00061 #include <diagnostic_updater/DiagnosticStatusWrapper.h>
00062 #include <pr2_controller_manager/controller_manager.h>
00063 #include <diagnostic_msgs/DiagnosticArray.h>
00064 
00065 #include <std_srvs/Empty.h>
00066 
00067 #include <realtime_tools/realtime_publisher.h>
00068 #include <std_msgs/Float64.h>
00069 #define BCAP_CONNECTION_UDP 1
00070 #include "utf8.h"
00071 #include "b-Cap.h"
00072 
00073 #define DEFAULT_SERVER_IP_ADDRESS               "133.11.216.196"                /* Your controller IP address */
00074 #define DEFAULT_SERVER_PORT_NUM                 5007
00075 #define DEFAULT_UDP_TIMEOUT (10 * 1000)
00076 #define CLOCK_PRIO 0
00077 #define CONTROL_PRIO 0
00078 
00079 #define RAD2DEG(x) ((x) * 180.0 / M_PI)
00080 #define DEG2RAD(x) ((x) * M_PI / 180.0)
00081 
00082 class DensoController : public OpenControllersInterface::OpenController
00083 {
00084   class DensoControllerStatus : public OpenControllersInterface::ControllerStatus {
00085     public:
00086       DensoControllerStatus(BCAP_HRESULT hr): hr_(hr){};
00087       DensoControllerStatus(u_int error_code): hr_((BCAP_HRESULT)error_code){};
00088       virtual ~DensoControllerStatus(){};
00089       virtual bool isHealthy(){
00090           return SUCCEEDED(hr_);
00091       }
00092       BCAP_HRESULT hr_;
00093   };
00094   typedef boost::shared_ptr<DensoControllerStatus> DensoControllerStatusPtr;
00095 
00096 public:
00097   DensoController() :
00098       OpenControllersInterface::OpenController()
00099   {
00100     prev_angle_.resize(6);
00101     prev_vel_.resize(6);
00102   }
00103 #define SAFE_EXIT(exit_code) {                  \
00104     ROS_FATAL("fatal error has occurred");      \
00105     quitRequest();              \
00106   }
00107 
00108   virtual ~DensoController(){}
00109 
00110   void start()
00111   {
00112     OpenController::start();
00113   }
00114 private:
00115   std::string server_ip_address_;
00116   int server_port_number_;
00117   // for bCap parameters
00118   int iSockFD_;
00119   u_int lhController_;
00120   u_int lhRobot_;
00121   int udp_timeout_;
00122   std::map<std::string, u_int>   var_handlers_;
00123   std::map<std::string, u_short> var_types_;
00124   char errdesc_buffer_[2048]; // TODO: is this enough?
00125 
00126   std::vector<double> prev_angle_;
00127   std::vector<double> prev_vel_;
00128   struct timespec prev_time_;
00129 
00130 public:
00134   BCAP_HRESULT bCapOpen()
00135   {
00136     BCAP_HRESULT hr = BCAP_S_OK;
00137     hr = bCap_Open(server_ip_address_.c_str(), server_port_number_, &iSockFD_); /* Init socket  */
00138     return hr;
00139   }
00140 
00141   BCAP_HRESULT bCapClose()
00142   {
00143     BCAP_HRESULT hr = BCAP_S_OK;
00144     hr = bCap_Close(iSockFD_);
00145     return hr;
00146   }
00147 
00148   BCAP_HRESULT bCapControllerConnect()
00149   {
00150     BCAP_HRESULT hr = BCAP_S_OK;
00151     hr = bCap_ControllerConnect(iSockFD_, (char*)"", (char*)"caoProv.DENSO.VRC", (char*)(server_ip_address_.c_str()), (char*)"",
00152                                 &lhController_);
00153     return hr;
00154   }
00155 
00156   BCAP_HRESULT bCapControllerDisConnect()
00157   {
00158     BCAP_HRESULT hr = BCAP_S_OK;
00159     hr = bCap_ControllerDisconnect(iSockFD_, lhController_);
00160     return hr;
00161   }
00162 
00163   BCAP_HRESULT bCapClearError()
00164   {
00165     BCAP_HRESULT hr = BCAP_S_OK;
00166     long lResult;
00167     hr = bCap_ControllerExecute(iSockFD_, lhController_, (char*)"ClearError", (char*)"", &lResult);
00168     ROS_INFO("clearError %02x %02x", hr, lResult);
00169     return hr;
00170   }
00171 
00172   BCAP_HRESULT bCapGetRobot()
00173   {
00174     BCAP_HRESULT hr = BCAP_S_OK;
00175     long lResult;
00176     hr = bCap_ControllerGetRobot(iSockFD_, lhController_, (char*)"", (char*)"", &lhRobot_); /* Get robot handle */
00177     ROS_INFO("GetRobot %02x %02x", hr, lhRobot_);
00178     return hr;
00179   }
00180   BCAP_HRESULT bCapReleaseRobot()
00181   {
00182     BCAP_HRESULT hr = BCAP_S_OK;
00183     hr = bCap_RobotRelease(iSockFD_, lhRobot_); /* Release robot handle */
00184     return hr;
00185   }
00186 
00187   BCAP_HRESULT bCapRobotExecute(char* command, char* arg)
00188   {
00189     BCAP_HRESULT hr = BCAP_S_OK;
00190     long lResult;
00191     hr = bCap_RobotExecute(iSockFD_, lhRobot_, command, arg, &lResult);
00192     return hr;
00193   }
00194 
00195   BCAP_HRESULT bCapTakearm()
00196   {
00197     BCAP_VARIANT takearmparam, takearmresult;
00198     takearmparam.Type = VT_I4 | VT_ARRAY;
00199     takearmparam.Arrays = 2;
00200     ((u_int*)(&takearmparam.Value.LongValue))[0] = 0;
00201     ((u_int*)(&takearmparam.Value.LongValue))[1] = 1;
00202     BCAP_HRESULT hr;
00203     //hr = bCap_RobotExecute(iSockFD_, lhRobot_, "Takearm", takearmparam, &takearmresult);
00204     hr = bCap_RobotExecute2(iSockFD_, lhRobot_, "Takearm", &takearmparam, &takearmresult);
00205     //BCAP_HRESULT hr = bCapRobotExecute("Takearm", "");
00206     return hr;
00207   }
00208 
00209   BCAP_HRESULT bCapGiveArm()
00210   {
00211     BCAP_VARIANT lResult;
00212     BCAP_HRESULT hr;
00213     hr = bCap_RobotExecute(iSockFD_, lhRobot_, (char*)"Givearm", (char*)"", &lResult);
00214     return hr;
00215   }
00216 
00217   BCAP_HRESULT bCapSetExternalSpeed(float arg)
00218   {
00219     BCAP_HRESULT hr;
00220     BCAP_VARIANT extspeedparam, extspeedresult;
00221     extspeedparam.Type = VT_R4 | VT_ARRAY;
00222     extspeedparam.Arrays = 1;
00223     extspeedparam.Value.FloatValue = arg;
00224     //((u_int*)(&extspeedparam.Value.LongValue))[1] = 0;
00225     //((u_int*)(&extspeedparam.Value.LongValue))[2] = 0;
00226     //hr = bCap_RobotExecute(iSockFD_, lhRobot_, "ExtSpeed", (char*)"80.0", &lResult);
00227     hr = bCap_RobotExecute2(iSockFD_, lhRobot_, "ExtSpeed", &extspeedparam, &extspeedresult);
00228 
00229     //BCAP_HRESULT hr = bCapRobotExecute("ExtSpeed", arg);
00230     return hr;
00231   }
00232 
00233   void bCapInitializeVariableHandlers()
00234   {
00235     var_handlers_.insert(std::map<std::string, u_int>::value_type("MODE",bCapControllerGetVariable("@MODE")));
00236     var_handlers_.insert(std::map<std::string, u_int>::value_type("ERROR_CODE",bCapControllerGetVariable("@ERROR_CODE")));
00237     var_handlers_.insert(std::map<std::string, u_int>::value_type("ERROR_DESCRIPTION",bCapControllerGetVariable("@ERROR_DESCRIPTION")));
00238     var_handlers_.insert(std::map<std::string, u_int>::value_type("VERSION",bCapControllerGetVariable("@VERSION")));
00239     var_handlers_.insert(std::map<std::string, u_int>::value_type("SPEED",bCapRobotGetVariable("@SPEED")));
00240     var_handlers_.insert(std::map<std::string, u_int>::value_type("ACCEL",bCapRobotGetVariable("@ACCEL")));
00241     var_handlers_.insert(std::map<std::string, u_int>::value_type("DECEL",bCapRobotGetVariable("@DECEL")));
00242     var_handlers_.insert(std::map<std::string, u_int>::value_type("JSPEED",bCapRobotGetVariable("@JSPEED")));
00243     var_handlers_.insert(std::map<std::string, u_int>::value_type("JACCEL",bCapRobotGetVariable("@JACCEL")));
00244     var_handlers_.insert(std::map<std::string, u_int>::value_type("JDECEL",bCapRobotGetVariable("@JDECEL")));
00245     var_handlers_.insert(std::map<std::string, u_int>::value_type("EXTSPEED",bCapRobotGetVariable("@EXTSPEED")));
00246     var_handlers_.insert(std::map<std::string, u_int>::value_type("EXTACCEL",bCapRobotGetVariable("@EXTACCEL")));
00247     var_handlers_.insert(std::map<std::string, u_int>::value_type("EXTDECEL",bCapRobotGetVariable("@EXTDECEL")));
00248     var_handlers_.insert(std::map<std::string, u_int>::value_type("SERVO_ON",bCapRobotGetVariable("@SERVO_ON")));
00249     var_handlers_.insert(std::map<std::string, u_int>::value_type("BUSY_STATUS",bCapControllerGetVariable("@BUSY_STATUS")));
00250     var_handlers_.insert(std::map<std::string, u_int>::value_type("CURRENT_TIME",bCapControllerGetVariable("@CURRENT_TIME")));
00251     var_handlers_.insert(std::map<std::string, u_int>::value_type("LOCK",bCapControllerGetVariable("@LOCK")));
00252     var_handlers_.insert(std::map<std::string, u_int>::value_type("EMERGENCY_STOP",bCapControllerGetVariable("@EMERGENCY_STOP")));
00253 
00254     var_types_.insert(std::map<std::string, u_short>::value_type("ERROR_CODE", VT_I4));
00255     var_types_.insert(std::map<std::string, u_short>::value_type("MODE", VT_I4));
00256     var_types_.insert(std::map<std::string, u_short>::value_type("ERROR_DESCRIPTION", VT_BSTR));
00257     var_types_.insert(std::map<std::string, u_short>::value_type("VERSION", VT_BSTR));
00258     var_types_.insert(std::map<std::string, u_short>::value_type("SPEED", VT_R4));
00259     var_types_.insert(std::map<std::string, u_short>::value_type("ACCEL", VT_R4));
00260     var_types_.insert(std::map<std::string, u_short>::value_type("DECEL", VT_R4));
00261     var_types_.insert(std::map<std::string, u_short>::value_type("JSPEED", VT_R4));
00262     var_types_.insert(std::map<std::string, u_short>::value_type("JACCEL", VT_R4));
00263     var_types_.insert(std::map<std::string, u_short>::value_type("JDECEL", VT_R4));
00264     var_types_.insert(std::map<std::string, u_short>::value_type("EXTSPEED", VT_R4));
00265     var_types_.insert(std::map<std::string, u_short>::value_type("EXTACCEL", VT_R4));
00266     var_types_.insert(std::map<std::string, u_short>::value_type("EXTDECEL", VT_R4));
00267     var_types_.insert(std::map<std::string, u_short>::value_type("BUSY_STATUS", VT_BOOL));
00268     var_types_.insert(std::map<std::string, u_short>::value_type("CURRENT_TIME", VT_DATE));
00269     var_types_.insert(std::map<std::string, u_short>::value_type("LOCK", VT_BOOL));
00270     var_types_.insert(std::map<std::string, u_short>::value_type("EMERGENCY_STOP", VT_BOOL));
00271   }
00272 
00273   u_int bCapControllerGetVariable(const std::string& varname)
00274   {
00275     BCAP_HRESULT hr = BCAP_S_OK;
00276     u_int varresult;
00277     hr = bCap_ControllerGetVariable(iSockFD_, lhController_, (char*)(varname.c_str()), (char*)"", &varresult);
00278     if(FAILED(hr)) {
00279         ROS_WARN("failed to controller get variable '%s' hr:%02x result:%02x", varname.c_str(), hr, varresult);
00280     }
00281     return varresult;
00282   }
00283 
00284   u_int bCapRobotGetVariable(const std::string& varname)
00285   {
00286     BCAP_HRESULT hr = BCAP_S_OK;
00287     u_int varresult;
00288     hr = bCap_RobotGetVariable(iSockFD_, lhRobot_, (char*)(varname.c_str()), (char*)"", &varresult);
00289     if(FAILED(hr)) {
00290         ROS_WARN("failed to controller get variable '%s' hr:%02x result:%02x", varname.c_str(), hr, varresult);
00291     }
00292     return varresult;
00293   }
00294 
00295   bool bCapGetBoolVariable(const std::string& var_name)
00296   {
00297     bool var = 0;
00298     if( var_types_.find(var_name.c_str()) != var_types_.end() ) {
00299       BCAP_HRESULT hr = bCap_VariableGetValue(iSockFD_, var_handlers_[var_name.c_str()], &var);
00300       if( FAILED(hr) ) {
00301         ROS_WARN("Failed to get %s, return 0 instead.", var_name.c_str());
00302         return 0;
00303       }
00304       return var;
00305     }
00306     ROS_WARN("No handler for %s, return 0 instead.", var_name.c_str());
00307     return 0;
00308   }
00309 
00310   u_int bCapGetIntegerVariable(const std::string& var_name)
00311   {
00312     u_int var = 0;
00313     if( var_types_.find(var_name.c_str()) != var_types_.end() ) {
00314       BCAP_HRESULT hr = bCap_VariableGetValue(iSockFD_, var_handlers_[var_name.c_str()], &var);
00315       if( FAILED(hr) ) {
00316         ROS_WARN("Failed to get %s, return 0 instead.", var_name.c_str());
00317         return 0;
00318       }
00319       return var;
00320     }
00321     ROS_WARN("No handler for %s, return 0 instead.", var_name.c_str());
00322     return 0;
00323   }
00324 
00325   u_int __errorcode__;
00326   u_int bCapGetErrorCode()
00327   {
00328     //u_int errorcode = 0; // this local variable is not allocated in debug mode...? why...
00329     __errorcode__ = 0;
00330     if( var_types_.find("ERROR_CODE") != var_types_.end() ) {
00331       BCAP_HRESULT hr = bCap_VariableGetValue(iSockFD_, var_handlers_["ERROR_CODE"], &__errorcode__);
00332       if( FAILED(hr) ) {
00333         ROS_WARN("Failed to get ERROR_CODE, return %02x instead.", hr);
00334         return hr;
00335       }
00336       return __errorcode__;
00337     }
00338     ROS_WARN("ERROR_CODE is not in variable handlers");
00339     return 0;
00340   }
00341 
00342   // 1: manual, 2: teachcheck, 3:auto
00343   u_int bCapGetMode()
00344   {
00345     return bCapGetIntegerVariable("MODE");
00346   }
00347 
00348   bool bCapGetEmergencyStop()
00349   {
00350     return bCapGetBoolVariable("EMERGENCY_STOP");
00351   }
00352 
00353   u_int bCapErrorDescription(std::string& errormsg)
00354   {
00355     if( var_types_.find("ERROR_DESCRIPTION") != var_types_.end() ) {
00356       BCAP_HRESULT hr = bCap_VariableGetValue(iSockFD_, var_handlers_["ERROR_DESCRIPTION"], errdesc_buffer_);
00357       errormsg = errdesc_buffer_; //copy
00358 
00359       // find null
00360       size_t strlen = 0;
00361       while(strlen<2000) {
00362         if( *((uint16_t*)errdesc_buffer_+strlen) == 0 ) {
00363           break;
00364         }
00365         ++strlen;
00366       }
00367 
00368       ROS_INFO("raw error description: %s", errdesc_buffer_);
00369       try {
00370           utf8::utf16to8((uint16_t*)errdesc_buffer_, (uint16_t*)errdesc_buffer_+strlen, std::back_inserter(errormsg));
00371       } catch (utf8::invalid_utf16& e) {
00372           errormsg = errdesc_buffer_; //copy
00373       }
00374       return hr;
00375     }
00376     ROS_WARN("ERROR_DESCRIPTION is not in variable handlers");
00377     return 0;
00378   }
00379 
00380 
00381   BCAP_HRESULT bCapMotor(bool command)
00382   {
00383     BCAP_HRESULT hr = BCAP_S_OK;
00384     BCAP_VARIANT motorarmparam, motorarmresult;
00385     motorarmparam.Type = VT_I4 | VT_ARRAY;
00386     motorarmparam.Arrays = 2;
00387     if (command)
00388     {
00389       //hr = bCapRobotExecute("Motor", "1");
00390       ((u_int*)(&motorarmparam.Value.LongValue))[0] = 1;
00391       ((u_int*)(&motorarmparam.Value.LongValue))[1] = 0;
00392 
00393       hr = bCap_RobotExecute2(iSockFD_, lhRobot_, "Motor", &motorarmparam, &motorarmresult);
00394     }
00395     else
00396     {
00397       //hr = bCapRobotExecute("Motor", "0");
00398       ((u_int*)(&motorarmparam.Value.LongValue))[0] = 0;
00399       ((u_int*)(&motorarmparam.Value.LongValue))[1] = 1;
00400 
00401       hr = bCap_RobotExecute2(iSockFD_, lhRobot_, "Motor", &motorarmparam, &motorarmresult);
00402     }
00403     return hr;
00404   }
00405 
00406   BCAP_HRESULT bCapCurJnt(std::vector<double>& jointvalues)
00407   {
00408     jointvalues.resize(8);
00409     BCAP_HRESULT hr = BCAP_E_FAIL;
00410     hr = bCap_RobotExecute(iSockFD_, lhRobot_, "CurJnt", "", &jointvalues[0]);
00411     return hr;
00412   }
00413 
00414   BCAP_HRESULT bCapSlvChangeMode(u_int arg)
00415   {
00416     //long lResult;
00417     //BCAP_HRESULT hr = bCap_RobotExecute(iSockFD_, lhRobot_, "slvChangeMode", arg, &lResult);
00418     BCAP_HRESULT hr;
00419     BCAP_VARIANT slvchangeparam, slvchangeresult;
00420     slvchangeparam.Type = VT_I4;
00421     slvchangeparam.Arrays = 1;
00422     slvchangeparam.Value.LongValue = arg;
00423     hr = bCap_RobotExecute2(iSockFD_, lhRobot_, "slvChangeMode", &slvchangeparam, &slvchangeresult);
00424     //ROS_INFO("change slave mode: hr: %02x, result: %02x", hr, slvchangeresult);
00425     return hr;
00426   }
00427 
00428   BCAP_HRESULT bCapRobotSlvMove(BCAP_VARIANT* pose, BCAP_VARIANT* result)
00429   {
00430     // ROS_INFO("sending angle: %f %f %f %f %f %f",
00431     //          pose->Value.DoubleArray[0],
00432     //          pose->Value.DoubleArray[1],
00433     //          pose->Value.DoubleArray[2],
00434     //          pose->Value.DoubleArray[3],
00435     //          pose->Value.DoubleArray[4],
00436     //          pose->Value.DoubleArray[5]);
00437 
00438     // struct timeval tv;
00439     // tv.tv_sec = 0;
00440     // tv.tv_usec = 1000 * 1;
00441     // setsockopt(iSockFD_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
00442     extern int failed_to_send_packet;
00443     struct timespec tick, before;
00444     std::vector<double> current_angle;
00445     std::vector<double> current_vel;
00446     std::vector<double> current_acc;
00447     for (size_t i = 0; i < 6; i++)
00448     {
00449       current_angle.push_back(pose->Value.DoubleArray[i]);
00450     }
00451 
00452     char* command = (char*)"slvMove";
00453     clock_gettime(CLOCK_MONOTONIC, &tick);
00454     BCAP_HRESULT hr = bCap_RobotExecute2(iSockFD_, lhRobot_, command, pose, result);
00455 
00456     if (FAILED(hr)) {
00457       ROS_WARN("failed to slvmove, errorcode: %02x", hr);
00458     }
00459 
00460     clock_gettime(CLOCK_MONOTONIC, &before);
00461     static const int NSEC_PER_SECOND = 1e+9;
00462     //static const int USEC_PER_SECOND = 1e6;
00463     double roundtrip = (before.tv_sec + double(before.tv_nsec) / NSEC_PER_SECOND)
00464         - (tick.tv_sec + double(tick.tv_nsec) / NSEC_PER_SECOND);
00465 
00466     if (prev_angle_.size() > 0)
00467     {
00468       double tm = (tick.tv_sec + double(tick.tv_nsec) / NSEC_PER_SECOND)
00469           - (prev_time_.tv_sec + double(prev_time_.tv_nsec) / NSEC_PER_SECOND);
00470       current_vel.resize(6);
00471       for (size_t i = 0; i < 6; i++)
00472       {
00473         current_vel.at(i) = (current_angle[i] - prev_angle_[i]) / tm;
00474       }
00475     }
00476     if (prev_vel_.size() > 0)
00477     {
00478       double tm = (tick.tv_sec + double(tick.tv_nsec) / NSEC_PER_SECOND)
00479           - (prev_time_.tv_sec + double(prev_time_.tv_nsec) / NSEC_PER_SECOND);
00480       current_acc.resize(6);
00481       for (size_t i = 0; i < 6; i++)
00482       {
00483         current_acc.at(i) = (current_vel[i] - prev_vel_[i]) / tm;
00484       }
00485     }
00486 
00487     prev_time_ = tick;
00488     //ROS_INFO("current angle: %f %f %f %f %f %f", current_angle[0], current_angle[1], current_angle[2], current_angle[3],
00489              //current_angle[4], current_angle[5]);
00490 
00491     // if (current_vel.size() > 0) {
00492     //   ROS_INFO("current vel: %f %f %f %f %f %f",
00493     //            current_vel[0],
00494     //            current_vel[1],
00495     //            current_vel[2],
00496     //            current_vel[3],
00497     //            current_vel[4],
00498     //            current_vel[5]);
00499     //   }
00500     //   if (prev_vel_.size() > 0) {
00501     //     ROS_INFO("prev vel: %f %f %f %f %f %f",
00502     //            prev_vel_[0],
00503     //            prev_vel_[1],
00504     //            prev_vel_[2],
00505     //            prev_vel_[3],
00506     //            prev_vel_[4],
00507     //            prev_vel_[5]);
00508     //   }
00509     // if (current_acc.size() > 0) {
00510     //     ROS_INFO("current acc: %f %f %f %f %f %f",
00511     //            current_acc[0],
00512     //            current_acc[1],
00513     //            current_acc[2],
00514     //            current_acc[3],
00515     //            current_acc[4],
00516     //            current_acc[5]);
00517     //   }
00518 
00519     if (failed_to_send_packet)
00520     {
00521       ROS_WARN("  roundtrip: %f", roundtrip);
00522       setUDPTimeout((udp_timeout_ / 1000), (udp_timeout_ % 1000) * 1000);
00523 
00524       // print the angle
00525       // if (prev_angle_.size() > 0) {
00526       //   ROS_INFO("prev angle: %f %f %f %f %f %f",
00527       //            prev_angle_[0],
00528       //            prev_angle_[1],
00529       //            prev_angle_[2],
00530       //            prev_angle_[3],
00531       //            prev_angle_[4],
00532       //            prev_angle_[5]);
00533       // }
00534       // ROS_INFO("current angle: %f %f %f %f %f %f",
00535       //          current_angle[0],
00536       //          current_angle[1],
00537       //          current_angle[2],
00538       //          current_angle[3],
00539       //          current_angle[4],
00540       //          current_angle[5]);
00541     }
00542 
00543     // memoize prev angle
00544     for (size_t i = 0; i < 6; i++) {
00545         prev_angle_.at(i) = current_angle.at(i);
00546         prev_vel_.at(i) = current_vel.at(i);
00547         
00548     }
00549     return hr;
00550   }
00551 
00552   BCAP_HRESULT bCapFillBuffer()
00553   {
00554       ROS_WARN("try to fill buffer");
00555       BCAP_HRESULT hr;
00556       std::vector<double> cur_jnt;
00557       hr = bCapCurJnt(cur_jnt);
00558       BCAP_VARIANT vntPose, vntResult;
00559       vntPose.Type = VT_R8 | VT_ARRAY;
00560       vntPose.Arrays = 8;
00561       for (int i = 0; i < 8; i++)
00562       {
00563         vntPose.Value.DoubleArray[i] = cur_jnt[i];
00564       }
00565       // Fill the buffer for later use, 
00566       // unless fill the buffer, bCap slave will fall down 
00567       for (int i = 0; i < 4; i++) {
00568           hr = bCapRobotSlvMove(&vntPose, &vntResult);
00569           if (FAILED(hr)) {
00570             return hr;
00571           }
00572       }
00573   }
00574 
00575   BCAP_HRESULT bCapReflectRealState() {
00576       // fill ac
00577       std::vector<double> cur_jnt;
00578       BCAP_HRESULT hr;
00579       hr = bCapCurJnt(cur_jnt);
00580       int i = 0;
00581       for (OpenControllersInterface::TransmissionIterator it = cm_->model_.transmissions_.begin();
00582           it != cm_->model_.transmissions_.end(); ++it)
00583       { // *** js and ac must be consistent
00584         pr2_hardware_interface::Actuator *ac = hw_->getActuator((*it)->actuator_names_[0]);
00585         ac->state_.position_ = DEG2RAD(cur_jnt[i]); // degree -> radian
00586         i++;
00587       }
00588       return hr;
00589   }
00590 
00591   virtual void finalizeHW()
00592   {
00593     ROS_INFO("finalizeHW is called");
00594     if (!dryrunp_)
00595     {
00596       setUDPTimeout(2, 0);
00597       boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
00598       long lResult;
00599       BCAP_HRESULT hr = BCAP_S_OK;
00600       //bCapClearError();
00601 
00602       hr = bCapSlvChangeMode(0);
00603       if (FAILED(hr))
00604       {
00605         ROS_WARN("failed to change slave mode");
00606         SAFE_EXIT(1);
00607       }
00608 
00609       // disable logging mode
00610       // hr = bCapRobotExecute("stopLog", "");
00611       // if (FAILED(hr))
00612       // {
00613       //   ROS_WARN(failed to disable logging mode");
00614       // }
00615 
00616       hr = bCapMotor(false);
00617       if (FAILED(hr))
00618       {
00619         ROS_WARN("failed to motor off");
00620       }
00621       else
00622       {
00623         ROS_INFO("successed to motor off");
00624       }
00625       hr = bCapGiveArm();
00626       if (FAILED(hr))
00627       {
00628         ROS_WARN("failed to give arm");
00629       }
00630       else
00631       {
00632         ROS_INFO("successed to give arm");
00633       }
00634       hr = bCapReleaseRobot();
00635       if (FAILED(hr))
00636       {
00637         ROS_WARN("failed to release the robot");
00638       }
00639       else
00640       {
00641         ROS_INFO( "successed to release the robot");
00642       }
00643       hr = bCapControllerDisConnect();
00644       if (FAILED(hr))
00645       {
00646         ROS_WARN("failed to disconnect from the controller");
00647       }
00648       else
00649       {
00650         ROS_INFO("successed to disconnect from the controller");
00651       }
00652       /* Stop b-CAP service (Very important in UDP/IP connection) */
00653       hr = bCapServerStop();
00654       if (FAILED(hr))
00655       {
00656         ROS_WARN("failed to stop the service");
00657       }
00658       else
00659       {
00660         ROS_INFO("successed to stop the service");
00661       }
00662       boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
00663       hr = bCapClose();
00664       if (FAILED(hr))
00665       {
00666         ROS_WARN("failed to close bCap");
00667       }
00668       else
00669       {
00670         ROS_INFO("successed to close bCap");
00671       }
00672     }
00673     ROS_INFO("finalizing finished");
00674   }
00675 
00676   OpenControllersInterface::ControllerStatusPtr updateJoints(struct timespec* spec_result)
00677   {
00678     // build vntPose
00679     BCAP_VARIANT vntPose;
00680     vntPose.Type = VT_R8 | VT_ARRAY;
00681     vntPose.Arrays = 8;
00682     {
00683       int i = 0;
00684       for (OpenControllersInterface::TransmissionIterator it = cm_->model_.transmissions_.begin();
00685           it != cm_->model_.transmissions_.end(); ++it)
00686       { // *** js and ac must be consistent
00687         pr2_mechanism_model::JointState *js = cm_->state_->getJointState((*it)->joint_names_[0]);
00688         pr2_hardware_interface::Actuator *ac = hw_->getActuator((*it)->actuator_names_[0]);
00689         // ROS_INFO("js: %f, ac: %f", js->commanded_effort_, ac->state_.position_);
00690         double target_angle = RAD2DEG(ac->state_.position_);
00691         if (true)
00692         {
00693           target_angle = RAD2DEG(ac->state_.position_ + js->commanded_effort_);
00694           // check min/max
00695 #define SAFE_OFFSET_DEG 1
00696           if (RAD2DEG(cm_->state_->model_->robot_model_.getJoint((*it)->joint_names_[0])->limits->lower)
00697               + SAFE_OFFSET_DEG > target_angle)
00698           {
00699             ROS_WARN("too small joint angle! %f", target_angle);
00700             target_angle = RAD2DEG(
00701                 cm_->state_->model_->robot_model_.getJoint((*it)->joint_names_[0])->limits->lower) + SAFE_OFFSET_DEG;
00702           }
00703           else if (RAD2DEG(cm_->state_->model_->robot_model_.getJoint((*it)->joint_names_[0])->limits->upper)
00704               - SAFE_OFFSET_DEG < target_angle)
00705           {
00706             ROS_WARN("too large joint angle! %f", target_angle);
00707             target_angle = RAD2DEG(
00708                 cm_->state_->model_->robot_model_.getJoint((*it)->joint_names_[0])->limits->upper) - SAFE_OFFSET_DEG;
00709           }
00710           //ROS_INFO("target_angle: %f", target_angle);
00711         }
00712         else
00713         {
00714           target_angle = RAD2DEG(ac->state_.position_);
00715         }
00716         vntPose.Value.DoubleArray[i] = target_angle;
00717         i++;
00718       }
00719     }
00720     ROS_DEBUG("target  angles: %f %f %f %f %f %f", vntPose.Value.DoubleArray[0], vntPose.Value.DoubleArray[1], vntPose.Value.DoubleArray[2], vntPose.Value.DoubleArray[3], vntPose.Value.DoubleArray[4], vntPose.Value.DoubleArray[5]);
00721     vntPose.Value.DoubleArray[6] = 0;
00722     vntPose.Value.DoubleArray[7] = 0;
00723     // send vntPose
00724     DensoControllerStatusPtr status;
00725     BCAP_VARIANT vntReturn;
00726     if (!dryrunp_)
00727     {
00728       if (spec_result)
00729       {
00730         clock_gettime(CLOCK_REALTIME, spec_result);
00731       }
00732       // check bcap status beforehand
00733       u_int errorcode;
00734       errorcode = bCapGetErrorCode();
00735       if (FAILED(errorcode)) {
00736         ROS_WARN("bad status! robot needs recovery! hr: %02x", errorcode);
00737         status.reset(new DensoControllerStatus(errorcode));
00738         return boost::static_pointer_cast<OpenControllersInterface::ControllerStatus>(status);
00739       }
00740       BCAP_HRESULT hr = bCapRobotSlvMove(&vntPose, &vntReturn);
00741       ROS_DEBUG("updateJoints hr: %02x", hr);
00742       if (hr == 0xF200501)
00743       {
00744         ROS_DEBUG("buf is filled, it's fine.");
00745         status.reset(new DensoControllerStatus(BCAP_S_OK));
00746       }
00747       else if (FAILED(hr))
00748       {
00749         status.reset(new DensoControllerStatus(hr));
00750       }
00751       else
00752       {
00753         //status.reset(new DensoControllerStatus(BCAP_S_OK));
00754         //while (hr == 0 && g_halt_requested_ == false)
00755         //{
00756         //  // 0 means that there is an empty buffer
00757         //  ROS_WARN("buf space found, re-send the angles to the controller");
00758         //  if (spec_result)
00759         //  {
00760         //    clock_gettime(CLOCK_REALTIME, spec_result);
00761         //  }
00762         //  hr = bCapRobotSlvMove(&vntPose, &vntReturn);
00763         //  if (hr == 0xF200501)
00764         //  {
00765         //    ROS_WARN("buf is filled");
00766         //  }
00767         //}
00768         status.reset(new DensoControllerStatus(hr));
00769       }
00770     } else {
00771       // always return a healthy status when it's running in dryurun mode
00772       status.reset(new DensoControllerStatus(BCAP_S_OK));
00773       for (size_t i = 0; i < 16; i++) {
00774         vntReturn.Value.DoubleArray[i] = vntPose.Value.DoubleArray[i];
00775       }
00776 
00777     }
00778 
00779     ROS_DEBUG("current angles: %f %f %f %f %f %f", vntReturn.Value.DoubleArray[0], vntReturn.Value.DoubleArray[1], vntReturn.Value.DoubleArray[2], vntReturn.Value.DoubleArray[3], vntReturn.Value.DoubleArray[4], vntReturn.Value.DoubleArray[5]);
00780     hw_->current_time_ = ros::Time::now(); // ???
00781     {
00782       int i = 0;
00783       for (OpenControllersInterface::TransmissionIterator it = cm_->model_.transmissions_.begin();
00784           it != cm_->model_.transmissions_.end(); ++it)
00785       { // *** js and ac must be consistent
00786         pr2_mechanism_model::JointState *js = cm_->state_->getJointState((*it)->joint_names_[0]);
00787         pr2_hardware_interface::Actuator *ac = hw_->getActuator((*it)->actuator_names_[0]);
00788         ac->state_.velocity_ = DEG2RAD(prev_vel_.at(i));
00789         if (!dryrunp_)
00790         { // if not in the dryrun mode, we just copy the vntReturn value
00791           ac->state_.position_ = DEG2RAD(vntReturn.Value.DoubleArray[i]);
00792         }
00793         else
00794         { // if in the dryrun mode, we just copy the target value
00795           double target_angle = ac->state_.position_ + js->commanded_effort_;
00796           ac->state_.position_ = target_angle;
00797         }
00798         i++;
00799       }
00800     }
00801     return boost::static_pointer_cast<OpenControllersInterface::ControllerStatus>(status);
00802   }
00803 
00804 
00805   OpenControllersInterface::ControllerStatusPtr recoverController()
00806   {
00807 #define CAST_STATUS(hr) \
00808     boost::static_pointer_cast<OpenControllersInterface::ControllerStatus>(DensoControllerStatusPtr(new DensoControllerStatus(hr)))
00809 
00810     ROS_WARN("try to recover controller...");
00811     u_int errorcode;
00812     std::string errormsg;
00813 
00814     errorcode = bCapGetErrorCode();
00815     bCapErrorDescription(errormsg);
00816     
00817     ROS_INFO("errormsg: %s", errormsg.c_str());
00818 
00819     if (errorcode == BCAP_E_UNEXPECTED)
00820     {
00821       ROS_FATAL("Unexpected Error occured. no way to recover!");
00822       return CAST_STATUS(errorcode);
00823     }
00824 
00825     if (errorcode >= 0x83204071 && errorcode <= 0x83204078)
00826     {
00827       ROS_INFO("joint angle is over the software limit.");
00828       ROS_INFO("currently, there is no way to recover, quit.");
00829       // TODO publish message and return healthy status so that an application can send recovery-trajectory.
00830       return CAST_STATUS(BCAP_E_FAIL);
00831     }
00832     if (errorcode >= 0x84204081 && errorcode <= 0x842040A8)
00833     {
00834       ROS_INFO("joint angle velocity is over the software limit.");
00835       ROS_INFO("currently, there is no way to recover, quit.");
00836       // TODO publish message and return healthy status so that an application can send recovery-trajectory.
00837       return CAST_STATUS(BCAP_E_FAIL);
00838     }
00839     if (errorcode >= 0x84204051 && errorcode <= 0x84204058)
00840     {
00841       ROS_INFO("joint angle velocity(sent) is over the software limit.");
00842       //ROS_INFO("currently, there is no way to recover, quit.");
00843       //return CAST_STATUS(BCAP_E_FAIL);
00844       // TODO publish message and return healthy status so that an application can send recovery-trajectory.
00845       BCAP_HRESULT hr;
00846       hr = bCapClearError();
00847       if (FAILED(hr)) {
00848           ROS_WARN("failed to clear error %02x", hr);
00849           return CAST_STATUS(hr);
00850       }
00851       hr = bCapGiveArm();
00852       if (FAILED(hr)) {
00853           ROS_WARN("failed to give arm %02x", hr);
00854           return CAST_STATUS(hr);
00855       }
00856       //hr = bCap_RobotRelease(iSockFD_, lhRobot_); /* Release robot handle */
00857       //if (FAILED(hr))
00858       //{
00859       //  ROS_WARN("failed to release the robot");
00860       //}
00861       //hr = bCapGetRobot();
00862       //if (FAILED(hr)) {
00863       //    ROS_WARN("failed to get robot %02x", hr);
00864       //    return CAST_STATUS(hr);
00865       //}
00866       boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
00867       hr = bCapTakearm();
00868       if (FAILED(hr)) {
00869           ROS_WARN("failed to take arm %02x", hr);
00870           return CAST_STATUS(hr);
00871       }
00872       hr = bCapMotor(true);
00873       if (FAILED(hr)) {
00874           ROS_WARN("failed to turn on motor %02x", hr);
00875           return CAST_STATUS(hr);
00876       }
00877       hr = bCapSlvChangeMode(0x202);
00878       if (FAILED(hr)) {
00879           ROS_WARN("failed to change to slvmode %02x", hr);
00880           return CAST_STATUS(hr);
00881       }
00882       return CAST_STATUS(BCAP_S_OK);
00883     }
00884     if (errorcode >= 0x84204041 && errorcode <= 0x84204048)
00885     {
00886       ROS_INFO("joint angle acceleration is over the software limit.");
00887       ROS_INFO("currently, there is no way to recover, quit.");
00888       // TODO publish message and return healthy status so that an application can send recovery-trajectory.
00889       return CAST_STATUS(BCAP_E_FAIL);
00890     }
00891 
00892 
00893     if (errorcode == 0x83204231)
00894     {
00895       ROS_INFO("invalid command was sent and everything stopped, needs to restart everything");
00896       //TODO restart everything
00897       return CAST_STATUS(BCAP_E_FAIL);
00898     }
00899 
00900     if (errorcode == 0x81501003)
00901     {
00902       ROS_INFO("motor is off, turn on");
00903       BCAP_HRESULT hr = bCapMotor(true);
00904       return CAST_STATUS(hr);
00905     }
00906 
00907     if (errorcode == 0x84201482)
00908     {
00909       // error: postion buffer is empty.
00910       //BCAP_HRESULT hr = bCapFillBuffer(); // this does not work
00911       // now completely restart bcap things
00912       BCAP_HRESULT hr;
00913       hr = bCapMotor(false);
00914       if (FAILED(hr)) {
00915         ROS_WARN("failed to turn off motor %02x", hr);
00916         return CAST_STATUS(hr);
00917       }
00918       hr = bCapGiveArm();
00919       if (FAILED(hr)) {
00920         ROS_WARN("failed to give arm %02x", hr);
00921         return CAST_STATUS(hr);
00922       }
00923       hr = bCapReleaseRobot();
00924       if (FAILED(hr)) {
00925         ROS_WARN("failed to release robot %02x", hr);
00926         return CAST_STATUS(hr);
00927       }
00928       hr = bCapControllerDisConnect();
00929       if (FAILED(hr)) {
00930         ROS_WARN("failed to disconnect controller %02x", hr);
00931         return CAST_STATUS(hr);
00932       }
00933       hr = bCapServerStop();
00934       if (FAILED(hr)) {
00935         ROS_WARN("failed to stop bcap service %02x", hr);
00936         return CAST_STATUS(hr);
00937       }
00938       boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
00939       hr = bCapClose();
00940       if (FAILED(hr)) {
00941         ROS_WARN("failed to close bcap socket %02x", hr);
00942         return CAST_STATUS(hr);
00943       }
00944       hr = bCapOpen();
00945       if (FAILED(hr)) {
00946         ROS_WARN("failed to open socket %02x", hr);
00947         return CAST_STATUS(hr);
00948       }
00949       setUDPTimeout(2, 0); // 2000msec
00950       hr = bCapServerStart();
00951       if (FAILED(hr)) {
00952         ROS_WARN("failed to start service %02x", hr);
00953         return CAST_STATUS(hr);
00954       }
00955       hr = bCapControllerConnect();
00956       if (FAILED(hr)) {
00957         ROS_WARN("failed to connect controller %02x", hr);
00958         return CAST_STATUS(hr);
00959       }
00960       hr = bCapClearError();
00961       if (FAILED(hr)) {
00962         ROS_WARN("failed to clear error %02x", hr);
00963         return CAST_STATUS(hr);
00964       }
00965       hr = bCapGetRobot();
00966       if (FAILED(hr)) {
00967         ROS_WARN("failed to get robot %02x", hr);
00968         return CAST_STATUS(hr);
00969       }
00970       hr = bCapTakearm();
00971       if (FAILED(hr)) {
00972         ROS_WARN("failed to take arm %02x", hr);
00973         return CAST_STATUS(hr);
00974       }
00975       hr = bCapMotor(true);
00976       if (FAILED(hr))
00977       {
00978         ROS_WARN("failed to turn on motor %02x", hr);
00979         return CAST_STATUS(hr);
00980       }
00981       hr = bCapRobotExecute("clearLog", "");
00982       if (FAILED(hr))
00983       {
00984         ROS_FATAL("failed to clear logging");
00985         return CAST_STATUS(hr);
00986       }
00987       hr = bCapSlvChangeMode(0x202);
00988       if (FAILED(hr))
00989       {
00990         ROS_FATAL("failed to change slave mode");
00991         return CAST_STATUS(hr);
00992       }
00993       hr = bCapFillBuffer();
00994       if (FAILED(hr))
00995       {
00996         ROS_FATAL("failed to fill bcap buffer");
00997         return CAST_STATUS(hr);
00998       }
00999       hr = bCapReflectRealState();
01000       if (FAILED(hr))
01001       {
01002         ROS_FATAL("failed to reflect real robot state into controller manager");
01003         return CAST_STATUS(hr);
01004       }
01005       setUDPTimeout((udp_timeout_ / 1000), (udp_timeout_ % 1000) * 1000);
01006 
01007       return CAST_STATUS(hr);
01008     }
01009 
01010     if (errorcode == 0x84201486)
01011     {
01012         u_int mode;
01013         boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
01014         while(!g_quit_)
01015         {
01016             mode = bCapGetMode();
01017             if (mode != 3) {
01018               // user set controller to manual or teachcheck mode, wait until the user set back to auto
01019               ROS_WARN("waiting until you set back to auto");
01020               boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
01021             } else {
01022               bool estop = bCapGetEmergencyStop();
01023               if (estop) {
01024                 ROS_WARN("please turn off emergency stop");
01025                 boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
01026                 continue;
01027               } else {
01028                 break;
01029               }
01030             }
01031         }
01032         //TODO restart bcap server
01033         BCAP_HRESULT hr;
01034         hr = bCapControllerConnect();
01035         if (FAILED(hr)) {
01036           ROS_WARN("failed to connect controller %02x", hr);
01037           return CAST_STATUS(hr);
01038         }
01039         hr = bCapClearError();
01040         if (FAILED(hr)) {
01041           ROS_WARN("failed to clear error %02x", hr);
01042           return CAST_STATUS(hr);
01043         }
01044         hr = bCapGiveArm();
01045         if (FAILED(hr)) {
01046           ROS_WARN("failed to give arm %02x", hr);
01047           return CAST_STATUS(hr);
01048         }
01049         hr = bCapGetRobot();
01050         if (FAILED(hr)) {
01051           ROS_WARN("failed to get robot %02x", hr);
01052           return CAST_STATUS(hr);
01053         }
01054         boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
01055         hr = bCapTakearm();
01056         if (FAILED(hr)) {
01057           ROS_WARN("failed to take arm %02x", hr);
01058           return CAST_STATUS(hr);
01059         }
01060         hr = bCapMotor(true);
01061         if (FAILED(hr)) {
01062           ROS_WARN("failed to turn on motor %02x", hr);
01063           return CAST_STATUS(hr);
01064         }
01065         hr = bCapSlvChangeMode(0x202);
01066         if (FAILED(hr)) {
01067           ROS_WARN("failed to change to slvmode %02x", hr);
01068           return CAST_STATUS(hr);
01069         }
01070         hr = bCapFillBuffer();
01071         if (FAILED(hr)) {
01072           ROS_WARN("failed to fill buffer in slave mode");
01073           return CAST_STATUS(hr);
01074         }
01075         hr = bCapReflectRealState();
01076         if (FAILED(hr)) {
01077           ROS_WARN("failed to reflect real state");
01078           return CAST_STATUS(hr);
01079         }
01080         return CAST_STATUS(BCAP_S_OK);
01081     }
01082     if (errorcode == 0x83500121)
01083     {
01084       ROS_INFO("robot is not in slavemode, try to change it");
01085       BCAP_HRESULT hr;
01086       hr = bCapClearError();
01087       if (FAILED(hr)) return CAST_STATUS(hr);
01088       hr = bCapMotor(true);
01089       if (FAILED(hr)) {
01090         ROS_WARN("failed to turn on motor, cannot recover");
01091         return CAST_STATUS(hr);
01092       }
01093       hr = bCapRobotExecute("clearLog", "");
01094       if (FAILED(hr)) {
01095         ROS_WARN("failed to clear log");
01096         return CAST_STATUS(hr);
01097       }
01098       hr = bCapSlvChangeMode(0x202);
01099       if (FAILED(hr)) {
01100         ROS_WARN("failed to change slvmode, cannot recover");
01101         return CAST_STATUS(hr);
01102       }
01103       hr = bCapFillBuffer();
01104       if (FAILED(hr)) {
01105         ROS_WARN("failed to fill buffer in slave mode");
01106         return CAST_STATUS(hr);
01107       }
01108       hr = bCapReflectRealState();
01109       if (FAILED(hr)) {
01110         ROS_WARN("failed to reflect real state");
01111         return CAST_STATUS(hr);
01112       }
01113       return CAST_STATUS(hr);
01114     }
01115     if (errorcode == 0x83501032)
01116     {
01117       //TODO rethink the way to recover
01118       ROS_INFO("invalid command when the robot is in slave mode, disable slave mode");
01119       BCAP_HRESULT hr = bCapSlvChangeMode(0);
01120       return CAST_STATUS(hr);
01121     }
01122 
01123     if (errorcode == 0x81501025)
01124     {
01125       ROS_INFO("do not send message while an error is occuring");
01126       BCAP_HRESULT hr = bCapClearError();
01127       return CAST_STATUS(hr);
01128     }
01129 
01130     return CAST_STATUS(BCAP_S_OK);
01131 #undef CAST_STATUS(hr)
01132   }
01133  
01134   void setUDPTimeout(long sec, long usec)
01135   {
01136 #ifdef BCAP_CONNECTION_UDP
01137     struct timeval tv;
01138     tv.tv_sec = sec;
01139     tv.tv_usec = usec;
01140     if (setsockopt(iSockFD_, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
01141     {
01142       ROS_WARN("Failed to set send timeout");
01143     }
01144     if (setsockopt(iSockFD_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
01145     {
01146       ROS_WARN("Failed to set recv timeout");
01147     }
01148 #endif
01149   }
01150 
01151   BCAP_HRESULT bCapServerStart()
01152   {
01153     BCAP_HRESULT hr = bCap_ServiceStart(iSockFD_); /* Start b-CAP service */
01154     return hr;
01155   }
01156   BCAP_HRESULT bCapServerStop()
01157   {
01158     BCAP_HRESULT hr = bCap_ServiceStop(iSockFD_); /* Start b-CAP service */
01159     return hr;
01160   }
01161 
01165   void initializeCM()
01166   {
01167     hw_ = new pr2_hardware_interface::HardwareInterface();
01168     hw_->addActuator(new pr2_hardware_interface::Actuator("j1_motor"));
01169     hw_->addActuator(new pr2_hardware_interface::Actuator("j2_motor"));
01170     hw_->addActuator(new pr2_hardware_interface::Actuator("j3_motor"));
01171     hw_->addActuator(new pr2_hardware_interface::Actuator("j4_motor"));
01172     hw_->addActuator(new pr2_hardware_interface::Actuator("j5_motor"));
01173     hw_->addActuator(new pr2_hardware_interface::Actuator("flange_motor"));
01174     // // Create controller manager
01175     //pr2_controller_manager::ControllerManager cm_(ec.hw_);
01176     cm_ = boost::shared_ptr<pr2_controller_manager::ControllerManager>(
01177         new pr2_controller_manager::ControllerManager(hw_));
01178   }
01179 
01183   void initializeHW()
01184   {
01185     // for denso connection
01186     if (!dryrunp_)
01187     {
01188       BCAP_HRESULT hr;
01189       ROS_INFO("bCapOpen");
01190       hr = bCapOpen();
01191       if(FAILED(hr))
01192       {
01193         ROS_FATAL("failed to open bCap socket. Exitting...");
01194         ROS_FATAL("make sure that your robot is connected to %s:%d", server_ip_address_.c_str(), server_port_number_);
01195         exit(1);
01196       }
01197       setUDPTimeout(2, 0); // 2000msec
01198       ROS_INFO("bCapServerStart");
01199       hr = bCapServerStart();
01200       if(FAILED(hr))
01201       {
01202         ROS_FATAL("failed to start bCap server. Exitting...");
01203         exit(1);
01204       }
01205       ROS_INFO("bCapControllerConnect");
01206       hr = bCapControllerConnect();
01207       if(FAILED(hr))
01208       {
01209         ROS_FATAL("failed to connect bCap controller. Exitting...");
01210         exit(1);
01211       }
01212       ROS_INFO("bCapClearError");
01213       hr = bCapClearError();
01214       if(FAILED(hr))
01215       {
01216         ROS_FATAL("failed to clear bCap error. Exitting...");
01217         exit(1);
01218       }
01219       ROS_INFO("bCapGetRobot");
01220       hr = bCapGetRobot();
01221       if(FAILED(hr))
01222       {
01223         ROS_FATAL("failed to get bCap robot. Exitting...");
01224         exit(1);
01225       }
01226       ROS_INFO("bCapTakearm");
01227       hr = bCapTakearm();
01228       if(FAILED(hr))
01229       {
01230         ROS_FATAL("failed to take bCap arm. Exitting...");
01231         exit(1);
01232       }
01233       ROS_INFO("bCapSetExternalSpeed");
01234       hr = bCapSetExternalSpeed(100.0);
01235       if(FAILED(hr))
01236       {
01237         ROS_FATAL("failed to set external speed. Exitting...");
01238         exit(1);
01239       }
01240 
01241       bCapInitializeVariableHandlers();
01242 
01243       {
01244         ROS_WARN("bCapMotor On");
01245         hr = bCapMotor(true);
01246         if (FAILED(hr))
01247         {
01248           u_int errorcode;
01249           std::string errormsg;
01250           errorcode = bCapGetErrorCode();
01251           bCapErrorDescription(errormsg);
01252           ROS_INFO("errormsg: %s", errormsg.c_str());
01253           ROS_WARN("failed to motor on, errorcode: %02x, errormsg: %s", errorcode, errormsg.c_str());
01254           //ROS_FATAL("failed to motor on");
01255           finalize();
01256           SAFE_EXIT(1);
01257         }
01258       }
01259 
01260       // enable logging
01261       hr = bCapRobotExecute("clearLog", "");
01262       if (FAILED(hr))
01263       {
01264         ROS_FATAL("failed to enable logging mode");
01265         SAFE_EXIT(1);
01266       }
01267 
01268       // enable logging
01269       // {
01270       //   BCAP_HRESULT hr = bCapRobotExecute("startLog", "");
01271       //   if (FAILED(hr)) {
01272       //     ROS_FATAL("failed to start logging mode");
01273       //     SAFE_EXIT(1);
01274       //   }
01275       // }
01276 
01277       hr = bCapSlvChangeMode(0x202);
01278       //BCAP_HRESULT hr = bCapSlvChangeMode((char*)"258"); // 0x102
01279       if (FAILED(hr))
01280       {
01281         ROS_FATAL("failed to change slave mode");
01282         SAFE_EXIT(1);
01283       }
01284 
01285       ROS_INFO("initialize bCap slave connection");
01286       hr = bCapFillBuffer();
01287       if (FAILED(hr))
01288       {
01289         ROS_FATAL("failed to fill bcap buffer");
01290         SAFE_EXIT(1);
01291       }
01292       ROS_INFO("bCap slave initialization done");
01293 
01294       hr = bCapReflectRealState();
01295       if (FAILED(hr))
01296       {
01297         ROS_FATAL("failed to reflect real robot state into controller manager");
01298         SAFE_EXIT(1);
01299       }
01300       setUDPTimeout((udp_timeout_ / 1000), (udp_timeout_ % 1000) * 1000);
01301     }
01302   }
01303 
01304   void initializeROS(ros::NodeHandle& node)
01305   {
01306     //TODO (Trivial) Since all of the tasks done within this method don't seem to be ROS-specific,
01307     //     moving them to somewhere else might make more sense.
01308 
01309     // Determine ip address of the robot's embedded machine.
01310     if (!node.getParam("server_ip", server_ip_address_))
01311     {
01312       server_ip_address_ = (char*)DEFAULT_SERVER_IP_ADDRESS;
01313     }
01314 
01315     // Determine the pre-set port number used to communicate the robot's embedded computer via bCap.
01316     if (!node.getParam("server_port", server_port_number_))
01317     {
01318       server_port_number_ = DEFAULT_SERVER_PORT_NUM;
01319     }
01320 
01321     if (!dryrunp_)
01322     {
01323       ROS_INFO("server: %s:%d", server_ip_address_.c_str(), server_port_number_);
01324     }
01325 
01326     // Determine the pre-set UDP timeout length.
01327     if (!node.getParam("udp_timeout", udp_timeout_))
01328     {
01329       udp_timeout_ = DEFAULT_UDP_TIMEOUT;
01330     }
01331     if (!dryrunp_)
01332     {
01333       ROS_INFO("udp_timeout: %d micro sec", udp_timeout_);
01334     }
01335   }
01336 
01337   void quitRequest()
01338   {
01339     ROS_INFO("denso_controller received a quit request");
01340     OpenController::quitRequest(); // call super class
01341     ros::shutdown();
01342   }
01343 };
01344 
01345 DensoController g_controller;
01346 void quitRequested(int sigint)
01347 {
01348   // do nothing
01349   ROS_WARN("request quit to denso controller using signal");
01350   g_controller.quitRequest();
01351 }
01352 
01353 int main(int argc, char *argv[])
01354 {
01355   // Keep the kernel from swapping us out
01356   OpenControllersInterface::OpenController::initRT();
01357 
01358   // Initialize ROS and parse command-line arguments
01359   ros::init(argc, argv, "denso_controller",
01360             // quitRequested is used as a SIGINT handler instead of the handler prepared by ROS.
01361             ros::init_options::NoSigintHandler);
01362   // Parse options
01363   //g_options.program_ = argv[0];
01364   g_controller.parseArguments(argc, argv);
01365   if (optind < argc)
01366   {
01367     g_controller.Usage("Extra arguments");
01368   }
01369 
01370   // do these work?
01371   signal(SIGTERM, quitRequested);
01372   signal(SIGINT, quitRequested);
01373   signal(SIGHUP, quitRequested);
01374   int rv = 1;
01375   // Set up realtime context, start ROS processes, load robot description.
01376   g_controller.initialize();
01377   boost::thread t(&DensoController::start, &g_controller);
01378   {
01379     OpenControllersInterface::Finalizer finalizer(&g_controller);
01380     ros::Rate loop_rate(100);
01381     while (ros::ok())
01382     {
01383       ros::spinOnce();
01384       loop_rate.sleep();
01385     }
01386     ROS_WARN("ROS has been terminated");
01387     t.join();
01388     ROS_WARN("start thread has been terminated");
01389   }
01390 
01391   g_controller.cleanupPidFile();
01392   return 0;
01393 }
01394 


denso_controller
Author(s): Ryohei Ueda
autogenerated on Thu Jun 6 2019 20:15:19