MotionServer.c
Go to the documentation of this file.
1 // MotionServer.c
2 //
3 /*
4 * Software License Agreement (BSD License)
5 *
6 * Copyright (c) 2013, Yaskawa America, Inc.
7 * All rights reserved.
8 *
9 * Redistribution and use in binary form, with or without modification,
10 * is permitted provided that the following conditions are met:
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of the Yaskawa America, Inc., nor the names
16 * of its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 
32 #include "MotoROS.h"
33 
34 //-----------------------
35 // Function Declarations
36 //-----------------------
37 // Main Task:
38 void Ros_MotionServer_StartNewConnection(Controller* controller, int sd);
39 void Ros_MotionServer_StopConnection(Controller* controller, int connectionIndex);
40 
41 // WaitForSimpleMsg Task:
42 void Ros_MotionServer_WaitForSimpleMsg(Controller* controller, int connectionIndex);
43 BOOL Ros_MotionServer_SimpleMsgProcess(Controller* controller, SimpleMsg* receiveMsg, SimpleMsg* replyMsg);
44 int Ros_MotionServer_MotionCtrlProcess(Controller* controller, SimpleMsg* receiveMsg, SimpleMsg* replyMsg);
45 BOOL Ros_MotionServer_StopMotion(Controller* controller);
46 BOOL Ros_MotionServer_ServoPower(Controller* controller, int servoOnOff);
47 BOOL Ros_MotionServer_ResetAlarm(Controller* controller);
50 int Ros_MotionServer_JointTrajDataProcess(Controller* controller, SimpleMsg* receiveMsg, SimpleMsg* replyMsg);
55 int Ros_MotionServer_JointTrajPtFullExProcess(Controller* controller, SimpleMsg* receiveMsg, SimpleMsg* replyMsg);
56 int Ros_MotionServer_GetDhParameters(Controller* controller, SimpleMsg* replyMsg);
57 int Ros_MotionServer_SetSelectedTool(Controller* controller, SimpleMsg* receiveMsg, SimpleMsg* replyMsg);
58 
59 // AddToIncQueue Task:
63 BOOL Ros_MotionServer_ClearQ_All(Controller* controller);
65 int Ros_MotionServer_GetQueueCnt(Controller* controller, int groupNo);
67 
68 // Utility functions:
71 void Ros_MotionServer_PrintError(USHORT err_no, char* msgPrefix);
72 
73 //-----------------------
74 // Function implementation
75 //-----------------------
76 
77 //-----------------------------------------------------------------------
78 // Start the tasks for a new motion server connection:
79 // - WaitForSimpleMsg: Task that waits to receive new SimpleMessage
80 // - AddToIncQueueProcess: Task that take data from a message and generate Incmove
81 //-----------------------------------------------------------------------
83 {
84  int groupNo;
85  int connectionIndex;
86  int sockOpt;
87 
88  printf("Starting new connection to the Motion Server\r\n");
89 
90 ATTEMPT_MOTION_CONNECTION:
91  //look for next available connection slot
92  for (connectionIndex = 0; connectionIndex < MAX_MOTION_CONNECTIONS; connectionIndex++)
93  {
94  if (controller->sdMotionConnections[connectionIndex] == INVALID_SOCKET)
95  {
96  controller->sdMotionConnections[connectionIndex] = sd;
97  break;
98  }
99  }
100 
101  if (connectionIndex == MAX_MOTION_CONNECTIONS)
102  {
103  if (Ros_MotionServer_HasDataInQueue(controller)) //another client is actively controlling motion
104  {
105  puts("Motion server already connected... not accepting last attempt.");
106  mpClose(sd);
107  return;
108  }
109  else
110  {
111  puts("Motion server already connected... closing old connection.");
112  Ros_MotionServer_StopConnection(controller, 0); //close socket, cleanup resources, and delete tasks
113  goto ATTEMPT_MOTION_CONNECTION; //goto is sometimes useful... don't judge me
114  }
115  }
116 
117  //This timeout detection takes two hours. So, it's not terribly useful. But, it still serves a purpose.
118  sockOpt = 1;
119  mpSetsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char*)&sockOpt, sizeof(sockOpt));
120 
121  // If not started, start the IncMoveTask (there should be only one instance of this thread)
122  if(controller->tidIncMoveThread == INVALID_TASK)
123  {
124  puts("Creating new task: IncMoveTask");
125 
126  controller->tidIncMoveThread = mpCreateTask(MP_PRI_IP_CLK_TAKE, MP_STACK_SIZE,
128  (int)controller, 0, 0, 0, 0, 0, 0, 0, 0, 0);
129  if (controller->tidIncMoveThread == ERROR)
130  {
131  puts("Failed to create task for incremental-motion. Check robot parameters.");
132  mpClose(sd);
133  controller->tidIncMoveThread = INVALID_TASK;
135  mpSetAlarm(8004, "MOTOROS FAILED TO CREATE TASK", 4);
136 
137  return;
138  }
139  }
140 
141  // If not started, start the AddToIncQueueProcess for each control group
142  for(groupNo = 0; groupNo < controller->numGroup; groupNo++)
143  {
144  if (controller->ctrlGroups[groupNo]->tidAddToIncQueue == INVALID_TASK)
145  {
146  printf("Creating new task: tidAddToIncQueue (groupNo = %d)\n", groupNo);
147 
148  controller->ctrlGroups[groupNo]->tidAddToIncQueue = mpCreateTask(MP_PRI_TIME_NORMAL, MP_STACK_SIZE,
150  (int)controller, groupNo, 0, 0, 0, 0, 0, 0, 0, 0);
151  if (controller->ctrlGroups[groupNo]->tidAddToIncQueue == ERROR)
152  {
153  puts("Failed to create task for parsing motion increments. Check robot parameters.");
154  mpClose(sd);
155  controller->ctrlGroups[groupNo]->tidAddToIncQueue = INVALID_TASK;
157  mpSetAlarm(8004, "MOTOROS FAILED TO CREATE TASK", 5);
158  return;
159  }
160  }
161  }
162 
163 
164  if (controller->tidMotionConnections[connectionIndex] == INVALID_TASK)
165  {
166  printf("Creating new task: tidMotionConnections (connectionIndex = %d)\n", connectionIndex);
167 
168 
169  //start new task for this specific connection
170  controller->tidMotionConnections[connectionIndex] = mpCreateTask(MP_PRI_TIME_NORMAL, MP_STACK_SIZE,
172  (int)controller, connectionIndex, 0, 0, 0, 0, 0, 0, 0, 0);
173 
174  if (controller->tidMotionConnections[connectionIndex] != ERROR)
175  {
176  Ros_Controller_SetIOState(IO_FEEDBACK_MOTIONSERVERCONNECTED, TRUE); //set feedback signal indicating success
177  }
178  else
179  {
180  puts("Could not create new task in the motion server. Check robot parameters.");
181  mpClose(sd);
182  controller->sdMotionConnections[connectionIndex] = INVALID_SOCKET;
183  controller->tidMotionConnections[connectionIndex] = INVALID_TASK;
185  mpSetAlarm(8004, "MOTOROS FAILED TO CREATE TASK", 6);
186  return;
187  }
188  }
189 }
190 
191 
192 //-----------------------------------------------------------------------
193 // Close a connection along with all its associated task
194 //-----------------------------------------------------------------------
195 void Ros_MotionServer_StopConnection(Controller* controller, int connectionIndex)
196 {
197  int i;
198  int tid;
199  BOOL bDeleteIncMovTask;
200 
201  printf("Closing Motion Server Connection\r\n");
202 
203  //close this connection
204  mpClose(controller->sdMotionConnections[connectionIndex]);
205  //mark connection as invalid
206  controller->sdMotionConnections[connectionIndex] = INVALID_SOCKET;
207 
208  // Check if there are still some valid connection
209  bDeleteIncMovTask = TRUE;
210  for(i=0; i<MAX_MOTION_CONNECTIONS; i++)
211  {
212  if(controller->sdMotionConnections[connectionIndex] != INVALID_SOCKET)
213  {
214  bDeleteIncMovTask = FALSE;
215  break;
216  }
217  }
218 
219  // If there is no more connection, stop the inc_move task
220  if(bDeleteIncMovTask)
221  {
222  //set feedback signal
224 
225  // Stop adding increment to queue (for each ctrlGroup
226  for(i=0; i < controller->numGroup; i++)
227  {
228  controller->ctrlGroups[i]->hasDataToProcess = FALSE;
229  tid = controller->ctrlGroups[i]->tidAddToIncQueue;
230  controller->ctrlGroups[i]->tidAddToIncQueue = INVALID_TASK;
231  mpDeleteTask(tid);
232  }
233 
234  // terminate the inc_move task
235  tid = controller->tidIncMoveThread;
236  controller->tidIncMoveThread = INVALID_TASK;
237  mpDeleteTask(tid);
238  }
239 
240  // Stop message receiption task
241  tid = controller->tidMotionConnections[connectionIndex];
242  controller->tidMotionConnections[connectionIndex] = INVALID_TASK;
243  printf("Motion Server Connection Closed\r\n");
244 
245  mpDeleteTask(tid);
246 }
247 
249 {
250  int minSize = sizeof(SmPrefix) + sizeof(SmHeader);
251  int expectedSize;
252 
253  switch (receiveMsg->header.msgType)
254  {
255  case ROS_MSG_PING:
256  expectedSize = minSize;
257  break;
259  expectedSize = minSize + sizeof(SmBodyRobotStatus);
260  break;
262  expectedSize = minSize + sizeof(SmBodyJointTrajPtFull);
263  break;
265  expectedSize = minSize + sizeof(SmBodyJointFeedback);
266  break;
268  expectedSize = minSize + sizeof(SmBodyMotoMotionCtrl);
269  break;
271  expectedSize = minSize + sizeof(SmBodyMotoMotionReply);
272  break;
274  //Don't require the user to send data for non-existant control groups
275  if (recvByteSize >= (int)(minSize + sizeof(int))) //make sure I can at least get to [numberOfGroups] field
276  {
277  expectedSize = minSize + (sizeof(int) * 2);
278  expectedSize += (sizeof(SmBodyJointTrajPtExData) * receiveMsg->body.jointTrajDataEx.numberOfValidGroups); //check the number of groups to determine size of data
279  }
280  else
281  expectedSize = minSize + sizeof(SmBodyJointTrajPtFullEx);
282  break;
284  expectedSize = minSize + sizeof(SmBodyJointFeedbackEx);
285  break;
287  expectedSize = minSize + sizeof(SmBodyMotoReadIOBit);
288  break;
290  expectedSize = minSize + sizeof(SmBodyMotoWriteIOBit);
291  break;
293  expectedSize = minSize + sizeof(SmBodyMotoReadIOGroup);
294  break;
296  expectedSize = minSize + sizeof(SmBodyMotoWriteIOGroup);
297  break;
299  expectedSize = minSize; //no additional data on the request
300  break;
302  expectedSize = minSize + sizeof(SmBodySelectTool);
303  break;
304  default: //invalid message type
305  return -1;
306  }
307  return expectedSize;
308 }
309 
310 //-----------------------------------------------------------------------
311 // Task that waits to receive new SimpleMessage and then processes it
312 //-----------------------------------------------------------------------
313 void Ros_MotionServer_WaitForSimpleMsg(Controller* controller, int connectionIndex)
314 {
315  SimpleMsg receiveMsg;
316  SimpleMsg replyMsg;
317  int byteSize = 0, byteSizeResponse = 0;
318  int minSize = sizeof(SmPrefix) + sizeof(SmHeader);
319  int expectedSize;
320  int ret = 0;
321  int partialMsgByteCount = 0;
322  BOOL bSkipNetworkRecv = FALSE;
323 
324  while (TRUE) //keep accepting messages until connection closes
325  {
326  Ros_Sleep(0); //give it some time to breathe, if needed
327 
328  if (!bSkipNetworkRecv) //if I don't already have an extra complete packet buffered from the previous recv
329  {
330  //Receive message from the PC
331  memset((&receiveMsg) + partialMsgByteCount, 0x00, sizeof(SimpleMsg) - partialMsgByteCount);
332  byteSize = mpRecv(controller->sdMotionConnections[connectionIndex], (char*)((&receiveMsg) + partialMsgByteCount), sizeof(SimpleMsg) - partialMsgByteCount, 0);
333  if (byteSize <= 0)
334  break; //end connection
335 
336  byteSize += partialMsgByteCount;
337  partialMsgByteCount = 0;
338  }
339  else
340  {
341  byteSize = partialMsgByteCount;
342  partialMsgByteCount = 0;
343  bSkipNetworkRecv = FALSE;
344  }
345 
346  // Determine the expected size of the message
347  expectedSize = -1;
348  if(byteSize >= minSize)
349  {
350  expectedSize = Ros_MotionServer_GetExpectedByteSizeForMessageType(&receiveMsg, byteSize);
351 
352  if (expectedSize == -1)
353  {
354  printf("Unknown Message Received (%d)\r\n", receiveMsg.header.msgType);
356  }
357  else if (byteSize >= expectedSize) // Check message size
358  {
359  // Process the simple message
360  ret = Ros_MotionServer_SimpleMsgProcess(controller, &receiveMsg, &replyMsg);
361  if (ret != OK) //error during processing
362  {
363  break; //disconnect
364  }
365  else if (byteSize > expectedSize) // Received extra data in single message
366  {
367  //Special case where ROS_MSG_MOTO_JOINT_TRAJ_PT_FULL_EX message could have different lengths
369  byteSize == (int)(minSize + sizeof(SmBodyJointTrajPtFullEx)))
370  {
371  // All good
372  partialMsgByteCount = 0;
373  }
374  else
375  {
376  // Preserve the remaining bytes and treat them as the start of a new message
377  Db_Print("MessageReceived(%d bytes): expectedSize=%d, processing rest of bytes (%d, %d, %d)\r\n", byteSize, expectedSize, sizeof(receiveMsg), receiveMsg.body.jointTrajData.sequence, ((int*)((char*)&receiveMsg + expectedSize))[5]);
378  partialMsgByteCount = byteSize - expectedSize;
379  memmove(&receiveMsg, (char*)&receiveMsg + expectedSize, partialMsgByteCount);
380 
381  //Did I receive multiple full messages at once that all need to be processed before listening for new data?
382  if (partialMsgByteCount >= minSize)
383  {
384  expectedSize = Ros_MotionServer_GetExpectedByteSizeForMessageType(&receiveMsg, partialMsgByteCount);
385  bSkipNetworkRecv = (partialMsgByteCount >= expectedSize); //does my modified receiveMsg buffer contain a full message to process?
386  }
387  }
388  }
389  else // All good
390  partialMsgByteCount = 0;
391  }
392  else // Not enough data to process the command
393  {
394  Db_Print("MessageReceived(%d bytes): expectedSize=%d\r\n", byteSize, expectedSize);
396  }
397  }
398  else // Didn't even receive a command ID
399  {
400  Db_Print("Unknown Data Received (%d bytes)\r\n", byteSize);
402  }
403 
404  if (receiveMsg.header.commType != ROS_COMM_SERVICE_REPLY) //don't send a reply to a reply from the pc
405  {
406  //Send reply message
407  byteSizeResponse = mpSend(controller->sdMotionConnections[connectionIndex], (char*)(&replyMsg), replyMsg.prefix.length + sizeof(SmPrefix), 0);
408  if (byteSizeResponse <= 0)
409  break; // Close the connection
410  }
411  }
412 
413  Ros_Sleep(50); // Just in case other associated task need time to clean-up.
414 
415  //close this connection
416  Ros_MotionServer_StopConnection(controller, connectionIndex);
417 }
418 
419 
420 //-----------------------------------------------------------------------
421 // Checks the type of message and processes it accordingly
422 // Return -1=Failure; 0=Success; 1=CloseConnection;
423 //-----------------------------------------------------------------------
424 int Ros_MotionServer_SimpleMsgProcess(Controller* controller, SimpleMsg* receiveMsg, SimpleMsg* replyMsg)
425 {
426  int ret = ERROR;
427  int invalidSubcode = 0;
428 
429  switch(receiveMsg->header.msgType)
430  {
431  case ROS_MSG_PING:
432  memset(replyMsg, 0x00, sizeof(SimpleMsg));
433 
434  replyMsg->prefix.length = sizeof(SmHeader);
435  replyMsg->header.msgType = ROS_MSG_PING;
437  replyMsg->header.replyType = ROS_REPLY_SUCCESS;
438  ret = OK;
439  break;
440 
442  ret = Ros_MotionServer_JointTrajDataProcess(controller, receiveMsg, replyMsg);
443  break;
444 
445  //-----------------------
447  ret = Ros_MotionServer_MotionCtrlProcess(controller, receiveMsg, replyMsg);
448  break;
449 
450  //-----------------------
452  ret = Ros_MotionServer_JointTrajPtFullExProcess(controller, receiveMsg, replyMsg);
453  break;
454 
455 
456 //Maintain backward compatibility for users who are sending I/O over motion-server
457  //-----------------------
459  ret = Ros_IoServer_ReadIOBit(receiveMsg, replyMsg);
460  break;
461 
462  //-----------------------
464  ret = Ros_IoServer_WriteIOBit(receiveMsg, replyMsg);
465  break;
466 
467  //-----------------------
469  ret = Ros_IoServer_ReadIOGroup(receiveMsg, replyMsg);
470  break;
471 
472  //-----------------------
474  ret = Ros_IoServer_WriteIOGroup(receiveMsg, replyMsg);
475  break;
476 
477  //-----------------------
479  ret = Ros_MotionServer_GetDhParameters(controller, replyMsg);
480  break;
481 
482  //-----------------------
484  ret = Ros_MotionServer_SetSelectedTool(controller, receiveMsg, replyMsg);
485  break;
486 
487  //-----------------------
488  default:
489  printf("Invalid message type: %d\n", receiveMsg->header.msgType);
490  invalidSubcode = ROS_RESULT_INVALID_MSGTYPE;
491  break;
492  }
493 
494  // Check Invalid Case
495  if(invalidSubcode != 0)
496  {
497  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_INVALID, invalidSubcode, replyMsg, 0);
498  ret = ERROR;
499  }
500 
501  return ret;
502 }
503 
504 
505 //-----------------------------------------------------------------------
506 // Processes message of type: ROS_MSG_MOTO_JOINT_TRAJ_PT_FULL_EX
507 // Return -1=Failure; 0=Success; 1=CloseConnection;
508 //-----------------------------------------------------------------------
510  SimpleMsg* replyMsg)
511 {
512  SmBodyJointTrajPtFullEx* msgBody;
513  CtrlGroup* ctrlGroup;
514  int ret, i;
515  FlagsValidFields validationFlags;
516 
517  msgBody = &receiveMsg->body.jointTrajDataEx;
518 
519  // Check if controller is able to receive incremental move and if the incremental move thread is running
520  if(!Ros_Controller_IsMotionReady(controller))
521  {
522  int subcode = Ros_Controller_GetNotReadySubcode(controller);
523  printf("ERROR: Controller is not ready (code: %d). Can't process ROS_MSG_MOTO_JOINT_TRAJ_PT_FULL_EX.\r\n", subcode);
524  for (i = 0; i < msgBody->numberOfValidGroups; i += 1)
525  {
526  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_NOT_READY, subcode, replyMsg, msgBody->jointTrajPtData[i].groupNo);
527  }
528  return 0;
529  }
530 
531  // Pre-check to ensure no groups are busy
532  for (i = 0; i < msgBody->numberOfValidGroups; i += 1)
533  {
534  if (Ros_Controller_IsValidGroupNo(controller, msgBody->jointTrajPtData[i].groupNo))
535  {
536  ctrlGroup = controller->ctrlGroups[msgBody->jointTrajPtData[i].groupNo];
537  if (ctrlGroup->hasDataToProcess)
538  {
539  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_BUSY, 0, replyMsg, msgBody->jointTrajPtData[i].groupNo);
540  return 0;
541  }
542  }
543  else
544  {
545  printf("ERROR: GroupNo %d is not valid\n", msgBody->jointTrajPtData[i].groupNo);
547  return 0;
548  }
549 
550  // Check that minimum information (time, position, velocity) is valid
551  validationFlags = Valid_Time | Valid_Position | Valid_Velocity;
552  if( (msgBody->jointTrajPtData[i].validFields & validationFlags) != validationFlags)
553  {
554  printf("ERROR: Validfields = %d\r\n", msgBody->jointTrajPtData[i].validFields);
556  return 0;
557  }
558  }
559 
560  for (i = 0; i < msgBody->numberOfValidGroups; i += 1)
561  {
562  ctrlGroup = controller->ctrlGroups[msgBody->jointTrajPtData[i].groupNo];
563 
564  // Check the trajectory sequence code
565  if(msgBody->sequence == 0) // First trajectory point
566  {
567  // Initialize first point variables
568  ret = Ros_MotionServer_InitTrajPointFullEx(ctrlGroup, &msgBody->jointTrajPtData[i], msgBody->sequence);
569 
570  // set reply
571  if(ret == 0)
572  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, msgBody->jointTrajPtData[i].groupNo);
573  else
574  {
575  printf("ERROR: Ros_MotionServer_InitTrajPointFullEx returned %d\n", ret);
576  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_INVALID, ret, replyMsg, msgBody->jointTrajPtData[i].groupNo);
577  return 0; //stop processing other groups in this loop
578  }
579  }
580  else if(msgBody->sequence > 0)// Subsequent trajectory points
581  {
582  // Add the point to the trajectory
583  ret = Ros_MotionServer_AddTrajPointFullEx(ctrlGroup, &msgBody->jointTrajPtData[i], msgBody->sequence);
584 
585  // ser reply
586  if(ret == 0)
587  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, msgBody->jointTrajPtData[i].groupNo);
588  else if(ret == 1)
589  {
590  printf("ERROR: Ros_MotionServer_AddTrajPointFullEx returned %d\n", ret);
591  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_BUSY, 0, replyMsg, msgBody->jointTrajPtData[i].groupNo);
592  return 0; //stop processing other groups in this loop
593  }
594  else
595  {
596  printf("ERROR: Ros_MotionServer_AddTrajPointFullEx returned %d\n", ret);
597  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_INVALID, ret, replyMsg, msgBody->jointTrajPtData[i].groupNo);
598  return 0; //stop processing other groups in this loop
599  }
600  }
601  else
602  {
604  return 0; //stop processing other groups in this loop
605  }
606  }
607 
608  return 0;
609 }
610 
611 
612 //-----------------------------------------------------------------------
613 // Processes message of type: ROS_MSG_MOTO_MOTION_CTRL
614 // Return -1=Failure; 0=Success; 1=CloseConnection;
615 //-----------------------------------------------------------------------
617  SimpleMsg* replyMsg)
618 {
619  SmBodyMotoMotionCtrl* motionCtrl;
620 
621  //printf("In MotionCtrlProcess\r\n");
622 
623  // Check the command code
624  motionCtrl = &receiveMsg->body.motionCtrl;
625  switch(motionCtrl->command)
626  {
628  {
629  if(Ros_Controller_IsMotionReady(controller))
630  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_TRUE, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
631  else
633  break;
634  }
636  {
637  int count = Ros_MotionServer_GetQueueCnt(controller, motionCtrl->groupNo);
638  if(count >= 0)
639  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_TRUE, count, replyMsg, receiveMsg->body.motionCtrl.groupNo);
640  else
641  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_FAILURE, count, replyMsg, receiveMsg->body.motionCtrl.groupNo);
642  break;
643  }
644  case ROS_CMD_STOP_MOTION:
645  {
646  // Stop Motion
647  BOOL bRet = Ros_MotionServer_StopMotion(controller);
648 
649  // Reply msg
650  if(bRet)
651  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
652  else
653  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_FAILURE, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
654  break;
655  }
657  {
658  // Stop Motion
659  BOOL bRet = Ros_MotionServer_ServoPower(controller, ON);
660 
661  // Reply msg
662  if(bRet)
663  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
664  else
665  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_FAILURE, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
666  break;
667  }
668  case ROS_CMD_STOP_SERVOS:
669  {
670  // Stop Motion
671  BOOL bRet = Ros_MotionServer_ServoPower(controller, OFF);
672 
673  // Reply msg
674  if(bRet)
675  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
676  else
677  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_FAILURE, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
678  break;
679  }
680  case ROS_CMD_RESET_ALARM:
681  {
682  // Stop Motion
683  BOOL bRet = Ros_MotionServer_ResetAlarm(controller);
684 
685  // Reply msg
686  if(bRet)
687  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
688  else
689  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_FAILURE, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
690  break;
691  }
693  {
694  // Start Trajectory mode by starting the INIT_ROS job on the controller
695  BOOL bRet = Ros_MotionServer_StartTrajMode(controller);
696  if(bRet)
697  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
698  else
700  Ros_Controller_GetNotReadySubcode(controller), replyMsg, receiveMsg->body.motionCtrl.groupNo);
701  break;
702  }
704  case ROS_CMD_DISCONNECT:
705  {
706  BOOL bRet = Ros_MotionServer_StopTrajMode(controller);
707  if(bRet)
708  {
709  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
710  if(motionCtrl->command == ROS_CMD_DISCONNECT)
711  return 1;
712  }
713  else
714  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_FAILURE, 0, replyMsg, receiveMsg->body.motionCtrl.groupNo);
715  break;
716  }
717  }
718 
719  return 0;
720 }
721 
722 
723 //-----------------------------------------------------------------------
724 // Stop motion by stopping message processing and clearing the queue
725 //-----------------------------------------------------------------------
727 {
728  // NOTE: for the time being, stop motion will stop all motion for all control group
729  BOOL bRet;
730  BOOL bStopped;
731  int checkCnt;
732  int groupNo;
733 
734  // Stop any motion from being processed further
735  controller->bStopMotion = TRUE;
736 
737  // Check that background processing of message has been stopped
738  for(checkCnt=0; checkCnt<MOTION_STOP_TIMEOUT; checkCnt++)
739  {
740  bStopped = TRUE;
741  for(groupNo=0; groupNo<controller->numGroup; groupNo++)
742  bStopped &= !controller->ctrlGroups[groupNo]->hasDataToProcess;
743  if(bStopped)
744  break;
745  else
746  Ros_Sleep(1);
747  }
748 
749  // Clear queues
750  bRet = Ros_MotionServer_ClearQ_All(controller);
751 
752  // All motion should be stopped at this point, so turn of the flag
753  controller->bStopMotion = FALSE;
754 
755  return(bStopped && bRet);
756 }
757 
758 
759 //-----------------------------------------------------------------------
760 // Sets servo power to ON or OFF
761 //-----------------------------------------------------------------------
762 BOOL Ros_MotionServer_ServoPower(Controller* controller, int servoOnOff)
763 {
764  MP_SERVO_POWER_SEND_DATA sServoData;
765  MP_STD_RSP_DATA stdRespData;
766  int ret;
767  STATUS status;
768 
769 #ifdef DUMMY_SERVO_MODE
770  return TRUE;
771 #endif
772 
773  if (servoOnOff == OFF)
774  Ros_MotionServer_StopMotion(controller);
775 
776  if (servoOnOff == ON)
777  {
778  status = Ros_MotionServer_DisableEcoMode(controller);
779  if (status == NG)
780  {
781  Ros_Controller_StatusUpdate(controller);
782  return Ros_Controller_IsServoOn(controller) == servoOnOff;
783  }
784  }
785 
786  printf("Setting servo power: %d\n", servoOnOff);
787  memset(&sServoData, 0x00, sizeof(sServoData));
788  memset(&stdRespData, 0x00, sizeof(stdRespData));
789  sServoData.sServoPower = servoOnOff;
790 
791  ret = mpSetServoPower(&sServoData, &stdRespData);
792  if( (ret == 0) && (stdRespData.err_no == 0) )
793  {
794  // wait for confirmation
795  int checkCount;
796  for(checkCount=0; checkCount<MOTION_START_TIMEOUT; checkCount+=MOTION_START_CHECK_PERIOD)
797  {
798  // Update status
799  Ros_Controller_StatusUpdate(controller);
800 
801  if(Ros_Controller_IsServoOn(controller) == servoOnOff)
802  break;
803 
805  }
806  }
807  else
808  {
809  Ros_MotionServer_PrintError(stdRespData.err_no, "Can't turn off servo because:");
810  }
811 
812  // Update status
813  Ros_Controller_StatusUpdate(controller);
814  return Ros_Controller_IsServoOn(controller) == servoOnOff;
815 }
816 
818 {
819  int ret, i;
820  BOOL returnBoolean;
821  MP_ALARM_STATUS_RSP_DATA alarmstatus;
822  MP_STD_RSP_DATA responseData;
823 
824  returnBoolean = TRUE;
825 
826  ret = mpGetAlarmStatus(&alarmstatus);
827  if( ret != 0 )
828  {
829  printf("Could not get alarm status\n");
830  //Ignore this error. Continue to try and clear the alarm.
831  }
832 
833  if (alarmstatus.sIsAlarm & MASK_ISALARM_ACTIVEALARM) //alarm is active
834  {
835  MP_ALARM_CODE_RSP_DATA alarmcode;
836  ret = mpGetAlarmCode(&alarmcode);
837  if( ret != 0 )
838  {
839  printf("Could not get alarm code\n");
840  //Ignore this error. Continue to try and clear the alarm.
841  }
842  else
843  {
844  for (i = 0; i < alarmcode.usAlarmNum; i += 1)
845  printf("Has alarm: %d[%d], resetting...\n", alarmcode.AlarmData.usAlarmNo[i], alarmcode.AlarmData.usAlarmData[i]);
846  }
847 
848  ret = mpResetAlarm(&responseData);
849  if( ret != 0 )
850  {
851  printf("Could not reset the alarm, failure code: %d\n", responseData.err_no);
852  returnBoolean = FALSE;
853  }
854  }
855 
856  if (alarmstatus.sIsAlarm & MASK_ISALARM_ACTIVEERROR) //error is active
857  {
858  MP_ALARM_CODE_RSP_DATA alarmcode;
859  ret = mpGetAlarmCode(&alarmcode);
860  if (ret != 0)
861  {
862  printf("Could not get error code\n");
863  //Ignore this problem. Continue to try and clear the error.
864  }
865  else
866  {
867  printf("Has error: %d[%d], resetting...\n", alarmcode.usErrorNo, alarmcode.usErrorData);
868  }
869 
870  ret = mpCancelError(&responseData);
871  if (ret != 0)
872  {
873  printf("Could not cancel the error, failure code: %d\n", responseData.err_no);
874  returnBoolean = FALSE;
875  }
876  }
877 
878  Ros_Controller_StatusUpdate(controller);
879  return returnBoolean;
880 }
881 
882 //-----------------------------------------------------------------------
883 // Attempts to start playback of a job to put the controller in RosMotion mode
884 //-----------------------------------------------------------------------
886 {
887  int ret;
888  MP_STD_RSP_DATA rData;
889  MP_START_JOB_SEND_DATA sStartData;
890  int checkCount;
891  int grpNo;
892  STATUS status;
893 
894  printf("In StartTrajMode\r\n");
895 
896  // Update status
897  Ros_Controller_StatusUpdate(controller);
898 
899  // Reset PFL Activation Flag
900  if (controller->bPFLduringRosMove)
901  controller->bPFLduringRosMove = FALSE;
902 
903  // Check if already in the proper mode
904  if(Ros_Controller_IsMotionReady(controller))
905  return TRUE;
906 
907  // Check if currently in operation, we don't want to interrupt current operation
908  if(Ros_Controller_IsOperating(controller))
909  return FALSE;
910 
911 #ifndef DUMMY_SERVO_MODE
912  // Check for condition that need operator manual intervention
913  if(Ros_Controller_IsEStop(controller)
914  || Ros_Controller_IsHold(controller)
915  || !Ros_Controller_IsRemote(controller))
916  return FALSE;
917 #endif
918 
919  // Check for condition that can be fixed remotely
920  if(Ros_Controller_IsError(controller))
921  {
922  // Cancel error
923  memset(&rData, 0x00, sizeof(rData));
924  ret = mpCancelError(&rData);
925  if(ret != 0)
926  goto updateStatus;
927  }
928 
929  // Check for condition that can be fixed remotely
930  if(Ros_Controller_IsAlarm(controller))
931  {
932  // Reset alarm
933  memset(&rData, 0x00, sizeof(rData));
934  ret = mpResetAlarm(&rData);
935  if(ret == 0)
936  {
937  // wait for the Alarm reset confirmation
938  int checkCount;
939  for(checkCount=0; checkCount<MOTION_START_TIMEOUT; checkCount+=MOTION_START_CHECK_PERIOD)
940  {
941  // Update status
942  Ros_Controller_StatusUpdate(controller);
943 
944  if(Ros_Controller_IsAlarm(controller) == FALSE)
945  continue;
946 
948  }
949  if(Ros_Controller_IsAlarm(controller))
950  goto updateStatus;
951  }
952  else
953  goto updateStatus;
954  }
955 
956 
957 #ifndef DUMMY_SERVO_MODE
958  // Servo On
959  if(Ros_Controller_IsServoOn(controller) == FALSE)
960  {
961  MP_SERVO_POWER_SEND_DATA sServoData;
962  memset(&sServoData, 0x00, sizeof(sServoData));
963 
964  status = Ros_MotionServer_DisableEcoMode(controller);
965  if (status == NG)
966  {
967  goto updateStatus;
968  }
969 
970  sServoData.sServoPower = 1; // ON
971  memset(&rData, 0x00, sizeof(rData));
972  ret = mpSetServoPower(&sServoData, &rData);
973  if( (ret == 0) && (rData.err_no ==0) )
974  {
975  // wait for the Servo On confirmation
976  int checkCount;
977  for(checkCount=0; checkCount<MOTION_START_TIMEOUT; checkCount+=MOTION_START_CHECK_PERIOD)
978  {
979  // Update status
980  Ros_Controller_StatusUpdate(controller);
981 
982  if (Ros_Controller_IsServoOn(controller) == TRUE)
983  break;
984 
986  }
987  if(Ros_Controller_IsServoOn(controller) == FALSE)
988  goto updateStatus;
989  }
990  else
991  {
992  Ros_MotionServer_PrintError(rData.err_no, "Can't turn on servo because:");
993  goto updateStatus;
994  }
995  }
996 #endif
997 
998  // have to initialize the prevPulsePos that will be used when interpolating the traj
999  for(grpNo = 0; grpNo < MP_GRP_NUM; ++grpNo)
1000  {
1001  if(controller->ctrlGroups[grpNo] != NULL)
1002  {
1003  Ros_CtrlGroup_GetPulsePosCmd(controller->ctrlGroups[grpNo], controller->ctrlGroups[grpNo]->prevPulsePos);
1004  }
1005  }
1006 
1007  // Start Job
1008  memset(&rData, 0x00, sizeof(rData));
1009  memset(&sStartData, 0x00, sizeof(sStartData));
1010  sStartData.sTaskNo = 0;
1011  memcpy(sStartData.cJobName, MOTION_INIT_ROS_JOB, MAX_JOB_NAME_LEN);
1012  ret = mpStartJob(&sStartData, &rData);
1013  if( (ret != 0) || (rData.err_no !=0) )
1014  {
1015  Ros_MotionServer_PrintError(rData.err_no, "Can't start job because:");
1016  goto updateStatus;
1017  }
1018 
1019  // wait for the Motion Ready
1020  for(checkCount=0; checkCount<MOTION_START_TIMEOUT; checkCount+=MOTION_START_CHECK_PERIOD)
1021  {
1022  // Update status
1023  Ros_Controller_StatusUpdate(controller);
1024 
1025  if(Ros_Controller_IsMotionReady(controller))
1026  return(TRUE);
1027 
1029  }
1030 
1031 updateStatus:
1032  // Update status
1033  Ros_Controller_StatusUpdate(controller);
1034 
1035  return (Ros_Controller_IsMotionReady(controller));
1036 }
1037 
1038 
1039 
1040 //-----------------------------------------------------------------------
1041 // Set I/O signal matching the WAIT instruction to allow the controller
1042 // to resume job execution
1043 //-----------------------------------------------------------------------
1045 {
1046  // Don't change mode if queue is not empty
1047  if(Ros_MotionServer_HasDataInQueue(controller))
1048  {
1049  //printf("Failed: Ros_MotionServer_HasDataInQueue is true\r\n");
1050  return FALSE;
1051  }
1052 
1053  // Stop motion
1054  if(!Ros_MotionServer_StopMotion(controller))
1055  {
1056  //printf("Failed: Ros_MotionServer_StopMotion is false\r\n");
1057  return FALSE;
1058  }
1059 
1060  // Set I/O signal
1062 
1063  return TRUE;
1064 }
1065 
1066 
1067 //-----------------------------------------------------------------------
1068 // Processes message of type: ROS_MSG_JOINT_TRAJ_PT_FULL
1069 // Return: 0=Success; -1=Failure
1070 //-----------------------------------------------------------------------
1072  SimpleMsg* replyMsg)
1073 {
1074  SmBodyJointTrajPtFull* trajData;
1075  CtrlGroup* ctrlGroup;
1076  int ret;
1077  FlagsValidFields validationFlags;
1078 
1079  // Check if controller is able to receive incremental move and if the incremental move thread is running
1080  if(!Ros_Controller_IsMotionReady(controller))
1081  {
1082  int subcode = Ros_Controller_GetNotReadySubcode(controller);
1083  printf("ERROR: Controller is not ready (code: %d). Can't process ROS_MSG_JOINT_TRAJ_PT_FULL.\r\n", subcode);
1084  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_NOT_READY, subcode, replyMsg, receiveMsg->body.jointTrajData.groupNo);
1085  return 0;
1086  }
1087 
1088  // Set pointer reference
1089  trajData = &receiveMsg->body.jointTrajData;
1090 
1091  // Check group number valid
1092  if(Ros_Controller_IsValidGroupNo(controller, trajData->groupNo))
1093  {
1094  ctrlGroup = controller->ctrlGroups[trajData->groupNo];
1095  }
1096  else
1097  {
1099  return 0;
1100  }
1101 
1102  // Check that minimum information (time, position, velocity) is valid
1103  validationFlags = Valid_Time | Valid_Position | Valid_Velocity;
1104  if( (trajData->validFields & validationFlags) != validationFlags)
1105  {
1106  printf("ERROR: Validfields = %d\r\n", trajData->validFields);
1108  return 0;
1109  }
1110 
1111  //Due to data loss when converting from double (ROS PC) to float (Simple Message serialization), we cannot accept
1112  //a single trjectory that lasts more than 4 hours.
1113  if (trajData->time >= MAX_TRAJECTORY_TIME_LENGTH)
1114  {
1115  printf("ERROR: Trajectory time (%.4f) > MAX_TRAJECTORY_TIME_LENGTH (%.4f)\r\n", trajData->time, MAX_TRAJECTORY_TIME_LENGTH);
1117  return 0;
1118  }
1119 
1120  // Check the trajectory sequence code
1121  if(trajData->sequence == 0) // First trajectory point
1122  {
1123  // Initialize first point variables
1124  ret = Ros_MotionServer_InitTrajPointFull(ctrlGroup, trajData);
1125 
1126  // set reply
1127  if(ret == 0)
1128  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.jointTrajData.groupNo);
1129  else
1130  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_INVALID, ret, replyMsg, receiveMsg->body.jointTrajData.groupNo);
1131  }
1132  else if(trajData->sequence > 0)// Subsequent trajectory points
1133  {
1134  // Add the point to the trajectory
1135  ret = Ros_MotionServer_AddTrajPointFull(ctrlGroup, trajData);
1136 
1137  // ser reply
1138  if(ret == 0)
1139  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, receiveMsg->body.jointTrajData.groupNo);
1140  else if(ret == 1)
1141  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_BUSY, 0, replyMsg, receiveMsg->body.jointTrajData.groupNo);
1142  else
1143  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_INVALID, ret, replyMsg, receiveMsg->body.jointTrajData.groupNo);
1144  }
1145  else
1146  {
1148  }
1149 
1150  return 0;
1151 }
1152 
1153 //-----------------------------------------------------------------------
1154 // Convert SmBodyMotoJointTrajPtExData data to SmBodyJointTrajPtFull
1155 //-----------------------------------------------------------------------
1157 {
1158  SmBodyJointTrajPtFull jointTrajData;
1159 
1160  //convert SmBodyMotoJointTrajPtExData data to SmBodyJointTrajPtFull
1161  jointTrajData.groupNo = jointTrajDataEx->groupNo;
1162  jointTrajData.sequence = sequence;
1163  jointTrajData.validFields = jointTrajDataEx->validFields;
1164  jointTrajData.time = jointTrajDataEx->time;
1165  memcpy(jointTrajData.pos, jointTrajDataEx->pos, sizeof(float)*ROS_MAX_JOINT);
1166  memcpy(jointTrajData.vel, jointTrajDataEx->vel, sizeof(float)*ROS_MAX_JOINT);
1167  memcpy(jointTrajData.acc, jointTrajDataEx->acc, sizeof(float)*ROS_MAX_JOINT);
1168 
1169  return Ros_MotionServer_InitTrajPointFull(ctrlGroup, &jointTrajData);
1170 }
1171 
1172 //-----------------------------------------------------------------------
1173 // Setup the first point of a trajectory
1174 //-----------------------------------------------------------------------
1176 {
1177  long pulsePos[MAX_PULSE_AXES];
1178  long curPos[MAX_PULSE_AXES];
1179  int i;
1180 
1181  if(ctrlGroup->groupNo == jointTrajData->groupNo)
1182  {
1183  // Assign start position
1184  Ros_MotionServer_ConvertToJointMotionData(jointTrajData, &ctrlGroup->jointMotionData);
1185  ctrlGroup->timeLeftover_ms = 0;
1186  ctrlGroup->q_time = ctrlGroup->jointMotionData.time;
1187 
1188  // For MPL80/100 robot type (SLUBT): Controller automatically moves the B-axis
1189  // to maintain orientation as other axes are moved.
1190  if (ctrlGroup->bIsBaxisSlave)
1191  {
1192  //ROS joint order
1193  ctrlGroup->jointMotionData.pos[3] += -ctrlGroup->jointMotionData.pos[1] + ctrlGroup->jointMotionData.pos[2];
1194  ctrlGroup->jointMotionData.vel[3] += -ctrlGroup->jointMotionData.vel[1] + ctrlGroup->jointMotionData.vel[2];
1195  }
1196 
1197  // Convert start position to pulse format
1198  Ros_CtrlGroup_ConvertToMotoPos(ctrlGroup, ctrlGroup->jointMotionData.pos, pulsePos);
1199  Ros_CtrlGroup_GetPulsePosCmd(ctrlGroup, curPos);
1200 
1201  // Initialize prevPulsePos to the current position
1202  Ros_CtrlGroup_GetPulsePosCmd(ctrlGroup, ctrlGroup->prevPulsePos);
1203 
1204  // Check for each axis
1205  for(i=0; i<MAX_PULSE_AXES; i++)
1206  {
1207  // Check if position matches current command position
1208  if(abs(pulsePos[i] - curPos[i]) > START_MAX_PULSE_DEVIATION)
1209  {
1210  printf("ERROR: Trajectory start position doesn't match current position (MOTO joint order).\r\n");
1211  printf(" - Requested start: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld\r\n",
1212  pulsePos[0], pulsePos[1], pulsePos[2],
1213  pulsePos[3], pulsePos[4], pulsePos[5],
1214  pulsePos[6], pulsePos[7]);
1215  printf(" - Current pos: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld\r\n",
1216  curPos[0], curPos[1], curPos[2],
1217  curPos[3], curPos[4], curPos[5],
1218  curPos[6], curPos[7]);
1219  printf(" - ctrlGroup->prevPulsePos: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld\r\n",
1220  ctrlGroup->prevPulsePos[0], ctrlGroup->prevPulsePos[1], ctrlGroup->prevPulsePos[2],
1221  ctrlGroup->prevPulsePos[3], ctrlGroup->prevPulsePos[4], ctrlGroup->prevPulsePos[5],
1222  ctrlGroup->prevPulsePos[6], ctrlGroup->prevPulsePos[7]);
1223 
1225  }
1226 
1227  // Check maximum velocity limit
1228  if(abs(ctrlGroup->jointMotionData.vel[i]) > ctrlGroup->maxSpeed[i])
1229  {
1230  // excessive speed
1232  }
1233  }
1234 
1235  //printf("Trajectory Start Initialized\r\n");
1236  // Return success
1237  return 0;
1238  }
1239 
1241 }
1242 
1243 //-----------------------------------------------------------------------
1244 // Convert SmBodyMotoJointTrajPtExData data to SmBodyJointTrajPtFull
1245 //-----------------------------------------------------------------------
1247 {
1248  SmBodyJointTrajPtFull jointTrajData;
1249 
1250  //convert SmBodyMotoJointTrajPtExData data to SmBodyJointTrajPtFull
1251  jointTrajData.groupNo = jointTrajDataEx->groupNo;
1252  jointTrajData.sequence = sequence;
1253  jointTrajData.validFields = jointTrajDataEx->validFields;
1254  jointTrajData.time = jointTrajDataEx->time;
1255  memcpy(jointTrajData.pos, jointTrajDataEx->pos, sizeof(float)*ROS_MAX_JOINT);
1256  memcpy(jointTrajData.vel, jointTrajDataEx->vel, sizeof(float)*ROS_MAX_JOINT);
1257  memcpy(jointTrajData.acc, jointTrajDataEx->acc, sizeof(float)*ROS_MAX_JOINT);
1258 
1259  return Ros_MotionServer_AddTrajPointFull(ctrlGroup, &jointTrajData);
1260 }
1261 
1262 
1263 //-----------------------------------------------------------------------
1264 // Setup the subsequent point of a trajectory
1265 //-----------------------------------------------------------------------
1267 {
1268  int i;
1269  JointMotionData jointData;
1270 
1271  // Check that there isn't data current being processed
1272  if(ctrlGroup->hasDataToProcess)
1273  {
1274  // Busy
1275  return ROS_RESULT_BUSY;
1276  }
1277 
1278  // Convert message data to a jointMotionData
1279  Ros_MotionServer_ConvertToJointMotionData(jointTrajData, &jointData);
1280 
1281  // Check that incoming data is valid
1282  for(i=0; i<ctrlGroup->numAxes; i++)
1283  {
1284  // Check position softlimit
1285  // TODO? Note need to add function to Parameter Extraction Library
1286 
1287  // Velocity check
1288  if(abs(jointData.vel[i]) > ctrlGroup->maxSpeed[i])
1289  {
1290  // excessive speed
1291  printf("ERROR: Invalid speed in message TrajPointFull data: \r\n axis: %d, speed: %f, limit: %f\r\n",
1292  i, jointData.vel[i], ctrlGroup->maxSpeed[i]);
1293 
1294  #ifdef DEBUG
1295  Ros_SimpleMsg_DumpTrajPtFull(jointTrajData);
1296  #endif
1297 
1299  }
1300  }
1301 
1302  // Store of the message trajectory data to the control group for processing
1303  memcpy(&ctrlGroup->jointMotionDataToProcess, &jointData, sizeof(JointMotionData));
1304  ctrlGroup->hasDataToProcess = TRUE;
1305 
1306  return 0;
1307 }
1308 
1309 
1310 //-----------------------------------------------------------------------
1311 // Task that handles in the background messages that may have long processing
1312 // time so that they don't block other message from being processed.
1313 // Checks the type of message and processes it accordingly.
1314 //-----------------------------------------------------------------------
1316 {
1317  int interpolPeriod;
1318  CtrlGroup* ctrlGroup = controller->ctrlGroups[groupNo];
1319 
1320  // Initialization of pointers and memory
1321  interpolPeriod = controller->interpolPeriod;
1322  ctrlGroup->hasDataToProcess = FALSE;
1323 
1324  FOREVER
1325  {
1326  // if there is no message to process delay and try agsain
1327  if(ctrlGroup->hasDataToProcess)
1328  {
1329  // Interpolate increment move to reach position data
1330  Ros_MotionServer_JointTrajDataToIncQueue(controller, groupNo);
1331 
1332  // Mark message as processed
1333  ctrlGroup->hasDataToProcess = FALSE;
1334  }
1335 
1336  Ros_Sleep(interpolPeriod);
1337  }
1338 }
1339 
1340 
1341 //-----------------------------------------------------------------------
1342 // Decompose the message type: ROS_MSG_JOINT_TRAJ_PT_FULL into incremental
1343 // moves to be added to the inc move queue.
1344 // Interpolation is based on position, velocity and time
1345 // Acceleration is modeled by a linear equation acc = accCoef1 + accCoef2 * time
1346 //-----------------------------------------------------------------------
1348 {
1349  int interpolPeriod = controller->interpolPeriod;
1350  CtrlGroup* ctrlGroup = controller->ctrlGroups[groupNo];
1351  int i;
1352  JointMotionData _startTrajData;
1353  JointMotionData* startTrajData;
1354  JointMotionData* endTrajData;
1355  JointMotionData* curTrajData;
1356  float interval; // Time between startTime and the new data time
1357  float accCoef1[MP_GRP_AXES_NUM]; // Acceleration coefficient 1
1358  float accCoef2[MP_GRP_AXES_NUM]; // Acceleration coefficient 2
1359  int timeInc_ms; // time increment in millisecond
1360  int calculationTime_ms; // time in ms at which the interpolation takes place
1361  float interpolTime; // time increment in second
1362  long newPulsePos[MP_GRP_AXES_NUM];
1363  Incremental_data incData;
1364 
1365  //printf("Starting JointTrajDataProcess\r\n");
1366 
1367  // Initialization of pointers and memory
1368  curTrajData = &ctrlGroup->jointMotionData;
1369  endTrajData = &ctrlGroup->jointMotionDataToProcess;
1370  startTrajData = &_startTrajData;
1371  // Set the start of the trajectory interpolation as the current position (which should be the end of last interpolation)
1372  memcpy(startTrajData, curTrajData, sizeof(JointMotionData));
1373 
1374  // For MPL80/100 robot type (SLUBT): Controller automatically moves the B-axis
1375  // to maintain orientation as other axes are moved.
1376  if (ctrlGroup->bIsBaxisSlave)
1377  {
1378  //ROS joint order
1379  endTrajData->pos[3] += -endTrajData->pos[1] + endTrajData->pos[2];
1380  endTrajData->vel[3] += -endTrajData->vel[1] + endTrajData->vel[2];
1381  }
1382 
1383  memset(newPulsePos, 0x00, sizeof(newPulsePos));
1384  memset(&incData, 0x00, sizeof(incData));
1385  incData.frame = MP_INC_PULSE_DTYPE;
1386  incData.tool = ctrlGroup->tool;
1387 
1388  // Calculate an acceleration coefficients
1389  memset(&accCoef1, 0x00, sizeof(accCoef1));
1390  memset(&accCoef2, 0x00, sizeof(accCoef2));
1391  interval = (endTrajData->time - startTrajData->time) / 1000.0f; // time difference in sec
1392  if (interval > 0.0)
1393  {
1394  for (i = 0; i < ctrlGroup->numAxes; i++)
1395  {
1396  //Calculate acceleration coefficient (convert interval to seconds
1397  accCoef1[i] = ( 6 * (endTrajData->pos[i] - startTrajData->pos[i]) / (interval * interval) )
1398  - ( 2 * (endTrajData->vel[i] + 2 * startTrajData->vel[i]) / interval);
1399  accCoef2[i] = ( -12 * (endTrajData->pos[i] - startTrajData->pos[i]) / (interval * interval * interval))
1400  + ( 6 * (endTrajData->vel[i] + startTrajData->vel[i]) / (interval * interval) );
1401  }
1402  }
1403  else
1404  {
1405  printf("Warning: Group %d - Time difference between endTrajData (%d) and startTrajData (%d) is 0 or less.\r\n", groupNo, endTrajData->time, startTrajData->time);
1406  }
1407 
1408  // Initialize calculation variable before entering while loop
1409  calculationTime_ms = startTrajData->time;
1410  if(ctrlGroup->timeLeftover_ms == 0)
1411  timeInc_ms = interpolPeriod;
1412  else
1413  timeInc_ms = ctrlGroup->timeLeftover_ms;
1414 
1415  // While interpolation time is smaller than new ROS point time
1416  while( (curTrajData->time < endTrajData->time) && Ros_Controller_IsMotionReady(controller) && !controller->bStopMotion)
1417  {
1418  // Increment calculation time by next time increment
1419  calculationTime_ms += timeInc_ms;
1420  interpolTime = (calculationTime_ms - startTrajData->time) / 1000.0f;
1421 
1422  if( calculationTime_ms < endTrajData->time ) // Make calculation for full interpolation clock
1423  {
1424  // Set new interpolation time to calculation time
1425  curTrajData->time = calculationTime_ms;
1426 
1427  // For each axis calculate the new position at the interpolation time
1428  for (i = 0; i < ctrlGroup->numAxes; i++)
1429  {
1430  // Add position change for new interpolation time
1431  curTrajData->pos[i] = startTrajData->pos[i] // initial position component
1432  + startTrajData->vel[i] * interpolTime // initial velocity component
1433  + accCoef1[i] * interpolTime * interpolTime / 2 // accCoef1 component
1434  + accCoef2[i] * interpolTime * interpolTime * interpolTime / 6; // accCoef2 component
1435 
1436  // Add velocity change for new interpolation time
1437  curTrajData->vel[i] = startTrajData->vel[i] // initial velocity component
1438  + accCoef1[i] * interpolTime // accCoef1 component
1439  + accCoef2[i] * interpolTime * interpolTime / 2; // accCoef2 component
1440  }
1441 
1442  // Reset the timeInc_ms for the next interpolation cycle
1443  if(timeInc_ms < interpolPeriod)
1444  {
1445  timeInc_ms = interpolPeriod;
1446  ctrlGroup->timeLeftover_ms = 0;
1447  }
1448  }
1449  else // Make calculation for partial interpolation cycle
1450  {
1451  // Set the current trajectory data equal to the end trajectory
1452  memcpy(curTrajData, endTrajData, sizeof(JointMotionData));
1453 
1454  // Set the next interpolation increment to the the remainder to reach the next interpolation cycle
1455  if(calculationTime_ms > endTrajData->time)
1456  {
1457  ctrlGroup->timeLeftover_ms = calculationTime_ms - endTrajData->time;
1458  }
1459  }
1460 
1461  // Convert position in motoman pulse joint
1462  Ros_CtrlGroup_ConvertToMotoPos(ctrlGroup, curTrajData->pos, newPulsePos);
1463 
1464  // Calculate the increment
1465  incData.time = curTrajData->time;
1466  for (i = 0; i < MP_GRP_AXES_NUM; i++)
1467  {
1468  if (ctrlGroup->axisType.type[i] != AXIS_INVALID)
1469  incData.inc[i] = (newPulsePos[i] - ctrlGroup->prevPulsePos[i]);
1470  else
1471  incData.inc[i] = 0;
1472  }
1473 
1474  // Add the increment to the queue
1475  if(!Ros_MotionServer_AddPulseIncPointToQ(controller, groupNo, &incData))
1476  break;
1477 
1478  // Copy data to the previous pulse position for next iteration
1479  memcpy(ctrlGroup->prevPulsePos, newPulsePos, sizeof(ctrlGroup->prevPulsePos));
1480  }
1481 }
1482 
1483 
1484 //-------------------------------------------------------------------
1485 // Adds pulse increments for one interpolation period to the inc move queue
1486 //-------------------------------------------------------------------
1488 {
1489  int index;
1490 
1491  // Set pointer to specified queue
1492  Incremental_q* q = &controller->ctrlGroups[groupNo]->inc_q;
1493 
1494  while( q->cnt >= Q_SIZE ) //queue is full
1495  {
1496  //wait for items to be removed from the queue
1497  Ros_Sleep(controller->interpolPeriod);
1498 
1499  //make sure we don't get stuck in infinite loop
1500  if (!Ros_Controller_IsMotionReady(controller)) //<- they probably pressed HOLD or ESTOP
1501  {
1502  return FALSE;
1503  }
1504  }
1505 
1506  // Lock the q before manipulating it
1507  if(mpSemTake(q->q_lock, Q_LOCK_TIMEOUT) == OK)
1508  {
1509  // Get the index of the end of the queue
1510  index = Q_OFFSET_IDX( q->idx, q->cnt , Q_SIZE );
1511  // Copy data at the end of the queue
1512  q->data[index] = *dataToEnQ;
1513  // increase the count of elements in the queue
1514  q->cnt++;
1515 
1516  // Unlock the q
1517  mpSemGive(q->q_lock);
1518  }
1519  else
1520  {
1521  printf("ERROR: Unable to add point to queue. Queue is locked up!\r\n");
1522  return FALSE;
1523  }
1524 
1525  return TRUE;
1526 }
1527 
1528 
1529 //-------------------------------------------------------------------
1530 // Clears the inc move queue
1531 //-------------------------------------------------------------------
1533 {
1534  Incremental_q* q;
1535 
1536  // Check group number valid
1537  if(!Ros_Controller_IsValidGroupNo(controller, groupNo))
1538  return FALSE;
1539 
1540  // Set pointer to specified queue
1541  q = &controller->ctrlGroups[groupNo]->inc_q;
1542 
1543  // Lock the q before manipulating it
1544  if(mpSemTake(q->q_lock, Q_LOCK_TIMEOUT) == OK)
1545  {
1546  // Reset the queue. No need to modify index or delete data
1547  q->cnt = 0;
1548 
1549  // Unlock the q
1550  mpSemGive(q->q_lock);
1551 
1552  return TRUE;
1553  }
1554 
1555  return FALSE;
1556 }
1557 
1558 
1559 //-------------------------------------------------------------------
1560 // Clears the inc move queue
1561 //-------------------------------------------------------------------
1563 {
1564  int groupNo;
1565  BOOL bRet = TRUE;
1566 
1567  for(groupNo=0; groupNo<controller->numGroup; groupNo++)
1568  {
1569  bRet &= Ros_MotionServer_ClearQ(controller, groupNo);
1570  }
1571 
1572  return bRet;
1573 }
1574 
1575 
1576 //-------------------------------------------------------------------
1577 // Check the number of inc_move currently in the specified queue
1578 //-------------------------------------------------------------------
1580 {
1581  Incremental_q* q;
1582  int count;
1583 
1584  // Check group number valid
1585  if(!Ros_Controller_IsValidGroupNo(controller, groupNo))
1586  return -1;
1587 
1588  // Set pointer to specified queue
1589  q = &controller->ctrlGroups[groupNo]->inc_q;
1590 
1591  // Lock the q before manipulating it
1592  if(mpSemTake(q->q_lock, Q_LOCK_TIMEOUT) == OK)
1593  {
1594  count = q->cnt;
1595 
1596  // Unlock the q
1597  mpSemGive(q->q_lock);
1598 
1599  return count;
1600  }
1601 
1602  printf("ERROR: Unable to access queue count. Queue is locked up!\r\n");
1603  return ERROR;
1604 }
1605 
1606 
1607 
1608 //-------------------------------------------------------------------
1609 // Check that at least one control group of the controller has data in queue
1610 //-------------------------------------------------------------------
1612 {
1613  int groupNo;
1614  int qCnt;
1615 
1616  for(groupNo=0; groupNo<controller->numGroup; groupNo++)
1617  {
1618  qCnt = Ros_MotionServer_GetQueueCnt(controller, groupNo);
1619  if (qCnt > 0)
1620  return TRUE;
1621  else if (qCnt == ERROR)
1622  return ERROR;
1623  }
1624 
1625  return FALSE;
1626 }
1627 
1628 
1629 //-------------------------------------------------------------------
1630 // Task to move the robot at each interpolation increment
1631 // 06/05/13: Modified to always send information for all defined groups even if the inc_q is empty
1632 //-------------------------------------------------------------------
1633 void Ros_MotionServer_IncMoveLoopStart(Controller* controller) //<-- IP_CLK priority task
1634 {
1635 #if DX100
1636  MP_POS_DATA moveData;
1637 #else
1638  MP_EXPOS_DATA moveData;
1639 #endif
1640 
1641  Incremental_q* q;
1642  int i;
1643  int ret;
1644  LONG time;
1645  LONG q_time;
1646  int axis;
1647  //BOOL bNoData = TRUE; // for testing
1648 
1649  printf("IncMoveTask Started\r\n");
1650 
1651  memset(&moveData, 0x00, sizeof(moveData));
1652 
1653  for(i=0; i<controller->numGroup; i++)
1654  {
1655  moveData.ctrl_grp |= (0x01 << i);
1656  moveData.grp_pos_info[i].pos_tag.data[0] = Ros_CtrlGroup_GetAxisConfig(controller->ctrlGroups[i]);
1657  }
1658 
1659  FOREVER
1660  {
1661  mpClkAnnounce(MP_INTERPOLATION_CLK);
1662 
1663  if (Ros_Controller_IsMotionReady(controller)
1664  && Ros_MotionServer_HasDataInQueue(controller)
1665  && !controller->bStopMotion)
1666  {
1667  //bNoData = FALSE; // for testing
1668 
1669  for(i=0; i<controller->numGroup; i++)
1670  {
1671  q = &controller->ctrlGroups[i]->inc_q;
1672 
1673  // Lock the q before manipulating it
1674  if(mpSemTake(q->q_lock, Q_LOCK_TIMEOUT) == OK)
1675  {
1676  if(q->cnt > 0)
1677  {
1678  time = q->data[q->idx].time;
1679  q_time = controller->ctrlGroups[i]->q_time;
1680  moveData.grp_pos_info[i].pos_tag.data[2] = q->data[q->idx].tool;
1681  moveData.grp_pos_info[i].pos_tag.data[3] = q->data[q->idx].frame;
1682  moveData.grp_pos_info[i].pos_tag.data[4] = q->data[q->idx].user;
1683 
1684  memcpy(&moveData.grp_pos_info[i].pos, &q->data[q->idx].inc, sizeof(LONG) * MP_GRP_AXES_NUM);
1685 
1686  // increment index in the queue and decrease the count
1687  q->idx = Q_OFFSET_IDX( q->idx, 1, Q_SIZE );
1688  q->cnt--;
1689 
1690  // Check if complet interpolation period covered
1691  while(q->cnt > 0)
1692  {
1693  if( (q_time <= q->data[q->idx].time)
1694  && (q->data[q->idx].time - q_time <= controller->interpolPeriod) )
1695  {
1696  // next incMove is part of same interpolation period
1697 
1698  // check that information is in the same format
1699  if( (moveData.grp_pos_info[i].pos_tag.data[2] != q->data[q->idx].tool)
1700  || (moveData.grp_pos_info[i].pos_tag.data[3] != q->data[q->idx].frame)
1701  || (moveData.grp_pos_info[i].pos_tag.data[4] != q->data[q->idx].user) )
1702  {
1703  // Different format can't combine information
1704  break;
1705  }
1706 
1707  // add next incMove to current incMove
1708  for(axis=0; axis<MP_GRP_AXES_NUM; axis++)
1709  moveData.grp_pos_info[i].pos[axis] += q->data[q->idx].inc[axis];
1710  time = q->data[q->idx].time;
1711 
1712  // increment index in the queue and decrease the count
1713  q->idx = Q_OFFSET_IDX( q->idx, 1, Q_SIZE );
1714  q->cnt--;
1715  }
1716  else
1717  {
1718  // interpolation period complet
1719  break;
1720  }
1721  }
1722 
1723  controller->ctrlGroups[i]->q_time = time;
1724  }
1725  else
1726  {
1727  moveData.grp_pos_info[i].pos_tag.data[2] = 0;
1728  moveData.grp_pos_info[i].pos_tag.data[3] = MP_INC_PULSE_DTYPE;
1729  moveData.grp_pos_info[i].pos_tag.data[4] = 0;
1730  memset(&moveData.grp_pos_info[i].pos, 0x00, sizeof(LONG) * MP_GRP_AXES_NUM);
1731  }
1732 
1733  // Unlock the q
1734  mpSemGive(q->q_lock);
1735  }
1736  else
1737  {
1738  printf("ERROR: Can't get data from queue. Queue is locked up.\r\n");
1739  memset(&moveData.grp_pos_info[i].pos, 0x00, sizeof(LONG) * MP_GRP_AXES_NUM);
1740  continue;
1741  }
1742  }
1743 
1744 #if DX100
1745  // first robot
1746  if (controller->bIsDx100Sda)
1747  moveData.ctrl_grp = 1 | (1 << 2); //R1 + B1
1748  else
1749  moveData.ctrl_grp = 1; //R1 only
1750  ret = mpMeiIncrementMove(MP_SL_ID1, &moveData);
1751  if(ret != 0)
1752  {
1753  if(ret == -3)
1754  printf("mpMeiIncrementMove returned: %d (ctrl_grp = %d)\r\n", ret, moveData.ctrl_grp);
1755  else
1756  printf("mpMeiIncrementMove returned: %d\r\n", ret);
1757  }
1758  // if second robot
1759  moveData.ctrl_grp = 2; //R2 only
1760  if(controller->numRobot > 1)
1761  {
1762  ret = mpMeiIncrementMove(MP_SL_ID2, &moveData);
1763  if(ret != 0)
1764  {
1765  if(ret == -3)
1766  printf("mpMeiIncrementMove returned: %d (ctrl_grp = %d)\r\n", ret, moveData.ctrl_grp);
1767  else
1768  printf("mpMeiIncrementMove returned: %d\r\n", ret);
1769  }
1770  }
1771 #else
1772  ret = mpExRcsIncrementMove(&moveData);
1773  if(ret != 0)
1774  {
1775  if(ret == E_EXRCS_CTRL_GRP)
1776  printf("mpExRcsIncrementMove returned: %d (ctrl_grp = %d)\r\n", ret, moveData.ctrl_grp);
1777 #if (YRC1000||YRC1000u)
1778  else if (ret == E_EXRCS_IMOV_UNREADY)
1779  {
1780  printf("mpExRcsIncrementMove returned UNREADY: %d (Could be PFL Active)\r\n", ret);
1781  controller->bPFLduringRosMove = TRUE;
1782  }
1783 #endif
1784  else
1785  printf("mpExRcsIncrementMove returned: %d\r\n", ret);
1786  }
1787 #endif
1788 
1789  }
1790  //else // for testing
1791  //{
1792  // if(!bNoData)
1793  // {
1794  // printf("INFO: No data in queue.\r\n");
1795  // bNoData = TRUE;
1796  // }
1797  //}
1798  }
1799 }
1800 
1801 
1802 
1803 //-----------------------------------------------------------------------
1804 // Convert a JointTrajData message to a JointMotionData of a control group
1805 //-----------------------------------------------------------------------
1807 {
1808  int i, maxAxes;
1809 
1810  memset(jointMotionData, 0x00, sizeof(JointMotionData));
1811 
1812  maxAxes = min(ROS_MAX_JOINT, MP_GRP_AXES_NUM);
1813 
1814  jointMotionData->flag = jointTrajData->validFields;
1815  jointMotionData->time = (int)(jointTrajData->time * 1000);
1816 
1817  for(i=0; i<maxAxes; i++)
1818  {
1819  jointMotionData->pos[i] = jointTrajData->pos[i];
1820  jointMotionData->vel[i] = jointTrajData->vel[i];
1821  jointMotionData->acc[i] = jointTrajData->acc[i];
1822  }
1823 }
1824 
1825 void Ros_MotionServer_PrintError(USHORT err_no, char* msgPrefix)
1826 {
1827  char errMsg[ERROR_MSG_MAX_SIZE];
1828  memset(errMsg, 0x00, ERROR_MSG_MAX_SIZE);
1830  printf("%s %s\r\n", msgPrefix, errMsg);
1831 }
1832 
1834 {
1835  MP_SERVO_POWER_SEND_DATA sServoData;
1836  MP_STD_RSP_DATA rData;
1837  int ret;
1838 
1839 #ifdef DUMMY_SERVO_MODE
1840  return OK;
1841 #endif
1842 
1843  if (Ros_Controller_IsEcoMode(controller) == TRUE)
1844  {
1845  //toggle servos to disable energy-savings mode
1846  sServoData.sServoPower = 0; // OFF
1847  memset(&sServoData, 0x00, sizeof(sServoData));
1848  memset(&rData, 0x00, sizeof(rData));
1849  ret = mpSetServoPower(&sServoData, &rData);
1850  if ((ret == 0) && (rData.err_no == 0))
1851  {
1852  // wait for the Servo/Eco OFF confirmation
1853  int checkCount;
1854  for (checkCount = 0; checkCount<MOTION_START_TIMEOUT; checkCount += MOTION_START_CHECK_PERIOD)
1855  {
1856  // Update status
1857  Ros_Controller_StatusUpdate(controller);
1858 
1859  if (Ros_Controller_IsEcoMode(controller) == FALSE)
1860  break;
1861 
1863  }
1864  }
1865  else
1866  {
1867  Ros_MotionServer_PrintError(rData.err_no, "Can't disable energy-savings mode because:");
1868  return NG;
1869  }
1870  }
1871 
1872  if (Ros_Controller_IsEcoMode(controller) == FALSE)
1873  return OK;
1874  else
1875  return NG;
1876 }
1877 
1879 {
1880  int i;
1881  STATUS apiRet = OK;
1882 
1883  //initialize memory
1884  memset(replyMsg, 0x00, sizeof(SimpleMsg));
1885 
1886  // set prefix: length of message excluding the prefix
1887  replyMsg->prefix.length = sizeof(SmHeader) + sizeof(SmBodyMotoGetDhParameters);
1888 
1889  // set header information of the reply
1892  replyMsg->header.replyType = ROS_REPLY_SUCCESS;
1893 
1894  for (i = 0; i < controller->numGroup; i += 1)
1895  {
1896  if (controller->ctrlGroups[i] != NULL && replyMsg->header.replyType == ROS_REPLY_SUCCESS)
1897  {
1898  apiRet = GP_getDhParameters(i, &replyMsg->body.dhParameters.dhParameters[i]);
1899 
1900  if (apiRet == OK)
1901  replyMsg->header.replyType = ROS_REPLY_SUCCESS;
1902  else
1903  replyMsg->header.replyType = ROS_REPLY_FAILURE;
1904  }
1905  }
1906 
1907  return apiRet;
1908 }
1909 
1910 
1911 int Ros_MotionServer_SetSelectedTool(Controller* controller, SimpleMsg* receiveMsg, SimpleMsg* replyMsg)
1912 {
1913  int groupNo = receiveMsg->body.selectTool.groupNo;
1914  int tool = receiveMsg->body.selectTool.tool;
1915 
1916  if (groupNo >= 0 && groupNo < controller->numRobot)
1917  {
1918  if (tool >= MIN_VALID_TOOL_INDEX && tool <= MAX_VALID_TOOL_INDEX)
1919  {
1920  controller->ctrlGroups[receiveMsg->body.selectTool.groupNo]->tool = tool;
1921  Ros_SimpleMsg_MotionReply(receiveMsg, ROS_RESULT_SUCCESS, 0, replyMsg, groupNo);
1922  }
1923  else
1925  }
1926  else
1928 
1929  return 0;
1930 }
void Ros_Controller_SetIOState(ULONG signal, BOOL status)
Definition: Controller.c:793
SmMsgType msgType
LONG inc[MP_GRP_AXES_NUM]
Definition: CtrlGroup.h:55
int Ros_MotionServer_InitTrajPointFullEx(CtrlGroup *ctrlGroup, SmBodyJointTrajPtExData *jointTrajDataEx, int sequence)
void Ros_Controller_ErrNo_ToString(int errNo, char errMsg[ERROR_MSG_MAX_SIZE], int errMsgSize)
Definition: Controller.c:828
AXIS_TYPE type[MAX_PULSE_AXES]
void Ros_MotionServer_IncMoveLoopStart(Controller *controller)
BOOL bStopMotion
Definition: Controller.h:123
BOOL Ros_Controller_IsHold(Controller *controller)
Definition: Controller.c:493
BOOL Ros_MotionServer_AddPulseIncPointToQ(Controller *controller, int groupNo, Incremental_data *dataToEnQ)
SmBodyJointTrajPtFull jointTrajData
#define INVALID_TASK
Definition: Controller.h:68
SmCommandType command
f
BOOL Ros_CtrlGroup_GetPulsePosCmd(CtrlGroup *ctrlGroup, long pulsePos[MAX_PULSE_AXES])
Definition: CtrlGroup.c:212
int Ros_MotionServer_SetSelectedTool(Controller *controller, SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
int tool
#define IO_FEEDBACK_FAILURE
Definition: Controller.h:46
BOOL Ros_Controller_IsOperating(Controller *controller)
Definition: Controller.c:488
DH_PARAMETERS dhParameters[MOT_MAX_GR]
Incremental_q inc_q
Definition: CtrlGroup.h:92
BOOL Ros_Controller_IsServoOn(Controller *controller)
Definition: Controller.c:498
int Ros_MotionServer_AddTrajPointFull(CtrlGroup *ctrlGroup, SmBodyJointTrajPtFull *jointTrajData)
struct _SmHeader SmHeader
BOOL bIsBaxisSlave
Definition: CtrlGroup.h:103
SmPrefix prefix
struct _SmBodyMotoMotionCtrl SmBodyMotoMotionCtrl
void Ros_MotionServer_JointTrajDataToIncQueue(Controller *controller, int groupNo)
#define MOTION_START_TIMEOUT
Definition: MotionServer.h:36
int Ros_MotionServer_JointTrajDataProcess(Controller *controller, SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
#define START_MAX_PULSE_DEVIATION
Definition: Controller.h:76
SmBodyMotoMotionCtrl motionCtrl
#define MASK_ISALARM_ACTIVEALARM
Definition: Controller.h:80
int groupNo
int numRobot
Definition: Controller.h:115
int sequence
int Ros_IoServer_WriteIOBit(SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
Definition: IoServer.c:400
CtrlGroup * ctrlGroups[MP_GRP_NUM]
Definition: Controller.h:116
#define ERROR_MSG_MAX_SIZE
Definition: Controller.h:74
float pos[ROS_MAX_JOINT]
struct _SmBodyMotoWriteIOGroup SmBodyMotoWriteIOGroup
SEM_ID q_lock
Definition: CtrlGroup.h:60
float maxSpeed[MP_GRP_AXES_NUM]
Definition: CtrlGroup.h:89
void Ros_MotionServer_WaitForSimpleMsg(Controller *controller, int connectionIndex)
Definition: MotionServer.c:313
int subcode
#define Q_OFFSET_IDX(a, b, c)
Definition: CtrlGroup.h:44
int Ros_MotionServer_GetQueueCnt(Controller *controller, int groupNo)
long prevPulsePos[MAX_PULSE_AXES]
Definition: CtrlGroup.h:100
int Ros_MotionServer_GetExpectedByteSizeForMessageType(SimpleMsg *receiveMsg, int recvByteSize)
Definition: MotionServer.c:248
SmBodyJointTrajPtFullEx jointTrajDataEx
struct _SmBodySelectTool SmBodySelectTool
BOOL hasDataToProcess
Definition: CtrlGroup.h:97
BOOL bPFLduringRosMove
Definition: Controller.h:124
int Ros_IoServer_WriteIOGroup(SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
Definition: IoServer.c:442
void Db_Print(char *msgFormat,...)
Definition: Controller.c:982
float pos[MP_GRP_AXES_NUM]
Definition: CtrlGroup.h:71
BOOL Ros_MotionServer_ResetAlarm(Controller *controller)
Definition: MotionServer.c:817
int Ros_SimpleMsg_MotionReply(SimpleMsg *receiveMsg, int result, int subcode, SimpleMsg *replyMsg, int ctrlGrp)
struct _SmBodyMotoReadIOGroup SmBodyMotoReadIOGroup
int sdMotionConnections[MAX_MOTION_CONNECTIONS]
Definition: Controller.h:138
#define IO_FEEDBACK_MOTIONSERVERCONNECTED
Definition: Controller.h:43
struct _SmBodyJointTrajPtExData SmBodyJointTrajPtExData
void Ros_CtrlGroup_ConvertToMotoPos(CtrlGroup *ctrlGroup, float radPos[MAX_PULSE_AXES], long motopulsePos[MAX_PULSE_AXES])
Definition: CtrlGroup.c:548
int tidMotionConnections[MAX_MOTION_CONNECTIONS]
Definition: Controller.h:139
STATUS
int Ros_MotionServer_MotionCtrlProcess(Controller *controller, SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
Definition: MotionServer.c:616
void Ros_Sleep(float milliseconds)
Definition: Controller.c:999
STATUS Ros_MotionServer_DisableEcoMode(Controller *controller)
#define ROS_MAX_JOINT
Definition: SimpleMessage.h:35
struct _SmBodyMotoMotionReply SmBodyMotoMotionReply
BOOL Ros_MotionServer_ServoPower(Controller *controller, int servoOnOff)
Definition: MotionServer.c:762
BOOL Ros_Controller_IsEcoMode(Controller *controller)
Definition: Controller.c:503
int tidAddToIncQueue
Definition: CtrlGroup.h:98
#define MIN_VALID_TOOL_INDEX
Definition: MotionServer.h:42
SmBodySelectTool selectTool
struct _SmBodyJointTrajPtFullEx SmBodyJointTrajPtFullEx
float data[ROS_MAX_JOINT]
#define IO_FEEDBACK_MP_INCMOVE_DONE
Definition: Controller.h:40
SmHeader header
float vel[ROS_MAX_JOINT]
#define MOTION_INIT_ROS_JOB
Definition: MotionServer.h:38
struct _SmBodyJointFeedback SmBodyJointFeedback
int Ros_MotionServer_InitTrajPointFull(CtrlGroup *ctrlGroup, SmBodyJointTrajPtFull *jointTrajData)
BOOL Ros_Controller_IsValidGroupNo(Controller *controller, int groupNo)
Definition: Controller.c:255
UCHAR Ros_CtrlGroup_GetAxisConfig(CtrlGroup *ctrlGroup)
Definition: CtrlGroup.c:618
BOOL Ros_Controller_IsAlarm(Controller *controller)
Definition: Controller.c:460
double min(double a, double b)
int numGroup
Definition: Controller.h:114
float vel[MP_GRP_AXES_NUM]
Definition: CtrlGroup.h:72
BOOL Ros_Controller_IsRemote(Controller *controller)
Definition: Controller.c:483
int Ros_MotionServer_GetDhParameters(Controller *controller, SimpleMsg *replyMsg)
struct _SmBodyJointFeedbackEx SmBodyJointFeedbackEx
SmReplyType replyType
FlagsValidFields validFields
float acc[MP_GRP_AXES_NUM]
Definition: CtrlGroup.h:73
#define MAX_VALID_TOOL_INDEX
Definition: MotionServer.h:43
int tool
Definition: CtrlGroup.h:90
SmBodyMotoGetDhParameters dhParameters
void Ros_MotionServer_AddToIncQueueProcess(Controller *controller, int groupNo)
SmCommType commType
void Ros_MotionServer_PrintError(USHORT err_no, char *msgPrefix)
int Ros_IoServer_ReadIOGroup(SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
Definition: IoServer.c:354
int groupNo
Definition: CtrlGroup.h:82
UINT16 interpolPeriod
Definition: Controller.h:113
int Ros_MotionServer_JointTrajPtFullExProcess(Controller *controller, SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
Definition: MotionServer.c:509
BOOL Ros_Controller_StatusUpdate(Controller *controller)
Definition: Controller.c:695
#define MOTION_START_CHECK_PERIOD
Definition: MotionServer.h:37
#define Q_SIZE
Definition: CtrlGroup.h:36
struct _SmBodyMotoWriteIOBit SmBodyMotoWriteIOBit
#define INVALID_SOCKET
Definition: Controller.h:67
BOOL Ros_MotionServer_HasDataInQueue(Controller *controller)
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
#define Q_LOCK_TIMEOUT
Definition: CtrlGroup.h:41
#define MAX_MOTION_CONNECTIONS
Definition: Controller.h:58
int numAxes
Definition: CtrlGroup.h:83
#define MOTION_STOP_TIMEOUT
Definition: MotionServer.h:35
STATUS GP_getDhParameters(int ctrlGrp, DH_PARAMETERS *dh)
FlagsValidFields validFields
BOOL Ros_Controller_IsMotionReady(Controller *controller)
Definition: Controller.c:520
BOOL Ros_Controller_IsEStop(Controller *controller)
Definition: Controller.c:508
FlagsValidFields
SmBodyJointTrajPtExData jointTrajPtData[MOT_MAX_GR]
float pos[ROS_MAX_JOINT]
BOOL Ros_MotionServer_SimpleMsgProcess(Controller *controller, SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
Definition: MotionServer.c:424
void Ros_MotionServer_ConvertToJointMotionData(SmBodyJointTrajPtFull *jointTrajData, JointMotionData *jointMotionData)
int Ros_IoServer_ReadIOBit(SimpleMsg *receiveMsg, SimpleMsg *replyMsg)
Definition: IoServer.c:319
int Ros_Controller_GetNotReadySubcode(Controller *controller)
Definition: Controller.c:558
JointMotionData jointMotionData
Definition: CtrlGroup.h:95
struct _SmBodyMotoReadIOBit SmBodyMotoReadIOBit
float vel[ROS_MAX_JOINT]
BOOL Ros_MotionServer_StartTrajMode(Controller *controller)
Definition: MotionServer.c:885
int tidIncMoveThread
Definition: Controller.h:140
struct _SmBodyRobotStatus SmBodyRobotStatus
BOOL Ros_MotionServer_StopTrajMode(Controller *controller)
float acc[ROS_MAX_JOINT]
Incremental_data data[Q_SIZE]
Definition: CtrlGroup.h:63
BOOL Ros_MotionServer_StopMotion(Controller *controller)
Definition: MotionServer.c:726
#define MAX_TRAJECTORY_TIME_LENGTH
Definition: MotionServer.h:40
BOOL Ros_Controller_IsError(Controller *controller)
Definition: Controller.c:468
struct _SmBodyJointTrajPtFull SmBodyJointTrajPtFull
int Ros_MotionServer_AddTrajPointFullEx(CtrlGroup *ctrlGroup, SmBodyJointTrajPtExData *jointTrajDataEx, int sequence)
float time
JointMotionData jointMotionDataToProcess
Definition: CtrlGroup.h:96
int timeLeftover_ms
Definition: CtrlGroup.h:99
void Ros_MotionServer_StopConnection(Controller *controller, int connectionIndex)
Definition: MotionServer.c:195
void Ros_MotionServer_StartNewConnection(Controller *controller, int sd)
Definition: MotionServer.c:82
#define MASK_ISALARM_ACTIVEERROR
Definition: Controller.h:81
AXIS_MOTION_TYPE axisType
Definition: CtrlGroup.h:101
BOOL Ros_MotionServer_ClearQ(Controller *controller, int groupNo)
float acc[ROS_MAX_JOINT]
BOOL Ros_MotionServer_ClearQ_All(Controller *controller)
long q_time
Definition: CtrlGroup.h:93


motoman_driver
Author(s): Jeremy Zoss (Southwest Research Institute), Ted Miller (MotoROS) (Yaskawa Motoman), Eric Marcil (MotoROS) (Yaskawa Motoman)
autogenerated on Sat May 8 2021 02:27:43