technoshop.essais_mesure_fi.../simu/erreur_mc.ts
2025-07-21 10:56:11 +02:00

138 lines
3.1 KiB
TypeScript

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
}