//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); } } }