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 OptoForceUnit::OptoForceUnit() : isRecording(false), stopRecordingFlag(false)
32 {
33 }
34 
35 void
37 {
38  std::string calibrationFilePath = getProperty<std::string>("CalibrationFilePath").getValue();
39  if (!ArmarXDataPath::getAbsolutePath(calibrationFilePath, calibrationFilePath))
40  {
41  throw LocalException("Could not find calibration file '") << calibrationFilePath << "'";
42  }
43  ARMARX_INFO << "reading config " << calibrationFilePath;
44  RapidXmlReaderPtr reader = RapidXmlReader::FromFile(calibrationFilePath);
45  RapidXmlReaderNode rootNode = reader->getRoot("Calibration");
46 
47  auto findDaqNode = [&](std::string serialNumber)
48  {
49  for (RapidXmlReaderNode daqNode : rootNode.nodes("Daq"))
50  {
51  if (daqNode.attribute_value("serialNumber") == serialNumber)
52  {
53  return daqNode;
54  }
55  }
57  };
58 
59  offeringTopic(getProperty<std::string>("OptoForceTopicName").getValue());
60 
61  OPort* portlist = ports.listPorts(true);
62  ARMARX_INFO << "Found " << ports.getLastSize() << " Optoforce device(s).";
63 
64 
65  portlist = ports.listPorts(true);
66  ARMARX_INFO << "Found " << ports.getLastSize() << " Optoforce device(s):";
67 
68  for (int i = 0; i < ports.getLastSize(); i++)
69  {
70  std::string deviceName(portlist[i].name);
71  std::string serialNumber(portlist[i].serialNumber);
72  ARMARX_INFO << "Found DAQ: deviceName='" << deviceName << "', serialNumber='"
73  << serialNumber << "'";
74  RapidXmlReaderNode daqNode = findDaqNode(serialNumber);
75  if (!daqNode.is_valid())
76  {
77  throw LocalException("Could not find config node for device deviceName='")
78  << 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 void
100 {
101  topicPrx = getTopic<OptoForceUnitListenerPrx>(
102  getProperty<std::string>("OptoForceTopicName").getValue());
103  readTask->start();
104 }
105 
106 void
107 OptoForceUnit::run()
108 {
109  ARMARX_IMPORTANT << "run";
110 
111 
112  OptoForceUnitListenerPrx batchPrx = topicPrx->ice_batchOneway();
113  ARMARX_IMPORTANT << "got batch Proxy";
114 
115  while (readTask->isRunning())
116  {
117  bool flushNeeded = false;
118 
119  for (const DaqWrapperPtr& daqPtr : daqList)
120  {
121  OptoPackage* pa = 0;
122  int size = daqPtr->daq.readAll(pa, false);
123  if (size == 0)
124  {
125  // size == 0: no new data for daq
126  continue;
127  }
128  if (size < 0)
129  {
130  // size == -1: buffer full
131  ARMARX_WARNING << "buffer full of daq " << daqPtr->deviceName;
132  }
133  if (daqPtr->daq.getSize() > 0)
134  {
135  IceUtil::Time now = IceUtil::Time::now();
136  TimestampVariantPtr nowTimestamp = new TimestampVariant(now);
137 
138  int sensorCount = daqPtr->daq.getSensorSize();
139 
140  std::vector<std::array<float, 3>> data;
141  data.resize(sensorCount);
142 
143  for (int i = 0; i < sensorCount; i++)
144  {
145  if (!daqPtr->enableFlags.at(i))
146  {
147  continue;
148  }
149  for (int n = 0; n < size; n++)
150  {
151  float countsPerN = daqPtr->countsPerN.at(i);
152  float x = pa[i * size + n].x / countsPerN - daqPtr->offsets.at(i).at(0);
153  float y = pa[i * size + n].y / countsPerN - daqPtr->offsets.at(i).at(1);
154  float z = pa[i * size + n].z / countsPerN - daqPtr->offsets.at(i).at(2);
155 
156  batchPrx->reportSensorValues(daqPtr->deviceName + ":" + to_string(i),
157  daqPtr->sensorNames.at(i),
158  x,
159  y,
160  z,
161  nowTimestamp);
162  flushNeeded = true;
163  data.at(i) = {x, y, z};
164  }
165  }
166  delete[] pa;
167 
168  if (isRecording)
169  {
170  recordingFile << "{\"timestamp\":\"" << now.toDateTime() << "\",";
171  recordingFile << "\"daq\":\"" << daqPtr->serialNumber << "\",\"data\":[";
172  bool first = true;
173  for (int i = 0; i < sensorCount; i++)
174  {
175  if (!daqPtr->enableFlags.at(i))
176  {
177  continue;
178  }
179  if (!first)
180  {
181  recordingFile << ",";
182  }
183  first = false;
184  recordingFile << "[" << data.at(i).at(0) << "," << data.at(i).at(1) << ","
185  << data.at(i).at(2) << "]";
186  }
187  recordingFile << "]}\n";
188  recordingFile.flush();
189  }
190  }
191  }
192  if (isRecording && stopRecordingFlag)
193  {
194  recordingFile.close();
195  isRecording = false;
196  }
197  stopRecordingFlag = false;
198  if (flushNeeded)
199  {
200  batchPrx->ice_flushBatchRequests();
201  }
202  else
203  {
204  usleep(1000); // 1ms
205  }
206  }
207 }
208 
209 void
211 {
212 }
213 
214 void
216 {
217  readTask->stop();
218 }
219 
222 {
225 }
226 
227 OptoForceUnit::DaqWrapper::DaqWrapper(const std::string& deviceName,
228  const std::string& serialNumber,
229  const RapidXmlReaderNode& daqNode) :
230  deviceName(deviceName), serialNumber(serialNumber)
231 {
232  int i = 0;
233  for (RapidXmlReaderNode sensorNode : daqNode.nodes("Sensor"))
234  {
235  float counts_at_nc = sensorNode.attribute_as_float("counts_at_nc");
236  float nominalCapacity = sensorNode.attribute_as_float("nominalCapacity");
237  std::string sensorName =
238  sensorNode.attribute_value_or_default("name", serialNumber + "-" + to_string(i));
239  countsPerN.push_back(counts_at_nc / nominalCapacity);
240  sensorNames.push_back(sensorName);
241  enableFlags.push_back(
242  sensorNode.attribute_as_optional_bool("enabled", "true", "false", true));
243  offsets.push_back({sensorNode.attribute_as_float("offsetX"),
244  sensorNode.attribute_as_float("offsetY"),
245  sensorNode.attribute_as_float("offsetZ")});
246  i++;
247  }
248 }
249 
250 void
251 OptoForceUnit::DaqWrapper::printInfo()
252 {
253  SensorConfig config = daq.getConfig();
254  int state = config.getState();
255  int speed = config.getSpeed();
256  int filter = config.getFilter();
257  int mode = config.getMode();
258 
259  ARMARX_IMPORTANT_S << "device: " << deviceName << " serialNumber:" << serialNumber;
260  ARMARX_IMPORTANT_S << "state: " << state;
261  ARMARX_IMPORTANT_S << "speed: " << speed;
262  ARMARX_IMPORTANT_S << "filter: " << filter;
263  ARMARX_IMPORTANT_S << "mode: " << mode;
264  ARMARX_IMPORTANT_S << "getBytesPerRead: " << daq.getBytesPerRead();
265  ARMARX_IMPORTANT_S << "getSensorSize: " << daq.getSensorSize();
266  ARMARX_IMPORTANT_S << "getSize: " << daq.getSize();
267  ARMARX_IMPORTANT_S << "getVersion: " << daq.getVersion();
268 }
269 
270 void
271 OptoForceUnit::DaqWrapper::checkSensorCount()
272 {
273  if ((int)countsPerN.size() != daq.getSensorSize())
274  {
275  throw LocalException("Sensor count mismatch. Configured: ")
276  << ((int)countsPerN.size()) << " found: " << daq.getSensorSize();
277  }
278  ARMARX_INFO_S << "Configured: " << ((int)countsPerN.size()) << " found: " << daq.getSensorSize()
279  << " sensors";
280 }
281 
282 void
283 armarx::OptoForceUnit::startRecording(const std::string& filepath, const Ice::Current&)
284 {
285  ARMARX_IMPORTANT << "start recording: " << filepath;
286  recordingFile.open(filepath);
287  isRecording = true;
288 }
289 
290 void
292 {
293  stopRecordingFlag = true;
294 }
armarx::RapidXmlReaderPtr
std::shared_ptr< RapidXmlReader > RapidXmlReaderPtr
Definition: RapidXmlReader.h:67
armarx::RapidXmlReader::FromFile
static RapidXmlReaderPtr FromFile(const std::string &path)
Definition: RapidXmlReader.h:573
ARMARX_IMPORTANT_S
#define ARMARX_IMPORTANT_S
Definition: Logging.h:210
armarx::OptoForceUnit::OptoForceUnit
OptoForceUnit()
Definition: OptoForceUnit.cpp:31
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::RapidXmlReaderNode::NullNode
static RapidXmlReaderNode NullNode()
Definition: RapidXmlReader.h:131
armarx::OptoForceUnit::onExitComponent
void onExitComponent() override
Definition: OptoForceUnit.cpp:215
armarx::TimestampVariant
Definition: TimestampVariant.h:54
armarx::OptoForceUnit::onConnectComponent
void onConnectComponent() override
Definition: OptoForceUnit.cpp:99
armarx::OptoForceUnit::onDisconnectComponent
void onDisconnectComponent() override
Definition: OptoForceUnit.cpp:210
armarx::RunningTask
Definition: ArmarXMultipleObjectsScheduler.h:36
StringHelpers.h
armarx::OptoForceUnit::stopRecording
void stopRecording(const Ice::Current &) override
Definition: OptoForceUnit.cpp:291
IceInternal::Handle< TimestampVariant >
armarx::OptoForceUnit::onInitComponent
void onInitComponent() override
Definition: OptoForceUnit.cpp:36
armarx::OptoForceUnit::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: OptoForceUnit.cpp:221
OptoForceUnit.h
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
TimestampVariant.h
armarx::RapidXmlReaderNode
Definition: RapidXmlReader.h:69
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:41
armarx::OptoForceUnitPropertyDefinitions
Definition: OptoForceUnit.h:40
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::ManagedIceObject::offeringTopic
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
Definition: ManagedIceObject.cpp:300
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::RapidXmlReaderNode::nodes
std::vector< RapidXmlReaderNode > nodes(const char *name=nullptr) const
Definition: RapidXmlReader.h:181
armarx::RapidXmlReaderNode::is_valid
bool is_valid() const
Definition: RapidXmlReader.h:457
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:202
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:109
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::OptoForceUnit::startRecording
void startRecording(const std::string &filepath, const Ice::Current &) override
Definition: OptoForceUnit.cpp:283