1. This forum is obsolete and read-only. Feel free to contact us at support.keenswh.com

Ship Thrusters and Orientation

Discussion in 'Programming (In-game)' started by Jewboii, Mar 20, 2015.

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

    Jewboii Apprentice Engineer

    Messages:
    242
    I know how to get a list of all thrusters attached to a ship. I do not know how to figure out which local direction they are point (up, down, etc), and if they are "Large" or "Small". I'm trying to calculate total possible acceleration/deceleration in each direction. The users will obviously have to input the ship mass, but I'd like at least this part to be automated. If I stare at it long enough, I think I can do the orientation stuff (it'd be faster to ask though), but I have no idea how to tell "Large" and "Small" apart since they don't seem to inherit different interfaces.

    IMyGridTerminalSystem should really provide information all of the GUI information like instantaneous velocity, ship mass, power consumption, etc.
     
  2. shimonu

    shimonu Apprentice Engineer

    Messages:
    396
    Check by names? (if they didn't get changed) For orientation there is script with gyroscopes orientation this may help link.
     
    Last edited by a moderator: Mar 20, 2015
  3. MisterSwift

    MisterSwift Apprentice Engineer

    Messages:
    367
    Doesn't .Orientation property inherited from IMyCubeBlock work?

    Code:
    MyBlockOrientation foo = someblock.Orientation;
    throw new Exception(foo.Left.ToString());
    // .Left, .Forward and .Up are of type Base6Directions.Direction enumeration
    
     
  4. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    Do what MisterSwift posted. Though i think that "Orientation.Forward" is what you need and not "Left". Not 100% sure yet, as i can not change my code thanks to my desktops PSU dying a week ago.
    I used the Orientation.ToString() method myself and it is quite useful. Dont rely on naming the components as that is a faulty method due to errorous uer inputs and usage.
    You could also extract the orientation matrix somewhere (again, not 100% sure from where as i cant start my desktop) as you most likely need to performa a matrix rotation because of a "misalignment" of ship grid pivot and what you want it to be (thus your desired direction is not the same as the internal one for the code).
     
  5. MisterSwift

    MisterSwift Apprentice Engineer

    Messages:
    367
    someblock.Orientation.GetMatrix() returns your matrix of type VRageMath.Matrix according to Documentation.chm =)

    For grid size, this *might* work:
    IMyTerminalBlock interface inherits from IMyCubeBlock, which has CubeGrid property that returns an IMyCubeGrid.
    IMyCubeGrid interfaces in turn have a GridSize property (type single) which returns the grid's block size in meters (0.5 for small, 2.5 for large)
    It also has the GridSizeEnum property (type MyCubeSize), which is an enum where 0 = Large and Small = 1

    So, see what you can get from someblock.CubeGrid.GridSizeEnum

    Edit: Clarified GridSize property thanks to JoeTheDestroyer
     
    Last edited by a moderator: Mar 20, 2015
  6. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    Yeah thats it :p
    Code:
    Matrix m;
    IMyCubeBlock block = someBlock;
    block.Orientation.GetMatrix(out m);
    // do stuff with [I]m[/I]
    Edit:
    But keep in mind that matrices just like vectors are very buggy and annoying to use when you want to access their elements the way you would expect them.
    Like for vectors where Vector3.X etc does not work, the same applies for Matrix.Mmn with m,n = 1,2,3,4 (e.g. M11, M34,..) in my experience from a few weeks ago.
     
    Last edited by a moderator: Mar 20, 2015
  7. Jewboii

    Jewboii Apprentice Engineer

    Messages:
    242
    For Vector3 and Vector3D, you have to use GetDim. For Matrix, you can use Col. For Matrix3D, you use GetRow. Getting a row of a Matrix and a column on a Matrix3D is annoying because you have to transpose.

    block.Orientation.GetMatrix will be a 0, 90, 180 degree rotation matrix, correct? I want to make sure I understand what my output will be, which I think will be local orientation.

    I don't get what you mean here. Could you elaborate?

    Perfect! I'll try this when I get home.
     
    Last edited by a moderator: Mar 20, 2015
  8. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    From what I gather of your purpose, you don't need to determine "Large" vs. "Small". Just use .GetMaximum<float>("Override") which returns the maximum thrust value (in Newtons) that you can set the thruster to.

    "Forward" is the direction a thruster points (i.e., the nozzle direction). The direction it applies thrust is the opposite, so "Backward" or "-Forward".

    Yes, the directions/matrix returned is in grid-coordinates/space, which have no concept of "forward", "left", etc. These only have meaning for a player flying the ship, and thus these are defined by the orientation of the cockpit on the grid.

    However, it sounds like Jewboii is working on an autopilot script, so this should be a non-issue. An autopilot doesn't care what the user thinks is forward/left/up.

    It is the size of the side of a cube, in meters. So 2.5 for large grid and 0.5 for small grid.

    ---

    If you want examples of using all of this, see my coordinate space conversion library, particularly the getForward() function.
     
    Last edited by a moderator: Mar 20, 2015
  9. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    Well then, if you know how to access all values from vectors and matrices, good :)

    I dont quite understand that you mean by "0, 90, 180 degree rotation matrix" but the matrix is structured as follows: Row1 = +Right | -Left, Row2 = +Up | -Down, Row3 = +Backward | -Forward, Row4 = Translation. I however have never checked if Translation is zero or not.

    With the grid misalingment i meant that for the game it is Forward = -Z, Up = +Y and Left = -X. For you and how you build your ship however it could be that your desired forward is +Y and your desired left is +X. Thus you had to rotate the blocks rotation from their actual orientation toward your desired orientation.
     
    Last edited by a moderator: Mar 20, 2015
  10. woodster

    woodster Trainee Engineer

    Messages:
    78
    I found the following to work quite well for getting thrusters and their orientation. I wasn't concerned with their sizes, so there's no detection for that. It just gets the list of all thrusters and shows a way to check the orientation.

    As mentioned in a previous reply, the orientation is opposite to direction of thrust, so in my example, you'll see I check for "Backward" orientation to get forward thrusters.

    List<IMyTerminalBlock> grid = new List<IMyTerminalBlock>();

    void Main()
    {
    grid.Clear();

    GridTerminalSystem.GetBlocksOfType<IMyThrust>(grid);
    for(int i = 0; i < grid.Count; i++)
    {
    IMyThrust thruster = grid as IMyThrust;

    // Check if thruster is a "Forward" thruster
    if (thruster.Orientation.Forward.ToString() == "Backward")
    {
    // Do something here with the forward thruster
    }
    }
    }
     
    Last edited by a moderator: Mar 20, 2015
  11. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    Alright, I'll give it a shot:
    Code:
    List<IMyThrust>[] organizeThrusters(List<IMyTerminalBlock> thrusters)
    {
      var org=new List<IMyThrust>[6];
      for(int dir=0;dir<6;++dir) org[dir]=new List<IMyThrust>();
      for(int i=0;i<thrusters.Count;++i)
      {
        Matrix bmat;
        thrusters[i].Orientation.GetMatrix(out bmat);
        int dir=(int)bmat.Forward.Dot(new Vector3(1,2,3));
        dir=(2*Math.Abs(dir)-2)+(Math.Sign(dir)+1)/2;
        org[dir].Add(thrusters[i] as IMyThrust);
      }
      return org;
    }
    WARNING!!! This code is completely untested! I don't have access to the game or documentation at the moment. It looks right to me, but be sure to test it before you rely on it!

    This should organize thrusters by the grid/local axis they apply thrust on. If I have my math right,
    indices 0-5 should correspond to +X,-X,+Y,-Y,+Z,-Z respectively.

    (The version I use in my autopilot code is slightly different, that dot product trick only just occurred to me.)

    EDIT: I have now confirmed in game that the above is accurate, so disregard the warning.
     
    Last edited by a moderator: Mar 20, 2015
  12. Jewboii

    Jewboii Apprentice Engineer

    Messages:
    242
    Alternatively...

    Code:
    List<IMyThrust>[] organizeThrusters(List<IMyTerminalBlock> thrusters)
    {
      var org=new List<IMyThrust>[6];
      for(int dir=0;dir<6;++dir) org[dir]=new List<IMyThrust>();
      for(int i=0;i<thrusters.Count;++i)
      {
        Matrix bmat;
        thrusters[i].Orientation.GetMatrix(out bmat);
        int dir=(int)bmat.Forward.Dot(new Vector3(1,2,3)) + 3;
        if(dir>3) --dir;
        org[dir].Add(thrusters[i] as IMyThrust);
      }
      return org;
    }
    
    indices 0-5 should correspond to -Z,-Y,-X,+X,+Y,+Z respectively.

    Alternatively #2

    Code:
    List<IMyThrust>[,] organizeThrusters(List<IMyTerminalBlock> thrusters)
    {
      var org=new List<IMyThrust>[2,3];
      for(int dir=0;dir<6;++dir) org[dir]=new List<IMyThrust>();
      for(int i=0;i<thrusters.Count;++i)
      {
        Matrix bmat;
        thrusters[i].Orientation.GetMatrix(out bmat);
        int dir=(int)bmat.Forward.Dot(new Vector3(1,2,3));
        if(dir > 0) org[0, dir-1].Add(thrusters[i] as IMyThrust);
        else org[1, -dir-1].Add(thrusters[i] as IMyThrust);
      }
      return org;
    }
    
    indices 0,0-2 should correspond to +X,+Y,+Z respectively.
    indices 1,0-2 should correspond to -X,-Y,-Z respectively.
     
    Last edited by a moderator: Mar 20, 2015
  13. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    heh yeah the .Dot method is nice and i like it.
    I would have suggested a change along
    Code:
    int dir=(int)bmat.Forward.Dot(new Vector3(1,3,5));
    if(dir < 0)
      dir = -dir - 1;
    
    for: -X X -Y Y -Z Z

    or
    Code:
    int dir=(int)bmat.Forward.Dot(new Vector3(1,3,5));
    if(dir < 0)
      dir = -dir;
    else
      dir--;
    
    for: X -X Y -Y Z -Z

    Edit:
    Fixed copy-paste error
     
    Last edited by a moderator: Mar 20, 2015
  14. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    Backwards, I think. "Forward" is the direction the thruster points, "-Forward" is the direction it applies thrust. So you have to negate the results of the above codes to get the thrust direction.

    This was the main thing behind my warning about testing, I'm not sure I have this exactly right in my head. Normally, I would make a little test to check, but I'm at work and don't have the game handy...

    Or get rid of the if statements (extra instruction count cost):
    Code:
    org[(-Math.Sign(dir)+1)/2, Math.Abs(dir)-1].Add(thrusters[i] as IMyThrust);
    The method I was using before in my autopilot code just looped through the dimensions looking for non-zeros, meaning the instruction count cost was ~4*# of thrusters. I thought of the code above to reduce it to 1*# of thrusters.
     
    Last edited by a moderator: Mar 20, 2015
  15. Jewboii

    Jewboii Apprentice Engineer

    Messages:
    242
    One last question (maybe). This .Forward method depends on whatever the game's base orientation for this ship is (I think what plaYer2k was mentioning). If I want to associate the games .Forward with my perceived -Z, I would need players to explicitly specify 2 thrusters that are on different axiis so I can transform one basis to another. Is this correct?

    For simplicity, I'll probably require that my system be in sync with a cockpit or remote control block so I don't need to worry about this second transformation stage.
     
  16. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    Well three different methods that quickly come in mind to change the orientation are:
    - Assign the new orientation manually. That might happen in any way you like. A vector3I for the rotation around X/Y/Z-axis in a predefined order or with a full matrix .. or something different.
    - Use a "source block" which has the desired orientation and use the orientation matrix of that block for your matrix transformation. Though i am terribly bad at that, so without testing i cant give a good anser on how to properly proceed here for SE :s
    - You could of course use two thrusters and then each compare of the axis for their alignment is the same as one of your two "source thrusters" and add them in groups per direction. (That was actually what you meant, i think)


    Edit:
    added third method after reading your post again
     
    Last edited by a moderator: Mar 20, 2015
  17. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    Yes. Although IMHO, it's better to think of it as the ship having no base "orientation" (i.e., meaning for forward,up,etc).

    The orientation of a ship is solely (and only) defined by the cockpit the player is inhabiting.

    Fun thing to try, place two cockpits on your ship facing different directions. Notice how the "(Forward)" etc labels on your thrusters shift around as you change cockpits.

    Cockpit-type blocks have an orientation so you can use GetMatrix on them too.

    In fact, I suspect that if you multiply the cockpit and thruster's orientation matrices in the right way, it will give you directly what you want. I'm not confident enough to post the formula here without testing it first, though.

    P.S. To be clear, when I say cockpit, I mean anything with the IMyShipController interface.
     
    Last edited by a moderator: Mar 20, 2015
  18. Jewboii

    Jewboii Apprentice Engineer

    Messages:
    242
    So using the .Foward thing is actually unfeasible, since it produces different results based on whatever arbitrary controller was last inhabited? That'd be funny if they initiate the navigation system, sit in a passenger seat, and then the ship starts heading towards the destination sideways lol.

    Hmm... Other than manually specifying at least two thrusters and their directions, I guess there won't be a consistent (or maybe constant) way to define a ship's orientation.

    In any case, the .GetMaximum<float>("Override") tip was simply grande, thank you.

    I disagree, because there tends to be more forward thrust than other directions, and you'd want to utilize that. Having said that... I'll probably use that to at least define the Z axis. The X and Y are less important for my purposes. I have to think about this problem a bit more before continuing. Thank you everyone for your suggestions!
     
  19. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    No, ".Forward" doesn't mean forward, as in the direction in front of you.

    ".Forward" means exactly "-Z" (in the block or grid local coordinate system), nothing else. It never changes.

    forward (again, as in the direction in front of you), depends on the user. It changes based on which cockpit the user enters (and the system adds the "(direction)" labels to thruster CustomName's to match). The only way to get this is to have the user tell you, for example by using specially named blocks or by defining which cockpit to use as reference.

    This is why I said it's better to think of a ship (by which I mean base cube grid) as having no forward/up/left. Then you won't get confused by ".Forward", ".Left", ".Up" not really meaning what their name implies. (By the way, FYI ".Up" is broken but the other two work.)

    Now you're talking about optimizing the orientation of a ship to maximize thrust. I've thought about this a bit, but in general it gets pretty complicated.

    Since a ship with a full thruster loadout can reach a target location/speed with any orientation, I don't consider the above a part of the basic auto-pilot problem. For me, a basic autopilot (continuously) answers two questions: How much thruster power to apply to reach target position and velocity? Similarly, how much gyro power to apply for target orientation? Determining the best orientation for the shortest time (i.e., orientation optimization) is something I will deal with at a higher level (like a flight planner). (Notice that none of these really have anything to do with what the user considers the front of their ship.)

    Also, a ship's orientation may be independent of the direction it's moving. For example, a ship sliding sideways into a docking port. Or a welding drone sliding along a surface it is welding. So you may not always want to use the optimal orientation. Even "optimal orientation" is a questionable term as optimal orientation w.r.t. thrust is quite different from optimal orientation w.r.t. power.
     
    Last edited by a moderator: Mar 20, 2015
  20. Jewboii

    Jewboii Apprentice Engineer

    Messages:
    242
    To be certain then, .Forward (and related functions) is a constant arbitrary orientation that is assigned to the grid upon conception (before any IMyShipControllers and the like are placed), and it is independent to any IMyShipController orientations and the like? If so, then that is good news.

    I do not care which way "forward" or ".Forward" is; I only care that it is constant.
     
  21. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    Yep, precisely.
     
  22. plaYer2k

    plaYer2k Master Engineer

    Messages:
    3,160
    Yes it is.

    The values .Forward .Backward .Left .Right .Up and .Down each represent an orientation vector that is relative to the local grid orientation for each IMyCubeGrid like JoeTheDestroyer already mentioned.
    The value for them is the same if the blocks each got the same orientation per relative axis within the grid.

    So if you got several thrusters that all point (thruster exhaust) in the same direction, then at least the .Forward and .Backward vectors for all these thrusters are the same. You could however still have varying vectors for the other directions like .Up and .Left as they are independent from .Forward of course.

    So the ."direction" members return the block-specific orientation for that one single block you look at in relation to the cubegrid.

    But like previously said, only one orientation matters for you and that is either .Forward or .Backward, depending on why way you prefer it.
    So each of them says in which direction along the X/Y/Z-coordinates of the IMyCubeGrid the respective orientation vector is pointing at.

    What you need is to only compare them an sort it accordingly like in the fine code example JoeTheDestroyer has given earlier.
    Afterwards just access the array by index (depending on your index system ofc)

    Edit:
    That said, the code to get and index all thrusters is one already and only the indexing aswell as a block filter for the right thruster is missing in addition to your actual working code where you define the thruster outputs for each of the blocks (thruster).
     
    Last edited by a moderator: Mar 20, 2015
  23. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    Just wanted to say that I managed to test the initial code I posted in-game and it seems to work as planned.

    Ok, had a chance to look at this. If you want to organize thrusters with respect to a cockpit block (or any block, really):
    Code:
    List<IMyThrust>[] organizeThrusters(List<IMyTerminalBlock> thrusters, IMyTerminalBlock reference)
    {
      Matrix refm;
      reference.Orientation.GetMatrix(out refm);
    
      var org=new List<IMyThrust>[6];
      for(int dir=0;dir<6;++dir) org[dir]=new List<IMyThrust>();
      for(int i=0;i<thrusters.Count;++i)
      {
        Matrix bmat;
        thrusters[i].Orientation.GetMatrix(out bmat);
        bmat=bmat*Matrix.Transpose(refm);
        int dir=(int)bmat.Forward.Dot(new Vector3(1,2,3));
        dir=(2*Math.Abs(dir)-2)+(Math.Sign(dir)+1)/2;
        org[dir].Add(thrusters[i] as IMyThrust);
      }
      return org;
    }
    The indices for the lists are: 0) Right, 1) Left, 2) Up, 3) Down, 4) Backward and 5) Forward, with respect to the reference block provided.
     
    Last edited by a moderator: Mar 20, 2015
  24. Jewboii

    Jewboii Apprentice Engineer

    Messages:
    242
    So the thruster thing I think is worked out, but I have a pre-requisite problem. I can't seem to get "GetMaximum<float>("Override")" to work. Can someone provide an example? It always returns 0.
     
  25. JoeTheDestroyer

    JoeTheDestroyer Junior Engineer

    Messages:
    573
    Straight from my autopilot code:
    Code:
    Thruster t;
    t.blk=l[i] as IMyThrust;
    
    t.max=t.blk.GetMaximum<float>("Override");
     
Thread Status:
This last post in this thread was made more than 31 days old.