Midterm Project document - oboywei/ee240500 GitHub Wiki
此Project目標為將三軸加速器所收集到的data轉換成位移 並在Html檔案中畫出其移動路徑。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Mazing</title>
<style>
canvas{
border:2px solid #000000;
background-color: #f1f1f1;
}
</style>
<script type="text/javascript" src="walkertest.js"></script>
<button onclick="walking()">walking</button><br>
</head>
<body onload = "startmaze()">
<p id = "demo1">demo1</p>
<p id = "demo2">demo2</p>
<p id = "demo3">demo3</p>
<p id = "demo4">demo4</p>
<p id = "demo5">demo5</p>
<p id = "demo6">demo6</p>
<script>
<!--
`var batch=30;`
`var samples=batch;`
`var timecycle=0;`
`var requestCounter = 0;`
`var interval = 0;`
`var nodata = 0;`
`var serverAddressBase = "xdata.";`
`var serverAddress = "xdata.0"; //default file to get from server`
`var vx=0;`
`var vy=0; `
`var vz=0;`
`d1 = [];`
`d2 = [];`
`d3 = [];`
`// Pre-pad the arrays with # of samples null values`
`for (var i=0; i< samples; ++i) {`
`d1.push(null);`
`d2.push(null);`
`d3.push(null);`
`}`
`var xmlHttp = createXmlHttpRequestObject();`
`// creates XMLHttpRequest Instance`
`function createXmlHttpRequestObject(){`
`// will store XMLHttpRequest object`
`// at here`
`var xmlHttp;`
`// works all exceprt IE6 and older `
`try`
`{`
`// try to create XMLHttpRequest object`
`xmlHttp = new XMLHttpRequest(); `
`}`
`catch(e)`
`{`
`// assume IE 6 or older`
`try`
`{`
`xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");`
`}`
`catch(e){ }`
`}`
`// return object or display error`
`if (!xmlHttp)`
`alert("Error creating the XMLHttpRequest Object");`
`else`
`return xmlHttp;`
`}`
`function GetJsonData()`
`{`
`//debug`
`//myDiv = document.getElementById("myDivElement"); `
`//myDiv.innerHTML += "Getting Json Data<br>"; `
`nodata=0;`
`if(xmlHttp)`
`{`
`try`
`{`
`xmlHttp.open("Get", serverAddress, false);`
`//xmlHttp.onreadystatechange = handleRequestStateChange; //We use synchronous data transfer, so we don't need this here`
`xmlHttp.send(null);`
`try{`
`handleJsonData();`
`}`
`catch(err){`
`if(err=="no data"){`
`//alert('Waiting '+serverAddressBase+requestCounter);`
`//setTimeout(GetJsonData,10); //Try again 10ms later`
`nodata=1; //record status`
`}`
`}`
`}`
`catch(e)`
`{`
`alert("Can't connect to server\n" + e.toString());`
`}`
`}`
`}`
`function handleRequestStateChange()`
`{`
`if (xmlHttp.readyState == 4)`
`{`
`if(xmlHttp.status == 200|| xmlHttp.status == 0)`
`{`
`try`
`{`
`handleJsonData();`
`}`
`catch(e)`
`{`
`alert("Error reading the response: " + e.toString());`
`}`
`}`
`else`
`{`
`alert("Problem retrieving data:\n" + xmlHttp.statusText);`
`}`
`}`
`}`
`function handleJsonData()`
`{`
`var result = xmlHttp.responseText;`
`if(result==''){`
`//alert('No data from xmlhttprequest object!');`
`throw "no data";`
`}`
`else{`
`try{`
`var jobject = eval("(" + result + ")");`
`var i=0;`
`if(jobject.time>timecycle){`
`timecycle=jobject.time;`
`if(jobject.xarray.length==0){`
`throw "no data";`
`}`
`else{`
`for (i=0;i<jobject.xarray.length;i++)`
`{`
`//debug`
`//myDiv.innerHTML += jobject.xarray[i][0] + ", " + jobject.xarray[i][1] + "<br>" ;`
`d1[i]=jobject.xarray[i][0];`
`d2[i]=jobject.xarray[i][1];`
`d3[i]=jobject.xarray[i][2];`
`/*`
`d1.push(jobject.xarray[i][0]); `
`d2.push(jobject.xarray[i][1]); `
`d3.push(jobject.xarray[i][2]);`
`*/`
`}`
`}`
`}`
`else{`
`//Do nothing`
`}`
`}`
`catch(e){`
`//Retry; ignore all json errors`
`}`
`}`
`}`
`controll();`
//-->
</script>
<div style="text-align:center;width:480px;">
<button onclick="moveup()">UP</button><br>
<button onclick="moveleft()">LEFT</button>
<button onclick="moveright()">RIGHT</button><br>
<button onclick="movedown()">DOWN</button>
</div>
</body>
</html>
walker.js:
var walker;
var Exit;
function startmaze() {
mazeArea.start();
walker = new component(20, 20, "green.png", (mazeArea.canvas.width-20)/2, (mazeArea.canvas.height-20)/2);
ctxx = mazeArea.context;
ctx.drawImage("green.png",0,0,400,200);
}
//create a canvas that represent the whole maze plane
var mazeArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 400;
this.canvas.height = 400;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updatemazeArea, 20);
},
//the mazeArea.clear method, we don't use it here. Instead, we use the clearwalker method
clear : function(){
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, img, x, y) {
this.image = new Image();
this.image.src = img;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speed_x = 0;
this.speed_y = 0;
this.trackornot = 0;
this.update = function(){ //update the new walker's image
ctx = mazeArea.context;
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
}
this.newPosition = function(){
this.x += this.speed_x;
this.y += this.speed_y;
//preventing the walker from walking out of the canvas
this.hitWall();
}
this.hitWall = function(){
var upWall = 0;
var downWall = mazeArea.canvas.height - this.height;
var leftWall = 0;
var rightWall = mazeArea.canvas.height - this.width;
if(this.y < upWall){this.y = upWall; this.speed_y=0;}
if(this.y > downWall){this.y = downWall; this.speed_y=0;}
if(this.x < leftWall){this.x = leftWall; this.speed_x=0;}
if(this.x > rightWall){this.x = rightWall; this.speed_x=0;}
}
//
this.clearwalker = function(){
mazeArea.context.clearRect(this.x, this.y, this.x+this.width, this.y+this.height);
}
}
function updatemazeArea(){
`//mazeArea.clear(); //use the mazeArea.clear method(we don't use it in this case)`
`walker.clearwalker(); //use the clearwalker method`
`mazeArea.context.moveTo(walker.x+walker.width/2, walker.y+walker.height/2);`
`walker.newPosition();`
`walker.update();`
`mazeArea.context.lineTo(walker.x+walker.width/2, walker.y+walker.height/2);`
`mazeArea.context.stroke();`
}
//track the walker's path
function track(){
walker.trackornot = 1;
}
//testing the movement of the walker
function moveup(){
walker.speed_y -= 1;
}
function movedown(){
walker.speed_y += 1;
}
function moveleft(){
walker.speed_x -= 1;
}
function moveright(){
walker.speed_x += 1;
}
//<--
function controll()
{
serverAddress=serverAddressBase+requestCounter;
`GetJsonData();`
`if(!nodata){ `
`requestCounter=(requestCounter+1)%2; `
`}`
`else{`
`}`
`document.getElementById("demo1").innerHTML = "d1:"+d1+", d2:"+d2+", d3:"+d3+", time:"+timecycle;`
`document.getElementById("demo2").innerHTML = "d1[0]:"+d1[0]+", d2[0]:"+d2[0]+", d3[0]:"+d3[0];`
`// document.getElementById("demo3").innerHTML = accInx;`
`// document.getElementById("demo4").innerHTML = accIny;`
`var errorcounty=0;`
`var errorcountx=0;`
`for(var dcount=0; dcount<samples; ++dcount){`
`var ay=0;`
`var ax=0;`
`if(d1[dcount]>150||d1[dcount]<-150){ay = d1[dcount];}`
`if(d2[dcount]>100||d2[dcount]<-100){ax = d2[dcount];}`
`vy += ay/20000;`
`vx += ax/20000;`
`if(d1[dcount]<100&&d1[dcount]>-100){errorcounty+=1;}`
`if(d2[dcount]<150&&d2[dcount]>-150){errorcountx+=1;}`
`if(errorcounty>15){vy=0;}`
`if(errorcountx>15){vx=0;}`
`}`
`document.getElementById("demo3").innerHTML = "vx:"+vx;`
`document.getElementById("demo4").innerHTML = "vy:"+vy;`
`setTimeout(controll,20);`
`}`
function walking(){
walker.speed_x = vx;
walker.speed_y = vy;
`document.getElementById("demo5").innerHTML = "walker.speed_x:"+walker.speed_x;`
`document.getElementById("demo6").innerHTML = "walker.speed_y:"+walker.speed_y;`
setTimeout(walking,20);
}
本project遇到最大的問題是三軸加速器data的誤差值。
即使將三軸加速器平放在桌面上,仍會收到一些微幅的加速度變化,
而三軸加速器在移動時,也沒辦法每一秒都精準的收集到加速度的變化,
收集到的數值有時也會有很大的誤差。
在這樣的狀況下,加速度隨時間積分為速度,速度隨時間積分為位移,
誤差也隨時間爆炸性的不斷累積,因此若無排除誤差,這個位移紀錄器是完全無法使用的。
本project使用排除誤差的方式是:
- 小於一定值得data值不予採用
if(d1[dcount]>150||d1[dcount]<-150){ay = d1[dcount];}
if(d2[dcount]>100||d2[dcount]<-100){ax = d2[dcount];}
- 每當取到一次不予採用的值,errorcounter++,當errorcounter>15時,所有數據歸零