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使用排除誤差的方式是:

  1. 小於一定值得data值不予採用
    if(d1[dcount]>150||d1[dcount]<-150){ay = d1[dcount];} if(d2[dcount]>100||d2[dcount]<-100){ax = d2[dcount];}
  2. 每當取到一次不予採用的值,errorcounter++,當errorcounter>15時,所有數據歸零
⚠️ **GitHub.com Fallback** ⚠️