Draw most recent targets on webpage

Draws the most recently received targets from each camera in yellow.

Change-Id: I32b31d1b350cc5579dfdd202adeb661fd16c1332
diff --git a/y2019/vision/server/www/main.ts b/y2019/vision/server/www/main.ts
index a260787..0d88a43 100644
--- a/y2019/vision/server/www/main.ts
+++ b/y2019/vision/server/www/main.ts
@@ -1,6 +1,6 @@
 import {FIELD_WIDTH, FT_TO_M} from './constants';
 import {drawField, drawTarget} from './field';
-import {drawRobot} from './robot';
+import {drawRobot, Frame} from './robot';
 
 function main(): void {
   const vis = new Visualiser();
@@ -16,7 +16,7 @@
   private targetX = 0;
   private targetY = 0;
   private targetTheta = 0;
-  private cameraColors = ['red', 'red', 'red', 'red', 'red'];
+  private cameraFrames : Frame[];
 
   constructor() {
     const canvas = <HTMLCanvasElement>document.getElementById('field');
@@ -30,6 +30,7 @@
   initWebSocket(server: string): void {
     const socket = new WebSocket(`ws://${server}/ws`);
     const reader = new FileReader();
+    this.cameraFrames = [];
     reader.addEventListener('loadend', (e) => {
       const text = e.srcElement.result;
       const j = JSON.parse(text);
@@ -44,13 +45,7 @@
         this.targetY = j.lineFollowDebug.goalTarget.y;
         this.targetTheta = j.lineFollowDebug.goalTarget.theta;
       }
-      for (let ii of [0, 1, 2, 3, 4]) {
-        if (j.cameraDebug[ii].timeSinceLastTarget > 0.25) {
-          this.cameraColors[ii] = 'red';
-        } else {
-          this.cameraColors[ii] = 'green';
-        }
-      }
+      this.cameraFrames = j.cameraDebug;
     });
     socket.addEventListener('message', (event) => {
       reader.readAsText(event.data);
@@ -81,7 +76,7 @@
     this.reset(ctx);
 
     drawField(ctx);
-    drawRobot(ctx, this.x, this.y, this.theta, this.cameraColors);
+    drawRobot(ctx, this.x, this.y, this.theta, this.cameraFrames);
     ctx.save();
     ctx.lineWidth = 2.0 * ctx.lineWidth;
     if (this.targetLocked) {
diff --git a/y2019/vision/server/www/robot.ts b/y2019/vision/server/www/robot.ts
index 6329fb3..71defb6 100644
--- a/y2019/vision/server/www/robot.ts
+++ b/y2019/vision/server/www/robot.ts
@@ -1,28 +1,45 @@
 import {CAMERA_POSES} from './camera_constants';
 import {FT_TO_M, IN_TO_M} from './constants';
+import {drawTarget} from './field';
 
 const ROBOT_WIDTH = 25 * IN_TO_M;
 const ROBOT_LENGTH = 31 * IN_TO_M;
-const CAMERA_SCALE = 0.3;
+const CAMERA_SCALE = 0.2;
+
+interface Pose {
+  x : number;
+  y : number;
+  theta: number;
+}
+
+export interface Frame {
+  timeSinceLastTarget : number;
+  currentFrameAge : number;
+  targets : Pose[];
+}
 
 function drawCamera(
-    ctx: CanvasRenderingContext2D,
-    pose: {x: number, y: number, theta: number}): void {
+    ctx: CanvasRenderingContext2D, pose: Pose, frame: Frame): void {
+  ctx.save();
+  ctx.translate(pose.x, pose.y);
+  ctx.rotate(pose.theta);
+  if (frame.timeSinceLastTarget > 0.25) {
+    ctx.strokeStyle = 'red';
+  } else {
+    ctx.strokeStyle = 'green';
+  }
   ctx.beginPath();
-  ctx.moveTo(pose.x, pose.y);
-  ctx.lineTo(
-      pose.x + CAMERA_SCALE * Math.cos(pose.theta + Math.PI / 4.0),
-      pose.y + CAMERA_SCALE * Math.sin(pose.theta + Math.PI / 4.0));
-  ctx.lineTo(
-      pose.x + CAMERA_SCALE * Math.cos(pose.theta - Math.PI / 4.0),
-      pose.y + CAMERA_SCALE * Math.sin(pose.theta - Math.PI / 4.0));
+  ctx.moveTo(0, 0);
+  ctx.lineTo(CAMERA_SCALE, CAMERA_SCALE);
+  ctx.lineTo(CAMERA_SCALE, -CAMERA_SCALE);
   ctx.closePath();
   ctx.stroke();
+  ctx.restore();
 }
 
 export function drawRobot(
     ctx: CanvasRenderingContext2D, x: number, y: number, theta: number,
-    camera_colors: string[]): void {
+    cameraFrames: Frame[]): void {
   ctx.save();
   ctx.translate(x, y);
   ctx.rotate(theta);
@@ -39,9 +56,19 @@
   ctx.stroke();
   ctx.lineWidth = 3.0 * ctx.lineWidth;
   for (let ii of [0, 1, 2, 3, 4]) {
-    ctx.strokeStyle = camera_colors[ii];
-    drawCamera(ctx, CAMERA_POSES[ii]);
+    if (ii < cameraFrames.length) {
+      drawCamera(ctx, CAMERA_POSES[ii], cameraFrames[ii]);
+    }
   }
 
   ctx.restore();
+
+  for (let frame of cameraFrames) {
+    if (frame.targets) {
+      for (let target of frame.targets) {
+        ctx.strokeStyle = 'yellow';
+        drawTarget(ctx, target.x, target.y, target.theta);
+      }
+    }
+  }
 }