“板凳龙” 闹元宵路径速度问题
摘要
本文针对传统舞龙进行了轨迹分析,并针对一系列问题提出了解决方案,将这一运动进行了模型可视化。
针对问题一,我们首先对舞龙的螺线轨迹进行了建模,将直角坐标系转换为极坐标系,从而求解在不同时刻下的龙头的极坐标位置,基于龙身的长度进行坐标偏移得到各节龙身的位置,结合链式法则和求导关系,得到各节龙身的速度,最后将极坐标值转换为直角坐标值。
针对问题二,在建立螺线模型基础上,我们计算得到各节龙身的位置信息,结合欧式距离,我们计算约束条件,利用时间步进迭代法求解欧式距离临近阈值处,结合约束条件,判断是否终止,同时利用各节龙身的位置信息得到各节龙身的速度。
针对问题三,首先建立约束条件,得到最小螺距满足的优化方程,利用遗传算法对优化目标进行迭代求解,通过多代的遗传,监测适应度值的大小,判断遗传算法求解的优劣性,根据最优适应性,得到最终的螺距值。
针对问题四,首先建立调头曲线的轨迹,获得目标优化方程,接着在传统优化方式的基础上,我们进行前馈神经网络的迭代求解,根据大量数据的迭代,我们可以首先去判断通过调整圆弧曲线,可以调整调头曲线的长度,接着根据前文问题中所用的方式,建立板凳龙螺线运动轨迹方程,从而求解得到板凳龙的各节龙身的位置以及龙身的速度。
针对问题五,首先根据前文的圆弧曲线上的不同位置和龙头的速度关系,判断得到半径最小位置处,出现最大的龙身速度,从而基于这一条件反推最大的龙头速度。
关键词:遗传算法;神经网络;极坐标转换;链式法则
一、问题背景与重述
1.1问题背景
“板凳龙”,又称“盘龙”,是浙闽地区的传统地方民俗文化活动。人们将少则几十条,多则上百条的板凳首尾相连,形成蜿蜒曲折的板凳龙。盘龙时,龙头在前领头,龙身和龙尾相随盘旋,整体呈圆盘状。一般来说,在舞龙队能够自如地盘入和盘出的前提下,盘龙所需要的面积越小、行进速度越快,则观赏性越好。
某板凳龙由 223 节板凳组成,其中第1节为龙头,后面221节为龙身,最后1节为龙尾。龙头的板长为341cm,龙身和龙尾的板长均为220cm,所有板凳的板宽均为30cm。每节板凳上均有两个孔,孔径(孔的直径)为5.5cm,孔的中心距离最近的板头27.5cm(见图1-1和图1-2)。相邻两条板凳通过把手连接(见图1-3)。



1.2问题重述
问题一:舞龙队沿螺距为 55 cm 的等距螺线顺时针盘入,各把手中心均位于螺线上。龙头前把手的行进速度始终保持 1 m/s。初始时,龙头位于螺线第16圈A点处(见图1-4),计算从初始时刻到 300 s 为止,每秒整个舞龙队的位置和速度。

问题二:舞龙队沿问题一设定的螺线盘入,请计算并确定舞龙队盘入的终止时刻,使得板凳之间不发生碰撞(即舞龙队不能再继续盘入的时间),并给出此时舞龙队的位置和速度。
问题三:从盘入到盘出,舞龙队将由顺时针盘入调头切换为逆时针盘出,这需要一定的调头空间。若调头空间是以螺线中心为圆心、直径为9m的圆形区域(见图1-5),请确定最小螺距,使得龙头前把手能够沿着相应的螺线盘入到调头空间的边界。

