#c #physics
#c #физика
Вопрос:
Я написал программу, которая будет имитировать бросок мяча с 50-метрового здания. Я добавил функцию обнаружения столкновений, изменив скорость в направлении y, когда мяч ударяется о землю (y < 0), сохранив горизонтальную скорость неизменной и умножив обе скорости на некоторое минимальное значение, чтобы мяч в конечном итоге остановился.
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
int main() {
FILE *fp;
FILE *fr;
float ax = 0, ay = 0, x = 0, y = 0, vx = 0, vy = 0;
float time = 0, deltaTime = .001;
float min = -.00000000001;
int numBounces = 0;
fr = fopen("input_data.txt", "rt");
fp = fopen( "output_data.txt", "w" );
if(fr == NULL){ printf("File not found");}
if(fp == NULL){ printf("File not found");}
fscanf(fr, "ax: %f ay: %f x: %f y: %f vx: %f vy: %fn", amp;ax, amp;ay, amp;x, amp;y, amp;vx, amp;vy);
while (vx > min amp;amp; vy > min) {
time = time deltaTime;
vx = vx ax*deltaTime;
vy = vy ay*deltaTime;
x = x vx*deltaTime (.5*ax*deltaTime*deltaTime);
y = y vy*deltaTime (.5*ay*deltaTime*deltaTime);
fprintf(fp, "%ft%ft%ft%ft%ft%ft%ftn", ax, ay, x, y, vx, vy, time);
//Collision occurs; implement collision response
if(y < 0) {
vx = vx ax*deltaTime*(.00001);
vy = -(vy ay*deltaTime*(.00001));
numBounces ;
fprintf(fp, "%ft%ft%ft%ft%ft%ft%ftn", ax, ay, x, y, vx, vy, time);
}
}
fclose(fp);
fclose(fr);
system ("PAUSE");
return 0;
}
Я не получаю правильные значения, необходимые для создания правильного графика данных.
Это может быть связано с тем, что мои условия в цикле while необходимо изменить, или что я неправильно реализовал реакцию на столкновение.
Вот также некоторые примеры данных:
ax: 0 ay: -9.8 x: 0 y: 50 vx: 8.66 vy: 5
Комментарии:
1. насколько ошибочен ваш код, генерирующий выходные данные?
2. Мой график данных не состоит ни из чего
3. что вы подразумеваете под «ничего»? можете ли вы опубликовать пример?
4. @gpu_drug — Я опубликовал изображение графика. Как вы можете видеть, нет эскиза графика
Ответ №1:
чтобы ничего не выводить, вы можете попробовать fflush(fp)
в конце каждого цикла. и, насколько я вижу в вашем коде, ваш объект получает немного больше скорости всякий раз, когда он попадает на землю, вам нужно изменить vy = -(vy ay*deltaTime*(.00001))
на vy = -(vy - ay*deltaTime*(.00001))
, чтобы исправить это. вы также можете создать лучшую реализацию для столкновения, если каждый раз вычисляете точное время столкновения y < 0
, а затем перемещаете объект вниз, меняете скорости и перемещаете объект вверх до конца цикла, чтобы столкновение было более реалистичным.
мы знаем, что deltaY = 1/2 * ay * t ^ 2 vy * t, поэтому мы можем вычислить t, используя формулу Фоллинга :
assuming py is the current height of object(it's distance to ground)
=> -py = 0.5 * ay* t * t vy * t
=> 0 = 0.5 * ay * t * t vy * t py
=> t = (-vy - sqrt(vy*vy - 2 * ay * py)) / (2 * ay)
и поскольку t должно быть положительным, и зная, что ay отрицательно, а py положительно, мы можем предположить, что правильный ответ
=> tc = (sqrt(vy*vy - 2 * ay * py) - vy) / 2 / ay
теперь у нас есть tc, который является временем столкновения. итак, мы должны отменить последние изменения положения и скорости, затем просто пошагать tc
секунды, а затем поменять местами vy и шаг deltaTime - tc
секунды, чтобы завершить этот кадр. итак, внутри условия if было бы похоже (у меня просто могут возникнуть некоторые проблемы с математикой, поэтому, если случайно вы не получили ожидаемых результатов, просто перепроверьте все уравнения):
if (y < 0) {
float tc = (sqrt(vy*vy - 2 *ay * y)) / 2 / ay;
x = x - vx*deltaTime - (.5*ax*deltaTime*deltaTime);
y = y - vy*deltaTime - (.5*ay*deltaTime*deltaTime);
vx = vx - ax * deltaTime;
vy = vy - ay * deltaTime;
vx = vx ax * tc;
vy = vy ay * tc;
x = x vx*tc (.5*ax*tc*tc);
y = y vy*tc (.5*ay*tc*tc);
vy = -(vy - ay*deltaTime*(.00001));
// you can also change above line and simply write
// vy = vy * -0.99;
// that will also create friction as you want it to be there
vx = vx ax * (deltaTime - tc);
vy = vy ay * (deltaTime - tc);
x = x vx* (deltaTime - tc) (.5*ax* (deltaTime - tc)* (deltaTime - tc));
y = y vy* (deltaTime - tc) (.5*ay* (deltaTime - tc)* (deltaTime - tc));
numBounces ;
fprintf(fp, "%ft%ft%ft%ft%ft%ft%ftn", ax, ay, x, y, vx, vy, time);
}
Комментарии:
1. Изменение vy на vy = -(vy — ay * deltaTime *(.00001)), похоже, не сработало. И если бы я хотел реализовать более реалистичное столкновение, как я мог бы найти точное время столкновения?
2. не запись выходных данных произошла из-за того, что ваша программа никогда по-настоящему не выходит из while, поэтому вызывается fclose neve, и выходные данные на самом деле не записываются в файл (он просто создает кэш того, что он должен записать из-за проблем с производительностью, просто используйте fflush, чтобы исправить это), и ваше изменение состояло в исправлении вашей формулы, сейчас я редактирую свой ответ, чтобы добавить все формулы, которые вам нужны для лучшего моделирования.
3. Не должна ли формула для вычисления tc быть deltaY = (1/2)ay t ^ 2 vy t вместо deltaY = ay t ^ 2 vy t
4. Я исправлял в каждом случае после подопечных это не только объяснение, в котором есть эта проблема, я исправлю это прямо сейчас.
5. @kachilous исправил ли fflush вашу проблему с тем, что вы ничего не записывали в файл?