34 uint32_t i, n = m_readings.size();
37 for (i = 0; i < n; i++)
39 out <<
CPose3D(m_readings[i].eNosePoseOnTheRobot);
40 out << m_readings[i].readingsVoltage;
41 out << m_readings[i].sensorTypes;
42 out << m_readings[i].hasTemperature;
43 if (m_readings[i].hasTemperature)
out << m_readings[i].temperature;
46 out << sensorLabel << timestamp;
67 for (i = 0; i < n; i++)
70 m_readings[i].eNosePoseOnTheRobot = aux.
asTPose();
71 in >> m_readings[i].readingsVoltage;
72 in >> m_readings[i].sensorTypes;
75 in >> m_readings[i].hasTemperature;
76 if (m_readings[i].hasTemperature)
77 in >> m_readings[i].temperature;
81 m_readings[i].hasTemperature =
false;
82 m_readings[i].temperature = 0;
108 ASSERT_(readings.size() == 16);
113 TPose3D(0.20, -0.15, 0.10, 0, 0, 0);
122 m_readings.push_back(eNose);
126 TPose3D(0.20, 0.15, 0.10, .0, .0, .0);
135 m_readings.push_back(eNose);
148 if (!m_readings.empty())
149 out_sensorPose =
CPose3D(m_readings[0].eNosePoseOnTheRobot);
151 out_sensorPose =
CPose3D(0, 0, 0);
156 for (
auto& r : m_readings) r.eNosePoseOnTheRobot = newSensorPose.
asTPose();
165 noise_filtering(reading, timestamp);
168 if (decimate_count != decimate_value)
177 m_antiNoise_window[winNoise_size / 2].reading_filtered,
178 m_antiNoise_window[winNoise_size / 2].timestamp);
182 reading = last_Obs.estimation;
183 timestamp = last_Obs.timestamp;
188 last_Obs.timestamp, last_Obs.reading, last_Obs.estimation,
195 cout <<
"Error when decimating \n";
210 temporal_Obs.reading = reading;
211 temporal_Obs.timestamp = timestamp;
214 if (m_antiNoise_window.empty())
217 temporal_Obs.reading_filtered = reading;
220 m_antiNoise_window.assign(winNoise_size, temporal_Obs);
225 m_antiNoise_window.erase(m_antiNoise_window.begin());
226 m_antiNoise_window.push_back(temporal_Obs);
230 float partial_sum = 0;
231 for (
auto& i : m_antiNoise_window) partial_sum += i.reading;
233 m_antiNoise_window.at(winNoise_size / 2).reading_filtered =
234 partial_sum / winNoise_size;
238 cout <<
"Error when filtering noise from readings \n";
253 if (reading < min_reading) min_reading = reading;
256 if (!first_iteration)
263 if ((incT > 0) & (!first_incT))
269 if (fabs(incT - fixed_incT) > (
double)(0.05))
270 cout <<
"IncT is not constant by HW." << endl;
274 if (incT > 0) first_incT =
false;
278 if (reading < last_Obs.reading)
281 a_decay * std::abs(reading - min_reading) + b_decay;
286 a_rise * std::abs(reading - min_reading) + b_rise;
293 last_Obs.estimation =
294 d2f(((reading - last_Obs.reading) * last_Obs.tau / incT) +
297 last_Obs.estimation = reading;
300 last_Obs.timestamp = timestamp;
301 last_Obs.reading = reading;
306 last_Obs.tau = b_rise;
307 last_Obs.reading = reading;
308 last_Obs.timestamp = timestamp;
309 last_Obs.estimation =
311 first_iteration =
false;
314 catch (
const exception& e)
316 cerr <<
"**Exception in " 317 "CObservationGasSensors::CMOSmodel::inverse_MOSmodeling** " 334 sprintf(buffer,
"./log_MOSmodel_GasDistribution.txt");
336 if (!m_debug_dump) m_debug_dump =
new ofstream(buffer);
338 if (m_debug_dump->is_open())
340 *m_debug_dump <<
format(
"%f \t", time);
341 *m_debug_dump <<
format(
"%f \t", reading);
342 *m_debug_dump <<
format(
"%f \t", estimation);
343 *m_debug_dump <<
format(
"%f \t", tau);
344 *m_debug_dump <<
"\n";
347 cout <<
"Unable to open file";
355 for (
size_t j = 0; j < m_readings.size(); j++)
357 o <<
format(
"e-nose #%u:\n", (
unsigned)j);
359 vector<float>::const_iterator it;
360 std::vector<int>::const_iterator itKind;
363 m_readings[j].readingsVoltage.size() ==
364 m_readings[j].sensorTypes.size());
366 for (it = m_readings[j].readingsVoltage.begin(),
367 itKind = m_readings[j].sensorTypes.begin();
368 it != m_readings[j].readingsVoltage.end(); it++, itKind++)
369 o <<
format(
"%04X: %.03f ", *itKind, *it);
374 " Sensor pose on robot: (x,y,z)=(%.02f,%.02f,%.02f)\n",
375 m_readings[j].eNosePoseOnTheRobot.x,
376 m_readings[j].eNosePoseOnTheRobot.y,
377 m_readings[j].eNosePoseOnTheRobot.z);
379 o <<
"Measured temperature: ";
380 if (m_readings[j].hasTemperature)
381 o <<
format(
"%.03f degC\n", m_readings[j].temperature);
383 o <<
"NOT AVAILABLE\n";
mrpt::math::TPose3D asTPose() const
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
Template for column vectors of dynamic size, compatible with Eigen.
std::string std::string format(std::string_view fmt, ARGS &&... args)
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files.
The structure for each e-nose.
void getSensorPose(mrpt::poses::CPose3D &out_sensorPose) const override
A general method to retrieve the sensor pose on the robot.
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
#define ASSERT_(f)
Defines an assertion mechanism.
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
float d2f(const double d)
shortcut for static_cast<float>(double)
This base provides a set of functions for maths stuff.
math::TPose3D eNosePoseOnTheRobot
The pose of the sensors on the robot.
std::vector< int > sensorTypes
The kind of sensors in the array (size of "sensorTypes" is the same that the size of "readingsVoltage...
double timestampTotime_t(const mrpt::system::TTimeStamp t) noexcept
Transform from TTimeStamp to standard "time_t" (actually a double number, it can contain fractions of...
void save_log_map(const mrpt::system::TTimeStamp ×tamp, float reading, float estimation, float tau)
Save the gas distribution estiamtion into a log file for offline representation.
This namespace contains representation of robot actions and observations.
Declares a class derived from "CObservation" that represents a set of readings from gas sensors...
void setSensorPose(const mrpt::poses::CPose3D &newSensorPose) override
A general method to change the sensor pose on the robot.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
void pause(const std::string &msg=std::string("Press any key to continue...")) noexcept
Shows the message "Press any key to continue" (or other custom message) to the current standard outpu...
Virtual base class for "archives": classes abstracting I/O streams.
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
mrpt::vision::TStereoCalibResults out
Declares a class that represents any robot's observation.
void noise_filtering(float reading, const mrpt::system::TTimeStamp ×tamp)
Reduce noise by averaging with a mobile window of specific size (winNoise_size)
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
void inverse_MOSmodeling(float reading, const mrpt::system::TTimeStamp ×tamp)
Estimates the gas concentration based on readings and sensor model.
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
std::vector< float > readingsVoltage
The set of readings (in volts) from the array of sensors (size of "sensorTypes" is the same that the ...
void getDescriptionAsText(std::ostream &o) const override
Build a detailed, multi-line textual description of the observation contents and dump it to the outpu...
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
int sprintf(char *buf, size_t bufSize, const char *format,...) noexcept MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
virtual void getDescriptionAsText(std::ostream &o) const
Build a detailed, multi-line textual description of the observation contents and dump it to the outpu...
bool get_GasDistribution_estimation(float &reading, mrpt::system::TTimeStamp ×tamp)
Obtain an estimation of the gas distribution based on raw sensor readings.