201 lines
7.8 KiB
C#
201 lines
7.8 KiB
C#
|
|
using System;
|
|||
|
|
using CaeKnowledge.Data;
|
|||
|
|
using ToolPathParser;
|
|||
|
|
|
|||
|
|
namespace CaeCuttingForce.FlatendCutter
|
|||
|
|
{
|
|||
|
|
public class LineForce
|
|||
|
|
{
|
|||
|
|
private const double PI = Math.PI;
|
|||
|
|
private const double AngularIncrement = 0.006; // h1
|
|||
|
|
private const double AxialIncrement = 0.006; // da
|
|||
|
|
|
|||
|
|
public void CalculateCuttingForce(int direction, ToolPosition position, CuttingForceCoefficients coefficients, ToolParameters toolParams)
|
|||
|
|
{
|
|||
|
|
// 刀具参数
|
|||
|
|
int N = toolParams.NumberOfTeeth; // 刀齿数 N
|
|||
|
|
double RAD = toolParams.ToolRadius; // 刀具半径 RAD
|
|||
|
|
double beta = toolParams.HelixAngle; // 刀具螺旋角 beta
|
|||
|
|
double Ap = position.AxialDepth; // 轴向切削深度 Ap
|
|||
|
|
double Ae = position.RadialDepth; // 径向切削深度 Ae
|
|||
|
|
double nrot = position.SpindleSpeed; // 主轴转速 n
|
|||
|
|
double fd = position.FeedRate; // 进给速度 fd
|
|||
|
|
|
|||
|
|
// 计算中间变量
|
|||
|
|
double thetaPit = 2.0 * PI / N; // 齿间角
|
|||
|
|
double kb = Math.Tan(beta * PI / 180.0) / RAD; // 刀具常数
|
|||
|
|
double c = fd / (nrot * N); // 每齿进给量
|
|||
|
|
|
|||
|
|
// 计算切入角和切出角
|
|||
|
|
double thetaSt = Math.Asin(1 - Ae / RAD); // 切入角
|
|||
|
|
double thetaEx = 0.5 * PI; // 切出角
|
|||
|
|
|
|||
|
|
// 计算角向和轴向积分数目
|
|||
|
|
int K = (int)Math.Floor(2.0 * PI / AngularIncrement); // 角向积分步数
|
|||
|
|
int L = (int)Math.Floor(Ap / AxialIncrement); // 轴向积分步数
|
|||
|
|
|
|||
|
|
// 初始化结果数组
|
|||
|
|
double[] Fx = new double[K];
|
|||
|
|
double[] Fy = new double[K];
|
|||
|
|
double[] Fz = new double[K];
|
|||
|
|
double[] Fx_global = new double[K];
|
|||
|
|
double[] Fy_global = new double[K];
|
|||
|
|
double[] Fz_global = new double[K];
|
|||
|
|
|
|||
|
|
int M = L * N * K;
|
|||
|
|
double[] Px = new double[M];
|
|||
|
|
double[] Qx = new double[M];
|
|||
|
|
double[] h = new double[M];
|
|||
|
|
|
|||
|
|
double[] R1 = new double[N * K];
|
|||
|
|
|
|||
|
|
int m = 0;
|
|||
|
|
int n = 0;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 主计算循环
|
|||
|
|
for (int i = 0; i < K; i++)
|
|||
|
|
{
|
|||
|
|
double R_val = i * AngularIncrement; // 螺旋槽底部切削刃的接触角
|
|||
|
|
|
|||
|
|
for (int k = 0; k < N; k++)
|
|||
|
|
{
|
|||
|
|
R1[n] = R_val + k * thetaPit; // 第k个齿当前角度的位置
|
|||
|
|
double R2 = R1[n];
|
|||
|
|
|
|||
|
|
for (int j = 0; j < L; j++)
|
|||
|
|
{
|
|||
|
|
double alph = (j + 1) * AxialIncrement;
|
|||
|
|
R2 = R1[n] - kb * alph;
|
|||
|
|
|
|||
|
|
// 角度规范化到 [0, 2π]
|
|||
|
|
while (R2 > 2.0 * PI)
|
|||
|
|
R2 -= 2.0 * PI;
|
|||
|
|
while (R2 < 0)
|
|||
|
|
R2 += 2.0 * PI;
|
|||
|
|
|
|||
|
|
//R3[m] = R2;
|
|||
|
|
|
|||
|
|
// 计算Px和Qx
|
|||
|
|
Px[m] = (RAD - Ae) / Math.Tan(R2);
|
|||
|
|
double Ox = RAD * Math.Cos(thetaSt) - c;
|
|||
|
|
Qx[m] = (RAD - c * Math.Cos(R2)) * Math.Cos(R2);
|
|||
|
|
|
|||
|
|
if (R2 >= thetaSt && R2 <= thetaEx)
|
|||
|
|
{
|
|||
|
|
// 切削厚度计算
|
|||
|
|
if (Px[m] >= Ox)
|
|||
|
|
{
|
|||
|
|
h[m] = RAD - (RAD - Ae) / Math.Sin(R2);
|
|||
|
|
}
|
|||
|
|
else if (Qx[m] < Ox)
|
|||
|
|
{
|
|||
|
|
h[m] = c * Math.Cos(R2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算微分切削力
|
|||
|
|
double dft = (coefficients.ktc * h[m] + coefficients.kte) * AxialIncrement;
|
|||
|
|
double dfr = (coefficients.krc * h[m] + coefficients.kre) * AxialIncrement;
|
|||
|
|
double dfu = (coefficients.kuc * h[m] + coefficients.kue) * AxialIncrement;
|
|||
|
|
|
|||
|
|
if (direction == 1)
|
|||
|
|
{
|
|||
|
|
// 坐标变换矩阵
|
|||
|
|
double[,] T = {
|
|||
|
|
{ Math.Sin(R2), -Math.Cos(R2), 0 },
|
|||
|
|
{ Math.Cos(R2), Math.Sin(R2), 0 },
|
|||
|
|
{ 0, 0, 1 }
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
double fxComponent = T[0, 0] * dft + T[0, 1] * dfr + T[0, 2] * dfu;
|
|||
|
|
double fyComponent = T[1, 0] * dft + T[1, 1] * dfr + T[1, 2] * dfu;
|
|||
|
|
double fzComponent = T[2, 0] * dft + T[2, 1] * dfr + T[2, 2] * dfu;
|
|||
|
|
|
|||
|
|
Fx[i] += fxComponent;
|
|||
|
|
Fy[i] += fyComponent;
|
|||
|
|
Fz[i] += fzComponent;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
else if (direction == 2)
|
|||
|
|
{
|
|||
|
|
// 坐标变换矩阵
|
|||
|
|
double[,] T = {
|
|||
|
|
{ Math.Sin(R2), -Math.Cos(R2), 0 },
|
|||
|
|
{ Math.Cos(R2), Math.Sin(R2), 0 },
|
|||
|
|
{ 0, 0, -1 }
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
double fxComponent = T[0, 0] * dft + T[0, 1] * dfr + T[0, 2] * dfu;
|
|||
|
|
double fyComponent = T[1, 0] * dft + T[1, 1] * dfr + T[1, 2] * dfu;
|
|||
|
|
double fzComponent = T[2, 0] * dft + T[2, 1] * dfr + T[2, 2] * dfu;
|
|||
|
|
|
|||
|
|
Fx[i] += fxComponent;
|
|||
|
|
Fy[i] += fyComponent;
|
|||
|
|
Fz[i] += fzComponent;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
m++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
n++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (direction == 1)
|
|||
|
|
{
|
|||
|
|
// 坐标转换到工件坐标系
|
|||
|
|
Fx_global[i] = Fy[i];
|
|||
|
|
Fy_global[i] = -Fx[i];
|
|||
|
|
Fz_global[i] = Fz[i];
|
|||
|
|
}
|
|||
|
|
else if (direction == 2)
|
|||
|
|
{
|
|||
|
|
// 坐标转换到工件坐标系
|
|||
|
|
Fx_global[i] = Fy[i];
|
|||
|
|
Fy_global[i] = Fx[i];
|
|||
|
|
Fz_global[i] = -Fz[i];
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 计算并设置结果
|
|||
|
|
SetResults(position, Fx_global, Fy_global, Fz_global, K);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
private void SetResults(ToolPosition position, double[] Fx_global, double[] Fy_global, double[] Fz_global, int K)
|
|||
|
|
{
|
|||
|
|
// 计算平均值
|
|||
|
|
double sumFx = 0, sumFy = 0, sumFz = 0;
|
|||
|
|
for (int i = 0; i < K; i++)
|
|||
|
|
{
|
|||
|
|
sumFx += Fx_global[i];
|
|||
|
|
sumFy += Fy_global[i];
|
|||
|
|
sumFz += Fz_global[i];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double aFx = sumFx / K;
|
|||
|
|
double aFy = sumFy / K;
|
|||
|
|
double aFz = sumFz / K;
|
|||
|
|
|
|||
|
|
// 设置结果到position对象
|
|||
|
|
position.AverageFx = aFx;
|
|||
|
|
position.AverageFy = aFy;
|
|||
|
|
position.AverageFz = aFz;
|
|||
|
|
|
|||
|
|
// 计算最大值
|
|||
|
|
double maxFx = 0, maxFy = 0, maxFz = 0;
|
|||
|
|
for (int i = 0; i < K; i++)
|
|||
|
|
{
|
|||
|
|
if (Math.Abs(Fx_global[i]) > Math.Abs(maxFx)) maxFx = Fx_global[i];
|
|||
|
|
if (Math.Abs(Fy_global[i]) > Math.Abs(maxFy)) maxFy = Fy_global[i];
|
|||
|
|
if (Math.Abs(Fz_global[i]) > Math.Abs(maxFz)) maxFz = Fz_global[i];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
position.MaxFx = maxFx;
|
|||
|
|
position.MaxFy = maxFy;
|
|||
|
|
position.MaxFz = maxFz;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|