双摆混沌实验室:两根摆杆一松手,轨迹三秒看上头
双摆最好玩的地方是「完全不可预测」:同样的初始角度,多摆 0.1 度轨迹都会彻底分道扬镳。这个工具把双摆的微分方程搬进浏览器,两根摆臂按真实物理过程实时演算,第二个摆锤会拖出越画越密的混沌轨迹;长度、质量、初始角度、重力都能拖滑块调整,暂停后还能直接拽摆锤改角度,松手就是一副不一样的图。先看成品,再讲这个网页怎么用一段提示词做成单文件应用并部署上线。
这个工具做什么
它把「双摆混沌模拟」做成一个零依赖的单页应用:
- 真物理演算:不是用正弦波糊弄,而是按双摆拉格朗日方程写角加速度,再用 RK4 积分推进每一帧。
- 两个摆实时联动:摆 1 / 摆 2 的长度、质量、初始角度,以及重力和演算速度,全部实时可调。
- 轨迹逐渐混沌:第二个摆锤的运动轨迹最多保留 4000 个点,跑起来就是一副越绕越密的图。
- 拖拽改角:暂停状态下直接拖住任一摆锤,初始角度跟随鼠标变化,滑块同步更新。
- 6 种轨迹配色:青紫、红黄、绿青、橙粉、白灰、紫粉一键切换。
- 随时暂停 / 重置 / 清空:空格暂停、R 重置、C 清空轨迹,快捷键全部接好。
- 帧率显示:右上角实时显示 fps,方便判断当前设备跑得顺不顺。

准备环境:进入码道CodeArts
本文用 CodeArts 的 WebUI 版来演示。先进入 CodeArts 并开通体验版,不需要装任何软件,浏览器就能用:
进入 CodeArts:https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz
开通后有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。本文用 WebUI 版演示。
进入 AI 开发者空间
- 浏览器打开 https://devstation.developer.huaweicloud.com/aidevspace?utm_source=opcsfsq&utm_medium=wbwz
- 弹窗「请选择要进入的版本」→ 点击 体验版
- 首次使用会跳到华为云登录页,扫码登录一次,后续浏览器会话复用
- 弹窗「临时凭据自动配置」→ 点击 同意,沙箱自动创建
进入 AI 开发者空间主界面后,先等左侧菜单加载出来,再找到 CodeArts,点击它右侧的浏览器图标,打开码道 WebUI 对话窗口:

打开后码道 WebUI 会先和你打招呼,下方就是需求输入框:

小贴士:体验版沙箱 3 小时后自动重置,生成完记得把
index.html下载保存。
任务描述
在码道 WebUI 输入框粘贴以下需求,回车发送:
开发一个「双摆混沌模拟」网页应用:画布上用两条摆臂串联两个摆锤,分别显示长度、质量、初始角度和重力参数;点击开始后按真实物理规律实时演算,并在画布上画出第二个摆锤的轨迹,轨迹会逐渐呈现混沌图案;支持暂停、重置,支持拖拽一个摆锤改变初始角度,支持切换轨迹颜色和清空轨迹;界面简洁美观,单个网页即跑即玩。完成后用部署功能部署成可访问的网页应用,并告诉我访问地址。

