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