Welcome to Keen Software House Forums! Log in or Sign up to interact with the KSH community.
  1. You are currently browsing our forum as a guest. Create your own forum account to access all forum functionality.

Script done just once, no redoing with new parameters

Discussion in 'Programming Questions and Suggestions' started by rafcio_21, Feb 26, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. rafcio_21 Trainee Engineer

    Messages:
    11
    I am writting an autopilot script. I can already show on screen values, which allows me to aim manually to the destination point.

    The issue is that to set gyroscope, I need to repeat my instructions. Example of what I mean:
    Code:
    void Main() {
      var pos = GridTerminalSystem.GetBlockWithName("pos") as IMyGyro;
      var align = GridTerminalSystem.GetBlockWithName("align") as IMyTerminalBlock;
      var behind = GridTerminalSystem.GetBlockWithName("behind") as IMyTerminalBlock;
      VRageMath.Vector3D pos_cord = pos.GetPosition();
      VRageMath.Vector3D align_cord = align.GetPosition();
      VRageMath.Vector3D behind_cord = behind.GetPosition();
      Vector3D target = new Vector3D(0,0,0); 
      double dis;
      dis = Vector3D.Distance(align_cord,target);
      if( pos.GyroOverride == false) {
        pos.GetActionWithName("Override").Apply(pos);
      }
      double roll=1; //lewo ,prawo ,left, right
      double pitch=0; //gora ,dol ,up ,down
      double yaw=0; //obracanie, rolling, 1 = ~10 rpm
      pos.SetValue<float>("Roll",(float)roll);     
      pos.SetValue<float>("Pitch",(float)pitch);     
      pos.SetValue<float>("Yaw",(float)yaw);
      if(dis>2000) {
        roll=1;
        pos.SetValue<float>("Roll",(float)roll); 
      }
    }
    
    I want it to stop rolling when value dis<2000. But the script is executed just once. How can I manage to fix that?


    If I will end my script, it will align to destination point using only 2 align blocks/coords on both sides :)
     
  2. Igneous01 Apprentice Engineer

    Messages:
    266
    It only runs once because you are not looping it.

    The only thing that can accomplish this is a while or for loop

    Code:
    while (dis > 2000)
    {
        pos.SetValue<float>("Roll", (float)roll); 
    }
    
    Perhaps in the future we will be able to implement custom events for such things to reduce the redundant instructions of override.
     
  3. rafcio_21 Trainee Engineer

    Messages:
    11
    But when I put script into a while loop, starting script is saying that there is no Main() :/
     
  4. Igneous01 Apprentice Engineer

    Messages:
    266
    I suggest you read up on the basics of C# syntax. It sounds to me like you're trying to wrap your main method in an global while loop; which is impossible.
     
  5. rafcio_21 Trainee Engineer

    Messages:
    11
    Code:
    string prawda = "false";
    void Main() {
      while(prawda != "true") {
        var pos = GridTerminalSystem.GetBlockWithName("pos") as IMyGyro;
        var align = GridTerminalSystem.GetBlockWithName("align") as IMyTerminalBlock;
        var behind = GridTerminalSystem.GetBlockWithName("behind") as IMyTerminalBlock;
        VRageMath.Vector3D pos_cord = pos.GetPosition();
        VRageMath.Vector3D align_cord = align.GetPosition();
        VRageMath.Vector3D behind_cord = behind.GetPosition();
        if( pos.GyroOverride == false) {
          //pos.GetActionWithName("Override").Apply(pos);
        }
        double roll=0; //lewo ,prawo ,left, right
        double pitch=0; //gora ,dol ,up ,down
        double yaw=0; //obracanie, rolling, 1 = ~10 rpm
        pos.SetValue<float>("Roll",(float)roll);     
        pos.SetValue<float>("Pitch",(float)pitch);     
        pos.SetValue<float>("Yaw",(float)yaw); 
        Vector3D target = new Vector3D(10000,10000,10000); 
        double dis;
        dis = Vector3D.Distance(align_cord,target);
        //Debug("x1: " + Math.Round(align_cord.GetDim(0),2).ToString() + " y1: " + Math.Round(align_cord.GetDim(1),2).ToString() + " z1: " + Math.Round(align_cord.GetDim(2),2).ToString() + " distance: " + dis.ToString() ,false);
        dis = Vector3D.Distance(behind_cord,target);
        //Debug(" x2: " + Math.Round(behind_cord.GetDim(0),2).ToString() + " y2: " + Math.Round(behind_cord.GetDim(1),2).ToString() + " z2: " + Math.Round(behind_cord.GetDim(2),2).ToString() + " distance: " + dis.ToString() ,true);
        double[] a = new double[3];
        double[] b = new double[3];
        double[] c = new double[3];
        double[] c2 = new double[3];
        //double[,] d = new double[3, 3];
        double[][] d = new double[3][];
        for(int i = 0; i < 3; i++){
          d[i] = new double[3];
        }
        for(int k=0;k<3;k++) {
          a[k]=align_cord.GetDim(k);
          b[k]=behind_cord.GetDim(k);
          c[k]=target.GetDim(k);
          c2[k]=target.GetDim(k)+k;
        }
        for(int l=0;l<3;l++) {
          d[0][l]=b[l]-a[l];
          //Debug("[0][" + l + "]: " + Math.Round(d[0][l],2).ToString(),true);
          d[1][l]=c[l]-a[l];
          //Debug("[1][" + l + "]: " + Math.Round(d[1][l],2).ToString(),true);
          d[2][l]=c2[l]-a[l];
          //Debug("[2][" + l + "]: " + Math.Round(d[2][l],2).ToString(),true);
        }
        double wynik,param1,param2,param3;
        wynik = (d[0][0]*d[1][1]*d[2][2]) + (d[0][1]*d[1][2]*d[2][0]) + (d[0][2]*d[1][0]*d[2][1]) - ( (d[0][2]*d[1][1]*d[2][0]) + (d[0][0]*d[1][2]*d[2][1]) + (d[0][1]*d[1][0]*d[2][2]) );
        param1 = (d[0][0]*d[1][1]*d[2][2]) + (d[0][2]*d[1][0]*d[2][1]) - ( (d[0][2]*d[1][1]*d[2][0]) + (d[0][1]*d[1][0]*d[2][2]) );
        param2 = (d[0][1]*d[1][2]*d[2][0]) + (d[0][2]*d[1][0]*d[2][1]) - ( (d[0][0]*d[1][2]*d[2][1]) + (d[0][1]*d[1][0]*d[2][2]) );
        param3 = (d[0][0]*d[1][1]*d[2][2]) + (d[0][1]*d[1][2]*d[2][0]) - ( (d[0][2]*d[1][1]*d[2][0]) + (d[0][0]*d[1][2]*d[2][1]) );
        if(Math.Pow(dis,1.8)>param1 & Math.Pow(dis,1.8)>param2 & Math.Pow(dis,1.8)>param3){ 
          prawda = "true";
        } 
        Debug("czy naprzeciw: " + Math.Round(wynik,2).ToString() + " : " +  Math.Round(param1,2).ToString() + " : " +  Math.Round(param2,2).ToString() + " : " +  Math.Round(param3,2).ToString() + " : " + prawda,false);
      }
    }
    void Debug(string text, bool concatenate) 
    { 
        List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>(); 
        GridTerminalSystem.GetBlocksOfType<IMyRadioAntenna>(blocks); 
        IMyRadioAntenna antenna = blocks[0] as IMyRadioAntenna; 
        if(concatenate) 
            antenna.SetCustomName(antenna.CustomName + " " + text + "\n"); 
        else 
            antenna.SetCustomName(text); 
    }
    
    Thats my code. I got 3 params and I want to end script, when variable prawda = "true". By redoing script I can get this done. But no with loop :/ loop just doesn't work.
     
    Last edited by a moderator: Feb 26, 2015
  6. rafcio_21 Trainee Engineer

    Messages:
    11
    Ok, timer block fixed my problem.

    I added:
    Code:
    List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>(); 
        GridTerminalSystem.GetBlocksOfType<IMyTimerBlock>(blocks); 
        IMyTimerBlock program = blocks[0] as IMyTimerBlock; 
        program.GetActionWithName("Start").Apply(program);
    
     
  7. Igneous01 Apprentice Engineer

    Messages:
    266
    I see a lot of problems with your code:

    1. Why are you comparing strings for something so simple?
    Code:
    prawda != "true"
    - this is about 100 times slower than declaring prawda as a bool and simply checking
    Code:
    !prawda
    2. Wrapping your whole main method inside a while loop like that is asking for trouble. I assume it gave you that error message because you hit the IL limit in game.
    First off, you don't need a while loop over the ENTIRE thing, once you've got the blocks in your variables its not like you need to search for them again.

    3. I had assumed initially you only wanted to update a gyro override, but the mathematics you have is far too complicated to loop because you will hit that IL limit too soon.

    4. The only thing your script does right now is set the gyro overrides to 0. I don't see why you are even looping this because it will never accomplish whatever you set out to do with it.
     
  8. rafcio_21 Trainee Engineer

    Messages:
    11
    Because I'll print that variable anyway for debug, so for now I need it to be string.

    The code is only for experiments and a sketch of program. When experiment will be done and all setting will work correctly, I'll rewrite code to classes, functions and optimize.

    The math is simple determinant of the matrix to check if two vectors are on the same 2d surface in 3d dimension, it isn't anyhow advanced for computer and works perfect so far.

    But I need another data, because 2d surface have 360 degrees (it is like a line on which you can turn you ship), and one of the possible directions on this flat surface is an destination point.

    Example, I assume that there is no need for yaw, lets say that to set destination you need to roll (Y axis) and pitch (X axis). And in this exmaple I can only set Y axis with no data about X axis :/

    Not sure if should I make third topic with questions :woot: Any idea how to get it done?

    I'd need to make ship vector a straight and calculate distance between straight and destination point, but I totally dunno how to get this done...
     
    Last edited by a moderator: Feb 27, 2015
  9. SigmaStrain Trainee Engineer

    Messages:
    27
    You could try setting up gyros oriented at right angles and calculate your orientation from there. Check the released codes section. I've got some code that does exactly what you're looking for here.
     
  10. rafcio_21 Trainee Engineer

    Messages:
    11
    I have already calculated it by using cross vector function and finding another 2d surface for yaw :D the only thing left is to find last one cross vector and make surface from it to get a pitch values :D

    The problem is that there is no 3DPoint type. 3DVector shouldn't be used to storage coordinates. I don't get why people keep using it. Vector is vector, that's not a point in space. Vector should be calculated from at least 2 points.
     
  11. mze9412 Junior Engineer

    Messages:
    791
    You can also print booleans as debug, no need to make it a string ...

    This is C# which has true booleans, not c or c++ ;)
     
  12. rafcio_21 Trainee Engineer

    Messages:
    11
    Nice idea, but still it is kinda catching little mistakes :D I deleted that variable and cleaned code I little bit.

    Code:
    int licz = 0;
    double[][] matrix = new double[4][];
    double[][] matrix2 = new double[4][];
    double wynik1,wynik2;
    void Main() {
        var pos = GridTerminalSystem.GetBlockWithName("pos") as IMyGyro;
        var align = GridTerminalSystem.GetBlockWithName("align") as IMyTerminalBlock;
        var behind = GridTerminalSystem.GetBlockWithName("behind") as IMyTerminalBlock;
        var behind_up = GridTerminalSystem.GetBlockWithName("behind_up") as IMyTerminalBlock;
        var behind_right = GridTerminalSystem.GetBlockWithName("behind_right") as IMyTerminalBlock;
        VRageMath.Vector3D pos_cord = pos.GetPosition();
        VRageMath.Vector3D align_cord = align.GetPosition();
        VRageMath.Vector3D behind_cord = behind.GetPosition();
        VRageMath.Vector3D behind_up_cord = behind_up.GetPosition();
        VRageMath.Vector3D behind_right_cord = behind_right.GetPosition();
        VRageMath.Vector3D target = new Vector3D(10000,10000,10000); 
        double dis;
        dis = VRageMath.Vector3D.Distance(behind_cord,target);
        licz++;
        //counting X
        matrix = VectorMatrix(align_cord, behind_cord, target, target);
        wynik1=Math.Round(Surface(matrix),2);
        //counting Y
        matrix2 = crossProduct_Y_matrix(matrix, align_cord, behind_cord, behind_up_cord );
        wynik2=Math.Round(Surface(matrix2),2);
        Debug(licz + ". X: " + wynik1.ToString() + ". Y: " + wynik2.ToString() + " distance: " + dis ,false);
        
        List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>(); 
        GridTerminalSystem.GetBlocksOfType<IMyTimerBlock>(blocks); 
        IMyTimerBlock program = blocks[0] as IMyTimerBlock; 
        program.GetActionWithName("Start").Apply(program);
    }
    void Debug(string text, bool concatenate) 
    { 
        List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>(); 
        GridTerminalSystem.GetBlocksOfType<IMyRadioAntenna>(blocks); 
        IMyRadioAntenna antenna = blocks[0] as IMyRadioAntenna; 
        if(concatenate) 
            antenna.SetCustomName(antenna.CustomName + " " + text + "\n"); 
        else 
            antenna.SetCustomName(text); 
    }
    double Absolute(double val) 
    { 
        if(val<0) val=val-(2*val);
        return val;
    }
    double[][] VectorMatrix(VRageMath.Vector3D a, VRageMath.Vector3D b, VRageMath.Vector3D c, VRageMath.Vector3D d) {
        double[] aa = new double[3];
        double[] bb = new double[3];
        double[] cc = new double[3];
        double[] dd = new double[3];
    
        double[][] matrix = new double[3][];
        for(int i = 0; i < 3; i++){
          matrix[i] = new double[3];
        }
        for(int k=0;k<3;k++) {
          aa[k]=a.GetDim(k);
          bb[k]=b.GetDim(k);
          cc[k]=c.GetDim(k);
          dd[k]=d.GetDim(k)+k;
        }
        for(int l=0;l<3;l++) {
          //AB
          matrix[0][l]=bb[l]-aa[l];
          //AC
          matrix[1][l]=cc[l]-aa[l];
          //AD
          matrix[2][l]=dd[l]-aa[l];
          //CD
          //matrix[3][l]=dd[l]-cc[l];
        }
        return matrix;
    }
    double Surface(double[][] matrix) {
      double wynik;
      wynik = (matrix[0][0]*matrix[1][1]*matrix[2][2]) + (matrix[0][1]*matrix[1][2]*matrix[2][0]) + (matrix[0][2]*matrix[1][0]*matrix[2][1]) - ( (matrix[0][2]*matrix[1][1]*matrix[2][0]) + (matrix[0][0]*matrix[1][2]*matrix[2][1]) + (matrix[0][1]*matrix[1][0]*matrix[2][2]) );
      return wynik;
    }
    double[][] crossProduct_Y_matrix(double[][] matrix, VRageMath.Vector3D align_cord, VRageMath.Vector3D behind_cord, VRageMath.Vector3D behind_up_cord) {
      VRageMath.Vector3D a = new Vector3D(matrix[1][0],matrix[1][1],matrix[1][2]);
      VRageMath.Vector3D b = new Vector3D(matrix[2][0],matrix[2][1],matrix[2][2]);
      VRageMath.Vector3D crossProduct = Vector3D.Cross(a,b);
      double[] aa = new double[3];
      double[] bb = new double[3];
      double[] cc = new double[3];
      for(int k=0;k<3;k++) {
        aa[k]=crossProduct.GetDim(k);
        bb[k]=behind_cord.GetDim(k);
        cc[k]=behind_up_cord.GetDim(k);
      }
      for(int l=0;l<3;l++) {
          // Align to cross product vector
          matrix[1][l]=aa[l]; 
          //Behind to Behind_up Vector
          matrix[2][l]=bb[l]-cc[l];
        }
          return matrix;
    }
    
    Now with the block "align" on front, "behind" block in line behind it (main vector) and "behind_up" block which is on "behind" block (vector normal to main vector).

    It allows to set roll and yaw values, when value of wynik1 and wynik2 is close to 0, that means you have set it correctly. Target also must be a vector for calculations, so I always make from destination point 2 points close to each other.

    May I have changed topic name to "Autopilot tryouts and calculations"?
     
Thread Status:
This last post in this thread was made more than 31 days old.