1. Limited time only! Sign up for a free 30min personal tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Two-Dimensional Collision With Two Moving Objects

Tags:
  1. Jul 31, 2015 #1
    1. The problem statement, all variables and given/known data

    Two moving objects (circle shaped) with a known mass, move in a 2D plane with a known constant direction and speed, at certain point, objects collide with eachother (elastic). At that point, the coordinates of the center each object is known, their radius is also known, their Vx and Vy are known (everything whats needed is known, almost). Determine the final speed vector for each object

    2. Relevant equations

    I found this equation:

    b09d23456a39b81126c36844fdc13582.png

    What exactly are the theta and phi angles and how are they calculated on a cartesian plane.
    Are they calculated in radians or degrees for that equation (I guess that they are in radians, due to the final 1/2 pi).

    3. The attempt at a solution

    I have some troubles determining the angles (theta and phi), because I am not sure whether or not I have to add them certain values (180, 180, 360) depending on the different quadrants( +x+y, -x+y, -x-y, +x-y).

    Thank you very much!
     
  2. jcsd
  3. Jul 31, 2015 #2

    haruspex

    User Avatar
    Science Advisor
    Homework Helper
    Gold Member
    2016 Award

    A physics equation has no value unless the variables it uses are defined. Wherever you found those equations, you should also find those definitions. Maybe you don't understand the definitions given, but if so you need to quote those definitions in your post so that others can interpret them, but it's a bit tough trying to guess the definitions from these equations alone.

    Better still, ignore those equations you found, make up your own variable names, and people on this forum can help you develop your own equations from the basic laws that apply. What are those laws?
     
  4. Jul 31, 2015 #3
    I've got those equations on this website, also on wikipedia. :P

    Anyways, here is what I am trying to do, I hope you can help me with it.

    I'm trying to program with Java, a small 2D game (just for fun and learning) in which I use circles as objects with certain radius which move with a speed given on pixels and updates the position on the X/Y Axis 60 times per second. The X/Y Axis is kinda awkward, because the 0,0 coordenates of the window on which the textures are rendered is at the top left of the window and the Y Axis is inverted (down increases and up decreases). With that in mind, I have to determine the point of impact of two objects based on their position (x,y), velocity (velx, vely : for example with :velx=2, vely=2, the rendered circle moves down to the right side of the window), radius and mass.

    The collision is calculated based on the radius of the objects and their position [ ( ( x2-x1)^2 + (y2-y1)^2 )^1/2 <= r2+r1 ] (x1,y1/x2,y2 the position of the objects based on coordenates, and r1,r2 their radius). It works like a charm, so when they are touching I run the script that makes them change their velocity; which I have been trying to accomplish with no success. With the equation of the opening post I managed to have some good collisions, regardless, I have problems sometimes where the objects do not move properly.

    So, I have all the information needed to do the math, but the main problem I have is the inverted Y Axis, which messes up with the angles and I have not managed to make it right. I hope you guys can help me out. Thanks in advance!
     
  5. Jul 31, 2015 #4

    haruspex

    User Avatar
    Science Advisor
    Homework Helper
    Gold Member
    2016 Award

    Based on the diagram at the link, the two theta angles are the angles to the x axis made by the trajectories of the approaching discs. Phi is the angle to the x axis made by the line through the two centres when the discs touch.
    The author has been inconsistent, showing theta2 as measured from the -ve x direction but the other two from the +ve x. Looking at the equations, theta2 is really measured from the +ve x direction, so the diagram is wrong. The equations' theta2 is pi plus the angle shown. (Getting this wrong will affect the signs of the trig functions.)
    All three are measured clockwise from the reference, whereas the Cartesian standard is to measure anticlockwise. However, that makes sense because down is +ve Y in the computer's representation.
    It depends what your trig functions expect. Radians would be standard.
    Getting the trig signs right can be quite a challenge.
    E.g. for finding theta1, you use arctan(vy/vx), but that only gives an answer in a range of pi (-pi/2 to +pi/2 I would guess). For the equations, you need to know the angle in a full 2pi range. To determine that, you have to look at the sign of vy and/or vx. If vx is negative the object is heading left, so the angle must be in the range pi/2 to 3pi/2. To correct, just add pi to the arctan result.
    You also need to protect against zero-divide in calculating vy/vx.

    Another thought....
    Sounds as though your time intervals are small enough that there are no funny effects where objects overlap etc. But if that is a problem, you need to detect that the collision occurred somewhere in the last time interval, compute exactly when that was, execute the bounce logic on that basis, then position the objects based on how they would have travelled since.
    Of course, this can get quite hairy with multiple collisions by the same object in one time interval.
     
  6. Aug 2, 2015 #5
    Thanks a lot for your help. I have corrected the equation based on what you have suggested, I just have to find the correct angles to make the objects bounce.

    I have a few questions:

    1. Do I have to use the same phi for both objects?(pretty sure I have to).

    2.
    theta2 = (PI + "theta2")



    In regards to the last thought, I have been reading about how to calculate the exact position of impact to correct the location of the objects so that they do not overlap. In the meanwhile, to test the correct final velocity of each object, I make them collide just once with a boolean field.

    Another issue that I have been thinking on is that I calculate the distance between each object based on their position (x,y) to calculate the distance between their centers and comparing it to their radius, with a pythagorean theorem, but it only work if the objects are within the frame (+x,+y).

    Again, thanks for your help.

    Edit:


    I ran 4 collisions and here you can see the results:

    Code (Text):

    Initial position, direction and speed
    objects have same radius and same mass (2*PI*r, just used the area of the circle to give them mass).
    vx, vy: pixels per 0,016666 seconds (game updates 60 times per second).

    Angle of collision
    Phi 44.55387947558248

    gO1
    x:610.0
    y:307.0
    Vx:-1.0
    Vy:-1.0
    theta, deg:45.0
    theta, rad:0.7853981633974483

    gO2
    x:564.7000000000047
    y:262.39999999999765
    Vx:0.1
    Vy:0.2
    theta, deg:63.43494882292201
    theta, rad:1.1071487177940904

    gO1
    x:610.0
    y:307.0
    Vx:0.1347928708643486
    Vy:0.0780045497865444
    theta, deg:30.057939577479935
    theta, rad:0.5246100119925381

    gO2
    x:564.7000000000047
    y:262.39999999999765
    Vx:0.6618245460937124
    Vy:0.753142930591247
    theta, deg:48.6926021887038
    theta, rad:0.8498462295566787

    Result: awkward collision



    Initial position, direction and speed

    Angle of collision
    Phi-38.54716002467078

    gO1
    x:518.0
    y:308.0
    Vx:1.0
    Vy:-1.0
    theta, deg:-45.0
    theta, rad:-0.7853981633974483

    gO2
    x:567.7000000000054
    y:268.3999999999973
    Vx:0.1
    Vy:0.2
    theta, deg:63.43494882292201
    theta, rad:1.1071487177940904

    gO1
    x:518.0
    y:308.0
    Vx:0.05737619804002281
    Vy:-0.18661970335408506
    theta, deg:-72.9099627395368
    theta, rad:-1.272518907311302

    gO2
    x:567.7000000000054
    y:268.3999999999973
    Vx:-0.6457889329971941
    Vy:-0.45208696110824664
    theta, deg:34.994086837063115
    theta, rad:0.6107620340355598

    Result: Collision seemed correct



    Initial position, direction and speed

    Angle of collision
    Phi:59.37821096161859

    gO1
    x:549.0
    y:241.0
    Vx:1.0
    Vy:1.0
    theta, deg:45.0
    theta, rad:0.7853981633974483

    gO2
    x:581.2000000000085
    y:295.39999999999577
    Vx:0.1
    Vy:0.2
    theta, deg:63.43494882292201
    theta, rad:1.1071487177940904

    gO1
    x:549.0
    y:241.0
    Vx:0.4040808389247806
    Vy:-0.09282509782172968
    theta, deg:-12.937479313695539
    theta, rad:-0.22580161093264345

    gO2
    x:581.2000000000085
    y:295.39999999999577
    Vx:0.49575577862969233
    Vy:0.8686060359455879
    theta, deg:60.28449181093118
    theta, rad:1.052162869992308

    Result: awkward collision



    Initial position, direction and speed

    Angle of collision
    Phi-55.11124190812558

    M1
    x:619.0
    y:246.0
    Vx:-1.0
    Vy:1.0
    theta, deg:-45.0
    theta, rad:-0.7853981633974483

    M2
    x:582.6000000000088
    y:298.1999999999956
    Vx:0.1
    Vy:0.2
    theta, deg:63.43494882292201
    theta, rad:1.1071487177940904

    M1
    x:619.0
    y:246.0
    Vx:0.318051489820771
    Vy:0.059985539221356285
    theta, deg:10.680706869495856
    theta, rad:0.18641350131307896

    M2
    x:582.6000000000088
    y:298.1999999999956
    Vx:-0.4108658742107923
    Vy:-0.7079128926404634
    theta, deg:59.869530325480376
    theta, rad:1.0449204258022249

    Result: awkward collision
     
    Last edited: Aug 2, 2015
  7. Aug 2, 2015 #6

    haruspex

    User Avatar
    Science Advisor
    Homework Helper
    Gold Member
    2016 Award

    Just to be clear, the equations shown at the link are correct. The error is merely in the way theta2 is drawn in the diagram.
    Yes.
    Because Vx<0 you need to add pi. And as I mentioned, you need to check for Vx = 0 before calculating the ratio for arctan's argument.
    A possible approach is to drive the iterations by events, not time intervals.
    From current position, inspect each pair of objects to see when they will collide (if they will). Take the shortest time.
    While the remaining time to the next event is greater than your chosen refresh interval, iterate sleeping and redrawing.
    When the time to the next event is less than the refresh interval, sleep for only that time, etc.
    Not sure what you are saying here.
    What is your policy for objects which move outside the displayable region? In principle you need to keep track of them because a fast moving object may exit the scene only to collide with a bunch of slow moving ones that already left. The result may be that the fast moving one ricochets back into view.
    Or are you saying the equations go wrong when x or y is negative?

    Feel free to post your code snippets.
     
  8. Aug 2, 2015 #7
    Code (Java):
    public void collisions(LinkedList<GameObject> gameObjects){
           
            //Declaration of the final velocity values of
           
           
            //the loop.
            for(int i = 0; i < gameObjects.size(); i++){
                for (int j = i+1; j < gameObjects.size(); j++){
                   
                    //Assigns the object located in i position to gO1 and j position to gO2              
                    GameObject gO1 = gameObjects.get(i);
                    GameObject gO2 = gameObjects.get(j);
                   
                    //checks if the objects intersect using a method of gameObject's class.
                    if(gO1.intersects(gO2)){
                        //checks if the objects intersecting eachother have different faction,
                        //added this in case that I want a specific object not to be checked for collisions.
                        if (gO1.getFaction() != gO2.getFaction()){
                           
                            //debug info.
                           
                            System.out.println("");
                            System.out.println("Initial position, direction and speed");
                            System.out.println("");
                            System.out.println("Angle of collision");
                            System.out.println("Phi"+Math.toDegrees(gO1.phi(gO2)));
                            System.out.println("");
                            System.out.println("M1");
                            System.out.println("x:"+gO1.getXr());
                            System.out.println("y:"+gO1.getYr());
                            System.out.println("Vx:"+gO1.getVelX());
                            System.out.println("Vy:"+gO1.getVelY());
                            System.out.println("theta, deg:"+Math.toDegrees(gO1.theta()));
                            System.out.println("theta, rad:"+gO1.theta());
                            System.out.println("");
                            System.out.println("M2");
                            System.out.println("x:"+gO2.getXr());
                            System.out.println("y:"+gO2.getYr());
                            System.out.println("Vx:"+gO2.getVelX());
                            System.out.println("Vy:"+gO2.getVelY());
                            System.out.println("theta, deg:"+Math.toDegrees(gO2.theta()));
                            System.out.println("theta, rad:"+gO2.theta());
                           
                         
                            //calculates the final Vx of gO1.
                            gO1Vxf = (( ( Math.sqrt( Math.pow(gO1.getVelX(),2) + Math.pow(gO1.getVelY(),2) ) * (Math.cos(gO1.theta() - gO1.phi(gO2))) * (gO1.getMass() - gO2.getMass()) + 2 * gO2.getMass() * Math.sqrt( Math.pow(gO2.getVelX(),2) + Math.pow(gO2.getVelY(),2) ) * (Math.cos(gO2.theta() - gO1.phi(gO2))) ) * Math.cos(gO1.phi(gO2))) / (gO1.getMass()+gO2.getMass()) + Math.sqrt( Math.pow(gO1.getVelX(),2) + Math.pow(gO1.getVelY(),2) ) * Math.sin(gO1.theta() - gO1.phi(gO2)) * Math.cos(gO1.phi(gO2)+Math.PI/2) );
                            //calculates the final Vy of gO1.                      
                            gO1Vyf = (( ( Math.sqrt( Math.pow(gO1.getVelX(),2) + Math.pow(gO1.getVelY(),2) ) * (Math.cos(gO1.theta() - gO1.phi(gO2))) * (gO1.getMass() - gO2.getMass()) + 2 * gO2.getMass() * Math.sqrt( Math.pow(gO2.getVelX(),2) + Math.pow(gO2.getVelY(),2) ) * (Math.sin(gO2.theta() - gO1.phi(gO2))) ) * Math.sin(gO1.phi(gO2))) / (gO1.getMass()+gO2.getMass()) + Math.sqrt( Math.pow(gO1.getVelX(),2) + Math.pow(gO1.getVelY(),2) ) * Math.sin(gO1.theta() - gO1.phi(gO2)) * Math.sin(gO1.phi(gO2)+Math.PI/2) );
                            //calculates the final Vx of gO2.
                            gO2Vxf = (( ( Math.sqrt( Math.pow(gO2.getVelX(),2) + Math.pow(gO2.getVelY(),2) ) * (Math.cos(gO2.theta() - gO1.phi(gO2))) * (gO2.getMass() - gO1.getMass()) + 2 * gO1.getMass() * Math.sqrt( Math.pow(gO1.getVelX(),2) + Math.pow(gO1.getVelY(),2) ) * (Math.cos(gO1.theta() - gO1.phi(gO2))) ) * Math.cos(gO1.phi(gO2))) / (gO2.getMass()+gO1.getMass()) + Math.sqrt( Math.pow(gO2.getVelX(),2) + Math.pow(gO2.getVelY(),2) ) * Math.sin(gO2.theta() - gO1.phi(gO2)) * Math.cos(gO1.phi(gO2)+Math.PI/2) );
                            //calculates the final Vy of gO2.
                            gO2Vyf = (( ( Math.sqrt( Math.pow(gO2.getVelX(),2) + Math.pow(gO2.getVelY(),2) ) * (Math.cos(gO2.theta() - gO1.phi(gO2))) * (gO2.getMass() - gO1.getMass()) + 2 * gO1.getMass() * Math.sqrt( Math.pow(gO1.getVelX(),2) + Math.pow(gO1.getVelY(),2) ) * (Math.sin(gO1.theta() - gO1.phi(gO2))) ) * Math.sin(gO1.phi(gO2))) / (gO2.getMass()+gO1.getMass()) + Math.sqrt( Math.pow(gO2.getVelX(),2) + Math.pow(gO2.getVelY(),2) ) * Math.sin(gO2.theta() - gO1.phi(gO2)) * Math.sin(gO1.phi(gO2)+Math.PI/2) );
                           
                            //sets the final velocity of each object.
                            gO1.setVelX(gO1Vxf);
                            gO1.setVelY(gO1Vyf);
                            gO2.setVelX(gO2Vxf);
                            gO2.setVelY(gO2Vyf);
                         
                         
                            //those objects can no longer collide (temporary "solution", to prevent objects getting stuck)
                            gO2.setFaction(gO1.getFaction());
                           
                            //More debug info.
                           
                            System.out.println("");
                            System.out.println("Final position(same), direction and speed");
                            System.out.println("");
                            System.out.println("M1");
                            System.out.println("x:"+gO1.getXr());
                            System.out.println("y:"+gO1.getYr());
                            System.out.println("Vx:"+gO1.getVelX());
                            System.out.println("Vy:"+gO1.getVelY());
                            System.out.println("theta, deg:"+Math.toDegrees(gO1.theta()));
                            System.out.println("theta, rad:"+gO1.theta());
                            System.out.println("");
                            System.out.println("M2");
                            System.out.println("x:"+gO2.getXr());
                            System.out.println("y:"+gO2.getYr());
                            System.out.println("Vx:"+gO2.getVelX());
                            System.out.println("Vy:"+gO2.getVelY());
                            System.out.println("theta, deg:"+Math.toDegrees(gO2.theta()));
                            System.out.println("theta, rad:"+gO2.theta());
                           
                        }
                   
                    }
               
                }
           
            }
       
           
        }
    Code (Java):

        /**
         *
         * @param m
         * @return whether the objects intersect or not.
         * It calculates the distance of the objects using phythagoras theorem: a*a + b*b = c*c,
         * checking a*a + b*b with the sum of the radious of the objects.
         */

        public boolean intersects(GameObject m){
         
            if( Math.pow(this.getXr() - m.getXr(), 2 ) + Math.pow(this.getYr() - m.getYr() , 2 ) <= Math.pow(this.getRadius() + m.getRadius(), 2) )
                       
                return true;
            else
                return false;  

        }
       
        /**
         *
         * @return  theta: the angle of the direction of the object with the X axis.
         * currently the conditions are only useful to prevent Y/0 division (pretty sure it
         * does not use the best solution to it - adding 0.001). It calculates the angle with
         * Math.atan(dy/dx). So, the conditions are there to correct certain angles due to that
         * it does not cover the full 2 PI range. But, what are those corrections? Im clueless.
         */

        public double theta(){
           
            if(this.getVelX() == 0 && this.getVelY() == 0)
                this.setVelX(0.001);
               
            if(this.getVelY() > 0 && this.getVelX() <= 0){
               
                return Math.PI + Math.atan(this.getVelY()  / this.getVelX()) ;
           
            }else if(this.getVelY() >= 0 && this.getVelX() > 0){
               
                return Math.atan(this.getVelY()  / this.getVelX()) ;
             
            }else if(this.getVelY() < 0 && this.getVelX() >= 0){
               
                return 2*Math.PI + Math.atan(this.getVelY()  / this.getVelX() );
           
            }else //if(this.getVelY() <= 0 && this.getVelX() < 0)
               
                return Math.PI + Math.atan(this.getVelY()  / this.getVelX()) ;
                         
            }
        /**
         *
         * @param m
         * @return phi: the angle of the collision of the objects with the X axis.
         * currently the conditions are only useful to prevent Y/0 division (pretty sure it
         * does not use the best solution to it - adding 0.001). It calculates the angle with
         * Math.atan(dy/dx). So, the conditions are there to correct certain angles due to that
         * it does not cover the full 2 PI range. But, what are those corrections? Im clueless.
         * Note: the position of the objects is based on x+radius, to check where is the center,
         * because x,y point is located at the upper left of the object.
         */

        public double phi(GameObject m){
           
            if(this.getYr() - m.getYr() > 0 && this.getXr() - m.getXr() <= 0){
             
                return Math.PI + Math.atan((this.getYr() - m.getYr()) / (this.getXr() - m.getXr()) );
           
            }else if(this.getYr() - m.getYr() >= 0 && this.getXr() - m.getXr() > 0){
             
                return Math.atan((this.getYr() - m.getYr()) / (this.getXr() - m.getXr()) );
           
            }else if(this.getYr() - m.getYr() < 0 && this.getXr() - m.getXr() >= 0){
             
                return  Math.PI + Math.atan((this.getYr() - m.getYr()) / (this.getXr() - m.getXr()) );
            //ok
            }else //if(this.getYr() - m.getYr() <= 0 && this.getXr() - m.getXr() < 0){
               
                return Math.atan((this.getYr() - m.getYr()) / (this.getXr() - m.getXr()) );
           
           
            }
                     
           
       
        public double getXr() {
            return getX()+ getRadius();
        }

        public double getYr() {
            return getY()+ getRadius();
        }
    I wouldn't be surprised if the errors are due to typos, I just fixed several in other part of the code. :p

    I think that I am getting close to the solution, the objects bounce correctly at some angles. My biggest burden is the inverted Y-Axis, which makes me make mistakes with the adjustment of the angles.


    In regards to the last part of your previous post, I just realized that I was talking nonsense. the distance is checked correctly.
     
  9. Aug 2, 2015 #8

    haruspex

    User Avatar
    Science Advisor
    Homework Helper
    Gold Member
    2016 Award

    For the arctan logic, you don't need so many cases.
    I would start by defining a constant as the max value you allow as the result of a division, MaxReal, say.
    Then your test for potential overflow is abs(Vx)*MaxReal < abs(Vy). When that returns true, angle=pi/2, else angle = atan (Vy/Vx).
    Either way, you then adjust for negative Vx, if ((Vx)<0) angle += pi. That should be it.
    Likewise for phi.

    I see you have a problem with coliding objects getting stuck. I assume this is because as they try to separate after a collision they appear to collide again.
    You could solve that by checking whether their relative velocity along the line of centres is bringing them closer or taking them further apart. With your existing method, seems to me you could have problems when there are multiple collisions in one time step.
     
  10. Aug 2, 2015 #9
    I managed to get it right with your input. I will now try to solve other problems related to it. The objects sometimes get stuck as you say, regardless, I am planning to have some animations that allow me to simulate some kind of 3D effect where if an object collides it can either go up or down or also get destroyed, etc. Still, I will try to fix it.
    Thanks a lot! :D
     
    Last edited: Aug 2, 2015
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: Two-Dimensional Collision With Two Moving Objects
Loading...