列车多质点纵向动力学方程数值求解(C#)

本文介绍了一位作者使用C#编程语言,基于简单的动力学方程,对HXD单机和C70型货车54辆编组进行列车运行模拟的过程,主要展示了如何在WinForm中实现列车位置、速度和力的计算,旨在学习和验证列车纵向动力学模型。
摘要由CSDN通过智能技术生成
  **

前言

铁路设计院行车专业时长借助牵引电算软件进行列车运行模拟,出于兴趣,本文对多质点列车纵向动力学模型求解过程进行了分析。知网上搜了好多文章,看的不太懂,大多数都是采用Newmark或其它高级方法进行仿真。此文采用简单的动力学方程,以HXD单机,C70型货车54辆编组进行验证学习,纯C#代码实现,没有Matlab或其它仿真软件辅助。内容简单,期待有该方面大佬深入指点一二。模型及仿真按钮图片如下:案例纵断面情况图纵向动力学模型

补充说明

以下代码在WinForm窗体运行,需要两个控件,Button与ListBox,代码较简单,先读懂再修改运行。

代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TractionCalculation
{
    public partial class TrainDynamicsSolver : Form
    {
        public TrainDynamicsSolver()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            TrainDynamicsSolver solver = new TrainDynamicsSolver();
            solver.TimeStep = 0.0000008;
            solver.TotalTime = 0.08*2+0.03;
            solver.TrainLength = 55;
            solver.Mass = new double[(int)solver.TrainLength];
            solver.Position = new double[(int)solver.TrainLength];
            solver.Velocity = new double[(int)solver.TrainLength];
            solver.Force= new double[(int)solver.TrainLength];
            solver.couplingForce = new double[(int)solver.TrainLength];

            for (int i = 0; i < solver.TrainLength; i++)
            {
                if (i < solver.TrainLength - 1)
                {
                    solver.Mass[i] = 94;
                    solver.Position[i] = i * (14 + 14) / 2;
                }
                else
                {
                    solver.Mass[i] = 150;
                    solver.Position[i] = 1.0*(14 + 23) / 2 + (solver.TrainLength - 2) * (14 + 14) / 2.0;
                }
                solver.Velocity[i] = 0;
                if (i == solver.TrainLength - 1)
                {
                    solver.Force[i] = solver.GetTractionForce(solver.Velocity[i]);
                }
                else
                {
                    solver.Force[i] = 0;
                }
            }

            solver.Solve();

            // 输出结果
            listBox1.Items.Add("迭代完成!!!");
            //for (int i = solver.Mass.Length-1; i > -1; i--)
            //{
            //    listBox1.Items.Add("车辆:" + ((solver.Mass.Length - 1) - i)+"    "+"位置:"+ solver.Position[i] + "    " +"速度:"+ solver.Velocity[i]);
            //}
            //for (int i = solver.Mass.Length - 1; i >0; i--)
            //{
            //    listBox1.Items.Add("第"+ ((solver.Mass.Length - 1) - i) + "与"+ ((solver.Mass.Length - 1) - i+1) + "辆车"+"   位置差:" + (solver.Position[i]- solver.Position[i-1]) + "    " + "速度差:" + (solver.Velocity[i]- solver.Velocity[i-1]));
            //}
        }



        public double TimeStep { get; set; } // 时间步长
        public double TotalTime { get; set; } // 总时间
        public double TrainLength { get; set; } // 列车长度
        public double[] Mass { get; set; } // 各质点质量,以数组形式存储
        public double[] Position { get; set; } // 各质点位置,以数组形式存储
        public double[] Velocity { get; set; } // 各质点速度,以数组形式存储
        public double[] Force { get; set; }//各质点合力,以数组形式存储
        public double[] couplingForce { get; set; }//车钩力
        //public double a = 0.001;//位移限制数
        public double thetaValue=12;//坡度值
        public double lengthValue=2.6;//坡度长


        public void Solve()
        {
            int numParticles = Mass.Length; // 质点个数
            int numSteps = (int)(TotalTime / TimeStep); // 总步数
            StringBuilder[] str = new StringBuilder[Mass.Length];//输出结果
            for (int i = 0; i < str.Length; i++)
            {
                str[i] = new StringBuilder();
            }
            for (int i = 0; i < numSteps; i++)
            {
                double[] acceleration = CalculateAcceleration(Position, Velocity, Force,couplingForce); // 计算加速度
                for (int j = 0; j < numParticles; j++)
                {
                    Velocity[j] += acceleration[j] * TimeStep * 3600 * 3.6; // 更新速度
                    Position[j] += (1.0*Velocity[j] / 3.6) * (TimeStep*3600)+ acceleration[j] * (TimeStep*3600) * (TimeStep*3600) * 0.5; // 更新位置
                }

                // 存储结果
                if (i % 475 == 0)
                {
                    for (int j = Mass.Length - 1; j > -1; j--)
                    {
                        if (j > 0)
                        {
                            str[j].AppendLine("车辆:" + j + "    " + "位置:" + Position[j] + "    " + "速度:" + Velocity[j] + "    " + "车钩力:" + couplingForce[j] +
                              "    " + "位置差" + (Position[j] - Position[j - 1]) + "    " + "速度差:" + (Velocity[j] - Velocity[j - 1]));
                        }
                        else
                        {
                            str[j].AppendLine("车辆:" + j + "    " + "位置:" + Position[j] + "    " + "速度:" + Velocity[j] + "    " + "车钩力:" + couplingForce[j]);
                        }
                    }
                }
            }
            for (int i = 0; i < str.Length; i++)
            {
                //WritetoTxt(i.ToString(),str[i].ToString(), @"C:\Users\Administrator\Desktop\迭代结果\");
            }
        }

        /// <summary>
        /// 计算加速度
        /// </summary>
        /// <param name="position">位置数组</param>
        /// <param name="velocity">速度数组</param>
        /// <param name="force">合外力数组</param>
        /// <returns>加速度数组</returns>
        private double[] CalculateAcceleration(double[] position, double[] velocity, double[] netForce,double[] couplingForce)
        {
            int numParticles = position.Length;
            double[] acceleration = new double[numParticles];

            // 计算每个质点的加速度
            for (int i = 0; i < numParticles; i++)
            {
                double relativeVelocity, relativeDistance;
                if (i == 0) // 第一个质点
                {
                    relativeVelocity = (velocity[i + 1] - velocity[i])/3.6;
                    relativeDistance = position[i + 1] - position[i] - (14 + 14) / 2.0;
                    //if(relativeDistance>a)
                    //{
                    //    position[i]= position[i + 1] - a - (14 + 14) / 2;
                    //    relativeDistance = position[i + 1] - position[i] - (14 + 14) / 2;
                    //}
                    if (velocity[i] != 0)
                    {
                        if (position[i] > 2.5*1000 && position[i] < (2.5 + lengthValue)*1000)
                        {
                            couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                            netForce[i] = couplingForce[i] - GetBasicResistanceForce(i, velocity[i]) -
                            GetAdditionalResistanceForce(i, thetaValue, 0, double.MaxValue);
                        }
                        else
                        {
                            couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                            netForce[i] = couplingForce[i] - GetBasicResistanceForce(i, velocity[i]) -
                            GetAdditionalResistanceForce(i, 0, 0, double.MaxValue);
                        }
                    }
                    else
                    {
                        couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                        netForce[i] = couplingForce[i];
                    }
                        
                }
                else if (i == numParticles - 1) // 最后一个质点
                {
                    relativeVelocity = (velocity[i] - velocity[i - 1])/3.6;
                    relativeDistance = position[i] - position[i - 1] - (23 + 14) /2.0;
                    //if (relativeDistance > a)
                    //{
                    //    position[i] = position[i - 1] + a + (23 + 14) / 2;
                    //    relativeDistance = position[i] - position[i - 1] - (23 + 14) / 2;
                    //}
                    if (velocity[i] != 0)
                    {
                        if (position[i] > 2.5 * 1000 && position[i] < (2.5 + lengthValue) * 1000)
                        {
                            couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                            netForce[i] = GetTractionForce(velocity[i]) - couplingForce[i] - GetBasicResistanceForce(i, velocity[i]) -
                           GetAdditionalResistanceForce(i, thetaValue, 0, double.MaxValue);
                        }
                        else
                        {
                            couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                            netForce[i] = GetTractionForce(velocity[i]) - couplingForce[i] - GetBasicResistanceForce(i, velocity[i]) -
                          GetAdditionalResistanceForce(i, 0, 0, double.MaxValue);
                        }
                    }
                    else
                    {
                        couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                        netForce[i] = GetTractionForce(velocity[i]) - couplingForce[i];
                    }
                }
                else // 中间质点
                {
                    double relativeVelocity1;
                    double relativeDistance1;
                    relativeVelocity = (velocity[i] - velocity[i - 1])/3.6;
                    relativeVelocity1 = (velocity[i + 1] - velocity[i])/3.6;
                    relativeDistance = position[i] - position[i - 1] - (14 + 14) / 2;
                    //if (relativeDistance > a)
                    //{
                    //    position[i] = position[i - 1] + a + (14 + 14) / 2;
                    //    relativeDistance = position[i] - position[i - 1] - (14 + 14) / 2;
                    //}
                    if (i == numParticles - 2)
                    {
                        relativeDistance1 = position[i + 1] - position[i] - (23 + 14) / 2.0;
                        //if (relativeDistance1 > a)
                        //{
                        //    position[i] = position[i + 1] - a - (14 + 14) / 2;
                        //    relativeDistance1 = position[i + 1] - position[i] - (23 + 14) / 2;
                        //}
                    }
                    else
                    {
                        relativeDistance1 = position[i + 1] - position[i] - (14 + 14) / 2;
                        //if (relativeDistance1 > a)
                        //{
                        //    position[i] = position[i + 1] - a - (14 + 14) / 2;
                        //    relativeDistance1 = position[i + 1] - position[i] - (14 + 14) / 2;
                        //}
                    }
                    if (velocity[i] != 0)
                    {
                        if (position[i] > 2.5 * 1000 && position[i] < (2.5 + lengthValue) * 1000)
                        {
                            couplingForce[i+1] = GetCouplingForce(relativeVelocity1, relativeDistance1);
                            couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                            netForce[i] = couplingForce[i + 1] - couplingForce[i]
                            - GetBasicResistanceForce(i, velocity[i]) - GetAdditionalResistanceForce(i, thetaValue, 0, double.MaxValue);
                        }
                        else
                        {
                            couplingForce[i + 1] = GetCouplingForce(relativeVelocity1, relativeDistance1);
                            couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                            netForce[i] = couplingForce[i + 1] - couplingForce[i]
                           - GetBasicResistanceForce(i, velocity[i]) - GetAdditionalResistanceForce(i, 0, 0, double.MaxValue);
                        }
                    }
                    else
                    {
                        couplingForce[i + 1] = GetCouplingForce(relativeVelocity1, relativeDistance1);
                        couplingForce[i] = GetCouplingForce(relativeVelocity, relativeDistance);
                        netForce[i] = couplingForce[i + 1] - couplingForce[i];
                    }
                }
                acceleration[i] = netForce[i] / Mass[i];
            }
            return acceleration;
        }

        /// <summary>
        /// 获取车钩力
        /// </summary>
        /// <param name="relativeVelocity">相对速度</param>
        /// <param name="relativeDistance">相对位移</param>
        /// <returns>车钩力</returns>
        private double GetCouplingForce(double relativeVelocity, double relativeDistance)
        {
            double k = 20000;//单位:KN/m
            double d = 5000;//单位:KN/(m/s)
            return k * relativeDistance + d * relativeVelocity;
        }

        /// <summary>
        /// 获取机车牵引力
        /// </summary>
        /// <param name="speed">机车速度值</param>
        /// <returns>机车牵引力</returns>
        private double GetTractionForce(double speed)
        {
            if (speed < 10)
                speed = 10;
            return 288.2 + 99.29 * Math.Cos(0.02518 * speed) + 74.99 * Math.Sin(0.02518 * speed) +
                25.03 * Math.Cos(0.05036 * speed) - 12.82 * Math.Sin(0.05036 * speed) + 7.143 * Math.Cos(0.07554 * speed) -
                12.57 * Math.Sin(0.07554 * speed);
        }

        /// <summary>
        /// 获取基本阻力
        /// </summary>
        /// <param name="i">第i个质点</param>
        /// <param name="speed">速度</param>
        /// <returns>基本阻力</returns>
        private double GetBasicResistanceForce(int i, double speed)
        {
            if (i == Mass.Length - 1)//机车基本阻力
            {
                return (1.48 + 0.0018 * speed - 0.0003 * speed * speed) * Mass[i] * 9.8 / 1000;
            }
            else//车辆机车阻力
            {
                return (1.48 + 0.0018 * speed - 0.0003 * speed * speed) * Mass[i] * 9.8 / 1000;
            }
        }

        /// <summary>
        /// 获取附加阻力
        /// </summary>
        /// <param name="i">第i个质点</param>
        /// <param name="theta">坡道附加单位阻力</param>
        /// <param name="ls">隧道附加单位阻力</param>
        /// <param name="r">曲线附加单位阻力</param>
        /// <returns>附加阻力</returns>
        private double GetAdditionalResistanceForce(int i, double theta, double ls, double r)
        {
            return (theta + 0.00013 * ls + 600.0 / r) * Mass[i] * 9.8 / 1000;
        }

        /// <summary>
        /// 获取空气制动力
        /// </summary>
        /// <returns></returns>
        private double GetAirBrakeForce()
        {
            return 0;
        }

        /// <summary>
        /// 获取动力制动力
        /// </summary>
        /// <returns></returns>
        private double GetDynamicBrakeForce()
        {
            return 0;
        }

        /// <summary>
        /// 写入文本
        /// </summary>
        /// <param name="i">车辆序号</param>
        /// <param name="strContext">文本内容</param>
        /// <param name="strPath">文本路径</param>
        private void WritetoTxt(string i,string strContext,string strPath)
        {
            DirectoryInfo theFolder = new DirectoryInfo(strPath);
            if (theFolder.Exists)
            {
            }
            else
            {
                Directory.CreateDirectory(strPath);
            }
            using (FileStream fs = new FileStream(strPath +i.ToString()+ ".txt", FileMode.Append, FileAccess.Write, FileShare.Delete | FileShare.ReadWrite))
            {
                byte[] data = Encoding.UTF8.GetBytes(strContext);
                fs.Write(data, 0, data.Length);
                fs.Flush();
                fs.Close();
            }
        }
    }
}

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
质点弹道是指质点在空气中运动的轨迹,其受到空气阻力和重力的影响。根据运动学和动力学的基本原理,可以建立质点在空气中的运动方程,以描述其运动轨迹。假设质点的初始位置为 $(x_0,y_0,z_0)$,初始速度为 $(v_{x0},v_{y0},v_{z0})$,则质点在空气中的运动方程可以表示为: $$ \begin{aligned} x(t) &= x_0 + v_{x0}t \\ y(t) &= y_0 + v_{y0}t \\ z(t) &= z_0 + v_{z0}t - \frac{1}{2}gt^2 \\ \end{aligned} $$ 其中 $g$ 是重力加速度,$t$ 是时间。这个模型假设空气阻力对质点运动的影响可以忽略。在实际情况中,空气阻力是不可忽略的,因此需要考虑空气阻力对质点的影响。 考虑空气阻力对质点运动的影响,可以将动力学方程和欧拉动力学方程应用于质点的运动。动力学方程描述了质点运动时所受的力以及加速度之间的关系,欧拉动力学方程则描述了质点的运动状态以及其变化过程。根据动力学方程和欧拉动力学方程,可以得到质点在空气中的运动方程: $$ \begin{aligned} \frac{dx}{dt} &= v_x \\ \frac{dy}{dt} &= v_y \\ \frac{dv_x}{dt} &= -\frac{1}{2} \rho C_d A v_x^2 \frac{1}{m} \\ \frac{dv_y}{dt} &= -\frac{1}{2} \rho C_d A v_y^2 \frac{1}{m} \\ \frac{dz}{dt} &= v_z \\ \frac{dv_z}{dt} &= -g - \frac{1}{2} \rho C_d A v_z^2 \frac{1}{m} \\ \end{aligned} $$ 其中,$\rho$ 是空气密度,$C_d$ 是阻力系数,$A$ 是物体的参考面积,$m$ 是物体的质量。这个模型中,假设空气阻力的大小与速度的平方成正比,与速度的方向相反。 通过求解上述运动方程,可以得到质点在空气中的运动轨迹。需要注意的是,这个模型中假设空气阻力对质点运动的影响是恒定的,而实际情况中空气阻力也受到其他因素的影响,因此模型的精度可能会受到一定的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值