(请注意,我也已将其发布到Yahoo! Groups上的Visual Basic 6编程列表中,但是自2017年以来似乎已经死了,所以我想我也将其发布在这里。)
我最近接管了一个正在工作的VB6程序,该程序具有一个例程,可以在给定轴点,导程测量,投影角,矢量(初始角,最终角)的情况下,将数据点从轴向平面转换为投影平面,渐变)和投影点。它被编写为一个返回布尔值以指示其是否成功的函数。
它必须从轴向计算旋转角度,然后使用牛顿-拉夫森迭代法确定该角度的值。它设置了执行此操作的30次迭代的上限,但是对于某些参数集,它无法在这30次迭代中找到解决方案。
请问有人知道执行此转换的替代方法吗?该程序用于驱动计算出数据点的CNC机床,我相信这些参数是有效的,只是所使用的方法阻止了它的进行。
我添加了日志记录输出代码以跟踪问题,发现它归结为轴向平面和投影平面之间的转换,并且投影角度具有特定的上限值(它也使用该值的+/-裕度作为过程的一部分)。
迭代代码无法找到在设定的最大尝试次数(30)之内的设定公差范围内的解决方案。
我尝试增加最大尝试次数,减少增量,增加容差,并减少所应用的边距值,但到目前为止,我没有做过任何工作,或者重复了相同的错误。
我期望输出是轮廓平面的数组,这些轮廓平面位于投影平面上,并且使用提供的导程测量和投影角度等于提供的轴向平面点,但是我遇到了一些错误,这些错误指示迭代过程无法找到最多30次尝试的解决方案。
编辑后添加:
我已经基于VB6代码编写了以下伪代码,以尝试解释该例程的工作方式:
'AxialPoint, ProjectedPoint: structures with ProfileRadius, ProfileWidth,
'NormalAngle, UnwrapAngle and Attribute fields
'Lead: lead measurement
'ProjectionAngle: projection angle onto the projected plane in degrees
'Vector(): provides initial value of Beta, Last Beta value found, Last
'gradient) - set by the calling routine as (0, 0, 0) in this case
'Beta is the angle of rotation from the axial plane
Function AxialToProjected(AxialPoint, Lead, ProjectionAngle, Vector(),
ProjectedPoint):
LeadAngle := Atn(Lead / (2 * PI * AxialPoint.ProfileRadius)) 'radians
SA := Sin(LeadAngle)
CA = Cos(LeadAngle)
CT := -CosD(AxialPoint.NormalAngle)
ST := SinD(AxialPoint.NormalAngle)
SG := SinD(ProjectionAngle)
CG := CosD(ProjectionAngle)
C1 := SA * CG * CT
C2 := CA * CG * ST
C3 := CA * SG * CT
Iteration := 0
FBeta := 0.0001
While (Abs(FBeta) >= 0.0001) And (Iteration < 9) Do
NewValue(Beta, OldBeta, FBeta, Increment:=0.1, Gradient, SVB(),
Iteration, Multiplier:=10)
SB := Sin(Beta)
CB := Cos(Beta)
OldFBeta := FBeta
FBeta := C1 * CB + C2 * SB - C3
If Iteration >= 2 Then
Gradient := (Beta - OldBeta) / (FBeta - OldFBeta)
End If
End While
If (Abs(FBeta) > 0.0001) Then
'The code reaches this point with the specific parameters
Report "Iteration failed to find a solution within 30 tries" error
Else
'The code doesn't reach this point
X3 := Beta * Lead / 2 * PI + AxialPoint.ProfileWidth
With ProjectedPoint Do
.ProfileWidth := X3 * CG - AxialPoint.ProfileRadius * SB * SG
.ProfileRadius := AxialPoint.ProfileRadius * CB
.NormalAngle := ATan2(CA * CB * CG * ST - SA * SB * CG * CT,
-CA * CT) * RadToDeg
.Attribute := AxialPoint.Attribute
.UnwrapAngle := AxialPoint.UnwrapAngle
End With
End If
End AxialToProjected()
SinD()和CosD()接受一个角度(度)并将其转换为弧度,然后再将其传递给正常的Sin()和Cos()函数。
NewValue()例程在增加Iteration值的同时,使用FBeta,Increment,Gradient,SVB()和Multiplier根据OldBeta的值计算Beta的新值:
'Beta: current axial plane rotation angle estimate
'OldBeta: previous current axial plane rotation angle estimate
'FBeta: gradient of tangent to the normal
'Increment: increment size to adjust Beta by
'Gradient: gradient for the Newton method
NewValue(Beta, OldBeta, FBeta, Increment, Gradient, SVB(), Iteration,
Multiplier):
If Iteration > 2 Then
MaxChange := Abs(Increment * Multiplier)
Change := -FBeta * Gradient
If Abs(Change) > MaxChange Then
Beta := Beta + TransferSign(MaxChange, Change)
'TransferSign() will return -MaxChange if Change < 0 or
'MaxChange if Change >= 0
Else
Beta := Beta + Change
End If
ElseIf Iteration = 2 Then
If SVB(3) = 0 Then
Beta := SVB(1) + Increment
Else
Beta := -FBeta * SVB(3)
End If
Else
Beta := SVB(1) 'Set Beta to initial value
End If
End NewValue()
稍后我将上传一个图,因为我需要弄清楚如何从我的涂鸦中绘制它:)
只是添加一些额外的上下文,该例程用于使用CNC机器计算ZA和ZN型蠕虫的点数。
每种类型只有一组特定的参数会导致错误发生,我相信这是由于初始估计值离根太远而无法在30次尝试限制内解决的,但我不是确定如何得出更好的初始估算值。