一种全新的,自创的(2d无人开车)的算法

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<title>2D无人驾车系统(积分预判防相撞)</title>

<style>

body { margin: 0; display: flex; flex-direction: column; align-items: center; background: #f0f0f0; font-family: Arial; }

#canvas { background: #fff; border: 3px solid #333; }

.controls { margin: 10px 0; display: flex; gap: 15px; align-items: center; }

input { width: 80px; padding: 5px; }

button { padding: 6px 18px; cursor: pointer; background: #4CAF50; color: white; border: none; border-radius: 4px; }

button:hover { background: #45a049; }

.tip { margin-top: 5px; font-size: 14px; color: #666; }

</style>

</head>

<body>

<div class="tip">红色顶点是目的地,红色顶点上方蓝色数字为车辆编号</div>

<canvas id="canvas" width="1000" height="600"></canvas>

<div class="controls">

<label>车辆数量: <input type="number" id="carCount" value="5" min="1" max="150" step="1"></label>

<button id="startBtn">启动系统</button>

<button id="stopBtn">停止系统</button>

</div>

<script>

// 原机械臂核心算法(完全保留)

function F(x, k) { return 1 + Math.pow(x, k) + x; }

function integral(eq, a, b, d=0.1, K=5) {

const g = new Function('x', `return ${eq};`);

let s = [[a, b]], r = 0.0;

while (s.length > 0) {

let n = [];

for (let [x0, x1] of s) {

const dx = x1 - x0;

if (dx < d) {

const m = (x0 + x1)/2;

const m_scaled = m/(2*Math.PI);

const f_values = Array.from({length:K}, (_,k) => F(m_scaled, k+1));

let W = 0.0, V = 0.0;

const g_m = g(m);

for (let k = 0; k < K; k++) {

const w = 1/(f_values[k] + 1e-12);

W += w; V += w * g_m;

}

r += dx * (W ? V/W : g_m);

continue;

}

const u = g(x0), v = g(x1), mid = (x0+x1)/2, mv = g(mid);

if (Math.abs(u-v) < 1e-8 && Math.abs(mv-u) < 1e-8) {

r += dx * mv; continue;

}

const h = dx/10;

for (let i = 0; i < 10; i++) n.push([x0+i*h, x0+(i+1)*h]);

}

s = n;

}

return r;

}

function c(seg) { let cnt = 0; for (let i=0;i<seg.length;i++) for(let j=i+1;j<seg.length;j++) if(seg[i]>seg[j]) cnt++; return cnt; }

function w(arr, wa) {

let a = [...arr], n = a.length;

if (n <=1) return a;

const exp_wa = Array.from({length:n}, (_,i) => Math.pow(wa, i+1));

for (let i=0;i<n;i++) {

let swapped = false;

for (let j=0;j<n-i-1;j++) {

const v1 = a[j]*(1 + wa + exp_wa[j]);

const v2 = a[j+1]*(1 + wa + exp_wa[j+1]);

if (Math.abs(v1-v2) <1e-8) {

const eq = `{a\[j\]}\*x - {a[j+1]}*x`;

const r = integral(eq, 0, 1);

if (r>0) { [a[j],a[j+1]] = [a[j+1],a[j]]; swapped=true; }

} else if (v1>v2) { [a[j],a[j+1]] = [a[j+1],a[j]]; swapped=true; }

}

if (!swapped) break;

}

return a;

}

function sortAngle(arr) {

let n = arr.length;

if (n<=1) return [...arr];

let segs = [], i=0;

while (i < n) {

let l=1;

while (i+l <n && arr[i+l]>=arr[i+l-1]) l++;

const s = arr.slice(i, i+l);

const r = l>1 ? c(s)/(l-1) : 0;

segs.push({s, r});

i += l;

}

let n_segs = [];

for (let {s, r} of segs) {

if (r>0 && s.length>1) {

const avg = s.reduce((a,b)=>a+b)/s.length;

const wa_sum = Array.from({length:20}, (_,k) => 1/(F(avg, k+1)+1e-12)).reduce((a,b)=>a+b);

n_segs.push({s:w(s, wa_sum), r: c(w(s, wa_sum))/(s.length-1)});

} else n_segs.push({s, r});

}

return n_segs.flatMap(item => item.s);

}

// 全局变量

const canvas = document.getElementById('canvas');

const ctx = canvas.getContext('2d');

const [W, H] = [canvas.width, canvas.height];

let cars = [], isRunning = false;

// 性能优化:离屏画布(批量绘制避免重复渲染)

const offscreenCanvas = document.createElement('canvas');

const offscreenCtx = offscreenCanvas.getContext('2d');

offscreenCanvas.width = W;

offscreenCanvas.height = H;

// 速度归一化函数(机械臂旋转速度专用)

function normalizeSpeed(speed) {

return Math.max(0.01, Math.min(speed, 0.1)) * 0.5;

}

class Car {

constructor(id) {

this.id = id;

this.size = {w:30, h:15};

this.x = Math.random() * (W - 2*this.size.w) + this.size.w;

this.y = Math.random() * (H - 2*this.size.h) + this.size.h;

this.angle = Math.random() * Math.PI * 2;

this.speed = Math.random() * 1.5 + 1.2;

this.maxSpeed = 4;

this.target = this.getRandomTarget();

this.arriveTimer = 0;

this.emergency = false;

this.emergencyTimer = 0;

// 绑定机械臂(隐藏)

this.arm = {

len: [20, 15, 10],

angle: [Math.random()*Math.PI/2, Math.random()*Math.PI/2, Math.random()*Math.PI/2],

joint: []

};

this.rotateSpeed = 0.05;

// 缓存积分计算参数(减少重复创建)

this.predictTimeStep = 5;

this.predictD = 0.5;

}

getRandomTarget() {

return {

x: Math.random() * (W - 4*this.size.w) + 2*this.size.w,

y: Math.random() * (H - 4*this.size.h) + 2*this.size.h

};

}

updateArmJoint() {

let [x, y] = [this.x, this.y];

this.arm.joint = [{x, y}];

for (let i=0; i<this.arm.len.length; i++) {

x += this.arm.len[i] * Math.cos(this.arm.angle[i]);

y += this.arm.len[i] * Math.sin(this.arm.angle[i]);

this.arm.joint.push({x, y});

}

}

rotateArmWhenReverse() {

this.updateArmJoint();

const speed = normalizeSpeed(this.rotateSpeed);

const angleArr = [...this.arm.angle];

const sortedAngles = sortAngle(angleArr);

this.arm.angle = sortedAngles.map(ang => ang + speed * (Math.random() > 0.5 ? 1 : -1));

this.angle = this.arm.angle[this.arm.angle.length - 1];

}

// 积分预测未来位置(缓存参数优化)

predictFuturePos() {

const eqX = `({this.x}) + Math.cos({this.angle}) * ${this.speed} * x`;

const eqY = `({this.y}) + Math.sin({this.angle}) * ${this.speed} * x`;

const futureX = integral(eqX, 0, this.predictTimeStep, this.predictD);

const futureY = integral(eqY, 0, this.predictTimeStep, this.predictD);

return {x: futureX, y: futureY};

}

// 优化碰撞检测:减少重复计算

checkCollision(otherCars) {

const collisionRange = 60;

const predictRange = 80;

for (let car of otherCars) {

if (car.id === this.id) continue;

const dx = this.x - car.x;

const dy = this.y - car.y;

const dist = Math.hypot(dx, dy);

// 即时碰撞

if (dist < collisionRange * 0.7) return true;

// 预判碰撞(跳过已计算的车辆对,避免重复)

if (this.id < car.id) {

const myFuture = this.predictFuturePos();

const carFuture = car.predictFuturePos();

const futureDist = Math.hypot(myFuture.x - carFuture.x, myFuture.y - carFuture.y);

if (futureDist < predictRange) return true;

}

}

// 边界碰撞

if (this.x < this.size.w || this.x > W - this.size.w || this.y < this.size.h || this.y > H - this.size.h) {

return true;

}

return false;

}

// 强制分离逻辑(保留原逻辑)

forceSeparate(otherCars) {

for (let car of otherCars) {

if (car.id === this.id) continue;

const dx = this.x - car.x;

const dy = this.y - car.y;

const dist = Math.hypot(dx, dy);

if (dist < this.size.w * 1.5) {

const pushForce = 2;

const dirX = dx / dist;

const dirY = dy / dist;

this.x += dirX * pushForce;

this.y += dirY * pushForce;

car.x -= dirX * pushForce;

car.y -= dirY * pushForce;

this.rotateArmWhenReverse();

car.rotateArmWhenReverse();

}

}

}

control(otherCars) {

const dx = this.target.x - this.x;

const dy = this.target.y - this.y;

const targetAngle = Math.atan2(dy, dx);

const distToTarget = Math.hypot(dx, dy);

if (distToTarget < 20) {

this.arriveTimer++;

if (this.arriveTimer > 30) {

this.target = this.getRandomTarget();

this.arriveTimer = 0;

}

} else {

this.arriveTimer = 0;

}

// 碰撞检测与紧急处理

const isCollision = this.checkCollision(otherCars);

if (isCollision && !this.emergency) {

this.emergency = true;

this.emergencyTimer = 150;

this.rotateArmWhenReverse();

}

if (this.emergency) {

this.speed = -Math.abs(this.speed) * 0.8;

this.emergencyTimer--;

if (this.emergencyTimer <= 0) {

this.emergency = false;

this.speed = Math.abs(this.speed);

}

} else {

const angleDiff = targetAngle - this.angle;

const normalizedDiff = (angleDiff + Math.PI) % (2 * Math.PI) - Math.PI;

const steerFactor = distToTarget > 100 ? 0.1 : 0.02;

this.angle += normalizedDiff * steerFactor;

this.speed = Math.min(this.maxSpeed, distToTarget * 0.01);

}

// 位置更新

this.x += Math.cos(this.angle) * this.speed;

this.y += Math.sin(this.angle) * this.speed;

// 边界反弹

if (this.x < this.size.w) this.x = this.size.w + 5;

if (this.x > W - this.size.w) this.x = W - this.size.w -5;

if (this.y < this.size.h) this.y = this.size.h +5;

if (this.y > H - this.size.h) this.y = H - this.size.h -5;

// 强制分离

this.forceSeparate(otherCars);

}

// 绘制车辆+红色编号;绘制目的地+蓝色编号

draw() {

// 绘制车辆本体

offscreenCtx.save();

offscreenCtx.translate(this.x, this.y);

offscreenCtx.rotate(this.angle);

offscreenCtx.fillStyle = `hsl(${this.id * 30}, 70%, 50%)`;

offscreenCtx.fillRect(-this.size.w/2, -this.size.h/2, this.size.w, this.size.h);

// 绘制车辆红色编号

offscreenCtx.fillStyle = 'red';

offscreenCtx.font = '12px Arial bold';

offscreenCtx.textAlign = 'center';

offscreenCtx.fillText(this.id, 0, -this.size.h/2 - 5);

// 绘制车辆朝向箭头

offscreenCtx.fillStyle = 'black';

offscreenCtx.beginPath();

offscreenCtx.moveTo(10, 0);

offscreenCtx.lineTo(-5, -5);

offscreenCtx.lineTo(-5, 5);

offscreenCtx.fill();

offscreenCtx.restore();

// 绘制目的地(红色顶点)

offscreenCtx.fillStyle = 'red';

offscreenCtx.beginPath();

offscreenCtx.arc(this.target.x, this.target.y, 5, 0, 2*Math.PI);

offscreenCtx.fill();

// 绘制目的地上方蓝色编号

offscreenCtx.fillStyle = 'blue';

offscreenCtx.font = '12px Arial bold';

offscreenCtx.textAlign = 'center';

offscreenCtx.fillText(this.id, this.target.x, this.target.y - 10);

}

}

// 优化动画循环:离屏画布批量渲染

function animate() {

if (!isRunning) return;

// 清空离屏画布

offscreenCtx.clearRect(0, 0, W, H);

// 批量更新+绘制所有车辆

cars.forEach(car => {

car.control(cars);

car.draw();

});

// 一次性绘制到主画布(减少重绘次数)

ctx.clearRect(0, 0, W, H);

ctx.drawImage(offscreenCanvas, 0, 0);

requestAnimationFrame(animate);

}

// 按钮事件

document.getElementById('startBtn').addEventListener('click', () => {

if (isRunning) return;

isRunning = true;

const carCount = parseInt(document.getElementById('carCount').value);

cars = [];

for (let i=0; i<carCount; i++) {

cars.push(new Car(i));

}

animate();

});

document.getElementById('stopBtn').addEventListener('click', () => {

isRunning = false;

});

</script>

</body>

</html>

相关推荐
0思必得02 小时前
[Web自动化] CSS布局与定位
前端·css·自动化·html·web自动化
天外天-亮12 小时前
v-if、v-show、display: none、visibility: hidden区别
前端·javascript·html
be or not to be13 小时前
HTML入门系列:从图片到表单,再到音视频的完整实践
前端·html·音视频
jlspcsdn15 小时前
20251222项目练习
前端·javascript·html
new code Boy21 小时前
前端base-64 编码解码
前端·javascript·html
东方佑1 天前
使用Python标准库将Word文档转换为HTML:深入解析.docx文件处理脚本
python·html·word
be or not to be1 天前
HTML 与 CSS 基础入门笔记
css·笔记·html
代码小库2 天前
基于 SpringBoot 的漫画网站系统设计与实现 | 毕业设计实战项目分享(附源码)
html