PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
PlusCivcoBrachyStepper.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 
10 #include "SEIDrv32.h"
11 #include <sstream>
12 
13 //----------------------------------------------------------------------------
14 PlusCivcoBrachyStepper::PlusCivcoBrachyStepper(unsigned long COMPort/*=1*/, unsigned long BaudRate/*=9600*/)
15 {
16  this->m_COMPort = 0;
17  this->SetCOMPort(COMPort);
18 
19  this->m_BaudRate = 0;
20  this->SetBaudRate(BaudRate);
21 
22  this->m_DeviceNumber = 0; // Currently we assume only one device
23  this->m_DeviceAddress = 0;
24 }
25 
26 //----------------------------------------------------------------------------
28 {
29 
30 }
31 
32 //----------------------------------------------------------------------------
34 {
35  // SEI Initialization.
36  // Start the SEI Server Program, and look for devices on the SEI bus
37  // the zero means to look on all com ports, and the AUTOASSIGN means
38  // that if there are address conflicts on the SEI bus, the device
39  // addresses will automatically be reassigned so there are no conflicts
40  // Initialization.
41  if (this->IsStepperAlive() != PLUS_SUCCESS)
42  {
43  if (::InitializeSEI(this->m_COMPort, REINITIALIZE | AUTOASSIGN | NORESET) != 0)
44  {
45  LOG_ERROR("Failed to initialize SEI! COMPort=" << this->m_COMPort);
46  return PLUS_FAIL;
47  }
48 
49  if (this->SetBaudRate(this->m_BaudRate) != PLUS_SUCCESS)
50  {
51  LOG_ERROR("Failed to set baud rate for SEI!");
52  return PLUS_FAIL;
53  }
54  }
55  else
56  {
57  LOG_DEBUG("No need to initialize SEI, it's already connected!");
58  }
59 
60  if (this->GetNumberOfSeiDevices() > 0)
61  {
62  // We assume that only one device connected to bus
63  const long devNumber = 0;
64  long lModel = 0;
65  long lSerialNumber = 0;
66  long lVersion = 0;
67  long lAddress = 0;
68  if (this->GetSeiDeviceInfo(devNumber, lModel, lSerialNumber, lVersion, lAddress) != PLUS_SUCCESS)
69  {
70  LOG_ERROR("Failed to get SEI device info for device number: " << devNumber);
71  return PLUS_FAIL;
72  }
73 
74  this->m_DeviceAddress = lAddress;
75  this->m_DeviceNumber = devNumber;
76  }
77  else
78  {
79  LOG_WARNING("No device connected to ED2!");
80  }
81 
82  return PLUS_SUCCESS;
83 }
84 
85 //----------------------------------------------------------------------------
87 {
88  if (::IsInitialized() != 1)
89  {
90  // Device not yet initialized
91  return PLUS_SUCCESS;
92  }
93 
94  if (::CloseSEI() != 0)
95  {
96  LOG_ERROR("Failed to close SEI!");
97  return PLUS_FAIL;
98  }
99 
100  return PLUS_SUCCESS;
101 }
102 
103 //----------------------------------------------------------------------------
105  double& GPosition, double& RPosition, unsigned long& PositionRequestNumber)
106 {
107  // Increase the m_PositionNumber on every position request
108  PositionRequestNumber = ++m_PositionRequestNumber;
109 
110  // Probe position
111  PPosition = 0.0;
112  // Grid position
113  GPosition = 0.0; // There is no optical encoder on template grid
114  // Probe rotation
115  RPosition = 0.0;
116 
117  // Probe rotation encoder value
118  long rotAngle(0);
119  if (::ED2GetPosition1(this->m_DeviceAddress, &rotAngle) != 0)
120  {
121  LOG_ERROR("Failed to get position1 (rotation angle) from E2 device!");
122  return PLUS_FAIL;
123  }
124 
125  RPosition = this->ConvertFloatToDecimal(rotAngle);
126 
127  // Probe translation encoder value
128  long probePositionInCm(0);
129  if (::ED2GetPosition2(this->m_DeviceAddress, &probePositionInCm) != 0)
130  {
131  LOG_ERROR("Failed to get position2 (probe position) from E2 device!");
132  return PLUS_FAIL;
133  }
134 
135  PPosition = this->ConvertFloatToDecimal(probePositionInCm) * 10.0;
136 
137  // Change the sign of the encoder value to be correspond with the tracker coordinate system defined in the model
138  PPosition = -1.0 * PPosition;
139 
140  return PLUS_SUCCESS;
141 }
142 
143 //----------------------------------------------------------------------------
144 // IEEE Standard 754 floating point to double conversion
145 // http://steve.hollasch.net/cgindex/coding/ieeefloat.html
147 {
148  // Separate input number into the sign, exponent, and mantissa fields.
149  int sign = ((floatPoint >> 31) == 0) ? 1 : -1;
150 
151  // Extract the exponent from the exponent field
152  // The exponent field needs to represent both positive and negative exponents.
153  // To do this, a bias is added to the actual exponent in order to get the stored exponent.
154  int exp = ((floatPoint >> 23) & 0xff);
155 
156  // Extract the mantissa from the mantissa field
157  // The mantissa, also known as the significand, represents the precision bits
158  // of the number. It is composed of an implicit leading bit and the fraction bits.
159  int m = (exp == 0) ? (floatPoint & 0x7fffff) << 1 : (floatPoint & 0x7fffff) | 0x800000;
160 
161  // Copy the binary numbers to char array
162  char bitset[25];
163  _ltoa_s(m, bitset, 25, 2);
164 
165  // Compute the normalized mantissa in decimal format
166  double mantissa = 0;
167  for (int i = 0; i < 24; i++)
168  {
169  const char bit = bitset[i];
170  mantissa += atoi(&bit) * pow(2.0, -i);
171  }
172 
173  // subtract the bias to recover the actual exponent of two
174  // the bias is 2^(k-1) - 1, where k is the number of bits in the exponent field, giving 127 for the 32-bit format
175  const double bias = 127;
176 
177  // Convert the binary value to decimal
178  // Set the sign of the decimal number according to the sign bit of the original floating point number: make it negative for 1; leave positive for 0.
179  double decimalPoint = sign * mantissa * pow(2.0, exp - bias);
180 
181  return decimalPoint;
182 }
183 
184 //----------------------------------------------------------------------------
185 PlusStatus PlusCivcoBrachyStepper::GetDeviceModelInfo(std::string& version, std::string& model, std::string& serial)
186 {
187  long lModel = 0;
188  long lSerialNumber = 0;
189  long lVersion = 0;
190  long lAddress = 0;
191  if (this->GetSeiDeviceInfo(this->m_DeviceNumber, lModel, lSerialNumber, lVersion, lAddress) != PLUS_SUCCESS)
192  {
193  LOG_ERROR("Failed to get SEI device info for device number: " << this->m_DeviceNumber);
194  return PLUS_FAIL;
195  }
196 
197  // Set version info
198  std::ostringstream strVersion;
199  strVersion << lVersion;
200  version = strVersion.str();
201 
202  // Set model info
203  std::ostringstream strModel;
204  strModel << lModel;
205  model = strModel.str();
206 
207  // Set serial info
208  std::ostringstream strSerial;
209  strModel << lModel;
210  serial = strModel.str();
211 
212  return PLUS_SUCCESS;
213 }
214 
215 //----------------------------------------------------------------------------
217 {
218  if (::ResetSEI() != 0)
219  {
220  LOG_ERROR("Failed to reset SEI bus!");
221  return PLUS_FAIL;
222  }
223 
224  return PLUS_SUCCESS;
225 }
226 
227 //----------------------------------------------------------------------------
229 {
230  // Set 0 encoder values
231  CalibMsg = "Encoder values set to 0!";
232  return this->ResetStepper();
233 }
234 
235 //----------------------------------------------------------------------------
237 {
238  if (::IsInitialized() != 1)
239  {
240  // Device not yet initialized
241  return PLUS_FAIL;
242  }
243 
244  return PLUS_SUCCESS;
245 }
246 
247 //----------------------------------------------------------------------------
249 {
250  this->m_BaudRate = BaudRate;
251 
252  if (this->IsStepperAlive() == PLUS_SUCCESS)
253  {
254  if (::SetBaudRate(BaudRate) != 0)
255  {
256  LOG_ERROR("Failed to set baud rate for SEI!");
257  return PLUS_FAIL;
258  }
259  }
260 
261  return PLUS_SUCCESS;
262 }
263 
264 //----------------------------------------------------------------------------
266 {
267  if (this->IsStepperAlive() == PLUS_SUCCESS)
268  {
269  // If the SEI server still running in the backgroud no need to change COM port
270  LOG_DEBUG("Unable to set serial port number, stepper already connected!");
271  return PLUS_FAIL;
272  }
273 
274  this->m_COMPort = COMPort;
275  return PLUS_SUCCESS;
276 }
277 
278 //----------------------------------------------------------------------------
280 {
282 }
283 
284 //----------------------------------------------------------------------------
285 PlusStatus PlusCivcoBrachyStepper::GetSeiDeviceInfo(long devnum, long& model, long& serialnum, long& version, long& addr)
286 {
287  if (::GetDeviceInfo(devnum, &model, &serialnum, &version, &addr) != 0)
288  {
289  LOG_ERROR("Failed to get device info from SEI with device number: " << devnum);
290  return PLUS_FAIL;
291  }
292  return PLUS_SUCCESS;
293 }
294 
virtual PlusStatus ResetStepper()
bool IsInitialized()
Definition: SEIDrv.cpp:107
virtual PlusStatus Disconnect()
long __stdcall ResetSEI()
igsioStatus PlusStatus
Definition: PlusCommon.h:40
virtual PlusStatus IsStepperAlive()
long GetDeviceInfo(long devnum, long &serialnum, long &addr, char *model, char *firmwareVersion)
Definition: SEIDrv.cpp:117
for i
void CloseSEI()
Definition: SEIDrv.cpp:141
PlusStatus GetSeiDeviceInfo(long devnum, long &model, long &serialnum, long &version, long &addr)
#define PLUS_FAIL
Definition: PlusCommon.h:43
virtual PlusStatus GetEncoderValues(double &PPosition, double &GPosition, double &RPosition, unsigned long &PositionRequestNumber)
long InitializeSEI(long comm, long mode, int devicesExpected)
Definition: SEIDrv.cpp:67
PlusCivcoBrachyStepper(unsigned long COMPort=1, unsigned long BaudRate=9600)
virtual PlusStatus GetDeviceModelInfo(std::string &version, std::string &model, std::string &serial)
virtual PlusStatus Connect()
double ConvertFloatToDecimal(long floatPoint)
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
virtual PlusStatus InitializeStepper(std::string &CalibMsg)
unsigned long m_PositionRequestNumber
virtual PlusStatus SetBaudRate(unsigned long BaudRate)
virtual PlusStatus SetCOMPort(unsigned long COMPort)
const long AUTOASSIGN
Definition: SEIDrv.h:22
long GetNumberOfDevices()
Definition: SEIDrv.cpp:112
long __stdcall ED2GetPosition2(long address, long *pos)
const long REINITIALIZE
Definition: SEIDrv.h:27
const long NORESET
Definition: SEIDrv.h:25
long __stdcall ED2GetPosition1(long address, long *pos)