PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusChRoboticsTracker.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 "ChrSerialPacket.h"
10 #include "PlusSerialLine.h"
12 #include "vtkMatrix4x4.h"
13 #include "vtkObjectFactory.h"
14 #include "vtkPlusDataSource.h"
15 #include "vtkTransform.h"
16 #include "vtkXMLDataElement.h"
17 #include "vtkXMLUtilities.h"
18 #include "vtksys/SystemTools.hxx"
19 #include <deque>
20 #include <sstream>
21 
22 #include <math.h>
23 
24 #ifdef _WIN32
25  #include <io.h> // for findnext
26 #else
27  #include <dirent.h>
28 #endif
29 
30 
32 
33 //-------------------------------------------------------------------------
34 // Definitions of constant register address (addresses that must remain the same on all firmware versions)
35 static const unsigned char UM6_GET_FW_VERSION = 170;
36 
37 // Definitions of some error packets - these are also required to remain constant through all firmware revisions
38 static const unsigned char UM6_BAD_CHECKSUM = 253;
39 static const unsigned char UM6_UNKNOWN_ADDRESS = 254;
40 static const unsigned char UM6_INVALID_BATCH_SIZE = 255;
41 
42 static const unsigned char DATA_REGISTER_START_ADDRESS = 85;
43 static const unsigned char COMMAND_START_ADDRESS = 170;
44 
45 //-------------------------------------------------------------------------
46 
47 static const int MAX_COMMAND_REPLY_WAIT = 3000; // number of maximum replies to wait for a command reply
48 
49 //-------------------------------------------------------------------------
51  SerialPort(5),
52  BaudRate(115200)
53 {
54  this->Serial = new SerialLine();
55 
56  this->OrientationSensorTool = NULL;
57 
58  this->FirmwareDefinition = vtkXMLDataElement::New();
59 
61 
62  // No callback function provided by the device, so the data capture thread will be used to poll the hardware and add new items to the buffer
63  this->StartThreadForInternalUpdates = true;
64  this->AcquisitionRate = 20;
65 }
66 
67 //-------------------------------------------------------------------------
69 {
70  if (this->Recording)
71  {
72  this->StopRecording();
73  }
74 
75  if (this->Serial->IsHandleAlive())
76  {
77  this->Serial->Close();
78  delete this->Serial;
79  this->Serial = NULL;
80  }
81 
82  this->FirmwareDefinition->Delete();
83  this->FirmwareDefinition = NULL;
84 }
85 
86 //-------------------------------------------------------------------------
87 void vtkPlusChRoboticsTracker::PrintSelf(ostream& os, vtkIndent indent)
88 {
89  Superclass::PrintSelf(os, indent);
90 }
91 
92 //-------------------------------------------------------------------------
94 {
95  LOG_TRACE("vtkPlusChRoboticsTracker::Connect");
96 
97  if (this->Serial->IsHandleAlive())
98  {
99  LOG_ERROR("Already connected to serial port");
100  return PLUS_FAIL;
101  }
102 
103  std::ostringstream strComPort;
104  strComPort << "COM" << this->SerialPort;
105  this->Serial->SetPortName(strComPort.str());
106 
107  this->Serial->SetSerialPortSpeed(this->BaudRate);
108 
109  this->Serial->SetMaxReplyTime(1000);
110 
111  if (!this->Serial->Open())
112  {
113  LOG_ERROR("Cannot open serial port " << strComPort.str());
114  return PLUS_FAIL;
115  }
116 
117  if (!this->Serial->IsHandleAlive())
118  {
119  LOG_ERROR("COM port handle is not alive " << strComPort.str());
120  return PLUS_FAIL;
121  }
122 
124  {
125  LOG_ERROR("Failed to load firmware description for the connected device");
126  this->Serial->Close();
127  return PLUS_FAIL;
128  }
129 
131  {
132  LOG_ERROR("Failed to update data item descriptors from firmware description");
133  this->Serial->Close();
134  return PLUS_FAIL;
135  }
136 
137  this->OrientationSensorTool = NULL;
138  GetToolByPortName("OrientationSensor", this->OrientationSensorTool);
139 
140  return PLUS_SUCCESS;
141 }
142 
143 //-------------------------------------------------------------------------
145 {
146  LOG_TRACE("vtkPlusChRoboticsTracker::Disconnect");
147  this->StopRecording();
148 
149  this->Serial->Close();
150 
151  this->OrientationSensorTool = NULL;
152  return PLUS_SUCCESS;
153 }
154 
155 //-------------------------------------------------------------------------
157 {
158  LOG_TRACE("vtkPlusChRoboticsTracker::Probe");
159 
160  LOG_ERROR("vtkPlusChRoboticsTracker::Probe is not implemented");
161 
162  return PLUS_SUCCESS;
163 }
164 
165 //-------------------------------------------------------------------------
167 {
168  LOG_TRACE("vtkPlusChRoboticsTracker::InternalStartRecording");
169  return PLUS_SUCCESS;
170 }
171 
172 //-------------------------------------------------------------------------
174 {
175  LOG_TRACE("vtkPlusChRoboticsTracker::InternalStopRecording");
176  return PLUS_SUCCESS;
177 }
178 
179 //-------------------------------------------------------------------------
181 {
182  LOG_TRACE("vtkPlusChRoboticsTracker::InternalUpdate");
183 
184  ChrSerialPacket packet;
185 
186  while (this->Serial->GetNumberOfBytesAvailableForReading() > 0)
187  {
188  if (ReceivePacket(packet) == PLUS_SUCCESS)
189  {
190  ProcessPacket(packet);
191  }
192  }
193 
194  const double unfilteredTimestamp = vtkIGSIOAccurateTimer::GetSystemTime();
195 
196  if (this->OrientationSensorTool != NULL)
197  {
198  vtkSmartPointer<vtkMatrix4x4> orientationSensorToTracker = vtkSmartPointer<vtkMatrix4x4>::New();
199 
200  // LOG_TRACE("roll="<<this->EulerRoll.GetValue() <<", pitch="<<this->EulerPitch.GetValue() <<", yaw="<<this->EulerYaw.GetValue());
201 
202  vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
203  transform->RotateX(this->EulerRoll.GetValue());
204  transform->RotateY(this->EulerPitch.GetValue());
205  transform->RotateZ(this->EulerYaw.GetValue());
206  transform->GetMatrix(orientationSensorToTracker);
207 
208  // This device has no frame numbering, so just auto increment tool frame number
209  unsigned long frameNumber = this->OrientationSensorTool->GetFrameNumber() + 1 ;
210  ToolTimeStampedUpdate(this->OrientationSensorTool->GetId(), orientationSensorToTracker, TOOL_OK, frameNumber, unfilteredTimestamp);
211  }
212 
213  return PLUS_SUCCESS;
214 }
215 
216 //-------------------------------------------------------------------------
217 PlusStatus vtkPlusChRoboticsTracker::FindFirmwareDefinition(const std::string& requestedFirmwareId, vtkXMLDataElement* foundDefinition)
218 {
219  std::string firmwareFullPath = vtkPlusConfig::GetInstance()->GetDeviceSetConfigurationPath(this->FirmwareDirectory.c_str());
220  LOG_DEBUG("Loading the firmware files from " << firmwareFullPath);
221 
222  std::vector<std::string> firmwareFileList;
223  GetFileNamesFromDirectory(firmwareFileList, firmwareFullPath);
224  if (firmwareFileList.size() == 0)
225  {
226  LOG_ERROR("Failed to load firmware definitions from " << firmwareFullPath);
227  return PLUS_FAIL;
228  }
229 
230  for (std::vector<std::string>::iterator it = firmwareFileList.begin(); it != firmwareFileList.end(); ++it)
231  {
232  LOG_DEBUG("Loading firmware from: " << (*it));
233  vtkSmartPointer<vtkXMLDataElement> firmwareElemRoot = vtkSmartPointer<vtkXMLDataElement>::Take(vtkXMLUtilities::ReadElementFromFile((*it).c_str()));
234  if (firmwareElemRoot.GetPointer() == NULL)
235  {
236  LOG_WARNING("Failed to read firmware definition from " << (*it) << ". The file is ignored.");
237  continue;
238  }
239  const char* foundFirmwareId = firmwareElemRoot->GetAttribute("id");
240  if (foundFirmwareId == NULL)
241  {
242  LOG_WARNING("Id not found in firmware definition file " << (*it) << ". The file is ignored.");
243  continue;
244  }
245 
246  if (requestedFirmwareId.compare(foundFirmwareId) == 0)
247  {
248  // found firmware description
249  foundDefinition->DeepCopy(firmwareElemRoot);
250  return PLUS_SUCCESS;
251  }
252  }
253 
254  foundDefinition->RemoveAllAttributes();
255  foundDefinition->RemoveAllNestedElements();
256  LOG_ERROR("Could not find ChRobotics firmware definition for attached device (" << requestedFirmwareId << ")");
257  return PLUS_FAIL;
258 }
259 
260 //----------------------------------------------------------------------------
261 void vtkPlusChRoboticsTracker::GetFileNamesFromDirectory(std::vector<std::string>& fileNames, const std::string& dir)
262 {
263 #ifdef _WIN32 // Windows
264  _finddata_t file;
265  std::string findPath = dir + "\\*.*";
266  long currentPosition = _findfirst(findPath.c_str(), &file); //find the first file in directory
267  if (currentPosition == -1L)
268  {
269  return ; //end the procedure if no file is found
270  }
271  do
272  {
273  std::string fileName = file.name;
274  //ignore . and ..
275  if (strcmp(fileName.c_str(), ".") != 0 && strcmp(fileName.c_str(), "..") != 0)
276  {
277  //If not subdirectory
278  if (!(file.attrib & _A_SUBDIR))
279  {
280  fileNames.push_back(std::string(dir) + "/" + fileName);
281  }
282  }
283  }
284  while (_findnext(currentPosition, &file) == 0);
285  _findclose(currentPosition); //close search
286 #else // Linux
287  DIR* d;
288  struct dirent* ent;
289  if ((d = opendir(dir.c_str())) != NULL)
290  {
291  while ((ent = readdir(d)) != NULL)
292  {
293  std::string entry(ent->d_name);
294  if (entry != "." && entry != "..")
295  {
296  fileNames.push_back(dir + "/" + entry);
297  }
298  }
299  }
300  closedir(d);
301 #endif
302 }
303 
304 //-------------------------------------------------------------------------
306 {
307  PlusStatus status = PLUS_SUCCESS;
308 
309  if (FindDataItemDescriptor("Roll (phi)", this->EulerRoll) != PLUS_SUCCESS) { status = PLUS_FAIL; }
310  if (FindDataItemDescriptor("Pitch (theta)", this->EulerPitch) != PLUS_SUCCESS) { status = PLUS_FAIL; }
311  if (FindDataItemDescriptor("Yaw (psi)", this->EulerYaw) != PLUS_SUCCESS) { status = PLUS_FAIL; }
312 
313  return status;
314 }
315 
316 //-------------------------------------------------------------------------
318 {
319  this->EulerRoll.ReadValueFromPacket(packet);
320  this->EulerPitch.ReadValueFromPacket(packet);
321  this->EulerYaw.ReadValueFromPacket(packet);
322 }
323 
324 
325 //-------------------------------------------------------------------------
327 {
328  if (this->FirmwareDefinition == NULL)
329  {
330  LOG_ERROR("Firmware definition is not available");
331  return PLUS_FAIL;
332  }
333 
334  const std::string dataGroupElemName = "DataGroup";
335  const std::string dataItemElemName = "DataItem";
336 
337  for (int dataGroupIndex = 0; dataGroupIndex < this->FirmwareDefinition->GetNumberOfNestedElements(); ++dataGroupIndex)
338  {
339  vtkXMLDataElement* groupElem = this->FirmwareDefinition->GetNestedElement(dataGroupIndex);
340  if (groupElem == NULL)
341  {
342  continue;
343  }
344  if (dataGroupElemName.compare(groupElem->GetName()) != 0)
345  {
346  // not a data group
347  continue;
348  }
349  for (int dataItemIndex = 0; dataItemIndex < groupElem->GetNumberOfNestedElements(); ++dataItemIndex)
350  {
351  vtkXMLDataElement* dataItemElem = groupElem->GetNestedElement(dataItemIndex);
352 
353  if (dataItemElemName.compare(dataItemElem->GetName()) != 0)
354  {
355  // not a data item
356  continue;
357  }
358 
359  vtkXMLDataElement* dataItemNameElem = dataItemElem->FindNestedElementWithName("Name");
360  if (dataItemNameElem == NULL)
361  {
362  // name is undefined
363  continue;
364  }
365  if (itemName.compare(dataItemNameElem->GetCharacterData()) != 0)
366  {
367  // item name does not match the item that we are looking for
368  continue;
369  }
370  // data item description found
371  return foundItem.ReadDescriptionFromXml(dataItemElem);
372  }
373  }
374 
375  LOG_ERROR("Data item desctiption not found: " << itemName);
376  return PLUS_FAIL;
377 }
378 
379 //-------------------------------------------------------------------------
381 {
382  LOG_TRACE("vtkPlusChRoboticsTracker::LoadFirmwareDescriptionForConnectedDevice");
383  this->FirmwareVersionId.clear();
384 
385  ChrSerialPacket fwRequest;
386  fwRequest.SetHasData(false);
387  fwRequest.SetBatchEnable(false);
388  fwRequest.SetAddress(UM6_GET_FW_VERSION);
389 
390  ChrSerialPacket fwReply;
391 
392  if (SendCommand(fwRequest, fwReply) != PLUS_SUCCESS)
393  {
394  LOG_ERROR("Failed to query ChRobotics device firmware version");
395  return PLUS_FAIL;
396  }
397 
398  // Convert packet data to string
399  unsigned char dataLength = fwReply.GetDataLength();
400  for (int i = 0; i < dataLength; i++)
401  {
402  this->FirmwareVersionId.push_back(fwReply.GetDataByte(i));
403  }
404 
405  // Search loaded firmware items to determine if we have a definition
406  // for the firmware revision given by the sensor.
407  if (FindFirmwareDefinition(this->FirmwareVersionId, this->FirmwareDefinition) != PLUS_SUCCESS)
408  {
409  LOG_ERROR("Failed to load firmware definition for ChRobotics device version " << this->FirmwareVersionId);
410  return PLUS_FAIL;
411  }
412 
413  LOG_INFO("CHRobotics device firmware identified (" << this->FirmwareVersionId << ") and firmware definition loaded.");
414  return PLUS_SUCCESS;
415 }
416 
417 //-------------------------------------------------------------------------
419 {
420  if (SendPacket(requestPacket) != PLUS_SUCCESS)
421  {
422  return PLUS_FAIL;
423  }
424  for (int i = 0; i < MAX_COMMAND_REPLY_WAIT; i++)
425  {
426  ReceivePacket(replyPacket);
427  if (replyPacket.GetAddress() == requestPacket.GetAddress())
428  {
429  // we've received reply to the command
430  return PLUS_SUCCESS;
431  }
432  }
433  LOG_ERROR("Failed to receive reply to command " << int(requestPacket.GetAddress()));
434  return PLUS_FAIL;
435 }
436 
437 //-------------------------------------------------------------------------
439 {
440  std::vector<unsigned char> data_array;
441 
442  packet.ComputeChecksum();
443  unsigned char packetLength = packet.GetPacketLength();
444  for (int i = 0; i < packetLength; i++)
445  {
446  this->Serial->Write(packet.GetPacketByte(i));
447  }
448 
449  LOG_TRACE("Sent packet: address=" << int(packet.GetAddress()) << ", data length=" << int(packet.GetDataLength()));
450 
451  return PLUS_SUCCESS;
452 }
453 
454 //-------------------------------------------------------------------------
456 {
457  // search for the packet start sequence "snp"
458  std::deque<unsigned char> lastThreeChars;
459  unsigned char d = 0;
460  this->Serial->Read(d);
461  lastThreeChars.push_back(d);
462  this->Serial->Read(d);
463  lastThreeChars.push_back(d);
464  this->Serial->Read(d);
465  lastThreeChars.push_back(d);
466  while (lastThreeChars[0] != 's' || lastThreeChars[1] != 'n' || lastThreeChars[2] != 'p')
467  {
468  lastThreeChars.pop_front();
469  if (!this->Serial->Read(d))
470  {
471  LOG_ERROR("Failed to read packet header (start sequence) through serial line");
472  return PLUS_FAIL;
473  }
474  lastThreeChars.push_back(d);
475  }
476 
477  if (!this->Serial->Read(d))
478  {
479  LOG_ERROR("Failed to read packet header (packet descriptor) through serial line");
480  return PLUS_FAIL;
481  }
482  packet.SetPacketDescriptor(d);
483 
484  if (!this->Serial->Read(d))
485  {
486  LOG_ERROR("Failed to read packet header (address) through serial line");
487  return PLUS_FAIL;
488  }
489  packet.SetAddress(d);
490 
491  // Copy data bytes into packet data array
492  int dataLength = packet.GetDataLength();
493  for (int i = 0; i < dataLength; i++)
494  {
495  if (!this->Serial->Read(d))
496  {
497  LOG_ERROR("Failed to read packet data[" << i << "] through serial line");
498  return PLUS_FAIL;
499  }
500  packet.SetDataByte(i, d);
501  }
502 
503  unsigned char checksum0 = 0;
504  if (!this->Serial->Read(checksum0))
505  {
506  LOG_ERROR("Failed to read packet checksum[0] through serial line");
507  return PLUS_FAIL;
508  }
509  unsigned char checksum1 = 0;
510  if (!this->Serial->Read(checksum1))
511  {
512  LOG_ERROR("Failed to read packet checksum[1] through serial line");
513  return PLUS_FAIL;
514  }
515 
516  // Compute the checksum and compare with the one given in the packet. If different, ignore this packet
517  packet.ComputeChecksum();
518 
519  if (packet.GetChecksumByte(0) != checksum0 || packet.GetChecksumByte(1) != checksum1)
520  {
521  LOG_ERROR("Received a packet with bad checksum through serial line ("
522  << "address=" << int(packet.GetAddress()) << ", checksum: "
523  << int(packet.GetChecksumByte(0)) << "!=" << int(checksum0) << " and/or "
524  << int(packet.GetChecksumByte(1)) << "!=" << int(checksum1) << ")"
525  );
526  return PLUS_FAIL;
527  }
528 
529  LOG_TRACE("Received packet: address=" << int(packet.GetAddress()) << ", data length=" << int(packet.GetDataLength()));
530 
531  return PLUS_SUCCESS;
532 }
533 
534 //-------------------------------------------------------------------------
536 {
537  // Firmware-independent processing
538 
539  if (packet.GetAddress() == UM6_BAD_CHECKSUM)
540  {
541  LOG_WARNING("Received ChRobotics sensor reply: BAD_CHECKSUM");
542  return PLUS_FAIL;
543  }
544  else if (packet.GetAddress() == UM6_UNKNOWN_ADDRESS)
545  {
546  LOG_WARNING("Received ChRobotics sensor reply: UNKNOWN_ADDRESS");
547  return PLUS_FAIL;
548  }
549  else if (packet.GetAddress() == UM6_INVALID_BATCH_SIZE)
550  {
551  LOG_WARNING("Received ChRobotics sensor reply: INVALID_BATCH_SIZE");
552  return PLUS_FAIL;
553  }
554 
555  if (packet.GetHasData())
556  {
557  // Packet has data.
558 
559  // If this packet reported the contents of data registers, update local data registers accordingly
561  {
562  UpdateDataItemValues(packet);
563  }
564  else if (packet.GetAddress() < DATA_REGISTER_START_ADDRESS)
565  {
566  // this packet reported the contents of configuration registers
567  // we could get here the new configuration register value
568  }
569  else
570  {
571  // command received
572  LOG_WARNING("Improperly formatted packet: commands should never contain data");
573  }
574  }
575  else
576  {
577  // Packet has no data
579  {
580  // configuration register address
581  // the packet signifies that a write operation to a configuration register was just completed
582  }
583  else if (packet.GetAddress() >= COMMAND_START_ADDRESS)
584  {
585  // command register address
586  // the packet signals that a received command either succeeded or failed
587  }
588  }
589 
590  return PLUS_SUCCESS;
591 
592 }
593 
594 //----------------------------------------------------------------------------
595 PlusStatus vtkPlusChRoboticsTracker::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
596 {
597  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
598  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, SerialPort, deviceConfig);
599  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, BaudRate, deviceConfig);
600  XML_READ_CSTRING_ATTRIBUTE_OPTIONAL(FirmwareDirectory, deviceConfig);
601  return PLUS_SUCCESS;
602 }
603 
604 //----------------------------------------------------------------------------
605 PlusStatus vtkPlusChRoboticsTracker::WriteConfiguration(vtkXMLDataElement* rootConfigElement)
606 {
607  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(trackerConfig, rootConfigElement);
608  trackerConfig->SetUnsignedLongAttribute("SerialPort", this->SerialPort);
609  trackerConfig->SetUnsignedLongAttribute("BaudRate", this->BaudRate);
610  return PLUS_SUCCESS;
611 }
virtual PlusStatus InternalDisconnect()
unsigned char GetDataLength()
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
bool ReadValueFromPacket(ChrSerialPacket &packet)
Definition: ChrDataItem.h:111
int Write(const BYTE *data, int numberOfBytesToWrite)
PlusStatus LoadFirmwareDescriptionForConnectedDevice()
static const int MAX_COMMAND_REPLY_WAIT
PlusStatus FindDataItemDescriptor(const std::string itemName, ChrDataItem &foundItem)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
void SetMaxReplyTime(int maxreply)
int
Definition: phidget22.h:3069
igsioStatus PlusStatus
Definition: PlusCommon.h:40
int Read(BYTE *data, int maxNumberOfBytesToRead)
static const unsigned char UM6_BAD_CHECKSUM
PlusStatus ReadDescriptionFromXml(vtkXMLDataElement *dataItemElem)
Definition: ChrDataItem.h:27
void SetBatchEnable(bool enable)
virtual PlusStatus ToolTimeStampedUpdate(const std::string &aToolSourceId, vtkMatrix4x4 *matrix, ToolStatus status, unsigned long frameNumber, double unfilteredtimestamp, const igsioFieldMapType *customFields=NULL)
bool RequirePortNameInDeviceSetConfiguration
void SetHasData(bool has_data)
unsigned char GetChecksumByte(int index)
for i
double AcquisitionRate
PlusStatus FindFirmwareDefinition(const std::string &id, vtkXMLDataElement *foundDefinition)
#define PLUS_FAIL
Definition: PlusCommon.h:43
unsigned char GetPacketByte(int index)
static vtkPlusConfig * GetInstance()
Class for reading and writing data through the serial (RS-232) port.
void SetPacketDescriptor(unsigned char packetDescriptor)
void GetFileNamesFromDirectory(std::vector< std::string > &fileNames, const std::string &dir)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
void SetAddress(unsigned char address)
unsigned char GetDataByte(int index)
PlusStatus ProcessPacket(ChrSerialPacket &packet)
static const unsigned char DATA_REGISTER_START_ADDRESS
PlusStatus SendPacket(ChrSerialPacket &packet)
vtkStandardNewMacro(vtkPlusChRoboticsTracker)
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus GetToolByPortName(const char *aPortName, vtkPlusDataSource *&aSource)
Interface for the CH Robotics CHR-UM6 tracker.
void UpdateDataItemValues(ChrSerialPacket &packet)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
virtual PlusStatus StopRecording()
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
void SetDataByte(int index, unsigned char value)
void ComputeChecksum(void)
unsigned char GetPacketLength()
void PrintSelf(ostream &os, vtkIndent indent)
unsigned char GetAddress()
bool StartThreadForInternalUpdates
unsigned int GetNumberOfBytesAvailableForReading() const
static const unsigned char COMMAND_START_ADDRESS
std::string GetDeviceSetConfigurationPath(const std::string &subPath)
PlusStatus ReceivePacket(ChrSerialPacket &packet)
PlusStatus SendCommand(ChrSerialPacket &requestPacket, ChrSerialPacket &replyPacket)
static const unsigned char UM6_INVALID_BATCH_SIZE
void SetSerialPortSpeed(DWORD speed)
bool IsHandleAlive() const
static const unsigned char UM6_GET_FW_VERSION
double GetValue()
Definition: ChrDataItem.h:138
static const unsigned char UM6_UNKNOWN_ADDRESS