自動運転の模索後
以前に、自動運転の模索 において、自動運転の取り掛かりについて触れました。すでに運転手のいない自動運転タクシーが実験段階にあります。また、外国では公道走行中の自動運転車が思い通りに走行せず、事故を引き起こしたニュースが報道されています。
前回の記述を発展させ、リサジュー曲線(五葉線)とばら曲線上を走行する車の自動制御について考察します。
制御方法
ここで行われる制御は、江戸時代の茶運び人形などにも採用された初歩的な方法です。数メートル離れた客に茶菓子を出すロボットに採用されました。
客は不動であり、あらかじめ客の位置がロボットに教え込まれていました。何かの拍子に客が移動しても追従できません。
お互いに、一定の法則に従った車の動きは相手に逐一、知らされ衝突が起きそうになると、一方の車が進路をゆずる方法です。
2台の車の調整を図る今回の制御は茶菓子もてなしロボット よりは進化していると思われます。
自動運転制御コード
<html>
<head>
<input type="button" onClick=up200() value="updown " style="width:70px;height:30px;">
<input type="button" onClick=t3set() value="速 度 " style="width:70px;height:30px;">
<input type="button" onClick=R1set() value="ずれ差 " style="width:70px;height:30px;">
<input type="button" onClick=T1set() value="安全度 " style="width:70px;height:30px;">
<input type="button" onClick=start() value="開 始 " style="width:70px;height:30px;background-color:pink;">
<font size=5 color='magenta'>自動運転の模索</font><font color='black'><BR></font>
<script type="text/javascript" charset="Shift_JIS">
const HK=30;
const SIZ1=210;
const SIZ2=210;
const ZX=220;
const ZY=220;
const sc=0.0025; //②ばら曲線
const co2 = ["blue", "yellow"]; //color
const th2 = [3, 2]; //thickness, 6-4, 4.5-3
const co1 = ["tomato", "seagreen"]; //color
const DrvMode=["手動運転", "自動運転"];
const Control=["衝突発生", "衝突回避"];
var ln=0; //表示行
var t3=4; //遅延処理
var R1=0.0; //遅れ位相
var T1=8.0; //衝突危険域 2.0 4.0 1.9418
var bx = []; //バラ曲線の軌跡x値を格納, 801
var by = []; //バラ曲線の軌跡y値を格納
var rx = []; //リサジュー曲線の軌跡x値を格納, 4007
var ry = []; //リサジュー曲線の軌跡y値を格納
var driveMode=0; //0:なりゆき運転, 1:自動制御運転
var max2w=max2=0; //ばら曲線のポイント数
var max1w=max1=0; //リサジュー曲線のポイント数
var baraCount=0; //ばら曲線の連続描画回数
var lissCount=0; //リサジュー曲線の連続描画回数
var status=0; //衝突なし
var updown=1; //up/down
var ctx, wx, wy, vx, vy, first, p, q, img1;
var r=R1; //0~1.0 |------------128:①リサジュー曲線(五葉線)実行中
var s=0.0; //0~1.0 ||----------- 64:②ばら曲線実行中
var retry=flag=0; //flag:98765432109876543210
//||-------------256:②ばら曲線
img1 = new Image(); //|--------------512:①リサジュー曲線(五葉線)実行終了
img1.src = "https://aidesign.lolipop.jp/wp-content/uploads/2016/07/AutoDriving.png";//ばら曲線,早めにロードしておく
function initial(){
var canvas1 = document.getElementById('sample'); //描画コンテキストの取得実行終了
if (canvas1.getContext) {
ctx = canvas1.getContext('2d'); //次から具体的な描画内容を指定する
ctx.drawImage(img1, 5, 10, 440, 357); //ばら曲線を描画
ctx.font = "26px Arial";
ctx.fillText("開始ボタンをクリックして運転開始です。", 3, ZY*2-40);
ctx.font = "12px Arial";
ctx.fillText("開始ボタン以外は拡張用です。(ver0.09)", 5, ZY*2-10);
}
else alert("Canvas-error.");
}
function start() { //開 始
r=R1; //0~1.0
s=0.0; //0~1.0
baraCount = lissCount = max1w = max2w = flag=status = retry = driveMode = ln = 0;
ctx.clearRect(0, 0, 545, 440);
//②ばら曲線の軌跡を求める
while(s<=10.0015){
q = s * Math.PI;
p = 0.4 * q;
bx[max2] = ZX + SIZ1 * Math.sin(p) * Math.cos(q); //x
by[max2++] = ZY - SIZ1 * Math.sin(p) * Math.sin(q); //y
s += sc; //function1
}
//①五葉線
var th=0.0; //0~2.0
var b=0.7; //para-1
var c=-3; //para-2
var d=5; //para-3
var st=0.001; //step
for(max1=0; ;){
var t = th * Math.PI; //theta
q = t * d;
p = 1 + Math.sin(c * q) / 4; //a
r = p / 2 * (1 + b * Math.sin(q)); //r
rx[max1] = ZX + SIZ2 * r * Math.cos(t); //x
ry[max1++] = ZY + 25 - SIZ2 * r * Math.sin(t); //y
th += st; //linear function
if(th > 2.0005) break;
}
first = new Date().getTime();
flag = 64 | 128; //②ばら曲線実行中,①五葉線実行中
head12();
draw12(); //1:blue, 2:red
ctx.fillStyle = 'midnightblue'; //塗りつぶしの色
ctx.font = "14px Arial";
ctx.fillText("\xA9Aidesign,2016", ZX+HK+70, 20);
} // end of start()
function up200(){
}
function t3set(){
}
function R1set(){
}
function T1set(){
}
function autoDrive(){
r=R1; //0~1.0
s=0.0; //0~1.0
baraCount=lissCount=max1w=max2w=status=retry=0;
flag = 64 | 128; //②ばら曲線実行中,①リサジュー曲線(五葉線)実行中
first = new Date().getTime();
ctx.clearRect(0, 0, 460, 440);
++driveMode; //自動制御運転
++ln;head12();
draw12(); //1:blue, 2:red
}
function head12(){
msg(DrvMode[driveMode]);++ln;
ctx.clearRect(5, 13, 100, 26);
ctx.fillStyle = 'darkblue'; //塗りつぶしの色
ctx.font = "24px Arial";
ctx.fillText(DrvMode[driveMode], 5, 32);
}
function draw12(){ // <<<<<***** blue ②ばら曲線 64, 256 *****>>>>>
if((flag&256)==0){ //終了済みか
if(max2w<max2){
vx = bx[max2w];
vy = by[max2w++];
var ct2 = baraCount % 2;
dot(vx, vy, co2[ct2], th2[ct2]);
}
else{ //終了
baraCount++; //ばら曲線の連続描画回数
//alert("ばら曲線="+flag+" bCt="+baraCount+" lCt:"+lissCount+" MAX1W:"+max1w+" max1="+max1);
if(lissCount==0){ //①リサジュー曲線(四葉線)が終わっていない
max2w = 0;
}
else{
flag -= flag % 256; //flag &= 0xffffff00;
flag |= 256;
vx = vy = 999;
//alert("ばら曲線描画終了 MAX2W:"+max2w+" max2="+max2);
}
}
}
// <<<<<***** function draw1(), blue ①リサジュー曲線(五葉線)128, 512 *****>>>>>
if((flag&512)==0){ //終了済みか
if(max1w<max1){
wx = rx[max1w];
wy = ry[max1w];
var wk = control2(wx, wy, vx, vy); //衝突か
if(wk==0) max1w++; //0なら衝突は起きない
else{ //1なら衝突が起きる状態
ring("select06"); //ピッ
if(driveMode==0){
pentagon(ctx, HK, wx, wy, 'darkmagenta'); //手動運転
msg(Control[driveMode]); //衝突発生
}
else{ //自動運転
if(status==0) retry = 0;
ctx.fillStyle = ctx.strokeStyle = 'darkgreen'; //線のカラー設定
ctx.font = "16px Arial";
ctx.clearRect(wx-60, wy-10, 28, 18);
ctx.fillText("時間調整" + (retry+1) + '回', wx-123, wy+4);
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc(wx, wy, HK, 0, Math.PI*2, true);
ctx.stroke();
msg(Control[driveMode]+":"+retry); //衝突回避
++retry;
}
//console.log("STATUS="+status+" wk="+wk+" CT="+retry);
}
status = wk;
var ct1 = lissCount % 2;
dot(wx, wy, co1[ct1], th2[ct1]);
}
else {
lissCount++; //リサジュー曲線の連続描画回数
if(baraCount==0){ //②ばら曲線が終わっていない
max1w = 0;
}
else{
flag -= flag % 256; //flag &= 0xffffff00;
flag |= 512;
wx = wy = 0;
}
}
}
/////////////////////////////////////////////////////////////////////
var time = new Date().getTime() - first; //実行時間を計測
ctx.fillStyle = "green"; //塗りつぶしの色
ctx.font = "14px Arial";
ctx.clearRect(2, 40, 78, 16);
var tm = " "+time+"ミリ秒";
ctx.fillText(tm.substr(tm.length-8, 8), 5, 55);
if(flag < 768) setTimeout(draw12, t3);
else{
//alert("driveMode="+driveMode);
if(driveMode==0) setTimeout(autoDrive, 1000);
else msg("運転終了"); //すべて終了
}
} // end of draw12()
function dot(x1, y1, col, thickness){
ctx.fillStyle = col; //塗りつぶしの色は赤
ctx.fillRect(x1, y1, thickness, thickness);
}
function control2(gx, gy, hx, hy){ //衝突チェック-自動制御処理
var w = 0;
var ux = gx - T1;
var px = gx + T1;
var uy = gy - T1;
var py = gy + T1;
//console.log("VX=%d VY=%d U1=%d V1=%d U2=%d V2=%d", hx, hy, ux, px, ux, py);
if(hx>=ux){
if(hx<=px){
if(hy>=uy){ //衝突が起きる
if(hy<=py){ //衝突発生
w = 1; //増分なし、衝突回避に時間調整
}
}
}
}
return w;
}
function pentagon(ctx, hk, px, py, color){
const DT=36; //5角形, DT=360/(5*2)
const R=0.382;
var x=[];
var y=[];
for(var i=0; i<10; ++i){
var t=(i*DT+90)*Math.PI/180.0;
if(i % 2){
x[i]=R * Math.cos(t);
y[i]=R * Math.sin(t);
}
else{
x[i]=Math.cos(t);
y[i]=Math.sin(t);
}
x[i] = px + x[i] * hk;
y[i] = py - y[i] * hk;
}
ctx.beginPath(); //パスの描画を始める
ctx.moveTo(x[0], y[0]); //線の開始位置 (xの座標値 , yの座標値)
for(var j=1; j<10; ++j) ctx.lineTo(x[j], y[j]);
ctx.lineTo(x[0], y[0]);
ctx.closePath();
ctx.fillStyle = color; //線のカラー設定
ctx.fill(); //線の終了
}
function ring(tune){
document.getElementById(tune).play();
}
function msg(tx){
ctx.fillStyle = 'darkgreen'; //塗りつぶしの色
ctx.font = "14px Arial";
ctx.fillText(tx, 460, (ln++)*14+14);
}
window.onload = initial;
</script>
</head>
<body>
<canvas id="sample" width="550" height="440" style="background-color:snow;border:1px solid green;float:left;"></canvas>
</body>
<audio id="select06" preload="auto"> <source src="https://aidesign.lolipop.jp/wp-content/uploads/2014/11/lock3.wav"> </audio>
</html>
自動運転例
自動運転の模索