【不务正业】太空工程师自动导航v1.0 beta
//By dudujerry
//2021.4.17
//自动导航 v1.0 beta
Vector3D TARGET = new Vector3D(158267.95,-25453.61,-60794.93); List<IMyThrust> _thrusts = new List<IMyThrust>(); List<IMyShipController> _shipControls = new List<IMyShipController>(); List<IMyCameraBlock> _camera = new List<IMyCameraBlock>(); List<IMyGyro> _gyros = new List<IMyGyro>(); IMyShipController _cockpit; Vector3D _MaxAngleAcceleration; Vector3D _InitAngleVelocity; Vector3D targetThrustPower = new Vector3D(); Vector3D t = new Vector3D(); bool _dam; int debug = 0; double debug2 = 0; int _state; //0代表正在寻找位置,1代表降落 double _maxThrust; float _height; bool _flag = false ; float bac = 0,fr = 0,lef = 0 ,rig = 0,up = 0,down = 0; const string COCKPIT_NAME = "MainCockpit" ; const double MAX_DISTANCE = 2000; const double GYRO_I = 30; const double GYRO_D = 30; const double MAX_ERROR = 0.1; const double MAX_ANGLE_ERROR = 0.5; const double MAX_VELOCITY_ERROR = 0.5; const double GYRO_MULTEXTRA = 2; const int GYRO_T = 30; const float _ELE_MAX_ERROR = 2; const float _MIN_VELOCITY = 2; const float MAX_VELOCITY = 100; const double THRUST_I = 30; const double THRUST_D = 30; const int THRUST_T = 30; const double THRUST_MULTEXTRA = 1; const double _extra = 100; class PIDClass{ public double getPID( double d){ d_data.Add(d); if (d_data.Count == 1){ d_data.Add(d); } if (d_data.Count > T){ d_data.Remove(d_data[0]); } double sum_d = 0; foreach ( double i in d_data){ sum_d += i; } double fir = d + 1/I*(sum_d/d_data.Count) + D*(d_data[d_data.Count - 1] - d_data[d_data.Count - 2]); if (P2 == 0 || (fir >= 0 && P2 > 0)) return P * fir; //输出结果 else if (fir < 0 && P2 > 0){ return P2*fir; } return 0; } public void setMultiplier( int t, double p, double i, double d){ T = t; P = p; I = i; D = d; } public void setExtraMultiplier( double p2){ P2 = p2; } public PIDClass( int t, double p, double i, double d){ T = t; P = p; I = i; D = d; } private int T = 30; //周期,这个周期不是公式中的时间间隔T,而是储存累加结果的周期 private double P = 0.0001; //比例系数 private double I = 10; //积分系数 private double D = 50; //微分系数 private double P2 = 0; private List< double > d_data = new List< double >(); }; PIDClass gyroPIDX,gyroPIDY,gyroPIDZ; PIDClass thrustPIDX,thrustPIDY,thrustPIDZ; PIDClass thrustPIDY2,thrustPIDY3,thrustPIDZ2; PIDClass VthrustPIDX,VthrustPIDY,VthrustPIDZ; PIDClass VthrustPIDY2,VthrustPIDY3,VthrustPIDZ2; PIDClass VthrustPIDX4,VthrustPIDY4,VthrustPIDZ4; void PrintVector3D(Vector3D v){ Echo( "X=" +Math.Round(v.X,4).ToString()); Echo( "Y=" +Math.Round(v.Y,4).ToString()); Echo( "Z=" +Math.Round(v.Z,4).ToString()); } public void AddVector(Vector3D addvector,IMyShipController cockpit,List<IMyThrust> thrusts){ float ShipMass = cockpit.CalculateShipMass().PhysicalMass; //MatrixD refLookAtMatrix = MatrixD.CreateLookAt(new Vector3D(),cockpit.WorldMatrix.Forward, cockpit.WorldMatrix.Up); //addvector = Vector3D.TransformNormal(addvector,refLookAtMatrix); addvector = addvector*ShipMass; double totalG = addvector.Length() ; double totalthrust = 0; //debug foreach ( var thrust in thrusts){ thrust.ThrustOverride = 0; thrust.ThrustOverridePercentage = 0; var maxthrust = thrust.MaxEffectiveThrust; thrust.Enabled = false ; if (!thrust.IsFunctional){ continue ; } switch (cockpit.WorldMatrix.GetClosestDirection(thrust.WorldMatrix.Backward)) { //设定推力 case Base6Directions.Direction.Backward: thrust.ThrustOverridePercentage=(targetThrustPower.Z>0)?( float )targetThrustPower.Z:0; thrust.Enabled = (targetThrustPower.Z>0)? true : false ; if (addvector.Z > 0 && !_dam ){ thrust.Enabled = true ; float oldth = ( float )thrust.ThrustOverride; if (maxthrust <addvector.Z + thrust.ThrustOverride){ thrust.ThrustOverride = maxthrust; addvector.Z -= maxthrust - oldth; } else { thrust.ThrustOverride += ( float )addvector.Z; addvector.Z = 0; } } break ; case Base6Directions.Direction.Forward: thrust.ThrustOverridePercentage=(targetThrustPower.Z<0)?( float )-targetThrustPower.Z:0; thrust.Enabled = (targetThrustPower.Z<0)? true : false ; if (addvector.Z < 0&& !_dam){ thrust.Enabled = true ; float fz = (-1) * ( float )addvector.Z; float oldth = ( float )thrust.ThrustOverride; if (maxthrust <fz + oldth){ thrust.ThrustOverride = maxthrust; addvector.Z += maxthrust - oldth; } else { thrust.ThrustOverride += fz; addvector.Z = 0; } } break ; case Base6Directions.Direction.Right: thrust.ThrustOverridePercentage=(targetThrustPower.X>0)?( float )targetThrustPower.X:0; thrust.Enabled = (targetThrustPower.X>0)? true : false ; if (addvector.X > 0&& !_dam){ thrust.Enabled = true ; float oldth = ( float )thrust.ThrustOverride; if (maxthrust <addvector.X + oldth){ thrust.ThrustOverride = maxthrust; addvector.X -= maxthrust - oldth; } else { thrust.ThrustOverride += ( float )addvector.X; addvector.X = 0; } } break ; case Base6Directions.Direction.Left: thrust.ThrustOverridePercentage=(targetThrustPower.X<0)?( float )-targetThrustPower.X:0; thrust.Enabled = (targetThrustPower.X<0)? true : false ; if (addvector.X < 0&& !_dam){ thrust.Enabled = true ; float fz = (-1) * ( float )addvector.X; float oldth = ( float )thrust.ThrustOverride; if (maxthrust <fz + oldth){ thrust.ThrustOverride = maxthrust; addvector.X += maxthrust - oldth; } else { thrust.ThrustOverride += fz; addvector.X = 0; } } break ; case Base6Directions.Direction.Up: thrust.ThrustOverridePercentage=(targetThrustPower.Y>0)?( float )targetThrustPower.Y:0; thrust.Enabled = (targetThrustPower.Y>0)? true : false ; if (addvector.Y > 0&& !_dam){ thrust.Enabled = true ; float oldth = ( float )thrust.ThrustOverride; if (maxthrust <addvector.Y + oldth){ thrust.ThrustOverride = maxthrust; addvector.Y -= maxthrust - oldth; } else { thrust.ThrustOverride += ( float )addvector.Y; addvector.Y = 0; int th = ( int )thrust.ThrustOverride; } } break ; case Base6Directions.Direction.Down: thrust.ThrustOverridePercentage=(targetThrustPower.Y<0)?( float )-targetThrustPower.Y:0; thrust.Enabled = (targetThrustPower.Y<0)? true : false ; if (addvector.Y < 0&& !_dam){ thrust.Enabled = true ; float fz = (-1) * ( float )addvector.Y; float oldth = ( float )thrust.ThrustOverride; if (maxthrust <fz + oldth){ thrust.ThrustOverride = maxthrust; addvector.Y += maxthrust - oldth; } else { thrust.ThrustOverride += fz; addvector.Y = 0; } } break ; } totalthrust += thrust.ThrustOverride; //debug } } void SetGyros( double pitch, double yaw, double roll){ foreach ( var gyro in _gyros){ gyro.Enabled = true ; gyro.GyroOverride = true ; //gyro.Roll = (float)roll; //gyro.Pitch = (float)pitch; //gyro.Yaw = (float)yaw; if (pitch == 0 && yaw == 0 && roll == 0) gyro.GyroOverride = false ; switch (_cockpit.WorldMatrix.GetClosestDirection(gyro.WorldMatrix.Backward)) { //正右负左,正上负下 case Base6Directions.Direction.Forward: gyro.Pitch = ( float )-pitch; gyro.Yaw = ( float )yaw; gyro.Roll = ( float )-roll; break ; case Base6Directions.Direction.Backward: gyro.Pitch = ( float )pitch; gyro.Yaw = ( float )yaw; gyro.Roll = ( float )roll; break ; case Base6Directions.Direction.Right: gyro.Pitch = ( float )roll; gyro.Roll = ( float )-pitch; gyro.Yaw = ( float )yaw; break ; case Base6Directions.Direction.Left: gyro.Pitch = ( float )roll; gyro.Roll = ( float )-pitch; gyro.Yaw = ( float )yaw; break ; case Base6Directions.Direction.Down: gyro.Pitch = ( float )pitch; gyro.Roll = ( float )-yaw; gyro.Yaw = ( float )roll; break ; case Base6Directions.Direction.Up: gyro.Roll = ( float )yaw; gyro.Pitch = ( float )-pitch; gyro.Yaw = ( float )roll; break ; } } } bool InitGyros(){ //测陀螺仪最大角加速度 if (_MaxAngleAcceleration.Length() != 0){ //若已经测过了,返回 return true ; } Vector3D angularVelocity = _cockpit.GetShipVelocities().AngularVelocity; MatrixD refLookAtMatrix = MatrixD.CreateLookAt( new Vector3D(), _cockpit.WorldMatrix.Forward, _cockpit.WorldMatrix.Up); Vector3D meAngleVelocityToMe = Vector3D.TransformNormal(angularVelocity, refLookAtMatrix); //(*)- double meRollAngleVelocity = meAngleVelocityToMe.Z*180/Math.PI; //当前角速度 double mePitchAngleVelocity = meAngleVelocityToMe.X*180/Math.PI; double meYawAngleVelocity = meAngleVelocityToMe.Y*180/Math.PI; //得到当前帧的角速度(*)- if (_InitAngleVelocity.Length() == 0){ _InitAngleVelocity = new Vector3D(mePitchAngleVelocity,meYawAngleVelocity,meRollAngleVelocity); SetGyros(60,60,60); } else { _MaxAngleAcceleration = new Vector3D((mePitchAngleVelocity - _InitAngleVelocity.X)*60,(meYawAngleVelocity - _InitAngleVelocity.Y)*60,(meRollAngleVelocity - _InitAngleVelocity.Z)*60); //计算最大角加速度,由于一秒60帧所以乘60 //gys.SetOverride(false); //gys.Yaw = gys.Pitch = 0; //返回原状态(*)- SetGyros(0,0,0); double P = 60/(GYRO_T*(1/GYRO_I*180+GYRO_D*180))*GYRO_MULTEXTRA; gyroPIDX.setMultiplier(GYRO_T,P,1/GYRO_I,GYRO_D); gyroPIDY.setMultiplier(GYRO_T,P,1/GYRO_I,GYRO_D); gyroPIDZ.setMultiplier(GYRO_T,P,1/GYRO_I,GYRO_D); } return false ; } bool gyroOperation(Vector3D target){ Vector3D err = new Vector3D(target.X,target.Y,target.Z); if (err.Length() <= MAX_ERROR) return true ; Vector3D nowtarget = new Vector3D(gyroPIDX.getPID(target.X),-gyroPIDY.getPID(target.Y),gyroPIDZ.getPID(target.Z)); SetGyros(nowtarget.X,nowtarget.Y,nowtarget.Z); return false ; } public static double TargetAngleToMe(Vector3D targetToMe, string direction){ targetToMe = Vector3D.Normalize(targetToMe); Vector3D zForward = new Vector3D(0,0,-1); targetToMe.X *= -1; //SE中,前负后正,右负左正,上负下正 targetToMe.Y *= -1; targetToMe.Z *= -1; if (direction == "Yaw" ){ Vector3D targetYawVector = new Vector3D(targetToMe.X,0,targetToMe.Z); return Math.Atan2(targetToMe.X,targetToMe.Z) * 180/Math.PI; } else if (direction == "Pitch" ){ Vector3D targetYawVector = new Vector3D(0,targetToMe.Y,targetToMe.Z); return Math.Atan2(targetToMe.Y,targetToMe.Z) * 180/Math.PI; } else if (direction == "Roll" ){ Vector3D targetRollVector = new Vector3D(targetToMe.X,targetToMe.Y,0); return Math.Atan2(targetToMe.X,targetToMe.Y) * 180/Math.PI; } return 0; } Vector3D GetTarget( string str){ //解析坐标 return new Vector3D(0,0,0); } public Program() { // 构造函数,每次脚本运行时会被首先调用一次。用它来初始化脚本。 // 构造函数是可选项, // 如不需要可以删除。 // // 建议这里设定RuntimeInfo.UpdateFrequency, // 这样脚本就不需要定时器方块也能自动运行了。 Runtime.UpdateFrequency = UpdateFrequency.Update1; _MaxAngleAcceleration = new Vector3D(); _InitAngleVelocity = new Vector3D(); debug = 0; gyroPIDX = new PIDClass(GYRO_T,1,1/GYRO_I,GYRO_D); gyroPIDY = new PIDClass(GYRO_T,1,1/GYRO_I,GYRO_D); gyroPIDZ = new PIDClass(GYRO_T,1,1/GYRO_I,GYRO_D); GridTerminalSystem.GetBlocksOfType<IMyGyro>(_gyros); GridTerminalSystem.GetBlocksOfType<IMyShipController>(_shipControls); GridTerminalSystem.GetBlocksOfType<IMyCameraBlock>(_camera); GridTerminalSystem.GetBlocksOfType<IMyThrust>(_thrusts); foreach ( var cam in _camera){ cam.EnableRaycast = true ; } bool flag = false ; foreach ( var coc in _shipControls){ if (coc.CustomName == COCKPIT_NAME){ _cockpit = coc; flag = true ; } } if (!flag) _cockpit = _shipControls[0]; MatrixD refLookAtMatrix = MatrixD.CreateLookAt( new Vector3D(), _cockpit.WorldMatrix.Forward, _cockpit.WorldMatrix.Up); SetTarget(); /*if(_cockpit.GetNaturalGravity().Length() != 0){ Vector3D v3d = new Vector3D(); _cockpit.TryGetPlanetPosition(out v3d); Vector3D tar_p = Vector3D.Normalize(t - v3d); Vector3D me_p = Vector3D.Normalize(_cockpit.CenterOfMass - v3d); double angle = Math.Abs(Math.Acos(Vector3D.Dot(tar_p,me_p)/Math.Abs(tar_p.Length()*me_p.Length()))*180/Math.PI); v3d = Vector3D.TransformNormal(t - v3d,refLookAtMatrix); _height = (float)v3d.Length(); double ele = 0; _cockpit.TryGetPlanetElevation(MyPlanetElevation.Surface,out ele); }*/ foreach ( var thrust in _thrusts){ switch (_cockpit.WorldMatrix.GetClosestDirection(thrust.WorldMatrix.Backward)) { case Base6Directions.Direction.Backward: bac += thrust.MaxEffectiveThrust; break ; case Base6Directions.Direction.Forward: fr += thrust.MaxEffectiveThrust; break ; case Base6Directions.Direction.Left: lef += thrust.MaxEffectiveThrust; break ; case Base6Directions.Direction.Right: rig += thrust.MaxEffectiveThrust; break ; case Base6Directions.Direction.Up: up += thrust.MaxEffectiveThrust; _maxThrust += thrust.MaxEffectiveThrust; break ; case Base6Directions.Direction.Down: down += thrust.MaxEffectiveThrust; break ; } } bac /= _cockpit.CalculateShipMass().PhysicalMass; fr /= _cockpit.CalculateShipMass().PhysicalMass; lef /= _cockpit.CalculateShipMass().PhysicalMass; rig /= _cockpit.CalculateShipMass().PhysicalMass; up /= _cockpit.CalculateShipMass().PhysicalMass; down /= _cockpit.CalculateShipMass().PhysicalMass; Vector3D distance = t - _cockpit.CenterOfMass; t = Vector3D.TransformNormal(distance, refLookAtMatrix); if (distance.X < 0) distance.X = -distance.X; if (distance.Y < 0) distance.Y = -distance.Y; if (distance.Z < 0) distance.Z = -distance.Z; thrustPIDX = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*lef/((THRUST_I+THRUST_D+1)*MAX_VELOCITY),THRUST_I,THRUST_D); thrustPIDY = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*down/((THRUST_I+THRUST_D+1)*MAX_VELOCITY),THRUST_I,THRUST_D); thrustPIDZ = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*bac/((THRUST_I+THRUST_D+1)*MAX_VELOCITY),THRUST_I,THRUST_D); //debug2 = angle; VthrustPIDX = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*MAX_VELOCITY/((THRUST_I+THRUST_D+1)*distance.X),THRUST_I,THRUST_D); VthrustPIDY = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*MAX_VELOCITY/((THRUST_I+THRUST_D+1)*distance.Y),THRUST_I,THRUST_D); VthrustPIDZ = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*MAX_VELOCITY/((THRUST_I+THRUST_D+1)*distance.Z),THRUST_I,THRUST_D); VthrustPIDX4 = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*MAX_VELOCITY/((THRUST_I+THRUST_D+1)*distance.X),THRUST_I,THRUST_D); VthrustPIDY4 = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*MAX_VELOCITY/((THRUST_I+THRUST_D+1)*distance.Y),THRUST_I,THRUST_D); VthrustPIDZ4 = new PIDClass(THRUST_T,10*THRUST_MULTEXTRA*MAX_VELOCITY/((THRUST_I+THRUST_D+1)*distance.Z),THRUST_I,THRUST_D); thrustPIDX.setExtraMultiplier(20*THRUST_MULTEXTRA*rig/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY)); thrustPIDY.setExtraMultiplier(20*THRUST_MULTEXTRA*up/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY)); thrustPIDZ.setExtraMultiplier(20*THRUST_MULTEXTRA*fr/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY)); _cockpit.DampenersOverride = false ; } public void Save() { // 当程序需要保存时,会发出提醒。使用这种方法可以将状态保存 // 至内存或其他路径。此为备选项, // 如果不需要,可以删除。 foreach ( var thrust in _thrusts){ thrust.Enabled = true ; thrust.ThrustOverridePercentage = 0; } foreach ( var gyro in _gyros){ gyro.Enabled = true ; gyro.GyroOverride = false ; } } void SetTarget() { t = TARGET; } float GetH( float v){ MatrixD refLookAtMatrix = MatrixD.CreateLookAt( new Vector3D(), _cockpit.WorldMatrix.Forward, _cockpit.WorldMatrix.Up); float ShipMass = _cockpit.CalculateShipMass().PhysicalMass; Vector3D g = _cockpit.GetNaturalGravity(); float totalg = ( float )g.Length(); float upv = ( float )((_maxThrust - ShipMass*totalg) / (ShipMass)); //Echo("upv" + upv.ToString()); Vector3D V = Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix); float vv = ( float )V.Length(); float nowv = vv; float t = vv/upv; float x = ( float )(vv*t - 0.5*upv*t*t); float totalh = x; Echo( "x = " + x.ToString()); return totalh + ( float )_extra; } public void Main( string argument, UpdateType updateSource) { /*foreach(var thrust in _thrusts){ thrust.Enabled = true; thrust.ThrustOverridePercentage = 0; } foreach(var gyro in _gyros){ gyro.Enabled = true; gyro.GyroOverride = false; } return;*/ Echo( "State=" +_state.ToString()); targetThrustPower = new Vector3D(); if (InitGyros() == false ) return ; _dam = _cockpit.DampenersOverride; MatrixD refLookAtMatrix = MatrixD.CreateLookAt( new Vector3D(), _cockpit.WorldMatrix.Forward, _cockpit.WorldMatrix.Up); Vector3D V = Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix); SetTarget(); Vector3D g = _cockpit.GetNaturalGravity(); float totalg = ( float )g.Length(); if (_dam == true ) targetThrustPower=-Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix); if (totalg == 0) { t = t - _cockpit.CenterOfMass; t = Vector3D.TransformNormal(t, refLookAtMatrix); // Vector3D tar = new Vector3D(TargetAngleToMe(t, "Pitch" ),TargetAngleToMe(t, "Yaw" ),0); AddVector( new Vector3D(0,0,0),_cockpit,_thrusts); if (!gyroOperation(tar)) return ; if (!_cockpit.DampenersOverride)targetThrustPower = new Vector3D(0,0,0); foreach ( var cam in _camera){ int timebeforeray = cam.TimeUntilScan(MAX_DISTANCE); if (timebeforeray > 0) continue ; MyDetectedEntityInfo info = cam.Raycast(MAX_DISTANCE,0,0); if (!info.IsEmpty()) _cockpit.DampenersOverride = true ; } if (!_cockpit.DampenersOverride){ //Vector3D a = new Vector3D(-thrustPIDX.getPID(t.X),thrustPIDY.getPID(t.Y),thrustPIDZ.getPID(t.Z)); double tarv = VthrustPIDZ4.getPID(-t.Z); double tara = thrustPIDZ.getPID(tarv + V.Z); Vector3D a = new Vector3D(0,0,-tara); Echo( "tarv = " + (tarv+V.Z).ToString()); Echo( "tara = " + tara.ToString()); if (Math.Abs(Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix).Z) >= 99) a = new Vector3D(0,0,0); AddVector(a,_cockpit,_thrusts); } } else { if (_flag == false ) { _state = -1; Vector3D v3d = new Vector3D(); _cockpit.TryGetPlanetPosition( out v3d); Vector3D tar_p = Vector3D.Normalize(t - v3d); Vector3D me_p = Vector3D.Normalize(_cockpit.CenterOfMass - v3d); double angle = Math.Abs(Math.Acos(Vector3D.Dot(tar_p,me_p)/Math.Abs(tar_p.Length()*me_p.Length()))*180/Math.PI); v3d = Vector3D.TransformNormal(_cockpit.CenterOfMass - v3d,refLookAtMatrix); _height = ( float )v3d.Length(); double ele = 0; _cockpit.TryGetPlanetElevation(MyPlanetElevation.Surface, out ele); thrustPIDY2 = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*down/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY),THRUST_I,THRUST_D); thrustPIDY3 = new PIDClass(THRUST_T,10*THRUST_MULTEXTRA*down/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY),THRUST_I,THRUST_D); //debug2 = THRUST_MULTEXTRA*down/((1/THRUST_I+THRUST_D+1)*_height); thrustPIDZ2 = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*bac/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY),THRUST_I,THRUST_D); VthrustPIDY2 = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*MAX_VELOCITY/((1/THRUST_I+THRUST_D+1)*_height),THRUST_I,THRUST_D); VthrustPIDY3 = new PIDClass(THRUST_T,30*THRUST_MULTEXTRA*MAX_VELOCITY/((1/THRUST_I+THRUST_D+1)*ele),THRUST_I,THRUST_D); //debug2 = THRUST_MULTEXTRA*down/((1/THRUST_I+THRUST_D+1)*_height); VthrustPIDZ2 = new PIDClass(THRUST_T,20*THRUST_MULTEXTRA*MAX_VELOCITY/((1/THRUST_I+THRUST_D+1)*angle),THRUST_I,THRUST_D); thrustPIDY2.setExtraMultiplier(20*THRUST_MULTEXTRA*up/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY)); thrustPIDY3.setExtraMultiplier(10*THRUST_MULTEXTRA*up/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY)); //debug2 = THRUST_MULTEXTRA*up/ele; thrustPIDZ2.setExtraMultiplier(20*THRUST_MULTEXTRA*fr/((1/THRUST_I+THRUST_D+1)*MAX_VELOCITY)); } _flag = true ; if (_state == -1){ double v = Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix).Length(); if (v > MAX_VELOCITY_ERROR) _cockpit.DampenersOverride = true ; else { _state = 0; _cockpit.DampenersOverride = false ; } AddVector( new Vector3D(0,0,0),_cockpit,_thrusts); } else if (_state == 0){ Vector3D plantPosition; _cockpit.TryGetPlanetPosition( out plantPosition); Vector3D tar_p = t - plantPosition; Vector3D me_p = _cockpit.CenterOfMass - plantPosition; double angle = Math.Abs(Math.Acos(Vector3D.Dot(tar_p,me_p)/Math.Abs(tar_p.Length()*me_p.Length()))*180/Math.PI); t = Vector3D.TransformNormal(t,refLookAtMatrix); g = Vector3D.TransformNormal(g,refLookAtMatrix); Vector3D gv = new Vector3D(TargetAngleToMe(g, "Pitch" )-90,TargetAngleToMe(t, "Yaw" ),TargetAngleToMe(g, "Roll" )); AddVector(-g,_cockpit,_thrusts); if (!gyroOperation(gv)) return ; Vector3D moveg = -g; double verr = VthrustPIDZ2.getPID(angle)+V.Z; moveg.Z = -thrustPIDZ2.getPID(verr); //解决,双重PID Echo( "angle_err = " +angle.ToString()); Echo( "velocity_err = " + verr.ToString()); Echo( "PID outcome = " + moveg.Z.ToString()); double z_v = V.Z; if (Math.Abs(z_v) >= MAX_VELOCITY-1 && z_v * moveg.Z > 0) moveg.Z = 0; plantPosition = Vector3D.TransformNormal(_cockpit.CenterOfMass-plantPosition,refLookAtMatrix); double vverr = VthrustPIDY2.getPID(_height - plantPosition.Length())-V.Y; double y2 = thrustPIDY2.getPID(vverr); //高了为负,待测试 Echo( "height_err = " + (_height - plantPosition.Length()).ToString()); Echo( "verr = " + vverr.ToString()); Echo( "PID outcome = " + y2.ToString()); moveg.Y += y2; moveg.Y += z_v*z_v/plantPosition.Length(); //***向心力 AddVector(moveg,_cockpit,_thrusts); if (angle <= MAX_ANGLE_ERROR) _state = 1; } else if (_state == 1){ double v = Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix).Length(); if (v > MAX_VELOCITY_ERROR) _cockpit.DampenersOverride = true ; else { _state = 2; _cockpit.DampenersOverride = false ; } AddVector( new Vector3D(0,0,0),_cockpit,_thrusts); } else if (_state == 2){ /* PID方法 * double ele = 0; _cockpit.TryGetPlanetElevation(MyPlanetElevation.Surface, out ele); g = Vector3D.TransformNormal(g,refLookAtMatrix); Vector3D gv = new Vector3D(TargetAngleToMe(g, "Pitch" )-90,0,TargetAngleToMe(g, "Roll" )); gyroOperation(gv); double verr = VthrustPIDY3.getPID(ele)-V.Y; Vector3D moveg = new Vector3D(0,-thrustPIDY3.getPID(verr)-g.Y,0); //待测试*** Echo( "ele err = " + ele.ToString()); Echo( "tar v = " + (verr+V.Y).ToString()); Echo( "PID outcome = " + (moveg.Y+g.Y).ToString()); double y_v = Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix).Y; if (y_v > MAX_VELOCITY-1 && y_v*moveg.Y > 0) moveg.Y = 0; AddVector(moveg,_cockpit,_thrusts);*/ double ele = 0; _cockpit.TryGetPlanetElevation(MyPlanetElevation.Surface, out ele); float minh = GetH(( float )_cockpit.GetShipSpeed()); g = Vector3D.TransformNormal(g,refLookAtMatrix); g = Vector3D.Normalize(g); Vector3D gv = new Vector3D(TargetAngleToMe(g, "Pitch" )-90,0,TargetAngleToMe(g, "Roll" )); gyroOperation(gv); AddVector( new Vector3D(0,0,0),_cockpit,_thrusts); //Vector3D V = Vector3D.TransformNormal(_cockpit.GetShipVelocities().LinearVelocity,refLookAtMatrix); if (ele <= _ELE_MAX_ERROR ){ _state = 3; } else if (ele <= minh && V.Y < 0 && -V.Y >= _MIN_VELOCITY){ targetThrustPower = -g; AddVector( new Vector3D(0,0,0),_cockpit,_thrusts); } } else if (_state == 3){ AddVector( new Vector3D(0,0,0),_cockpit,_thrusts); g = Vector3D.TransformNormal(g,refLookAtMatrix); g = Vector3D.Normalize(g); Vector3D gv = new Vector3D(TargetAngleToMe(g, "Pitch" )-90,TargetAngleToMe(t, "Yaw" ),TargetAngleToMe(g, "Roll" )); gyroOperation(gv); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2019-02-17 【OI】关于斯特林数的简单理解