Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Constraints in spherical coordinates

Discussion in 'Physics' started by SurfWise, Feb 1, 2021.

  1. SurfWise

    SurfWise

    Joined:
    Dec 13, 2020
    Posts:
    5
    Hello everyone!
    I have two rigid bodies (short: rb) in scene. Lets consider one of the rb as center of a sphere and other rb (wing) moves in relation to centre only in spherical coordinates - connected with fixed joint. Wing is always in distance R from centre. I am using following code to determine movement of wing on the sphere.

    Code (CSharp):
    1. var pos = transform.position; //get position
    2.             pos += -transform.forward * speed * Time.deltaTime; //move forward
    3.             var v = pos - InertialRef.position; //get new position relative to center of sphere
    4.             pos = InertialRef.position + v.normalized * R; //constrain position to surface of sphere
    5.             transform.position = pos; //set position
    I'd like to lock the movement only to part of the sphere - precisely 1/4 of a sphere. Speaking in spherical coordinates range - phi and theta would be phi = <0, PI/2 > ; theta = <0,PI>.

    You can see from the code that I want the wing to go only towards the direction it is facing transform.forward. I want the wing to stop whenever it reaches the limit of a sphere. However if the wing is at the edge but transform.forward is not perpendicular to the boarder of sphere I still would like it to slide at its edge (without going beyond the limits). Similar feeling we get when playing any FPS if we walk into the wall and still press W. When we face the wall perpendicular we stop, if we face it slightly to side from perpendicular we are still moving alongside the wall but slowly. Can You help me how to make those constraints with that kind of movement at the edge?

    I am using following methods for conversion between Cartesian and Spherical coordinates
    Code (CSharp):
    1.  public Vector3 SphericalToCartesianLocal(float R, float Theta, float Phi)
    2.     {
    3.         x = R * Mathf.Cos(Theta) * Mathf.Sin(Phi);
    4.         y = R * Mathf.Cos(Phi);
    5.         z = R * Mathf.Sin(Theta) * Mathf.Sin(Phi);
    6.  
    7.         return new Vector3(x, y, z);
    8.     }
    9.  
    10. public Vector3 CartesianToSpherical(Vector3 CenterPosition, Vector3 WingPosition)
    11.     {
    12.         Vector3 VecBetweenCenterAndWing = WingPosition - CenterPosition;
    13.  
    14.         float r = 22f;
    15.         theta = Mathf.Atan2(VecBetweenCenterAndWing.z,  VecBetweenCenterAndWing.x);
    16.         phi = Mathf.Acos(VecBetweenCenterAndWing.y / r);
    17.  
    18.         return new Vector3(r, theta, phi);
    19.     }
    Thank You for Your time and appreciate any tips!
     
  2. AlTheSlacker

    AlTheSlacker

    Joined:
    Jun 12, 2017
    Posts:
    326
    You appear to have two rbs connected by a fixed joint, then you are moving the child rb by updating its transform position directly. This is not normally how rbs are used, I would have expected you to have a driven joint or maybe some chained joints, or an articulation or a joint/articulation as a constraint with a force on the child body.

    Can you explain why the child rb is moving? Is the root body constrained/moving/controlled? Are these bodies kinematic or not. What is the true nature of the constraint between parent and child bodies?

    I'm sorry this is not addressing your question directly, but the answers will influence the solution.

    If you can share images or a small example.unitypackage that would help.
     
  3. SurfWise

    SurfWise

    Joined:
    Dec 13, 2020
    Posts:
    5
    Hello, thank You for response. I explained what I'd like to achieve in too simplified way as I was doing simplified model. What I am trying to achieve is realistic simulation of flying wing attached with tether to mass. It is the best shown under this link: https://kitex.tech/kitesim/

    I'd like to make wing dynamics as realistic as possible and I am trying out different approaches.
    One approach (used in link above) simulates the wing and tether as particles connected with springs forces (using Hook's Law). First Particle of tether is assumed to be fixed in space at the origin of inertial reference frame and for the last particle kite forces should be taken into account.

    Code (CSharp):
    1.  
    2.  for (int i = 0; i <= 4; i++)
    3.         {
    4.          //P[i] - i-th Particle position [Vector3]
    5.           s[i] = P[i + 1] - P[I];      // s[i] - segment vector between particle i+1 and i of tether
    6.            s_v[i] = v[i + 1] - v[I];   // s_v[i] - velocity of i-th segment
    7.            TetherSegmentLenght = TetherLenght/NumberOfTetherSegments;
    8.            //Spring forces acting on i-th tether particle calculated accordingly to hook's law
    9.             // k = 614000[N]  spring coefficient
    10.             // c = 427[N*s] damping coefficient
    11.             F_Spring[i] = Vector3.Normalize(-s[i]) * (k * (Vector3.Magnitude(s[i]) - TetherSegmentLenght) + c * (Vector3.Dot(Vector3.Normalize(s[i]), s_v[i])));
    12.           //Average segment velocity:
    13.                 v_s[i] = (v[i + 1] + v[i]) * 0.5f;
    14.         //Apparent air velocity of I-th segment      
    15.                 v_a_s[i] = V_wind_ref - v_s[i];
    16. //We need only perpendicular component of apparent air velocity as it has effect on drag force
    17.                 v_a_s_perpendicular[i] = v_a_s[i] - ((Vector3.Dot(v_a_s[i], Vector3.Normalize(s[i]))) * Vector3.Normalize(s[i]));
    18.                 F_Drag[i] = 0.5f * TetherDragCoeff * Rho * Vector3.Magnitude(v_a_s_perpendicular[i]) * Vector3.Magnitude(s[i]) * tetherDiameter * v_a_s_perpendicular[I];
    19. // To combine spring and drag forces acting on I-th particle (excluding particle 0 as for simplicity we assume this to be fixed in origin of inertial ref frame)
    20. if (i > 0 )   f[i] = F_Spring[i - 1] + F_Spring[i] + 0.5f * (F_Drag[i] + F_Drag[i - 1]);
    21.  
    First I try to model kite as one particle at the end of the tether with aerodynamics and gravity forces acting on particles

    Apparent wind velocity of wing and
    triad basis of the wing is calculated as:

    Code (CSharp):
    1.  
    2.            AppWingVel = WindVel - WingVel;
    3.             e_z =  Vector3.Normalize(-s[numberOfTetherSegments-1]);
    4.             e_y = Vector3.Normalize(Vector3.Cross(AppWingVel , e_z));
    5.             e_x = Vector3.Cross(e_z, e_y);
    6.  
    and external forces acting on wing are calculated as :

    Code (CSharp):
    1.  
    2.          // A_w = 10 [m2] area of the wing
    3.          // cl(alpha) and  cd(alpha) - aerodynamic coefficients with alpha(angle of attack) as argument
    4.          //
    5.            //Lift Force
    6.             F_L = 0.5f * Rho * Mathf.Pow( AppWingVelScalar, 2) * A_w * cl(alpha)* Vector3.Normalize(Vector3.Cross(v_a, e_y));
    7.            //Drag Force
    8.             F_D = 0.5f * Rho * Mathf.Pow( AppWingVelScalar, 2) * A_w * cd(alpha)* (1 + K_s_D * Mathf.Abs(u_s))*   Vector3.Normalize(v_a);
    9.             //Side Force due to the steering input
    10.             F_s = 0.5f * Rho * Mathf.Pow AppWingVelScalar, 2) * A_w * Aside * c_s * (i_s + i_s_c) * e_y;
    11.            //Gravity force
    12.             F_g = WingMass * G;
    13.            //Force acting on the wing
    14.             F_w = F_L + F_D + F_s + F_g +F_Spring[4];
    15.  
    16.  
    and angle of attack is calculated as:

    Code (CSharp):
    1.  
    2. alpha = Mathf.Acos(Vector3.Dot(AppWingVel, e_x) / AppWingVelScalar);
    3.  
    With all above calculations I've tried to use Verlet Integration to determine dynamics of each particle due to the forces acting in such way:

    Code (CSharp):
    1.  
    2. //Dynamics of wing
    3.         Vector3 New_goWingRefFrame = goWingRefFrame.transform.position + WingVelocity * Time.fixedDeltaTime + WingAcceleration * (Time.fixedDeltaTime * Time.fixedDeltaTime * 0.5f);
    4.         Vector3 NewWingAcceleration = (F_W / WingMass)/100;
    5.         Vector3 NewWingVelocity = WingVelocity + (WingAcceleration + NewWingAcceleration) * (Time.fixedDeltaTime * 0.5f);
    6.         goWingRefFrame.transform.position = New_goWingRefFrame;
    7.         WingVelocity = NewWingVelocity;
    8.         accKite = NewAccKite;
    9. //Dynamics of P1
    10.         Vector3 New_P1_pos = P1.transform.position + v[1] * Time.fixedDeltaTime + accP1 * (Time.fixedDeltaTime * Time.fixedDeltaTime * 0.5f);
    11.         Vector3 NewAccP1 = f[1];
    12.         Vector3 NewVelP1 = v[1] + (accP1 + NewAccP1) * (Time.fixedDeltaTime * 0.5f);
    13.         P1.transform.position = New_P1_pos;
    14.         v[1] = NewVelP1;
    15.         accP1 = NewAccP1;
    16.  
    and each of tether particle state is simulated similarly to P1

    Then I'd like to display the wing in space and I don't know if I should make it as Rigid body or just with MeshRenderer to display its shape and do all the physics by myself? What approach would be the best?

    For now the inertia of attitude dynamics is omitted as the wing is modelled as 1 point in space. Once this would give reasonable results I'd like to move to more advanced model.

    When I tried to simulate above model in Unity I get weird results... Tether can never be stiff as expected neither when I increase spring constant nor when clamp the maximum distance between two particles of the tether. It always seems too elastic. I've decreased the Physics Time Step to 0.001 and all the calculations are happening in FixedUpdate yet it doesn't solve my problem.

    What I presented above also explains why I wanted to constraint the motion of the wing only to 1/4 of sphere. Due to the aerodynamic forces wing should never fly closer to the source of wind than the mass that is connected to the wing and also should stop if it hits the ground.

    In second approach the dynamics of the wing are derived from Lagrangian equation regarding Potential and Kinetic energy of the system. In this case tether is assumed to be inelastic (stiff rod without spring forces acting on). I have found a set of differential algebraic equations of motion (I think it's too extensive to present it here but I can redirect to scientific article that derives such equations). What would be the best way to incorporate it with Unity Engine? Should the wing be done as rigid body? That give lots of possibilities in the future to use functionality of rbs. Yet I am aware that what I am doing is more on physics engine level...

    I'd appreciate any advices and hints that would point me to right direction of which approach would be recommended in such case. If anything is not clear enough I will clarify.
     
  4. maksvet

    maksvet

    Joined:
    Oct 22, 2020
    Posts:
    1
    I am very glad that I found this thread. I have an Idea of creating a control line air models simulator which is similar in physics to the kite.
    I have a couple questions: what is the real elasticity of the control lines you use on kite? Could you just have the kite moving on the surface of the sphere and have a person controlling it on a fixed distance. It's not like you could replicate the tension on physical controls easily enough.
    Thank you for the code and links: it's really helpful!