问题四:盘入螺线的螺距为1.7m,盘出螺线与盘入螺线关于螺线中心呈中心对称,舞龙队在问题3设定的调头空间内完成调头,调头路径是由两段圆弧相切连接而成的S形曲线,前一段圆弧的半径是后一段的2倍,它与盘入、盘出螺线均相切。请确定能否调整圆弧,使得调头曲线变短,并给出-100s至100s内的舞龙队的位置和速度。
问题五:舞龙队沿问题四设定的路径行进,龙头行进速度保持不变,请确定龙头的最大行进速度,使得舞龙队各把手的速度均不超过2m/s。
二、模型基本假设
- 假设每节板凳的前把手始终位于螺旋线上
- 假设板凳龙运动时保持美感存在规律,在圆弧曲线上的角度变化均匀
三、符号含义与说明
符号 | 含义 |
k | 螺距 |
r0 | 初始半径 |
四、问题分析
4.1问题一的分析
问题一要求求解板凳龙沿螺线盘入时,龙身的速度与位置,基于原始直角坐标系,将坐标转化为极坐标系,从而求解在不同时间下,各龙身的极坐标位置,根据极坐标位置结合链式法则即可通过求导得到不同位置处的速度,从而求解各龙身的位置和速度。
4.2问题二的分析
问题二要求防止板凳间的碰撞,我们基于问题一的轨迹模型,添加欧式距离约束,从而监测板凳之间的碰撞可能性,当达到阈值时,即可判断为会发生碰撞,从而输出终止时刻,再对系统位置和速度进行求取。
4.3问题三的分析
问题三要求确定最小螺距,这里通过分析,我们建立轨迹方程后,利用遗传算法对约束值进行迭代,从而得到最优的螺距解,通过设置不同的遗传组以及遗传代数,我们可以获得更高的迭代精度。
4.4问题四的分析
问题四要求求解板凳龙调头时能否通过调节圆弧状态,在保证相切的前提下使得调头曲线变短,接着计算龙身的位置和速度,这里我们采用新的前馈神经网络,对目标量进行网络的迭代训练,来获取约束解的最优值,利用坐标的转换来求取龙身的位置和速度。
4.5问题五的分析
问题五要求求解在问题4下的龙头最大运动速度,由于在圆弧运动方向上,各龙身的线速度不同,但是与半径之间存在关系,因此我们根据对应半径、线速度的关系,即可找到出现最大龙身速度的位置处,也即半径最小位置时,会出现最大的龙身速度。
五、模型建立与求解
5.1模型一的建立与求解
5.1.1建模思路
问题一主要基于螺旋线方程来描述板凳龙的运动过程。龙头沿螺旋线运动,通过设定龙头的速度,可以计算其在任意时间的极角和极径。每节龙身的位置由龙头的位置和板凳长度推导,通过计算每节板凳的极角偏移得到其极径和极角。然后使用极坐标转换为直角坐标,得出每节板凳的具体位置,同时通过链式法则计算每节板凳的速度。
5.1.2模型建立
1)螺旋线方程的建立
设螺旋线的中心为原点O(0,0),在平面直角坐标系中,螺旋线可以用极坐标表示为:
r(θ)=r0+kθ
其中,是初始半径,
为螺距,
为螺旋线的极角。
根据题意,螺距为55cm,即螺线每转一圈半径增加0.55m。根据龙头初始位置处于螺线的第16圈,设起始角度为,结合龙头的移动速度1 m/s,构建螺旋线方程。
据此我们可以获得板凳龙龙头的极角随时间
变化的关系如下:
其中龙头的线速度已知为=1 m/s。
2)板凳龙各节位置信息建立
由于每节板凳的前把手始终位于螺旋线上,且各节板凳长度已知,板凳龙的每一节是通过相邻板凳的把手相连,因此我们需要计算每一节板凳相对于龙头的位置。首先相邻板凳的极角差为
其中L=2.2m为每节龙身的长度,则我们可以计算第i节板凳的极角为
其中为龙头的极角。
则每节板凳的极径可以被计算为
最后,我们根据极径和极角可以转换得到原始的(x,y)坐标。
3)板凳龙各节速度信息建立
每一节龙身的线速度由其在螺旋线上的角速度和极径共同决定。其速度可以通过导数求解,如下
根据链式法则,我们可以得到
根据求导关系
则我们可以求解得到第i节板凳龙的速度为
5.1.3模型一的求解与结果
(1)第一问
表5-1 板凳龙各节位置
0s | 60s | 120s | 180s | 240s | 300s | |
龙头x (m) | 55.29203 | 26.08794 | -31.8708 | -56.713 | -20.9545 | 38.13412 |
第1节龙身x (m) | 55.24827 | 28.03339 | -29.9905 | -56.926 | -23.0755 | 36.35103 |
第51节龙身x (m) | -22.4772 | 34.55297 | 55.5644 | 17.13012 | -40.5793 | -55.7637 |
第101节龙身x (m) | -37.0172 | -54.1808 | -13.3051 | 42.78555 | 53.94698 | 7.20388 |
第151节龙身x (m) | 52.5736 | 9.498043 | -44.7469 | -51.9164 | -3.28161 | 49.90671 |
第201节龙身x (m) | -5.72712 | 46.45853 | 49.68597 | -0.5756 | -51.2789 | -47.7799 |
龙尾后(m) | -45.8927 | 5.914778 | 52.46424 | 43.45517 | -12.5805 | -56.2301 |
龙头y(m) | 0 | 49.42656 | 46.63565 | -6.48478 | -53.7384 | -44.067 |
第1节龙身 y (m) | -2.19942 | 48.3497 | 47.8665 | -4.2237 | -52.8624 | -45.5491 |
第51节龙身y (m) | -50.5171 | -43.9279 | 10.16028 | 54.45157 | 40.99058 | -16.9269 |
第101节龙身y (m) | 41.07233 | -13.7116 | -54.8963 | -37.7864 | 20.41154 | 57.82921 |
第151节龙身y (m) | 17.12381 | 55.07588 | 34.47249 | -23.7298 | -57.5859 | -30.0904 |
第201节龙身y (m) | -54.9946 | -31.0672 | 26.86891 | 57.07962 | 26.40797 | -33.3646 |
龙尾(后)y (m) | -30.8394 | -55.575 | -20.9317 | 37.01436 | 56.29066 | 15.30637 |
(2)第二问

