<?xml version='1.0' encoding='UTF-8'?>
<root >
<tabbed_widget name= "Main Window" parent= "main_window" >
<Tab containers= "1" tab_name= "Lateral Plan Conformance" >
<Container >
<DockSplitter orientation= "-" count= "4" sizes= "0.250949;0.249051;0.250949;0.249051" >
<DockArea name= "desired vs actual lateral acceleration (closer means better conformance to plan)" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "1.858161" bottom= "-1.823407" right= "1138.891674" left= "0.000194" />
<limitY />
<curve name= "/controlsState/lateralControlState/torqueState/actualLateralAccel" color= "#1f77b4" />
<curve name= "/controlsState/lateralControlState/torqueState/desiredLateralAccel" color= "#d62728" />
</plot>
</DockArea>
<DockArea name= "desired vs actual lateral acceleration, road-roll factored out (closer means better conformance to plan)" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "2.749816" bottom= "-3.723091" right= "1138.891674" left= "0.000194" />
<limitY />
<curve name= "Actual lateral accel (roll compensated)" color= "#1ac938" />
<curve name= "Desired lateral accel (roll compensated)" color= "#ff7f0e" />
</plot>
</DockArea>
<DockArea name= "controller feed-forward vs actuator output (closer means controller prediction is more accurate)" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "1.978032" bottom= "-1.570956" right= "1138.891674" left= "0.000194" />
<limitY />
<curve name= "/carOutput/actuatorsOutput/torque" color= "#9467bd" >
<transform alias= "/carOutput/actuatorsOutput/torque[Scale/Offset]" name= "Scale/Offset" >
<options value_offset= "0" value_scale= "-1" time_offset= "0" />
</transform>
</curve>
<curve name= "/controlsState/lateralControlState/torqueState/f" color= "#1f77b4" />
<curve name= "/carState/steeringPressed" color= "#ff000f" />
</plot>
</DockArea>
<DockArea name= "vehicle speed" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "105.981304" bottom= "-2.709314" right= "1138.891674" left= "0.000194" />
<limitY />
<curve name= "carState.vEgo mph" color= "#d62728" />
<curve name= "carState.vEgo kmh" color= "#1ac938" />
<curve name= "/carState/vEgo" color= "#ff7f0e" />
</plot>
</DockArea>
</DockSplitter>
</Container>
</Tab>
<Tab containers= "1" tab_name= "Vehicle Dynamics" >
<Container >
<DockSplitter orientation= "-" count= "3" sizes= "0.334282;0.331437;0.334282" >
<DockArea name= "configured-initial vs online-learned steerRatio, set configured value to match learned" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "19.665784" bottom= "19.359553" right= "1138.816328" left= "0.000000" />
<limitY />
<curve name= "/carParams/steerRatio" color= "#1f77b4" />
<curve name= "/liveParameters/steerRatio" color= "#1ac938" />
</plot>
</DockArea>
<DockArea name= "configured-initial vs online-learned tireStiffnessRatio, set configured value to match learned" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "1.112210" bottom= "0.995631" right= "1138.816328" left= "0.000000" />
<limitY />
<curve name= "/carParams/tireStiffnessFactor" color= "#d62728" />
<curve name= "/liveParameters/stiffnessFactor" color= "#ff7f0e" />
</plot>
</DockArea>
<DockArea name= "live steering angle offsets for straight-ahead driving, large values here may indicate alignment problems" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "-1.081041" bottom= "-4.494133" right= "1138.816328" left= "0.000000" />
<limitY />
<curve name= "/liveParameters/angleOffsetAverageDeg" color= "#f14cc1" />
<curve name= "/liveParameters/angleOffsetDeg" color= "#9467bd" />
</plot>
</DockArea>
</DockSplitter>
</Container>
</Tab>
<Tab containers= "1" tab_name= "Actuator Performance" >
<Container >
<DockSplitter orientation= "-" count= "3" sizes= "0.333333;0.333333;0.333333" >
<DockArea name= "offline-calculated vs online-learned lateral accel scaling factor, accel obtained from 100% actuator output" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "1.216110" bottom= "0.539474" right= "1138.920072" left= "0.000000" />
<limitY />
<curve name= "/liveTorqueParameters/latAccelFactorFiltered" color= "#1f77b4" />
<curve name= "/liveTorqueParameters/latAccelFactorRaw" color= "#d62728" />
<curve name= "/carParams/lateralTuning/torque/latAccelFactor" color= "#1c9222" />
</plot>
</DockArea>
<DockArea name= "learned lateral accel offset, vehicle-specific compensation to obtain true zero lateral accel" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "-0.304367" bottom= "-0.418688" right= "1138.920072" left= "0.000000" />
<limitY />
<curve name= "/liveTorqueParameters/latAccelOffsetFiltered" color= "#1ac938" />
<curve name= "/liveTorqueParameters/latAccelOffsetRaw" color= "#ff7f0e" />
</plot>
</DockArea>
<DockArea name= "offline-calculated vs online-learned EPS friction factor, necessary to start moving the steering wheel" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "0.226389" bottom= "0.158050" right= "1138.920072" left= "0.000000" />
<limitY />
<curve name= "/liveTorqueParameters/frictionCoefficientFiltered" color= "#f14cc1" />
<curve name= "/liveTorqueParameters/frictionCoefficientRaw" color= "#9467bd" />
<curve name= "/carParams/lateralTuning/torque/friction" color= "#1c9222" />
</plot>
</DockArea>
</DockSplitter>
</Container>
</Tab>
<Tab containers= "1" tab_name= "Actuator Delay" >
<Container >
<DockSplitter orientation= "-" count= "3" sizes= "0.30441;0.358464;0.337127" >
<DockArea name= "actuator lag learning state, 0 = learning, 1 = learned/applying, 2 = invalid" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "1.025000" bottom= "-0.025000" right= "1138.749979" left= "0.000000" />
<limitY />
<curve name= "/liveDelay/status" color= "#ff7f0e" />
</plot>
</DockArea>
<DockArea name= "offline default vs online estimated steering actuator lag" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "0.419648" bottom= "0.318362" right= "1138.749979" left= "0.000000" />
<limitY />
<curve name= "/liveDelay/lateralDelay" color= "#1f77b4" />
<curve name= "/liveDelay/lateralDelayEstimate" color= "#d62728" />
<curve name= "opendbc default steering lag" color= "#1ac938" />
</plot>
</DockArea>
<DockArea name= "online estimated steering actuator lag, standard deviation" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "0.067320" bottom= "-0.001642" right= "1138.749979" left= "0.000000" />
<limitY />
<curve name= "/liveDelay/lateralDelayEstimateStd" color= "#f14cc1" />
</plot>
</DockArea>
</DockSplitter>
</Container>
</Tab>
<Tab containers= "1" tab_name= "Controls Performance" >
<Container >
<DockSplitter orientation= "-" count= "4" sizes= "0.265655;0.251898;0.245731;0.236717" >
<DockArea name= "rate-of-change limits on steering actuator (blue = original, green = rate-limited before CAN output)" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "1.050000" bottom= "-1.050000" right= "1138.891921" left= "0.000194" />
<limitY />
<curve name= "/carControl/actuators/torque" color= "#0c00f2" />
<curve name= "/carOutput/actuatorsOutput/torque" color= "#2cd63a" />
</plot>
</DockArea>
<DockArea name= "controller feed-forward vs actuator output (closer means controller prediction is more accurate)" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "1.978032" bottom= "-1.570956" right= "1138.891921" left= "0.000194" />
<limitY />
<curve name= "/carOutput/actuatorsOutput/torque" color= "#9467bd" >
<transform alias= "/carOutput/actuatorsOutput/torque[Scale/Offset]" name= "Scale/Offset" >
<options value_offset= "0" value_scale= "-1.0" time_offset= "0" />
</transform>
</curve>
<curve name= "/controlsState/lateralControlState/torqueState/f" color= "#1f77b4" />
<curve name= "/carState/steeringPressed" color= "#ff000f" />
</plot>
</DockArea>
<DockArea name= "proportional, integral, and feed-forward terms (actuator output = sum of PIF terms)" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "2.099784" bottom= "-4.027542" right= "1138.891921" left= "0.000194" />
<limitY />
<curve name= "/controlsState/lateralControlState/torqueState/f" color= "#0ab027" />
<curve name= "/controlsState/lateralControlState/torqueState/p" color= "#d62728" />
<curve name= "/controlsState/lateralControlState/torqueState/i" color= "#ffaf00" />
<curve name= "Zero" color= "#756a6a" />
</plot>
</DockArea>
<DockArea name= "road roll angle, from openpilot localizer" >
<plot flip_y= "false" style= "Lines" mode= "TimeSeries" flip_x= "false" >
<range top= "0.109446" bottom= "-0.045525" right= "1138.891921" left= "0.000194" />
<limitY />
<curve name= "/liveParameters/roll" color= "#f14cc1" />
</plot>
</DockArea>
</DockSplitter>
</Container>
</Tab>
<currentTabIndex index= "0" />
</tabbed_widget>
<use_relative_time_offset enabled= "1" />
<!-- - - - - - - - - - - - - - - -->
<!-- - - - - - - - - - - - - - - -->
<Plugins >
<plugin ID= "DataLoad CSV" >
<default delimiter= "0" time_axis= "" />
</plugin>
<plugin ID= "DataLoad Rlog" />
<plugin ID= "DataLoad ULog" />
<plugin ID= "Cereal Subscriber" />
<plugin ID= "UDP Server" />
<plugin ID= "ZMQ Subscriber" />
<plugin ID= "Fast Fourier Transform" />
<plugin ID= "Quaternion to RPY" />
<plugin ID= "Reactive Script Editor" >
<library code= "--[[ Helper function to create a series from arrays

 new_series: a series previously created with ScatterXY.new(name)
 prefix: prefix of the timeseries, before the index of the array
 suffix_X: suffix to complete the name of the series containing the X value. If [nil], use the index of the array.
 suffix_Y: suffix to complete the name of the series containing the Y value
 timestamp: usually the tracker_time variable
 
 Example:
 
 Assuming we have multiple series in the form:
 
 /trajectory/node.{X}/position/x
 /trajectory/node.{X}/position/y
 
 where {N} is the index of the array (integer). We can create a reactive series from the array with:
 
 new_series = ScatterXY.new("my_trajectory") 
 CreateSeriesFromArray( new_series, "/trajectory/node", "position/x", "position/y", tracker_time );
