Skip to content

Commit 5410ab0

Browse files
authored
Update filtering of spikes in temp reading (#961)
1 parent a3be505 commit 5410ab0

File tree

5 files changed

+141
-69
lines changed

5 files changed

+141
-69
lines changed

src/libraries/icubmod/embObjLib/abstractEthResource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ namespace eth {
5353
string boardtypeString;
5454
string boardnameString;
5555
string firmwareString;
56+
uint8_t txROPratedivider;
5657
};
5758

5859
//AbstractEthResource();

src/libraries/icubmod/embObjLib/diagnosticInfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ void TimeOfInfo::toString(std::string &str_toi)
3434

3535
void EmbeddedInfo::printMessage()
3636
{
37+
if (finalMessage.size() == 0)
38+
return;
39+
3740
std::string str_toi;
3841
timeOfInfo.toString(str_toi);
3942

src/libraries/icubmod/embObjLib/ethResource.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ bool EthResource::open2(eOipv4addr_t remIP, yarp::os::Searchable &cfgtotal)
129129
properties.ipv4addressingString = brddata.properties.ipv4addressingstring;
130130
properties.boardtypeString = brddata.properties.typestring;
131131
properties.boardnameString = brddata.settings.name;
132+
properties.txROPratedivider = txconfig.txratedivider;
132133

133134

134135
eth::EthMonitorPresence::Config mpConfig;

src/libraries/icubmod/embObjMotionControl/embObjMotionControl.cpp

Lines changed: 73 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@
88
*/
99

1010
//#include <yarp/dev/CanBusInterface.h>
11-
#include <yarp/os/Bottle.h>
12-
#include <yarp/os/Time.h>
11+
// system std include
1312
#include <string.h>
1413
#include <iostream>
1514
#include <cmath>
1615

16+
// yarp include
17+
#include <yarp/os/Bottle.h>
18+
#include <yarp/os/Time.h>
1719
#include "embObjMotionControl.h"
1820
#include <ethManager.h>
1921
#include <FeatureInterface.h>
2022
#include <yarp/conf/environment.h>
2123

2224
#include <yarp/os/LogStream.h>
2325

26+
#include <yarp/os/NetType.h>
27+
#include <yarp/dev/ControlBoardHelper.h>
28+
29+
// local include
2430
#include "EoCommon.h"
2531
#include "EOarray.h"
2632
#include "EoProtocol.h"
@@ -29,10 +35,6 @@
2935
#include "EoProtocolAS.h"
3036
#include "motionControlDefaultValues.h"
3137

32-
#include <yarp/os/NetType.h>
33-
#include <yarp/dev/ControlBoardHelper.h>
34-
35-
3638
#include "eomcUtils.h"
3739

3840
using namespace yarp::dev;
@@ -50,9 +52,6 @@ using namespace yarp::dev::eomc;
5052
#define PARSER_MOTION_CONTROL_VERSION 6
5153

5254

53-
54-
55-
5655
static inline bool NOT_YET_IMPLEMENTED(const char *txt)
5756
{
5857
yError() << txt << " is not yet implemented for embObjMotionControl";
@@ -73,10 +72,7 @@ static bool nv_not_found(void)
7372
return false;
7473
}
7574

76-
static constexpr double const temperatureErrorValue_s = -5000;
77-
78-
79-
75+
//static constexpr double const temperatureErrorValue_s = -5000;
8076

8177
std::string embObjMotionControl::getBoardInfo(void)
8278
{
@@ -136,6 +132,15 @@ bool embObjMotionControl::alloc(int nj)
136132
_temperatureSensorsVector.resize(nj);
137133
_temperatureExceededLimitWatchdog.resize(nj);
138134
_temperatureSensorErrorWatchdog.resize(nj);
135+
_temperatureSpikesFilter.resize(nj);
136+
137+
// update threshold for watchdog parametrized on the ROP transmission rate (by default is 2ms)
138+
uint8_t txrate = res->getProperties().txROPratedivider;
139+
for(int i = 0; i < nj; ++i)
140+
{
141+
_temperatureExceededLimitWatchdog.at(i).setThreshold(txrate);
142+
_temperatureSensorErrorWatchdog.at(i).setThreshold(txrate);
143+
}
139144

140145
return true;
141146
}
@@ -217,7 +222,8 @@ embObjMotionControl::embObjMotionControl() :
217222
_kalman_params(0),
218223
_temperatureSensorsVector(0),
219224
_temperatureExceededLimitWatchdog(0),
220-
_temperatureSensorErrorWatchdog(0)
225+
_temperatureSensorErrorWatchdog(0),
226+
_temperatureSpikesFilter(0)
221227
{
222228
_gearbox_M2J = 0;
223229
_gearbox_E2J = 0;
@@ -1621,49 +1627,71 @@ bool embObjMotionControl::update(eOprotID32_t id32, double timestamp, void *rxda
16211627

16221628
eOmc_motor_status_t *mc_motor_status = reinterpret_cast<eOmc_motor_status_t*>(rxdata);
16231629

1624-
if((double)mc_motor_status->basic.mot_temperature != temperatureErrorValue_s) //I get a valid value
1630+
if((double)mc_motor_status->basic.mot_temperature < 0 ) //I get a invalid value
16251631
{
1626-
double tmp = _temperatureSensorsVector.at(motor)->convertRawToTempCelsius((double)mc_motor_status->basic.mot_temperature);
1627-
1628-
if (tmp > _temperatureLimits[motor].warningTemperatureLimit)
1632+
if(! _temperatureSensorErrorWatchdog.at(motor).isStarted())
16291633
{
1630-
if(! _temperatureExceededLimitWatchdog.at(motor).isStarted())
1631-
{
1632-
yWarning() << getBoardInfo() << "Motor" << motor << "The temperature (" << tmp << "[ ℃ ] ) exceeds the warning limit (" << _temperatureLimits[motor].warningTemperatureLimit << "[ ℃ ] ). Processes not stopped but it is strongly recommended decreasing motor usage or reducing currents and PWMs to not risk motor damaging";
1633-
_temperatureExceededLimitWatchdog.at(motor).start();
1634-
}
1635-
else
1636-
{
1637-
if(_temperatureExceededLimitWatchdog.at(motor).isExpired())
1638-
{
1639-
yWarning() << getBoardInfo() << "Motor" << motor << "The temperature (" << tmp << "[ ℃ ] ) exceeds the warning limit (" << _temperatureLimits[motor].warningTemperatureLimit << "[ ℃ ] ) again!. Processes not stopped but it is strongly recommended decreasing motor usage or reducing currents and PWMs to not risk motor damaging";
1640-
_temperatureExceededLimitWatchdog.at(motor).start();
1641-
}
1642-
_temperatureExceededLimitWatchdog.at(motor).increment();
1643-
}
1634+
yError() << getBoardInfo() << "At timestamp" << yarp::os::Time::now() << "In motor" << motor << "cannot read Temperature from I2C. There might be cabling problems, TDB cable might be broken or sensor unreachable";
1635+
_temperatureSensorErrorWatchdog.at(motor).start();
16441636
}
16451637
else
16461638
{
1647-
_temperatureExceededLimitWatchdog.at(motor).clear();
1639+
_temperatureSensorErrorWatchdog.at(motor).increment();
1640+
if( _temperatureSensorErrorWatchdog.at(motor).isExpired())
1641+
{
1642+
yError()<< getBoardInfo() << "Motor" << motor << "failed to read" << _temperatureSensorErrorWatchdog.at(motor).getCount() << "temperature readings for" << yarp::os::Time::now() - _temperatureSensorErrorWatchdog.at(motor).getStartTime() << "seconds";
1643+
_temperatureSensorErrorWatchdog.at(motor).start();
1644+
}
16481645
}
1646+
return true;
16491647
}
1650-
else //I get a NOT valid value
1648+
1649+
//if I'm here I have a valid value
1650+
double delta_tmp = 0;
1651+
double tmp = _temperatureSensorsVector.at(motor)->convertRawToTempCelsius((double)mc_motor_status->basic.mot_temperature);
1652+
1653+
// check if this is a spike or not
1654+
// evaluate difference between current and previous temperature
1655+
if(!_temperatureSpikesFilter.at(motor).isStarted()) //Pre-set of the filter buffer is ready
16511656
{
1652-
if(! _temperatureSensorErrorWatchdog.at(motor).isStarted())
1657+
_temperatureSpikesFilter.at(motor).start(tmp);
1658+
return true;
1659+
}
1660+
1661+
// when i'm here the filter is ready.
1662+
delta_tmp = std::abs(tmp - _temperatureSpikesFilter.at(motor).getPrevTemperature());
1663+
1664+
//1. check if I have a good value (not a spike)
1665+
if(delta_tmp > _temperatureSpikesFilter.at(motor).getTemperatureThreshold())
1666+
{
1667+
//it is a spike
1668+
return true;
1669+
}
1670+
// this is a not spike --> can update prev temperature
1671+
_temperatureSpikesFilter.at(motor).updatePrevTemperature(tmp);
1672+
1673+
//2. tmp is good and check the limits
1674+
if(tmp > _temperatureLimits[motor].warningTemperatureLimit)
1675+
{
1676+
if(! _temperatureExceededLimitWatchdog.at(motor).isStarted())
16531677
{
1654-
yError() << getBoardInfo() << "At timestamp" << yarp::os::Time::now() << "In motor" << motor << "cannot read Temperature from I2C. There might be cabling problems, TDB cable might be broken or sensor unreachable";
1655-
_temperatureSensorErrorWatchdog.at(motor).start();
1678+
yWarning() << getBoardInfo() << "Motor" << motor << "The temperature (" << tmp << "[ ℃ ] ) exceeds the warning limit (" << _temperatureLimits[motor].warningTemperatureLimit << "[ ℃ ] ). Processes not stopped but it is strongly recommended decreasing motor usage or reducing currents and PWMs to not risk motor damaging";
1679+
_temperatureExceededLimitWatchdog.at(motor).start();
16561680
}
16571681
else
16581682
{
1659-
_temperatureSensorErrorWatchdog.at(motor).increment();
1660-
if( _temperatureSensorErrorWatchdog.at(motor).isExpired())
1683+
if(_temperatureExceededLimitWatchdog.at(motor).isExpired())
16611684
{
1662-
yError()<< getBoardInfo() << "Motor" << motor << "failed to read temperature for" << yarp::os::Time::now() - _temperatureSensorErrorWatchdog.at(motor).getStartTime() << "seconds";
1663-
_temperatureSensorErrorWatchdog.at(motor).start();
1685+
yWarning() << getBoardInfo() << "Motor" << motor << "The temperature (" << tmp << "[ ℃ ] ) exceeds the warning limit (" << _temperatureLimits[motor].warningTemperatureLimit << "[ ℃ ] ) again!. Processes not stopped but it is strongly recommended decreasing motor usage or reducing currents and PWMs to not risk motor damaging";
1686+
_temperatureExceededLimitWatchdog.at(motor).start();
16641687
}
1688+
_temperatureExceededLimitWatchdog.at(motor).increment();
16651689
}
16661690
}
1691+
else
1692+
{
1693+
_temperatureExceededLimitWatchdog.at(motor).clear();
1694+
}
16671695
}
16681696

16691697
return true;
@@ -4821,10 +4849,10 @@ bool embObjMotionControl::getTemperatureRaw(int m, double* val)
48214849
return ret;
48224850
}
48234851

4824-
if (((double)status.mot_temperature) == temperatureErrorValue_s) //using -5000 as the default value on 2FOC for initializing the temperature. If cannot read from I2C the value cannot be updated
4825-
{
4826-
return false;
4827-
}
4852+
// if (((double)status.mot_temperature) == temperatureErrorValue_s) //using -5000 as the default value on 2FOC for initializing the temperature. If cannot read from I2C the value cannot be updated
4853+
// {
4854+
// return false;
4855+
// }
48284856

48294857
*val = _temperatureSensorsVector.at(m)->convertRawToTempCelsius((double)status.mot_temperature);
48304858

src/libraries/icubmod/embObjMotionControl/embObjMotionControl.h

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030

3131
using namespace std;
3232

33+
// system std include
3334
#include <string>
3435
#include <mutex>
36+
#include <math.h>
3537
// Yarp stuff
3638
#include <yarp/os/Bottle.h>
3739
#include <yarp/os/BufferedPort.h>
@@ -44,11 +46,12 @@ using namespace std;
4446

4547
#include<yarp/dev/ImplementJointFault.h>
4648

49+
#include <abstractEthResource.h>
4750

51+
// local include
4852
#include "IethResource.h"
4953
#include"EoError.h"
5054
#include <ethManager.h>
51-
#include <abstractEthResource.h>
5255

5356
#include "serviceParser.h"
5457
#include "eomcParser.h"
@@ -75,8 +78,6 @@ using namespace std;
7578

7679
#define EMBOBJMC_DONT_USE_MAIS
7780

78-
79-
8081
//
8182
// helper structures
8283
//
@@ -114,16 +115,14 @@ class Watchdog
114115

115116
bool _isStarted;
116117
uint32_t _count;
118+
double _time;
117119
uint32_t _threshold; // use 10000 as limit on the watchdog for the error on the temperature sensor receiving of the values -
118120
// since the ETH callback timing is 2ms by default so using 10000 we can set a checking threshould of 5 second
119121
// in which we can allow the tdb to not respond. If cannot receive response over 1s we trigger the error
120-
121-
double _time;
122-
123122
public:
124123

125-
Watchdog(): _count(0), _isStarted(false), _threshold(10000), _time(0){;}
126-
Watchdog(uint32_t threshold):_count(0), _isStarted(false),_threshold(threshold), _time(0){;}
124+
Watchdog(): _count(0), _isStarted(false), _threshold(60000), _time(0){;}
125+
Watchdog(uint32_t threshold):_count(0), _isStarted(false), _threshold(threshold), _time(0){;}
127126
~Watchdog() = default;
128127
Watchdog(const Watchdog& other) = default;
129128
Watchdog(Watchdog&& other) noexcept = default;
@@ -138,8 +137,49 @@ void increment() {++_count;}
138137
void clear(){_isStarted=false;}
139138
double getStartTime() {return _time;}
140139
uint32_t getCount() {return _count; }
140+
void setThreshold(uint8_t txrateOfRegularROPs){_threshold = _threshold / txrateOfRegularROPs;}
141+
uint32_t getThreshold(){return _threshold;}
142+
143+
};
141144

145+
class TemperatureFilter
146+
{
147+
private:
148+
uint32_t _threshold; // threshold for the delta between current and previous temperature --> set to 20 Celsius deg by default --> over 20 deg delta spike
149+
double _motorTempPrev; // motor temperature at previous instant for checking positive temperature spikes
150+
bool _isStarted;
151+
int32_t _initCounter;
152+
std::vector<double> _initTempBuffer;
153+
public:
154+
TemperatureFilter(): _threshold(20), _isStarted(false), _initCounter(50), _initTempBuffer(0), _motorTempPrev(0){;}
155+
TemperatureFilter(uint32_t threshold, int32_t initCounter): _threshold(threshold), _isStarted(false), _initCounter(initCounter), _initTempBuffer(0), _motorTempPrev(0){;}
156+
~TemperatureFilter() = default;
157+
TemperatureFilter(const TemperatureFilter& other) = default;
158+
TemperatureFilter(TemperatureFilter&& other) noexcept = default;
159+
TemperatureFilter& operator=(const TemperatureFilter& other) = default;
160+
TemperatureFilter& operator=(TemperatureFilter&& other) noexcept = default;
161+
162+
bool isStarted(){return _isStarted;}
163+
uint32_t getTemperatureThreshold() {return _threshold; }
164+
double getPrevTemperature(){return _motorTempPrev;}
165+
void updatePrevTemperature(double temperature){_motorTempPrev = temperature;}
166+
void start(double temperature)
167+
{
168+
if(_initCounter < 0)
169+
{
170+
int median_pos = std::ceil(_initTempBuffer.size() / 2) -1;
171+
_motorTempPrev = _initTempBuffer.at(median_pos);
172+
_isStarted = true;
173+
}
174+
else
175+
{
176+
_initTempBuffer.push_back(temperature);
177+
--_initCounter;
178+
}
179+
180+
}
142181
};
182+
143183
}}}
144184

