You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Julia-GLMakie包栈溢出错误排查与解决方案求助

Julia GLMakie交互式四连杆机制栈溢出错误解决方案

问题概述

使用Julia的GLMakie包开发交互式四连杆机制时,绘制连杆的代码行触发栈溢出错误,程序重复执行近4万次。增大Linux系统栈内存限制(ulimit -s 16384)后问题仍未解决。

错误代码

using GLMakie

# 常量定义
a = 2
b = 5
c = 7
d = 9

# 可观测变量定义
RadTheta2_2 = Observable(.523)
RadTheta3_12 = Observable(-1.288)
RadTheta4_12 = Observable(-2.567)

# 随可观测变量变化的位置点
R1_x2 = d * cos(0) 
R1_y2 = d * sin(0)

R2_x2 = @lift a * cos.($RadTheta2_2)
R2_y2 = @lift a * sin.($RadTheta2_2)

R3_x_12 = @lift b * cos.($RadTheta3_12)
R3_y_12 = @lift b * sin.($RadTheta3_12)

R4_x_12 = @lift c * cos.($RadTheta4_12)
R4_y_12 = @lift c * sin.($RadTheta4_12)

# 创建画布
fig = Figure(size = (3840,2160))

# 创建坐标轴
ax = Axis(fig[1,1],
    titlealign = :center,
    titlefont= :bold,
    aspect = DataAspect(),
    title = "Interactive Fourbar Mechanism",
    titlesize = 24,
    xlabel = "x direction",
    xlabelsize = 24,
    xminorticksvisible = true,
    xminorgridvisible = true,
    xminorticks = IntervalsBetween(5),
    ylabel = "y direction",
    ylabelsize = 24,
)

# 触发错误的代码行
dLine = lines!(ax, [0,R1_x2], [0,R1_y2], color = "orange")
aLine = lines!(ax, [0,R2_x2], [0,R2_y2], color = "red")
bLine = lines!(ax, [R2_x2,R3_x_12], [R2_y2,R3_y_12], color = "blue")
cLine = lines!(ax, [R1_x2,R3_x_12], [R1_y2,R3_y_12], color = "black")

# 创建图例
Legend(
    fig[1,2],
    [dLine, aLine, bLine, cLine],
    ["d [R1]", "a [R2]", "b [R3]","c [R4]"],
    height = 600,
    width = 200
)

# 创建滑块网格
sg = SliderGrid(
    fig[2, 1],
    (label = "θ2", range = -10:1:10, format = "rad", startvalue = 0),
    width = 1200
)

sliderobservables = [s.value for s in sg.sliders]
connect!(RadTheta2_2, sliderobservables[1])

display(fig)

预期效果

通过SliderGrid滑块更新Observable变量值,联动更新连杆位置向量,实时刷新图形显示新的连杆位置。

问题根源

  1. Observable使用错误:绘制连杆时,直接将单个值的Observable(如R2_x2)放入坐标数组([0, R2_x2]),生成了混合数值与Observable的数组。GLMakie在处理这种嵌套Observable时会陷入无限递归,最终耗尽栈内存导致溢出。
  2. 四连杆角度约束缺失:当前代码中RadTheta3_12和RadTheta4_12是固定值,未随RadTheta2_2联动计算,即使解决栈溢出,滑块拖动后也只有第一个连杆会动,不符合四连杆的运动逻辑。

解决方案

1. 修正Observable的坐标传递方式

将绘制连杆的代码改为用@lift包裹整个坐标数组,确保传递给lines!的是包含数值的Observable数组,而非混合数组:

# 修正后的连杆绘制代码
dLine = lines!(ax, [0,R1_x2], [0,R1_y2], color = "orange")  # R1是常量,无需修改
aLine = lines!(ax, @lift([0, $R2_x2]), @lift([0, $R2_y2]), color = "red")
bLine = lines!(ax, @lift([$R2_x2, $R3_x_12]), @lift([$R2_y2, $R3_y_12]), color = "blue")
cLine = lines!(ax, @lift([$R1_x2, $R3_x_12]), @lift([$R1_y2, $R3_y_12]), color = "black")

同时,简化位置变量的@lift写法(单个数值无需广播cos.,用cos即可):

R2_x2 = @lift a * cos($RadTheta2_2)
R2_y2 = @lift a * sin($RadTheta2_2)

R3_x_12 = @lift b * cos($RadTheta3_12)
R3_y_12 = @lift b * sin($RadTheta3_12)

R4_x_12 = @lift c * cos($RadTheta4_12)
R4_y_12 = @lift c * sin($RadTheta4_12)

2. 添加四连杆角度联动计算