这轮码道具体做了什么
不是复述通用 AI 能力,而是它在这个项目里的实际动作:
- 在
/workspace/double-pendulum下创建单文件index.html,把运动方程、RK4 积分、Canvas 绘制、拖拽交互和快捷键都放进一个文件,无第三方依赖。 - 先探测空闲端口,再写文件、用
python3 -m http.server启动服务,curl自检 HTTP 200 后给出预览地址。 - 最后拼接出内部预览 URL,并附上功能说明和文件位置。
代码亮点
以下是 index.html 里值得关注的设计思路和实现细节。
1. 角加速度来自微分方程,不是动画预设
双摆的运动没有解析解,代码直接根据拉格朗日方程把两个摆的角加速度写成 derivs。看不懂公式也没关系,只要知道 th1/th2 是角度、w1/w2 是角速度,函数返回的就是每帧的变化率:
// 双摆角加速度(拉格朗日方程数值形式)
function derivs(s, p){
const d = s.th1 - s.th2;
const sd = Math.sin(d), cd = Math.cos(d);
const den1 = (p.m1 + p.m2)*p.L1 - p.m2*p.L1*cd*cd;
const a1 = ( p.m2*p.L1*s.w1*s.w1*sd*cd
+ p.m2*p.g*Math.sin(s.th2)*cd
+ p.m2*p.L2*s.w2*s.w2*sd
- (p.m1+p.m2)*p.g*Math.sin(s.th1) ) / den1;
const den2 = (p.L2/p.L1)*den1;
const a2 = ( -p.m2*p.L2*s.w2*s.w2*sd*cd
+ (p.m1+p.m2)*p.g*Math.sin(s.th1)*cd
- (p.m1+p.m2)*p.L1*s.w1*s.w1*sd
- (p.m1+p.m2)*p.g*Math.sin(s.th2) ) / den2;
return { th1:s.w1, w1:a1, th2:s.w2, w2:a2 };
}
2. RK4 推进,一帧拆成 8 步
单步欧拉积分在双摆这种高敏感系统里会把能量算飞。代码用经典的四阶龙格-库塔积分,每帧实际按 dt/8 连续推进 8 次,轨迹才能稳定:
// RK4 积分一步
function rk4(s, p, dt){
const k1 = derivs(s, p);
const s2 = { th1:s.th1+k1.th1*dt/2, w1:s.w1+k1.w1*dt/2, th2:s.th2+k1.th2*dt/2, w2:s.w2+k1.w2*dt/2 };
const k2 = derivs(s2, p);
const s3 = { th1:s.th1+k2.th1*dt/2, w1:s.w1+k2.w1*dt/2, th2:s.th2+k2.th2*dt/2, w2:s.w2+k2.w2*dt/2 };
const k3 = derivs(s3, p);
const s4 = { th1:s.th1+k3.th1*dt, w1:s.w1+k3.w1*dt, th2:s.th2+k3.th2*dt, w2:s.w2+k3.w2*dt };
const k4 = derivs(s4, p);
return {
th1: s.th1 + (k1.th1+2*k2.th1+2*k3.th1+k4.th1)*dt/6,
w1: s.w1 + (k1.w1 +2*k2.w1 +2*k3.w1 +k4.w1 )*dt/6,
th2: s.th2 + (k1.th2+2*k2.th2+2*k3.th2+k4.th2)*dt/6,
w2: s.w2 + (k1.w2 +2*k2.w2 +2*k3.w2 +k4.w2 )*dt/6,
};
}
主循环里也没有每帧重新起 timer,而是持续复用 requestAnimationFrame,按真实帧间隔算 dt,卡顿自动调小步长:
function loop(ts){
if(!last) last = ts;
let dt = (ts - last) / 1000;
last = ts;
if(dt > 0.05) dt = 0.05;
if(running){
const speed = parseFloat(document.getElementById('spd').value);
const total = dt * speed;
const sub = 8;
const h = total / sub;
for(let i = 0; i < sub; i++){
state = rk4(state, params, h);
}
const pos = positions();
trail.push({x: pos.x2, y: pos.y2});
if(trail.length > MAX_TRAIL) trail.shift();
}
draw();
requestAnimationFrame(loop);
}
3. 拖拽改角:把鼠标位置反向算回角度
暂停时拖摆锤,本质是在「从已完成状态恢复到重新开始时」直接把摆锤拨到鼠标指向的位置。atan2 算相对角度,syncAngleSliders 再反过来刷新滑块,保证画布和面板始终一致:
function hitTest(m){
const pos = positions();
const r1 = 6 + Math.sqrt(params.m1)*2.2 + 8;
const r2 = 6 + Math.sqrt(params.m2)*2.2 + 8;
if(Math.hypot(m.x-pos.x2, m.y-pos.y2) < r2) return 2;
if(Math.hypot(m.x-pos.x1, m.y-pos.y1) < r1) return 1;
return null;
}
拖拽第二个摆锤时,以摆锤 1 为原点反算方向;拖第一个摆锤时,以支点为原点。拖完 initial 同步更新,下次点「重置」也会回到这个新姿势。
4. Canvas 只负责画,状态全部放在内存对象
state = { th1, w1, th2, w2 } 就是全部物理状态,params 存长度、质量、重力,trail 存轨迹点数组。视图层每帧清空画布重画,避免任何元素进退场动画带来的额外状态。轨迹颜色用线性渐变一笔画出,保留 4000 个点后从队头丢弃最旧点,性能也稳。
直接下载试玩
本次生成的项目就是单文件 index.html,没有第三方依赖,把文件保存到本地后双击用浏览器打开即可运行。源码同步到公开 Demo Park 仓库:
- Demo Park 仓库:https://atomgit.com/deli007/demo_park
- 本案例目录:https://atomgit.com/deli007/demo_park/tree/main/codearts-pendulum-lab
总结
双摆混沌实验室把可玩性压回三个点:运动方程来自真实微分方程,RK4 每帧 8 步保证轨迹稳定,拖拽交互让混沌从「看」变成「能上手拨」。把角度、质量、重力都暴露成滑块后,一套代码能玩出无穷种轨迹。后续可以继续加「轨迹保存/对比」「多摆同时跑」「慢动作回放」,或者把初始条件做成随机种子,一键生成一张混沌海报。
- 点赞
- 收藏
- 关注作者
评论(0)