OptoForceUnit.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package RobotAPI::ArmarXObjects::OptoForceUnit
17  * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu )
18  * @date 2017
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "OptoForceUnit.h"
24 
27 
28 
29 using namespace armarx;
30 
31 
33  : isRecording(false), stopRecordingFlag(false)
34 {
35 
36 }
37 
39 {
40  std::string calibrationFilePath = getProperty<std::string>("CalibrationFilePath").getValue();
41  if (!ArmarXDataPath::getAbsolutePath(calibrationFilePath, calibrationFilePath))
42  {
43  throw LocalException("Could not find calibration file '") << calibrationFilePath << "'";
44  }
45  ARMARX_INFO << "reading config " << calibrationFilePath;
46  RapidXmlReaderPtr reader = RapidXmlReader::FromFile(calibrationFilePath);
47  RapidXmlReaderNode rootNode = reader->getRoot("Calibration");
48 
49  auto findDaqNode = [&](std::string serialNumber)
50  {
51  for (RapidXmlReaderNode daqNode : rootNode.nodes("Daq"))
52  {
53  if (daqNode.attribute_value("serialNumber") == serialNumber)
54  {
55  return daqNode;
56  }
57  }
59  };
60 
61  offeringTopic(getProperty<std::string>("OptoForceTopicName").getValue());
62 
63  OPort* portlist = ports.listPorts(true);
64  ARMARX_INFO << "Found " << ports.getLastSize() << " Optoforce device(s).";
65 
66 
67  portlist = ports.listPorts(true);
68  ARMARX_INFO << "Found " << ports.getLastSize() << " Optoforce device(s):";
69 
70  for (int i = 0; i < ports.getLastSize(); i++)
71  {
72  std::string deviceName(portlist[i].name);
73  std::string serialNumber(portlist[i].serialNumber);
74  ARMARX_INFO << "Found DAQ: deviceName='" << deviceName << "', serialNumber='" << serialNumber << "'";
75  RapidXmlReaderNode daqNode = findDaqNode(serialNumber);
76  if (!daqNode.is_valid())
77  {
78  throw LocalException("Could not find config node for device deviceName='") << deviceName << "', serialNumber='" << serialNumber << "'";
79  }
80  DaqWrapperPtr daqPtr(new DaqWrapper(deviceName, serialNumber, daqNode));
81  daqList.push_back(daqPtr);
82  }
83 
84  ARMARX_INFO << "number of ports: " << ports.getLastSize();
85 
86  for (int i = 0; i < ports.getLastSize(); ++i)
87  {
88  const DaqWrapperPtr& daq = daqList.at(i);
89  ARMARX_IMPORTANT << "Opening port #" << i << " " << portlist[i].name;
90  daq->daq.open(portlist[i]);
91  daq->printInfo();
92  daq->checkSensorCount();
93  }
94 
95  readTask = new RunningTask<OptoForceUnit>(this, &OptoForceUnit::run, "OptoForceUnit");
96 
97 }
98 
99 
101 {
102  topicPrx = getTopic<OptoForceUnitListenerPrx>(getProperty<std::string>("OptoForceTopicName").getValue());
103  readTask->start();
104 }
105 
106 void OptoForceUnit::run()
107 {
108  ARMARX_IMPORTANT << "run";
109 
110 
111  OptoForceUnitListenerPrx batchPrx = topicPrx->ice_batchOneway();
112  ARMARX_IMPORTANT << "got batch Proxy";
113 
114  while (readTask->isRunning())
115  {
116  bool flushNeeded = false;
117 
118  for (const DaqWrapperPtr& daqPtr : daqList)
119  {
120  OptoPackage* pa = 0;
121  int size = daqPtr->daq.readAll(pa, false);
122  if (size == 0)
123  {
124  // size == 0: no new data for daq
125  continue;
126  }
127  if (size < 0)
128  {
129  // size == -1: buffer full
130  ARMARX_WARNING << "buffer full of daq " << daqPtr->deviceName;
131  }
132  if (daqPtr->daq.getSize() > 0)
133  {
134  IceUtil::Time now = IceUtil::Time::now();
135  TimestampVariantPtr nowTimestamp = new TimestampVariant(now);
136 
137  int sensorCount = daqPtr->daq.getSensorSize();
138 
139  std::vector<std::array<float, 3>> data;
140  data.resize(sensorCount);
141 
142  for (int i = 0; i < sensorCount; i++)
143  {
144  if (!daqPtr->enableFlags.at(i))
145  {
146  continue;
147  }
148  for (int n = 0; n < size; n++)
149  {
150  float countsPerN = daqPtr->countsPerN.at(i);
151  float x = pa[i * size + n].x / countsPerN - daqPtr->offsets.at(i).at(0);
152  float y = pa[i * size + n].y / countsPerN - daqPtr->offsets.at(i).at(1);
153  float z = pa[i * size + n].z / countsPerN - daqPtr->offsets.at(i).at(2);
154 
155  batchPrx->reportSensorValues(daqPtr->deviceName + ":" + to_string(i), daqPtr->sensorNames.at(i), x, y, z, nowTimestamp);
156  flushNeeded = true;
157  data.at(i) = {x, y, z};
158  }
159  }
160  delete[] pa;
161 
162  if (isRecording)
163  {
164  recordingFile << "{\"timestamp\":\"" << now.toDateTime() << "\",";
165  recordingFile << "\"daq\":\"" << daqPtr->serialNumber << "\",\"data\":[";
166  bool first = true;
167  for (int i = 0; i < sensorCount; i++)
168  {
169  if (!daqPtr->enableFlags.at(i))
170  {
171  continue;
172  }
173  if (!first)
174  {
175  recordingFile << ",";
176  }
177  first = false;
178  recordingFile << "[" << data.at(i).at(0) << "," << data.at(i).at(1) << "," << data.at(i).at(2) << "]";
179  }
180  recordingFile << "]}\n";
181  recordingFile.flush();
182  }
183 
184  }
185  }
186  if (isRecording && stopRecordingFlag)
187  {
188  recordingFile.close();
189  isRecording = false;
190  }
191  stopRecordingFlag = false;
192  if (flushNeeded)
193  {
194  batchPrx->ice_flushBatchRequests();
195  }
196  else
197  {
198  usleep(1000); // 1ms
199  }
200  }
201 }
202 
203 
205 {
206 
207 }
208 
209 
211 {
212  readTask->stop();
213 }
214 
216 {
219 }
220 
221 
222 
223 OptoForceUnit::DaqWrapper::DaqWrapper(const std::string& deviceName, const std::string& serialNumber, const RapidXmlReaderNode& daqNode)
224  : deviceName(deviceName), serialNumber(serialNumber)
225 {
226  int i = 0;
227  for (RapidXmlReaderNode sensorNode : daqNode.nodes("Sensor"))
228  {
229  float counts_at_nc = sensorNode.attribute_as_float("counts_at_nc");
230  float nominalCapacity = sensorNode.attribute_as_float("nominalCapacity");
231  std::string sensorName = sensorNode.attribute_value_or_default("name", serialNumber + "-" + to_string(i));
232  countsPerN.push_back(counts_at_nc / nominalCapacity);
233  sensorNames.push_back(sensorName);
234  enableFlags.push_back(sensorNode.attribute_as_optional_bool("enabled", "true", "false", true));
235  offsets.push_back({sensorNode.attribute_as_float("offsetX"), sensorNode.attribute_as_float("offsetY"), sensorNode.attribute_as_float("offsetZ")});
236  i++;
237  }
238 }
239 
240 void OptoForceUnit::DaqWrapper::printInfo()
241 {
242  SensorConfig config = daq.getConfig();
243  int state = config.getState();
244  int speed = config.getSpeed();
245  int filter = config.getFilter();
246  int mode = config.getMode();
247 
248  ARMARX_IMPORTANT_S << "device: " << deviceName << " serialNumber:" << serialNumber;
249  ARMARX_IMPORTANT_S << "state: " << state;
250  ARMARX_IMPORTANT_S << "speed: " << speed;
251  ARMARX_IMPORTANT_S << "filter: " << filter;
252  ARMARX_IMPORTANT_S << "mode: " << mode;
253  ARMARX_IMPORTANT_S << "getBytesPerRead: " << daq.getBytesPerRead();
254  ARMARX_IMPORTANT_S << "getSensorSize: " << daq.getSensorSize();
255  ARMARX_IMPORTANT_S << "getSize: " << daq.getSize();
256  ARMARX_IMPORTANT_S << "getVersion: " << daq.getVersion();
257 }
258 
259 void OptoForceUnit::DaqWrapper::checkSensorCount()
260 {
261  if ((int)countsPerN.size() != daq.getSensorSize())
262  {
263  throw LocalException("Sensor count mismatch. Configured: ") << ((int)countsPerN.size()) << " found: " << daq.getSensorSize();
264  }
265  ARMARX_INFO_S << "Configured: " << ((int)countsPerN.size()) << " found: " << daq.getSensorSize() << " sensors";
266 }
267 
268 
269 void armarx::OptoForceUnit::startRecording(const std::string& filepath, const Ice::Current&)
270 {
271  ARMARX_IMPORTANT << "start recording: " << filepath;
272  recordingFile.open(filepath);
273  isRecording = true;
274 }
275 
276 void armarx::OptoForceUnit::stopRecording(const Ice::Current&)
277 {
278  stopRecordingFlag = true;
279 }
armarx::RapidXmlReaderPtr
std::shared_ptr< RapidXmlReader > RapidXmlReaderPtr
Definition: RapidXmlReader.h:66
armarx::RapidXmlReader::FromFile
static RapidXmlReaderPtr FromFile(const std::string &path)
Definition: RapidXmlReader.h:497
ARMARX_IMPORTANT_S
#define ARMARX_IMPORTANT_S
Definition: Logging.h:203
armarx::OptoForceUnit::OptoForceUnit
OptoForceUnit()
Definition: OptoForceUnit.cpp:32
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::RapidXmlReaderNode::NullNode
static RapidXmlReaderNode NullNode()
Definition: RapidXmlReader.h:119
armarx::OptoForceUnit::onExitComponent
void onExitComponent() override
Definition: OptoForceUnit.cpp:210
armarx::TimestampVariant
Definition: TimestampVariant.h:54
armarx::OptoForceUnit::onConnectComponent
void onConnectComponent() override
Definition: OptoForceUnit.cpp:100
armarx::OptoForceUnit::onDisconnectComponent
void onDisconnectComponent() override
Definition: OptoForceUnit.cpp:204
armarx::RunningTask
Definition: ArmarXMultipleObjectsScheduler.h:35
StringHelpers.h
armarx::OptoForceUnit::stopRecording
void stopRecording(const Ice::Current &) override
Definition: OptoForceUnit.cpp:276
IceInternal::Handle< TimestampVariant >
armarx::OptoForceUnit::onInitComponent
void onInitComponent() override
Definition: OptoForceUnit.cpp:38
armarx::OptoForceUnit::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: OptoForceUnit.cpp:215
OptoForceUnit.h
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
TimestampVariant.h
armarx::RapidXmlReaderNode
Definition: RapidXmlReader.h:68
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::OptoForceUnitPropertyDefinitions
Definition: OptoForceUnit.h:38
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::ManagedIceObject::offeringTopic
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
Definition: ManagedIceObject.cpp:290
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::RapidXmlReaderNode::nodes
std::vector< RapidXmlReaderNode > nodes(const char *name=nullptr) const
Definition: RapidXmlReader.h:158
armarx::RapidXmlReaderNode::is_valid
bool is_valid() const
Definition: RapidXmlReader.h:392
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:195
armarx::ArmarXDataPath::getAbsolutePath
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
Definition: ArmarXDataPath.cpp:111
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:34
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::OptoForceUnit::startRecording
void startRecording(const std::string &filepath, const Ice::Current &) override
Definition: OptoForceUnit.cpp:269