direcs  2012-09-30
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
laserThread.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) Markus Knapp *
3  * www.direcs.de *
4  * *
5  * This file is part of direcs. *
6  * *
7  * direcs is free software: you can redistribute it and/or modify it *
8  * under the terms of the GNU General Public License as published *
9  * by the Free Software Foundation, version 3 of the License. *
10  * *
11  * direcs is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with direcs. If not, see <http://www.gnu.org/licenses/>. *
18  * *
19  *************************************************************************/
20 
21 #include "laserThread.h"
22 
23 
25 {
26  stopped = false;
29  simulationMode = false;
30  measureMode = false;
31  numReadingsFront = 0;
32  numReadingsRear = 0;
37 
38  // for the simulation values
39  inifile1 = new Inifile();
40  inifile1->setFilename("direcs.sim");
41 
42  // for the simulation values
43  // file name will be set during call of saveLaserData
44  inifileLaserdata = new Inifile();
45 }
46 
47 
49 {
50  // laserScannerFrontIsConnected is set in the isConnected method!
52  {
54  {
55  // closing com port etc. is done in the laser class destructor
56  delete laserS300;
57  }
58  }
59 
60  delete inifileLaserdata;
61  delete inifile1;
62 }
63 
64 
66 {
67  stopped = true;
68  numReadingsFront = 0;
69  numReadingsRear = 0;
70 }
71 
72 
74 {
75  static int errorCounter = 0;
76 
77 
78  // check if all necessary values wer set / members are initialised
80  {
81  // don't thread
82  stopped = true;
83  }
84 
85  // check if all 180 beams were read
86  numReadingsFront = 0;
87  numReadingsRear = 0;
88 
89  //
90  // start "threading"...
91  //
92  while (!stopped)
93  {
94  // let the thread sleep some time
95  // for having more time for the other threads
96  msleep(THREADSLEEPTIME);
97 
98  if (
99  ((simulationMode==false) && (laserScannerFrontIsConnected == true)) ||
100  ((simulationMode==false) && (laserScannerRearIsConnected == true))
101  )
102  {
104  {
106  if (laserS300->readRequestTelegram() != -1)
107  {
110 
111  // resetting error counter one by one (for each good read, we are moving to "0".
112  if (errorCounter > 0)
113  {
114  errorCounter--;
115  }
116  }
117  else
118  {
119  if (errorCounter >= MAXERRORS)
120  {
121  // emitting a signal to other modules which don't get the return value but need to know that we have a sensor error here.
122  emit systemerror(-1);
123 
124  stopped = true;
125  emit message(QString("%1 ERRORs reading S300 data. Laser thread stopped!").arg(MAXERRORS));
126  errorCounter = 0;
127  }
128  else
129  {
130  errorCounter++;
131  emit message(QString("%1. error reading S300 laser.").arg(errorCounter));
132  }
133  }
134  }
135  }
136  else
137  {
138  //---------------------------------
139  // S I M U L A T I O N M O D E
140  //---------------------------------
143  //====================================================================
144  // e m i t Signal
145  //====================================================================
148  }
149  }
150  stopped = false;
151 }
152 
153 
155 {
157  {
158  float currentDistance = 0.0;
159 
160 
161  if (mountingLaserscannerFront == "normal")
162  {
163  // /get the data from 0 to 270 degrees (left to right)
164  // since we have a resolution at 0.5 degrees, this is an index for the array with 540 values!
165  for (int angleIndex=0; angleIndex<(laserscannerAngleFront/laserscannerResolutionFront); angleIndex++)
166  {
167  // get distance
168  currentDistance = laserS300->getDistance(angleIndex);
169 
170  // are we in a the special measure mode? (e.g. walking around the robot for saving a special distance)
171  if (measureMode)
172  {
173  // only store value from laser if the new value (current distance) is less than the last stored value
174  if (currentDistance < laserScannerValuesFront[angleIndex])
175  {
176  // store the value in an array in this thread
177  laserScannerValuesFront[angleIndex] = currentDistance;
178  }
179  }
180  else
181  {
182  // store the value in an array in this thread
183  laserScannerValuesFront[angleIndex] = currentDistance;
184  }
185 
186  // send value over the network
187  // *0l23a42# means LASER1 has at angle 23 a length of 42 cm
188  emit sendNetworkString( QString("*%1l%2a%3#").arg(LASER1).arg(angleIndex).arg( (int) (laserScannerValuesFront[angleIndex]*100) ) );
189  }
190  }
191  else
192  {
193  // flip the data, due to a flipped mounting of the hardware!
194  //
195  // get the data from 0 to 270 degrees (left to right)
196  // since we have a resolution at 0.5 degrees, this is an index for the array with 540 values!
197  // 'flip' will be increased every step - 1, so the data are stored from 270 deg to 0 deg
198  for (int angleIndex=0, flip=(laserscannerAngleFront/laserscannerResolutionFront)-1; angleIndex<(laserscannerAngleFront/laserscannerResolutionFront); angleIndex++, flip--)
199  {
200  // get distance
201  currentDistance = laserS300->getDistance(angleIndex);
202 
203  // are we in a the special measure mode? (e.g. walking around the robot for saving a special distance)
204  if (measureMode)
205  {
206  // only store value from laser if the new value (current distance) is less than the last stored value
207  if (currentDistance < laserScannerValuesFront[angleIndex])
208  {
209  // store the value in an array in this thread
210  laserScannerValuesFront[flip] = currentDistance;
211  }
212  }
213  else
214  {
215  // store the value in an array in this thread
216  laserScannerValuesFront[flip] = currentDistance;
217  }
218 
219  // send value over the network
220  // *0l23a42# means LASER1 has at angle 23 a length of 42 cm
221  emit sendNetworkString( QString("*%1l%2a%3#").arg(LASER1).arg(angleIndex).arg( (int) (laserScannerValuesFront[angleIndex]*100) ) );
222  }
223  }
224  }
225 }
226 
227 
229 {
230  if (laserscannerTypeRear == S300)
231  {
233  }
234 }
235 
236 
237 float LaserThread::getValue(short int laserScanner, int angle)
238 {
239  switch(laserScanner)
240  {
241  case LASER1:
242  if ( (angle < 0) || ((angle >= (laserscannerAngleFront/laserscannerResolutionFront) ) ) )
243  {
244  qDebug("Laser1 angle %d out of allowed range 0-%.1f (LaserThread::getValue).", angle, (laserscannerAngleFront/laserscannerResolutionFront));
245  return 0;
246  }
247  return laserScannerValuesFront[angle];
248  break;
249  case LASER2:
250  if ( (angle < 0) || ((angle >= (laserscannerAngleRear/laserscannerResolutionRear) ) ) )
251  {
252  qDebug("Laser1 angle %d out of allowed range 0-%.1f (LaserThread::getValue).", angle, (laserscannerAngleRear/laserscannerResolutionRear));
253  return 0;
254  }
255  return laserScannerValuesRear[angle];
256  break;
257  }
258 
259  return 0;
260 }
261 
262 
263 int LaserThread::getFlag(short int laserScanner, int angle)
264 {
265  switch(laserScanner)
266  {
267  case LASER1:
268  if ( (angle < 0) || ((angle >= (laserscannerAngleFront/laserscannerResolutionFront) ) ) )
269  {
270 // qDebug("Laser1 angle %d out of allowed range 0-%.1f (LaserThread::getFlag).", angle, (laserscannerAngleFront/laserscannerResolutionFront));
271  return 0;
272  }
273  return laserScannerFlagsFront[angle];
274  break;
275  case LASER2:
276  if ( (angle < 0) || ((angle >= (laserscannerAngleRear/laserscannerResolutionRear) ) ) )
277  {
278 // qDebug("Laser2 angle %d out of allowed range 0-%.1f (LaserThread::getFlag).", angle, (laserscannerAngleRear/laserscannerResolutionRear));
279  return 0;
280  }
281  return laserScannerFlagsRear[angle];
282  break;
283  }
284 
285  return 0;
286 }
287 
288 
289 void LaserThread::setFlag(short int laserScanner, int angle, int flag)
290 {
291  switch(laserScanner)
292  {
293  case LASER1:
294  if ( (angle < 0) || ((angle >= (laserscannerAngleFront/laserscannerResolutionFront) ) ) )
295  {
296 // qDebug("Laser1 angle %d out of allowed range 0-%.1f (LaserThread::setFlag).", angle, (laserscannerAngleFront/laserscannerResolutionFront));
297  break;
298  }
299  laserScannerFlagsFront[angle] = flag;
300  break;
301  case LASER2:
302  if ( (angle < 0) || ((angle >= (laserscannerAngleRear/laserscannerResolutionRear) ) ) )
303  {
304 // qDebug("Laser2 angle %d out of allowed range 0-%.1f (LaserThread::setFlag).", angle, (laserscannerAngleRear/laserscannerResolutionRear));
305  break;
306  }
307  laserScannerFlagsRear[angle] = flag;
308  break;
309  }
310 
311  return;
312 }
313 
314 
316 {
317  // check if all necessary values have been initialised
319  {
320  if (laserscannerAngleFront == -1)
321  {
322  qDebug("Front laser angle not set before calling LaserThread::setSimulationMode()!");
323  return;
324  }
325  if (laserscannerResolutionFront == -1)
326  {
327  qDebug("Front laser resolution not set before calling LaserThread::setSimulationMode()!");
328  return;
329  }
330  }
331 
333  {
334  if (laserscannerAngleRear == -1)
335  {
336  qDebug("Rear laser angle not set before calling LaserThread::setSimulationMode()!");
337  return;
338  }
339  if (laserscannerResolutionRear == -1)
340  {
341  qDebug("Rear laser resolution not set before calling LaserThread::setSimulationMode()!");
342  return;
343  }
344  }
345 
346  // store the sim state
347  simulationMode = state;
348 
349 
350  if (simulationMode == true)
351  {
352  // sim value init
353  if (readSimulationValues() == false)
354  {
355  simulationMode = false;
356  return;
357  }
358 
361 
362  // copy sim values into the distances values
363  for (int i=0; i<laserScannerValuesFront.count(); i++)
364  {
365  // the distances
366  // laserScannerValuesFront[i] = 2.30; //(i+1) / 100;
368  // the flags
370  }
371 
372  for (int i=0; i<laserScannerValuesRear.count(); i++)
373  {
374  // the distances
375  // laserScannerValuesRear[i] = 2.30; //(i+1) / 100;
377  // the flags
379  }
380 
381  // for refreshing the gui (deleting simulated laser lines)
384  }
385  else
386  {
387  // initialisation
388  for (int i=0; i<laserScannerValuesFront.count(); i++)
389  {
390  // the distances
392  // the flags
394  }
395 
396  for (int i=0; i<laserScannerValuesRear.count(); i++)
397  {
398  // the distances
399  laserScannerValuesRear[i] = 0;
400  // the flags
402  }
403 
404  // for refreshing the gui (deleting simulated laser lines)
407  }
408 }
409 
410 
412 {
413  // store that we are in measure state now (or not)
414  measureMode = state;
415 }
416 
417 
418 void LaserThread::setSerialPort(short int laserScanner, QString serialPort)
419 {
420  switch (laserScanner)
421  {
422  case LASER1:
424  {
425  return;
426  }
427 
429  {
430  laserS300->setDevicePort(serialPort);
431  return;
432  }
433 
434  qDebug("Laser1 type %d not supported (LaserThread::setSerialPort", laserscannerTypeFront);
435  return;
436  break;
437  case LASER2:
439  {
440  return;
441  }
442 
444  {
446  qDebug("Laser2 for S300 not yet supported (LaserThread::setSerialPort)");
447  return;
448  }
449 
450  qDebug("Laser2 type %d not supported (LaserThread::setSerialPort)", laserscannerTypeRear);
451  return;
452  break;
453  default:
454  qDebug("Laser number %d not yet supported (LaserThread::setSerialPort)", laserScanner);
455  break;
456  }
457 }
458 
459 
460 void LaserThread::setMounting(short int laserScanner, QString mounting)
461 {
462  switch (laserScanner)
463  {
464  case LASER1:
465  mountingLaserscannerFront = mounting;
466  break;
467  case LASER2:
468  mountingLaserscannerRear = mounting;
469  break;
470  default:
471  qDebug("laser number not yet supported (LaserThread::setMounting");
472  break;
473  }
474 }
475 
476 
477 void LaserThread::setType(short int laserScanner, QString laserType)
478 {
479  switch (laserScanner)
480  {
481  case LASER1:
482  if (laserType=="S300")
483  {
485  }
486  else
487  {
488  if (laserType=="none")
489  {
491  }
492  else
493  {
494  qDebug("laser type not yet supported (LaserThread::setLaserscannerType, LASER1");
495  }
496  }
497  break;
498  case LASER2:
499  if (laserType=="S300")
500  {
502  }
503  else
504  {
505  if (laserType=="none")
506  {
508  }
509  else
510  {
511  qDebug("laser type not yet supported (LaserThread::setLaserscannerType, LASER2");
512  }
513  }
514  break;
515  default:
516  qDebug("laser number not yet supported (LaserThread::setLaserscannerType");
517  break;
518  }
519 
520 
521  // create the laser object
522  // S300 stuff
523  if (laserType=="S300")
524  {
525  laserS300 = new SickS300();
526 
527  // let the splash screen and the GUI / log file from the direcs class show laser init messages
528  // (connect the signal from the laser class to the signal from this class)
529  connect(laserS300, SIGNAL(message(QString)), this, SIGNAL(message(QString)));
530 
531  return;
532  }
533 }
534 
535 
536 void LaserThread::setAngle(short int laserScanner, int angle)
537 {
538  switch (laserScanner)
539  {
540  case LASER1:
541  // store value in the class member
542  laserscannerAngleFront = angle;
543  break;
544  case LASER2:
545  // store value in the class member
546  laserscannerAngleRear = angle;
547  break;
548  default:
549  qDebug("laser number not yet supported (LaserThread::setLaserscannerAngle");
550  break;
551  }
552 }
553 
554 
555 void LaserThread::setResolution(short int laserScanner, float resolution)
556 {
557  switch (laserScanner)
558  {
559  case LASER1:
560  // store value in the class member
561  laserscannerResolutionFront = resolution;
562  break;
563  case LASER2:
564  // store value in the class member
565  laserscannerResolutionRear = resolution;
566  break;
567  default:
568  qDebug("laser number not yet supported (LaserThread::setLaserscannerResolution");
569  break;
570  }
571 }
572 
573 
574 int LaserThread::getAngle(short int laserScanner)
575 {
576  switch (laserScanner)
577  {
578  case LASER1:
579  return laserscannerAngleFront;
580  break;
581  case LASER2:
582  return laserscannerAngleRear;
583  break;
584  }
585 
586  qDebug("laser number not yet supported (LaserThread::getAngle");
587  return 0;
588 }
589 
590 
591 float LaserThread::getResolution(short int laserScanner)
592 {
593  switch (laserScanner)
594  {
595  case LASER1:
597  break;
598  case LASER2:
600  break;
601  }
602 
603  qDebug("laser number not yet supported (LaserThread::getResolution");
604  return 0;
605 }
606 
607 
608 bool LaserThread::isConnected(short int laserScanner)
609 {
610  switch (laserScanner)
611  {
612  case LASER1:
613  // check if all necessary values have been initialised
614  if (laserscannerAngleFront == -1)
615  {
616  qDebug("Front laser angle not set before calling LaserThread::isConnecteed()!");
617  return false;
618  }
619  if (laserscannerResolutionFront == -1)
620  {
621  qDebug("Front laser resolution not set before calling LaserThread::isConnecteed()!");
622  return false;
623  }
624 
625  // initialisation of the laser values list (QList). Create one object with length 0.0 for every laser line
627  {
628  laserScannerValuesFront.append(0.0);
629  }
630 
631  // add a 0 flag for each line
633  {
634  laserScannerFlagsFront.append(0);
635  }
636 
637  // initialisation of the laser simulation values list (QList)
639  {
640  simulationValuesFront.append(0.0);
641  }
642 
644  {
646  if (laserS300->openComPort() == true)
647  {
648  if (laserS300->setup() == 0)
649  {
651  return true;
652  }
653  }
654 
656  return false;
657  }
658  else
659  {
661  {
662  qDebug("ERROR: Unsupported laser type! (LaserThread::isConnected)");
663  }
665  return false;
666  }
667  break;
668  case LASER2:
669  // check if all necessary values have been initialised
670  if (laserscannerAngleRear == -1)
671  {
672  qDebug("Rear laser angle not set before calling LaserThread::isConnecteed()!");
673  return false;
674  }
675  if (laserscannerResolutionRear == -1)
676  {
677  qDebug("Rear laser resolution not set before calling LaserThread::isConnecteed()!");
678  return false;
679  }
680 
681  // initialisation of the laser values list (QList). Create one object with length 0.0 for every laser line
682  for (int i=0; i<(laserscannerAngleRear/laserscannerResolutionRear); i++)
683  {
684  laserScannerValuesRear.append(0.0);
685  }
686 
687  // add a 0 flag for each line
688  for (int i=0; i<(laserscannerAngleRear/laserscannerResolutionRear); i++)
689  {
690  laserScannerFlagsRear.append(0);
691  }
692 
693  // initialisation of the laser simulation values list (QList)
694  for (int i=0; i<(laserscannerAngleRear/laserscannerResolutionRear); i++)
695  {
696  simulationValuesRear.append(0.0);
697  }
698 
699  if (laserscannerTypeRear == S300)
700  {
702  qDebug("Support for a second S300 as rear laser scanner not implemented yet");
704  return false;
705  }
706  else
707  {
708  if (laserscannerTypeRear != NONE)
709  {
710  qDebug("ERROR: Unsupported laser type! (LaserThread::isConnected)");
711  }
713  return false;
714  }
715  break;
716  default:
717  qDebug("laser number not yet supported (LaserThread::setMounting");
718  break;
719  }
720 
721 
722  stopped = true; // don't run the thread!
723  return false;
724 }
725 
726 
728 {
729  float floatValue = -1.0;
730 
731 
732  // read the FRONT laser sim values from file
734  {
735  // read value from ini file
736  floatValue = inifile1->readFloat("Frontlaser", QString("%1").arg(i) );
737 
738  if (floatValue == -1)
739  {
740  simulationValuesFront[i] = 0.0;
741  qDebug("Simulation value \"%d\" not found in sim file at [Frontlaser]! LaserThread::setSimulationValues", i);
742  qDebug("Stopping to read!");
743  return false;
744  }
745  else
746  {
747  // store the value
748  simulationValuesFront[i] = floatValue;
749  }
750  }
751 
752  // read the REAR laser sim values from file
753  for (int i=0; i<(laserscannerAngleRear/laserscannerResolutionRear); i++)
754  {
755  // read value from ini file
756  floatValue = inifile1->readFloat("Rearlaser", QString("%1").arg(i) );
757 
758  if (floatValue == -1)
759  {
760  simulationValuesRear[i] = 0.0;
761  qDebug("Simulation value \"%d\" not found in sim file at [Rearlaser]! LaserThread::setSimulationValues", i);
762  qDebug("Stopping to read!");
763  return false;
764  }
765  else
766  {
767  // store the value
768  simulationValuesRear[i] = floatValue;
769  }
770  }
771 
772  return true;
773 }
774 
775 
777 {
778  QDateTime now; // this is for the timestamp in the log
779  QString filename;
780  QString stringName;
781  QString stringValue;
782 
783 
784  // get current date and time
785  now = QDateTime::currentDateTime(); // get the current date and time
786 
787  // set filenam
788  filename = QString("direcs__%1-%2-%3__%4-%5-%6.sim").arg(now.toString("yyyy")).arg(now.toString("MM")).arg(now.toString("dd")).arg(now.toString("hh")).arg(now.toString("mm")).arg(now.toString("ss"));
789  inifileLaserdata->setFilename(filename);
790 
792 
793  // write the FRONT laser sim values to file
795  {
796  // convert i to string
797  stringName = QString("%1").arg(i);
798 
799  // convert laser float values to string
800  // we are using a string instead of float here, since Qt write float in a quite non human readable format like 'settingt=@Variant(\0\0\0\x87@\xa0\0\0)'.
801  stringValue = QString("%1").arg( laserScannerValuesFront.at(i) );
802 
803  // write value to ini file
804  inifileLaserdata->writeSetting("Frontlaser", stringName, stringValue);
805  }
806 
807  // write the REAR laser sim values to file
808  for (int i=0; i<(laserscannerAngleRear/laserscannerResolutionRear); i++)
809  {
810  // convert i to string
811  stringName = QString("%1").arg(i);
812 
813  // convert laser float values to string
814  // we are using a string instead of float here, since Qt write float in a quite non human readable format like 'settingt=@Variant(\0\0\0\x87@\xa0\0\0)'.
815  stringValue = QString("%1").arg( laserScannerValuesRear.at(i) );
816 
817  // write value to ini file
818  inifileLaserdata->writeSetting("Rearlaser", stringName, stringValue);
819  }
820 
821 
822  emit message(QString("Laser data written to <b>%1</b>").arg(filename));
823 }