9#include <iCubCanProtocol.h>
10#include <yarp/os/Time.h>
11#include <yarp/os/Log.h>
12#include <yarp/os/LogStream.h>
15#include <yarp/os/LogStream.h>
21#define SPECIAL_TRIANGLE_CFG_MAX_NUM 20
22#define TRIANGLE_MAX_NUM_IN_BOARD 16
28using yarp::os::Bottle;
29using yarp::os::Property;
31using yarp::dev::CanMessage;
36 _isDiagnosticPresent(false)
44 fprintf(stderr,
"%s\n", config.toString().c_str());
49 correct &= config.check(
"canbusDevice");
50 correct &= config.check(
"canDeviceNum");
51 correct &= config.check(
"skinCanIds");
52 correct &= config.check(
"period");
56 yError()<<
"Insufficient parameters to CanBusSkin.";
61 _canBusNum = config.find(
"canDeviceNum").asInt32();
63 sprintf(name,
"canSkin on bus %d", _canBusNum);
66 int period=config.find(
"period").asInt32();
67 setPeriod((
double)period/1000.0);
69 netID = config.find(
"canDeviceNum").asInt32();
71 Bottle ids=config.findGroup(
"skinCanIds").tail();
75 yWarning()<<
"CanBusSkin id list contains more than one entry -> devices will be merged. ";
78 for (
int i=0; i<ids.size(); i++)
81 int id = ids.get(i).asInt32();
84 yDebug<<
"Id reading from: " << id;
94 prop.put(
"device", config.find(
"canbusDevice").asString().c_str());
95 prop.put(
"physDevice", config.find(
"physDevice").asString().c_str());
96 prop.put(
"canTxTimeout", 500);
97 prop.put(
"canRxTimeout", 500);
98 prop.put(
"canDeviceNum", config.find(
"canDeviceNum").asInt32());
99 prop.put(
"canMyAddress", 0);
109 yError()<<
"Error opening PolyDriver check parameters";
117 yError()<<
"Error opening /ecan device not available";
140 yInfo() <<
"Skin on can bus " << _canBusNum <<
" uses NEW configuration version!!!";
141 ret = readNewConfiguration(config);
146 yWarning() <<
"Skin on can bus " << _canBusNum <<
" uses old configuration version!!!";
147 ret = readOldConfiguration(config);
152 yError() <<
"Error reading config";
163 uint8_t can_msg_class = 0;
166 can_msg_class = ICUBCANPROTO_CLASS_PERIODIC_SKIN;
170 can_msg_class = ICUBCANPROTO_CLASS_PERIODIC_ANALOGSENSOR;
172 for (
unsigned int i=0; i<
cardId.size(); i++)
173 for (
unsigned int id=0;
id<16; ++id)
182 portSkinDiagnosticsOut.open(
"/diagnostics/skin/errors:o");
186 yarp::os::Time::delay(0.01);
190 for(
size_t i=0; i<
cardId.size(); i++)
192 if(! sendCANMessage(
cardId[i], ICUBCANPROTO_POL_AS_CMD__SET_TXMODE, &txmode))
197 PeriodicThread::start();
201bool CanBusSkin::sendCANMessage(uint8_t destAddr, uint8_t command,
void *
data)
204 unsigned int msgSent = 0;
207 id= ((ICUBCANPROTO_CLASS_POLLING_ANALOGSENSOR << 8 ) | (destAddr & 0x0f));
211 msg.getData()[0] = command;
215 case ICUBCANPROTO_POL_SK_CMD__SET_BRD_CFG:
218 msg.getData()[1] = 0;
219 msg.getData()[1] = brdCfg->
skinType & 0x0f;
220 msg.getData()[2] = brdCfg->
period;
221 msg.getData()[3] = brdCfg->
noLoad;
225 case ICUBCANPROTO_POL_SK_CMD__SET_TRIANG_CFG:
230 msg.getData()[3] = trCfg->
cfg.
shift;
231 msg.getData()[4] = 0;
234 msg.getData()[4] = 1;
237 msg.getData()[6] = (trCfg->
cfg.
cdcOffset & 0xff00) >> 8;
240 case ICUBCANPROTO_POL_AS_CMD__SET_TXMODE:
242 uint8_t *txmode = (uint8_t *)
data;
245 msg.getData()[1] = 0;
249 msg.getData()[1] = 1;
263 yWarning() <<
"skin on can bus " << _canBusNum <<
":try to send a unknown message(command id=" <<command <<
")";
269 yError() <<
"skin on can bus " << _canBusNum <<
": Could not write to the CAN interface.";
280bool CanBusSkin::readNewSpecialConfiguration(yarp::os::Searchable& config)
283 unsigned int numofcfg;
293 for(j=0; j<numofcfg; j++)
296 if(_canBusNum != boardCfgList[j].patch)
298 yError() <<
"Skin on can bus " << _canBusNum <<
"configured SpecialBoardConfig on patch with a different id from my can bus " << _canBusNum <<
"patch=" <<boardCfgList[j].
patch ;
304 for(
int a=boardCfgList[j].boardAddrStart; a<=boardCfgList[j].
boardAddrEnd; a++)
306 for(boardIdx=0; boardIdx<
cardId.size(); boardIdx++)
311 if(boardIdx>=
cardId.size())
313 yError() <<
"Skin on can bus %d" << _canBusNum <<
": card with address " << a <<
"is not present ";
322 for(
int listIdx=boardCfgList[j].boardAddrStart; listIdx<= boardCfgList[j].
boardAddrEnd; listIdx++)
324 if(!sendCANMessage(listIdx, ICUBCANPROTO_POL_SK_CMD__SET_BRD_CFG, (
void*)&boardCfgList[j].cfg))
329 for (
unsigned int triangleId = 0; triangleId < 16; triangleId++)
331 unsigned int index = 16*12*boardIdx + triangleId*12;
334 for(
unsigned int k = 0; k < 12; k++)
337 if((index+k) >=
data.size())
338 yError() <<
"readNewSpecialConfiguration: index too big";
345 yarp::os::Time::delay(0.01);
354 for(j=0; j<numofcfg; j++)
359 if(_canBusNum != triangleCfg[j].patch)
361 yError() <<
"Skin on can bus " << _canBusNum <<
"configured SpecialTriangleConfig on patch with a different id from my can bus" << _canBusNum <<
"patch=" <<triangleCfg[j].
patch ;
365 for(
size_t i=0; i<
cardId.size(); i++)
367 if(
cardId[i]==triangleCfg[j].boardAddr)
372 yError() <<
"Skin on can bus %d" << _canBusNum <<
": card with address " << triangleCfg[j].
boardAddr <<
"is not present ";
382 if(!sendCANMessage(triangleCfg[j].boardAddr, ICUBCANPROTO_POL_SK_CMD__SET_TRIANG_CFG, (
void*)&triangleCfg[j]))
389bool CanBusSkin::readNewConfiguration(yarp::os::Searchable& config)
397 for (
size_t board_idx = 0; board_idx <
cardId.size(); board_idx++)
399 for (
unsigned int triangleId = 0; triangleId < 16; triangleId++)
401 int index = 16*12*board_idx + triangleId*12;
404 for(
unsigned int k = 0; k < 12; k++)
407 if((index+k) >=
data.size())
408 yError() <<
"readNewConfiguration: index too big";
416 for(
size_t i=0; i<
cardId.size(); i++)
418 if(!sendCANMessage(
cardId[i], ICUBCANPROTO_POL_SK_CMD__SET_BRD_CFG, (
void*)&_brdCfg))
427 spTrCfg.
cfg = _triangCfg;
432 for(
size_t i=0; i<
cardId.size(); i++)
435 if(!sendCANMessage(
cardId[i], ICUBCANPROTO_POL_SK_CMD__SET_TRIANG_CFG, (
void*)&spTrCfg))
439 yarp::os::Time::delay(0.5);
442 if(!readNewSpecialConfiguration(config))
449bool CanBusSkin::readOldConfiguration(yarp::os::Searchable& config)
455 msg4C_Timer = config.findGroup(
"4C_Timer").tail();
456 msg4C_CDCOffsetL = config.findGroup(
"4C_CDCOffsetL").tail();
457 msg4C_CDCOffsetH = config.findGroup(
"4C_CDCOffsetH").tail();
458 msg4C_TimeL = config.findGroup(
"4C_TimeL").tail();
459 msg4C_TimeH = config.findGroup(
"4C_TimeH").tail();
461 msg4E_Shift = config.findGroup(
"4E_Shift").tail();
462 msg4E_Shift3_1 = config.findGroup(
"4E_Shift3_1").tail();
463 msg4E_NoLoad = config.findGroup(
"4E_NoLoad").tail();
464 msg4E_Param = config.findGroup(
"4E_Param").tail();
465 msg4E_EnaL = config.findGroup(
"4E_EnaL").tail();
466 msg4E_EnaH = config.findGroup(
"4E_EnaH").tail();
471 int numofcards =
cardId.size();
474 checkParameterListLength(
"4C_Timer", msg4C_Timer, numofcards, Value(0x01));
475 checkParameterListLength(
"4C_CDCOffsetL", msg4C_CDCOffsetL, numofcards, Value(0x00));
476 checkParameterListLength(
"4C_CDCOffsetH", msg4C_CDCOffsetH, numofcards, Value(0x20));
477 checkParameterListLength(
"4C_TimeL", msg4C_TimeL, numofcards, Value(0x00));
478 checkParameterListLength(
"4C_TimeH", msg4C_TimeH, numofcards, Value(0x00));
480 checkParameterListLength(
"4E_Shift", msg4E_Shift, numofcards, Value(0x02));
481 checkParameterListLength(
"4E_Shift3_1", msg4E_Shift3_1, numofcards, Value(0x22));
482 checkParameterListLength(
"4E_NoLoad", msg4E_NoLoad, numofcards, Value(0xF0));
483 checkParameterListLength(
"4E_Param", msg4E_Param, numofcards, Value(0x00));
484 checkParameterListLength(
"4E_EnaL", msg4E_EnaL, numofcards, Value(0xFF));
485 checkParameterListLength(
"4E_EnaH", msg4E_EnaH, numofcards, Value(0xFF));
496 int baseLine = msg4E_NoLoad.get(
idx).asInt32();
498 for (
unsigned int triangleId = 0; triangleId < 16; triangleId++)
500 unsigned int index = 16*12*board_idx + triangleId*12;
503 for(
unsigned int k = 0; k < 12; k++)
506 if((index+k) >=
data.size())
507 yError() <<
"readOldConfiguration: index too big";
508 data[index + k] = baseLine;
513 if(sendCANMessage4C())
515 return sendCANMessage4E();
529 for(
size_t i=0; i<
cardId.size(); i++)
531 sendCANMessage(
cardId[i], ICUBCANPROTO_POL_AS_CMD__SET_TXMODE, &txmode);
535 PeriodicThread::stop();
547 lock_guard<mutex> lck(
mtx);
549 return yarp::dev::IAnalogSensor::AS_OK;
554 return yarp::dev::IAnalogSensor::AS_OK;;
596 lock_guard<mutex> lck(
mtx);
598 unsigned int canMessages = 0;
603 yError(
"CanBusSkin: CanRead failed");
608 errors.resize(canMessages);
610 for (
unsigned int i = 0; i < canMessages; i++) {
614 unsigned int msgid = msg.getId();
615 unsigned int id = (msgid & 0x00F0) >> 4;
616 unsigned int sensorId = (msgid & 0x000F);
617 unsigned int msgType = (int) msg.getData()[0];
618 int len = msg.getLen();
621 cout <<
"DEBUG: CanBusSkin: Board ID (" <<
id <<
"): Sensor ID (" << sensorId <<
"): "
622 <<
"Message type (" << std::uppercase << std::showbase << std::hex << (int) msg.getData()[0] <<
") "
623 << std::nouppercase << std::noshowbase << std::dec <<
" Length (" << len <<
"): ";
624 cout <<
"Content: " << std::uppercase << std::showbase << std::hex;
625 for (
int k = 0; k < len; ++k) {
626 cout << (int) msg.getData()[k] <<
" ";
628 cout <<
"\n" << std::nouppercase << std::noshowbase << std::dec;
631 for (
size_t j = 0; j <
cardId.size(); j++) {
633 int index = 16*12*j + sensorId*12;
635 if (msgType == 0x40) {
637 for(
int k = 0; k < 7; k++) {
638 data[index + k] = msg.getData()[k + 1];
640 }
else if (msgType == 0xC0) {
642 for(
int k = 0; k < 5; k++) {
643 data[index + k + 7] = msg.getData()[k + 1];
651 _isDiagnosticPresent =
true;
654 short head = msg.getData()[6];
655 short tail = msg.getData()[7];
656 int fullMsg = (head << 8) | (tail & 0xFF);
661 errors[i].sensor = sensorId;
662 errors[i].error = fullMsg;
666 yError() <<
"canBusSkin error code: " <<
667 "canDeviceNum: " <<
errors[i].net <<
668 "board: " <<
errors[i].board <<
669 "sensor: " <<
errors[i].sensor <<
672 yarp::sig::Vector &
out = portSkinDiagnosticsOut.prepare();
680 portSkinDiagnosticsOut.write(
true);
686 _isDiagnosticPresent =
false;
703 yDebug<<
"CanBusSkin Thread releasing...";
711bool CanBusSkin::diagnoseSkin(
void) {
713 using yarp::sig::Vector;
716 for (
size_t i = 0; i <
errors.size(); ++i)
718 Vector &
out = portSkinDiagnosticsOut.prepare();
726 portSkinDiagnosticsOut.write(
true);
735void CanBusSkin::checkParameterListLength(
const string &i_paramName, Bottle &i_paramList,
const int &i_length,
const Value &i_defaultValue) {
736 if ((i_paramList.isNull()) || (i_paramList.size() != i_length)) {
737 yWarning() <<
"CanBusSkin: The number of " << i_paramName <<
" parameters provided is different than the number of CAN IDs for this BUS. Check your parameters.";
738 yWarning() <<
"CanBusSkin: Using default values for " << i_paramName <<
" parameters.";
741 for (i= i_paramList.size() ; i <= (
unsigned int) i_length; ++i) {
742 i_paramList.add(i_defaultValue);
751bool CanBusSkin::sendCANMessage4C(
void) {
752 for (
size_t i = 0; i <
cardId.size(); ++i) {
754 printf(
"CanBusSkin: Thread initialising board ID: %d. \n",
cardId[i]);
755 printf(
"CanBusSkin: Sending 0x4C message to skin boards. \n");
758 unsigned int canMessages=0;
759 unsigned id = 0x200 +
cardId[i];
763 msg4c.getData()[0] = 0x4C;
764 msg4c.getData()[1] = 0x01;
765 msg4c.getData()[2] = 0x01;
766 msg4c.getData()[3] = msg4C_Timer.get(i).asInt32();
767 msg4c.getData()[4] = msg4C_CDCOffsetL.get(i).asInt32();
768 msg4c.getData()[5] = msg4C_CDCOffsetH.get(i).asInt32();
769 msg4c.getData()[6] = msg4C_TimeL.get(i).asInt32();
770 msg4c.getData()[7] = msg4C_TimeH.get(i).asInt32();
774 yDebug <<
"CanBusSkin: Input parameters (msg 4C) are: " << std::hex << std::showbase
775 << (int) msg4c.getData()[0] <<
" " << (int) msg4c.getData()[1] <<
" " << (int) msg4c.getData()[2] <<
" "
776 << msg4C_Timer.get(i).asInt32() <<
" " << msg4C_CDCOffsetL.get(i).asInt32() <<
" " << msg4C_CDCOffsetH.get(i).asInt32() <<
" "
777 << msg4C_TimeL.get(i).asInt32() <<
" " << msg4C_TimeH.get(i).asInt32() << std::dec << std::noshowbase
779 yDebug <<
"CanBusSkin: Output parameters (msg 4C) are: " << std::hex << std::showbase
780 << (int) msg4c.getData()[0] <<
" " << (int) msg4c.getData()[1] <<
" " << (int) msg4c.getData()[2] <<
" "
781 << (int) msg4c.getData()[3] <<
" " << (int) msg4c.getData()[4] <<
" " << (int) msg4c.getData()[5] <<
" "
782 << (int) msg4c.getData()[6] <<
" " << (int) msg4c.getData()[7]
787 yError() <<
"CanBusSkin: Could not write to the CAN interface. \n";
798bool CanBusSkin::sendCANMessage4E(
void) {
800 for (
size_t i = 0; i <
cardId.size(); ++i) {
803 printf(
"CanBusSkin: Thread initialising board ID: %d. \n",
cardId[i]);
804 printf(
"CanBusSkin: Sending 0x4E message to skin boards. \n");
807 unsigned int canMessages = 0;
808 unsigned id = 0x200 +
cardId[i];
812 msg4e.getData()[0] = 0x4E;
813 msg4e.getData()[1] = msg4E_Shift.get(i).asInt32();
814 msg4e.getData()[2] = msg4E_Shift3_1.get(i).asInt32();
815 msg4e.getData()[3] = msg4E_NoLoad.get(i).asInt32();
816 msg4e.getData()[4] = msg4E_Param.get(i).asInt32();
817 msg4e.getData()[5] = msg4E_EnaL.get(i).asInt32();
818 msg4e.getData()[6] = msg4E_EnaH.get(i).asInt32();
819 msg4e.getData()[7] = 0x0A;
823 yDebug <<
"CanBusSkin: Input parameters (msg 4E) are: " << std::hex << std::showbase
824 << (int) msg4e.getData()[0] <<
" " << msg4E_Shift.get(i).asInt32() <<
" " << msg4E_Shift3_1.get(i).asInt32() <<
" "
825 << msg4E_NoLoad.get(i).asInt32() <<
" " << msg4E_Param.get(i).asInt32() <<
" " << msg4E_EnaL.get(i).asInt32() <<
" "
826 << msg4E_EnaH.get(i).asInt32() <<
" " << (int) msg4e.getData()[7] << std::dec << std::noshowbase
828 yDebug <<
"CanBusSkin: Output parameters (msg 4E) are: " << std::hex << std::showbase
829 << (int) msg4e.getData()[0] <<
" " << (int) msg4e.getData()[1] <<
" " << (int) msg4e.getData()[2] <<
" "
830 << (int) msg4e.getData()[3] <<
" " << (int) msg4e.getData()[4] <<
" " << (int) msg4e.getData()[5] <<
" "
831 << (int) msg4e.getData()[6] <<
" " << (int) msg4e.getData()[7] << std::dec << std::noshowbase
836 yError() <<
"CanBusSkin: Could not write to the CAN interface.";
849bool CanBusSkin::checkFirmwareVersion(
void)
851 bool firmware_version_ok =
true;
853 for (
size_t i = 0; i <
cardId.size(); ++i)
856 yDebug(
"CanBusSkin: check firmware version for board ID: %d. \n",
cardId[i]);
859 unsigned int canMessages=0;
860 unsigned int id = (ICUBCANPROTO_CLASS_POLLING_ANALOGSENSOR << 8) + (0x00 << 4) + (
cardId[i]);
863 unsigned int recvId = ( (ICUBCANPROTO_CLASS_POLLING_ANALOGSENSOR << 8) + (
cardId[i] << 4) );
870 outBuffer[0].getData()[0]= ICUBCANPROTO_POL_MC_CMD__GET_FIRMWARE_VERSION;
874 yError() <<
"CanBusSkin: Could not write to the CAN interface. \n";
880 yarp::os::Time::delay(0.3);
884 unsigned int read_messages=0;
890 yError() <<
"CanBusSkin: CanRead failed \n";
894 if (read_messages==0)
896 yError (
"No answers\n");
902 for (i=0; i<read_messages; i++)
931 fprintf(stderr,
"type %d\n", type);
932 fprintf(stderr,
"version %d\n", version);
933 fprintf(stderr,
"release %d\n", release);
934 fprintf(stderr,
"build %d\n", build);
936 if(version > 2) { firmware_version_ok =
true; }
938 if(version < 2) { firmware_version_ok =
false; }
941 if(release > 16) { firmware_version_ok =
true; }
943 if(release < 16) { firmware_version_ok =
false; }
946 if(build >= 25) { firmware_version_ok =
true; }
948 { firmware_version_ok =
false; }
954 if(!firmware_version_ok)
956 yWarning() <<
"Diagnostic check was enabled in the config file, but the firwmare does not support it yet! \
957 Please verify that the firmware version is at least 2.10.15 as shown in the canLoader\
958 disabling parsing of diagnostic messages";
961 yInfo() <<
"Firwmare check for skin diagnostic messages ok";
966 return firmware_version_ok;
const int CAN_DRIVER_BUFFER_SIZE
#define SPECIAL_TRIANGLE_CFG_MAX_NUM
#define TRIANGLE_MAX_NUM_IN_BOARD
const int CAN_DRIVER_BUFFER_SIZE
virtual int getState(int ch)
yarp::sig::VectorOf< iCub::skin::diagnostics::DetectedError > errors
The detected skin errors.
virtual void threadRelease()
yarp::dev::CanBuffer inBuffer
yarp::sig::VectorOf< int > cardId
yarp::dev::CanBuffer outBuffer
yarp::dev::ICanBufferFactory * pCanBufferFactory
virtual bool threadInit()
yarp::dev::ICanBus * pCanBus
virtual int getChannels()
virtual int read(yarp::sig::Vector &out)
yarp::dev::PolyDriver driver
virtual bool open(yarp::os::Searchable &config)
virtual int calibrateSensor()
virtual int calibrateChannel(int ch, double v)
void setDefaultValues(void)
bool readDefaultBoardCfg(yarp::os::Searchable &config, SkinBoardCfgParam *boardCfg)
bool isDefaultBoardCfgPresent(yarp::os::Searchable &config)
bool readSpecialBoardCfg(yarp::os::Searchable &config, SpecialSkinBoardCfgParam *boardCfg, unsigned int *numofcfg)
bool readDefaultTriangleCfg(yarp::os::Searchable &config, SkinTriangleCfgParam *triangCfg)
bool readSpecialTriangleCfg(yarp::os::Searchable &config, SpecialSkinTriangleCfgParam *triangleCfg, unsigned int *numofcfg)
bool isDefaultTriangleCfgPresent(yarp::os::Searchable &config)
void setDefaultValues(void)
static uint32_t idx[BOARD_NUM]
std::string printErrorCode(int code)