根据四连杆的几何约束,通过RadTheta2_2实时计算RadTheta3_12和RadTheta4_12,示例代码如下(基于平面四连杆闭合方程推导):

# 联动计算RadTheta3和RadTheta4
on(RadTheta2_2) do theta2
    K1 = d/a
    K2 = d/c
    K3 = (a^2 - b^2 + c^2 + d^2)/(2*a*c)
    A = cos(theta2) - K1 - K2*cos(theta2) + K3
    B = -2*sin(theta2)
    C = K1 - (K2+1)*cos(theta2) + K3
    discriminant = B^2 - 4*A*C
    if discriminant >= 0
        sqrt_d = sqrt(discriminant)
        theta4_1 = 2*atan((-B + sqrt_d)/(2*A))
        RadTheta4_12[] = theta4_1
        # 计算theta3
        numerator = a*sin(theta2) - c*sin(theta4_1)
        denominator = a*cos(theta2) + d - c*cos(theta4_1)
        theta3 = atan(numerator, denominator)
        RadTheta3_12[] = theta3
    end
end

最终修正代码

using GLMakie

# 常量定义
a = 2
b = 5
c = 7
d = 9

# 可观测变量定义
RadTheta2_2 = Observable(.523)
RadTheta3_12 = Observable(-1.288)
RadTheta4_12 = Observable(-2.567)

# 联动计算RadTheta3和RadTheta4
on(RadTheta2_2) do theta2
    K1 = d/a
    K2 = d/c
    K3 = (a^2 - b^2 + c^2 + d^2)/(2*a*c)
    A = cos(theta2) - K1 - K2*cos(theta2) + K3
    B = -2*sin(theta2)
    C = K1 - (K2+1)*cos(theta2) + K3
    discriminant = B^2 - 4*A*C
    if discriminant >= 0
        sqrt_d = sqrt(discriminant)
        theta4_1 = 2*atan((-B + sqrt_d)/(2*A))
        RadTheta4_12[] = theta4_1
        # 计算theta3
        numerator = a*sin(theta2) - c*sin(theta4_1)
        denominator = a*cos(theta2) + d - c*cos(theta4_1)
        theta3 = atan(numerator, denominator)
        RadTheta3_12[] = theta3
    end
end

# 随可观测变量变化的位置点
R1_x2 = d * cos(0) 
R1_y2 = d * sin(0)

R2_x2 = @lift a * cos($RadTheta2_2)
R2_y2 = @lift a * sin($RadTheta2_2)

R3_x_12 = @lift b * cos($RadTheta3_12)
R3_y_12 = @lift b * sin($RadTheta3_12)

# 创建画布
fig = Figure(size = (1200, 800))  # 调整为更合理的尺寸

# 创建坐标轴
ax = Axis(fig[1,1],
    titlealign = :center,
    titlefont= :bold,
    aspect = DataAspect(),
    title = "Interactive Fourbar Mechanism",
    titlesize = 24,
    xlabel = "x direction",
    xlabelsize = 24,
    xminorticksvisible = true,
    xminorgridvisible = true,
    xminorticks = IntervalsBetween(5),
    ylabel = "y direction",
    ylabelsize = 24,
)

# 修正后的连杆绘制代码
dLine = lines!(ax, [0,R1_x2], [0,R1_y2], color = "orange", linewidth=3)
aLine = lines!(ax, @lift([0, $R2_x2]), @lift([0, $R2_y2]), color = "red", linewidth=3)
bLine = lines!(ax, @lift([$R2_x2, $R3_x_12]), @lift([$R2_y2, $R3_y_12]), color = "blue", linewidth=3)
cLine = lines!(ax, @lift([$R1_x2, $R3_x_12]), @lift([$R1_y2, $R3_y_12]), color = "black", linewidth=3)

# 添加连杆端点标记
scatter!(ax, [0, R1_x2], [0, R1_y2], color="orange", markersize=10)
scatter!(ax, @lift([$R2_x2]), @lift([$R2_y2]), color="red", markersize=10)
scatter!(ax, @lift([$R3_x_12]), @lift([$R3_y_12]), color="blue", markersize=10)

# 创建图例
Legend(
    fig[1,2],
    [dLine, aLine, bLine, cLine],
    ["d [R1]", "a [R2]", "b [R3]","c [R4]"],
    height = 400,
    width = 150
)

# 创建滑块网格
sg = SliderGrid(
    fig[2, 1],
    (label = "θ2 (rad)", range = -π:0.01:π, format = "{:.2f}", startvalue = .523),
    width = 800
)

sliderobservables = [s.value for s in sg.sliders]
connect!(RadTheta2_2, sliderobservables[1])

display(fig)

内容的提问来源于stack exchange,提问作者Volarus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:02:02