
三链轮弦长模型算法介绍
物理场景:
两个上链轮(A、B)水平对齐,中心距 a = 120mm;一个下链轮(C)悬挂在下方,形成三角形布局。链条绕过三个链轮,求底部链轮的垂直位置 h。
核心假设:弦长模型
链条是离散直线段(每节 p = 12.7mm),绕链轮时形成多边形包络,不是光滑圆弧。
三链轮系统总包角恒等于 360°(一个完整多边形),所以弧长部分:
arc = Z × p = 11 × 12.7 = 139.7 mm \text{arc} = Z \times p = 11 \times 12.7 = 139.7\text{mm} arc=Z×p=11×12.7=139.7mm
这是一个常量 ,不随 h 变化。
公式推导:
链条总长由三部分组成:
L = a + 2×diag + Z×p
其中 diag = √((a/2)² + h²) 是上链轮到下链轮的斜边长度。
由于 L = 节数 × p,可直接求解 h:
diag = (L - a - Z×p) / 2
h = √(diag² - (a/2)²)
计算步骤:
- 输入节数
n,算出链长L = n × 12.7 - 减去固定项:
剩余 = L - 120 - 139.7 - 每侧斜边:
diag = 剩余 / 2 - 勾股定理:
h = √(diag² - 60²)
结果示例(a=120mm, Z=11):
| 节数 | L(mm) | 2×斜边 | 弧长 | h(mm) |
|---|---|---|---|---|
| 41 | 520.7 | 261.0 | 139.7 | 115.9 |
| 42 | 533.4 | 273.7 | 139.7 | 123.0 |
| 43 | 546.1 | 286.4 | 139.7 | 130.0 |
与旧模型的对比:
旧模型用 R × 包角 计算弧长,需要牛顿迭代(因为包角随 h 变化)。新模型用 Z×p 常量弧长,直接求解,无需迭代,更简洁也更符合链条直线段的物理特性。
csharp
"""
根据链条节数计算底部链轮的垂直位置
从80mm开始,按每节12.7mm叠加链条长度,计算对应的垂直距离
弦长模型:链条为离散直线段,绕链轮形成多边形包络
三链轮系统总包角恒为360°,弧长部分 = Z*p(常量),不随h变化
公式: L = a + 2*sqrt((a/2)^2 + h^2) + Z*p
直接求解: h = sqrt(((L - a - Z*p)/2)^2 - (a/2)^2)
"""
import math
import json
def calculate_vertical_from_links():
"""
已知:
- 两上链轮水平中心距: 120mm (固定)
- 链条节距: 12.7mm
- 链条节数: 从某个起始值开始递增
- 弧长模型: Z*p 常量(链条为弦长,绕链轮形成多边形)
求:底部链轮到两上链轮中心连线的垂直距离
几何关系:
L = a + 2*sqrt((a/2)^2 + h^2) + Z*p
h = sqrt(((L - a - Z*p)/2)^2 - (a/2)^2)
"""
horizontal_center_dist = 120 # 两上链轮水平中心距 (mm)
pitch = 12.7 # 08B链条节距 (mm)
# 链轮参数
teeth = 11
pitch_circle_diameter = pitch / math.sin(math.pi / teeth)
pitch_circle_radius = pitch_circle_diameter / 2
# 弦长模型:弧长 = Z*p(常量,三链轮总包角=360°)
arc_length_const = teeth * pitch # 11 * 12.7 = 139.7mm
half_a = horizontal_center_dist / 2
results = []
print("=" * 100)
print("根据链条节数计算底部链轮垂直位置(弦长模型)")
print("=" * 100)
print(f"\n参数:")
print(f" 两上链轮水平中心距: {horizontal_center_dist} mm")
print(f" 链条节距: {pitch} mm")
print(f" 链轮齿数: {teeth}")
print(f" 节圆直径: {pitch_circle_diameter:.2f} mm")
print(f" 弧长(常量): Z*p = {teeth}*{pitch} = {arc_length_const:.1f} mm\n")
print(f"{'节数':<6} {'链条总长':<12} {'2x斜边':<12} {'弧长':<10} {'h(mm)':<12} {'备注'}")
print("-" * 80)
# 从33节开始,到50节
for num_links in range(33, 51):
chain_length = num_links * pitch
# 直接求解: L = a + 2*diag + Z*p
# diag = (L - a - Z*p) / 2
remainder = chain_length - horizontal_center_dist - arc_length_const
if remainder <= 0:
continue
diag = remainder / 2.0
# h = sqrt(diag^2 - (a/2)^2)
h_sq = diag**2 - half_a**2
if h_sq <= 0:
continue
h = math.sqrt(h_sq)
# 验证
calculated_length = horizontal_center_dist + 2 * diag + arc_length_const
final_error = abs(calculated_length - chain_length)
result = {
"chain_links": num_links,
"chain_length_mm": round(chain_length, 2),
"vertical_distance_mm": round(h, 3),
"diagonal_mm": round(diag, 3),
"arc_length_mm": round(arc_length_const, 2),
"calculated_length_mm": round(calculated_length, 2),
"error_mm": round(final_error, 3),
"note": f"{num_links}节链条"
}
results.append(result)
note_text = "可用" if 80 <= h <= 150 else "超出范围"
print(f"{num_links:<6} {chain_length:<12.1f} {2*diag:<12.1f} {arc_length_const:<10.1f} "
f"{h:<12.3f} {note_text}")
print("-" * 100)
print(f"\n共计算 {len(results)} 种节数配置")
# 过滤出h在80-150mm范围内的结果
valid_results = [r for r in results if 80 <= r['vertical_distance_mm'] <= 150]
output = {
"success": True,
"message": "计算完成(弦长模型)",
"parameters": {
"horizontal_center_distance_mm": horizontal_center_dist,
"pitch_mm": pitch,
"teeth": teeth,
"pitch_circle_diameter_mm": round(pitch_circle_diameter, 2),
"arc_length_const_mm": round(arc_length_const, 2),
"model": "L = a + 2*diag + Z*p"
},
"total_configurations": len(results),
"valid_configurations_80_150mm": len(valid_results),
"results": valid_results
}
with open('chain_vertical_by_links.json', 'w', encoding='utf-8') as f:
json.dump(output, f, indent=2, ensure_ascii=False)
print(f"\n有效结果(h 80-150mm范围)已保存到: chain_vertical_by_links.json")
print(f"共 {len(valid_results)} 个有效配置")
return valid_results
if __name__ == "__main__":
calculate_vertical_from_links()