6
$\begingroup$

A ball is thrown towards a vertical wall. The ball is initially located a distance xf from the wall, a height y0 above the ground, and is released with initial velocity v0 at an angle theta to the horizontal. The ball undergoes an elastic collision with the wall; that is, the horizontal component of the velocity of the ball is reversed and the vertical component remains unchanged. Plot the motion of the ball for several different initial velocities (v0 and theta).

I'm not great at coding, but I have to learn this for Physics.

I kinda already did something like this without the wall. I just have to basically get it to bounce off a wall and hit the ground.

So I attempted to use the same thing as the last one, but need some help incorporating the wall into everything.

eqnsMotion[vi_, θ_] := Module[{forceEqns, boundaries, g = 9.8},
  forceEqns = {x''[t] == 0, y''[t] == -g};
  boundaries = {x[0] == 0, x'[0] == vi*Cos[θ], y[0] == 0, 
  y'[0] == vi*Sin[θ]};
  DSolve[Join[forceEqns, boundaries], {x[t], y[t]}, t][[1]]
  ]

So that is my eqn of motion, then I hav ea time of flight so I can solve for t.

tof[vi_, θ_] :=  Solve[Evaluate[y[t] /. eqnsMotion[vi, θ]] == 
0, t][[2]]

To plot it i used a ParametricPlot and I use the Show function.

trajectory[vi_, θ_] := ParametricPlot[Evaluate[{x[t], y[t]} 
/. eqnsMotion[vi, θ]], {t, 0,Evaluate[t /. tof[vi, θ]]}]

How would I go about putting a wall at some distance xf?

$\endgroup$

4 Answers 4

12
$\begingroup$

I like to do these things using kinematics equations.

enter image description here

(*version Nov 03, 2017*)
Manipulate[
 tick;

 If[state == "RUN" || state == "STEP",
  If[state == "RUN",
   tick = Not[tick]
   ];

  t += delT;

  If[direction == "right",
   xnow = xnow + v0 Cos[theta Degree] delT;
   If[xnow >= xf,
    direction = "left"
    ]
   ,
   xnow = xnow - v0 Cos[theta Degree] delT;
   If[xnow <= 0,
    direction = "right"
    ]
   ];

  ynow = ynow + vy  delT - 1/2 * g * (delT)^2;
  vy = vy - g delT;


  If[ynow <= 0,
   state = "STOP"
   ];

  If[showTrace, AppendTo[trace, {xnow, ynow}]];

  graph = Graphics[
    {
     {PointSize[.06], Red, Point[{xnow, ynow}]},
     {Line[{{xf, 0}, {xf, yrange}}]},
     {Line[{{0, 0}, {yrange, 0}}]},
     {Arrowheads[Medium], 
      Arrow[{{0, y0}, {.5 Cos[theta Degree], 
         y0 + .5 Sin[theta Degree]}}]},
     If[showTrace, {Dashed, Blue, Line[trace]}]
     },
    PlotRange -> {{-.1, xrange}, {-.1, yrange}}, Axes -> True, 
    ImageSize -> {300}, ImagePadding -> 20, GridLines -> Automatic, 
    GridLinesStyle -> LightGray
    ]
  ];

 Grid[{
   {"time ", "x", "y", "vx", "vy", "state", SpanFromLeft},
   {padIt[t, {3, 3}], padIt[xnow, {3, 3}], padIt[ynow, {3, 3}], 
    padIt[N@vx, {3, 3}], padIt[vy, {3, 3}], state, SpanFromLeft},
   {graph, SpanFromLeft}}, Frame -> All, Spacings -> {1, 1}]

 ,
 Grid[{
   {Button[
     Text@Style["run", 12], {reset[]; state = "RUN"; 
      tick = Not[tick]}, ImageSize -> {50, 40}],
    Button[Text@Style["step", 12], {state = "STEP"; tick = Not[tick]},
      ImageSize -> {50, 40}],
    Button[
     Text@Style["reset", 12], {state = "STEP"; reset[]; 
      tick = Not[tick]}, ImageSize -> {50, 40}]
    },
   {"Theta angle (degree)",
    Manipulator[Dynamic[theta, {theta = #; reset[]; state = "STEP";
        tick = Not[tick]} &],
     {0, 80, 1 }, ImageSize -> Tiny], Dynamic[theta]
    },
   {"v0 (m/s)",
    Manipulator[
     Dynamic[v0, {v0 = #; reset[]; state = "STEP"; 
        tick = Not[tick]} &],
     {0.1, 10, .1}, ImageSize -> Tiny], Dynamic[v0]
    },

   {"time step (sec)",
    Manipulator[
     Dynamic[delT, {delT = #; state = "STEP"; reset[]; 
        tick = Not[tick]} &],
     {0.001, .05, 0.001}, ImageSize -> Tiny], Dynamic[delT]
    },

   {"x range",
    Manipulator[
     Dynamic[xrange, {xrange = #; reset[]; state = "STEP"; 
        tick = Not[tick]} &],
     {1, 10, 0.1}, ImageSize -> Tiny], Dynamic[xrange]
    },

   {"y range",
    Manipulator[
     Dynamic[yrange, {yrange = #; reset[]; state = "STEP"; 
        tick = Not[tick]} &],
     {1, 10, 0.1}, ImageSize -> Tiny], Dynamic[yrange]
    },
   {"show trace ", Checkbox[Dynamic[showTrace, {showTrace = #} &]]}

   },
  Frame -> True, FrameStyle -> Gray]
 ,

 {{delT, 0.005}, None},
 {{showTrace, True}, None},
 {{trace, {}}, None},
 {{theta, 45}, None},
 {{t, 0}, None},
 {{g, 9.81}, None},
 {{xnow, 0}, None},
 {{ynow, 1}, None},
 {{xf, 2}, None},
 {{y0, 1}, None},
 {{v0, 9.8}, None},
 {{direction, "right"}, None},
 {{graph, 0}, None},
 {{state, "STEP"}, None},
 {{xrange, 2}, None},
 {{yrange, 3.5}, None},
 {{tick, False}, None},
 {{vy, Sin[45 Degree]}, None},
 TrackedSymbols :> {tick},

 Initialization :> (
   reset[] := {
     xnow = 0;
     ynow = y0;
     t = 0;
     vy = v0 Sin[theta Degree];
     trace = {};
     direction = "right"
     };

   padIt[v_, f_List] := 
    AccountingForm[Chop[v], f, NumberSigns -> {"", ""}, 
     NumberPadding -> {"0", "0"}, SignPadding -> True]
   )
 ]
$\endgroup$
2
  • 4
    $\begingroup$ This is very nice! $\endgroup$ Nov 3, 2017 at 7:39
  • $\begingroup$ slick application $\endgroup$
    – MikeY
    Nov 3, 2017 at 18:52
5
$\begingroup$

Set and initial condition, x[0] == xf, and make sure the ball is headed toward the wall (assume wall is to the left)

 eqnsMotion[vi_, θ_,XF_] := Module[{forceEqns, boundaries, g = 9.8},
  forceEqns = {x''[t] == 0, y''[t] == -g};
  boundaries = {x[0] == XF, x'[0] == -vi*Cos[θ], y[0] == 0, 
  y'[0] == vi*Sin[θ]};
  DSolve[Join[forceEqns, boundaries], {x[t], y[t]}, t][[1]]
  ]

and put in an absolute value around the X value

  trajectory[vi_, θ_,XF_] := ParametricPlot[Evaluate[{Abs[x[t]], y[t]} 
 /. eqnsMotion[vi, θ,XF]], {t, 0,Evaluate[t /. tof[vi, θ]]}]

so

 trajectory[10,.2,3]

enter image description here

$\endgroup$
4
  • $\begingroup$ Awesome! I see what you did there, but what if I also want the ball to go to a wall that's to the right instead? I've been working on my code and I set it to have a yi, but it'll only work if it goes to the right. $\endgroup$ Nov 2, 2017 at 20:28
  • $\begingroup$ Do you want two walls, that it bounces between? If so, a bit more complicated. Or if the wall is not located at x = 0. $\endgroup$
    – MikeY
    Nov 2, 2017 at 20:47
  • $\begingroup$ Just one wall. I want the ball to start from x=0 and then hit a wall at some xf to the right and bounce off it. I was thinking of using a WhenEvent. How would that work or is there a better way than that? $\endgroup$ Nov 2, 2017 at 20:50
  • 2
    $\begingroup$ Since it is a single wall, and the ball perfectly reflects off of it, and you mainly want a plot of it, I'd just shift everything to the left distance XF, get the result as I did, then shift it back. No need to go all fancy with event tracking. KISS! $\endgroup$
    – MikeY
    Nov 2, 2017 at 20:52
4
$\begingroup$

I will show how to solve the problem with two walls that Nasser solved without solving any equations other than the one that OP has already solved.

Let me first restate OP's eqnsMotion with a slight change for convenience, and a function which determines at what time t the trajectory ends.

eqnsMotion[vi_, \[Theta]_] := Module[{forceEqns, boundaries, g = 9.8},
  forceEqns = {x''[t] == 0, y''[t] == -g};
  boundaries = {x[0] == 0, x'[0] == vi*Cos[\[Theta]], y[0] == 0, 
    y'[0] == vi*Sin[\[Theta]]};
  DSolveValue[Join[forceEqns, boundaries], {x[t], y[t]}, t]
  ]
groundCollision[{_, y_}] := t /. FindRoot[y, {t, 100}]

The problem this solves is the following: Given a projectile with velocity $v$ and angle with respect to the ground $\theta$, how does the projectile travel? We can plot it for an example:

trajectory = eqnsMotion[10, Pi/4];
tmax = groundCollision[trajectory];
ParametricPlot[trajectory, {t, 0, tmax}]

Trajectory.

Since the collision with the walls are elastic, the projectile will still follow this exact trajectory when we introduce walls. The only difference is that the segments of this trajectory will be divided up and reflected as appropriate, something we can achieve with simple quotient and modulus operations. We simply need to modify our result from eqnsMotion with this:

insertWall[{x_, y_}, wallx_] := If[
  OddQ[Quotient[x, wallx]],
  {wallx - Mod[x, wallx], y},
  {Mod[x, wallx], y}
  ]

If we place a wall at $x = 2$ and assume a wall at $x = 0$, we get the following:

wallx = 2;
ParametricPlot[
 insertWall[trajectory, wallx],
 {t, 0, tmax},
 Axes -> False,
 PlotStyle -> Dashed,
 Epilog -> {
   Line[{{0, 0}, {wallx, 0}}],
   InfiniteLine[{{0, 0}, {0, 1}}],
   InfiniteLine[{{wallx, 0}, {wallx, 1}}]
   }]

Trajectory when there are walls.

I'd like to point out here that this type of visualization is also related to the reduced zone scheme for the dispersion curve of free electrons in solid state physics. I made such a visualization in the following question:

$\endgroup$
3
$\begingroup$

with more than one wall, bouncing off the ground etc you are better to do this numerically and use WhenEvent for the bounce:

th = Pi/4
v = 5
forceEqns = {x''[t] == 0, y''[t] == -10};
boundaries = {x[0] == 0, x'[0] == v*Cos[th], y[0] == 0, 
   y'[0] == v*Sin[th]};
sol = {x[t], y[t]} /. NDSolve[{
      forceEqns, boundaries,
      WhenEvent[x[t] == 1/2, x'[t] -> -x'[t]],
      WhenEvent[y[t] == 0, y'[t] -> -y'[t]]}, {x[t], y[t]}, {t, 0, 
      1}][[1]];
ParametricPlot[sol, {t, 0, 1}]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.