YARP
Yet Another Robot Platform
imuBosch_BNO055.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <arpa/inet.h>
20 #include <cerrno> // Error number definitions
21 #include <cmath>
22 #include <cstdlib>
23 #include <cstring>
24 #include <fcntl.h> // File control definitions
25 #include <iostream>
26 #include <termios.h> // terminal io (serial port) interface
27 #include <unistd.h>
28 
29 #include <linux/i2c-dev.h>
30 #ifdef I2C_HAS_SMBUS_H
31 extern "C" {
32 # include <i2c/smbus.h>
33 }
34 #endif
35 #include <linux/kernel.h>
36 
37 #include <sys/ioctl.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 
41 #include <mutex>
42 #include <yarp/os/Log.h>
43 #include <yarp/os/LogComponent.h>
44 #include <yarp/os/LogStream.h>
45 #include <yarp/math/Math.h>
46 #include <yarp/os/Time.h>
47 
48 #include "imuBosch_BNO055.h"
49 
50 using namespace std;
51 using namespace yarp::os;
52 using namespace yarp::dev;
53 
54 namespace {
55 YARP_LOG_COMPONENT(IMUBOSCH_BNO055, "yarp.device.imuBosch_BNO055")
56 constexpr uint8_t i2cAddrA = 0x28;
57 }
58 
59 //constexpr uint8_t i2cAddrB = 0x29;
60 
62  verbose(false),
63  status(0),
64  nChannels(12),
65  m_timeStamp(0.0),
66  timeLastReport(0.0),
67  i2c_flag(false),
68  checkError(false),
69  fd(0),
70  responseOffset(0),
71  readFunc(&BoschIMU::sendReadCommandSer),
72  totMessagesRead(0),
73  errs(0),
74  dataIsValid(false)
75 {
76  data.resize(12);
77  data.zero();
78  data_tmp.resize(12);
79  data_tmp.zero();
80  errorCounter.resize(11);
81  errorCounter.zero();
82 }
83 
84 BoschIMU::~BoschIMU() = default;
85 
86 
88 {
89  //debug
90  yCTrace(IMUBOSCH_BNO055, "Parameters are:\n\t%s", config.toString().c_str());
91 
92  if(!config.check("comport") && !config.check("i2c"))
93  {
94  yCError(IMUBOSCH_BNO055) << "Params 'comport' and 'i2c' not found";
95  return false;
96  }
97 
98  if (config.check("comport") && config.check("i2c"))
99  {
100  yCError(IMUBOSCH_BNO055) << "Params 'comport' and 'i2c' both specified";
101  return false;
102  }
103 
104  i2c_flag = config.check("i2c");
105 
107 
108  // In case of reading through serial the first two bytes of the response are the ack, so
109  // they need to be discarded when publishing the data.
110  responseOffset = i2c_flag ? 0 : 2;
111 
112  if (i2c_flag)
113  {
114  if (!config.find("i2c").isString())
115  {
116  yCError(IMUBOSCH_BNO055) << "i2c param malformed, it should be a string, aborting.";
117  return false;
118  }
119 
120  std::string i2cDevFile = config.find("i2c").asString();
121  fd = ::open(i2cDevFile.c_str(), O_RDWR);
122 
123  if (fd < 0)
124  {
125  yCError(IMUBOSCH_BNO055, "Can't open %s, %s", i2cDevFile.c_str(), strerror(errno));
126  return false;
127  }
128 
129  if (::ioctl(fd, I2C_SLAVE, i2cAddrA) < 0)
130  {
131  yCError(IMUBOSCH_BNO055, "ioctl failed on %s, %s", i2cDevFile.c_str(), strerror(errno));
132  return false;
133  }
134 
135  }
136  else
137  {
138  fd = ::open(config.find("comport").toString().c_str(), O_RDWR | O_NOCTTY );
139  if (fd < 0) {
140  yCError(IMUBOSCH_BNO055, "Can't open %s, %s", config.find("comport").toString().c_str(), strerror(errno));
141  return false;
142  }
143  //Get the current options for the port...
144  struct termios options;
145  tcgetattr(fd, &options);
146 
147  cfmakeraw(&options);
148 
149  //set the baud rate to 115200
150  int baudRate = B115200;
151  cfsetospeed(&options, baudRate);
152  cfsetispeed(&options, baudRate);
153 
154  //set the number of data bits.
155  options.c_cflag &= ~CSIZE; // Mask the character size bits
156  options.c_cflag |= CS8;
157 
158  //set the number of stop bits to 1
159  options.c_cflag &= ~CSTOPB;
160 
161  //Set parity to None
162  options.c_cflag &=~PARENB;
163 
164  //set for non-canonical (raw processing, no echo, etc.)
165  // options.c_iflag = IGNPAR; // ignore parity check
166  options.c_oflag = 0; // raw output
167  options.c_lflag = 0; // raw input
168 
169  // SET NOT BLOCKING READ
170  options.c_cc[VMIN] = 0; // block reading until RX x characters. If x = 0, it is non-blocking.
171  options.c_cc[VTIME] = 2; // Inter-Character Timer -- i.e. timeout= x*.1 s
172 
173  //Set local mode and enable the receiver
174  options.c_cflag |= (CLOCAL | CREAD);
175 
176  tcflush(fd, TCIOFLUSH);
177 
178  //Set the new options for the port...
179  if ( tcsetattr(fd, TCSANOW, &options) != 0)
180  {
181  yCError(IMUBOSCH_BNO055, "Configuring comport failed");
182  return false;
183  }
184 
185  }
186 
187  nChannels = config.check("channels", Value(12)).asInt32();
188 
189  double period = config.check("period",Value(10),"Thread period in ms").asInt32() / 1000.0;
190  setPeriod(period);
191 
192  if (config.check("sensor_name") && config.find("sensor_name").isString())
193  {
194  m_sensorName = config.find("sensor_name").asString();
195  }
196  else
197  {
198  m_sensorName = "sensor_imu_bosch_bno055";
199  yCWarning(IMUBOSCH_BNO055) << "Parameter \"sensor_name\" not set. Using default value \"" << m_sensorName << "\" for this parameter.";
200  }
201 
202  if (config.check("frame_name") && config.find("frame_name").isString())
203  {
204  m_frameName = config.find("frame_name").asString();
205  }
206  else
207  {
208  m_frameName = m_sensorName;
209  yCWarning(IMUBOSCH_BNO055) << "Parameter \"frame_name\" not set. Using the same value as \"sensor_name\" for this parameter.";
210  }
211 
212  return PeriodicThread::start();
213 }
214 
216 {
217  yCTrace(IMUBOSCH_BNO055);
218  //stop the thread
219  PeriodicThread::stop();
220  return true;
221 }
222 
223 bool BoschIMU::checkReadResponse(unsigned char* response)
224 {
225  if(response[0] == (unsigned char) REPLY_HEAD)
226  {
227  return true;
228  }
229 
230  if(response[0] == (unsigned char) ERROR_HEAD)
231  {
232  if(response[1] != REGISTER_NOT_READY) // if error is 0x07, do not print error messages
233  {
234  yCError(IMUBOSCH_BNO055,
235  "Inertial sensor didn't understand the command. \n\
236  If this error happens more than once in a row, please check serial communication is working fine and it isn't affected by electrical disturbance.");
237  }
238  errorCounter[response[1]]++;
239  readSysError();
240  return false;
241  }
242 
243  errorCounter[0]++;
244  yCError(IMUBOSCH_BNO055,
245  "Received unknown response message. \n\
246  If this error happens more than once in a row, please check serial communication is working fine and it isn't affected by electrical disturbance.");
247  dropGarbage();
248  readSysError();
249  return false;
250 }
251 
252 bool BoschIMU::checkWriteResponse(unsigned char* response)
253 {
254  if(response[0] == (unsigned char) ERROR_HEAD)
255  {
256  if(response[1] == (unsigned char) WRITE_SUCC)
257  {
258  return true;
259  }
260  if(response[1] != REGISTER_NOT_READY) // if error is 0x07, do not print error messages
261  {
262  yCError(IMUBOSCH_BNO055,
263  "Inertial sensor didn't understand the command. \n\
264  If this error happens more than once in a row, please check serial communication is working fine and it isn't affected by electrical disturbance.");
265  }
266  errorCounter[response[1]]++;
267  readSysError();
268  return false;
269  }
270 
271  errorCounter[0]++;
272  yCError(IMUBOSCH_BNO055,
273  "Received unknown response message. \n\
274  If this error happens more than once in a row, please check serial communication is working fine and it isn't affected by electrical disturbance.");
275  dropGarbage();
276  readSysError();
277  return false;
278 }
279 
280 bool BoschIMU::sendReadCommandSer(unsigned char register_add, int len, unsigned char* buf, std::string comment)
281 {
282  int command_len;
283  int nbytes_w;
284 
285  //
286  // Create a READ message
287  //
288  bool success = false;
289  for(int trials=0; (trials<3) && (success==false); trials++)
290  {
291  totMessagesRead++;
292  command_len = 4;
293  command[0]= START_BYTE; // start byte
294  command[1]= READ_CMD; // read operation
295  command[2]= register_add; // register to read
296  command[3]= len; // length in bytes
297 
298 // yCTrace(IMUBOSCH_BNO055, "> READ_COMMAND: %s ... ", comment.c_str());
299 // yCTrace(IMUBOSCH_BNO055, "Command is:");
300 // printBuffer(command, command_len);
301 
302  nbytes_w = ::write(fd, (void*)command, command_len);
303 
304  if(nbytes_w != command_len)
305  {
306  yCError(IMUBOSCH_BNO055) << "Cannot correctly send the message: " << comment;
307  // DO NOT return here. If something was sent, then the imu will reply with a message
308  // even an error message. I have to parse it before proceeding and not leave garbage behind.
309  }
310  // Read the write reply
311  memset(buf, 0x00, 20);
312  int readbytes = readBytes(buf, RESP_HEADER_SIZE);
313  if(readbytes != RESP_HEADER_SIZE)
314  {
315  yCError(IMUBOSCH_BNO055, "Expected %d bytes, read %d instead", RESP_HEADER_SIZE, readbytes);
316  success = false;
317  }
318  else if(!checkReadResponse(buf))
319  {
320  success = false;
322  }
323  else
324  {
325  success = true;
326 // yCTrace(IMUBOSCH_BNO055, "> SUCCESS!"); fflush(stdout);
327 
328  // Read the data payload
329  readBytes(&buf[2], (int) buf[1]);
330 // yCTrace(IMUBOSCH_BNO055, "\tReply is:");
331 // printBuffer(buf, buf[1]+2);
332 // yCTrace(IMUBOSCH_BNO055, "***************");
333  }
334  }
335 // if(!success)
336 // yCError(IMUBOSCH_BNO055, "> FAILED reading %s!", comment.c_str());
337  return success;
338 }
339 
340 bool BoschIMU::sendWriteCommandSer(unsigned char register_add, int len, unsigned char* cmd, std::string comment)
341 {
342  int command_len = 4+len;
343  int nbytes_w;
344 
345  command[0]= START_BYTE; // start byte
346  command[1]= WRITE_CMD; // read operation
347  command[2]= register_add; // operation mode register
348  command[3]= (unsigned char) len; // length 1 byte
349  for(int i=0; i<len; i++)
350  command[4+i] = cmd[i]; // data
351 
352 // yCTrace(IMUBOSCH_BNO055, "> WRITE_COMMAND: %s ... ", comment.c_str());
353 // yCTrace(IMUBOSCH_BNO055, "Command is:");
354 // printBuffer(command, command_len);
355 
356  nbytes_w = ::write(fd, (void*)command, command_len);
357  if(nbytes_w != command_len)
358  {
359  yCError(IMUBOSCH_BNO055) << "Cannot correctly send the message: " << comment;
360  // DO NOT return here. If something was sent, then the imu will reply with a message
361  // even an error message. I have to parse it before proceeding and not leave garbage behind.
362  }
363 
364  // Read the write reply
365  memset(response, 0x00, 20);
366  readBytes(response, 2);
367  if(!checkWriteResponse(response))
368  {
369 // yCTrace(IMUBOSCH_BNO055, "> FAILED!"); fflush(stdout);
370  yCError(IMUBOSCH_BNO055) << "FAILED writing " << comment;
371  return false;
372  }
373 // yCTrace(IMUBOSCH_BNO055, "> SUCCESS!"); fflush(stdout);
374 // yCTrace(IMUBOSCH_BNO055, "\tReply is:");
375 // printBuffer(response, 2);
376 // yCTrace(IMUBOSCH_BNO055, "***************");
377  return true;
378 }
379 
380 int BoschIMU::readBytes(unsigned char* buffer, int bytes)
381 {
382  int r = 0;
383  int bytesRead = 0;
384  do
385  {
386  r = ::read(fd, (void*)&buffer[bytesRead], 1);
387  if(r > 0)
388  bytesRead += r;
389  }
390  while(r!=0 && bytesRead < bytes);
391 
392  return bytesRead;
393 }
394 
396 {
397  char byte;
398  while( (::read(fd, (void*) &byte, 1) > 0 ))
399  {
400 // yCTrace(IMUBOSCH_BNO055, "Dropping byte 0x%02X", byte);
401  }
402  return;
403 }
404 
405 void BoschIMU::printBuffer(unsigned char* buffer, int length)
406 {
407  for(int i=0; i< length; i++)
408  printf("\t0x%02X ", buffer[i]);
409  printf("\n");
410 }
411 
413 {
414  // avoid recursive error check
415  if(checkError)
416  return;
417 
418  checkError = true;
420  if(!sendReadCommandSer(REG_SYS_STATUS, 1, response, "Read SYS_STATUS register") )
421  {
422  yCError(IMUBOSCH_BNO055) << "@ line " << __LINE__;
423  }
424 
425  if(!sendReadCommandSer(REG_SYS_ERR, 1, response, "Read SYS_ERR register") )
426  {
427  yCError(IMUBOSCH_BNO055) << "@ line " << __LINE__;
428  }
429  checkError = false;
430  return;
431 }
432 
433 bool BoschIMU::sendAndVerifyCommandSer(unsigned char register_add, int len, unsigned char* cmd, std::string comment)
434 {
435  uint8_t attempts=0;
436  bool ret;
437  do
438  {
439  ret=sendWriteCommandSer(register_add, len, cmd, comment);
440  attempts++;
441  }while((attempts<= ATTEMPTS_NUM_OF_SEND_CONFIG_CMD) && (ret==false));
442 
443  return(ret);
444 }
445 
446 bool BoschIMU::sendReadCommandI2c(unsigned char register_add, int len, unsigned char* buf, std::string comment)
447 {
448  if (i2c_smbus_read_i2c_block_data(fd, register_add, len, buf) < 0)
449  {
450  yCError(IMUBOSCH_BNO055) << "Cannot correctly send the message: " << comment;
451  return false;
452  }
453  return true;
454 }
455 
457 {
458  if (i2c_flag)
459  {
460  int trials = 0;
461  // Make sure we have the right device
462  while (i2c_smbus_read_byte_data(fd, REG_CHIP_ID) != BNO055_ID)
463  {
464  if (trials == 10)
465  {
466  yCError(IMUBOSCH_BNO055) << "Wrong device on the bus, it is not BNO055";
467  return false;
468  }
470  trials++;
471 
472  }
473 
475 
476  // Set the device in config mode
477  if (i2c_smbus_write_byte_data(fd, REG_OP_MODE, CONFIG_MODE) < 0)
478  {
479  yCError(IMUBOSCH_BNO055) << "Unable to set the Config mode";
480  return false;
481  }
482 
484 
485  if (i2c_smbus_write_byte_data(fd, REG_SYS_TRIGGER, TRIG_EXT_CLK_SEL) < 0)
486  {
487  yCError(IMUBOSCH_BNO055) << "Unable to set external clock";
488  return false;
489  }
490 
492 
493  // Perform any required configuration
494 
495 
496  if (i2c_smbus_write_byte_data(fd, REG_PAGE_ID, 0x00) < 0)
497  {
498  yCError(IMUBOSCH_BNO055) << "Unable to set the page ID";
499  return false;
500  }
501 
503  // Set the device into operative mode
504 
505  if (i2c_smbus_write_byte_data(fd, REG_OP_MODE, NDOF_MODE) < 0)
506  {
507  yCError(IMUBOSCH_BNO055) << "Unable to set the Operative mode";
508  return false;
509  }
510 
512  }
513  else
514  {
515  unsigned char msg;
516  timeLastReport = yarp::os::SystemClock::nowSystem();
517 
518  msg = 0x00;
519  if(!sendAndVerifyCommandSer(REG_PAGE_ID, 1, &msg, "PAGE_ID") )
520  {
521  yCError(IMUBOSCH_BNO055) << "Set page id 0 failed";
522  return(false);
523  }
524 
526 
527  //Removed because useless
529  //
530  // Set power mode
531  //
533  // msg = 0x00;
534  // if(!sendAndVerifyCommand(REG_POWER_MODE, 1, &msg, "Set power mode") )
535  // {
536  // yCError(IMUBOSCH_BNO055) << "Set power mode failed";
537  // return(false);
538  // }
539  //
540  // yarp::os::SystemClock::delaySystem(SWITCHING_TIME);
541 
542 
544  //
545  // Set the device in config mode
546  //
548 
549  msg = CONFIG_MODE;
550  if(!sendAndVerifyCommandSer(REG_OP_MODE, 1, &msg, "Set config mode") )
551  {
552  yCError(IMUBOSCH_BNO055) << "Set config mode failed";
553  return(false);
554  }
555 
557 
558 
560  //
561  // Set external clock
562  //
564 
565  msg = TRIG_EXT_CLK_SEL;
566  if(!sendAndVerifyCommandSer(REG_SYS_TRIGGER, 1, &msg, "Set external clock") )
567  {
568  yCError(IMUBOSCH_BNO055) << "Set external clock failed";
569  return(false);
570  }
572 
574  //
575  // Perform any required configuration
576  //
578 
579 
580 
582 
584  //
585  // Set the device into operative mode
586  //
588 
589  msg = NDOF_MODE;
590  if(!sendAndVerifyCommandSer(REG_OP_MODE, 1, &msg, "Set config NDOF_MODE") )
591  {
592  yCError(IMUBOSCH_BNO055) << "Set config NDOF_MODE failed";
593  return false;
594  }
595 
597  }
598 
599  // Do a first read procedure to verify everything is fine.
600  // In case the device fails to read, stop it and quit
601  for(int i=0; i<10; i++)
602  {
603  // read data from IMU
604  run();
605  if(dataIsValid)
606  break;
607  else
609  }
610 
611  if(!dataIsValid)
612  {
613  yCError(IMUBOSCH_BNO055) << "First read from the device failed, check everything is fine and retry";
614  return false;
615  }
616 
617  return true;
618 }
619 
621 {
622  m_timeStamp = yarp::os::SystemClock::nowSystem();
623 
624  int16_t raw_data[16];
625 
626  // In order to avoid zeros when a single read from a sensor is missing,
627  // initialize the new measure to be equal to the previous one
628  data_tmp = data;
629 
630 
631  if (!(this->*readFunc)(REG_ACC_DATA, 32, response, "Read all"))
632  {
633  yCError(IMUBOSCH_BNO055) << "Failed to read all the data";
634  errs++;
635  dataIsValid = false;
636  return;
637  }
638  else
639  {
640  // Correctly construct int16 data
641  for(int i=0; i<16; i++)
642  {
643  raw_data[i] = response[responseOffset+1+i*2] << 8 | response[responseOffset+i*2];
644  }
645 
646  // Get quaternion
647  quaternion_tmp = quaternion;
648  quaternion_tmp.w() = ((double)raw_data[12]) / (2 << 13);
649  quaternion_tmp.x() = ((double)raw_data[13]) / (2 << 13);
650  quaternion_tmp.y() = ((double)raw_data[14]) / (2 << 13);
651  quaternion_tmp.z() = ((double)raw_data[15]) / (2 << 13);
652 
653  // Convert to RPY angles
654  RPY_angle.resize(3);
655 
656  // Check quaternion values are meaningful. The aim of this check is simply
657  // to verify values are not garbage.
658  // Ideally the correct check is that quaternion.abs ~= 1, but to avoid
659  // calling a sqrt every cicle only for a rough estimate, the check here
660  // is that the self product is nearly 1
661  double sum_squared = quaternion_tmp.w() * quaternion_tmp.w() +
662  quaternion_tmp.x() * quaternion_tmp.x() +
663  quaternion_tmp.y() * quaternion_tmp.y() +
664  quaternion_tmp.z() * quaternion_tmp.z();
665 
666  if( (sum_squared < 0.9) || (sum_squared > 1.2) )
667  {
668  dataIsValid = false;
669  return;
670  }
671 
672  dataIsValid = true;
673  RPY_angle = yarp::math::dcm2rpy(quaternion.toRotationMatrix4x4());
674  data_tmp[0] = RPY_angle[0] * 180 / M_PI;
675  data_tmp[1] = RPY_angle[1] * 180 / M_PI;
676  data_tmp[2] = RPY_angle[2] * 180 / M_PI;
677 
678  // Fill in accel values
679  data_tmp[3] = (double)raw_data[0] / 100.0;
680  data_tmp[4] = (double)raw_data[1] / 100.0;
681  data_tmp[5] = (double)raw_data[2] / 100.0;
682 
683 
684  // Fill in Gyro values
685  data_tmp[6] = (double)raw_data[6] / 16.0;
686  data_tmp[7] = (double)raw_data[7] / 16.0;
687  data_tmp[8] = (double)raw_data[8] / 16.0;
688 
689  // Fill in Magnetometer values
690  data_tmp[9] = (double)raw_data[3] / 16.0;
691  data_tmp[10] = (double)raw_data[4] / 16.0;
692  data_tmp[11] = (double)raw_data[5] / 16.0;
693  }
694 
695  // Protect only this section in order to avoid slow race conditions when gathering this data
696  {
697  std::lock_guard<std::mutex> guard(mutex);
698  data = data_tmp;
699  quaternion = quaternion_tmp;
700  }
701 
702  if (m_timeStamp > timeLastReport + TIME_REPORT_INTERVAL) {
703  // if almost 1 errors occourred in last interval, then print report
704  if(errs != 0)
705  {
706  yCDebug(IMUBOSCH_BNO055, "Periodic error report of last %d sec:", TIME_REPORT_INTERVAL);
707  yCDebug(IMUBOSCH_BNO055, "\t errors while reading data: %d", errs);
708  }
709 
710  errs = 0;
711  timeLastReport=m_timeStamp;
712  }
713 }
714 
716 {
717  std::lock_guard<std::mutex> guard(mutex);
718  out.resize(nChannels);
719  out.zero();
720 
721  out = data;
722  if(nChannels == 16)
723  {
724  out[12] = quaternion.w();
725  out[13] = quaternion.x();
726  out[14] = quaternion.y();
727  out[15] = quaternion.z();
728  }
729 
730  return dataIsValid;
731 }
732 
734 {
735  *nc = nChannels;
736  return true;
737 }
738 
739 bool BoschIMU::calibrate(int ch, double v)
740 {
741  // TODO: start a calib procedure in which the calib status register is read
742  // until all sensors are calibrated (0xFFFF). Then the offsets are saved
743  // into memory for the next run.
744  // This procedure should be abortable by CTRL+C
745  return false;
746 }
747 
748 
749 yarp::dev::MAS_status BoschIMU::genericGetStatus(size_t sens_index) const
750 {
751  if (sens_index != 0)
752  {
753  yCError(IMUBOSCH_BNO055) << "sens_index must be equal to 0, since there is only one sensor in consideration";
755  }
756 
758 }
759 
760 bool BoschIMU::genericGetSensorName(size_t sens_index, string& name) const
761 {
762  if (sens_index != 0)
763  {
764  yCError(IMUBOSCH_BNO055) << "sens_index must be equal to 0, since there is only one sensor in consideration";
765  return false;
766  }
767 
768  name = m_sensorName;
769  return true;
770 }
771 
772 bool BoschIMU::genericGetFrameName(size_t sens_index, string& frameName) const
773 {
774  if (sens_index != 0)
775  {
776  yCError(IMUBOSCH_BNO055) << "sens_index must be equal to 0, since there is only one sensor in consideration";
777  return false;
778  }
779 
780  frameName = m_frameName;
781  return true;
782 
783 }
784 
786 {
787  return 1;
788 }
789 
790 
792 {
793  return genericGetStatus(sens_index);
794 }
795 
796 bool BoschIMU::getThreeAxisLinearAccelerometerName(size_t sens_index, string& name) const
797 {
798  return genericGetSensorName(sens_index, name);
799 }
800 
801 bool BoschIMU::getThreeAxisLinearAccelerometerFrameName(size_t sens_index, string& frameName) const
802 {
803  return genericGetFrameName(sens_index, frameName);
804 }
805 
806 bool BoschIMU::getThreeAxisLinearAccelerometerMeasure(size_t sens_index, yarp::sig::Vector& out, double& timestamp) const
807 {
808  if (sens_index != 0)
809  {
810  yCError(IMUBOSCH_BNO055) << "sens_index must be equal to 0, since there is only one sensor in consideration";
811  return false;
812  }
813 
814  out.resize(3);
815  std::lock_guard<std::mutex> guard(mutex);
816  out[0] = data[3];
817  out[1] = data[4];
818  out[2] = data[5];
819 
820  timestamp = m_timeStamp;
821  return true;
822 }
823 
824 
826 {
827  return 1;
828 }
829 
830 
832 {
833  return genericGetStatus(sens_index);
834 }
835 
836 bool BoschIMU::getThreeAxisGyroscopeName(size_t sens_index, string& name) const
837 {
838  return genericGetSensorName(sens_index, name);
839 }
840 
841 bool BoschIMU::getThreeAxisGyroscopeFrameName(size_t sens_index, string& frameName) const
842 {
843  return genericGetFrameName(sens_index, frameName);
844 }
845 
846 bool BoschIMU::getThreeAxisGyroscopeMeasure(size_t sens_index, yarp::sig::Vector& out, double& timestamp) const
847 {
848  if (sens_index != 0)
849  {
850  yCError(IMUBOSCH_BNO055) << "sens_index must be equal to 0, since there is only one sensor in consideration";
851  return false;
852  }
853 
854  out.resize(3);
855  std::lock_guard<std::mutex> guard(mutex);
856  out[0] = data[6];
857  out[1] = data[7];
858  out[2] = data[8];
859 
860  timestamp = m_timeStamp;
861  return true;
862 }
863 
865 {
866  return 1;
867 }
868 
870 {
871  return genericGetStatus(sens_index);
872 }
873 
874 bool BoschIMU::getOrientationSensorName(size_t sens_index, string& name) const
875 {
876  return genericGetSensorName(sens_index, name);
877 }
878 
879 bool BoschIMU::getOrientationSensorFrameName(size_t sens_index, string& frameName) const
880 {
881  return genericGetFrameName(sens_index, frameName);
882 }
883 
884 bool BoschIMU::getOrientationSensorMeasureAsRollPitchYaw(size_t sens_index, yarp::sig::Vector& rpy, double& timestamp) const
885 {
886  if (sens_index != 0)
887  {
888  yCError(IMUBOSCH_BNO055) << "sens_index must be equal to 0, since there is only one sensor in consideration";
889  return false;
890  }
891 
892  rpy.resize(3);
893  std::lock_guard<std::mutex> guard(mutex);
894  rpy[0] = data[0];
895  rpy[1] = data[1];
896  rpy[2] = data[2];
897 
898  timestamp = m_timeStamp;
899  return true;
900 }
901 
903 {
904  return 1;
905 }
906 
908 {
909  return genericGetStatus(sens_index);
910 }
911 
912 bool BoschIMU::getThreeAxisMagnetometerName(size_t sens_index, string& name) const
913 {
914  return genericGetSensorName(sens_index, name);
915 }
916 
917 bool BoschIMU::getThreeAxisMagnetometerFrameName(size_t sens_index, string& frameName) const
918 {
919  return genericGetFrameName(sens_index, frameName);
920 }
921 
922 bool BoschIMU::getThreeAxisMagnetometerMeasure(size_t sens_index, yarp::sig::Vector& out, double& timestamp) const
923 {
924  if (sens_index != 0)
925  {
926  yCError(IMUBOSCH_BNO055) << "sens_index must be equal to 0, since there is only one sensor in consideration";
927  return false;
928  }
929 
930  out.resize(3);
931  std::lock_guard<std::mutex> guard(mutex);
932  // The unit measure of Bosch BNO055 is uT
933  out[0] = data[9] / 1000000;
934  out[1] = data[10]/ 1000000;
935  out[2] = data[11]/ 1000000;
936 
937  timestamp = m_timeStamp;
938  return true;
939 }
940 
941 
943 {
944  yCTrace(IMUBOSCH_BNO055, "Thread released");
945  //TBD write more meaningful report
946 // for(unsigned int i=0; i<errorCounter.size(); i++)
947 // yCTrace(IMUBOSCH_BNO055, "Error type %d, counter is %d", i, (int)errorCounter[i]);
948 // yCTrace(IMUBOSCH_BNO055, "On overall read operations of %ld", totMessagesRead);
949  ::close(fd);
950 }
LogStream.h
CONFIG_MODE
#define CONFIG_MODE
Definition: imuBosch_BNO055.h:104
BoschIMU::getNrOfOrientationSensors
size_t getNrOfOrientationSensors() const override
Get the number of orientation sensors in the device.
Definition: imuBosch_BNO055.cpp:864
BoschIMU::getOrientationSensorStatus
yarp::dev::MAS_status getOrientationSensorStatus(size_t sens_index) const override
Get the status of orientation sensor.
Definition: imuBosch_BNO055.cpp:869
BoschIMU::sendWriteCommandSer
bool sendWriteCommandSer(unsigned char register_add, int len, unsigned char *cmd, std::string comment="")
Definition: imuBosch_BNO055.cpp:340
BoschIMU::getNrOfThreeAxisLinearAccelerometers
size_t getNrOfThreeAxisLinearAccelerometers() const override
Get the number of three axis linear accelerometers in the device.
Definition: imuBosch_BNO055.cpp:785
yarp::sig::VectorOf::resize
void resize(size_t size) override
Resize the vector.
Definition: Vector.h:254
BoschIMU::close
bool close() override
Close the device.
Definition: imuBosch_BNO055.cpp:215
BoschIMU::getChannels
bool getChannels(int *nc) override
Get the number of channels of the sensor.
Definition: imuBosch_BNO055.cpp:733
yarp::os::Searchable
A base class for nested structures that can be searched.
Definition: Searchable.h:69
READ_CMD
#define READ_CMD
Definition: imuBosch_BNO055.h:69
yarp::sig::file::read
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:827
ERROR_HEAD
#define ERROR_HEAD
Definition: imuBosch_BNO055.h:73
M_PI
#define M_PI
Definition: fakeLocalizerDev.cpp:44
yCWarning
#define yCWarning(component,...)
Definition: LogComponent.h:146
yarp::math::dcm2rpy
yarp::sig::Vector dcm2rpy(const yarp::sig::Matrix &R)
Converts a dcm (direction cosine matrix) rotation matrix to roll-pitch-yaw angles (defined in Math....
Definition: math.cpp:780
yarp::os::Searchable::toString
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
BoschIMU::threadInit
bool threadInit() override
Initialize process with desired device configurations.
Definition: imuBosch_BNO055.cpp:456
YARP_LOG_COMPONENT
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
BoschIMU::getThreeAxisMagnetometerFrameName
bool getThreeAxisMagnetometerFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame in which three axis magnetometer measurements are expressed.
Definition: imuBosch_BNO055.cpp:917
BoschIMU::calibrate
bool calibrate(int ch, double v) override
Calibrate the sensor, single channel.
Definition: imuBosch_BNO055.cpp:739
BoschIMU::getThreeAxisMagnetometerStatus
yarp::dev::MAS_status getThreeAxisMagnetometerStatus(size_t sens_index) const override
Get the status of three axis magnetometer.
Definition: imuBosch_BNO055.cpp:907
NDOF_MODE
#define NDOF_MODE
Definition: imuBosch_BNO055.h:108
ATTEMPTS_NUM_OF_SEND_CONFIG_CMD
#define ATTEMPTS_NUM_OF_SEND_CONFIG_CMD
Definition: imuBosch_BNO055.h:123
BoschIMU::read
bool read(yarp::sig::Vector &out) override
Read a vector from the sensor.
Definition: imuBosch_BNO055.cpp:715
BoschIMU::readSysError
void readSysError()
Definition: imuBosch_BNO055.cpp:412
REPLY_HEAD
#define REPLY_HEAD
Definition: imuBosch_BNO055.h:72
WRITE_CMD
#define WRITE_CMD
Definition: imuBosch_BNO055.h:68
ret
bool ret
Definition: ImplementAxisInfo.cpp:72
BoschIMU::getThreeAxisLinearAccelerometerMeasure
bool getThreeAxisLinearAccelerometerMeasure(size_t sens_index, yarp::sig::Vector &out, double &timestamp) const override
Get three axis linear accelerometer measurements.
Definition: imuBosch_BNO055.cpp:806
REGISTER_NOT_READY
#define REGISTER_NOT_READY
Definition: imuBosch_BNO055.h:79
BoschIMU::getThreeAxisLinearAccelerometerStatus
yarp::dev::MAS_status getThreeAxisLinearAccelerometerStatus(size_t sens_index) const override
Get the status of three axis linear accelerometer.
Definition: imuBosch_BNO055.cpp:791
yarp::dev
An interface for the device drivers.
Definition: audioBufferSizeData.cpp:17
BoschIMU::getThreeAxisGyroscopeMeasure
bool getThreeAxisGyroscopeMeasure(size_t sens_index, yarp::sig::Vector &out, double &timestamp) const override
Get three axis gyroscope measurements.
Definition: imuBosch_BNO055.cpp:846
yarp::os::SystemClock::nowSystem
static double nowSystem()
Definition: SystemClock.cpp:37
BoschIMU::sendReadCommandI2c
bool sendReadCommandI2c(unsigned char register_add, int len, unsigned char *buf, std::string comment="")
Definition: imuBosch_BNO055.cpp:446
REG_PAGE_ID
#define REG_PAGE_ID
Definition: imuBosch_BNO055.h:86
BoschIMU::~BoschIMU
~BoschIMU()
BoschIMU
imuBosch_BNO055: This device will connect to the proper analogServer and read the data broadcasted ma...
Definition: imuBosch_BNO055.h:157
yarp::sig::VectorOf< double >
Log.h
BoschIMU::getThreeAxisLinearAccelerometerFrameName
bool getThreeAxisLinearAccelerometerFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame in which three axis linear accelerometer measurements are expressed.
Definition: imuBosch_BNO055.cpp:801
RESP_HEADER_SIZE
#define RESP_HEADER_SIZE
Definition: imuBosch_BNO055.h:118
yarp::os::Value::isString
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:159
BoschIMU::checkWriteResponse
bool checkWriteResponse(unsigned char *response)
Definition: imuBosch_BNO055.cpp:252
BNO055_ID
#define BNO055_ID
Definition: imuBosch_BNO055.h:116
REG_OP_MODE
#define REG_OP_MODE
Definition: imuBosch_BNO055.h:99
BoschIMU::getThreeAxisLinearAccelerometerName
bool getThreeAxisLinearAccelerometerName(size_t sens_index, std::string &name) const override
Get the name of three axis linear accelerometer.
Definition: imuBosch_BNO055.cpp:796
REG_SYS_TRIGGER
#define REG_SYS_TRIGGER
Definition: imuBosch_BNO055.h:101
Math.h
yarp::os::SystemClock::delaySystem
static void delaySystem(double seconds)
Definition: SystemClock.cpp:32
REG_SYS_STATUS
#define REG_SYS_STATUS
Definition: imuBosch_BNO055.h:96
BoschIMU::getThreeAxisGyroscopeName
bool getThreeAxisGyroscopeName(size_t sens_index, std::string &name) const override
Get the name of three axis gyroscope.
Definition: imuBosch_BNO055.cpp:836
yarp::os::Value::asString
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
yarp::os::Searchable::check
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
buffer
Definition: V4L_camera.h:75
yarp::sig::VectorOf::zero
void zero()
Zero the elements of the vector.
Definition: Vector.h:377
imuBosch_BNO055.h
WRITE_SUCC
#define WRITE_SUCC
Definition: imuBosch_BNO055.h:74
yarp::os::Searchable::find
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
BoschIMU::sendReadCommandSer
bool sendReadCommandSer(unsigned char register_add, int len, unsigned char *buf, std::string comment="")
Definition: imuBosch_BNO055.cpp:280
BoschIMU::checkReadResponse
bool checkReadResponse(unsigned char *response)
Definition: imuBosch_BNO055.cpp:223
TIME_REPORT_INTERVAL
#define TIME_REPORT_INTERVAL
Definition: imuBosch_BNO055.h:121
BoschIMU::printBuffer
void printBuffer(unsigned char *buffer, int length)
Definition: imuBosch_BNO055.cpp:405
REG_CHIP_ID
#define REG_CHIP_ID
Definition: imuBosch_BNO055.h:83
yarp::os::PeriodicThread
An abstraction for a periodic thread.
Definition: PeriodicThread.h:25
BoschIMU::open
bool open(yarp::os::Searchable &config) override
Open the device and set up parameters/communication.
Definition: imuBosch_BNO055.cpp:87
LogComponent.h
REG_ACC_DATA
#define REG_ACC_DATA
Definition: imuBosch_BNO055.h:88
SWITCHING_TIME
#define SWITCHING_TIME
Definition: imuBosch_BNO055.h:120
START_BYTE
#define START_BYTE
Definition: imuBosch_BNO055.h:67
yCError
#define yCError(component,...)
Definition: LogComponent.h:157
BoschIMU::readBytes
int readBytes(unsigned char *buffer, int bytes)
Definition: imuBosch_BNO055.cpp:380
yarp::os
An interface to the operating system, including Port based communication.
Definition: AbstractCarrier.h:17
yCDebug
#define yCDebug(component,...)
Definition: LogComponent.h:112
BoschIMU::sendAndVerifyCommandSer
bool sendAndVerifyCommandSer(unsigned char register_add, int len, unsigned char *cmd, std::string comment)
Definition: imuBosch_BNO055.cpp:433
BoschIMU::getOrientationSensorMeasureAsRollPitchYaw
bool getOrientationSensorMeasureAsRollPitchYaw(size_t sens_index, yarp::sig::Vector &rpy, double &timestamp) const override
Get orientation sensor measurements.
Definition: imuBosch_BNO055.cpp:884
BoschIMU::getThreeAxisGyroscopeStatus
yarp::dev::MAS_status getThreeAxisGyroscopeStatus(size_t sens_index) const override
Get the status of three axis gyroscope.
Definition: imuBosch_BNO055.cpp:831
BoschIMU::getOrientationSensorFrameName
bool getOrientationSensorFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame in which orientation sensor measurements are expressed.
Definition: imuBosch_BNO055.cpp:879
yarp::dev::MAS_status
MAS_status
Status of a given analog sensor exposed by a multiple analog sensors interface.
Definition: MultipleAnalogSensorsInterfaces.h:37
REG_SYS_ERR
#define REG_SYS_ERR
Definition: imuBosch_BNO055.h:97
BoschIMU::getThreeAxisMagnetometerName
bool getThreeAxisMagnetometerName(size_t sens_index, std::string &name) const override
Get the name of three axis magnetometer.
Definition: imuBosch_BNO055.cpp:912
yarp::dev::MAS_ERROR
@ MAS_ERROR
The sensor is in generic error state.
Definition: MultipleAnalogSensorsInterfaces.h:39
Time.h
yCTrace
#define yCTrace(component,...)
Definition: LogComponent.h:88
BoschIMU::getThreeAxisGyroscopeFrameName
bool getThreeAxisGyroscopeFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame in which three axis gyroscope measurements are expressed.
Definition: imuBosch_BNO055.cpp:841
BoschIMU::getNrOfThreeAxisMagnetometers
size_t getNrOfThreeAxisMagnetometers() const override
Get the number of three axis magnetometers in the device.
Definition: imuBosch_BNO055.cpp:902
yarp::os::Value::toString
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:359
BoschIMU::getThreeAxisMagnetometerMeasure
bool getThreeAxisMagnetometerMeasure(size_t sens_index, yarp::sig::Vector &out, double &timestamp) const override
Get three axis magnetometer measurements.
Definition: imuBosch_BNO055.cpp:922
yarp::sig::file::write
bool write(const ImageOf< PixelRgb > &src, const std::string &dest, image_fileformat format=FORMAT_PPM)
Definition: ImageFile.cpp:971
yarp::os::Value
A single value (typically within a Bottle).
Definition: Value.h:47
BoschIMU::run
void run() override
Update loop where measurements are read from the device.
Definition: imuBosch_BNO055.cpp:620
BoschIMU::getNrOfThreeAxisGyroscopes
size_t getNrOfThreeAxisGyroscopes() const override
Get the number of three axis gyroscopes in the device.
Definition: imuBosch_BNO055.cpp:825
yarp::os::Time::delay
void delay(double seconds)
Wait for a certain number of seconds.
Definition: Time.cpp:114
TRIG_EXT_CLK_SEL
#define TRIG_EXT_CLK_SEL
Definition: imuBosch_BNO055.h:111
yarp::dev::MAS_OK
@ MAS_OK
The sensor is working correctly.
Definition: MultipleAnalogSensorsInterfaces.h:38
BoschIMU::threadRelease
void threadRelease() override
Terminate communication with the device and release the thread.
Definition: imuBosch_BNO055.cpp:942
BoschIMU::getOrientationSensorName
bool getOrientationSensorName(size_t sens_index, std::string &name) const override
Get the name of orientation sensor.
Definition: imuBosch_BNO055.cpp:874
byte
unsigned char byte
Definition: laserFromDepth.h:38
BoschIMU::dropGarbage
void dropGarbage()
Definition: imuBosch_BNO055.cpp:395