MATLAB - beste Weg, um dynamisch aktualisieren, a-line Griffe,' XData und YData?
Ich die Erhebung von Daten und Darstellung von Daten in Echtzeit. Die Daten werden produziert von einem motion capture system. Ich habe eine Klasse DynamicDataset
ist, dass nur ein wrapper um eine 2-Säulen-matrix (obwohl es differenzierter, als dass) mit einem event-notifier für neue Daten Hinzugefügt; eine andere Klasse DynamicPlotter
hört sich das für die Daten-Ereignis Hinzugefügt und aktualisiert den plot dynamisch. Entsprechenden code-Schnipsel:
classdef DynamicDataset < handle
properties
newestData = [];
data = []
end
events
DataAdded
end
methods
function append(obj, val)
obj.data(end+1,:) = val;
obj.newestData = val;
notify(obj, 'DataAdded');
end
end
end
classdef DynamicPlotter < dynamicprops
properties
FH %# figure handle
AH %# axes handle
LH %# array of line handles - may have multiple lines on the plot
dynProps = {} %# cell array of dynamic property names -
%# use to access individual datasets
end
methods
function obj = DynamicPlotter(props) %# props is a cell array of dynamic
%# properties to store information
for i = 1:length(props)
addprop(obj, props{i});
obj.(props{i}) = DynamicDataset;
obj.dynProps = [obj.dynProps props{i}];
addlistener(obj.(props{i}), 'DataAdded', @obj.updatePlot(i));
end
obj.createBlankPlot();
end
function createBlankPlot(obj)
obj.FH = figure;
obj.AH = axes;
hold all;
for i = 1:length(obj.dynProps)
obj.LH(i) = plot(nan); %# only used to produce a line handle
set(obj.LH(i), 'XData', [], 'YData', []);
end
end
function updatePlot(obj, propNum)
X = get(obj.LH(propNum), 'XData');
Y = get(obj.LH(propNum), 'YData');
X(end+1) = obj.(dynProps{propNum}).newestData(1);
Y(end+1) = obj.(dynProps{propNum}).newestData(2);
set(obj.LH(propNum), 'XData', X, 'YData', Y);
end
end
end
Basiert auf der MATLAB-Code Profil, die set
Befehl in updatePlot()
ist ziemlich teuer. Ich Frage mich, ob es nicht eine bessere Möglichkeit zum zeichnen einzelner Punkte, wie Sie kommen? Idealerweise würde ich push den einzigen Punkt in XData
und YData
und zeichnen Sie diesen Punkt nur, aber ich weiß nicht, ob dies möglich ist.
Bitte beachten Sie, dass es möglicherweise mehrere lineseries-Objekten (D. H., mehrere Graphen auf dem selben Grundstück); plot()
nimmt die axes-handle als argument, so wäre es nicht betrachten Sie die Eigenschaften der zuvor gezeichneten Linie Griffe (oder gibt es einen Weg, um es so zu tun?); Ich dachte nur das zu tun plot(x,y);hold all;
aber das würde mir separate line Griffe jedes mal, die jeweils einem einzigen Punkt.
Könnte es sein, dass es gibt keine Möglichkeit, Plotten eingehenden Punkte schneller, aber ich dachte, ich würde bitten.
BEARBEITEN: Aktualisierung der OP mit dem tatsächlichen code, mit dem ich arbeite, anstatt ein generisches Beispiel, das für eine Fehlinterpretation.
- Ich weiß nicht, ob Sie gesehen haben, diese aber werfen Sie einen Blick auf stackoverflow.com/questions/1693429/... . Im Prinzip mit Klassen in matlab führt in der Regel zu schlechte Leistung
- danke, habe ich gesehen, dass vor. Mein Projekt erfordert die Verwendung von Klassen aus Gründen, die ich erhalte nicht in, so gibt es keinen Weg vorbei.. würde aber den
set
rufen langsam sein, einfach, weil es heißt innerhalb einer Methode? - korrigieren Sie die addlistener Zeile wie:
addlistener(obj.(props{i}), 'DataAdded', @(src,ev) obj.updatePlot(i));
. Sie könnten auch will hinzufügendrawnow
am Ende derupdatePlot
Funktion - Hoppla, sollte
props
Fehler in der Transkription. Für das hinzufügen@(src,ev)
- wenn ich nicht verwenden, diese Argumente sind Sie wirklich benötigt, gibt es? Schließlich habe ichdrawnow
drin vor, aber das hat keinen Einfluss auf die EinstellungXData
undYData
gezeichnet.. - Darf ich Fragen, wie schlecht/langsam ist, ist es für Sie derzeit? auch in welchen Intervallen die Daten zu kommen, und für wie lange?
drawnow
nur Spülen, um alle Nachrichten in der Warteschlange Operationen.@(src,ev)
war nötig, sonst MATLAB warf einen Fehler. - beachten Sie auch die gesammelten Daten bekommt im Laufe der Zeit größer. Also, wenn Sie nicht haben, um ziehen Sie die ganze Sache von Anfang nach jedem Anhängen, es ist ein bisherige Lösung, die ich gepostet, die angepasst werden können, um Ihren Fall (OOP-Stil), in dem ich die Daten in eine sliding-window Art und Weise mit einem kreisförmigen Puffer...
- Ich habe 4
props
proDynamicPlotter
und zweiDynamicPlotter
Objekte für insgesamt 8 Linien gezeichnet werden, der auf zwei getrennten Diagrammen; ich wollte Daten bei 100Hz (d.h. Anfrage alle 10 ms). Ich mache das mit einemfor
Schleife und fügen Sie einfach[uptime sin(uptime)]
wouptime
ist eintoc
entsprechend einertic
zu Beginn der Schleife; bei der Schleife Ipause(1/100)
. Wenn ich den plot dieser fährt in 24 Sekunden, wenn ich das nicht Tue, wird es im 11. Nach der code-profiler, 67% der Zeit inset
; 33% fließen inpause()
. Ich wollte zu maximierenpause()
Zeit, im Grunde.. - schließlich bist du auf jeden Fall Recht, dass ich nicht brauchen, ziehen von Anfang an. Ich zeige im 30-Sekunden-Schnappschüsse jetzt - so Ihr Vorschlag wird sicherlich beschleunigen die Ausführung, wenn ich das sammeln von Daten über einen langen Zeitraum der Zeit, aber wird nicht helfen, im inneren, dass die Schwelle. Kann ich wohl einfach entsorgen Sie die alte
XData
undYData
da es gespeichert in derDynamicDataset
Objekt ohnehin.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Menge der Daten, die Sie Handhabung in jeder update, ist groß (wenn auch nur mit einem einzigen Punkt tatsächlich ändert), wodurch der code O(N^2).
Durch die Verwendung einer zweiten lineseries der Aufbau einer großen Gruppe von Daten, können Sie die Alternative zwischen hinzufügen jeden Punkt zu einer kurzen "aktiven" Zeile, und selten das hinzufügen von großen Blöcken zu den wichtigsten lineseries. Während dies nicht genau das vermeiden O(N^2), können Sie verringern Sie die Konstante signifikant.
Wenn Sie dies tun, denken Sie daran, überlappen sich die "alten" lineseries und "aktiv" lineseries durch einen Punkt, so dass Sie eine Verbindung herstellen.
Im wesentlichen:
Teil der Grund, warum Ihr code möglicherweise für eine lange Zeit zu laufen ist, weil man mit einer for-Schleife zuweisen Ihre Variablen. Je nachdem, welche version von Matlab, die Sie verwenden, das wird langsam Ihren Prozess deutlich nach. Ich schlage vor, mit Vektorisierung Werte zuweisen Ihre x-und y so:
Können Sie dann zuordnen der ersten Punkte in Ihre Daten.
Wenn Sie zeichnen, weisen die XDataSource und YDataSource.
Wenn du nun in einer Schleife durch um die Werte zu ändern, verwenden Sie die refreshdata zu aktualisieren, die Xdata-und Ydata-Werte. Verwenden Sie die drawnow Funktion zum aktualisieren der Abbildung Fenster.
Dein code ist sehr langsam, weil Sie replotting alle Werte jedes mal, die Sie aufrufen updatePlot. Daher würde ich nur plot der neueste Punkt in updatePlot (Das ist auch das problem, dass Sie erklärt habe: Idealerweise würde ich push den einzigen Punkt in XData und YData, und zeichnen Sie diesen Punkt nur, aber ich weiß nicht, ob dies möglich ist.)
Eigenschaft hinzufügen LH_point_counter
ändern updatePlot