diff --git a/source/RobotAPI/gui-plugins/SensorActorWidgetsPlugin/ArmarXPlotter/ArmarXPlotter.cpp b/source/RobotAPI/gui-plugins/SensorActorWidgetsPlugin/ArmarXPlotter/ArmarXPlotter.cpp index 5c43f0c871bbe9ad621df9860d95a401b7fa74bb..0eb423190b4501404ff07f2554d68ede715ccc44 100644 --- a/source/RobotAPI/gui-plugins/SensorActorWidgetsPlugin/ArmarXPlotter/ArmarXPlotter.cpp +++ b/source/RobotAPI/gui-plugins/SensorActorWidgetsPlugin/ArmarXPlotter/ArmarXPlotter.cpp @@ -274,7 +274,7 @@ namespace armarx { logstream << "Timestamp"; - for (auto & channel : selectedChannels) + for (auto& channel : selectedChannels) { logstream << "," << channel.toStdString(); } @@ -334,7 +334,7 @@ namespace armarx ScopedLock lock(dataMutex); IceUtil::Time curTime = TimeUtil::GetTime(); // erase old markers - for (auto & markerChannel : markers) + for (auto& markerChannel : markers) { for (auto it = markerChannel.second.begin(); it != markerChannel.second.end();) { @@ -383,7 +383,7 @@ namespace armarx marker->setLineStyle(QwtPlotMarker::VLine); marker->setLabelAlignment(Qt::AlignBottom | Qt::AlignLeft); int i = 0; - for (auto & markerSubMap : markers) + for (auto& markerSubMap : markers) { if (markerSubMap.first == datafieldId) { @@ -623,7 +623,8 @@ namespace armarx { ScopedLock lock(dataMutex); - + auto now = TimeUtil::GetTime(); + std::map<std::string, ChannelHistory> histories; markers.clear(); for (int i = 0; i < selectedChannels.size(); i++) { @@ -633,6 +634,22 @@ namespace armarx DataFieldIdentifierPtr identifier = new DataFieldIdentifier(selectedChannels.at(i).toStdString()); auto prx = getProxy<ObserverInterfacePrx>(identifier->observerName); + + // get past data of that datafield + auto id = identifier->getIdentifierStr(); + auto historiesIt = histories.find(identifier->channelName); + + if (historiesIt == histories.end()) + { + auto start = IceUtil::Time::now(); + histories[identifier->channelName] = prx->getPartialChannelHistory(identifier->channelName, + (now - IceUtil::Time::seconds(shownInterval)).toMicroSeconds(), now.toMicroSeconds()); + ARMARX_DEBUG << "history data polling took : " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " got " << histories[identifier->channelName].size() << " entries"; + historiesIt = histories.find(identifier->channelName); + } + + long lastTimestamp = 0; + VariantPtr var = VariantPtr::dynamicCast(prx->getDataField(identifier)); auto type = var->getType(); if (type == VariantType::String) @@ -646,6 +663,15 @@ namespace armarx QwtThermo* bar = createBar(selectedChannels.at(i)); bars[selectedChannels.at(i).toStdString()] = bar; + + for (auto& entry : historiesIt->second) + { + if (lastTimestamp + pollingInterval < entry.first) + { + dataMap[id].push_back(TimeData(IceUtil::Time::microSeconds(entry.first), VariantPtr::dynamicCast(entry.second[identifier->datafieldName].value))); + lastTimestamp = entry.first; + } + } } else { @@ -674,7 +700,42 @@ namespace armarx bars[key] = bar; } } + for (auto& entry : historiesIt->second) + { + if (lastTimestamp + pollingInterval < entry.first) + { + auto dict = JSONObject::ConvertToBasicVariantMap(json, entry.second[identifier->datafieldName].value); + for (const auto& e : dict) + { + if (e.first == "timestamp") // TimedVariants always contain a timestamp field which is irrelevant + { + continue; + } + std::string key = id + "." + e.first; + // ARMARX_INFO << key << ": " << *VariantPtr::dynamicCast(e.second); + VariantPtr var = VariantPtr::dynamicCast(e.second); + auto type = var->getType(); + if (type == VariantType::String) + { + // complex contain additional strings often, which cannot be selected right now -> disable strings from complex types + // if (dataMap[id].size() == 0 || dataMap[id].rbegin()->data->getString() != var->getString()) + // { + // // only insert if changed + // dataMap[id].push_back(TimeData(time, var)); + // newData[key] = var; + // } + } + else + { + dataMap[key].push_back(TimeData(IceUtil::Time::microSeconds(entry.first), var)); + } + } + } + } + + } + } catch (...) { @@ -822,7 +883,7 @@ namespace armarx { auto dict = JSONObject::ConvertToBasicVariantMap(json, var); - for (const auto & e : dict) + for (const auto& e : dict) { if (e.first == "timestamp") // TimedVariants always contain a timestamp field which is irrelevant { @@ -885,7 +946,7 @@ namespace armarx { logstream << (time - logStartTime).toMilliSecondsDouble() << ","; - for (auto & channel : selectedChannels) + for (auto& channel : selectedChannels) { logstream << dataMaptoAppend.at(channel.toStdString())->Variant::getOutputValueOnly(); if (!selectedChannels.endsWith(channel)) diff --git a/source/RobotAPI/libraries/core/remoterobot/RobotStateObserver.h b/source/RobotAPI/libraries/core/remoterobot/RobotStateObserver.h index 2c4eae0066b81b1f61ca99cb9c2777254fb4a47d..972e9c15552660df4224dcf2b4a6449dec0c70dc 100644 --- a/source/RobotAPI/libraries/core/remoterobot/RobotStateObserver.h +++ b/source/RobotAPI/libraries/core/remoterobot/RobotStateObserver.h @@ -49,11 +49,11 @@ namespace armarx * RobotStatePropertyDefinition Property Definitions */ class RobotStateObserverPropertyDefinitions: - public ComponentPropertyDefinitions + public ObserverPropertyDefinitions { public: RobotStateObserverPropertyDefinitions(std::string prefix): - ComponentPropertyDefinitions(prefix) + ObserverPropertyDefinitions(prefix) { defineOptionalProperty<std::string>("TCPsToReport", "", "comma seperated list of nodesets' endeffectors, which poses and velocities that should be reported. * for all, empty for none"); }