00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 #include <mtconnect_state_machine/state_machine.h>
00018 #include <mtconnect_state_machine/utilities.h>
00019 #include <industrial_robot_client/utils.h>
00020 
00021 using namespace mtconnect_state_machine;
00022 
00023 static const std::string PARAM_TASK_DESCRIPTION = "task_description";
00024 static const std::string PARAM_FORCE_FAULT_STATE = "force_fault";
00025 static const std::string PARAM_STATE_OVERRIDE = "state_override";
00026 static const std::string PARAM_LOOP_RATE = "loop_rate";
00027 static const std::string PARAM_CHECK_ENABLED = "home_check";
00028 static const std::string PARAM_HOME_TOL = "home_tol";
00029 static const std::string PARAM_MAT_STATE = "material_state";
00030 static const std::string KEY_HOME_POSITION = "home";
00031 
00032 
00033 static const std::string KEY_JM_HOME_TO_APPROACH = "JM_HOME_TO_APPROACH";
00034 static const std::string KEY_JM_APPROACH_TO_PICK = "JM_APPROACH_TO_PICK";
00035 static const std::string KEY_JM_PICK_TO_CHUCK = "JM_PICK_TO_CHUCK";
00036 static const std::string KEY_JM_CHUCK_TO_DOOR = "JM_CHUCK_TO_DOOR";
00037 static const std::string KEY_JM_DOOR_TO_HOME = "JM_DOOR_TO_HOME";
00038 
00039 
00040 static const std::string KEY_JM_HOME_TO_DOOR = "JM_HOME_TO_DOOR";
00041 static const std::string KEY_JM_DOOR_TO_CHUCK = "JM_DOOR_TO_CHUCK";
00042 static const std::string KEY_JM_CHUCK_TO_DROP = "JM_CHUCK_TO_DROP";
00043 static const std::string KEY_JM_DROP_TO_HOME = "JM_DROP_TO_HOME";
00044 
00045 static const std::string DEFAULT_GRASP_ACTION = "gripper_action_service";
00046 static const std::string DEFAULT_VISE_ACTION = "vise_action_service";
00047 static const std::string DEFAULT_MATERIAL_LOAD_ACTION = "material_load_action";
00048 static const std::string DEFAULT_MATERIAL_UNLOAD_ACTION = "material_unload_action";
00049 static const std::string DEFAULT_CNC_OPEN_DOOR_ACTION = "cnc_open_door_action";
00050 static const std::string DEFAULT_CNC_CLOSE_DOOR_ACTION = "cnc_close_door_action";
00051 static const std::string DEFAULT_CNC_OPEN_CHUCK_ACTION = "cnc_open_chuck_action";
00052 static const std::string DEFAULT_CNC_CLOSE_CHUCK_ACTION = "cnc_close_chuck_action";
00053 static const std::string DEFAULT_JOINT_TRAJ_ACTION = "joint_trajectory_action";
00054 static const std::string DEFAULT_ROBOT_STATES_TOPIC = "robot_states";
00055 static const std::string DEFAULT_ROBOT_SPINDLE_TOPIC = "robot_spindle";
00056 static const std::string DEFAULT_ROBOT_STATUS_TOPIC = "robot_status";
00057 static const std::string DEFAULT_JOINT_STATE_TOPIC = "joint_states";
00058 static const std::string DEFAULT_SM_STATUS_TOPIC = "state_machine_status";
00059 static const std::string DEFAULT_EXTERNAL_COMMAND_SERVICE = "external_command";
00060 static const std::string DEFAULT_MATERIAL_LOAD_SET_STATE_SERVICE = "/MaterialLoad/set_mtconnect_state";
00061 static const std::string DEFAULT_MATERIAL_UNLOAD_SET_STATE_SERVICE = "/MaterialUnload/set_mtconnect_state";
00062 static const std::string DEFAULT_TRAJECTORY_FILTER_SERVICE = "filter_trajectory_with_constraints";
00063 
00064 static const std::string MTCONNECT_ACTION_ACTIVE_FLAG = "ACTIVE";
00065 
00066 
00067 typedef mtconnect_msgs::SetMTConnectState::Request MtConnectState;
00068 
00069 StateMachine::StateMachine() :
00070     nh_()
00071 {
00072   
00073   state_ = StateTypes::INVALID;
00074   loop_rate_ = 0;
00075   home_check_ = false;
00076   home_tol_ = 0.0;
00077   cycle_stop_req_= false;
00078   material_state_ = false;
00079   material_load_state_ = mtconnect_msgs::SetMTConnectState::Request::NOT_READY;
00080 }
00081 
00082 StateMachine::~StateMachine()
00083 {
00084 
00085 }
00086 
00087 bool StateMachine::init()
00088 {
00089   ros::NodeHandle ph("~");
00090   std::string task_desc;
00091 
00092   if (!ph.getParam(PARAM_LOOP_RATE, loop_rate_))
00093   {
00094     ROS_WARN_STREAM("Param: " << PARAM_LOOP_RATE << " not set, using default");
00095     loop_rate_ = 10;
00096   }
00097   if (!ph.getParam(PARAM_CHECK_ENABLED, home_check_))
00098   {
00099     ROS_WARN_STREAM("Param: " << PARAM_CHECK_ENABLED << "not set, setting enabled");
00100     home_check_ = true;
00101   }
00102   if (!ph.getParam(PARAM_HOME_TOL, home_tol_))
00103   {
00104     ROS_WARN_STREAM("Param: " << PARAM_HOME_TOL << " not set, using default");
00105     home_tol_ = 0.1; 
00106   }
00107   if (!ph.getParam(PARAM_TASK_DESCRIPTION, task_desc))
00108   {
00109     ROS_ERROR("Failed to load task description parameter");
00110     return false;
00111   }
00112 
00113   std::map<std::string, boost::shared_ptr<mtconnect::JointPoint> > points;
00114   if (!parseTaskXml(task_desc, joint_paths_, points))
00115   {
00116     ROS_ERROR("Failed to parse xml");
00117     return false;
00118   }
00119 
00120   if (points.empty())
00121   {
00122     ROS_ERROR("Failed to find defined points");
00123     return false;
00124   }
00125 
00126   ROS_INFO_STREAM("Adding home position from task description");
00127   home_ = points[KEY_HOME_POSITION];
00128   if (home_->values_.empty())
00129   {
00130     ROS_ERROR("Home position is empty, failed to load home");
00131     return false;
00132   }
00133 
00134   
00135   material_load_server_ptr_ = MaterialLoadServerPtr(new MaterialLoadServer(nh_, DEFAULT_MATERIAL_LOAD_ACTION, false));
00136   material_load_server_ptr_->registerGoalCallback(boost::bind(&StateMachine::materialLoadGoalCB, this));
00137   material_unload_server_ptr_ = MaterialUnloadServerPtr(
00138       new MaterialUnloadServer(nh_, DEFAULT_MATERIAL_UNLOAD_ACTION, false));
00139   material_unload_server_ptr_->registerGoalCallback(boost::bind(&StateMachine::materialUnloadGoalCB, this));
00140 
00141   
00142   open_door_client_ptr_ = CncOpenDoorClientPtr(new CncOpenDoorClient(DEFAULT_CNC_OPEN_DOOR_ACTION, false));
00143   close_door_client_ptr_ = CncCloseDoorClientPtr(new CncCloseDoorClient(DEFAULT_CNC_CLOSE_DOOR_ACTION, false));
00144   open_chuck_client_ptr_ = CncOpenChuckClientPtr(new CncOpenChuckClient(DEFAULT_CNC_OPEN_CHUCK_ACTION, false));
00145   close_chuck_client_ptr_ = CncCloseChuckClientPtr(new CncCloseChuckClient(DEFAULT_CNC_CLOSE_CHUCK_ACTION, false));
00146   grasp_action_client_ptr_ = GraspActionClientPtr(new GraspActionClient(DEFAULT_GRASP_ACTION, false));
00147   vise_action_client_ptr_ = GraspActionClientPtr(new GraspActionClient(DEFAULT_VISE_ACTION, false));
00148   joint_traj_client_ptr_ = JointTractoryClientPtr(new JointTractoryClient(DEFAULT_JOINT_TRAJ_ACTION, false));
00149 
00150   
00151   robot_states_pub_ = nh_.advertise<mtconnect_msgs::RobotStates>(DEFAULT_ROBOT_STATES_TOPIC, 1);
00152   robot_spindle_pub_ = nh_.advertise<mtconnect_msgs::RobotSpindle>(DEFAULT_ROBOT_SPINDLE_TOPIC, 1);
00153   state_machine_pub_ = nh_.advertise<mtconnect_example_msgs::StateMachineStatus>(DEFAULT_SM_STATUS_TOPIC, 1);
00154 
00155   
00156   robot_status_sub_ = nh_.subscribe(DEFAULT_ROBOT_STATUS_TOPIC, 1, &StateMachine::robotStatusCB, this);
00157   joint_states_sub_ = nh_.subscribe(DEFAULT_JOINT_STATE_TOPIC, 1, &StateMachine::jointStatesCB, this);
00158 
00159   
00160   external_command_srv_ = nh_.advertiseService(DEFAULT_EXTERNAL_COMMAND_SERVICE, &StateMachine::externalCommandCB,
00161                                                this);
00162 
00163   
00164   material_load_set_state_client_ = nh_.serviceClient<mtconnect_msgs::SetMTConnectState>(
00165       DEFAULT_MATERIAL_LOAD_SET_STATE_SERVICE);
00166   material_unload_set_state_client_ = nh_.serviceClient<mtconnect_msgs::SetMTConnectState>(
00167       DEFAULT_MATERIAL_UNLOAD_SET_STATE_SERVICE);
00168 
00169   trajectory_filter_client_ = nh_.serviceClient<arm_navigation_msgs::FilterJointTrajectoryWithConstraints>(
00170       DEFAULT_TRAJECTORY_FILTER_SERVICE);
00171 
00172   
00173   material_load_server_ptr_->start();
00174   material_unload_server_ptr_->start();
00175 
00176   setState(StateTypes::IDLE);
00177 
00178   return true;
00179 
00180 }
00181 
00182 void StateMachine::run()
00183 {
00184   ROS_INFO_STREAM("Entering blocking run");
00185   ros::Rate r(loop_rate_);
00186   while (ros::ok())
00187   {
00188     
00189     runOnce();
00190     callPublishers();
00191     ros::spinOnce();
00192     errorChecks();
00193     overrideChecks();
00194     
00195     r.sleep();
00196   }
00197 
00198 }
00199 
00200 void StateMachine::runOnce()
00201 {
00202   
00203   MaterialLoadServer::Result load_res;
00204   MaterialUnloadServer::Result unload_res;
00205 
00206   switch (state_)
00207   {
00208     case StateTypes::IDLE:
00209       break;
00210 
00211     case StateTypes::INITING:
00212       setState(StateTypes::CHECK_HOME);
00213       break;
00214 
00215     case StateTypes::CHECK_HOME:
00216       if ( isHome())
00217       {
00218         ROS_INFO_STREAM("Robot start home check passed");
00219         setState(StateTypes::WAIT_FOR_ACTIONS);
00220       }
00221       else
00222       {
00223         ROS_ERROR_STREAM("Robot not in home state on start");
00224         setState(StateTypes::ABORTING);
00225       }
00226       break;
00227 
00228     case StateTypes::WAIT_FOR_ACTIONS:
00229       if (areActionsReady())
00230       {
00231         setState(StateTypes::WAIT_FOR_SERVICES);
00232       }
00233       else
00234       {
00235         ROS_INFO_STREAM_THROTTLE(20, "Waiting for actions to be ready");
00236       }
00237       break;
00238 
00239     case StateTypes::WAIT_FOR_SERVICES:
00240       if (areServicesReady())
00241       {
00242         setState(StateTypes::SET_MAT_ACTIONS_READY);
00243       }
00244       else
00245       {
00246         ROS_INFO_STREAM_THROTTLE(20, "Waiting for services to be ready");
00247       }
00248       break;
00249 
00250     case StateTypes::SET_MAT_ACTIONS_READY:
00251       if (setMatActionsReady())
00252       {
00253         setState(StateTypes::WAITING);
00254       }
00255       else
00256       {
00257         ROS_ERROR("Failed to set actions ready, aborting");
00258         setState(StateTypes::ABORTING);
00259       }
00260       break;
00261 
00262     case StateTypes::WAITING:
00263       ROS_INFO_STREAM_THROTTLE(20, "Waiting for request");
00264       if(cycle_stop_req_)
00265       {
00266         cycle_stop_req_ = false;
00267         setState(StateTypes::STOPPING);
00268       }
00269       if(material_state_)
00270       {
00271         if(material_load_state_ != mtconnect_msgs::SetMTConnectState::Request::READY)
00272         {
00273           ROS_INFO_STREAM("Material present, updating material load to READY");
00274           setMatLoad(mtconnect_msgs::SetMTConnectState::Request::READY);
00275         }
00276       }
00277       else
00278       {
00279         if(material_load_state_ != mtconnect_msgs::SetMTConnectState::Request::NOT_READY)
00280         {
00281           ROS_INFO_STREAM("Material no present, updating material load to NOT READY");
00282           setMatLoad(mtconnect_msgs::SetMTConnectState::Request::NOT_READY);
00283         }
00284       }
00285       break;
00286 
00287     case StateTypes::MATERIAL_LOADING:
00288       ROS_INFO_STREAM("++++++++++++++++++++++++ LOADING MATERIAL ++++++++++++++++++++++++");
00289       setState(StateTypes::ML_MOVE_PICK_APPROACH);
00290       break;
00291 
00292     case StateTypes::ML_MOVE_PICK_APPROACH:
00293       moveArm(KEY_JM_HOME_TO_APPROACH);
00294       openGripper();
00295       openDoor();
00296       setState(StateTypes::ML_WAIT_MOVE_PICK_APPROACH);
00297       break;
00298 
00299     case StateTypes::ML_WAIT_MOVE_PICK_APPROACH:
00300       if (isMoveDone() && isGripperOpened())
00301       {
00302         setState(StateTypes::ML_MOVE_PICK);
00303       }
00304       break;
00305 
00306     case StateTypes::ML_MOVE_PICK:
00307       moveArm(KEY_JM_APPROACH_TO_PICK);
00308       setState(StateTypes::ML_WAIT_MOVE_PICK);
00309       break;
00310 
00311     case StateTypes::ML_WAIT_MOVE_PICK:
00312       if (isMoveDone())
00313       {
00314         setState(StateTypes::ML_PICK);
00315       }
00316       break;
00317 
00318     case StateTypes::ML_PICK:
00319       if(material_state_)
00320       {
00321         closeGripper();
00322         setState(StateTypes::ML_WAIT_PICK);
00323       }
00324       else
00325       {
00326         ROS_ERROR_STREAM("Unexpected out of material during pick, aborting");
00327         setState(StateTypes::ABORTING);
00328       }
00329       break;
00330 
00331     case StateTypes::ML_WAIT_PICK:
00332       if (isGripperClosed() && isDoorOpened())
00333       {
00334         setState(StateTypes::ML_MOVE_CHUCK);
00335       }
00336       break;
00337 
00338     case StateTypes::ML_MOVE_CHUCK:
00339       moveArm(KEY_JM_PICK_TO_CHUCK);
00340       setState(StateTypes::ML_WAIT_MOVE_CHUCK);
00341       break;
00342 
00343     case StateTypes::ML_WAIT_MOVE_CHUCK:
00344       if (isMoveDone())
00345       {
00346         setState(StateTypes::ML_CLOSE_CHUCK);
00347       }
00348       break;
00349 
00350     case StateTypes::ML_CLOSE_CHUCK:
00351       closeChuck();
00352       setState(StateTypes::ML_WAIT_CLOSE_CHUCK);
00353       break;
00354 
00355     case StateTypes::ML_WAIT_CLOSE_CHUCK:
00356       if (isChuckClosed())
00357       {
00358         setState(StateTypes::ML_RELEASE_PART);
00359       }
00360       break;
00361 
00362     case StateTypes::ML_RELEASE_PART:
00363       openGripper();
00364       setState(StateTypes::ML_WAIT_RELEASE_PART);
00365       break;
00366 
00367     case StateTypes::ML_WAIT_RELEASE_PART:
00368       if (isGripperOpened())
00369       {
00370         setState(StateTypes::ML_MOVE_DOOR);
00371       }
00372       break;
00373 
00374     case StateTypes::ML_MOVE_DOOR:
00375       moveArm(KEY_JM_CHUCK_TO_DOOR);
00376       setState(StateTypes::ML_WAIT_MOVE_DOOR);
00377       break;
00378 
00379     case StateTypes::ML_WAIT_MOVE_DOOR:
00380       if (isMoveDone())
00381       {
00382         setState(StateTypes::ML_MOVE_HOME);
00383       }
00384       break;
00385 
00386     case StateTypes::ML_MOVE_HOME:
00387       moveArm(KEY_JM_DOOR_TO_HOME);
00388       closeDoor();
00389       setState(StateTypes::ML_WAIT_MOVE_HOME);
00390       break;
00391 
00392     case StateTypes::ML_WAIT_MOVE_HOME:
00393       if (isMoveDone() && isDoorClosed())
00394       {
00395         setState(StateTypes::MATERIAL_LOADED);
00396       }
00397       break;
00398 
00399     case StateTypes::MATERIAL_LOADED:
00400       ROS_INFO_STREAM("Material loaded");
00401       load_res.load_state = "Succeeded";
00402       material_load_server_ptr_->setSucceeded(load_res);
00403       setState(StateTypes::WAITING);
00404       break;
00405 
00406 
00407 
00408 
00409     case StateTypes::MATERIAL_UNLOADING:
00410       ROS_INFO_STREAM("++++++++++++++++++++++++ UNLOADING MATERIAL ++++++++++++++++++++++++");
00411       setState(StateTypes::MU_MOVE_DOOR);
00412       break;
00413 
00414     case StateTypes::MU_MOVE_DOOR:
00415       moveArm(KEY_JM_HOME_TO_DOOR);
00416       openDoor();
00417       setState(StateTypes::MU_WAIT_MOVE_DOOR);
00418       break;
00419 
00420     case StateTypes::MU_WAIT_MOVE_DOOR:
00421       if(isMoveDone() && isDoorOpened())
00422       {
00423         setState(StateTypes::MU_MOVE_CHUCK);
00424       }
00425       break;
00426 
00427     case StateTypes::MU_MOVE_CHUCK:
00428       moveArm(KEY_JM_DOOR_TO_CHUCK);
00429       setState(StateTypes::MU_WAIT_MOVE_CHUCK);
00430       break;
00431 
00432     case StateTypes::MU_WAIT_MOVE_CHUCK:
00433       if(isMoveDone())
00434       {
00435         setState(StateTypes::MU_PICK_PART);
00436       }
00437       break;
00438 
00439     case StateTypes::MU_PICK_PART:
00440       closeGripper();
00441       setState(StateTypes::MU_WAIT_PICK_PART);
00442       break;
00443 
00444     case StateTypes::MU_WAIT_PICK_PART:
00445       if(isGripperClosed())
00446       {
00447         setState(StateTypes::MU_OPEN_CHUCK);
00448       }
00449       break;
00450 
00451     case StateTypes::MU_OPEN_CHUCK:
00452       openChuck();
00453       setState(StateTypes::MU_WAIT_OPEN_CHUCK);
00454       break;
00455 
00456     case StateTypes::MU_WAIT_OPEN_CHUCK:
00457       if(isChuckOpened())
00458       {
00459         setState(StateTypes::MU_MOVE_DROP);
00460       }
00461       break;
00462 
00463     case StateTypes::MU_MOVE_DROP:
00464       moveArm(KEY_JM_CHUCK_TO_DROP);
00465       setState(StateTypes::MU_WAIT_MOVE_DROP);
00466       break;
00467 
00468     case StateTypes::MU_WAIT_MOVE_DROP:
00469       if(isMoveDone())
00470       {
00471         setState(StateTypes::MU_DROP);
00472       }
00473       break;
00474 
00475     case StateTypes::MU_DROP:
00476       openGripper();
00477       setState(StateTypes::MU_WAIT_DROP);
00478       break;
00479 
00480     case StateTypes::MU_WAIT_DROP:
00481       if(isGripperOpened())
00482       {
00483         setState(StateTypes::MU_MOVE_HOME);
00484       }
00485       break;
00486 
00487     case StateTypes::MU_MOVE_HOME:
00488       moveArm(KEY_JM_DROP_TO_HOME);
00489       setState(StateTypes::MU_WAIT_MOVE_HOME);
00490       break;
00491 
00492     case StateTypes::MU_WAIT_MOVE_HOME:
00493       if(isMoveDone())
00494       {
00495         setState(StateTypes::MATERIAL_UNLOADED);
00496       }
00497       break;
00498 
00499     case StateTypes::MATERIAL_UNLOADED:
00500       ROS_INFO_STREAM("Material unloaded");
00501       unload_res.unload_state = "Succeeded";
00502       material_unload_server_ptr_->setSucceeded(unload_res);
00503       setState(StateTypes::WAITING);
00504       break;
00505 
00506 
00507 
00508     case StateTypes::ABORTING:
00509       ROS_ERROR("Entering state machine abort sequence");
00510       setState(StateTypes::ABORT_GOALS);
00511       break;
00512 
00513     case StateTypes::ABORT_GOALS:
00514       ROS_INFO_STREAM("Aborting goals");
00515       abortActionServers();
00516       setState(StateTypes::CANCEL_REQUESTS);
00517       break;
00518 
00519     case StateTypes::CANCEL_REQUESTS:
00520       ROS_INFO_STREAM("Canceling requests");
00521       cancelActionClients();
00522       setState(StateTypes::ABORTED);
00523       break;
00524 
00525     case StateTypes::ABORTED:
00526       ROS_INFO_STREAM_THROTTLE(30, "Robot in ABORTED state");
00527       break;
00528 
00529     case StateTypes::STOPPING:
00530       ROS_INFO_STREAM("Beginning system stop");
00531       setState(StateTypes::S_SET_MAT_ACTIONS_NOT_READY);
00532       break;
00533 
00534     case StateTypes::S_SET_MAT_ACTIONS_NOT_READY:
00535       setMatActionsNotReady();
00536       setState(StateTypes::STOPPED);
00537       break;
00538 
00539     case StateTypes::STOPPED:
00540       ROS_INFO_STREAM("Completing stop");
00541       setState(StateTypes::IDLE);
00542       break;
00543 
00544     case StateTypes::RESETTING:
00545       setState(StateTypes::R_WAIT_FOR_HOME);
00546       break;
00547 
00548     case StateTypes::R_WAIT_FOR_HOME:
00549       if( isHome())
00550       {
00551         setState(StateTypes::R_SET_MAT_ACTIONS_NOT_READY);
00552       }
00553       else
00554       {
00555         ROS_ERROR_STREAM("Robot not in home state for FAULT RESET");
00556         setState(StateTypes::ABORTING);
00557       }
00558       break;
00559 
00560     case StateTypes::R_SET_MAT_ACTIONS_NOT_READY:
00561       setMatActionsNotReady();
00562       setState(StateTypes::IDLE);
00563       break;
00564 
00565     default:
00566       ROS_ERROR_STREAM("Unhandled state: " << state_ << ", setting state to aborted");
00567       setState(StateTypes::ABORTING);
00568       break;
00569   }
00570 }
00571 
00572 bool StateMachine::areActionsReady()
00573 {
00574   return open_door_client_ptr_->isServerConnected() && close_door_client_ptr_->isServerConnected()
00575       && open_chuck_client_ptr_->isServerConnected() && close_chuck_client_ptr_->isServerConnected()
00576       && grasp_action_client_ptr_->isServerConnected() && vise_action_client_ptr_->isServerConnected()
00577       && joint_traj_client_ptr_->isServerConnected();
00578 }
00579 
00580 bool StateMachine::areServicesReady()
00581 {
00582   return material_load_set_state_client_.exists() && material_unload_set_state_client_.exists()
00583       && trajectory_filter_client_.exists();
00584 }
00585 
00586 void StateMachine::abortActionServers()
00587 {
00588   ROS_INFO_STREAM("Checking material load action server");
00589   if (material_load_server_ptr_->isActive())
00590   {
00591     MaterialLoadServer::Result res;
00592     res.load_state = "Failed";
00593     material_load_server_ptr_->setAborted(res);
00594     ROS_INFO_STREAM("Material Load goal aborted");
00595   }
00596 
00597   ROS_INFO_STREAM("Checking material unload action server");
00598   if (material_unload_server_ptr_->isActive())
00599   {
00600     MaterialUnloadServer::Result res;
00601     res.unload_state = "Failed";
00602     material_unload_server_ptr_->setAborted(res);
00603     ROS_INFO_STREAM("Material Unload goal aborted");
00604   }
00605 }
00606 
00607 void StateMachine::cancelActionClients()
00608 {
00609   ROS_INFO_STREAM("Canceling all action clients");
00610   joint_traj_client_ptr_->cancelAllGoals();
00611 
00612   open_door_client_ptr_->cancelAllGoals();
00613   open_chuck_client_ptr_->cancelAllGoals();
00614   close_door_client_ptr_->cancelAllGoals();
00615   close_chuck_client_ptr_->cancelAllGoals();
00616 
00617   grasp_action_client_ptr_->cancelAllGoals();
00618   vise_action_client_ptr_->cancelAllGoals();
00619 }
00620 
00621 bool StateMachine::setMatActionsReady()
00622 {
00623   return setMatLoad(mtconnect_msgs::SetMTConnectState::Request::READY)
00624       && setMatUnload(mtconnect_msgs::SetMTConnectState::Request::READY);
00625 }
00626 
00627 bool StateMachine::setMatActionsNotReady()
00628 {
00629   return setMatLoad(mtconnect_msgs::SetMTConnectState::Request::NOT_READY)
00630       && setMatUnload(mtconnect_msgs::SetMTConnectState::Request::NOT_READY);
00631 }
00632 
00633 bool StateMachine::setMatLoad(int state)
00634 {
00635   bool rtn = false;
00636   mat_load_set_state_.request.state_flag = state;
00637 
00638   if (material_load_set_state_client_.call(mat_load_set_state_))
00639   {
00640     if (mat_load_set_state_.response.accepted)
00641     {
00642       material_load_state_ = state;
00643       ROS_INFO_STREAM("Material load set to: " << state);
00644       rtn = true;
00645     }
00646     else
00647     {
00648       ROS_WARN_STREAM("Material load failed to set to: " << state);
00649       rtn = false;
00650     }
00651   }
00652   else
00653   {
00654     ROS_WARN_STREAM("Material load service call failed");
00655     rtn = false;
00656   }
00657 
00658   return rtn;
00659 }
00660 
00661 bool StateMachine::setMatUnload(int state)
00662 {
00663   bool rtn = false;
00664   mat_unload_set_state_.request.state_flag = state;
00665 
00666   if (material_unload_set_state_client_.call(mat_unload_set_state_))
00667   {
00668     if (mat_unload_set_state_.response.accepted)
00669     {
00670       ROS_INFO_STREAM("Material unload set to: " << state);
00671       rtn = true;
00672     }
00673     else
00674     {
00675       ROS_WARN_STREAM("Material unload failed to set to: " << state);
00676       rtn = false;
00677     }
00678   }
00679   else
00680   {
00681     ROS_WARN_STREAM("Material unload service call failed");
00682     rtn = false;
00683   }
00684 
00685   return rtn;
00686 }
00687 
00688 void StateMachine::errorChecks()
00689 {
00690   using namespace industrial_msgs;
00691   bool error = false;
00692 
00693   if (robot_status_msg_.e_stopped.val == TriState::TRUE)
00694   {
00695     ROS_ERROR_STREAM_THROTTLE(5, "Robot estopped(" << robot_status_msg_.e_stopped << " aborting");
00696     error = true;
00697   }
00698   if (robot_status_msg_.in_error.val == TriState::TRUE)
00699   {
00700     ROS_ERROR_STREAM_THROTTLE(5, "General robot error(" << robot_status_msg_.in_error << " aborting");
00701     error = true;
00702   }
00703 
00704   if (error && !(StateTypes::ABORTING >= state_ && state_ <= StateTypes::ABORTED))
00705   {
00706     ROS_INFO_STREAM("One or more general errors detected, aborting");
00707     setState(StateTypes::ABORTING);
00708   }
00709 }
00710 
00711 void StateMachine::overrideChecks()
00712 {
00713   ros::NodeHandle ph("~");
00714   int state_override = StateTypes::INVALID;
00715   ph.getParamCached(PARAM_STATE_OVERRIDE, state_override);
00716 
00717   int force_fault_state = StateTypes::INVALID;
00718   ph.getParamCached(PARAM_FORCE_FAULT_STATE, force_fault_state);
00719 
00720   if (state_override != StateTypes::INVALID)
00721   {
00722     ROS_WARN_STREAM("Overriding state to: " << StateTypes::STATE_MAP[state_override]);
00723     setState(StateType(state_override));
00724     ph.setParam(PARAM_STATE_OVERRIDE, StateTypes::INVALID);
00725   }
00726   if (state_ == force_fault_state)
00727   {
00728     ROS_ERROR_STREAM("Forcing fault from state: "<< StateTypes::STATE_MAP[state_]);
00729     setState(StateTypes::ABORTING);
00730     ph.setParam(PARAM_FORCE_FAULT_STATE, StateTypes::INVALID);
00731   }
00732 
00733   
00734   bool mat_param_state = false;
00735   ph.getParamCached(PARAM_MAT_STATE, mat_param_state);
00736 
00737   if (material_state_ != mat_param_state)
00738   {
00739     ROS_INFO_STREAM("Detected change in material state, from " << material_state_ << " to " << mat_param_state);
00740     material_state_ = mat_param_state;
00741   }
00742 }
00743 
00744 
00745 void StateMachine::callPublishers()
00746 {
00747   robotStatusPublisher();
00748   robotSpindlePublisher();
00749   stateMachineStatusPublisher();
00750 }
00751 void StateMachine::robotStatusPublisher()
00752 {
00753   using namespace industrial_msgs;
00754   
00755   robot_state_msg_.header.stamp = ros::Time::now();
00756 
00757   
00758   if ((state_ != StateTypes::IDLE) && (state_ != StateTypes::ABORTED))
00759   {
00760     robot_state_msg_.avail.val = TriState::ENABLED;
00761     robot_state_msg_.mode.val = RobotMode::AUTO;
00762   }
00763   else
00764   {
00765     robot_state_msg_.avail.val = TriState::DISABLED;
00766     robot_state_msg_.mode.val = RobotMode::MANUAL;
00767   }
00768 
00769   
00770   
00771 
00772   
00773   
00774   
00775   robot_state_msg_.rexec.val = TriState::HIGH;
00776 
00777   
00778   robot_states_pub_.publish(robot_state_msg_);
00779 }
00780 
00781 void StateMachine::robotSpindlePublisher()
00782 {
00783   using namespace industrial_msgs;
00784   robot_spindle_msg_.header.stamp = ros::Time::now();
00785 
00786   
00787   robot_spindle_msg_.c_unclamp.val = TriState::HIGH;
00788   robot_spindle_msg_.s_inter.val = TriState::HIGH;
00789 
00790   robot_spindle_pub_.publish(robot_spindle_msg_);
00791 }
00792 
00793 
00794 void StateMachine::stateMachineStatusPublisher()
00795 {
00796   state_machine_stat_msg_.header.stamp = ros::Time::now();
00797   state_machine_stat_msg_.state = state_;
00798   state_machine_stat_msg_.state_name = StateTypes::STATE_MAP[state_];
00799 
00800   state_machine_pub_.publish(state_machine_stat_msg_);
00801 }
00802 
00803 
00804 
00805 void StateMachine::materialLoadGoalCB()
00806 {
00807   switch (state_)
00808   {
00809     case StateTypes::WAITING:
00810       ROS_INFO_STREAM("Accepting material load request");
00811       material_load_server_ptr_->acceptNewGoal();
00812       
00813       setState(StateTypes::MATERIAL_LOADING);
00814       break;
00815     default:
00816       ROS_WARN_STREAM("Material load request received in wrong state: " << state_);
00817       MaterialLoadServer::Result res;
00818       res.load_state = "Failed";
00819       material_load_server_ptr_->acceptNewGoal();
00820       material_load_server_ptr_->setAborted(res);
00821       break;
00822   }
00823 }
00824 void StateMachine::materialUnloadGoalCB()
00825 {
00826   switch (state_)
00827   {
00828     case StateTypes::WAITING:
00829       ROS_INFO_STREAM("Accepting material unload request");
00830       material_unload_server_ptr_->acceptNewGoal();
00831       
00832       setState(StateTypes::MATERIAL_UNLOADING);
00833       break;
00834     default:
00835       ROS_WARN_STREAM("Material unload request received in wrong state: " << state_);
00836       MaterialUnloadServer::Result res;
00837       res.unload_state = "Failed";
00838       material_unload_server_ptr_->acceptNewGoal();
00839       material_unload_server_ptr_->setAborted(res);
00840       break;
00841   }
00842 }
00843 void StateMachine::robotStatusCB(const industrial_msgs::RobotStatusConstPtr &msg)
00844 {
00845   robot_status_msg_ = *msg;
00846 }
00847 
00848 void StateMachine::jointStatesCB(const sensor_msgs::JointStateConstPtr &msg)
00849 {
00850   joint_state_msg_ = *msg;
00851 }
00852 
00853 bool StateMachine::externalCommandCB(mtconnect_example_msgs::StateMachineCmd::Request &req,
00854                                      mtconnect_example_msgs::StateMachineCmd::Response &res)
00855 {
00856   using namespace mtconnect_example_msgs;
00857 
00858   switch (req.command)
00859   {
00860     case StateMachineCmd::Request::STOP:
00861       if (state_ >= StateTypes::CYCLE_BEGIN && state_ <= StateTypes::CYCLE_END)
00862       {
00863         ROS_INFO_STREAM("External command STOP, setting stop request flag");
00864         cycle_stop_req_ = true;
00865         res.accepted = true;
00866       }
00867       else
00868       {
00869         ROS_WARN_STREAM("External command STOP ignored, wrong state: " << state_);
00870         res.accepted = false;
00871       }
00872       break;
00873 
00874     case StateMachineCmd::Request::FAULT_RESET:
00875       if (state_ == StateTypes::ABORTED)
00876       {
00877         ROS_INFO_STREAM("External command FAULT_RESET executing");
00878         setState(StateTypes::RESETTING);
00879         res.accepted = true;
00880       }
00881       else
00882       {
00883         ROS_WARN_STREAM("External command FAULT_RESET ignored, wrong state: " << state_);
00884         res.accepted = false;
00885       }
00886       break;
00887     case StateMachineCmd::Request::START:
00888       if (state_ == StateTypes::IDLE)
00889       {
00890         ROS_INFO_STREAM("External command START executing");
00891         setState(StateTypes::INITING);
00892         res.accepted = true;
00893       }
00894       else
00895       {
00896         ROS_WARN_STREAM("External command START ignored, wrong state: " << state_);
00897         res.accepted = false;
00898       }
00899       break;
00900 
00901     default:
00902       ROS_WARN_STREAM("External command: ignored");
00903       res.accepted = false;
00904       break;
00905   }
00906   return true;
00907 }
00908 
00909 bool StateMachine::isActionComplete(int action_state)
00910 {
00911   bool rtn = false;
00912   switch (action_state)
00913   {
00914     case actionlib::SimpleClientGoalState::PENDING:
00915       
00916       break;
00917 
00918     case actionlib::SimpleClientGoalState::ACTIVE:
00919       
00920       break;
00921 
00922     case actionlib::SimpleClientGoalState::SUCCEEDED:
00923       rtn = true;
00924       break;
00925 
00926     case actionlib::SimpleClientGoalState::PREEMPTED:
00927     case actionlib::SimpleClientGoalState::LOST:
00928     case actionlib::SimpleClientGoalState::REJECTED:
00929     case actionlib::SimpleClientGoalState::ABORTED:
00930       
00931       ROS_ERROR_STREAM("Bad action state: " << action_state);
00932       setState(StateTypes::ABORTING);
00933       break;
00934 
00935     default:
00936       ROS_ERROR_STREAM("Unrecognized action state: " << action_state);
00937       setState(StateTypes::ABORTING);
00938       break;
00939   }
00940 
00941   return rtn;
00942 }
00943 
00944 bool StateMachine::moveArm(const std::string & move_name)
00945 {
00946   joint_traj_goal_.trajectory = *joint_paths_[move_name];
00947   
00948   trajectory_filter_.request.trajectory = joint_traj_goal_.trajectory;
00949   if (!joint_traj_goal_.trajectory.points.empty())
00950   {
00951     if (trajectory_filter_client_.call(trajectory_filter_))
00952     {
00953       if (trajectory_filter_.response.error_code.val == trajectory_filter_.response.error_code.SUCCESS)
00954       {
00955         ROS_INFO_STREAM("======================== MOVING ROBOT ========================");
00956         
00957         joint_traj_goal_.trajectory = trajectory_filter_.response.trajectory;
00958         
00959         joint_traj_client_ptr_->sendGoal(joint_traj_goal_);
00960       }
00961       else
00962       {
00963         ROS_ERROR("Failed to process filter trajectory, entering fault state");
00964         setState(StateTypes::ABORTING);
00965       }
00966     }
00967 
00968     else
00969     {
00970       ROS_ERROR("Failed to call filter trajectory, entering fault state");
00971       setState(StateTypes::ABORTING);
00972     }
00973   }
00974   else
00975   {
00976     ROS_ERROR_STREAM(move_name << " trajectory is empty, failing");
00977     setState(StateTypes::ABORTING);
00978   }
00979 
00980   return true;
00981 }
00982 
00983 bool StateMachine::isMoveDone()
00984 {
00985   return isActionComplete(joint_traj_client_ptr_->getState().state_);
00986 }
00987 
00988 void StateMachine::openDoor()
00989 {
00990   ROS_INFO_STREAM("======================== OPENING DOOR ========================");
00991   mtconnect_msgs::OpenDoorGoal goal;
00992   goal.open_door = MTCONNECT_ACTION_ACTIVE_FLAG;
00993   open_door_client_ptr_->sendGoal(goal);
00994 }
00995 
00996 bool StateMachine::isDoorOpened()
00997 {
00998   return isActionComplete(open_door_client_ptr_->getState().state_);
00999 }
01000 
01001 void StateMachine::closeDoor()
01002 {
01003   ROS_INFO_STREAM("======================== CLOSING_DOOR ========================");
01004   mtconnect_msgs::CloseDoorGoal goal;
01005   goal.close_door = MTCONNECT_ACTION_ACTIVE_FLAG;
01006   close_door_client_ptr_->sendGoal(goal);
01007 }
01008 
01009 bool StateMachine::isDoorClosed()
01010 {
01011   return isActionComplete(close_door_client_ptr_->getState().state_);
01012 }
01013 
01014 void StateMachine::openChuck()
01015 {
01016   ROS_INFO_STREAM("======================== OPENING CHUCK ========================");
01017   
01018   mtconnect_msgs::OpenChuckGoal chuck_goal;
01019   chuck_goal.open_chuck = MTCONNECT_ACTION_ACTIVE_FLAG;
01020   open_chuck_client_ptr_->sendGoal(chuck_goal);
01021 
01022   
01023   object_manipulation_msgs::GraspHandPostureExecutionGoal vise_goal;
01024   vise_goal.goal = object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE;
01025   vise_action_client_ptr_->sendGoal(vise_goal);
01026 }
01027 
01028 bool StateMachine::isChuckOpened()
01029 {
01030   return isActionComplete(open_chuck_client_ptr_->getState().state_);
01031 }
01032 
01033 void StateMachine::closeChuck()
01034 {
01035   ROS_INFO_STREAM("======================== CLOSING CHUCK ========================");
01036   
01037   mtconnect_msgs::CloseChuckGoal chuck_goal;
01038   chuck_goal.close_chuck = MTCONNECT_ACTION_ACTIVE_FLAG;
01039   close_chuck_client_ptr_->sendGoal(chuck_goal);
01040 
01041   
01042   object_manipulation_msgs::GraspHandPostureExecutionGoal vise_goal;
01043   vise_goal.goal = object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP;
01044   vise_action_client_ptr_->sendGoal(vise_goal);
01045 }
01046 
01047 bool StateMachine::isChuckClosed()
01048 {
01049   return isActionComplete(close_chuck_client_ptr_->getState().state_)
01050       && isActionComplete(grasp_action_client_ptr_->getState().state_);
01051 }
01052 
01053 void StateMachine::openGripper()
01054 {
01055   ROS_INFO_STREAM("======================== OPENING GRIPPER ========================");
01056   object_manipulation_msgs::GraspHandPostureExecutionGoal goal;
01057   goal.goal = object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE;
01058   grasp_action_client_ptr_->sendGoal(goal);
01059 }
01060 
01061 bool StateMachine::isGripperOpened()
01062 {
01063   return isActionComplete(grasp_action_client_ptr_->getState().state_);
01064 }
01065 
01066 void StateMachine::closeGripper()
01067 {
01068   ROS_INFO_STREAM("======================== CLOSING GRIPPER ========================");
01069   object_manipulation_msgs::GraspHandPostureExecutionGoal goal;
01070   goal.goal = object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP;
01071   grasp_action_client_ptr_->sendGoal(goal);
01072 }
01073 
01074 bool StateMachine::isGripperClosed()
01075 {
01076   return isActionComplete(grasp_action_client_ptr_->getState().state_);
01077 }
01078 
01079 bool StateMachine::isHome()
01080 {
01081   bool rtn = false;
01082 
01083   if( home_check_ )
01084   {
01085     ROS_INFO_STREAM("Home checking ENABLED, returning range check");
01086     rtn = industrial_robot_client::utils::isWithinRange(home_->group_->joint_names_, home_->values_,
01087                                                       joint_state_msg_.name, joint_state_msg_.position, home_tol_);
01088   }
01089   else
01090   {
01091     ROS_WARN_STREAM("Home checking DISABLED, returning true");
01092     rtn = true;
01093   }
01094 
01095   return rtn;
01096 }