22#include <unordered_map>
30#include <yarp/os/LogStream.h>
31#include <yarp/os/Property.h>
32#include <yarp/os/Log.h>
33#include <yarp/os/Searchable.h>
40 YARP_LOG_COMPONENT(FineCalibrationCheckerThreadCOMPONENT,
"yarp.device.fineCalibrationCheckerThread")
44 :
yarp::os::Thread(), _deviceName(
"fineCalibrationChecker"), _portPrefix(
"/fineCalibrationChecker"),
45 _robotName(
"icub"), _remoteRawValuesPort(
"/icub/rawvalues"), _controlBoardsList(
yarp::os::Bottle()), _axesNamesList(
yarp::os::Bottle()), _deviceStatus(
deviceStatus::NONE)
48 _fineCalibrationCheckerDevice = std::make_unique<yarp::dev::PolyDriver>();
49 _rawValuesOublisherDevice = std::make_unique<yarp::dev::PolyDriver>();
52 yarp::os::Searchable &conf_group = rf.findGroup(
"GENERAL");
53 if (conf_group.isNull())
55 yCWarning(FineCalibrationCheckerThreadCOMPONENT) <<
"Missing GENERAL group! The module uses the default values";
60 if (conf_group.check(
"devicename")) { _deviceName = conf_group.find(
"devicename").asString(); }
61 if (conf_group.check(
"robotname")) { _robotName = conf_group.find(
"robotname").asString(); }
62 if (conf_group.check(
"remoteRawValuesPort")) { _remoteRawValuesPort = conf_group.find(
"remoteRawValuesPort").asString(); }
63 if (conf_group.check(
"remoteControlBoardsList"))
65 yarp::os::Bottle* subpartsList = conf_group.find(
"remoteControlBoardsList").asList();
66 yarp::os::Bottle &controlBoards = _controlBoardsList.addList();
67 for (
size_t i = 0; i < subpartsList->size(); i++)
69 controlBoards.addString(
"/" + _robotName +
"/" + subpartsList->get(i).asString());
72 if (conf_group.check(
"axesNamesList"))
74 yarp::os::Bottle* _jointsList = conf_group.find(
"axesNamesList").asList();
75 yarp::os::Bottle &axesNames = _axesNamesList.addList();
76 for (
size_t i = 0; i < _jointsList->size(); i++)
78 axesNames.addString(_jointsList->get(i).asString());
84 std::ifstream
file(
"zeroPositionsData.csv");
86 while (std::getline(
file, line))
88 std::istringstream iss(line);
89 std::string key, pos, res;
90 if (std::getline(iss, key,
',') && std::getline(iss, pos,
',') && std::getline(iss, res)) {
91 axesRawGoldenPositionsResMap[key] = {std::stoi(pos), std::stoi(res)};
93 yCDebug(FineCalibrationCheckerThreadCOMPONENT) <<
"Zero GOLDEN position for joint" << key
94 <<
"is" << axesRawGoldenPositionsResMap[key][0]
95 <<
"and its encoder has" << axesRawGoldenPositionsResMap[key][1] <<
"ticks per revolution";
104 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Configuring controlboards" << _controlBoardsList.toString();
105 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Configuring joint" << _axesNamesList.toString();
109 yarp::os::Property deviceProperties;
111 deviceProperties.put(
"device",
"remotecontrolboardremapper");
112 deviceProperties.put(
"axesNames", _axesNamesList.get(0));
113 deviceProperties.put(
"remoteControlBoards", _controlBoardsList.get(0));
114 deviceProperties.put(
"localPortPrefix",
"/" + _deviceName);
116 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Configuring device driver with properties:" << deviceProperties.toString();
118 _fineCalibrationCheckerDevice->open(deviceProperties);
120 if (!_fineCalibrationCheckerDevice->isValid())
122 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Unable to open device driver. Aborting...";
126 yarp::os::Property rawValuesDeviceProperties;
127 rawValuesDeviceProperties.put(
"device",
"rawValuesPublisherClient");
128 rawValuesDeviceProperties.put(
"remote", _remoteRawValuesPort);
129 rawValuesDeviceProperties.put(
"local",
"/" + _deviceName +
"/rawValuesPublisherClient");
131 _rawValuesOublisherDevice->open(rawValuesDeviceProperties);
133 if (!_rawValuesOublisherDevice->isValid())
135 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Unable to open raw values device driver. Aborting...";
139 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Opened all devices successfully";
149 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Thread started to run";
151 while(!this->isStopping())
156 yCDebug(FineCalibrationCheckerThreadCOMPONENT) <<
"Configuring calibration device";
157 if(!configureCalibration())
159 yCError(FineCalibrationCheckerThreadCOMPONENT) <<
"Failed to configure device";
168 if(!runCalibration())
170 yCError(FineCalibrationCheckerThreadCOMPONENT) <<
"Failed to calibrate axesNames attached to the device";
183 yCWarning(FineCalibrationCheckerThreadCOMPONENT) <<
"telemetryDeviceDumper warning : raw_data_values was not read correctly";
187 yCDebug(FineCalibrationCheckerThreadCOMPONENT) <<
"Get raw values from encoders:";
188 for (
auto [key,value] : rawDataValuesMap)
190 yCDebug(FineCalibrationCheckerThreadCOMPONENT) <<
"\t key:" << key <<
"value:" << value;
195 evaluateHardStopPositionDelta(_rawValuesTag,
"zeroPositionsData.csv",
"zeroPositionsDataDelta.csv");
201 if(!_iremotecalib->homingSingleJoint(0))
203 yCError(FineCalibrationCheckerThreadCOMPONENT) <<
"Failed to homing axesNames attached to the device";
207 yCDebug(FineCalibrationCheckerThreadCOMPONENT) <<
"Successfully homing axesNames attached to the device";
215 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Thread stopping";
226 if(this->isStopping())
228 if(_fineCalibrationCheckerDevice->close())
230 yCDebug(FineCalibrationCheckerThreadCOMPONENT) <<
"Closed device" << _deviceName;
234 yCError(FineCalibrationCheckerThreadCOMPONENT) <<
"Unable to close device" << _deviceName;
253bool FineCalibrationCheckerThread::configureCalibration()
259 if (!_fineCalibrationCheckerDevice->view(_imot) || _imot ==
nullptr)
261 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Unable to open motor interface. Aborting...";
265 if (!_fineCalibrationCheckerDevice->view(_iremotecalib) || _iremotecalib ==
nullptr)
267 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Unable to open remote calibrator interface. Aborting...";
271 if (!_fineCalibrationCheckerDevice->view(_icontrolcalib) || _icontrolcalib ==
nullptr)
273 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Unable to open control calibration interface. Aborting...";
277 if (!_rawValuesOublisherDevice->view(_iravap) || _iravap ==
nullptr)
279 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Unable to open raw values publisher interface. Aborting...";
285 rawDataMetadata = {};
287 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Configured raw values with metadata";
288 for (
auto [k, m] : rawDataMetadata.metadataMap)
290 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName
291 <<
"\t Key: " << k <<
"\n"
292 <<
"\t axesName: " << m.axesNames <<
"\n"
293 <<
"\t rawValueNames: " << m.rawValueNames;
296 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Opened remote calibrator and control calibration interfaces successfully";
300bool FineCalibrationCheckerThread::runCalibration()
306 _imot->getNumberOfMotors(&motors);
307 bool isCalibratorSet =
false;
308 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Starting calibration process on joint" << motors;
309 if(_iremotecalib->isCalibratorDevicePresent(&isCalibratorSet))
311 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Calibration device present!. Go on with calibration procedure";
313 if (_iremotecalib->calibrateSingleJoint(0))
315 yCDebug(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Calibration of joint ended successfully!";
319 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Unable to start calibration!. Closing!";
325 yCError(FineCalibrationCheckerThreadCOMPONENT) << _deviceName <<
"Calibration device not set yet. Closing!";
332void FineCalibrationCheckerThread::evaluateHardStopPositionDelta(
const std::string& key,
const std::string& inputFileName,
const std::string& outputFileName)
335 std::filesystem::path inputPath(inputFileName);
336 std::filesystem::path outputPath = inputPath.parent_path() / outputFileName;
337 int32_t goldPosition = 0;
338 int32_t rawPosition = 0;
339 int32_t resolution = 0;
340 int32_t rescaledPos = 0;
342 std::vector<ItemData> sampleItems = {};
344 std::ofstream
outFile(outputPath);
347 yCError(FineCalibrationCheckerThreadCOMPONENT) <<
"Unable to open output file:" << outputPath.string();
351 if(
auto it = rawDataValuesMap.find(key); it != rawDataValuesMap.end())
353 std::vector<std::string> axesNames = {};
354 std::vector<std::int32_t> rawData = {};
358 for (
size_t i = 0; i < axesNames.size(); ++i)
364 if (
auto it = axesRawGoldenPositionsResMap.find(axesNames[i]); it != axesRawGoldenPositionsResMap.end())
366 goldPosition = it->second[0];
367 resolution = it->second[1];
368 rawPosition = rawData[3*i];
372 rescaledPos = goldPosition * resolution / 65535;
373 delta = std::abs(rescaledPos - rawPosition);
377 outFile << axesNames[i] <<
"," << goldPosition <<
"," << rescaledPos <<
"," << rawPosition <<
"," << delta <<
"\n";
378 sampleItems.push_back({axesNames[i], goldPosition, rescaledPos, rawPosition, delta});
383 yCError(FineCalibrationCheckerThreadCOMPONENT) <<
"Key" << key <<
"not found in rawDataValuesMap";
384 outFile <<
"Key not found in rawDataValuesMap\n";
388 yCDebug(FineCalibrationCheckerThreadCOMPONENT) <<
"Output CSV written to:" << outputPath.string();
390 generateOutputImage(800, 400, sampleItems);
393void FineCalibrationCheckerThread::configureDevicesMap(std::vector<std::string> list)
451void FineCalibrationCheckerThread::generateOutputImage(
int frameWidth,
int frameHeight,
const std::vector<ItemData>& items)
453 cv::Mat image = cv::Mat::zeros(frameHeight, frameWidth, CV_8UC3);
454 image.setTo(cv::Scalar(255, 255, 255));
460 for (
size_t i = 0; i < items.size(); ++i)
462 int y = padding + i * lineHeight;
464 cv::Scalar bgColor = getColorForDelta(items[i].val3, 1, 3);
466 cv::Point(padding,
y),
467 cv::Point(frameWidth - padding,
y + lineHeight - 5),
468 bgColor, cv::FILLED);
472 cv::Point(padding,
y),
473 cv::Point(frameWidth - padding,
y + lineHeight - 5),
474 cv::Scalar(200, 200, 200), 1);
477 std::string text = items[i].name +
" " +
478 std::to_string(items[i].val1) +
" " +
479 std::to_string(items[i].val2) +
" " +
480 std::to_string(items[i].val3) +
" " +
481 std::to_string(items[i].val4);
483 cv::putText(image, text, cv::Point(padding + 5,
y + textOffset),
484 cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 0), 2);
487 cv::imwrite(
"output_frame.png", image);
488 cv::imshow(
"Output Frame", image);
490 cv::destroyAllWindows();
493cv::Scalar FineCalibrationCheckerThread::getColorForDelta(int32_t delta, int32_t threshold_1, int32_t threshold_2)
495 if (delta > threshold_2)
return cv::Scalar(0, 0, 255);
496 else if (delta > threshold_1)
return cv::Scalar(0, 165, 255);
497 else return cv::Scalar(0, 255, 0);
bool isCalibrationSuccessful() const
void threadRelease() override
FineCalibrationCheckerThread()=default
bool threadInit() override
virtual bool getMetadataMap(rawValuesKeyMetadataMap &metamap)=0
virtual bool getRawData(std::string key, std::vector< std::int32_t > &data)=0
virtual bool getAxesNames(std::string key, std::vector< std::string > &axesNames)=0
virtual bool getRawDataMap(std::map< std::string, std::vector< std::int32_t > > &map)=0
Copyright (C) 2008 RobotCub Consortium.