12ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown#!/usr/bin/env python2.6 22ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 32ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Copyright (C) 2011 The Android Open Source Project 42ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 52ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Licensed under the Apache License, Version 2.0 (the "License"); 62ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# you may not use this file except in compliance with the License. 72ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# You may obtain a copy of the License at 82ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 92ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# http://www.apache.org/licenses/LICENSE-2.0 102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Unless required by applicable law or agreed to in writing, software 122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# distributed under the License is distributed on an "AS IS" BASIS, 132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 142ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# See the License for the specific language governing permissions and 152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# limitations under the License. 162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 172ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 182ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 192ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Plots debug log output from VelocityTracker. 202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Enable DEBUG_VELOCITY to print the output. 212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 222ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# This code supports side-by-side comparison of two algorithms. 232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# The old algorithm should be modified to emit debug log messages containing 242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# the word "OLD". 252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# 262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport numpy as np 282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport matplotlib.pyplot as plot 292ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport subprocess 302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport re 312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport fcntl 322ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport os 332ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport errno 342ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownimport bisect 352ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownfrom datetime import datetime, timedelta 362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 372ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Parameters. 382ed2462aa29c564f5231f317c27b3188da875e52Jeff Browntimespan = 15 # seconds total span shown 392ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownscrolljump = 5 # seconds jump when scrolling 402ed2462aa29c564f5231f317c27b3188da875e52Jeff Browntimeticks = 1 # seconds between each time tick 412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 422ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Non-blocking stream wrapper. 432ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownclass NonBlockingStream: 442ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def __init__(self, stream): 452ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown fcntl.fcntl(stream, fcntl.F_SETFL, os.O_NONBLOCK) 462ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.stream = stream 472ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.buffer = '' 482ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.pos = 0 492ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 502ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def readline(self): 512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown while True: 522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown index = self.buffer.find('\n', self.pos) 532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if index != -1: 542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown result = self.buffer[self.pos:index] 552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.pos = index + 1 562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return result 572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.buffer = self.buffer[self.pos:] 592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.pos = 0 602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown try: 612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown chunk = os.read(self.stream.fileno(), 4096) 622ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown except OSError, e: 632ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if e.errno == errno.EAGAIN: 642ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return None 652ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown raise e 662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if len(chunk) == 0: 672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if len(self.buffer) == 0: 682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown raise(EOFError) 692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown else: 702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown result = self.buffer 712ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.buffer = '' 722ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.pos = 0 732ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return result 742ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.buffer += chunk 752ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 762ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Plotter 772ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownclass Plotter: 782ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def __init__(self, adbout): 792ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.adbout = adbout 802ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 812ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.fig = plot.figure(1) 822ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.fig.suptitle('Velocity Tracker', fontsize=12) 832ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.fig.set_dpi(96) 842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.fig.set_size_inches(16, 12, forward=True) 852ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 862ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_x = self._make_timeseries() 872ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_y = self._make_timeseries() 882ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_magnitude = self._make_timeseries() 892ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_axes = self._add_timeseries_axes( 902ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1, 'Velocity', 'px/s', [-5000, 5000], 912ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown yticks=range(-5000, 5000, 1000)) 922ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_line_x = self._add_timeseries_line( 932ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_axes, 'vx', 'red') 942ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_line_y = self._add_timeseries_line( 952ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_axes, 'vy', 'green') 962ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_line_magnitude = self._add_timeseries_line( 972ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_axes, 'magnitude', 'blue') 982ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._add_timeseries_legend(self.velocity_axes) 992ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1002ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown shared_axis = self.velocity_axes 1012ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_x = self._make_timeseries() 1032ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_y = self._make_timeseries() 1042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_magnitude = self._make_timeseries() 1052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_axes = self._add_timeseries_axes( 1062ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2, 'Old Algorithm Velocity', 'px/s', [-5000, 5000], 1072ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown sharex=shared_axis, 1082ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown yticks=range(-5000, 5000, 1000)) 1092ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_line_x = self._add_timeseries_line( 1102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_axes, 'vx', 'red') 1112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_line_y = self._add_timeseries_line( 1122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_axes, 'vy', 'green') 1132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_line_magnitude = self._add_timeseries_line( 1142ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_axes, 'magnitude', 'blue') 1152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._add_timeseries_legend(self.old_velocity_axes) 1162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1172ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.timer = self.fig.canvas.new_timer(interval=100) 1182ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.timer.add_callback(lambda: self.update()) 1192ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.timer.start() 1202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.timebase = None 1222ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._reset_parse_state() 1232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Initialize a time series. 1252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _make_timeseries(self): 1262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return [[], []] 1272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Add a subplot to the figure for a time series. 1292ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _add_timeseries_axes(self, index, title, ylabel, ylim, yticks, sharex=None): 1302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown num_graphs = 2 1312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown height = 0.9 / num_graphs 1322ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown top = 0.95 - height * index 1332ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes = self.fig.add_axes([0.1, top, 0.8, height], 1342ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown xscale='linear', 1352ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown xlim=[0, timespan], 1362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown ylabel=ylabel, 1372ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown yscale='linear', 1382ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown ylim=ylim, 1392ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown sharex=sharex) 1402ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes.text(0.02, 0.02, title, transform=axes.transAxes, fontsize=10, fontweight='bold') 1412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes.set_xlabel('time (s)', fontsize=10, fontweight='bold') 1422ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes.set_ylabel(ylabel, fontsize=10, fontweight='bold') 1432ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes.set_xticks(range(0, timespan + 1, timeticks)) 1442ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes.set_yticks(yticks) 1452ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes.grid(True) 1462ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1472ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown for label in axes.get_xticklabels(): 1482ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown label.set_fontsize(9) 1492ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown for label in axes.get_yticklabels(): 1502ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown label.set_fontsize(9) 1512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return axes 1532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Add a line to the axes for a time series. 1552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _add_timeseries_line(self, axes, label, color, linewidth=1): 1562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return axes.plot([], label=label, color=color, linewidth=linewidth)[0] 1572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Add a legend to a time series. 1592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _add_timeseries_legend(self, axes): 1602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown axes.legend( 1612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown loc='upper left', 1622ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown bbox_to_anchor=(1.01, 1), 1632ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown borderpad=0.1, 1642ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown borderaxespad=0.1, 1652ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown prop={'size': 10}) 1662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Resets the parse state. 1682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _reset_parse_state(self): 1692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_velocity_x = None 1702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_velocity_y = None 1712ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_velocity_magnitude = None 1722ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_old_velocity_x = None 1732ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_old_velocity_y = None 1742ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_old_velocity_magnitude = None 1752ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1762ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Update samples. 1772ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def update(self): 1782ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown timeindex = 0 1792ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown while True: 1802ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown try: 1812ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown line = self.adbout.readline() 1822ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown except EOFError: 1832ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown plot.close() 1842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return 1852ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if line is None: 1862ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown break 1872ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown print line 1882ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1892ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown try: 1902ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown timestamp = self._parse_timestamp(line) 1912ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown except ValueError, e: 1922ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown continue 1932ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if self.timebase is None: 1942ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.timebase = timestamp 1952ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown delta = timestamp - self.timebase 1962ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown timeindex = delta.seconds + delta.microseconds * 0.000001 1972ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 1982ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if line.find(': position') != -1: 1992ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_velocity_x = self._get_following_number(line, 'vx=') 2002ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_velocity_y = self._get_following_number(line, 'vy=') 2012ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_velocity_magnitude = self._get_following_number(line, 'speed=') 2022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._append(self.velocity_x, timeindex, self.parse_velocity_x) 2032ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._append(self.velocity_y, timeindex, self.parse_velocity_y) 2042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._append(self.velocity_magnitude, timeindex, self.parse_velocity_magnitude) 2052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2062ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if line.find(': OLD') != -1: 2072ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_old_velocity_x = self._get_following_number(line, 'vx=') 2082ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_old_velocity_y = self._get_following_number(line, 'vy=') 2092ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.parse_old_velocity_magnitude = self._get_following_number(line, 'speed=') 2102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._append(self.old_velocity_x, timeindex, self.parse_old_velocity_x) 2112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._append(self.old_velocity_y, timeindex, self.parse_old_velocity_y) 2122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._append(self.old_velocity_magnitude, timeindex, self.parse_old_velocity_magnitude) 2132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2142ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Scroll the plots. 2152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if timeindex > timespan: 2162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown bottom = int(timeindex) - timespan + scrolljump 2172ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.timebase += timedelta(seconds=bottom) 2182ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._scroll(self.velocity_x, bottom) 2192ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._scroll(self.velocity_y, bottom) 2202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._scroll(self.velocity_magnitude, bottom) 2212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._scroll(self.old_velocity_x, bottom) 2222ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._scroll(self.old_velocity_y, bottom) 2232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self._scroll(self.old_velocity_magnitude, bottom) 2242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Redraw the plots. 2262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_line_x.set_data(self.velocity_x) 2272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_line_y.set_data(self.velocity_y) 2282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.velocity_line_magnitude.set_data(self.velocity_magnitude) 2292ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_line_x.set_data(self.old_velocity_x) 2302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_line_y.set_data(self.old_velocity_y) 2312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.old_velocity_line_magnitude.set_data(self.old_velocity_magnitude) 2322ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2332ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown self.fig.canvas.draw_idle() 2342ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2352ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Scroll a time series. 2362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _scroll(self, timeseries, bottom): 2372ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown bottom_index = bisect.bisect_left(timeseries[0], bottom) 2382ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown del timeseries[0][:bottom_index] 2392ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown del timeseries[1][:bottom_index] 2402ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown for i, timeindex in enumerate(timeseries[0]): 2412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown timeseries[0][i] = timeindex - bottom 2422ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2432ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Extract a word following the specified prefix. 2442ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _get_following_word(self, line, prefix): 2452ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown prefix_index = line.find(prefix) 2462ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if prefix_index == -1: 2472ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return None 2482ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown start_index = prefix_index + len(prefix) 2492ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown delim_index = line.find(',', start_index) 2502ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if delim_index == -1: 2512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return line[start_index:] 2522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown else: 2532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return line[start_index:delim_index] 2542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Extract a number following the specified prefix. 2562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _get_following_number(self, line, prefix): 2572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown word = self._get_following_word(line, prefix) 2582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown if word is None: 2592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return None 2602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return float(word) 2612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2622ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Add a value to a time series. 2632ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _append(self, timeseries, timeindex, number): 2642ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown timeseries[0].append(timeindex) 2652ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown timeseries[1].append(number) 2662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Parse the logcat timestamp. 2682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown # Timestamp has the form '01-21 20:42:42.930' 2692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown def _parse_timestamp(self, line): 2702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown return datetime.strptime(line[0:18], '%m-%d %H:%M:%S.%f') 2712ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2722ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Notice 2732ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownprint "Velocity Tracker plotting tool" 2742ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownprint "-----------------------------------------\n" 2752ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownprint "Please enable debug logging and recompile the code." 2762ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2772ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Start adb. 2782ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownprint "Starting adb logcat.\n" 2792ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2802ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownadb = subprocess.Popen(['adb', 'logcat', '-s', '-v', 'time', 'Input:*', 'VelocityTracker:*'], 2812ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown stdout=subprocess.PIPE) 2822ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownadbout = NonBlockingStream(adb.stdout) 2832ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Prepare plotter. 2852ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownplotter = Plotter(adbout) 2862ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownplotter.update() 2872ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown 2882ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown# Main loop. 2892ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownplot.show() 290