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变量值,联动更新连杆位置向量,实时刷新图形显示新的连杆位置。
问题根源
- Observable使用错误:绘制连杆时,直接将单个值的Observable(如
R2_x2)放入坐标数组([0, R2_x2]),生成了混合数值与Observable的数组。GLMakie在处理这种嵌套Observable时会陷入无限递归,最终耗尽栈内存导致溢出。 - 四连杆角度约束缺失:当前代码中
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
相关产品推荐
相关产品推荐

