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.

help with master/slave rotors

Discussion in 'Programming Questions and Suggestions' started by chris chance, Dec 23, 2016.

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

    Messages:
    6
    hi, this is my first post. i love this game but i completely dont understand how to program scripts in this game.

    i saw one for a master and slave rotor. which the slave rotor mirrors the movement of the master. but it doesn't not work. does any have one that way?
     
  2. Sinbad Senior Engineer

    Messages:
    2,788
    Some thing like this should work,
    Code:
    void main()
    {
    IMyMotorStator Master = GridTerminalSystem.GetBlockWithName("Rotor Master") as IMyMotorStator;
    float SetPoint = MathHelper.ToDegrees(Master.Angle);
    //
    IMyMotorStator Slave1 = GridTerminalSystem.GetBlockWithName("Rotor Slave 1") as IMyMotorStator;
    float SlaveAngle1 = MathHelper.ToDegrees(Slave1.Angle);
    float Error1 = SetPoint-SlaveAngle1;
    if (Error1=>30f){Error1=30f;}
    if (Error1=<(-30f)){Error1=(-30f);}
    Slave1.SetValueFloat("Velocity", Error1);
    //
    }
    
    Make a timer with actions to "trigger now" itself and run the pb.
    Its an ugly, clunky way to do it, but it should work. To add more slave rotors, copy the bit between the // and increment all the '1'.
    The getblockwithname bit is looking for a specific block name, the one inside the (" ") either change those to match your block names, or change your names to match these.

    How it works,
    It gets the current angle of the master, and subtracts the current angle of the slave. This gives an error value. The 2 if statements constrain the error between -30 and +30.
    It then assigns that error value to the slave rotor as rpm, or velocity.
    So if the master is at 10degrees, and the slave is at 5 degrees, the slave will be given a speed of +5 rpm to drive its angle up. If the master is 10degrees, and the slave 15 degrees, the slave gets a speed of -5 rpm, driving its angle down.
    The closer the slave gets to the master, the slower it gets. The slaves will only get high speeds when they first align, after that, errors shouldnt exceed about +/-1. This is a negative feedback servomechanism, and is the foundation of automated motion control. However you move the master, the slaves will follow. Be carefull of crossing zero degrees, the slaves may try to race around in the wrong direction to catch the master. To be safe, stay between 5 and 355 degrees.
    The timer is important here, you are dealing with motion control, so need fast updates to keep smooth control. The timer setup above will trigger the script to run every game tick, or 60 times per in game second.
    Hope this works for you.
     
  3. chris chance Trainee Engineer

    Messages:
    6
  4. chris chance Trainee Engineer

    Messages:
    6
    note, this code did not work for me
     
  5. Sinbad Senior Engineer

    Messages:
    2,788
    im in game today, ill de-bug it properly. seems a hard read through isnt enough...

    oops, typo and and C# being picky about conditional operator order.

    Code:
    void Main()
    {
    IMyMotorStator Master = GridTerminalSystem.GetBlockWithName("Rotor Master") as IMyMotorStator;
    float SetPoint = MathHelper.ToDegrees(Master.Angle);
    //
    IMyMotorStator Slave1 = GridTerminalSystem.GetBlockWithName("Rotor Slave 1") as IMyMotorStator;
    float SlaveAngle1 = MathHelper.ToDegrees(Slave1.Angle);
    float Error1 = SetPoint-SlaveAngle1;
    if (Error1>=30f){Error1=30f;}
    if (Error1<=(-30f)){Error1=(-30f);}
    Slave1.SetValueFloat("Velocity", Error1);
    //
    }
    that works, just tested in game.
    the changes were: line 1, capitalise 'main' (rookie mistake, i really should have seen this)
    change 2 and 3 : lines 9 and 10, greater/less than or equal to, not equal to greater/less then. C# being a pedantic language. i blame microsoft, because its easy to.

    sorry for the typos, serves me right for not testing in game.
     
    Last edited: Dec 26, 2016
  6. chris chance Trainee Engineer

    Messages:
    6
    its all good, after i post i got really sick. so i just now able to try it out myself.

    i just played with it. it works pretty well, but it does this odd 360 spin when you cross over the 0 degrees mark.

    sorry for the bad typing here, still really sick
     
    Last edited: Dec 26, 2016
  7. Sinbad Senior Engineer

    Messages:
    2,788
    Sorry to hear you were ill, but im glad it works for you now, mostly. The zero crossing odd spin is a result of the math
    Target-actual=direction
    So if the target is 0.1degree, and the actual is 359.9degrees, the error is -359.8, which translates to spinning the wrong way as fast as it can to get to 0.1 by counting down. I never did find a simple fix for that. My advise, try to avoid crossing zero. If you dont need a full rotation,, but zero happens to fall in the middle of the range you are using, try removing the rotors and replacing them after spinning them to move zero out of range.

    Alternativly, if all you want is for them to spin at the same speed, disregarding angle tracking,
    Try this instead, it doesnt have the zero crossing issue, but its got a different one instead, see below.
    Code:
    void Main()
    {
    IMyMotorStator Master = GridTerminalSystem.GetBlockWithName("Rotor Master") as IMyMotorStator;
    float MasterVel = Master.Velocity;
    //
    IMyMotorStator Slave1 = GridTerminalSystem.GetBlockWithName("Rotor Slave 1") as IMyMotorStator;
    Slave1.SetValueFloat("Velocity", MasterVel);
    //
    }
    That will make sure the slave is doing the same rpm, in the same direction, with no regard for matching position. The slave will lag 1/60th of a second behind the master whenever you change speeds. It doesnt sound like much, but at a 60rpm difference (going from full forward to full reverse in one click) will lead to a six degree angle difference. Do it a few more times, and they wont be lined up at all, so only use this one if you are matching speeds, but dont care about angles.
    This will happen because the new speed is changed on the master, then read and assigned to the slave on seperate ticks. So the master gets an extra physics tick before the slave has its speed changed.
    Most of motion control is finding ways to remove issues like these and not create new ones, which are generally much harder to figure out why they happen.
     
  8. chris chance Trainee Engineer

    Messages:
    6
    yea, i had to stop and think about it cause the truth is i only need 180 degrees not a full 360. as of the lag in movement, thats ok.
     
    • Like Like x 1
  9. d4rky1989 Apprentice Engineer

    Messages:
    332
    There is a MathHelper class that can solve this issue. Currently I can't remember the exact class name nor the method name. But it is out there :p
     
    • Friendly Friendly x 1
  10. Sinbad Senior Engineer

    Messages:
    2,788
    its wrap angle, i know. i found it back when i started working with @GrindyGears on his excavator projects. https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.mathhelper.wrapangle.aspx
    the problem is, both angles would need to be wrapped. at some point the sign of the master changes, and the slave hasn't yet, it results in the same problem.

    i just tried it again, a year or so after the first attempt:
    Code:
    void Main()
    {
    IMyTextPanel Test = GridTerminalSystem.GetBlockWithName("LCD Test1") as IMyTextPanel;
    IMyMotorStator Master = GridTerminalSystem.GetBlockWithName("Rotor Master") as IMyMotorStator;
    float SetPoint = MathHelper.WrapAngle(Master.Angle);
    IMyMotorStator Slave1 = GridTerminalSystem.GetBlockWithName("Rotor Slave 1") as IMyMotorStator;
    float SlaveAngle1 = MathHelper.WrapAngle(Slave1.Angle);
    float Error1 = MathHelper.ToDegrees(SetPoint-SlaveAngle1);
    if (Error1>=30f){Error1=30f;}
    if (Error1<=(-30f)){Error1=(-30f);}
    Slave1.SetValueFloat("Velocity", Error1);
    
    }
    the race around zero crossing just happens at 180 degrees instead. maybe im using it wrong? but it gave me an idea...

    Code:
    void Main()
    {
    IMyTextPanel Test = GridTerminalSystem.GetBlockWithName("LCD Test1") as IMyTextPanel;
    IMyMotorStator Master = GridTerminalSystem.GetBlockWithName("Rotor Master") as IMyMotorStator;
    float SetPoint = MathHelper.ToDegrees(Master.Angle);
    IMyMotorStator Slave1 = GridTerminalSystem.GetBlockWithName("Rotor Slave 1") as IMyMotorStator;
    float SlaveAngle1 = MathHelper.ToDegrees(Slave1.Angle);
    float Error1 = (SetPoint-SlaveAngle1);
    if (Error1>=31f){Error1=Master.Velocity;}
    if (Error1<=(-31f)){Error1=Master.Velocity;}
    if (Error1>=30f){Error1=30f;}
    if (Error1<=(-30f)){Error1=(-30f);}
    Slave1.SetValueFloat("Velocity", Error1);
    
    }    
    this works! its the same as the original masterslave setup from above posts, but this time, instead of using an error of greater than 30 degrees to limit the slaves rpm, i use it as an error condition for detecting zero crossing first at 31degrees to set the slaves velocity to match the master. then use the 30rpm as a limit after that.
    in use, the slave should never be more than a few degrees behind the master, so large errors should not be seen often. when the large error is seen in the first script, the slave races further away from the master until the false indication becomes a true one.
    now, the few degrees of false indication force the slave to match the direction and speed of the master directly until the false indication condition has passed, the slave also crosses zero. then the large error goes away and operation resumes as normal.
    i even tried tripping it up by doing a few reverse directions over the zero crossing at 30rpm. a slight jiggle, but no race around.
    so, @chris chance the second script in this post doesnt have the race around issue with zero crossing.
    thanks, @d4rky1989 for getting me to look into this issue again.
     
  11. GrindyGears Senior Engineer

    Messages:
    1,787
    Not usually my section to post in, but hey, I'm glad you got that resolved, shows you're improving as a programmer
     
    • Like Like x 1
  12. Sinbad Senior Engineer

    Messages:
    2,788
    it was more to link your work than draw your attention, sorry.
     
Thread Status:
This last post in this thread was made more than 31 days old.