import { Plot } from '../plot/mod.ts' import { range } from '../utils/list.ts' const distance = 200 //cm const size = 300 //cm const gap = 2.6 //cm const radius = 1 //cm const markerSize = 2 * radius * 4 //4: px aspect factor function getPoints() { const plot = { x: [] as number[], y: [] as number[], mode: 'markers', name: 'references', marker: { size: markerSize }, } const step = 20 * gap for (const x of range(0, size + 1, step)) { for (const y of range(0, size + 1, step)) { plot.x.push(x) plot.y.push(y) } } return plot } function computePoints( samples: number, options = { static: true, dynamic: true, rounding: true }, ) { const label = [ options.static ? 'static' : undefined, options.dynamic ? 'dyn.' : undefined, options.rounding ? 'round.' : undefined, ].filter((v) => v).join('+') const plot = { x: [] as number[], y: [] as number[], mode: 'markers', name: `simulation (${label})`, marker: { size: markerSize }, opacity: 0.3, } const step = 20 * gap for (const x of range(0, size + 1, step)) { for (const y of range(0, size + 1, step)) { //Projected coordinates const phi = Math.atan(x / distance) const theta = Math.atan(y / distance) for (const _ of range(0, samples)) { // Static errors const laserAxisError = () => Math.random() * 3 - 3 / 2 const staticErrors = () => laserAxisError() // Dynamic errors const headMotorsError = () => Math.random() * 0.02 - 0.01 const headOrbitError = () => Math.random() * 0.2 - 0.1 const dynamicErrors = () => headMotorsError() + headOrbitError() // Code rounding const codeThetaRound = () => Math.random() * 4.39 - 4.39 / 2 const codePhiRound = () => Math.random() * 6.43 - 6.43 / 2 const thetaErr = (options.static && staticErrors()) + (options.dynamic && dynamicErrors()) + (options.rounding && codeThetaRound()) const phiErr = (options.static && staticErrors()) + (options.dynamic && dynamicErrors()) + (options.rounding && codePhiRound()) //Cartesian coordinates const x1 = Math.tan(phi + toRad(phiErr)) * distance const y1 = Math.tan(theta + toRad(thetaErr)) * distance plot.x.push(x1) plot.y.push(y1) } } } return plot } function getHoles() { const plot = { x: [] as number[], y: [] as number[], mode: 'markers', marker: { size: markerSize, color: 'rgba(0, 0, 0, 0)', line: { color: 'rgba(0, 0, 0, 1)', width: 1, }, }, opacity: 0.3, name: 'holes', } let shift = false for (const x of range(0, size, gap)) { for (const y of range(0, size, gap)) { plot.x.push(shift ? x + gap / 2 : x) plot.y.push(y) shift = !shift } } return plot } const plot = new Plot() plot.plot([ computePoints(1e3, { static: true, dynamic: true, rounding: true }), computePoints(1e3, { static: true, dynamic: true, rounding: false }), computePoints(1e3, { static: false, dynamic: true, rounding: false }), getPoints(), getHoles(), ], { xaxis: { range: [-10, size + 10] }, yaxis: { range: [-10, size + 10] }, }) function toRad(degree: number): number { return degree * Math.PI / 180 }