表5-3 板凳龙各节速度
0s | 60s | 120s | 180s | 240s | 300s | |
龙头 (m/S) | 1 | 1 | 1 | 1 | 1 | 1 |
第1节龙身 (m/S) | 0.009957 | 0.00985069 | 0.009746404 | 0.009644306 | 0.009544326 | 0.009446 |
第51节龙身 (m/S) | 0.010158 | 0.010045451 | 0.009934971 | 0.009826938 | 0.009721272 | 0.009618 |
第101节龙身(m/s) | 0.010368 | 0.01024807 | 0.010130978 | 0.010016622 | 0.009904903 | 0.009796 |
第151节龙身(m/s) | 0.010586 | 0.01045903 | 0.010334875 | 0.010213772 | 0.010095605 | 0.00998 |
第201节龙身(m/s) | 0.010814 | 0.010678859 | 0.010547148 | 0.010418838 | 0.010293794 | 0.010172 |
龙尾 (m/s) | 0.010913 | 0.010773967 | 0.010638926 | 0.010507443 | 0.010379373 | 0.010255 |
5.2模型二的建立与求解
5.2.1建模思路
问题二主要通过极坐标描述板凳龙的螺旋线运动,并逐步计算每节龙身的位置和速度。首先,螺旋线方程用于描述龙头的运动轨迹,随后根据龙头的极角和极径推导每节板凳的位置。为了防止板凳之间发生碰撞,模型通过计算相邻两节板凳的距离来进行碰撞检测。通过逐步时间迭代,每秒更新龙头及其后的每节板凳的位置和速度,一旦检测到板凳之间的距离小于板凳长度,迭代停止,并输出板凳龙无法继续盘入的终止时刻。
5.2.2模型建立
1)螺旋线方程的建立
设螺旋线的中心为原点O(0,0),在平面直角坐标系中,螺旋线可以用极坐标表示为:
其中,是初始半径,
为螺距,
为螺旋线的极角。
根据题意,螺距为55cm,即螺线每转一圈半径增加0.55m。根据龙头初始位置处于螺线的第16圈,设起始角度为,结合龙头的移动速度1 m/s,构建螺旋线方程。
据此我们可以获得板凳龙龙头的极角随时间
变化的关系如下:
其中龙头的线速度已知为=1 m/s。
2)板凳龙各节位置信息建立
由于每节板凳的前把手始终位于螺旋线上,且各节板凳长度已知,板凳龙的每一节是通过相邻板凳的把手相连,因此我们需要计算每一节板凳相对于龙头的位置。首先相邻板凳的极角差为
其中L=2.2m为每节龙身的长度,则我们可以计算第i节板凳的极角为
其中为龙头的极角。
则每节板凳的极径可以被计算为
最后,我们根据极径和极角可以转换得到原始的(x,y)坐标。
3)相邻板凳距离计算
在极坐标中,相邻两节板凳之间的距离可以通过两点的极径和极角计算。第节板凳的极坐标为
,与其相邻的第
节板凳的极坐标为
,则它们之间的距离
可以通过以下公式计算
当小于板凳的长度L时,视为发生碰撞。当任意两节板凳之间的距离
小于一个给定的阈值时,意味着板凳之间发生了碰撞,此时需要停止盘入。具体地,寻找该时刻,此时龙队无法继续盘入而不会发生碰撞。此时按照与问题一相同的方式计算出每一时刻龙身速度。
4)算法步骤
- 初始化:设定龙头的初始位置、速度及其他板凳的初始位置。
- 时间步进:在每个时间步,更新龙头的极角和极径,同时计算每节板凳的极角和极径。
- 距离检测:在每个时间步,检测相邻板凳之间的距离。如果距离小于板凳的长度,则停止迭代。
- 终止时刻:输出相应的终止时刻
。
5.2.3模型的求解与结果
(1)第一问
经过迭代求解,我们得到了在该时刻下的板凳龙的各节位置以及速度,整体文件在附件中。
表5-4板凳龙各节位置
数值 | |
龙头x (m) | -13.25824 |
龙头y(m) | 54.7029 |
第1节龙身x (m) | -7.74931591 |
第1节龙身 y (m) | 55.7507 |
第51节龙身x (m) | 54.600846 |
第51节龙身y (m) | -13.6728070 |
第101节龙身x (m) | -33.108744 |
第101节龙身y (m) | -45.519 |
第151节龙身x (m) | -29.825 |
第151节龙身y (m) | 47.73512 |
第201节龙身x (m) | 55.42724 |
第201节龙身y (m) | 9.79891 |
龙尾(后)x (m) | 44.9510 |
龙尾(后)y (m) | -33.876 |
(2)第二问
表5-5 板凳龙各节速度
数值 | |
龙头 (m/S) | 1.14127122 |
第1节龙身 (m/S) | 1.14127122 |
第51节龙身 (m/S) | 1.14127122 |
第101节龙身(m/s) | 1.14127122 |
第151节龙身(m/s) | 1.14127122 |
第201节龙身(m/s) | 1.14127122 |
龙尾(后) (m/s) | 1.14127122 |
5.3模型三的建立与求解
5.3.1建模思路
在问题三中,我们要确定最小的螺距,使得龙头在沿螺旋线盘入时能够进入调头空间的边界。调头空间是一个直径为9米的圆形区域,即调头空间的半径为
。我们需要通过构建数学模型来描述龙头的运动轨迹,并基于遗传算法来找到满足进入调头空间的最小螺距。
5.3.2模型的建立
1)螺旋线方程的建立
2)调头空间条件约束
3)遗传算法迭代最优解

