Controller.c
Go to the documentation of this file.
00001 // Controller.c
00002 //
00003 /*
00004 * Software License Agreement (BSD License) 
00005 *
00006 * Copyright (c) 2013, Yaskawa America, Inc.
00007 * All rights reserved.
00008 *
00009 * Redistribution and use in binary form, with or without modification,
00010 * is permitted provided that the following conditions are met:
00011 *
00012 *       * Redistributions in binary form must reproduce the above copyright
00013 *       notice, this list of conditions and the following disclaimer in the
00014 *       documentation and/or other materials provided with the distribution.
00015 *       * Neither the name of the Yaskawa America, Inc., nor the names 
00016 *       of its contributors may be used to endorse or promote products derived
00017 *       from this software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029 * POSSIBILITY OF SUCH DAMAGE.
00030 */ 
00031 
00032 #include "MotoROS.h"
00033 
00034 extern STATUS setsockopt
00035     (
00036     int    s,                 /* target socket */
00037     int    level,             /* protocol level of option */
00038     int    optname,           /* option name */
00039     char * optval,            /* pointer to option value */
00040     int    optlen             /* option length */
00041     );
00042 
00043 //-----------------------
00044 // Function Declarations
00045 //-----------------------
00046 BOOL Ros_Controller_Init(Controller* controller);
00047 BOOL Ros_Controller_WaitInitReady(Controller* controller);
00048 BOOL Ros_Controller_IsValidGroupNo(Controller* controller, int groupNo);
00049 int Ros_Controller_OpenSocket(int tcpPort);
00050 void Ros_Controller_ConnectionServer_Start(Controller* controller);
00051 // Status related
00052 void Ros_Controller_StatusInit(Controller* controller);
00053 BOOL Ros_Controller_IsAlarm(Controller* controller);
00054 BOOL Ros_Controller_IsError(Controller* controller);
00055 BOOL Ros_Controller_IsPlay(Controller* controller);
00056 BOOL Ros_Controller_IsTeach(Controller* controller);
00057 BOOL Ros_Controller_IsRemote(Controller* controller);
00058 BOOL Ros_Controller_IsOperating(Controller* controller);
00059 BOOL Ros_Controller_IsHold(Controller* controller);
00060 BOOL Ros_Controller_IsServoOn(Controller* controller);
00061 BOOL Ros_Controller_IsEStop(Controller* controller);
00062 BOOL Ros_Controller_IsWaitingRos(Controller* controller);
00063 int Ros_Controller_GetNotReadySubcode(Controller* controller);
00064 int Ros_Controller_StatusToMsg(Controller* controller, SimpleMsg* sendMsg);
00065 BOOL Ros_Controller_StatusRead(Controller* controller, USHORT ioStatus[IO_ROBOTSTATUS_MAX]);
00066 BOOL Ros_Controller_StatusUpdate(Controller* controller);
00067 // Wrapper around MPFunctions
00068 BOOL Ros_Controller_GetIOState(ULONG signal);
00069 void Ros_Controller_SetIOState(ULONG signal, BOOL status);
00070 int Ros_Controller_GetAlarmCode();
00071 void Ros_Controller_ErrNo_ToString(int errNo, char errMsg[ERROR_MSG_MAX_SIZE], int errMsgSize);
00072 
00073 //-----------------------
00074 // Function implementation
00075 //-----------------------
00076 
00077 //Report version info to display on pendant (DX200 only)
00078 void reportVersionInfoToController()
00079 {
00080 #if DX100 || FS100
00081         return;
00082 #else
00083         MP_APPINFO_SEND_DATA appInfoSendData;
00084         MP_STD_RSP_DATA stdResponseData;
00085 
00086         sprintf(appInfoSendData.AppName, "MotoROS");
00087 
00088         sprintf(appInfoSendData.Version, "v%s", APPLICATION_VERSION);
00089         sprintf(appInfoSendData.Comment, "Motoman ROS-I driver");
00090 
00091         mpApplicationInfoNotify(&appInfoSendData, &stdResponseData); //don't care about return value
00092 #endif
00093 }
00094 
00095 // Verify most of the setup parameters of the robot controller.
00096 // Please note that some parameters cannot be checked, such as
00097 // the parameter(s) which enable this task to run.
00098 // Returns FALSE if a critical parameter is not set such that it
00099 // will prevent intialization.
00100 BOOL Ros_Controller_CheckSetup()
00101 {
00102         int parameterValidationCode;
00103 
00104         parameterValidationCode = ValidateMotoRosSetupParameters();
00105         switch (parameterValidationCode)
00106         {
00107         case MOTOROS_SETUP_OK: return TRUE;
00108 
00109         case MOTOROS_SETUP_RS0: 
00110                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS Cfg: Set RS000=2", parameterValidationCode);
00111                 return TRUE;
00112 
00113         case MOTOROS_SETUP_S2C541:
00114                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS Cfg: Set S2C541=0", parameterValidationCode);
00115                 return TRUE;
00116 
00117         case MOTOROS_SETUP_S2C542:
00118                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS Cfg: Set S2C542=0", parameterValidationCode);
00119                 return TRUE;
00120 
00121         case MOTOROS_SETUP_S2C1100:
00122                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS Cfg: Set S2C1100=1", parameterValidationCode);
00123                 return FALSE;
00124 
00125         case MOTOROS_SETUP_S2C1103:
00126                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS Cfg: Set S2C1103=2", parameterValidationCode);
00127                 return FALSE;
00128 
00129         case MOTOROS_SETUP_S2C1117:
00130                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS Cfg: Set S2C1117=1", parameterValidationCode);
00131                 return FALSE;
00132 
00133         case MOTOROS_SETUP_S2C1119:
00134                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS Cfg: Set S2C1119=0 or 2", parameterValidationCode);
00135                 return TRUE;
00136 
00137         case MOTOROS_SETUP_NotCompatibleWithPFL:
00138                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS not compatible with PFL", parameterValidationCode);
00139                 return FALSE;
00140 
00141         //For all other error codes, please contact Yaskawa Motoman
00142         //to have the MotoROS Runtime functionality enabled on your
00143         //robot controller.
00144         default:
00145                 mpSetAlarm(MOTOROS_SETUPERROR_ALARMCODE, "MotoROS: Controller cfg invalid", parameterValidationCode);
00146                 return FALSE;
00147         }
00148 }
00149 
00150 //-------------------------------------------------------------------
00151 // Initialize the controller structure
00152 // This should be done before the controller is used for anything
00153 //------------------------------------------------------------------- 
00154 BOOL Ros_Controller_Init(Controller* controller)
00155 {
00156         int grpNo;
00157         int i;
00158         BOOL bInitOk;
00159         STATUS status;
00160         
00161         printf("Initializing controller\r\n");
00162 
00163         reportVersionInfoToController();
00164 
00165         // Turn off all I/O signal
00166         Ros_Controller_SetIOState(IO_FEEDBACK_WAITING_MP_INCMOVE, FALSE);
00167         Ros_Controller_SetIOState(IO_FEEDBACK_MP_INCMOVE_DONE, FALSE);
00168         Ros_Controller_SetIOState(IO_FEEDBACK_INITIALIZATION_DONE, FALSE);
00169         Ros_Controller_SetIOState(IO_FEEDBACK_CONNECTSERVERRUNNING, FALSE);
00170         Ros_Controller_SetIOState(IO_FEEDBACK_MOTIONSERVERCONNECTED, FALSE);
00171         Ros_Controller_SetIOState(IO_FEEDBACK_STATESERVERCONNECTED, FALSE);
00172         Ros_Controller_SetIOState(IO_FEEDBACK_IOSERVERCONNECTED, FALSE);
00173         Ros_Controller_SetIOState(IO_FEEDBACK_FAILURE, FALSE);
00174         
00175         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_1, FALSE);
00176         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_2, FALSE);
00177         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_3, FALSE);
00178         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_4, FALSE);
00179         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_5, FALSE);
00180         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_6, FALSE);
00181         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_7, FALSE);
00182         Ros_Controller_SetIOState(IO_FEEDBACK_RESERVED_8, FALSE);
00183         
00184         // Init variables and controller status
00185         bInitOk = TRUE;
00186         controller->bRobotJobReady = FALSE;
00187         controller->bRobotJobReadyRaised = FALSE;
00188         controller->bStopMotion = FALSE;
00189         Ros_Controller_StatusInit(controller);
00190         Ros_Controller_StatusRead(controller, controller->ioStatus);
00191         
00192         // wait for controller to be ready for reading parameter
00193         Ros_Controller_WaitInitReady(controller);
00194         
00195         bInitOk = Ros_Controller_CheckSetup();
00196         if (!bInitOk)
00197                 return FALSE; //Don't allow initialization to continue
00198 
00199         // Wait for alarms to clear, in case Ros_Controller_CheckSetup raised an alarm
00200         Ros_Controller_WaitInitReady(controller);
00201 
00202         // Get the interpolation clock
00203         status = GP_getInterpolationPeriod(&controller->interpolPeriod);
00204         if(status!=OK)
00205                 bInitOk = FALSE;
00206         
00207         // Get the number of groups
00208         controller->numGroup = GP_getNumberOfGroups();
00209 #ifdef DEBUG
00210         printf("controller->numGroup = %d\n", controller->numGroup);
00211 #endif
00212         if(controller->numGroup < 1)
00213                 bInitOk = FALSE;
00214 
00215         if (controller->numGroup > MOT_MAX_GR)
00216         {
00217                 mpSetAlarm(8001, "WARNING: Too many groups for ROS", 0); //force user to acknowledge ignored groups
00218                 printf("!!!---Detected %d control groups.  MotoROS will only control %d.---!!!\n", controller->numGroup, MOT_MAX_GR);
00219                 controller->numGroup = MOT_MAX_GR;
00220         }
00221         
00222         controller->numRobot = 0;
00223         
00224         // Check for each group
00225         for(grpNo=0; grpNo < MP_GRP_NUM; grpNo++)
00226         {
00227                 if(grpNo < controller->numGroup)
00228                 {
00229                         // Determine if specific group exists and allocate memory for it
00230                         controller->ctrlGroups[grpNo] = Ros_CtrlGroup_Create(grpNo,                                                             //Zero based index of the group number(0 - 3)
00231                                                                                                                                 (grpNo==(controller->numGroup-1)),      //TRUE if this is the final group that is being initialized. FALSE if you plan to call this function again.
00232                                                                                                                                 controller->interpolPeriod);            //Value of the interpolation period (ms) for the robot controller.
00233                         if(controller->ctrlGroups[grpNo] != NULL)
00234                         {
00235                                 Ros_CtrlGroup_GetPulsePosCmd(controller->ctrlGroups[grpNo], controller->ctrlGroups[grpNo]->prevPulsePos); // set the current commanded pulse
00236                                 controller->numRobot++;  //This counter is required for DX100 controllers with two control-groups (robot OR ext axis)
00237                         }
00238                         else
00239                                 bInitOk = FALSE;
00240                 }
00241                 else
00242                         controller->ctrlGroups[grpNo] = NULL;
00243         }
00244 
00245 #ifdef DEBUG
00246         printf("controller->numRobot = %d\n", controller->numRobot);
00247 #endif
00248         
00249         // Initialize Thread ID and Socket to invalid value
00250         controller->tidConnectionSrv = INVALID_TASK;
00251 
00252         for (i = 0; i < MAX_IO_CONNECTIONS; i++)
00253         {
00254                 controller->sdIoConnections[i] = INVALID_SOCKET;
00255                 controller->tidIoConnections[i] = INVALID_TASK;
00256         }
00257 
00258         controller->tidStateSendState = INVALID_TASK;
00259         for (i = 0; i < MAX_STATE_CONNECTIONS; i++)
00260         {
00261                 controller->sdStateConnections[i] = INVALID_SOCKET;
00262         }
00263 
00264         for (i = 0; i < MAX_MOTION_CONNECTIONS; i++)
00265         {
00266                 controller->sdMotionConnections[i] = INVALID_SOCKET;
00267                 controller->tidMotionConnections[i] = INVALID_TASK;
00268         }
00269         controller->tidIncMoveThread = INVALID_TASK;
00270 
00271 #ifdef DX100
00272         controller->bSkillMotionReady[0] = FALSE;
00273         controller->bSkillMotionReady[1] = FALSE;
00274 #endif
00275 
00276         if(bInitOk)
00277         {
00278                 // Turn on initialization done I/O signal
00279                 Ros_Controller_SetIOState(IO_FEEDBACK_INITIALIZATION_DONE, TRUE);
00280         }
00281         else
00282         {
00283                 Ros_Controller_SetIOState(IO_FEEDBACK_FAILURE, TRUE);
00284                 printf("Failure to initialize controller\r\n");
00285         }
00286         
00287         return bInitOk;
00288 }
00289 
00290 
00291 //-------------------------------------------------------------------
00292 // Wait for the controller to be ready to start initialization
00293 //------------------------------------------------------------------- 
00294 BOOL Ros_Controller_WaitInitReady(Controller* controller)
00295 {
00296         do  //minor alarms can be delayed briefly after bootup
00297         {
00298                 puts("Waiting for robot alarms to clear...");
00299                 Ros_Sleep(2500);
00300                 Ros_Controller_StatusRead(controller, controller->ioStatus);
00301 
00302         }while(Ros_Controller_IsAlarm(controller));
00303 
00304         return TRUE;
00305 }
00306 
00307 
00308 //-------------------------------------------------------------------
00309 // Check the number of inc_move currently in the specified queue
00310 //-------------------------------------------------------------------
00311 BOOL Ros_Controller_IsValidGroupNo(Controller* controller, int groupNo)
00312 {
00313         if((groupNo >= 0) && (groupNo < controller->numGroup))
00314                 return TRUE;
00315         else
00316         {
00317                 printf("ERROR: Attempt to access invalid Group No. (%d) \r\n", groupNo);
00318                 return FALSE;
00319         }
00320 }
00321 
00322 
00323 //-------------------------------------------------------------------
00324 // Open a socket to listen for incomming connection on specified port
00325 // return: <0  : Error
00326 //                 >=0 : socket descriptor
00327 //-------------------------------------------------------------------
00328 int Ros_Controller_OpenSocket(int tcpPort)
00329 {
00330         int sd;  // socket descriptor
00331         struct sockaddr_in      serverSockAddr;
00332         int ret;
00333 
00334         // Open the socket
00335         sd = mpSocket(AF_INET, SOCK_STREAM, 0);
00336         if (sd < 0)
00337                 return -1;
00338 
00339         // Set structure
00340         memset(&serverSockAddr, 0, sizeof(struct sockaddr_in));
00341         serverSockAddr.sin_family = AF_INET;
00342         serverSockAddr.sin_addr.s_addr = INADDR_ANY;
00343         serverSockAddr.sin_port = mpHtons(tcpPort);
00344 
00345         //bind to network interface
00346         ret = mpBind(sd, (struct sockaddr *)&serverSockAddr, sizeof(struct sockaddr_in)); 
00347         if (ret < 0)
00348                 goto closeSockHandle;
00349 
00350         //prepare to accept connections
00351         ret = mpListen(sd, SOMAXCONN);
00352         if (ret < 0)
00353                 goto closeSockHandle;
00354 
00355         return sd;
00356 
00357 closeSockHandle:
00358         printf("Error in Ros_Controller_OpenSocket\r\n");
00359 
00360         if(sd >= 0)
00361                 mpClose(sd);
00362 
00363         return -2;
00364 }
00365 
00366 
00367 //-----------------------------------------------------------------------
00368 // Main Connection Server Task that listens for new connections
00369 //-----------------------------------------------------------------------
00370 void Ros_Controller_ConnectionServer_Start(Controller* controller)
00371 {
00372         int     sdMotionServer = INVALID_SOCKET;
00373         int     sdStateServer = INVALID_SOCKET;
00374         int     sdIoServer = INVALID_SOCKET;
00375         int             sdMax;
00376         struct  fd_set  fds;
00377         int     sdAccepted = INVALID_SOCKET;
00378         struct  sockaddr_in     clientSockAddr;
00379         int     sizeofSockAddr;
00380         int     useNoDelay = 1;
00381         STATUS  s;
00382 
00383         //Set feedback signal (Application is installed and running)
00384         Ros_Controller_SetIOState(IO_FEEDBACK_CONNECTSERVERRUNNING, TRUE);
00385 
00386         printf("Controller connection server running\r\n");
00387 
00388         //New sockets for server listening to multiple port
00389         sdMotionServer = Ros_Controller_OpenSocket(TCP_PORT_MOTION);
00390         if(sdMotionServer < 0)
00391                 goto closeSockHandle;
00392         
00393         sdStateServer = Ros_Controller_OpenSocket(TCP_PORT_STATE);
00394         if(sdStateServer < 0)
00395                 goto closeSockHandle;
00396         
00397         sdIoServer = Ros_Controller_OpenSocket(TCP_PORT_IO);
00398         if(sdIoServer < 0)
00399                 goto closeSockHandle;
00400 
00401         sdMax = max(sdMotionServer, sdStateServer);
00402         sdMax = max(sdMax, sdIoServer);
00403 
00404         FOREVER //Continue to accept multiple connections forever
00405         {
00406                 FD_ZERO(&fds);
00407                 FD_SET(sdMotionServer, &fds); 
00408                 FD_SET(sdStateServer, &fds); 
00409                 FD_SET(sdIoServer, &fds); 
00410                 
00411                 if(mpSelect(sdMax+1, &fds, NULL, NULL, NULL) > 0)
00412                 {
00413                         memset(&clientSockAddr, 0, sizeof(clientSockAddr));
00414                         sizeofSockAddr = sizeof(clientSockAddr);
00415                         
00416                         //Check motion server
00417                         if(FD_ISSET(sdMotionServer, &fds))
00418                         {
00419                                 sdAccepted = mpAccept(sdMotionServer, (struct sockaddr *)&clientSockAddr, &sizeofSockAddr);
00420                                 if (sdAccepted < 0)
00421                                         break;
00422                                         
00423                                 s = setsockopt(sdAccepted, IPPROTO_TCP, TCP_NODELAY, (char*)&useNoDelay, sizeof (int));
00424                                 if( OK != s )
00425                                 {
00426                                         printf("Failed to set TCP_NODELAY.\r\n");
00427                                 }
00428                                 
00429                                 Ros_MotionServer_StartNewConnection(controller, sdAccepted);
00430                         }
00431                         
00432                         //Check state server
00433                         if(FD_ISSET(sdStateServer, &fds))
00434                         {
00435                                 sdAccepted = mpAccept(sdStateServer, (struct sockaddr *)&clientSockAddr, &sizeofSockAddr);
00436                                 if (sdAccepted < 0)
00437                                         break;
00438                                         
00439                                 s = setsockopt(sdAccepted, IPPROTO_TCP, TCP_NODELAY, (char*)&useNoDelay, sizeof (int));
00440                                 if( OK != s )
00441                                 {
00442                                         printf("Failed to set TCP_NODELAY.\r\n");
00443                                 }
00444                                 
00445                                 Ros_StateServer_StartNewConnection(controller, sdAccepted);
00446                         }
00447                         
00448                         //Check IO server
00449                         if(FD_ISSET(sdIoServer, &fds))
00450                         {
00451                                 sdAccepted = mpAccept(sdIoServer, (struct sockaddr *)&clientSockAddr, &sizeofSockAddr);
00452                                 if (sdAccepted < 0)
00453                                         break;
00454                                         
00455                                 s = setsockopt(sdAccepted, IPPROTO_TCP, TCP_NODELAY, (char*)&useNoDelay, sizeof (int));
00456                                 if( OK != s )
00457                                 {
00458                                         printf("Failed to set TCP_NODELAY.\r\n");
00459                                 }
00460                                 
00461                                 Ros_IoServer_StartNewConnection(controller, sdAccepted);
00462                         }
00463                 }
00464         }
00465         
00466 closeSockHandle:
00467         printf("Error!?... Connection Server is aborting.  Reboot the controller.\r\n");
00468 
00469         if(sdIoServer >= 0)
00470                 mpClose(sdIoServer);
00471         if(sdMotionServer >= 0)
00472                 mpClose(sdMotionServer);
00473         if(sdStateServer >= 0)
00474                 mpClose(sdStateServer);
00475 
00476         //disable feedback signal
00477         Ros_Controller_SetIOState(IO_FEEDBACK_CONNECTSERVERRUNNING, FALSE);
00478 }
00479 
00480 
00481 
00482 /**** Controller Status functions ****/
00483 
00484 //-------------------------------------------------------------------
00485 // Initialize list of Specific Input to keep track of
00486 //-------------------------------------------------------------------
00487 void Ros_Controller_StatusInit(Controller* controller)
00488 {
00489         controller->ioStatusAddr[IO_ROBOTSTATUS_ALARM_MAJOR].ulAddr = 50010;            // Alarm
00490         controller->ioStatusAddr[IO_ROBOTSTATUS_ALARM_MINOR].ulAddr = 50011;            // Alarm
00491         controller->ioStatusAddr[IO_ROBOTSTATUS_ALARM_SYSTEM].ulAddr = 50012;           // Alarm
00492         controller->ioStatusAddr[IO_ROBOTSTATUS_ALARM_USER].ulAddr = 50013;                     // Alarm
00493         controller->ioStatusAddr[IO_ROBOTSTATUS_ERROR].ulAddr = 50014;                          // Error
00494         controller->ioStatusAddr[IO_ROBOTSTATUS_PLAY].ulAddr = 50054;                           // Play
00495         controller->ioStatusAddr[IO_ROBOTSTATUS_TEACH].ulAddr = 50053;                          // Teach
00496         controller->ioStatusAddr[IO_ROBOTSTATUS_REMOTE].ulAddr = 80011; //50056;        // Remote  // Modified E.M. 7/9/2013
00497         controller->ioStatusAddr[IO_ROBOTSTATUS_OPERATING].ulAddr = 50070;                      // Operating
00498         controller->ioStatusAddr[IO_ROBOTSTATUS_HOLD].ulAddr = 50071;                           // Hold
00499         controller->ioStatusAddr[IO_ROBOTSTATUS_SERVO].ulAddr = 50073;                          // Servo ON
00500         controller->ioStatusAddr[IO_ROBOTSTATUS_ESTOP_EX].ulAddr = 80025;               // External E-Stop
00501         controller->ioStatusAddr[IO_ROBOTSTATUS_ESTOP_PP].ulAddr = 80026;               // Pendant E-Stop
00502         controller->ioStatusAddr[IO_ROBOTSTATUS_ESTOP_CTRL].ulAddr = 80027;             // Controller E-Stop
00503         controller->ioStatusAddr[IO_ROBOTSTATUS_WAITING_ROS].ulAddr = IO_FEEDBACK_WAITING_MP_INCMOVE; // Job input signaling ready for external motion
00504         controller->ioStatusAddr[IO_ROBOTSTATUS_INECOMODE].ulAddr = 50727;                      // Energy Saving Mode
00505         controller->alarmCode = 0;
00506 }
00507 
00508 
00509 BOOL Ros_Controller_IsAlarm(Controller* controller)
00510 {
00511         return ((controller->ioStatus[IO_ROBOTSTATUS_ALARM_MAJOR]!=0) 
00512                 || (controller->ioStatus[IO_ROBOTSTATUS_ALARM_MINOR]!=0)
00513                 || (controller->ioStatus[IO_ROBOTSTATUS_ALARM_SYSTEM]!=0)
00514                 || (controller->ioStatus[IO_ROBOTSTATUS_ALARM_USER]!=0) );
00515 }
00516 
00517 BOOL Ros_Controller_IsError(Controller* controller)
00518 {
00519         return ((controller->ioStatus[IO_ROBOTSTATUS_ERROR]!=0));
00520 }
00521 
00522 BOOL Ros_Controller_IsPlay(Controller* controller)
00523 {
00524         return ((controller->ioStatus[IO_ROBOTSTATUS_PLAY]!=0));
00525 }
00526 
00527 BOOL Ros_Controller_IsTeach(Controller* controller)
00528 {
00529         return ((controller->ioStatus[IO_ROBOTSTATUS_TEACH]!=0));
00530 }
00531 
00532 BOOL Ros_Controller_IsRemote(Controller* controller)
00533 {
00534         return ((controller->ioStatus[IO_ROBOTSTATUS_REMOTE]!=0));
00535 }
00536 
00537 BOOL Ros_Controller_IsOperating(Controller* controller)
00538 {
00539         return ((controller->ioStatus[IO_ROBOTSTATUS_OPERATING]!=0));
00540 }
00541 
00542 BOOL Ros_Controller_IsHold(Controller* controller)
00543 {
00544         return ((controller->ioStatus[IO_ROBOTSTATUS_HOLD]!=0));
00545 }
00546 
00547 BOOL Ros_Controller_IsServoOn(Controller* controller)
00548 {
00549         return ((controller->ioStatus[IO_ROBOTSTATUS_SERVO] != 0) && (controller->ioStatus[IO_ROBOTSTATUS_INECOMODE] == 0));
00550 }
00551 
00552 BOOL Ros_Controller_IsEcoMode(Controller* controller)
00553 {
00554         return (controller->ioStatus[IO_ROBOTSTATUS_INECOMODE] != 0);
00555 }
00556 
00557 BOOL Ros_Controller_IsEStop(Controller* controller)
00558 {
00559         return ((controller->ioStatus[IO_ROBOTSTATUS_ESTOP_EX]==0) 
00560                 || (controller->ioStatus[IO_ROBOTSTATUS_ESTOP_PP]==0)
00561                 || (controller->ioStatus[IO_ROBOTSTATUS_ESTOP_CTRL]==0) );
00562 }
00563 
00564 BOOL Ros_Controller_IsWaitingRos(Controller* controller)
00565 {
00566         return ((controller->ioStatus[IO_ROBOTSTATUS_WAITING_ROS]!=0));
00567 }
00568 
00569 BOOL Ros_Controller_IsMotionReady(Controller* controller)
00570 {
00571 #ifdef DX100
00572         if(controller->numRobot < 2)
00573                 return (controller->bRobotJobReady && controller->bSkillMotionReady[0]);
00574         else
00575         {
00576                 return (controller->bRobotJobReady && controller->bSkillMotionReady[0] && controller->bSkillMotionReady[1]);
00577         }
00578 #else
00579         return (controller->bRobotJobReady);
00580 #endif
00581 }
00582 
00583 int Ros_Controller_GetNotReadySubcode(Controller* controller)
00584 {
00585         // Check alarm
00586         if(Ros_Controller_IsAlarm(controller))
00587                 return ROS_RESULT_NOT_READY_ALARM;
00588         
00589         // Check error
00590         if(Ros_Controller_IsError(controller))
00591                 return ROS_RESULT_NOT_READY_ERROR;
00592         
00593         // Check e-stop
00594         if(Ros_Controller_IsEStop(controller))
00595                 return ROS_RESULT_NOT_READY_ESTOP;
00596 
00597         // Check play mode
00598         if(!Ros_Controller_IsPlay(controller))
00599                 return ROS_RESULT_NOT_READY_NOT_PLAY;
00600         
00601 #ifndef DUMMY_SERVO_MODE
00602         // Check remote
00603         if(!Ros_Controller_IsRemote(controller))
00604                 return ROS_RESULT_NOT_READY_NOT_REMOTE;
00605         
00606         // Check servo power
00607         if(!Ros_Controller_IsServoOn(controller))
00608                 return ROS_RESULT_NOT_READY_SERVO_OFF;
00609 #endif
00610 
00611         // Check hold
00612         if(Ros_Controller_IsHold(controller))
00613                 return ROS_RESULT_NOT_READY_HOLD;
00614 
00615         // Check operating
00616         if(!Ros_Controller_IsOperating(controller))
00617                 return ROS_RESULT_NOT_READY_NOT_STARTED;
00618         
00619         // Check ready I/O signal (should confirm wait)
00620         if(!Ros_Controller_IsWaitingRos(controller))
00621                 return ROS_RESULT_NOT_READY_WAITING_ROS;
00622 
00623         // Check skill send command
00624         if(!Ros_Controller_IsMotionReady(controller))
00625                 return ROS_RESULT_NOT_READY_SKILLSEND;
00626                 
00627         return ROS_RESULT_NOT_READY_UNSPECIFIED;
00628 }
00629 
00630 
00631 // Creates a simple message of type: ROS_MSG_ROBOT_STATUS = 13
00632 // Simple message containing the current state of the controller
00633 int Ros_Controller_StatusToMsg(Controller* controller, SimpleMsg* sendMsg)
00634 {
00635         //initialize memory
00636         memset(sendMsg, 0x00, sizeof(SimpleMsg));
00637         
00638         // set prefix: length of message excluding the prefix
00639         sendMsg->prefix.length = sizeof(SmHeader) + sizeof(SmBodyRobotStatus);
00640         
00641         // set header information
00642         sendMsg->header.msgType = ROS_MSG_ROBOT_STATUS;
00643         sendMsg->header.commType = ROS_COMM_TOPIC;
00644         sendMsg->header.replyType = ROS_REPLY_INVALID;
00645         
00646         // set body
00647         sendMsg->body.robotStatus.drives_powered = (int)(Ros_Controller_IsServoOn(controller));
00648         sendMsg->body.robotStatus.e_stopped = (int)(Ros_Controller_IsEStop(controller));
00649         sendMsg->body.robotStatus.error_code = controller->alarmCode;
00650         sendMsg->body.robotStatus.in_error = (int)Ros_Controller_IsAlarm(controller);
00651         sendMsg->body.robotStatus.in_motion = (int)(Ros_MotionServer_HasDataInQueue(controller));
00652         if(Ros_Controller_IsPlay(controller))
00653                 sendMsg->body.robotStatus.mode = 2;
00654         else
00655                 sendMsg->body.robotStatus.mode = 1;
00656         sendMsg->body.robotStatus.motion_possible = (int)(Ros_Controller_IsMotionReady(controller));
00657         
00658         return(sendMsg->prefix.length + sizeof(SmPrefix));
00659 }
00660 
00661 //-------------------------------------------------------------------
00662 // Get I/O state on the controller
00663 //-------------------------------------------------------------------
00664 BOOL Ros_Controller_StatusRead(Controller* controller, USHORT ioStatus[IO_ROBOTSTATUS_MAX])
00665 {
00666         return (mpReadIO(controller->ioStatusAddr, ioStatus, IO_ROBOTSTATUS_MAX) == 0);
00667 }
00668 
00669 //-------------------------------------------------------------------
00670 // Update I/O state on the controller
00671 //-------------------------------------------------------------------
00672 BOOL Ros_Controller_StatusUpdate(Controller* controller)
00673 {
00674         USHORT ioStatus[IO_ROBOTSTATUS_MAX];
00675         int i;
00676         
00677         if(Ros_Controller_StatusRead(controller, ioStatus))
00678         {
00679                 // Check for change of state and potentially react to the change
00680                 for(i=0; i<IO_ROBOTSTATUS_MAX; i++)
00681                 {
00682                         if(controller->ioStatus[i] != ioStatus[i])
00683                         {
00684                                 //printf("Change of ioStatus[%d]\r\n", i);
00685                                 
00686                                 controller->ioStatus[i] = ioStatus[i];
00687                                 switch(i)
00688                                 {
00689                                         case IO_ROBOTSTATUS_ALARM_MAJOR: // alarm
00690                                         case IO_ROBOTSTATUS_ALARM_MINOR: // alarm
00691                                         case IO_ROBOTSTATUS_ALARM_SYSTEM: // alarm
00692                                         case IO_ROBOTSTATUS_ALARM_USER: // alarm
00693                                         {
00694                                                 if(ioStatus[i] == 0)
00695                                                         controller->alarmCode = 0;
00696                                                 else
00697                                                         controller->alarmCode = Ros_Controller_GetAlarmCode();
00698                                         }
00699                                         //case IO_ROBOTSTATUS_ERROR: // error
00700                                         //              if(ioStatus[i] != 0)
00701                                         //              {
00702                                         //                      // Take action for alarm/error handling
00703                                         //              }
00704                                         //      break;
00705                                         case IO_ROBOTSTATUS_REMOTE: // remote
00706                                         case IO_ROBOTSTATUS_OPERATING: // operating
00707                                         case IO_ROBOTSTATUS_WAITING_ROS: // Job input signaling ready for external motion
00708                                         {
00709                                                 if(ioStatus[i] == 0)  // signal turned OFF
00710                                                 {
00711                                                         // Job execution stopped take action
00712                                                         controller->bRobotJobReady = FALSE;
00713                                                         controller->bRobotJobReadyRaised = FALSE;
00714                                                         Ros_MotionServer_ClearQ_All(controller);
00715                                                 }
00716                                                 else // signal turned ON
00717                                                 {
00718                                                         if(i==IO_ROBOTSTATUS_WAITING_ROS)
00719                                                                 controller->bRobotJobReadyRaised = TRUE;
00720                                                         
00721 #ifndef DUMMY_SERVO_MODE        
00722                                                         if(controller->bRobotJobReadyRaised
00723                                                                 && (Ros_Controller_IsOperating(controller))
00724                                                                 && (Ros_Controller_IsRemote(controller)) )
00725 #else
00726                                                         if(controller->bRobotJobReadyRaised
00727                                                                 && Ros_Controller_IsOperating(controller))
00728 #endif
00729                                                         {
00730                                                                 controller->bRobotJobReady = TRUE;
00731                                                                 if(Ros_Controller_IsMotionReady(controller))
00732                                                                         printf("Robot job is ready for ROS commands.\r\n");
00733                                                         }
00734                                                 }
00735                                                 break;
00736                                         }
00737                                 }
00738                         }
00739                 }
00740                 return TRUE;
00741         }
00742         return FALSE;
00743 }
00744 
00745 
00746 
00747 /**** Wrappers on MP standard function ****/
00748 
00749 //-------------------------------------------------------------------
00750 // Get I/O state on the controller
00751 //-------------------------------------------------------------------
00752 BOOL Ros_Controller_GetIOState(ULONG signal)
00753 {
00754         MP_IO_INFO ioInfo;
00755         USHORT ioState;
00756         int ret;
00757         
00758         //set feedback signal
00759         ioInfo.ulAddr = signal;
00760         ret = mpReadIO(&ioInfo, &ioState, 1);
00761         if(ret != 0)
00762                 printf("mpReadIO failure (%d)\r\n", ret);
00763                 
00764         return (ioState != 0);
00765 }
00766 
00767 
00768 //-------------------------------------------------------------------
00769 // Set I/O state on the controller
00770 //-------------------------------------------------------------------
00771 void Ros_Controller_SetIOState(ULONG signal, BOOL status)
00772 {
00773         MP_IO_DATA ioData;
00774         int ret;
00775         
00776         //set feedback signal
00777         ioData.ulAddr = signal;
00778         ioData.ulValue = status;
00779         ret = mpWriteIO(&ioData, 1);
00780         if(ret != 0)
00781                 printf("mpWriteIO failure (%d)\r\n", ret);
00782 }
00783 
00784 
00785 //-------------------------------------------------------------------
00786 // Get the code of the first alarm on the controller
00787 //-------------------------------------------------------------------
00788 int Ros_Controller_GetAlarmCode()
00789 {
00790         MP_ALARM_CODE_RSP_DATA alarmData;
00791         memset(&alarmData, 0x00, sizeof(alarmData));
00792         if(mpGetAlarmCode(&alarmData) == 0)
00793         {
00794                 if(alarmData.usAlarmNum > 0)
00795                         return(alarmData.AlarmData.usAlarmNo[0]);
00796                 else
00797                         return 0;
00798         }
00799         return -1;
00800 }
00801 
00802 
00803 //-------------------------------------------------------------------
00804 // Convert error code to string
00805 //-------------------------------------------------------------------
00806 void Ros_Controller_ErrNo_ToString(int errNo, char errMsg[ERROR_MSG_MAX_SIZE], int errMsgSize)
00807 {
00808         switch(errNo)
00809         {
00810                 case 0x2010: memcpy(errMsg, "Robot is in operation", errMsgSize); break;
00811                 case 0x2030: memcpy(errMsg, "In HOLD status (PP)", errMsgSize); break;
00812                 case 0x2040: memcpy(errMsg, "In HOLD status (External)", errMsgSize); break;
00813                 case 0x2050: memcpy(errMsg, "In HOLD status (Command)", errMsgSize); break;
00814                 case 0x2060: memcpy(errMsg, "In ERROR/ALARM status", errMsgSize); break;
00815                 case 0x2070: memcpy(errMsg, "In SERVO OFF status", errMsgSize); break;
00816                 case 0x2080: memcpy(errMsg, "Wrong operation mode", errMsgSize); break;
00817                 case 0x3040: memcpy(errMsg, "The home position is not registered", errMsgSize); break;
00818                 case 0x3050: memcpy(errMsg, "Out of range (ABSO data", errMsgSize); break;
00819                 case 0x3400: memcpy(errMsg, "Cannot operate MASTER JOB", errMsgSize); break;
00820                 case 0x3410: memcpy(errMsg, "The JOB name is already registered in another task", errMsgSize); break;
00821                 case 0x4040: memcpy(errMsg, "Specified JOB not found", errMsgSize); break;
00822                 case 0x5200: memcpy(errMsg, "Over data range", errMsgSize); break;
00823                 default: memcpy(errMsg, "Unspecified reason", errMsgSize); break;
00824         }
00825 }
00826 
00827 
00828 #ifdef DX100
00829 
00830 void Ros_Controller_ListenForSkill(Controller* controller, int sl)
00831 {
00832         SYS2MP_SENS_MSG skillMsg;
00833         STATUS apiRet;
00834         
00835         controller->bSkillMotionReady[sl - MP_SL_ID1] = FALSE;
00836         memset(&skillMsg, 0x00, sizeof(SYS2MP_SENS_MSG));
00837         
00838         FOREVER
00839         {
00840                 //SKILL complete
00841                 //This will cause the SKILLSND command to complete the cursor to move to the next line.
00842                 //Make sure all preparation is complete to move.
00843                 //mpEndSkillCommandProcess(sl, &skillMsg); 
00844                 mpEndSkillCommandProcess(sl, &skillMsg);
00845                 
00846                 Ros_Sleep(4); //sleepy time
00847                 
00848                 //Get SKILL command
00849                 //task will wait for a skillsnd command in INFORM
00850                 apiRet = mpReceiveSkillCommand(sl, &skillMsg);
00851                 
00852                 if (skillMsg.main_comm != MP_SKILL_COMM)
00853                 {
00854                         printf("Ignoring command, because it's not a SKILL command\n");
00855                         continue;
00856                 }
00857                 
00858                 //Process SKILL command
00859                 switch(skillMsg.sub_comm)
00860                 {
00861                 case MP_SKILL_SEND:
00862                         if(strcmp(skillMsg.cmd, "ROS-START") == 0)
00863                         {
00864                                 controller->bSkillMotionReady[sl - MP_SL_ID1] = TRUE;
00865                         }
00866                         else if(strcmp(skillMsg.cmd, "ROS-STOP") == 0)
00867                         {
00868                                 controller->bSkillMotionReady[sl - MP_SL_ID1] = FALSE;
00869                         }
00870                         else
00871                         {
00872                                 printf ("MP_SKILL_SEND(SL_ID=%d) - %s \n", sl, skillMsg.cmd);
00873                         }
00874 #ifdef DEBUG
00875                         printf("controller->bSkillMotionReady[%d] = %d\n", (sl - MP_SL_ID1), controller->bSkillMotionReady[sl - MP_SL_ID1]);
00876 #endif
00877 
00878                         if(Ros_Controller_IsMotionReady(controller))
00879                                 printf("Robot job is ready for ROS commands.\r\n");
00880                         break;
00881                         
00882                 case MP_SKILL_END:
00883                         //ABORT!!!
00884                         controller->bSkillMotionReady[sl - MP_SL_ID1] = FALSE;
00885                         break;
00886                 }
00887         }
00888 }
00889 #endif
00890 
00891 
00892 #if DX100
00893 // VxWorks 5.5 do not have vsnprintf, use vsprintf instead...
00894 int vsnprintf(char *s, size_t sz, const char *fmt, va_list args)
00895 {
00896         char tmpBuf[1024]; // Hopefully enough...
00897         size_t res;
00898         res = vsprintf(tmpBuf, fmt, args);
00899         tmpBuf[sizeof(tmpBuf) - 1] = 0;  // be sure ending \0 is there
00900         if (res >= sz)
00901         {
00902                 // Buffer overrun...
00903                 printf("Logging.. Error vsnprintf:%d max:%d, anyway:\r\n", (int)res, (int)sz);
00904                 printf("%s", tmpBuf);
00905                 res = -res;
00906         }
00907         strncpy(s, tmpBuf, sz);
00908         s[sz - 1] = 0;  // be sure ending \0 is there
00909         return res;
00910 }
00911 
00912 // VxWorks 5.5 do not have snprintf
00913 int snprintf(char *s, size_t sz, const char *fmt, ...)
00914 {
00915         size_t res;
00916         char tmpBuf[1024]; // Hopefully enough...
00917         va_list va;
00918 
00919         va_start(va, fmt);
00920         res = vsnprintf(tmpBuf, sz, fmt, va);
00921         va_end(va);
00922 
00923         strncpy(s, tmpBuf, sz);
00924         s[sz - 1] = 0;  // be sure ending \0 is there
00925         return res;
00926 }
00927 #endif
00928 
00929 void motoRosAssert(BOOL mustBeTrue, ROS_ASSERTION_CODE subCodeIfFalse, char* msgFmtIfFalse, ...)
00930 {
00931         const int MAX_MSG_LEN = 32;
00932         char msg[MAX_MSG_LEN];
00933         char subMsg[MAX_MSG_LEN];
00934         va_list va;
00935 
00936         if (!mustBeTrue)
00937         {
00938                 memset(msg, 0x00, MAX_MSG_LEN);
00939                 memset(subMsg, 0x00, MAX_MSG_LEN);
00940 
00941                 va_start(va, msgFmtIfFalse);
00942                 vsnprintf(subMsg, MAX_MSG_LEN, msgFmtIfFalse, va);
00943                 va_end(va);
00944 
00945                 snprintf(msg, MAX_MSG_LEN, "MotoROS:%s", subMsg); //add "MotoROS" to distinguish from other controller alarms
00946 
00947                 Ros_Controller_SetIOState(IO_FEEDBACK_FAILURE, TRUE);
00948                 Ros_Controller_SetIOState(IO_FEEDBACK_INITIALIZATION_DONE, FALSE);
00949 
00950                 mpSetAlarm(8000, msg, subCodeIfFalse);
00951 
00952                 while (TRUE) //forever
00953                 {
00954                         puts(msg);
00955                         Ros_Sleep(5000);
00956                 }
00957         }
00958 }
00959 
00960 void Db_Print(char* msgFormat, ...)
00961 {
00962 #ifdef DEBUG
00963         const int MAX_MSG_LEN = 128;
00964         char msg[MAX_MSG_LEN];
00965         va_list va;
00966 
00967         memset(msg, 0x00, MAX_MSG_LEN);
00968 
00969         va_start(va, msgFormat);
00970         vsnprintf(msg, MAX_MSG_LEN, msgFormat, va);
00971         va_end(va);
00972 
00973         printf(msg);
00974 #endif
00975 }
00976 
00977 void Ros_Sleep(float milliseconds)
00978 {
00979         mpTaskDelay(milliseconds / mpGetRtc()); //Tick length varies between controller models
00980 }


motoman_driver
Author(s): Jeremy Zoss (Southwest Research Institute)
autogenerated on Sat Jun 8 2019 19:06:57