PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
PlusCmsBrachyStepper.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2  Program: Plus
3  Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4  See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 #include "PlusConfigure.h"
8 
9 #include "PlusCmsBrachyStepper.h"
10 #include "vtkIGSIOAccurateTimer.h"
11 
12 #include "PlusSerialLine.h"
13 
14 #include <assert.h>
15 #include <iostream>
16 #include <math.h>
17 #include <sstream>
18 
19 #define STEPPERDEBUGMSG 0
20 
21 #if STEPPERDEBUGMSG
22 #include <stdio.h>
23 #endif
24 
25 #define STX 2
26 #define ETX 3
27 #define MAXTRIES 5
28 
29 static const int MAX_REPEATED_POSITION_ERROR_COUNT = 15;
30 
31 //----------------------------------------------------------------------------
32 static const char* CALIB_MSG_PROBE_TO_BASE = "Step the probe to home position. A green light should appear.";
33 static const char* CALIB_MSG_PROBE_TO_REF = "Step the probe to the reference position (12.5 mm). An amber light should replace the green light.";
34 static const char* CALIB_MSG_PROBE_TO_HOME = "Step the probe to the home position. The light should revert to green and flashes twice.";
35 
36 static const char* CALIB_MSG_GRID_TO_BASE = "Step the template grid to home position. A green light should appear.";
37 static const char* CALIB_MSG_GRID_TO_REF = "Step the template grid to the reference position (12.5 mm). An amber light should replace the green light.";
38 static const char* CALIB_MSG_GRID_TO_HOME = "Step the template grid to the home position. The light should revert to green and flashes twice.";
39 
40 static const char* CALIB_MSG_ROTATION_TO_BASE = "Rotate the probe to zero degree. A green light should appear.";
41 static const char* CALIB_MSG_ROTATION_TO_REF = "Rotate the probe to the reference position (10.5 deg or more). An amber light should replace the green light.";
42 static const char* CALIB_MSG_ROTATION_TO_HOME = "Rotate the probe to zero degree. The light should revert to green and flashes twice.";
43 
44 static const char* CALIB_MSG_COMPLETED = "Calibration completed!";
45 
48 
51 
54 
57 
60 
63 
66 
72 
73 // For motorized steppers
77 static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_MOTORIZATION_CODE = "82"; // scale factor (zero if stepper is not motorized)
79 
81 
83 
85 
87 
89 
91 
92 //******************************************************************
93 //******************************************************************
94 
95 //----------------------------------------------------------------------------
96 PlusCmsBrachyStepper::PlusCmsBrachyStepper( unsigned long COMPort/*=1*/, unsigned long BaudRate/*=19200*/)
97 {
98  m_StepperCOMPort = new SerialLine();
99  this->SetCOMPort(COMPort);
100  this->SetBaudRate(BaudRate);
101  m_StepperCOMPort->SetMaxReplyTime(1000);
102 
103  m_ProbeScale = 0;
104  m_GridScale = 0;
105  m_RotationScale = 0;
106 
107  m_IsCalibrated = false;
108  m_RepeatedPositionErrorCount = 0;
109 
111 
112  InitializeCriticalSection(&m_CriticalSection);
113 }
114 
115 //----------------------------------------------------------------------------
117 {
118  if (m_StepperCOMPort->IsHandleAlive())
119  {
120  m_StepperCOMPort->Close();
121  delete m_StepperCOMPort;
122  m_StepperCOMPort = NULL;
123  }
124 
125  DeleteCriticalSection(&m_CriticalSection);
126 }
127 
128 //----------------------------------------------------------------------------
130 {
131  std::ostringstream strComPort;
132  strComPort << "COM" << COMPort;
133 
134  // Change only if we not yet connected
135  if (this->m_StepperCOMPort->IsHandleAlive())
136  {
137  LOG_ERROR("Unable to set serial port number, stepper already connected!");
138  return PLUS_FAIL;
139  }
140 
141  this->m_StepperCOMPort->SetPortName(strComPort.str());
142  return PLUS_SUCCESS;
143 }
144 
145 //----------------------------------------------------------------------------
147 {
148  // Change only if we not yet connected
149  if (this->m_StepperCOMPort->IsHandleAlive())
150  {
151  LOG_ERROR("Unable to set serial port speed, stepper already connected!");
152  return PLUS_FAIL;
153  }
154 
155  this->m_StepperCOMPort->SetSerialPortSpeed(BaudRate);
156  return PLUS_SUCCESS;
157 }
158 
159 //----------------------------------------------------------------------------
161 {
162  if (!this->m_StepperCOMPort->IsHandleAlive())
163  {
164  this->m_StepperCOMPort->Open();
165  }
166 
167  if ( this->IsStepperAlive() != PLUS_SUCCESS )
168  {
169  LOG_ERROR("Stepper is not alive");
170  return PLUS_FAIL;
171  }
172 
173  if (!this->m_StepperCOMPort->IsHandleAlive())
174  {
175  LOG_ERROR("Stepper COM port handle is not alive");
176  return PLUS_FAIL;
177  }
178  if (!this->IsStepperCalibrated())
179  {
180  LOG_ERROR("Stepper is not calibrated");
181  return PLUS_FAIL;
182  }
183 
184  return PLUS_SUCCESS;
185 }
186 
187 //----------------------------------------------------------------------------
189 {
190  this->m_StepperCOMPort->Close();
191 
192  return PLUS_SUCCESS;
193 }
194 
195 //----------------------------------------------------------------------------
196 PlusStatus PlusCmsBrachyStepper::GetDeviceModelInfo( std::string& version, std::string& model, std::string& serial )
197 {
198  int iVerHi=0; int iVerLo=0; int iModelNum=0; int iSerialNum=0;
199  if ( this->GetVersionInfo(iVerHi, iVerLo, iModelNum, iSerialNum) != PLUS_SUCCESS )
200  {
201  LOG_ERROR("Failed to get version info from stepper!");
202  return PLUS_FAIL;
203  }
204 
205  std::ostringstream strVersion;
206  strVersion << iVerHi << "." << iVerLo;
207  version = strVersion.str();
208 
209  std::ostringstream strModel;
210  strModel << iModelNum;
211  model = strModel.str();
212 
213  std::ostringstream strSerial;
214  strSerial << iSerialNum;
215  serial = strSerial.str();
216 
217  return PLUS_SUCCESS;
218 }
219 
220 //----------------------------------------------------------------------------
222 {
223  std::vector<BYTE> vDecodedMessage;
224  PlusStatus retValue(PLUS_FAIL);
225  EnterCriticalSection(&m_CriticalSection);
226  for ( int i = 0; i < MAXTRIES; i++)
227  {
229 
230  if (vDecodedMessage.size() >= 2 )
231  {
232  Status = vDecodedMessage[1];
233  retValue = PLUS_SUCCESS;
234  break;
235  }
236  }
237  LeaveCriticalSection(&m_CriticalSection);
238  return retValue;
239 }
240 
241 //----------------------------------------------------------------------------
242 PlusStatus PlusCmsBrachyStepper::GetVersionInfo(int &iVerHi, int &iVerLo, int &iModelNum, int &iSerialNum)
243 {
244  std::vector<BYTE> vDecodedMessage;
245  PlusStatus retValue(PLUS_FAIL);
246  EnterCriticalSection(&m_CriticalSection);
247  for ( int i = 0; i < MAXTRIES; i++)
248  {
250 
251  if (vDecodedMessage.size() >= 7 )
252  {
253  iVerHi = vDecodedMessage[1];
254  iVerLo = vDecodedMessage[2];
255  iModelNum = vDecodedMessage[3] * 256 + vDecodedMessage[4];
256  iSerialNum = vDecodedMessage[5] * 256 + vDecodedMessage[6];
257  retValue = PLUS_SUCCESS;
258  break;
259  }
260  }
261  LeaveCriticalSection(&m_CriticalSection);
262  return retValue;
263 }
264 
265 //----------------------------------------------------------------------------
266 PlusStatus PlusCmsBrachyStepper::GetReferenceData(STEPPERCOMMAND command, STEPPERRESPCODE respcode, double &count, double &dist, double &scale)
267 {
268  std::vector<BYTE> vDecodedMessage;
269  PlusStatus retValue(PLUS_FAIL);
270  EnterCriticalSection(&m_CriticalSection);
271  for ( int i = 0; i < MAXTRIES; i++)
272  {
273  SendStepperCommand(command, respcode, vDecodedMessage);
274 
275  if (vDecodedMessage.size() >= 5)
276  {
277  count = vDecodedMessage[1] * 256 + vDecodedMessage[2];
278  dist = vDecodedMessage[3] * 256 + vDecodedMessage[4];
279  scale = (double)(dist/100.0) / (double)count;
280  retValue = PLUS_SUCCESS;
281  break;
282  }
283  }
284  LeaveCriticalSection(&m_CriticalSection);
285  return retValue;
286 }
287 
288 //----------------------------------------------------------------------------
289 PlusStatus PlusCmsBrachyStepper::GetProbeReferenceData(double &count, double &dist, double &scale)
290 {
291  count = 0; dist = 0; scale = 0;
293  {
294  m_ProbeScale = scale;
295  return PLUS_SUCCESS;
296  }
297 
298  return PLUS_FAIL;
299 }
300 
301 //----------------------------------------------------------------------------
302 PlusStatus PlusCmsBrachyStepper::GetGridReferenceData(double &count, double &dist, double &scale)
303 {
304  count = 0; dist = 0; scale = 0;
306  {
307  m_GridScale = scale;
308  return PLUS_SUCCESS;
309  }
310 
311  return PLUS_FAIL;
312 }
313 
314 //----------------------------------------------------------------------------
316 {
317  count = 0; dist = 0; scale = 0;
319  {
320  m_RotationScale = scale;
321  return PLUS_SUCCESS;
322  }
323 
324  return PLUS_FAIL;
325 }
326 
327 //----------------------------------------------------------------------------
328 PlusStatus PlusCmsBrachyStepper::GetEncoderValues(double &PPosition, double &GPosition, double &RPosition, unsigned long &PositionRequestNumber)
329 {
330  // Increase the m_PositionNumber on every position request
331  PositionRequestNumber = ++m_PositionRequestNumber;
332 
333  if ( ! m_IsCalibrated )
334  {
335  LOG_ERROR("Cannot get encoder values, the stepper is not calibrated");
336  return PLUS_FAIL;
337  }
338 
339  if ( m_ProbeScale == 0 || m_GridScale == 0 || m_RotationScale == 0 )
340  {
341  this->SetScalingParameters();
342  }
343 
344  std::vector<BYTE> vDecodedMessage;
345 
346  PlusStatus retValue(PLUS_FAIL);
347 
348  EnterCriticalSection(&m_CriticalSection);
350  LeaveCriticalSection(&m_CriticalSection);
351 
352  if (vDecodedMessage.size() >= 7)
353  {
354  PPosition = (static_cast<short>(vDecodedMessage[1]*256 + vDecodedMessage[2]))*m_ProbeScale;
355  GPosition = (static_cast<short>(vDecodedMessage[3]*256 + vDecodedMessage[4]))*m_GridScale;
356  RPosition = (static_cast<short>(vDecodedMessage[5]*256 + vDecodedMessage[6]))*m_RotationScale;
357  m_RepeatedPositionErrorCount = 0;
358  retValue = PLUS_SUCCESS;
359  }
360  else
361  {
362  m_RepeatedPositionErrorCount++;
363  }
364 
365  if ( m_RepeatedPositionErrorCount >= MAX_REPEATED_POSITION_ERROR_COUNT )
366  {
367  m_RepeatedPositionErrorCount = 0;
368  this->Disconnect();
369  this->Connect();
370  }
371 
372  return retValue;
373 }
374 
375 //----------------------------------------------------------------------------
376 PlusStatus PlusCmsBrachyStepper::GetCalibrationState(int &PState, int &GState, int &RState)
377 {
378  std::vector<BYTE> vDecodedMessage;
379  PlusStatus retValue(PLUS_FAIL);
380  EnterCriticalSection(&m_CriticalSection);
381  for ( int i = 0; i < MAXTRIES; i++)
382  {
384 
385  if (vDecodedMessage.size() >= 4)
386  {
387  PState = vDecodedMessage[1];
388  GState = vDecodedMessage[2];
389  RState = vDecodedMessage[3];
390  retValue = PLUS_SUCCESS;
391  break;
392  }
393  }
394  LeaveCriticalSection(&m_CriticalSection);
395  return retValue;
396 }
397 
398 //----------------------------------------------------------------------------
400 {
401  std::vector<BYTE> vDecodedMessage;
402  PlusStatus retValue(PLUS_FAIL);
403  EnterCriticalSection(&m_CriticalSection);
404  for ( int i = 0; i < MAXTRIES; i++)
405  {
407 
408  if (vDecodedMessage.size() >= 2)
409  {
410  State = vDecodedMessage[1];
411  retValue = PLUS_SUCCESS;
412  break;
413  }
414  }
415  LeaveCriticalSection(&m_CriticalSection);
416  return retValue;
417 
418 }
419 
420 //----------------------------------------------------------------------------
422 {
423  int PState = 0, GState = 0, RState = 0;
424  this->m_IsCalibrated = false;
425 
426  this->GetCalibrationState(PState, GState, RState);
427 
429  &&
430  PState == 5 && GState == 5 && RState == 9)
431  {
432  this->m_IsCalibrated = true;
433  this->SetScalingParameters();
434  }
436  &&
437  PState == 0 && GState == 5 && RState == 9)
438  {
439  this->m_IsCalibrated = true;
440  this->SetScalingParameters();
441  }
443  {
444  this->m_IsCalibrated = true;
445  this->SetScalingParameters();
446  }
447 
448  return this->m_IsCalibrated;
449 }
450 
451 //----------------------------------------------------------------------------
453 {
454  unsigned int Status;
455  if (!this->GetStatusInfo(Status))
456  {
457  return PLUS_FAIL;
458  }
459  return PLUS_SUCCESS;
460 }
461 
462 //----------------------------------------------------------------------------
464 {
465  int PState = 0, GState = 0, RState = 0;
466  this->GetCalibrationState(PState, GState, RState);
467  this->m_IsCalibrated = false;
468 
470  {
471  switch (PState)
472  {
473  case 1:
474  case 2:
475  CalibMsg = CALIB_MSG_PROBE_TO_REF;
476  break;
477  case 3:
478  case 4:
479  CalibMsg = CALIB_MSG_PROBE_TO_HOME;
480  break;
481  default:
482  CalibMsg = CALIB_MSG_PROBE_TO_BASE;
483  }
484  return PLUS_FAIL;
485  }
486  else if ((GState < 5) && (m_BrachyStepperType != BURDETTE_MEDICAL_SYSTEMS_DIGITAL_MOTORIZED_STEPPER)) //TODO: does motorized stepper need this? It works without it and does not flash the green light either
487  {
488  switch (GState)
489  {
490  case 1:
491  case 2:
492  CalibMsg = CALIB_MSG_GRID_TO_REF;
493  break;
494  case 3:
495  case 4:
496  CalibMsg = CALIB_MSG_GRID_TO_HOME;
497  break;
498  default:
499  CalibMsg = CALIB_MSG_GRID_TO_BASE;
500  }
501  return PLUS_FAIL;
502  }
503  else if (RState < 9)
504  {
505  switch (RState)
506  {
507  case 1:
508  case 2:
509  CalibMsg = CALIB_MSG_ROTATION_TO_REF;
510  break;
511  case 4:
512  CalibMsg = CALIB_MSG_ROTATION_TO_HOME;
513  break;
514  default:
515  CalibMsg = CALIB_MSG_ROTATION_TO_BASE;
516  }
517  return PLUS_FAIL;
518  }
519  CalibMsg = CALIB_MSG_COMPLETED;
520  this->SetScalingParameters();
521  this->m_IsCalibrated = true;
522  return PLUS_SUCCESS;
523 }
524 
525 //----------------------------------------------------------------------------
527 {
528  PlusStatus retValue(PLUS_FAIL);
529  EnterCriticalSection(&m_CriticalSection);
530  for ( int i = 0; i<MAXTRIES; i++)
531  {
532  std::vector<BYTE> ackMessage;
534  if(IsStepperACKRecieved(ackMessage, SC_RESET_SYSTEM))
535  {
536  retValue = PLUS_SUCCESS;
537  break;
538  }
539  ClearBuffer();
540  }
541  LeaveCriticalSection(&m_CriticalSection);
542  return retValue;
543 }
544 
545 //----------------------------------------------------------------------------
547 {
548  PlusStatus retValue(PLUS_FAIL);
549  EnterCriticalSection(&m_CriticalSection);
550  for ( int i = 0; i<MAXTRIES; i++)
551  {
552  std::vector<BYTE> ackMessage;
554  if(IsStepperACKRecieved(ackMessage, SC_MOTOR_ON))
555  {
556  retValue = PLUS_SUCCESS;
557  break;
558  }
559  ClearBuffer();
560  }
561  LeaveCriticalSection(&m_CriticalSection);
562  return retValue;
563 }
564 
565 //----------------------------------------------------------------------------
567 {
568  PlusStatus retValue(PLUS_FAIL);
569  EnterCriticalSection(&m_CriticalSection);
570  for ( int i = 0; i<MAXTRIES; i++)
571  {
572  std::vector<BYTE> ackMessage;
574  if(IsStepperACKRecieved(ackMessage, SC_MOTOR_OFF))
575  {
576  retValue = PLUS_SUCCESS;
577  break;
578  }
579  ClearBuffer();
580  }
581  LeaveCriticalSection(&m_CriticalSection);
582  return retValue;
583 }
584 
585 //----------------------------------------------------------------------------
587 {
588  PlusStatus retValue(PLUS_FAIL);
589  EnterCriticalSection(&m_CriticalSection);
590  for ( int i = 0; i<MAXTRIES; i++)
591  {
592  std::vector<BYTE> vDecodedMessage;
593  vDecodedMessage.reserve(50);
595 
596  if (vDecodedMessage.size() >= 2)
597  {
598  scaleFactor = vDecodedMessage[1];
599  retValue = PLUS_SUCCESS;
600  break;
601  }
602  ClearBuffer();
603  }
604  LeaveCriticalSection(&m_CriticalSection);
605 
606  return retValue;
607 }
608 
609 //----------------------------------------------------------------------------
611 {
612  int scaleFactor(0);
613  this->GetMotorizationScaleFactor(scaleFactor);
614 
615  // scaleFactor==0 for non-motorized steppers, scaleFactor>0 for motorized steppers
616  return ( scaleFactor > 0 );
617 }
618 
619 
620 //----------------------------------------------------------------------------
621 PlusStatus PlusCmsBrachyStepper::MoveProbeToPosition(double PositionInMm, int &ReturnCode)
622 {
623  if ( !this->IsStepperMotorized() )
624  {
625  LOG_ERROR("Cannot move probe, the stepper is not motorized");
626  return PLUS_FAIL;
627  }
628 
629  this->TurnMotorOn();
630 
631  // Get probe reference data
632  double count (0), dist(0), scale(0);
633  if ( !this->GetProbeReferenceData(count, dist, scale) )
634  {
635  LOG_ERROR("Unable to get probe reference data");
636  return PLUS_FAIL;
637  }
638 
639  int scaleFactor(0);
640  this->GetMotorizationScaleFactor(scaleFactor);
641 
642  double pPosition(0), gPosition(0), pRotation(0);
643  unsigned long positionRequestNumber(0);
644  if ( !this->GetEncoderValues(pPosition, gPosition, pRotation, positionRequestNumber) )
645  {
646  LOG_ERROR("Unable to get probe position");
647  return PLUS_FAIL;
648  }
649 
650  // Calculate position distance
651  double deltaPosMm = (PositionInMm - pPosition);
652 
653  // Calculate direction
654  const int direction = (deltaPosMm >= 0.0 ? 1 : 0 );
655 
656  // Calculate steps
657  const int steps = static_cast<int>(fabs(deltaPosMm*scaleFactor)+0.5);
658 
659  // Create stepper command
660  unsigned int ck;
661  unsigned char c1,c2, c3, c4, c5, c6, c7, c8;
662  std::string sMessage;
663 
664  sMessage.push_back('7');
665  sMessage.push_back('C');
666  this->BinToAscii((direction & 0xff),&c1,&c2);
667  sMessage.push_back(c1);
668  sMessage.push_back(c2);
669  this->BinToAscii(steps/256, &c3, &c4);
670  sMessage.push_back(c3);
671  sMessage.push_back(c4);
672  this->BinToAscii(steps%256, &c5, &c6);
673  sMessage.push_back(c5);
674  sMessage.push_back(c6);
675  ck = 0x7c + direction + (steps/256) + (steps%256);
676  ck &= 0xff;
677  this->BinToAscii(ck,&c7,&c8);
678  sMessage.push_back(c7);
679  sMessage.push_back(c8);
680 
681  // Send probe to desired position
682  STEPPERCOMMAND moveProbe = (static_cast<STEPPERCOMMAND>(sMessage.c_str()));
683 
684  std::vector<BYTE> vDecodedMessage;
685  PlusStatus retValue(PLUS_FAIL);
686  EnterCriticalSection(&m_CriticalSection);
687  ReturnCode = -1;
688  StepperInstruction(moveProbe);
689 
690  while ( ReturnCode == -1 )
691  {
692  GetStepperMessage(moveProbe, SRC_MOVE_COMPLETE, vDecodedMessage);
693 
694  if (vDecodedMessage.size() >= 2 )
695  {
696  ReturnCode = vDecodedMessage[1];
697  retValue = PLUS_SUCCESS;
698  break;
699  }
700  vtkIGSIOAccurateTimer::GetInstance()->Delay(0.5);
701  }
702  LeaveCriticalSection(&m_CriticalSection);
703 
704  this->TurnMotorOff();
705 
706  return retValue;
707 
708 }
709 
710 //----------------------------------------------------------------------------
712 {
713  PlusStatus retValue(PLUS_FAIL);
714  EnterCriticalSection(&m_CriticalSection);
715  for ( int i = 0; i<MAXTRIES; i++)
716  {
718  std::vector<BYTE> ackMessage;
719  if(IsStepperACKRecieved(ackMessage, SC_BUTTON_ENABLE))
720  {
721  retValue = PLUS_SUCCESS;
722  break;
723  }
724  ClearBuffer();
725  }
726  LeaveCriticalSection(&m_CriticalSection);
727  return retValue;
728 }
729 
730 //----------------------------------------------------------------------------
732 {
733  PlusStatus retValue(PLUS_FAIL);
734  EnterCriticalSection(&m_CriticalSection);
735  for ( int i = 0; i<MAXTRIES; i++)
736  {
738  std::vector<BYTE> ackMessage;
739  if(IsStepperACKRecieved(ackMessage, SC_BUTTON_DISABLE))
740  {
741  retValue = PLUS_SUCCESS;
742  break;
743  }
744  ClearBuffer();
745  }
746  LeaveCriticalSection(&m_CriticalSection);
747  return retValue;
748 }
749 
750 //----------------------------------------------------------------------------
752 {
753  PlusStatus retValue(PLUS_FAIL);
754  EnterCriticalSection(&m_CriticalSection);
755  for ( int i = 0; i<MAXTRIES; i++)
756  {
758  std::vector<BYTE> ackMessage;
760  {
761  retValue = PLUS_SUCCESS;
762  break;
763  }
764  ClearBuffer();
765  }
766  LeaveCriticalSection(&m_CriticalSection);
767  return retValue;
768 }
769 
770 //----------------------------------------------------------------------------
772 {
773  PlusStatus retValue(PLUS_FAIL);
774  EnterCriticalSection(&m_CriticalSection);
775  for ( int i = 0; i<MAXTRIES; i++)
776  {
778  std::vector<BYTE> ackMessage;
780  {
781  retValue = PLUS_SUCCESS;
782  break;
783  }
784  ClearBuffer();
785  }
786  LeaveCriticalSection(&m_CriticalSection);
787  return retValue;
788 }
789 
790 //----------------------------------------------------------------------------
791 void PlusCmsBrachyStepper::SendStepperCommand(STEPPERCOMMAND command, STEPPERRESPCODE Response, std::vector<BYTE> &vRawMessage)
792 {
793  vRawMessage.clear();
794 
795  StepperInstruction(command);
796 
797  GetStepperMessage(command, Response, vRawMessage);
798 }
799 
800 //----------------------------------------------------------------------------
801 void PlusCmsBrachyStepper::SendPositionRequestCommand(STEPPERCOMMAND command, std::vector<BYTE> &vRawMessage)
802 {
803  vRawMessage.clear();
804 
805  if ( ! m_IsCalibrated )
806  {
807  return;
808  }
809 
810  StepperInstruction(command);
811  std::vector<BYTE> StepperMessage;
812  bool ack = IsStepperACKRecieved(StepperMessage, command);
813  if( ack )
814  {
815  StepperMessage.clear();
816  this->ReadStepperAnswer(StepperMessage);
817  }
818 
819  GetPositionMessage(StepperMessage, vRawMessage);
820 
821  if ( !ack )
822  {
823  IsStepperACKRecieved(StepperMessage, command);
824  }
825 
826 #if STEPPERDEBUGMSG
827  std::cout<< "\n" << std::flush;
828 #endif
829 }
830 
831 //----------------------------------------------------------------------------
833 {
834  const char* p = command;
835 
836  m_StepperCOMPort->Write(STX);
837 
838 #if STEPPERDEBUGMSG
839  std::cout << "->" << std::flush;
840 #endif
841 
842  while (*p != 0)
843  {
844  m_StepperCOMPort->Write((BYTE)*p);
845 
846 #if STEPPERDEBUGMSG
847  BYTE b = (byte)*p;
848  std::cout << b << std::flush;
849 #endif
850  p++;
851 }
852 
853  m_StepperCOMPort->Write(ETX);
854 
855 #if STEPPERDEBUGMSG
856  std::cout << " " << std::flush;
857 #endif
858 
859 }
860 
861 //----------------------------------------------------------------------------
862 void PlusCmsBrachyStepper::ReadStepperAnswer(std::vector<BYTE> &stepperAnswer)
863 {
864  stepperAnswer.clear();
865  BYTE buff = 0;
866 
867 #if STEPPERDEBUGMSG
868  std::cout << "<-" << std::flush;
869 #endif
870 
871  while ( m_StepperCOMPort->Read(buff) && buff != ETX)
872  {
873  if (stepperAnswer.max_size() > stepperAnswer.size())
874  {
875  stepperAnswer.push_back(buff);
876  }
877 #if STEPPERDEBUGMSG
878  std::cout << buff << std::flush;
879 #endif
880 
881  }
882 
883  if (buff == ETX)
884  {
885  stepperAnswer.push_back(buff);
886  }
887 
888 #if STEPPERDEBUGMSG
889  std::cout << " " << std::flush;
890 #endif
891 
892 }
893 
894 //----------------------------------------------------------------------------
895 bool PlusCmsBrachyStepper::IsStepperACKRecieved(std::vector<BYTE> &ackMessage, STEPPERCOMMAND command )
896 {
897  this->ReadStepperAnswer(ackMessage);
898 
899  if (ackMessage.size() >= 5
900  &&
901  ( ackMessage[1] == 'F' && ackMessage[2] == 'A' ) )
902  {
903 
904  if ( command[0] == ackMessage[3] && command[1] == ackMessage[4] )
905  {
906  // recieved the expected ack
907  return PLUS_SUCCESS;
908  }
909  else
910  {
911  // recieved another ACK read the message and respond
912  std::vector<BYTE> StepperMessage;
913  this->ReadStepperAnswer(StepperMessage);
914  this->SendAckMessage(StepperMessage);
915  return PLUS_FAIL;
916  }
917  }
918 
919  return PLUS_FAIL;
920 }
921 
922 //----------------------------------------------------------------------------
923 void PlusCmsBrachyStepper::GetStepperMessage(STEPPERCOMMAND command, const char* Response, std::vector<BYTE> &DecodedMessage )
924 {
925  DecodedMessage.clear();
926 
927  std::vector<BYTE> StepperMessage;
928  StepperMessage.reserve(50);
929 
930  bool ack = IsStepperACKRecieved(StepperMessage, command);
931 
932  if ( ack )
933  {
934  StepperMessage.clear();
935  this->ReadStepperAnswer(StepperMessage);
936  }
937 
938  if (StepperMessage.size() >= 3 )
939  {
940  if (StepperMessage[0] == STX &&
941  StepperMessage[1] == Response[0] &&
942  StepperMessage[2] == Response[1])
943  {
944  DecodeStepperMessage(StepperMessage, DecodedMessage);
945  }
946 
947  this->SendAckMessage(StepperMessage);
948  }
949 
950  if ( !ack )
951  {
952  IsStepperACKRecieved(StepperMessage, command);
953  }
954 
955 #if STEPPERDEBUGMSG
956  std::cout<< "\n" << std::flush;
957 #endif
958 
959 }
960 
961 //----------------------------------------------------------------------------
962 void PlusCmsBrachyStepper::SendAckMessage(std::vector<BYTE> StepperMessage)
963 {
964  // Don't respond ack to an ack message
965  if ( StepperMessage.size() < 2 || StepperMessage[1] == 'F' )
966  {
967  return;
968  }
969 
970  std::vector<BYTE> DecodedMessage;
971 
972  this->DecodeStepperMessage(StepperMessage, DecodedMessage);
973 
974  std::string message;
975  this->CreateAckMessage(DecodedMessage[0], &message);
976  this->StepperInstruction(static_cast<STEPPERCOMMAND>(message.c_str()));
977 }
978 
979 //----------------------------------------------------------------------------
980 void PlusCmsBrachyStepper::GetPositionMessage(std::vector<BYTE> &StepperMessage, std::vector<BYTE> &DecodedMessage)
981 {
982  DecodedMessage.clear();
983 
984  if (StepperMessage.size() >= 3 )
985  {
986  if ( StepperMessage[0] == STX &&
987  (
988  (StepperMessage[1] == SRC_POSITION_DATA_BUTTON_ON[0] && StepperMessage[2] == SRC_POSITION_DATA_BUTTON_ON[1])
989  ||
990  (StepperMessage[1] == SRC_POSITION_DATA_BUTTON_OFF[0] && StepperMessage[2] == SRC_POSITION_DATA_BUTTON_OFF[1])
991  ||
992  (StepperMessage[1] == SRC_POSITION_DATA_BUTTON_LATCH[0] && StepperMessage[2] == SRC_POSITION_DATA_BUTTON_LATCH[1])
993  ))
994  {
995  DecodeStepperMessage(StepperMessage, DecodedMessage);
996  std::string message;
997  CreateAckMessage(DecodedMessage[0], &message);
998  this->StepperInstruction(static_cast<STEPPERCOMMAND>(message.c_str()));
999  return;
1000  }
1001  else if (StepperMessage[0] == STX
1002  &&
1003  ( StepperMessage[1] == SRC_COUNTERS_INVALID[0] && StepperMessage[2] == SRC_COUNTERS_INVALID[1]) )
1004  {
1005  this->SetScalingParameters();
1006  this->SendAckMessage(StepperMessage);
1007  return;
1008 
1009  }
1010  // Wrong message received
1011  this->SendAckMessage(StepperMessage);
1012  }
1013 
1014 }
1015 
1016 //----------------------------------------------------------------------------
1017 void PlusCmsBrachyStepper::DecodeStepperMessage(std::vector<BYTE> StepperMessage, std::vector<BYTE> &DecodedMessage)
1018 {
1019  DecodedMessage.clear();
1020  DecodedMessage.reserve(50);
1021 
1022  if ( StepperMessage.size() < 3 )
1023  {
1024  return;
1025  }
1026 
1027  unsigned int i = 1;
1028  unsigned int msglen = this->AsciiToBin(StepperMessage[i], StepperMessage[i+1]);
1029  DecodedMessage.push_back(msglen);
1030  msglen = msglen & 0x7;
1031 
1032  for( msglen ; msglen != 0; --msglen)
1033  {
1034  i = i+2;
1035  if ( StepperMessage.size() > i+1)
1036  {
1037  DecodedMessage.push_back(this->AsciiToBin(StepperMessage[i], StepperMessage[i+1]));
1038  }
1039  }
1040 }
1041 
1042 //----------------------------------------------------------------------------
1044 {
1045  // get reference data for scaling
1046  double count = 0, dist = 0, scale = 0;
1047 
1048  this->GetProbeReferenceData(count, dist, scale);
1049  this->GetGridReferenceData(count, dist, scale);
1050  this->GetRotationReferenceData(count, dist, scale);
1051 }
1052 
1053 //----------------------------------------------------------------------------
1055 {
1056  BYTE buff;
1057  while ( m_StepperCOMPort->Read(buff)){}
1058 }
1059 
1060 //----------------------------------------------------------------------------
1061 void PlusCmsBrachyStepper::CreateAckMessage(BYTE opcode, std::string *sMessage)
1062 {
1063  unsigned int ck;
1064  unsigned char c1,c2, c3, c4, c5, c6;
1065 
1066  ck = 0xfa + static_cast<unsigned int>(opcode);
1067  ck &= 0xff;
1068  this->BinToAscii(0xfa,&c1,&c2);
1069  sMessage->push_back(c1);
1070  sMessage->push_back(c2);
1071 
1072  this->BinToAscii(opcode,&c3,&c4);
1073  sMessage->push_back(c3);
1074  sMessage->push_back(c4);
1075 
1076  this->BinToAscii(ck,&c5,&c6);
1077  sMessage->push_back(c5);
1078  sMessage->push_back(c6);
1079 
1080 }
1081 
1082 //----------------------------------------------------------------------------
1083 unsigned int PlusCmsBrachyStepper::AsciiToBin(unsigned int i, unsigned int j)
1084 {
1085  i -= 0x30;
1086  if (i > 9)
1087  {
1088  i -= 7;
1089  }
1090 
1091  j -= 0x30;
1092  if (j > 9)
1093  {
1094  j -= 7;
1095  }
1096 
1097  return (i*16 + j);
1098 }
1099 
1100 //----------------------------------------------------------------------------
1101 void PlusCmsBrachyStepper::BinToAscii(unsigned int n, unsigned char *c1, unsigned char *c2)
1102 {
1103  unsigned int t1,t2;
1104  t1 = (n/16);
1105  t2 = (n%16);
1106  t1 += 0x30;
1107 
1108  if (t1 > 0x39)
1109  {
1110  t1 += 7;
1111  }
1112 
1113  t2 += 0x30;
1114 
1115  if (t2 > 0x39)
1116  {
1117  t2 += 7;
1118  }
1119 
1120  *c1 = (char)t1;
1121  *c2 = (char)t2;
1122 }
1123 
static const char * CALIB_MSG_ROTATION_TO_BASE
static const char * CALIB_MSG_ROTATION_TO_REF
virtual PlusStatus IsStepperAlive()
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_GRID_REFERENCE_DATA
int Write(const BYTE *data, int numberOfBytesToWrite)
static const char * CALIB_MSG_GRID_TO_REF
virtual PlusStatus InitializeStepper(std::string &CalibMsg)
static const char * CALIB_MSG_PROBE_TO_BASE
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_POSITION_DATA_2
PlusStatus GetMotorizationScaleFactor(int &scaleFactor)
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_IS_MOTORIZED
void SetMaxReplyTime(int maxreply)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_COUNTERS_INVALID
virtual PlusStatus Connect()
igsioStatus PlusStatus
Definition: PlusCommon.h:40
int Read(BYTE *data, int maxNumberOfBytesToRead)
void GetPositionMessage(std::vector< BYTE > &StepperMessage, std::vector< BYTE > &DecodedMessage)
PlusCmsBrachyStepper(unsigned long COMPort=1, unsigned long BaudRate=19200)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_POSITION_DATA_BUTTON_OFF
void GetStepperMessage(STEPPERCOMMAND command, const char *Response, std::vector< BYTE > &DecodedMessage)
PlusStatus StepperRotateCalibrationEnable()
static const char * CALIB_MSG_GRID_TO_HOME
void StepperInstruction(STEPPERCOMMAND command)
for i
void SendPositionRequestCommand(STEPPERCOMMAND command, std::vector< BYTE > &vRawMessage)
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_ROTATION_REFERENCE_DATA
PlusStatus GetCalibrationState(int &PState, int &GState, int &RState)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_MOVE_COMPLETE
bool IsStepperACKRecieved(std::vector< BYTE > &ackMessage, STEPPERCOMMAND command)
PlusStatus GetGridReferenceData(double &count, double &dist, double &scale)
#define PLUS_FAIL
Definition: PlusCommon.h:43
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_POSITION_DATA_1
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_ROTATE_STATE
virtual PlusStatus SetCOMPort(unsigned long COMPort)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_ROTATION_REFERENCE_DATA
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_PROBE_REFERENCE_DATA
Class for reading and writing data through the serial (RS-232) port.
Initial rotation matrix b
Definition: algo3.m:25
static const char * CALIB_MSG_GRID_TO_BASE
#define STX
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_DISABLE_ROTATE_CALIBRATION
virtual PlusStatus GetDeviceModelInfo(std::string &version, std::string &model, std::string &serial)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_CALIBRATION_STATES
void ReadStepperAnswer(std::vector< BYTE > &stepperAnswer)
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_ROTATE_STATE
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_VERSION_INFO
Image slice number p
Definition: algo4.m:14
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_STATUS_INFO
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus GetStatusInfo(unsigned int &Status)
static const char * CALIB_MSG_PROBE_TO_REF
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_PROBE_REFERENCE_DATA
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_STATUS_INFO
PlusStatus GetProbeReferenceData(double &count, double &dist, double &scale)
#define MAXTRIES
static void BinToAscii(unsigned int n, unsigned char *c1, unsigned char *c2)
virtual PlusStatus ResetStepper()
static unsigned int AsciiToBin(unsigned int i, unsigned int j)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_POSITION_DATA_BUTTON_ON
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_RESET_SYSTEM
virtual PlusStatus SetBaudRate(unsigned long BaudRate)
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_CALIBRATION_STATES
PlusStatus GetRotationReferenceData(double &count, double &dist, double &scale)
static const char * CALIB_MSG_PROBE_TO_HOME
PlusStatus GetVersionInfo(int &iVerHi, int &iVerLo, int &iModelNum, int &iSerialNum)
virtual PlusStatus GetEncoderValues(double &PPosition, double &GPosition, double &RPosition, unsigned long &PositionRequestNumber)
unsigned long m_PositionRequestNumber
void SendStepperCommand(STEPPERCOMMAND command, STEPPERRESPCODE Response, std::vector< BYTE > &vRawMessage)
PlusStatus MoveProbeToPosition(double PositionInMm, int &ReturnCode)
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_BUTTON_ENABLE
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_MOTOR_OFF
Phidget_ChannelClass uint32_t * count
Definition: phidget22.h:1321
PlusStatus StepperRotateCalibrationDisable()
static const char * CALIB_MSG_COMPLETED
static const int MAX_REPEATED_POSITION_ERROR_COUNT
void CreateAckMessage(BYTE opcode, std::string *sMessage)
BRACHY_STEPPER_TYPE m_BrachyStepperType
PlusStatus GetRotateState(int &State)
#define ETX
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_MOTOR_ON
void DecodeStepperMessage(std::vector< BYTE > StepperMessage, std::vector< BYTE > &DecodedMessage)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_MOTORIZATION_CODE
const char * message
Definition: phidget22.h:2457
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_BUTTON_DISABLE
unsigned char BYTE
Definition: ATC3DGm.h:449
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_GRID_REFERENCE_DATA
virtual PlusStatus Disconnect()
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_ENABLE_ROTATE_CALIBRATION
PlusStatus GetReferenceData(STEPPERCOMMAND command, STEPPERRESPCODE respcode, double &count, double &dist, double &scale)
static PlusCmsBrachyStepper::STEPPERCOMMAND SC_VERSION_INFO
void SetSerialPortSpeed(DWORD speed)
void SendAckMessage(std::vector< BYTE > StepperMessage)
static PlusCmsBrachyStepper::STEPPERRESPCODE SRC_POSITION_DATA_BUTTON_LATCH
bool IsHandleAlive() const
static const char * CALIB_MSG_ROTATION_TO_HOME