145185
namespace yarp {
@@ -220,7 +260,6 @@ class yarp::dev::embObjMotionControl: public DeviceDriver,
220260
public ImplementJointFault
221261
{
222262
private:
223-
224263
eth::TheEthManager* ethManager;
225264
eth::AbstractEthResource* res;
226265
ServiceParser* parser;
@@ -243,26 +282,26 @@ class yarp::dev::embObjMotionControl: public DeviceDriver,
243282

244283
std::vector<std::unique_ptr<eomc::ITemperatureSensor>> _temperatureSensorsVector;
245284

246-
eomc::focBasedSpecificInfo_t * _foc_based_info;
285+
eomc::focBasedSpecificInfo_t * _foc_based_info;
247286

248-
std::vector<eomc::encoder_t> _jointEncs;
249-
std::vector<eomc::encoder_t> _motorEncs;
287+
std::vector<eomc::encoder_t> _jointEncs;
288+
std::vector<eomc::encoder_t> _motorEncs;
250289

251-
std::vector<eomc::rotorLimits_t> _rotorsLimits; /** contains limit about rotors such as position and pwm */
252-
std::vector<eomc::jointLimits_t> _jointsLimits; /** contains limit about joints such as position and velocity */
253-
std::vector<eomc::motorCurrentLimits_t> _currentLimits;
254-
std::vector<eomc::temperatureLimits_t> _temperatureLimits;
255-
eomc::couplingInfo_t _couplingInfo; /** contains coupling matrix */
256-
std::vector<eomc::JointsSet> _jsets;
257-
std::vector<int> _joint2set; /** for each joint says the number of set it belongs to */
258-
std::vector<eomc::timeouts_t> _timeouts;
290+
std::vector<eomc::rotorLimits_t> _rotorsLimits; /** contains limit about rotors such as position and pwm */
291+
std::vector<eomc::jointLimits_t> _jointsLimits; /** contains limit about joints such as position and velocity */
292+
std::vector<eomc::motorCurrentLimits_t> _currentLimits;
293+
std::vector<eomc::temperatureLimits_t> _temperatureLimits;
294+
eomc::couplingInfo_t _couplingInfo; /** contains coupling matrix */
295+
std::vector<eomc::JointsSet> _jsets;
296+
std::vector<int> _joint2set; /** for each joint says the number of set it belongs to */
297+
std::vector<eomc::timeouts_t> _timeouts;
259298

260299
std::vector<eomc::impedanceParameters_t> _impedance_params; /** impedance parameters */ // TODO doubled!!! optimize using just one of the 2!!!
261-
eomc::impedanceLimits_t * _impedance_limits; /** impedancel imits */
300+
eomc::impedanceLimits_t * _impedance_limits; /** impedancel imits */
262301

263302

264303
eomc::PidInfo * _trj_pids;
265-
//eomc::PidInfo * _dir_pids;
304+
//eomc::PidInfo * _dir_pids;
266305
eomc::TrqPidInfo * _trq_pids;
267306
eomc::PidInfo * _cur_pids;
268307
eomc::PidInfo * _spd_pids;
@@ -298,13 +337,13 @@ class yarp::dev::embObjMotionControl: public DeviceDriver,
298337
double *_ref_positions; // used for direct position control.
299338
double *_ref_accs; // for velocity control, in position min jerk eq is used.
300339
double *_encodersStamp; /** keep information about acquisition time for encoders read */
301-
bool *checking_motiondone; /* flag telling if I'm already waiting for motion done */
340+
bool *checking_motiondone; /* flag telling if I'm already waiting for motion done */
302341
#define MAX_POSITION_MOVE_INTERVAL 0.080
303342
double *_last_position_move_time; /** time stamp for last received position move command*/
304343
eOmc_impedance_t *_cacheImpedance; /* cache impedance value to split up the 2 sets */
305344
std::vector<yarp::dev::eomc::Watchdog> _temperatureSensorErrorWatchdog; /* counter used to filter error coming from tdb reading fromm 2FOC board*/
306345
std::vector<yarp::dev::eomc::Watchdog> _temperatureExceededLimitWatchdog; /* counter used to filter the print of the exeded limits*/
307-
346+
std::vector<yarp::dev::eomc::TemperatureFilter> _temperatureSpikesFilter;
308347

309348
#ifdef NETWORK_PERFORMANCE_BENCHMARK
310349
Tools:Emb_RensponseTimingVerifier m_responseTimingVerifier;

0 commit comments

Comments
 (0)