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