PD Controller

with orbitControls, XZgrid, info

by Rebecca Chen

HTML

<div id="info">PD Controller 
<br>click your destination
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>

CSS

#info {
  position: absolute;
  top: 0px;
  width: 100%;
  padding: 10px;
  text-align: center;
  color: #ffff00
}

body {
  overflow: hidden;
}

JavaScript

class PDController {
	constructor (x=0, xref=0) {
  	this.x = x;
    this.xref = xref;
    this.v = 0;
    this.KP = 150;   // 'spring constant'
    this.KD = 20;   // 'damping'
  }
  
  update (dt) {
  	let f = -this.KP * (this.x-this.xref) - this.KD*this.v;
    this.v += f*dt;
    this.x += this.v*dt
    return this.x
  }
  setRef (ref) {
  	this.xref = ref;
  }
}

var camera, scene, renderer;
var stats;

var clock, mesh;
var pdcontrol;

init();
animate();

function init() {

	renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setClearColor(0x888888);
  document.body.appendChild(renderer.domElement);

  // STATS
  stats = new Stats();
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.top = '0px';
  stats.domElement.style.zIndex = 100;
  document.body.appendChild(stats.domElement);

  scene = new THREE.Scene();
  camera = new THREE.OrthographicCamera(-50, 50, 50, -50, -10, 100);
  camera.position.z = 10;

  let grid = new THREE.GridHelper(100, 10, 'red', 'white')
  scene.add(grid)
  grid.rotation.x = -Math.PI / 2
  window.addEventListener('resize', onWindowResize, false);
  window.addEventListener('mousedown', onDocumentMouseDown, false);

	///////////////////////////////
  clock = new THREE.Clock();
  clock.getDelta();

  pdcontrol = new PDController();
  mesh = new THREE.Mesh(new THREE.CircleGeometry(2), new THREE.MeshBasicMaterial())
  scene.add(mesh)

}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

function onDocumentMouseDown(event) {
  event.preventDefault();
  // NDC: [-1,1]x[-1,1]
  let mouseX = (event.clientX / window.innerWidth) * 2 - 1;
  let mouseY = -(event.clientY / window.innerHeight) * 2 + 1;

  pdcontrol.setRef (mouseX * 50)
}

function animate() {
  dt = clock.getDelta();
	mesh.position.x =...