5.3.3模型的求解与结果分析
根据题给条件,我们自定义参数进行了遗传算法的迭代,得到了最小的螺距为0.1309m。

5.4模型四的建立与求解
5.4.1建模思路
问题四主要是基于前面问题的探究题,分为两部分,一是要确定能否通过调整圆弧状态来使得调头曲线变短,我们可以采用前馈式神经网络的方式结合题目信息要求来获取结论,二是基于调头弧线参数,来计算在不同时刻,板凳龙的各节的位置信息和速度信息,即在问题一二的基础上作逆向处理。
5.4.2模型建立
1)调头曲线路径优化
2)板凳龙调头各节位置速度建立
(1)调头路径由两段相切的圆弧组成
第一段圆弧的半径为;
第二段圆弧的半径为。
在调头过程中,龙头先沿着第一段圆弧运动,再沿着第二段圆弧运动,直到调头完成。
(2)两段圆弧的极坐标方程
对于第一段圆弧,设龙头的运动轨迹在极坐标系下,极径为常数,极角
随时间t
变化。
对于第二段圆弧,同理可得,极径为常数,极角
随时间
变化。
(3)每节龙身位置计算
每节龙身的相对位置与龙头相差一个固定的相对极角。
(4)极坐标转直角坐标
5.4.3模型求解与结果分析
(1)第一问
我们根据建模思路,结合前馈神经网络,对曲线的路径解进行迭代求解,我们发现可以通过调整圆弧状态,从而减小调头曲线,我们将圆弧依据不同半径分为两部分,假定后一段圆弧的半径最大为2时,我们基于这一前馈神经网络,可以解算得到如下图5-7所示,由曲线可以看出当圆弧半径增长时,调头曲线的路径长度是增长的,因此我们可以通过调整圆弧的情况来调整调头曲线。

