自動運転シミュレーション その6

# 概要
自動運転シミュレーションを開発している。
server,client方式に変更する。
client、書いてみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/83735677-1e8c-dd7f-3060-da228fc54e46.png)

# サンプルコード

```

let url = "ws://localhost:50002/";
let agent = new WebSocket(url);
agent.onmessage = function(event) {
  var data = JSON.parse(event.data);
	draw(data.action);
};
agent.onclose = event => alert(`Closed ${event.code}`);
agent.onopen = event => alert(`open`);
agent.onerror = event => alert(`err`);
var canvas2 = document.createElement("canvas");
var ctx2 = canvas2.getContext("2d");

function c2() {
  var rectWidth = 200;
  var rectHeight = 110;
  var rectx2 = 50;
  var rectY = 130;
  var cornerRadius = 50;
	canvas2.width = 500;
	canvas2.height = 500;
	ctx2.fillStyle = "#0a0";
	ctx2.strokeStyle = "#888";
	ctx2.fillRect(0, 0, canvas2.width, canvas2.height);
	ctx2.save();
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY, rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2, rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2, rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2, rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY + cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + rectHeight, rectx2 - rectWidth, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY + rectHeight, rectx2 + rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth, rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.strokeStyle = "#f00"
	ctx2.lineWidth = 40;
	ctx2.stroke();	
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY, rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2, rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2, rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2, rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY + cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + rectHeight, rectx2 - rectWidth,rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY + rectHeight, rectx2 + rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth, rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.lineWidth = 39;
	ctx2.stroke();
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY, rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2, rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2, rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2,rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY + cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2,rectY + cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + rectHeight, rectx2 - rectWidth, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY + rectHeight, rectx2 + rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth, rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.strokeStyle = "yellow"
	ctx2.lineWidth = 3;
	ctx2.stroke();
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY, rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2 , rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2, rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2, rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY + cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + rectHeight, rectx2 - rectWidth, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY + rectHeight, rectx2 + rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth, rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.strokeStyle = "#888"
	ctx2.lineWidth = 2;
	ctx2.stroke();
  var sx = 150;
  var sy = 20;
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 + sx, 314 + rectY - sy);
	ctx2.lineTo(rectx2 + sx, 314 + rectY + sy);
	ctx2.strokeStyle = "#f00"
	ctx2.lineWidth = 2;
	ctx2.stroke();
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.fillStyle = "#fff"
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY - sy, 1, 5)
	ctx2.fillRect(rectx2 + sx, 314 + rectY - sy + 5, 1, 5)
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY - sy + 10, 1, 5)
	ctx2.fillRect(rectx2 + sx, 314 + rectY - sy + 15, 1, 5) 
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY, 1, 5)
	ctx2.fillRect(rectx2 + sx, 314 + rectY + sy - 15 , 1, 5)
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY + sy - 10, 1, 5)
	ctx2.fillRect(rectx2 + sx, 314 + rectY + sy - 5, 1, 5)
	ctx2.stroke();
	ctx2.restore()
}
c2();
function kaiten(d) {
  var e = document.getElementById("img1");
	e.style.transform = "rotate(" + d + "deg)";
}
function sense(src, s0, s1) {
  var p = 0;
  for (var y = s1; y < s1 + 20; y++) 
  {
    for (var x = s0; x < s0 + 20; x++) 
    {
      var r = src.data[(y * 240 + x) * 4];
      var g = src.data[(y * 240 + x) * 4 + 1];
      var b = src.data[(y * 240 + x) * 4 + 2];
      p += r + g + b;
    }
  }
  return p / 20 / 20 / 3 / 256;
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var OFF = document.createElement("canvas");
var OFF_CTX = OFF.getContext("2d");
var FOV = Math.PI / 3;
var DEPTH = 2 * Math.tan(FOV * 0.5);
var EYE = canvas.width / DEPTH;
OFF.height = canvas.height;
OFF.width = Math.ceil(canvas.height * DEPTH);
var car = {
  x: 140,
  y: 440,
  z: 18,
  a: Math.PI * 2,
  vx: 0,
  vy: 0,
  vz: 0,
  va: 0,
  px: 0,
  py: 0
};
var s0 = 0.1, 
	s1 = 0.1,
	s2 = 0.1,
	s3 = 0.1,
	s4 = 0.1;
function draw(r) {
  car.vx = Math.cos(car.a) / 1;
  car.vy = Math.sin(car.a) / 1;
  car.va = 0;
  if (r == 0)
  {
    car.va = -Math.PI / 30;
  }
  if (r == 1)
  {
    car.va = Math.PI / 30;
  }
	kaiten(car.va * 100);
  car.x += car.vx;
  car.y += car.vy;
  car.a += car.va;
  var horizon = Math.floor(canvas.height * 0.01);
  var scale = EYE * car.z;
  var yMin = Math.ceil(scale / OFF.height);
  var yMax = canvas.height - horizon;
  var near = scale / yMax - 1;
  OFF_CTX.clearRect(0, 0, OFF.width, OFF.height);
  OFF_CTX.save();
  OFF_CTX.translate(OFF.width * 0.5, OFF.height + near)
  OFF_CTX.rotate(Math.PI * 1.5 - car.a);
  OFF_CTX.drawImage(canvas2, -car.x, -car.y);
  OFF_CTX.restore();
  ctx.fillRect(0, horizon, canvas.width, yMax);
  for (var y = yMin; y < yMax; y += height)
  {
    var top = scale / y;
    var width = top * DEPTH;
    var height = Math.ceil(scale / Math.floor(top) - y);
    var bottom = scale / (y + height);
    ctx.drawImage(OFF, (OFF.width - width) * 0.5, OFF.height + near - top, width, top - bottom, 0, horizon + y, canvas.width, height);
  }
  var src = ctx.getImageData(0, 0, canvas.width, canvas.height);
  s0 = sense(src, 30, 107);
  s1 = sense(src, 70, 107);
  s2 = sense(src, 110, 107);
  s3 = sense(src, 150, 107);
  s4 = sense(src, 190, 107);    
  ctx.fillStyle = "gray";
  ctx.fillRect(30, 107, 20, 20);
  ctx.fillRect(70, 107, 20, 20);
  ctx.fillRect(110, 107, 20, 20);
  ctx.fillRect(150, 107, 20, 20);
  ctx.fillRect(190, 107, 20, 20);
  ctx.font = "14px arial black";
  var text = "a: " + Math.floor(car.a * 10);
  ctx.fillText(text, 10, 12);
  text = "xyz: " + Math.floor(car.x) + "  " + Math.floor(car.y) + "  " + Math.floor(car.z);
  ctx.fillText(text, 10, 24);
  ctx.fillStyle  = "white";   
}

function run() {
	setInterval(function() {
		var json = '{"observation": {"s0": "' + s0 + '", "s1": "' + s1 + '", "s2": "' + s2 + '", "s3": "' + s3 + '",  "s4": "' + s4 + '"  }, "reward": "1.0", "done": "false"}';
		agent.send(json);
	}, 100);
}




```

# 成果物

https://embed.plnkr.co/plunk/L185TI0SxvmPwUHH


以上。