Espruino:Примеры/Симуляция физики воды с помощью серводвигателей
Симуляция физики воды с помощью серводвигателей[1]
Это очень простая симуляция метода конечных элементов. Анализ с помощью метода конечных элементов применяется во многих областях – например, чтобы рассчитать воздушный поток вокруг корпуса болида «Формулы-1» или то, в состоянии ли мост себя поддерживать.
Основной принцип этого метода очень прост – возьмите что-либо и поделите на некоторое количество частей, а затем рассчитайте, как будет функционировать каждая из этих частей.
В этой статье мы создадим (очень примерную) симуляцию воды, текущей по тонкому каналу. Мы поделим воду на несколько вертикальных столбцов, каждый из которых будет наделён некоторой «массой», а также будет стараться коснуться других столбцов, находящихся слева и справа. Вот и всё. Это очень примитивная симуляция, но с её помощью можно создать вполне реалистичный эффект водной ряби (который, к слову, используется во многих компьютерных играх).
Нам понадобятся
- Плата Espruino, подключенная к серводвигателям
- Шесть серводвигателей, расположенных рядом друг с другом
Подсоединение
Просто подключите шесть серводвигателей к контактам B13, B14, B15, C4, C5 и C6. Более подробно о подключении серводвигателей к плате читайте в этой статье.
Код
Просто скопируйте код ниже в правую часть Web IDE, а затем кликните на кнопку загрузки кода.
// Оставляем свободные места в начале и конце
// для стационарных точек, которым не нужны серводвигатели:
var servos = [undefined,B13,B14,B15,C4,C5,C6,undefined];
// Стартовая позиция для каждой точки:
var pos = new Float32Array(servos.length);
// Скорость вращения каждой точки:
var velocity = new Float32Array(servos.length);
// Эта функция будет вызываться очень часто
// для выполнения каждого шага симуляции:
// of the simulation
function step() {
var i;
// Меняем позицию конечной точки при нажатии на кнопку:
pos[0] = digitalRead(BTN) ? 0.5 : 0;
// Для каждой точки...
for (i=1;i<servos.length-1;i++) {
// Ускорение зависит от дистанции между
// этой точкой и её соседями:
var accel = ((pos[i-1]+pos[i+1])/2) - pos[i];
// Рассчитываем новую скорость
// (с учётом трения и ускорения):
velocity[i] = velocity[i]*0.95 + accel*0.1;
}
// И, наконец, для каждой точки...
for (i=1;i<servos.length-1;i++) {
// ...рассчитываем новую позицию:
pos[i] += velocity[i];
// Отправляем новую позицию серводвигателю:
var p = 1.5+E.clip(pos[i],-0.5,0.5);
digitalPulse(servos[i],1,p);
}
}
// Вызываем это 50 раз в секунду:
setInterval(step, 20);
Теперь попробуйте зажать кнопку на плате и вообще поэкспериментируйте с проектом. Если всё сделано правильно, то движение серводвигателей будет напоминать рябь на поверхности пруда.
См.также
Внешние ссылки