Jump to content

hatbat

Member
  • Content Count

    11
  • Joined

  • Last visited

  • Medals

Posts posted by hatbat


  1. 7 hours ago, sarogahtyp said:

    okay, thx for debugging those typo.

     

    negative time:

    I ve calculated it manually and it seems to be a point of view problem.

    I think if you change obj1 and obj2 each other then the time is positive. Actually idk why but it resides in the formula and is no bug in the script.

     

    EDIT:

    I recalculated the complete formulas now and they are correct...

     

    6 hours ago, sarogahtyp said:

    If it is not the case that changing obj1 with obj2 gives a positive time then just negate the ETA before returning it.
    As I said the formulas seem to be correct.

    It would be cool if u check the distance value as well because it should be positive in any case.

    sent from mobile using Tapatalk
     


    Nah. Swapping object 1 and 2 had no effect, at least when calling the function. I've negated the result of _ETA as you suggested and that's provided a suitable workaround. It's also had the effect of fixing _DIST, which previously didn't work.

     

    I don't see how this couldn't be an error in the formula. I think the problem stems from the numerator which returns negative when it should be returning positive (at least I think so). Maybe when you get some time you could figure out why? This is the test scenario.

     

    https://www.dropbox.com/s/r1pkqe388jwukju/Virtual%20Velocity%20Testing.VR.zip?dl=0


  2. 4 hours ago, sarogahtyp said:

    I reread the formula for _ETA and it is correct.

    I be to go sleep now.

    Plz check all position and Velocity components and the numerator and dominator as well.

    If that is not helping then calculate an ETA manually with a calculator to verify the formula please.
    I ll look at your findings tomorrow in the morning.

    sent from mobile using Tapatalk
     


    Well...

     

    I set up some pretty extensive debugging and found that _numerator was evaluating to 0. I thought that was a little odd so I began to input some example numbers into a calculator and quickly realised the coordinates for the objects were identical. All down to this little typo.


    private _pos1 = if(_is_pos_obj1) then {_obj1} else {getPosASL _obj1};
    private _pos2 = if(_is_pos_obj2) then {_obj2} else {getPosASL _obj1};

     

    Since that's sorted I'd like to get on to the issue of the ETA being inverted. I don't think you quite understood what I meant when I said the ETA was negative so here's an example:

     

     

    Note how the ETA in the system chat is negative whilst moving towards the target and positive when away? Are _numerator and _dominator in the wrong order?

     

    This is the current script if it helps:

     

    /*
     Author: Sarogahtyp
     Description:
     Calculates the current estimated Time of arrival (ETA) at a rendevouz point and the distance at this point for two (flying) objects.
     the rendevouz point is the point where the two object will get closest together with their actual velocity vectors.
    
     Arguments:
    
     0: object1 or 3D ASL position 1 - one of both objects or its position
     1: object2 or 3D ASL position 2 - the other object or its position
     2: 3D velocity vector for position 1 - only needed if argument 1 is position
     3: 3D velocity vector for position 2 - only needed if argument 2 is position
    
     return value:
    
     array with 2 components
     0:  ETA
     1:  Minimum distance (on ETA)
    */
    
    
    params [
    	["_obj1", objNull, [objNull, []]], 
    	["_obj2", objNull, [objNull, []]],
    	["_vel1", objNull, [[]]], 
    	["_vel2", objNull, [[]]]
           ];
    	   
    if(isNull _obj1 || isNull _obj2) exitWith {true};
    
    private _is_pos_obj1 = (typeName _obj1 isEqualTo "ARRAY");
    private _is_pos_obj2 = (typeName _obj2 isEqualTo "ARRAY");
    
    if (( _is_pos_obj1 && isNull _vel1 ) || ( _is_pos_obj2 && isNull _vel2 )) exitWith {true}; 
    
    private ["_ETA", "_DIST", "_numerator", "_dominator"];
    
    //get ASL positions and split into coordinates
    private _pos1 = if(_is_pos_obj1) then {_obj1} else {getPosASL _obj1};
    private _pos2 = if(_is_pos_obj2) then {_obj2} else {getPosASL _obj2};
    
    _pos1 params ["_p1x", "_p1y", "_p1z"];
    _pos2 params ["_p2x", "_p2y", "_p2z"];
    
    //get velocities and split into coordinates
    _vel1 = if(_is_pos_obj1) then {_vel1} else {velocity _obj1};
    _vel2 = if(_is_pos_obj2) then {_vel2} else {velocity _obj2};
    
    _vel1 params ["_v1x", "_v1y", "_v1z"];
    _vel2 params ["_v2x", "_v2y", "_v2z"];
    
    //calculate ETA
    _numerator = (_p2y-_p1y)*_v2y + (_p2x-_p1x)*_v2x + (_p1z-_p2z)*_v1z + (_p1y-_p2y)*_v1y + (_p1x-_p2x)*_v1x + _v2z*_p2z - _v2z*_p1z;
    _dominator = _v2y^2 - 2*_v1y*_v2y + _v2x^2 - 2*_v1x*_v2x + _v1z^2 - 2*_v2z*_v1z + _v1y^2 + _v1x^2 + _v2z^2;
    
    if (_dominator != 0) then {
    
    _ETA = _numerator / _dominator;
    systemChat format ["Numerator: %1, Dominator: %2, ETA: %3, Obj1: %4, Pos1: %5 %6 %7, Vel1: %8 %9 %10, Obj2: %11, Pos2: %12 %13 %14, Vel2: %15 %16 %17", round _numerator, round _dominator, round _ETA, _obj1, round _p1x, round _p1y, round _p1z, round _v1x, round _v1y, round _v1z, _obj2, round _p2x, round _p2y, round _p2z, round _v2x, round _v2y, round _v2z];
    
    //calculate distance on ETA
    _DIST = sqrt ( ((_v2y-_v1y)*_ETA+_p2y-_p1y )^2 + ((_v2x-_v1x)*_ETA+_p2x-_p1x)^2 + ((_v1z-_v2z)*_ETA-_p2z+_p1z)^2 );
    
    } else {_ETA = '∞'; _DIST = '∞';};
    
    [_ETA, _DIST]

     

     

     


  3. 1 hour ago, sarogahtyp said:


    This is wrong!
    My mistake are two missing closing brackets at the end of the lines of _obj1 and _obj2


    sent from mobile using Tapatalk
     

     

    I fixed that and I'm not getting any more error reports but for reasons unknown _ETA always evaluates to zero, despite _obj1, _obj2, _vel1 and _vel2 all returning what they should be after having checked them. Perhaps you made a mistake when writing the equation? This is what I have right now:

     

    /*
     Author: Sarogahtyp
     Description:
     Calculates the current estimated Time of arrival (ETA) at a rendevouz point and the distance at this point for two (flying) objects.
     the rendevouz point is the point where the two object will get closest together with their actual velocity vectors.
    
     Arguments:
    
     0: object1 or 3D ASL position 1 - one of both objects or its position
     1: object2 or 3D ASL position 2 - the other object or its position
     2: 3D velocity vector for position 1 - only needed if argument 1 is position
     3: 3D velocity vector for position 2 - only needed if argument 2 is position
    
     return value:
    
     array with 2 components
     0:  ETA
     1:  Minimum distance (on ETA)
    */
    
    
    params [
    	["_obj1", objNull, [objNull, []]], 
    	["_obj2", objNull, [objNull, []]],
    	["_vel1", objNull, [[]]], 
    	["_vel2", objNull, [[]]]
           ];
    	   
    if(isNull _obj1 || isNull _obj2) exitWith {true};
    
    private _is_pos_obj1 = (typeName _obj1 isEqualTo "ARRAY");
    private _is_pos_obj2 = (typeName _obj2 isEqualTo "ARRAY");
    
    if (( _is_pos_obj1 && isNull _vel1 ) || ( _is_pos_obj2 && isNull _vel2 )) exitWith {true}; 
    
    private ["_ETA", "_DIST", "_numerator", "_dominator"];
    
    //get ASL positions and split into coordinates
    private _pos1 = if(_is_pos_obj1) then {_obj1} else {getPosASL _obj1};
    private _pos2 = if(_is_pos_obj2) then {_obj2} else {getPosASL _obj1};
    
    _pos1 params ["_p1x", "_p1y", "_p1z"];
    _pos2 params ["_p2x", "_p2y", "_p2z"];
    
    //get velocities and split into coordinates
    _vel1 = if(_is_pos_obj1) then {_vel1} else {velocity _obj1};
    _vel2 = if(_is_pos_obj2) then {_vel2} else {velocity _obj2};
    
    _vel1 params ["_v1x", "_v1y", "_v1z"];
    _vel2 params ["_v2x", "_v2y", "_v2z"];
    
    //calculate ETA
    _numerator = (_p2y-_p1y)*_v2y + (_p2x-_p1x)*_v2x + (_p1z-_p2z)*_v1z + (_p1y-_p2y)*_v1y + (_p1x-_p2x)*_v1x + _v2z*_p2z - _v2z*_p1z;
    _dominator = _v2y^2 - 2*_v1y*_v2y + _v2x^2 - 2*_v1x*_v2x + _v1z^2 - 2*_v2z*_v1z + _v1y^2 + _v1x^2 + _v2z^2;
    
    if (_dominator != 0) then {
    
    _ETA = _numerator / _dominator;
    
    //calculate distance on ETA
    _DIST = sqrt ( ((_v2y-_v1y)*_ETA+_p2y-_p1y )^2 + ((_v2x-_v1x)*_ETA+_p2x-_p1x)^2 + ((_v1z-_v2z)*_ETA-_p2z+_p1z)^2 );
    
    } else {_ETA = '∞'; _DIST = '∞';};
    systemChat str _ETA; //DEBUG
    
    [_ETA, _DIST]
    
    
    
    

     

     


  4. 1 minute ago, sarogahtyp said:

    ETA should go negative if both objects are moving apart each other because the time of being closest is history then.

    I thought bout a check for zero for the dominator as well. Should be better to have it

    sent from mobile using Tapatalk
     

     

    What I meant is that it was like the ETA was inverted. Positive when moving away and negative when moving together.


    For now I've just dodged the zero divisor by adding this 

     

    if (velocityEquations != 0) then {

     

    but I think it might be handy to have it return perhaps an infinity symbol if the velocity was zero. Could that be done?

     


  5. 5 minutes ago, sarogahtyp said:

    What issues?

    sent from mobile using Tapatalk
     

     

    At the start of a mission the velocity will be zero right? That doesn't sit so well with this part:

    t_dmin = positionEquations / velocityEquations;
    

    I also found that the ETA seemed to give a negative number when the two objects were moving towards each other. I wouldn't have a clue why that is and it could possibly be my fault but I found that it was fairly simple just to use abs when fetching the result.

     

    abs (round t_dmin);

     

    Still, I'm going to test your script if I can figure how to implement a function.


  6. 5 hours ago, sarogahtyp said:

    Found some minutes to create a script for it. Its completly untested and may contain errors and/or bugs.

    I am currently not able to test it. I would be happy if someone could do this and report errors and/or bugs here. I ll look what I ve to change then.


    Wow, this is rather fortunate timing. I had just written a much more simplistic script based off your post and was about to bring forward some issues. I'll test your script first but I have a feeling there might be the same problem. This is what I wrote.

     

    hostile = (nearestObjects [_this, ["Man"], 100]) select 1; //"B_Fighter_Pilot_F"
    
    while {true} do {
    
    P1x = getPosASL _this select 0;
    P1y = getPosASL _this select 1;
    P1z = getPosASL _this select 2;
     
    P2x = getPosASL hostile select 0;
    P2y = getPosASL hostile select 1;
    P2z = getPosASL hostile select 2;
     
    V1x = velocity _this select 0;
    V1y = velocity _this select 1;
    V1z = velocity _this select 2;
     
    V2x = velocity hostile select 0;
    V2y = velocity hostile select 1;
    V2z = velocity hostile select 2;
    
    positionEquations = ( (P2y-P1y)*V2y + (P2x-P1x)*V2x + (P1z-P2z)*V1z + (P1y-P2y)*V1y + (P1x-P2x)*V1x + V2z*P2z - V2z*P1z );
    velocityEquations = ( V2y^2 - 2*V1y*V2y + V2x^2 - 2*V1x*V2x + V1z^2 - 2*V2z*V1z + V1y^2 + V1x^2 + V2z^2 );
    
    if (velocityEquations != 0) then {
    
    t_dmin = positionEquations / velocityEquations;
    
    hintSilent parseText format [" Your speed: %1 m/s <br /> Hostile Speed: %2 m/s <br /> ETA = %3 seconds ", 
    round ((velocityModelSpace _this) select 1), round ((velocityModelSpace hostile) select 1), abs (round t_dmin)];
    
    } else {
    
    hintSilent "";
    
    };
    sleep 0.1;
    };

     


  7. I've just started learning to script in earnest and so far I've been playing with a "widget" that will report various things to the player about an oncoming wave of jets during an air combat mission. It works just fine but the obvious flaw is that the ETA does not account for the direction the enemy wave might be flying. I need the relative velocity of two objects along the direction between them; so basically how fast they're converging on each other. If, for example, one object was flying in a perfect orbit around the other then the result of this would be 0m/s because the two objects were neither moving closer nor further together. I've done enough research to know this calculation will be the sum of the velocities of the objects along said direction (playerjet getDir enemyjet) and will probably involve the x and y of the velocity command when used on these objects but I just don't have a good enough understanding of maths or scripting to work out how to get there. I'd greatly appreciate anyone's help.

     

    	monitor = 0; 
    	
    	_leaderVel = 999; //These two variables are predefined so that if a player has a poor connection and receives zero then the distance / speed equation will not be a divide by zero.
    	_distance = 999;
    	
    	player addAction ["Monitor Hostiles", {monitor = 1}, [], 10, false, true, "", "monitor == 0 && isEngineOn wingleader", -0, false];
    	player addAction ["Stop Monitoring Hostiles", {monitor = 0; hintSilent ""}, [], 10, false, true, "", "monitor == 1 && isEngineOn wingleader", -0, false];
    	
    	while {isEngineOn wingleader} do {
    	
    		if (monitor == 1) then {
    			_leaderSpeed = round speed wingleader;
    			_leaderVel = if (_leaderSpeed != 0) then {round ( _leaderSpeed * 0.277778)}; //Conversion to m/s.
    			_distance = if (player distance wingleader != 0) then {player distance wingleader};
    			_ETA = round (_distance / _leaderVel);
    			hintSilent parseText format ["Hostile now at %1 km/h and %2 m/s! <br />It's %3 km away with a %4 second ETA!", _leaderSpeed, _leaderVel, [(_distance / 1000),1] call BIS_fnc_cutDecimals, _ETA];
    			sleep 0.1;
    		};
    
    	};

     


  8. I need units to ignore formation for a mission I'm working on and I've solved this by giving each unit it's own group. Unfortunately this means I've quickly hit the 144 group cap. To solve this I've come up with a trigger that allows a unit to be in the a group with others but not attempt to form a formation until it's attacked. This code requires the condition function of a trigger however I need it to instead work within the init line of each soldier as creating a trigger and name for every soldier would be impractical. This is the code as applied to a trigger (the soldier's name is unit1, who from the start has a disableAI "MOVE"):

     

    CONDITION: (behaviour unit1) == "COMBAT"

     

    ON ACTIVATION: unit1 enableAI "MOVE";

     

    I've had success with combining this code into the init line of a soldier, though due to the nature of init lines, it only runs once at the beginning of the mission when it isn't needed. I need an example of how to make the code repeat itself until true, much like a trigger condition, though within an init line.

     

    Unit's current init line, I need the if statement to repeat itself if it doesn't currently return as true. 

    this disableAI "MOVE"; if ((behaviour this) == "COMBAT") then {this enableAI "MOVE"};
     
×