From bd01ea3f7848c9032b9c28c2de2aa57fba242317 Mon Sep 17 00:00:00 2001 From: Fisch Date: Thu, 13 May 2021 14:34:44 +0200 Subject: [PATCH] add timeline --- logdata_visualization/Timeline.pde | 168 ++++++++++++++++++ logdata_visualization/Visualization.pde | 2 + .../logdata_visualization.pde | 97 +++++++--- 3 files changed, 244 insertions(+), 23 deletions(-) create mode 100644 logdata_visualization/Timeline.pde diff --git a/logdata_visualization/Timeline.pde b/logdata_visualization/Timeline.pde new file mode 100644 index 0000000..06c3a03 --- /dev/null +++ b/logdata_visualization/Timeline.pde @@ -0,0 +1,168 @@ + +public class Timeline +{ + PVector posOrigin; + PVector size; + + int textsize=12; + + color cborder = color(200,200,200); + color ctimeslider = color(255,255,255); + + private float time_start; //in seconds + private float time_end; + + float[] preview_cmd; + float[] preview_throttle; + float[] preview_brake; + float[] preview_currentAll; + + public Timeline(int px, int py, int pw, int ph) { + this.posOrigin= new PVector(px,py); //lower left corner + this.size = new PVector(pw,ph); //to the right and up + + preview_cmd=new float[(int)this.size.x]; + preview_throttle=new float[(int)this.size.x]; + preview_brake=new float[(int)this.size.x]; + preview_currentAll=new float[(int)this.size.x]; + } + + + + public void generatePreview(Table logdata) { + int cID=0; //current ID for generating preview in datalog + for (int x=0;x (logdata.getRow(cID+1).getFloat("time")))) { //while starttime not reached + cID++; //next + } + int preview_mean_counter=0; + float preview_mean_cmd=0; + float preview_mean_brake=0; + float preview_mean_throttle=0; + float preview_mean_currentAll=0; + + + while ((cID+1 < logdata.getRowCount()) && ( t2 > (logdata.getRow(cID+1).getFloat("time")))) { //while endtime not reached + TableRow row = logdata.getRow(cID); + nextTimeData=(long)(logdata.getRow(cID+1).getFloat("time")*1000); //get time and convert from seconds to ms + + lastTimeMillis=nextTimeMillis; + + + preview_mean_cmd += (row.getInt("cmd_FrontL")+row.getInt("cmd_FrontR")+row.getInt("cmd_RearL")+row.getInt("cmd_RearR"))/4.0; + preview_mean_brake += row.getInt("brake"); + preview_mean_throttle += row.getInt("throttle"); + preview_mean_currentAll += row.getFloat("currentAll"); + /* + current_FrontL=row.getFloat("current_FrontL"); + current_FrontR=row.getFloat("current_FrontR"); + current_RearL=row.getFloat("current_RearL"); + current_RearR=row.getFloat("current_RearR"); + speed_FrontL=row.getInt("speed_FrontL"); + speed_FrontR=row.getInt("speed_FrontR"); + speed_RearL=row.getInt("speed_RearL"); + speed_RearR=row.getInt("speed_RearR"); + temp_Front=row.getFloat("temp_Front"); + temp_Rear=row.getFloat("temp_Rear"); + vbat_Front=row.getFloat("vbat_Front"); + vbat_Rear=row.getFloat("vbat_Rear"); + currentAll=row.getFloat("currentAll"); + throttle=row.getInt("throttle"); + brake=row.getInt("brake");*/ + + preview_mean_counter++; + + cID++; //next + } + preview_mean_cmd/=preview_mean_counter; + preview_mean_brake/=preview_mean_counter; + preview_mean_throttle/=preview_mean_counter; + preview_mean_currentAll/=preview_mean_counter; + + + + preview_cmd[x]=preview_mean_cmd; + preview_brake[x]=preview_mean_brake; + preview_throttle[x]=preview_mean_throttle; + preview_currentAll[x]=preview_mean_currentAll; + }//next pixel + + } + + public void setTimes(float _start,float _end) { + this.time_start=_start; + this.time_end=_end; + } + + + public void drawTL(float _time) { + //Preview visualization + for (int x=0;x=this.posOrigin.x && mx <=this.posOrigin.x+this.size.x && my>=this.posOrigin.y && my<=this.posOrigin.y+this.size.y) { //mouse whithin timeline boarder + float mousetime=xPosToTimeSeconds((int)(mx-this.posOrigin.x)); + //float mousetimesliderpercent=(mx-this.posOrigin.x)/this.size.x; + //float mousetime=mousetimesliderpercent*(this.time_end-this.time_start)+this.time_start; + return millis()/1000.0-mousetime; + } + return 0; + } + + private int timeSecondsToXPos(float _time) { + float timesliderpercent = (_time-this.time_start)/(this.time_end-this.time_start); //0<= x <=1 + return (int)(timesliderpercent*this.size.x); + } + + private float xPosToTimeSeconds(int _x) { + float mousetimesliderpercent=_x/this.size.x; + return mousetimesliderpercent*(this.time_end-this.time_start)+this.time_start; + } +} diff --git a/logdata_visualization/Visualization.pde b/logdata_visualization/Visualization.pde index 9dd71a1..e72daa7 100644 --- a/logdata_visualization/Visualization.pde +++ b/logdata_visualization/Visualization.pde @@ -17,6 +17,8 @@ abstract class Visualization boolean showMinMax=false; //default colors (not all used by every implementation) + + color cmain = color(255,255,255); color cmain2 = color(255,255,255); color cscale = color(100,100,100); diff --git a/logdata_visualization/logdata_visualization.pde b/logdata_visualization/logdata_visualization.pde index 226ef07..9ae3e82 100644 --- a/logdata_visualization/logdata_visualization.pde +++ b/logdata_visualization/logdata_visualization.pde @@ -12,6 +12,10 @@ Serial serial; String serialString=""; //last read string int serial_endchar=10; //10=ASCII Linefeed +//timeline +float logdata_start_time=0; +float logdata_end_time=0; + Visualization vis_cmd_FrontL; Visualization vis_cmd_FrontR; Visualization vis_cmd_RearL; @@ -41,8 +45,9 @@ Visualization vis_graph_speed_mean; Visualization vis_c_graph_receivedelay; - - +boolean showTimeline=!useSerial; +Timeline tl; +int timeoffset=0; //for moving timeslider Table logdata; @@ -52,6 +57,8 @@ long nextTimeData=0; //time of nextID row long lastTimeMillis=0; //local time long nextTimeMillis=0; //local time +boolean newdataforced=false; + int dataErrorCount=0; //Data from log @@ -78,8 +85,8 @@ int brake; color bg=color(0); void setup() { - size(1920, 1080); - //size(1000, 800); + //size(1920, 1080); + size(1000, 800); frameRate(100); if (useSerial) { @@ -96,8 +103,9 @@ void setup() { serialString = null; }else{ logdata = loadTable(logfile_name, "header, csv"); - - println("loaded "+logdata.getRowCount()+" lines. Times: "+logdata.getRow(0).getFloat("time")+"s to "+logdata.getRow(logdata.getRowCount()-1).getFloat("time")+"s"); + logdata_start_time=logdata.getRow(0).getFloat("time"); + logdata_end_time = logdata.getRow(logdata.getRowCount()-1).getFloat("time"); + println("loaded "+logdata.getRowCount()+" lines. Times: "+logdata_start_time+"s to "+logdata_end_time+"s"); } PVector pos_vis_cmd = new PVector(100,200); @@ -211,11 +219,16 @@ void setup() { + if (showTimeline) { + tl = new Timeline(30,height-30, width-30*2, 28); + tl.setTimes(logdata_start_time,logdata_end_time); + tl.generatePreview(logdata); + } } void draw() { - long loopmillis=millis(); + long loopmillis=millis()-timeoffset; if (useSerial) { if (serial.available() > 0) { @@ -257,21 +270,24 @@ void draw() { } } }else{ - while (loopmillis>=nextTimeData && nextID+1=nextTimeData && nextID+1 0)) { //valid row + TableRow row = logdata.getRow(nextID); + + lastTimeData=nextTimeData; + nextTimeData=(long)(logdata.getRow(nextID+1).getFloat("time")*1000); //get time and convert from seconds to ms + + lastTimeMillis=nextTimeMillis; + nextTimeMillis=loopmillis; + + cmd_FrontL=row.getInt("cmd_FrontL"); + cmd_FrontR=row.getInt("cmd_FrontR"); + cmd_RearL=row.getInt("cmd_RearL"); + cmd_RearR=row.getInt("cmd_RearR"); + current_FrontL=row.getFloat("current_FrontL"); + current_FrontR=row.getFloat("current_FrontR"); + current_RearL=row.getFloat("current_RearL"); current_RearR=row.getFloat("current_RearR"); speed_FrontL=row.getInt("speed_FrontL"); speed_FrontR=row.getInt("speed_FrontR"); @@ -290,7 +306,7 @@ void draw() { nextID+=(loopmillis-nextTimeData)/_timestep* 0.9; //fast forward estimated time steps } nextID++; - nextID=nextID%logdata.getRowCount(); + } } } @@ -363,4 +379,39 @@ void draw() { text(""+(dataErrorCount)+" errors", 5+70*3,12); + if(showTimeline) { + tl.drawTL(loopmillis/1000.0); + } + + + +} + +void mouseClicked() +{ + if (showTimeline) + { + int temp_timeoffset=(int)(tl.checkMouse(mouseX,mouseY)*1000); + if (temp_timeoffset!=0) { + + if (!(nextID+1 < logdata.getRowCount()) && (nextID >= 0)) { //nextID not valid + nextID=0; //rest to good value + } + + print("Jump nextID from "+nextID); + //find nextID to jump to + while ((nextID+1 < logdata.getRowCount()) && (nextID >= 0) && (millis()-temp_timeoffset > (long)(logdata.getRow(nextID+1).getFloat("time")*1000))) { //jumped forward + nextID++; + } + print(" over "+nextID); + while ((nextID+1 < logdata.getRowCount()) && (nextID >= 0) && (millis()-temp_timeoffset < (long)(logdata.getRow(nextID+1).getFloat("time")*1000))) { //jumped backward + nextID--; + } + println(" to "+nextID); + + timeoffset=temp_timeoffset; + newdataforced=true; //force read line for nextID + + } + } }