2015-01-25 4 views
-5

У меня есть код, который я создал для моделирования свободного падения объекта в вакууме. Когда timestep установлен на 1000 мс, он отлично работает без проблем. когда я устанавливаю timestep ниже 1000 мс, он отклоняется от реальных значений, падающих намного быстрее, чем обычно. Это занимает около 14 секунд, чтобы упасть на 1000 метров при 1000 мс, что является правильным значением. При времени 100 мс это занимает всего 5 секунд. при 10 мс это займет всего 2,2 секунды.Почему этот простой код freefall не работает

Может кто-нибудь, пожалуйста, скажите мне, что я делаю неправильно? Я думал, что я установил расчет timestep, чтобы иметь возможность обрабатывать более мелкие шаги.

Спасибо

 Body testbody = new Body(); 
     testbody.pos = new Vector(0, 1000); 
     testbody.velocity = new Vector(0, 0); 
     Bodytrack(testbody); 

     static void Bodytrack(Body body) 
     { 
      watch.Start(); 
      int timestep = 1000; 
      while (body.pos.Y > 0) 
      { 
       body.pos = body.pos + (body.velocity * (timestep/1000.0)); 
       if (body.pos.Y <= 0) { break; } 
       Thread.Sleep(timestep); 
       CalculateAcceleration(body); 
       Console.Clear(); 
       Console.WriteLine(body.velocity.Y); 
       Console.WriteLine(body.pos.Y); 
       Console.WriteLine(watch.Elapsed.TotalSeconds); 
      } 
      watch.Stop(); 
     } 



     public static void CalculateAcceleration(Body body) 
     { 
      body.acceleration = new Vector(0, -9.80665); 
      body.velocity = Vector.Add(body.acceleration, body.velocity); 
     } 
+3

Ни в коем случае вы не используете 'timestep' для вычисления новой скорости .... – SJuan76

+3

корпус.ускорение в метрах в секунду в секунду, но вы не используете временной шаг, чтобы повлиять на него. –

+0

И дополнительно к комментариям выше: когда вы его правильно реализуете с меньшими шагами, он будет падать быстрее, и это ожидается. – zerkms

ответ

2

Эта линия ваша проблема:

body.acceleration = new Vector(0, -9.80665); 

Каждый раз через петлю, вы установите ускорение -9.8 (что ускорение для 1000ms) вместо ускорение в течение прошедшего времени.

Необходимо учитывать количество времени, которое прошло. Если 500 мс прошло, то ускорение должно быть только -980665/2.

Вы должны изменить способ это:

public static void CalculateAcceleration(Body body, int timestep) 
{ 
    body.acceleration = new Vector(0, -9.80665 * (timestep/1000)); 
    body.velocity = Vector.Add(body.acceleration, body.velocity); 
} 
+0

Я вижу, должен ли я сохранить timestep/1000 в части, которая устанавливает body.pos? Или я должен удалить его оттуда? – Alex

+0

Должен ли 'timestep/1000' быть' timestep/1000.0' для предотвращения целочисленного деления? –

+0

@MatthewStrawbridge да, это так (но если круглые скобки, куда они ушли, это было бы не так, потому что «-980665 * timestep» произошло бы первым и сделало бы его двойным) –

0

Если я помню математику правильно (и управлять ими, чтобы записать его с помощью уценки) ...

Идея заключается в том, что горизонтальное положение на что-то не влияет, гравитация влияет только на вертикальное положение. Поэтому мы можем легко вычислить, где объект горизонтально (при отсутствии столкновений).

X(t) = Vx * t.

Это означает, что когда вы выбрасываете что-то горизонтально со скоростью 10 метров в секунду, он проедет 100 метров через 10 секунд.

Формула для горизонтального позиционирования немного более продвинута. Он содержит две части, первая часть - движение без силы тяжести, а вторая часть выступает в качестве противодействующей силы под действием силы тяжести.

Y(t) = Vy * t - (g * t^2)/2 где g - сила тяжести (обычно 9,82).

Vy * t - постоянное движение вверх, если сила тяжести не снизила бы его. (g * t^2)/2 - это увеличение тяготения.

Объект, который упал не будет иметь начальное усилие в любом направлении, таким образом, {Vx = 0, Vy = 0}, и вы можете легко получить текущую позицию этого, в любое время, используя pos(t) = -(g * t^2)/2. (Мы также знаем, что он упадет прямо вниз, поэтому вам не нужно вычислять горизонтальное позиционирование.) Вы уже знаете скорость его на speed(t) = g * t.

Вы не можете доверять кусочки времени, как это делает ваш код. Во-первых, Thread.Sleep не является точным. Лучше рассчитать время, прошедшее с момента последнего обновления, и использовать его в ваших расчетах.

+0

Формула такая же для горизонтальной и вертикальной, что и 'P (t) = P0 + V0 * t + (a * t^2)/2', где' a = -g' для вертикали и 'a = 0' для горизонтальной. –

+0

Я считал это, но если объект меняет направление или я реализую drag, этот метод больше не будет работать. – Alex

Смежные вопросы