--]]

function CreateSeriesFromArray( new_series, prefix, suffix_X, suffix_Y, timestamp )
 
 --- clear previous values
 new_series:clear()
 
 --- Append points to new_series
 index = 0
 while(true) do

 x = index;
 -- if not nil, get the X coordinate from a series
 if suffix_X ~= nil then 
 series_x = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_X) )
 if series_x == nil then break end
 x = series_x:atTime(timestamp)	 
 end
 
 series_y = TimeseriesView.find( string.format( "%s.%d/%s", prefix, index, suffix_Y) )
 if series_y == nil then break end 
 y = series_y:atTime(timestamp)
 
 new_series:push_back(x,y)
 index = index+1
 end
end

--[[ Similar to the built-in function GetSeriesNames(), but select only the names with a give prefix. --]]

function GetSeriesNamesByPrefix(prefix)
 -- GetSeriesNames(9 is a built-in function
 all_names = GetSeriesNames()
 filtered_names = {}
 for i, name in ipairs(all_names) do
 -- check the prefix
 if name:find(prefix, 1, #prefix) then
 table.insert(filtered_names, name);
 end
 end
 return filtered_names
end

--[[ Modify an existing series, applying offsets to all their X and Y values

 series: an existing timeseries, obtained with TimeseriesView.find(name)
 delta_x: offset to apply to each x value
 delta_y: offset to apply to each y value 
 
--]]

function ApplyOffsetInPlace(series, delta_x, delta_y)
 -- use C++ indeces, not Lua indeces
 for index=0, series:size()-1 do
 x,y = series:at(index)
 series:set(index, x + delta_x, y + delta_y)
 end
end
" />
<scripts />
</plugin>
<plugin ID= "CSV Exporter" />
</Plugins>
<!-- - - - - - - - - - - - - - - -->
<!-- - - - - - - - - - - - - - - -->
<customMathEquations >
<snippet name= "carState.vEgo kmh" >
<global > </global>
<function > return value * 3.6</function>
<linked_source > /carState/vEgo</linked_source>
</snippet>
<snippet name= "carState.vEgo mph" >
<global > </global>
<function > return value * 2.23694</function>
<linked_source > /carState/vEgo</linked_source>
</snippet>
<snippet name= "Desired lateral accel (roll compensated)" >
<global > </global>
<function > return (value * v1 ^ 2) - (v2 * 9.81)</function>
<linked_source > /controlsState/desiredCurvature</linked_source>
<additional_sources >
<v1 > /carState/vEgo</v1>
<v2 > /liveParameters/roll</v2>
</additional_sources>
</snippet>
<snippet name= "Actual lateral accel (roll compensated)" >
<global > </global>
<function > return (value * v1 ^ 2) - (v2 * 9.81)</function>
<linked_source > /controlsState/curvature</linked_source>
<additional_sources >
<v1 > /carState/vEgo</v1>
<v2 > /liveParameters/roll</v2>
</additional_sources>
</snippet>
<snippet name= "opendbc default steering lag" >
<global > </global>
<function > return value + 0.2</function>
<linked_source > /carParams/steerActuatorDelay</linked_source>
</snippet>
<snippet name= "Zero" >
<global > </global>
<function > return (0)</function>
<linked_source > /carState/canValid</linked_source>
</snippet>
</customMathEquations>
<snippets />
<!-- - - - - - - - - - - - - - - -->
</root>