2017-05-02 1 views
1

Ich Plotte Echtzeitdaten in Matlab (über eine serielle Schnittstelle empfangen werden), und ich fand eine merkwürdige Art und Weise die Bildwiederholfrequenz zu beeinflussen: die Größe der Veränderung Handlung. Wenn der Plot "normal" ist, wird er ~ 35 fps bekommen, und wenn ich ihn verkleinere, wird er über 120 fps gehen. Wenn ich jedoch das exakt gleiche Plot-Setup verwende, aber nur zufällig erzeugte Plot-Daten für jede Schleife, wird die Aktualisierungsrate von der Plotgröße nicht beeinflusst. Leider nicht in der Lage ist, Profil-Viewer (2017a) in den Plotten, um zu sehen, und nur Attribute alle der Wartezeit an die serielle Schnittstelle - was nicht möglich ist, da die variable Bildwiederholfrequenz oben beschrieben (auch habe ich ein nackte getestet - Serielle Aufrufe und Antworten von "bones" und der Roundtrip für Matlab liegt unter 8ms (~ 120fps).Echtzeit Matlab Plot Bildwiederholfrequenz wird von Grundstück betroffen

Die beiden Loop-Beispiele sollen nicht die gleiche Framerate erhalten, sie sollen lediglich zeigen, dass wenn man die Plotgröße ändert (einfach eine Ecke manuell nehmen und anpassen oder den Positionsparameter verwenden), das erste Beispiel (seriell) ist sehr von der Größe betroffen, und das zweite Beispiel (Zufall) ist nicht betroffen.

Zusatz:

Nachdem er mit einer modifizierten Version davon zu spielen, wo die Handlung durch einen Timer-Rückruf aktualisiert wird, sehe ich, dass ich entweder die serielle Schleife schnell machen kann (~ 170Hz) oder die Handlung aktualisieren schnell (~ 170Hz). Der andere leidet jedoch immer. Und wenn ich die Timer-Periode iterativ ändere, um die gleiche Aktualisierungsrate für beide zu erhalten, ist es nicht überraschend, dass es fast genau dieselbe Rate ist, wie ich sie mit der unten gezeigten Schleife bekomme. Es wäre schön, das Plot-Update in einen separaten Thread zu schreiben, ohne durch die Ringe zu springen, einen separaten Matlab-Prozess aufzurufen und zwischen den beiden zu kommunizieren.

Plot Setup:

figure_h = figure(); 
set(figure_h, 'KeyPressFcn', @key_press_function); 
set(figure_h, 'WindowButtonDownFcn', {@click_callback, obj}) 

%some random things that drastically speed up the plotting 
set(figure_h, 'Position', [100, 100, 350, 350]); %the size has a huge effect on performance 
set(figure_h, 'MenuBar', 'none'); 
set(figure_h, 'GraphicsSmoothing', 'Off'); 
set(figure_h, 'DockControls', 'Off'); 
set(figure_h, 'NumberTitle', 'Off'); 
set(figure_h, 'ToolBar', 'none'); 

%create plots 
scatter_h = plot(number_array(:,1)*scale, number_array(:,2)*scale, 'r.'); 
set(scatter_h, 'MarkerSize',8); 
set(scatter_h, 'Clipping','off'); 
hold on 
axis square 
grid on 
ylim([min_value, max_value*scale]); 
xlim([min_value, max_value*scale]); 
set(figure_h.CurrentAxes, 'xtick', [min_value:max_value/10:max_value]); %#ok<NBRAK> 
set(figure_h.CurrentAxes, 'ytick', [min_value:max_value/10:max_value]); %#ok<NBRAK> 
set(figure_h.CurrentAxes, 'XTickLabel',[]); 
set(figure_h.CurrentAxes, 'YTickLabel',[]); 
set(figure_h.CurrentAxes, 'ZTickLabel',[]); 
set(figure_h.CurrentAxes, 'ZGrid', 'off'); 
set(figure_h.CurrentAxes, 'XLimMode', 'manual'); 
set(figure_h.CurrentAxes, 'YLimMode', 'manual'); 
set(figure_h.CurrentAxes, 'ZLimMode', 'manual'); 
set(figure_h.CurrentAxes, 'ALimMode', 'manual'); 
set(figure_h.CurrentAxes, 'CLimMode', 'manual'); 
set(figure_h.CurrentAxes, 'DataAspectRatioMode', 'manual'); 
set(figure_h.CurrentAxes, 'CameraPositionMode', 'manual'); 
set(figure_h.CurrentAxes, 'CameraPosition', [max_value/2,max_value/2,1]); 
set(figure_h.CurrentAxes, 'CameraTargetMode', 'manual'); 
set(figure_h.CurrentAxes, 'CameraTarget', [max_value/2,max_value/2,0]); 
set(figure_h.CurrentAxes, 'CameraUpVectorMode', 'manual'); 
set(figure_h.CurrentAxes, 'CameraUpVector', [0,1,0]); 
set(figure_h.CurrentAxes, 'CameraViewAngleMode', 'manual'); 
set(figure_h.CurrentAxes, 'CameraViewAngle', 180); 
set(figure_h.CurrentAxes, 'GridAlphaMode', 'manual'); 
set(figure_h.CurrentAxes, 'Clipping', 'off'); 
circle_h = line((radius*cos(theta) + center_x)*scale,(radius*sin(theta) + center_y)*scale); 
hold off 

Vereinfachte Schleife für serielle:

while keep_running 

    %must wait for next packet to arrive 
    bytes = obj.bytes_available; 
    while keep_running && (bytes == 0) 
     bytes = obj.bytes_available; //function call actually directly uses the java serial objects for speed   
    end 

    %send request for next packet 
    obj.send_command(obj.cmd_id.cmd_history, true); //sends synchronously, otherwise, with async, an additional wait loop is necessary to prevent an async call if serial is still transmitting (Matlab throws an error otherwise - why they can't be queued, I don't know) 

    %grab the available buffer 
    new_buffer = obj.buffer_available(bytes); 

    %append new characters to running buffer 
    char_buffer = strcat(char_buffer, new_buffer); 

    %process buffer for all arrays 
    while (~isempty(strfind(char_buffer, '[')) && ~isempty(strfind(char_buffer, ']'))) %#ok<STREMP> 

     %extract a number array 
     [number_array, char_buffer] = extract_hex_array(char_buffer,3,2); 

     if ~isempty(number_array) 
      %remove any duplicate points 
      number_array = unique(number_array, 'rows', 'stable'); 

      frames = frames + 1; 

      %update data 
      set(scatter_h, 'xdata', number_array(:,1)*scale, 'ydata', number_array(:,2)*scale); 

      %update header information (after stabilization, and every 10 frames) 
      if frames > 25 && mod(frames, 10) == 0 
       avg_framerate = frames/toc(total_time); 
       set(figure_h, 'Name', strcat('rate: ', num2str(avg_framerate, '%.1f'), ' Hz buffer: ',num2str(length(char_buffer), '%05d'))); 
      end 

      %just a small delay, but not too small the callbacks stop working 
      pause(0.005); 
     end 
    end 
end 

Dummy Zufallsdatenschleife:

start_tic = tic; 
for i=1:200 
    array1 = 4095*rand(82,2); 
    set(scatter_h, 'xdata', array1(:,1), 'ydata', array1(:,2)); 
    pause(0.005); 
end 
end_tic = toc(start_tic); 
fprintf("fps: %f\n", i/end_tic); 
+0

Nur ein Hinweis auf die Eigenschaften einstellen. Sie können mehrere Eigenschaften in 'set' Funktion einstellen, besonders wenn ihre Werte gleich sind: ' set (figure_h.CurrentAxes, {'XLimMode', 'YLimMode', 'ZLimMode', ... ' ' 'ALimMode ',' CLimMode ',' DataAspectRatioMode ',' CameraPositionMode ', ...' '' CameraTargetMode ',' CameraViewAngleMode ',' CameraViewAngleMode ',' ' ' 'GridAlphaMode'}, repmat ({'manual'} , 1,11)). ' – Anthony

Antwort

0

Nach einer Dienstanforderung mit Mathworks einreichen, die offizielle Antwort ist, dass Matlab 2017a und vorher OpenGL auf Mac nicht benutzen (obwohl der "opengl info" Befehl sa ist) es wird unterstützt). Daher wird das Plotten auf Mac OS nicht so schnell wie Windows, bis sie ihre Plot-Bibliotheken reparieren.

Verwandte Themen