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.

[solved] Need help fixing gyro script, possible game bug?

Discussion in 'Programming Questions and Suggestions' started by Laiden, Mar 31, 2017.

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

    Hey folks! I need your opinion about this issue - a ingame script controlling gyros, getting badly interupted after connecting a connector. What exactly changes on a grid, when another grid connects it over connector?

    The goal: "keep ship horizontal to surface, using dedicated gyros controlled by script."

    The problem:
    The skript works great, but the moment another grid is connected by connectors, the ship starts to spasm out. This does not happen when using merge block. I have no idea what causes it or how to fix.

    What i've done:
    I make use of getNaturalGravity(), block.Orientation, block.WorldMatrix... and IMyGyro.Yaw, .Pitch, .Roll, GyroOverride. I logged changes that might occur when connecting grids, but nothing really noticable in grid or world orientation/directions vectors. Visual grid origin and axes unchanged as well. Only the center of mass moves. But still, gyros suddenly seem to act differently on override commands... Is this a game bug?

    Here's a video demonstrating it:

    The script:
    IMyShipController mCtrl = null; 
    IMyTimerBlock mTim = null;     
    List<IMyGyro> mGyros = null;   
    Matrix mRefOrInGrid = default( Matrix );   
    double mElapsed = 0;
    private double alignToGravity( ) {   
          // Axis:   
          // up green vert y yaw lh-rot   
          // right red horz x pitch rh-rot   
          // forward blue lat z roll rh-rot   
          // max rot 6.28 == 60rpm == 2Pi for small gyro   
          //        3.12 == 30rpm == pi for big gyro   
          if ( mCtrl == null || mGyros.Count == 0)   
            return 0.0;   
          // mat describes transformation to block orientation in world system   
          MatrixD refOr=mCtrl.WorldMatrix.GetOrientation();   
          Vector3D refDown = refOr.Down;   
          // world coordinate vector at reference point   
          Vector3D grav = mCtrl.GetNaturalGravity(); 
          if ( grav.Length() < 0.01 ) { 
            Echo ( "Low planetary gravity" ); 
            return 0.0; 
          // dot returns cosinus between two vectors. acos of -1..1 is 0 to pi   
          double angle = System.Math.Acos(MathHelper.Clamp(Vector3D.Dot(refDown, grav), -1, 1));   
          if (angle < 0.01) { //<0.57°   
            for( int i=0; i<mGyros.Count; i++)   
            mGyros[i].GyroOverride = false;   
            return 0.0;   
          // Cross returns orientation of rotation axis (world coordinates)   
          // Mind the order   
          Vector3D rot = Vector3D.Cross(grav, refDown );   
          rot.Normalize();  // magnitude is of no interest   
          // rotation axis relative to reference block   
          // We need inverse transformation block -> origin   
          // Transpose of orthogonal matrices is the inverse mat   
          // Rotation matrices are always orthogonal (using cartesian coordinate system)   
          rot = Vector3D.Transform(rot, MatrixD.Transpose(refOr));   
          rot = Vector3D.Transform(rot, mRefOrInGrid); //only if gyros not aligned   
          // max applicable rotation magnitude   
          if ((int)mCtrl.CubeGrid.GridSizeEnum == 1)   
            rot *= (angle * 2.0); // same as: div MathHelper.Pi * 6.28;   
            rot *= angle;     
          // ==== gyro specific code ====   
          int nGyro = 0;   
          IMyGyro gyro = null;   
          Vector3 localRot; 
          Matrix gyOr;     
          do {   
            gyro = mGyros[nGyro];   
            gyro.GyroOverride = true;   
            // align rotation to n-th gyro, if not same orientation as reference   
            gyro.Orientation.GetMatrix(out gyOr);   
            localRot = Vector3D.Transform(rot, MatrixD.Transpose(gyOr));   
            // Yaw has reversed rotation direction in UI
            gyro.Yaw = Convert.ToSingle(localRot.Y);   
            gyro.Pitch = Convert.ToSingle(localRot.X);   
            gyro.Roll = Convert.ToSingle(localRot.Z);   
          } while (nGyro < mGyros.Count);
          // angle difference in degree
          return angle / MathHelper.Pi * 180.0;
    If you have any ideas or suggestions to this issue, please let me know. I can provide more stuff if there's interest.
  2. Lynnux Junior Engineer

    I don't see a problem in this part of the code. Looks like a bug to me.
    Maybe the GridTerminalSystem gets messed up when connecting the other grid. In case of the merge block you didn't add terminal blocks to the grid.
    How do you look for the gyros and the ship controller ?
  3. gchristopher Apprentice Engineer

    Aside from questions like "can you use gyro.Yaw = yaw instead of gyro.SetValueFloat("Yaw", yaw) and have it be reliable?"

    you've really only got three pertinent value to diagnose if you want to narrow it down: mCtrl.WorldMatrix.GetOrientation().Down, mCtrl.GetNaturalGravity(), and gyro.Orientation.GetMatrix(out gyOr). Try putting the ship in as identical a position before and after docking the connector and Echo those values to see if there's a change? That'd point toward weirdness with WorldMatrix or maybe with the block reference lists?

    What happens if you connect the connector, then the script spazzes out, then you recompile the PB with the connector connected and try the script again?

    Also, what is mRefOrInGrid doing? I don't understand that line.
    Last edited: Apr 2, 2017
  4. Laiden Trainee Engineer

    Thank you for overlooking my code. What do you mean with "didn't add terminal blocks"? In the video I connected just a connector plus a small reactor or merge block. Well, I don't think it has something to do with the GridTerminalSystem, because I don't call that global inside the loop. I assign the block variables and List once in the program constructor. However, i doubted these references as well first and updated them in every new PB call, just to make sure. But it didn't change anything. This is the initialization method:
    bool init(){ 
      Echo( "alignToGravity::init()" );
      GridTerminalSystem.GetBlockGroupWithName( "GyroSystem" ).GetBlocksOfType<IMyGyro>( mGyros );     
      mCtrl = GridTerminalSystem.GetBlockWithName ( "Controller" ) as IMyShipController;   
      if( mCtrl != null && mGyros.Count > 0 ) {   
        mCtrl.Orientation.GetMatrix( out mRefOrInGrid ); 
        return mRefOrInGrid.IsValid();   
      return false; 
    --- Automerge ---
    Ah yes, i was surprised too, directly assigning IMyGyro.Yaw works! It seems it is a public member variable, made visible trough c# auto getter/setter mechanism. I believe the devs included these methods during latest API overhaul. Had no issues with that, but i can try out the old SetValue as well.

    At time I opened the thread, I had the procedure you described already behind me. But i echo'ed only the direction vectors (down, right, forward and grav) and set rotation values (rot), not the matrices itself. It didnt change when connecting something. Want me to post the test code?

    Unfortunately recompiling the code at any given moment doesnt avoid spasm :( Also connecting a merge block that has a connector which is connected with another grid also goes crazy. And connecting a merge block and parallely a connector after that fails too.

    mRefOrInGrid is the orientation the ship controller has within the grid coordinates. This is a Base6Direction, which means only 90° angles possible, e.g. something like UP(0|1|0). I need that, cause often the ships coordinates are upside down, depending how you started building the ship.
  5. Lynnux Junior Engineer

    Paßt ! Ich meinte, im Falle des Merge Blocks hast Du keine Terminal-Blöcke zum Schiff hinzugefügt im Gegensatz zum Verbinder (mit Reaktor). Dies ist ja ein Unterschied, der sich auf's GridTerminalSystem auswirken könnte. Z.B. eben genau wenn es nur einmal in void Program() initialisiert werden würde. Ist ja aber nicht der Fall.
    Sieht demnach ganz nach Bug aus.
    Auf Deutsch, um weitere Mißverständnisse zu vermeiden ;)
  6. gchristopher Apprentice Engineer

    Oh, okay. So it's being initialized somewhere else in the code? (Outside of the section you posted.)

    Can you post the world file to try to reproduce it? I tried (outside of gravity), connecting a connector and running a very similar gyro orientation script and haven't seen the behavior.
  7. Laiden Trainee Engineer

    Ah jetzt hab ich verstanden was du meinst. Das ist auch der Teil im System, den ich nicht ganz durchschaue. Systemtechnisch WIRD der Blockverbinder zum ursprünglichen Grid. Wogegen beim normalen Verbinder ein neues Grid angehängt wird, welches seine Entität behält.

    Yes, i havent post the full code. Initialisation, argument handling and function calls are done within the main.
    Thats interesting. I havent test it in space, because of the nature of the project, i can only have it within gravity.
    So, you would want to try it yourself? I can prepare a small world with the drone and upload it, if you want. The grids and scripts are saved in the world file, arent they?
    --- Automerge ---
    Okay, i got an insight. Was preparing a seperate game world, a 20km radius marslike. But on this planet, the script works normal with applied connector. Back on EasyStartEarth, same ship copy still goes crazy. This needs further testing, ill report back later.
  8. Laiden Trainee Engineer

    Seems it was a corrupt world save. I admit it was a quite old world that was used for testing. A new "Easy Start Earth" has no issues with my scipt and connectors, works fine. Also with the mods i usually run. Thanks to gchristopher who lead me to this! Sad how fragments from past versions can linger and make U loose your weekend on it -__-'
    • Agree Agree x 1
  9. gchristopher Apprentice Engineer

    Wow, I'm sorry! That's a hard one! Glad you got it!
Thread Status:
This last post in this thread was made more than 31 days old.