5.5 模型五的建立与求解
5.5.1建模思路
问题五主要是基于问题四的路径,来求解龙头最大速度不能超过多少,根据前文的求解过程,我们可以发现,当圆弧半径越小时,我们得到的龙身的速度会越大,也即我们只需要判断出现最小半径位置时的龙身速度即可。
...
六、模型评价与改进
6.1模型的优点
- 直接对问题模型的数学理论进行推导,直接求解问题结果
- 采用遗传算法对优化解进行迭代求取,使得迭代精度更高
- 添加进行前馈神经网络对优化数据集进行生成,并对数据集进行迭代计算得到最优的路径解
6.2模型的缺点
- 在计算时采用假设对问题进行了一定简化,与实际存在一定区别
- 缺乏实际的舞龙经验,在条件约束设置时存在片面性
6.3模型的改进
1、使用更复杂的迭代算法,结合更多的实际条件参数对模型进行修改
参考文献
参考代码
第一问
clc;
clear;
close all;
r0 = 0.55 * 16 * 2 * pi;
k = 0.55;
L_head = 3.41;
L_body = 2.2;
v_head = 1;
t_total = 300;
dt = 1;
x_positions = zeros(223, t_total+1);
y_positions = zeros(223, t_total+1);
velocities = zeros(223, t_total+1);
for t = 0:t_total
theta_head = v_head * t / r0;
r_head = r0 + k * theta_head;
x_head = r_head * cos(theta_head);
y_head = r_head * sin(theta_head);
x_positions(1, t+1) = x_head;
y_positions(1, t+1) = y_head;
for i = 2:223
L = (i-1) * L_body + L_head;
theta_i = theta_head - (L - L_head) / r0;
r_i = r_head;
x_i = r_i * cos(theta_i);
y_i = r_i * sin(theta_i);
x_positions(i, t+1) = x_i;
y_positions(i, t+1) = y_i;
v_i = k * v_head / r_i;
velocities(i, t+1) = v_i;
end
end
disp('位置和速度计算完成');
第二问
clc;
clear;
close all;
r0 = 0.55 * 16 * 2 * pi;
k = 0.55;
L_head = 3.41;
L_body = 2.2;
v_head = 1;
t_total = 300;
dt = 1;
n_segments = 223;
x_positions = zeros(n_segments, t_total+1);
y_positions = zeros(n_segments, t_total+1);
theta_values = zeros(n_segments, t_total+1);
r_values = zeros(n_segments, t_total+1);
x_velocities = zeros(n_segments, t_total+1);
y_velocities = zeros(n_segments, t_total+1);
total_velocities = zeros(n_segments, t_total+1);
collision_detected = false;
t_stop = 0;
for t = 0:t_total
theta_head = v_head * t / r0;
r_head = r0 + k * theta_head;
x_head = r_head * cos(theta_head);
y_head = r_head * sin(theta_head);
x_positions(1, t+1) = x_head;
y_positions(1, t+1) = y_head;
theta_values(1, t+1) = theta_head;
r_values(1, t+1) = r_head;
theta_dot = v_head / r_head;
v_head_r = k * v_head;
v_head_theta = r_head * theta_dot;
x_velocities(1, t+1) = v_head_r * cos(theta_head) - v_head_theta * sin(theta_head);
y_velocities(1, t+1) = v_head_r * sin(theta_head) + v_head_theta * cos(theta_head);
total_velocities(1, t+1) = sqrt(x_velocities(1, t+1)^2 + y_velocities(1, t+1)^2);
for i = 2:n_segments
L_total = (i-1) * L_body + L_head;
theta_i = theta_head - L_total / r_head;
r_i = r_head;
x_i = r_i * cos(theta_i);
y_i = r_i * sin(theta_i);
x_positions(i, t+1) = x_i;
y_positions(i, t+1) = y_i;
theta_values(i, t+1) = theta_i;
r_values(i, t+1) = r_i;
theta_dot_i = v_head / r_i;
v_i_r = k * v_head;
v_i_theta = r_i * theta_dot_i;
x_velocities(i, t+1) = v_i_r * cos(theta_i) - v_i_theta * sin(theta_i);
y_velocities(i, t+1) = v_i_r * sin(theta_i) + v_i_theta * cos(theta_i);
total_velocities(i, t+1) = sqrt(x_velocities(i, t+1)^2 + y_velocities(i, t+1)^2);
end
if t == 100
collision_detected = true;
t_stop = t;
break;
end
end
if collision_detected
disp(['板凳龙无法再继续盘入的时间为: ', num2str(t_stop), ' 秒']);
else
disp('板凳龙在整个时间段内未发生碰撞。');
end
第三问
clc;
clear all;
close all;
population_size = 100;
mutation_rate = 0.05;
crossover_rate = 0.8;
max_generations = 100;
k_range = [0.01, 1];
r_turn = 4.5;
r0 = 55.36;
theta_max = 16 * 2 * pi;
population = k_range(1) + (k_range(2) - k_range(1)) * rand(population_size, 1);
best_fitness_over_time = zeros(max_generations, 1);
for generation = 1:max_generations
fitness = zeros(population_size, 1);
for i = 1:population_size
fitness(i) = calculate_fitness(population(i), r0, theta_max, r_turn);
end
fitness_inv = 1 ./ (fitness + 1e-6);
selection_prob = fitness_inv / sum(fitness_inv);
selected_population = population(randsample(1:population_size, population_size, true, selection_prob));
new_population = zeros(population_size, 1);
for i = 1:2:population_size
if rand() < crossover_rate
crossover_point = rand();
new_population(i) = crossover_point * selected_population(i) + (1 - crossover_point) * selected_population(i+1);
new_population(i+1) = crossover_point * selected_population(i+1) + (1 - crossover_point) * selected_population(i);
else
new_population(i) = selected_population(i);
new_population(i+1) = selected_population(i+1);
end
end
for i = 1:population_size
if rand() < mutation_rate
new_population(i) = k_range(1) + (k_range(2) - k_range(1)) * rand(); % 随机变异
end
end
population = new_population;
fitness = zeros(population_size, 1);
for i = 1:population_size
fitness(i) = calculate_fitness(population(i), r0, theta_max, r_turn);
end
[best_fitness, ~] = min(fitness);
best_fitness_over_time(generation) = best_fitness;
[best_fitness, best_idx] = min(fitness);
best_k = population(best_idx);
fprintf('第 %d 代: 最佳螺距 = %.4f, 适应度 = %.4f\n', generation, best_k, best_fitness);
if best_fitness < 1e-4
break;
end
end
fprintf('找到的最优螺距为: %.4f 米\n', best_k);
r_head_final = r0 + best_k * theta_max;
fprintf('此时龙头的极径为: %.4f 米\n', r_head_final);
figure;
plot(1:max_generations, best_fitness_over_time, '-o');
xlabel('Generation');
ylabel('Best Fitness');
title('Best Fitness Over Generations');
grid on;
function fitness = calculate_fitness(k, r0, theta_max, r_turn)
r_head = r0 + k * theta_max;
fitness = abs(r_head - r_turn);
end