state_machine.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2013 Southwest Research Institute
00003 
00004  Licensed under the Apache License, Version 2.0 (the "License");
00005  you may not use this file except in compliance with the License.
00006  You may obtain a copy of the License at
00007 
00008  http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  Unless required by applicable law or agreed to in writing, software
00011  distributed under the License is distributed on an "AS IS" BASIS,
00012  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  See the License for the specific language governing permissions and
00014  limitations under the License.
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 // Material load moves
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 // Material unload moves
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 //convienence typdef for getting to mtconnect state (i.e. ready, not, ready, etc...)
00067 typedef mtconnect_msgs::SetMTConnectState::Request MtConnectState;
00068 
00069 StateMachine::StateMachine() :
00070     nh_()
00071 {
00072   // Setting default class values
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; //radians
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   // initializing action service servers
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   // initializing action service clients
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   // initializing publishers
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   // initializing subscribers
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   // initializing servers
00160   external_command_srv_ = nh_.advertiseService(DEFAULT_EXTERNAL_COMMAND_SERVICE, &StateMachine::externalCommandCB,
00161                                                this);
00162 
00163   // initializing clients
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   // starting action servers
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     //ROS_INFO_STREAM_THROTTLE(5, "Begin blocking run loop, state: " << state_);
00189     runOnce();
00190     callPublishers();
00191     ros::spinOnce();
00192     errorChecks();
00193     overrideChecks();
00194     //ROS_INFO_STREAM_THROTTLE(5, "End blocking run loop, state: " << state_);
00195     r.sleep();
00196   }
00197 
00198 }
00199 
00200 void StateMachine::runOnce()
00201 {
00202   //TODO: Remove these variables (they can't be used under a case statement)
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   // Material state override (defaults to not having material, ie false)
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 //Publishers
00745 void StateMachine::callPublishers()
00746 {
00747   robotStatusPublisher();
00748   robotSpindlePublisher();
00749   stateMachineStatusPublisher();
00750 }
00751 void StateMachine::robotStatusPublisher()
00752 {
00753   using namespace industrial_msgs;
00754   // updating header time stamps
00755   robot_state_msg_.header.stamp = ros::Time::now();
00756 
00757   // TODO: May want to rethink these conditions, not
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   //TODO: Figure out how the mode is supposed to be used
00770   //robot_state_msg_.mode.val = robot_status_msg_.mode.val;
00771 
00772   // TODO: Overriding these values until we know what they should be
00773   //robot_state_msg_.avail.val = TriState::ENABLED;
00774   //robot_state_msg_.mode.val = RobotMode::AUTO;
00775   robot_state_msg_.rexec.val = TriState::HIGH;
00776 
00777   // publishing
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   // TODO: Overriding these values until we know what they should be
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 //Callbacks
00805 void StateMachine::materialLoadGoalCB(/*const MaterialLoadServer::GoalConstPtr &gh*/)
00806 {
00807   switch (state_)
00808   {
00809     case StateTypes::WAITING:
00810       ROS_INFO_STREAM("Accepting material load request");
00811       material_load_server_ptr_->acceptNewGoal();
00812       //setMatUnload(MtConnectState::NOT_READY);
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(/*const MaterialUnloadServer::GoalConstPtr &gh*/)
00825 {
00826   switch (state_)
00827   {
00828     case StateTypes::WAITING:
00829       ROS_INFO_STREAM("Accepting material unload request");
00830       material_unload_server_ptr_->acceptNewGoal();
00831       //setMatLoad(MtConnectState::NOT_READY);
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       //ROS_INFO_STREAM_THROTTLE(1, "Action request is pending");
00916       break;
00917 
00918     case actionlib::SimpleClientGoalState::ACTIVE:
00919       //ROS_INFO_STREAM_THROTTLE(1, "Action request is active");
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       // These states indicate something bad happened
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   //ROS_INFO_STREAM("Filtering a joint trajectory with " << joint_traj_goal_.trajectory.points.size() << "points");
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         //ROS_INFO("Trajectory successfully filtered...sending goal");
00957         joint_traj_goal_.trajectory = trajectory_filter_.response.trajectory;
00958         //ROS_INFO_STREAM("Sending a joint trajectory with " << joint_traj_goal_.trajectory.points.size() << "points");
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   // Actual chuck
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   // Simulated chuck
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   // Actual chuck
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   // Simulated chuck
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 }


mtconnect_state_machine
Author(s): Shaun M. Edwards
autogenerated on Mon Jan 6 2014 11:30:57