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