GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/trace-player.cpp Lines: 0 83 0.0 %
Date: 2023-06-05 17:45:50 Branches: 0 234 0.0 %

Line Branch Exec Source
1
/*
2
 * Copyright 2017, Andrea Del Prete, LAAS-CNRS
3
 *
4
 */
5
6
#include <dynamic-graph/factory.h>
7
8
#include <sot/core/debug.hh>
9
#include <sot/torque_control/commands-helper.hh>
10
#include <sot/torque_control/trace-player.hh>
11
#include <tsid/utils/statistics.hpp>
12
#include <tsid/utils/stop-watch.hpp>
13
14
namespace dynamicgraph {
15
namespace sot {
16
namespace torque_control {
17
namespace dynamicgraph = ::dynamicgraph;
18
using namespace dynamicgraph;
19
using namespace dynamicgraph::command;
20
using namespace std;
21
using namespace dynamicgraph::sot::torque_control;
22
23
/// Define EntityClassName here rather than in the header file
24
/// so that it can be used by the macros DEFINE_SIGNAL_**_FUNCTION.
25
typedef TracePlayer EntityClassName;
26
27
/* --- DG FACTORY ---------------------------------------------------- */
28
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(TracePlayer, "TracePlayer");
29
30
/* ------------------------------------------------------------------- */
31
/* --- CONSTRUCTION -------------------------------------------------- */
32
/* ------------------------------------------------------------------- */
33
TracePlayer::TracePlayer(const std::string& name)
34
    : Entity(name), CONSTRUCT_SIGNAL_OUT(trigger, int, sotNOSIGNAL) {
35
  Entity::signalRegistration(m_triggerSOUT);
36
37
  /* Commands. */
38
  addCommand("addOutputSignal",
39
             makeCommandVoid2(
40
                 *this, &TracePlayer::addOutputSignal,
41
                 docCommandVoid2(
42
                     "Add a new output signal",
43
                     "Name of the text file where to read the data (string)",
44
                     "Name of the output signal (string)")));
45
46
  addCommand(
47
      "playNext",
48
      makeCommandVoid0(*this, &TracePlayer::playNext,
49
                       docCommandVoid0("Update all the output signals.")));
50
51
  addCommand("rewind",
52
             makeCommandVoid0(*this, &TracePlayer::rewind,
53
                              docCommandVoid0("Rewind all the data.")));
54
55
  addCommand("clear", makeCommandVoid0(
56
                          *this, &TracePlayer::clear,
57
                          docCommandVoid0("Clear all the output signals.")));
58
}
59
60
/* ------------------------------------------------------------------- */
61
/* --- SIGNALS ------------------------------------------------------- */
62
/* ------------------------------------------------------------------- */
63
64
DEFINE_SIGNAL_OUT_FUNCTION(trigger, int) {
65
  std::string astr = toString(iter);
66
  playNext();
67
  return s;
68
}
69
70
/* --- COMMANDS ---------------------------------------------------------- */
71
72
void TracePlayer::addOutputSignal(const string& fileName,
73
                                  const string& signalName) {
74
  // check there is no other signal with the same name
75
  if (m_outputSignals.find(signalName) != m_outputSignals.end())
76
    return SEND_MSG("It already exists a signal with name " + signalName,
77
                    MSG_TYPE_ERROR);
78
79
  // read the text file
80
  std::ifstream datafile(fileName.c_str());
81
  if (datafile.fail())
82
    return SEND_MSG("Error trying to read the file " + fileName,
83
                    MSG_TYPE_ERROR);
84
85
  const unsigned int SIZE = 1024;
86
  char buffer[SIZE];
87
  std::vector<double> newline;
88
  int nbLines = 0;
89
  bool firstIter = true;
90
  std::size_t size = -1;
91
  string fileNameShort = fileName.substr(1 + fileName.find_last_of("/"));
92
  while (datafile.good()) {
93
    datafile.getline(buffer, SIZE);
94
    const std::size_t gcount = datafile.gcount();
95
    if (gcount >= SIZE)
96
      return SEND_MSG("Read error: line " + toString(nbLines) +
97
                          " too long in file " + fileNameShort,
98
                      MSG_TYPE_ERROR);
99
100
    std::istringstream iss(buffer);
101
    newline.clear();
102
    double x;
103
    iss >> x;  // discard the first value, which is the time step
104
    while (1) {
105
      iss >> x;
106
      if (iss.fail()) break;
107
      newline.push_back(x);
108
    }
109
110
    if (newline.size() > 0) {
111
      if (firstIter)
112
        size = newline.size();
113
      else if (size != newline.size()) {
114
        SEND_MSG("In file " + fileNameShort +
115
                     " nb of elements in each line changed from " +
116
                     toString(size) + " to " + toString(newline.size()) +
117
                     " at line " + toString(nbLines),
118
                 MSG_TYPE_WARNING);
119
        size = newline.size();
120
      }
121
      m_data[signalName].push_back(
122
          Eigen::Map<Vector>(&newline[0], newline.size()));
123
      nbLines++;
124
    }
125
  }
126
  SEND_MSG("Finished reading " + toString(nbLines) + " lines of " +
127
               toString(size) + " elements from file " + fileNameShort,
128
           MSG_TYPE_INFO);
129
  m_dataPointers[signalName] = m_data[signalName].begin();
130
131
  // create a new output signal
132
  m_outputSignals[signalName] =
133
      new OutputSignalType(getClassName() + "(" + getName() +
134
                           ")::output(dynamicgraph::Vector)::" + signalName);
135
136
  // register the new signal
137
  m_triggerSOUT.addDependency(*m_outputSignals[signalName]);
138
  Entity::signalRegistration(*m_outputSignals[signalName]);
139
}
140
141
void TracePlayer::playNext() {
142
  typedef std::map<std::string, OutputSignalType*>::iterator it_type;
143
  for (it_type it = m_outputSignals.begin(); it != m_outputSignals.end();
144
       it++) {
145
    const string& signalName = it->first;
146
    OutputSignalType* signal = it->second;
147
    DataPointerType& dataPointer = m_dataPointers[signalName];
148
    const DataHistoryType& dataSet = m_data[signalName];
149
150
    if (dataPointer != dataSet.end()) ++dataPointer;
151
152
    if (dataPointer == dataSet.end())
153
      SEND_WARNING_STREAM_MSG("Reached end of dataset for signal " +
154
                              signalName);
155
    else
156
      signal->setConstant(*dataPointer);
157
  }
158
}
159
160
void TracePlayer::rewind() {
161
  typedef std::map<std::string, DataPointerType>::iterator it_type;
162
  for (it_type it = m_dataPointers.begin(); it != m_dataPointers.end(); it++) {
163
    const string& signalName = it->first;
164
    DataPointerType& dataPointer = it->second;
165
    const DataHistoryType& dataSet = m_data[signalName];
166
    dataPointer = dataSet.begin();
167
  }
168
}
169
170
void TracePlayer::clear() {
171
  m_data.clear();
172
  m_dataPointers.clear();
173
  m_outputSignals.clear();
174
}
175
176
/* --- PROTECTED MEMBER METHODS
177
 * ---------------------------------------------------------- */
178
179
/* ------------------------------------------------------------------- */
180
/* --- ENTITY -------------------------------------------------------- */
181
/* ------------------------------------------------------------------- */
182
183
void TracePlayer::display(std::ostream& os) const {
184
  os << "TracePlayer " << getName();
185
  try {
186
    getProfiler().report_all(3, os);
187
  } catch (ExceptionSignal e) {
188
  }
189
}
190
}  // namespace torque_control
191
}  // namespace sot
192
}  // namespace dynamicgraph