Как стать автором
Обновить
131
13.1

Пользователь

Отправить сообщение

Когда ветеран исследования, Ноам Шазир, увидел ранний вариант работы, он
был удивлён, что его имя стоит первым, что говорит о том, что его вклад
был первостепенным.

А мне часто публикующиеся рассказывали, что настоящий автор либо на первом, либо на последнем месте (чаще всего). Потому что на первое место часто ставят всякое нахрен не нужное начальство, которое страшно хочет быть в публикации, но делать ничего не делало для исследования.

А может и не подавать. Да и вообще, странное решение для управления пищалкой брать PNP транзистор с вывернутым включением.

Я бы, кстати, на месте китайцев повторитель бы и поставил. И избавился от двух резисторов - экономия как-никак.

А это от логики работы P21 зависит. Если он на земле лежит, то писка не будет. Единственно, R44 для эмиттерного повторителя лишний.

Однако транзистор включён неправильно: перепутаны местами коллектор и эмиттер.

А не тип транзистора (NPN)? Тогда получится эмиттерный повторитель.

Обычно, все эти задачи решают микроконтроллеры устройств. У них и быстродействие не очень, да и памяти мало. Причём , решают непрерывно. И ещё фильтр довольно быстро перестроится, если поменяется расположение магнитных объектов вокруг магнитометра (на судне, например, сгрузили грузовой контейнер), а вот МНК так не сможет автоматически. Нужно сбрасывать накопленный массив данных и запускать калибровку заново.

Кстати, для апостериорной обработки можно решить ту же задачу с помощью МНК. Единственно, точек будет много и решать такую систему довольно затратно. Фильтр же позволяет делать корректировку прямо во время движения объекта.

У меня пришла перемаркировання MPU6500. Регистр WHOAMI выдаёт 0x70. Магнитометра там, ожидаемо, нет.

вроде этих https://roboshop.spb.ru/sensors/datchiki-navigacii/mpu9250-module

Так. Погодите-ка. Я только что такую плату на 9250 вчера получил. И вчера попытался впервые её опросить по SPI. Может, я неправильно опрашиваю магнитометр, но только данных я нифига не получил (принимаются застывшие биты). Я вообще думал, сама 9250 внутри с магнитометром. И он там этот самый аналог AK8963. И я как-то не догадывался, что в 9250 внутри меняют схемотехнику. Отвратительно.

А она может и не решиться. Шумы измерений не позволят.

Есть. Только это будет просто экспериментальная программа. Буквально на попробовать. Я такое даже на свой гитхаб класть не хочу. Но все операции с матрицами там есть.

Вот она.

Магнитомягкие материалы постоянно добавляют свой вектор магнитного поля, совпадающий с полем Земли+поле магнитотвёрдого материала около них+поле другого магнитомягкого материала около них, причём, эти магнитомягкие материалы находятся где-то сбоку от магнитометра (но вращаются вместе с ним), и поэтому результирующий вектор, действующий на магнитометр получается как сумма всех этих векторов. Вот если бы магнитомягкие материалы находились бы внутри магнитометра, тогда никакого искажения не было бы.

Наверное, вы имели в виду двумерный вектор, а не одномерный? Магнитометр в приборе вовсе не всегда будет находиться в плоскости горизонта, поэтому используются все три координаты.

Анизотропия влиять на направление будет. Если бы она не влияла, матрица W осталась бы единичной.

Ступил. :) Исправлю.

А RFID-метку вживить/на ошейник не было бы проще?

Нет, всё равно не работает правильно.
Причина в матрице H у китайцев.

Что-то тут не то. Потому что на следующем шаге надо от измеренных показаний отнимать вот этот вектор D и получать ошибку. И эта ошибка будет неверная. Всё из-за удвоения произведения W*B. Вся проблема в матрице H - она должна отражать взаимосвязь датчиков, но получилось так, что в неё входят сами текущие показания датчиков.

Придумал сделать так. Wk/k-1 сделать единичной в матрице Hk. Это даст Bпоказаний=Bистинное*I+Bистинное*Wk/k-1+Vk (здесь Wk/k-1 - элементы матрицы Xk/k-1!). То есть, показания есть истинные показания+смещённые от истинных за счёт магнитомягких материалов+смещения нуля. Тогда фильтр подбирает эти самые смещения (Wk/k-1 и Vk). Тогда чтобы получить истинный результат из показаний прибора, нужно Bистинное=(Wk+I)^-1x(Bпоказаний-Vk). Вроде бы работает (пока без имитации магнитомягких материалов). До этого вообще не сходился никак. Завтра добавлю имитацию магнитомягких материалов и проверю точнее.

Основной фрагмент кода
#ifndef C_FILTER_KALMAN_SOFT_AND_HARD_IRON_H
#define C_FILTER_KALMAN_SOFT_AND_HARD_IRON_H

//****************************************************************************************************
//Класс фильтра Калмана для магнитомягких и магнитотвёрдых материалов
//****************************************************************************************************

//****************************************************************************************************
//подключаемые библиотеки
//****************************************************************************************************

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include "cvector.h"
#include "cmatrix.h"

//****************************************************************************************************
//макроопределения
//****************************************************************************************************

//****************************************************************************************************
//константы
//****************************************************************************************************

//****************************************************************************************************
//предварительные объявления
//****************************************************************************************************


//****************************************************************************************************
//прототипы функций
//****************************************************************************************************


//****************************************************************************************************
//Класс фильтра Калмана для магнитомягких и магнитотвёрдых материалов
//****************************************************************************************************

class CFilterKalman_SoftAndHardIron
{
 public:
  //-перечисления---------------------------------------------------------------------------------------
  //-структуры------------------------------------------------------------------------------------------
  //элементы фильтра Калмана
  struct SKalman
  {
   CMatrix Xk_1;//вектор состояния
   CMatrix Pk_1;//матрица ковариации
   CMatrix Rk_1;//матрица ориентации

   CMatrix Xk;//новый вектор состояния
   CMatrix Pk;//новая матрица ковариации
   CMatrix Rk;//новая матрица ориентации

   CMatrix F;//матрица динамики
   CMatrix dR;//матрица изменения ориентации
   CMatrix H;//матрица
   CMatrix Y;//матрица
   CMatrix X;//матрица
   CMatrix P;//матрица
   CMatrix M;//матрица
   CMatrix S;//матрица
   CMatrix K;//матрица коэффициента усиления фильтра Калмана
   CMatrix Identity;//единичная матрица

   bool FirstStep;//первый ли шаг
  };

  //список параметров для фильтра Калмана
  struct SKalmanParam
  {
   //интервал времени
   float dT;
   //углы ориентации в пространстве
   float Roll;
   float Pitch;
   float Yaw;
   //магнитометры
   float Mx;
   float My;
   float Mz;
  };
  //показания магнитометров
  struct SMeasure
  {
   float Mx;
   float My;
   float Mz;
  };

  //-константы------------------------------------------------------------------------------------------
 private:
  //-переменные-----------------------------------------------------------------------------------------
  SKalman sKalman;//параметры фильтра Калмана
 public:
  //-конструктор----------------------------------------------------------------------------------------
  CFilterKalman_SoftAndHardIron(void);
  //-деструктор-----------------------------------------------------------------------------------------
  ~CFilterKalman_SoftAndHardIron();
 public:
  //-открытые функции-----------------------------------------------------------------------------------
  void Init(void);//инициализация фильтра
  void Procesing(const SKalmanParam &sKalmanParam);//обработка фильтра
  CMatrix GetState(void);//получить результаты работы фильтра
  SMeasure Correction(const SMeasure sMeasure_Input);//скоррекировать показания магнитометров
 private:
  //-закрытые функции-----------------------------------------------------------------------------------
};

#endif




//****************************************************************************************************
//подключаемые библиотеки
//****************************************************************************************************
#include "cfilterkalman_softandhardiron.h"

//****************************************************************************************************
//глобальные переменные
//****************************************************************************************************

//****************************************************************************************************
//константы
//****************************************************************************************************

static const double M_PI_VALUE=3.141592653589793238462643383279;

//****************************************************************************************************
//макроопределения
//****************************************************************************************************

//****************************************************************************************************
//конструктор и деструктор
//****************************************************************************************************

//----------------------------------------------------------------------------------------------------
//конструктор
//----------------------------------------------------------------------------------------------------
CFilterKalman_SoftAndHardIron::CFilterKalman_SoftAndHardIron(void)
{
}
//----------------------------------------------------------------------------------------------------
//деструктор
//----------------------------------------------------------------------------------------------------
CFilterKalman_SoftAndHardIron::~CFilterKalman_SoftAndHardIron()
{
}
//****************************************************************************************************
//закрытые функции
//****************************************************************************************************

//----------------------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------------------


//****************************************************************************************************
//открытые функции
//****************************************************************************************************

//----------------------------------------------------------------------------------------------------
//инициализация фильтра
//----------------------------------------------------------------------------------------------------
void CFilterKalman_SoftAndHardIron::Init(void)
{
 sKalman.Xk_1=CMatrix(12,1);

 sKalman.Pk_1=CMatrix(12,12);
 sKalman.Pk_1.Unitary();

 sKalman.Rk_1=CMatrix(3,3);
 sKalman.Rk_1.Unitary();


 sKalman.Xk=CMatrix(12,1);

 sKalman.Pk=CMatrix(12,12);
 sKalman.Pk.Unitary();

 sKalman.Rk=CMatrix(3,3);
 sKalman.Rk.Unitary();


 sKalman.P=CMatrix(12,12);
 sKalman.X=CMatrix(12,1);
 sKalman.F=CMatrix(12,12);
 sKalman.dR=CMatrix(3,3);
 sKalman.H=CMatrix(3,12);
 sKalman.Y=CMatrix(3,1);
 sKalman.M=CMatrix(3,1);
 sKalman.S=CMatrix(3,3);
 sKalman.Identity=CMatrix(12,12);
 sKalman.Identity.Unitary();

 sKalman.FirstStep=true;
}

//----------------------------------------------------------------------------------------------------
//обработка фильтра
//----------------------------------------------------------------------------------------------------
void CFilterKalman_SoftAndHardIron::Procesing(const SKalmanParam &sKalmanParam)
{
 //применяем фильтр Калмана

 //матрица вращения из статьи "МЭМС акселерометры, магнитометры и углы ориентации"

 float cr=cos(M_PI_VALUE/180.0*sKalmanParam.Roll);
 float sr=sin(M_PI_VALUE/180.0*sKalmanParam.Roll);

 float cp=cos(M_PI_VALUE/180.0*sKalmanParam.Pitch);
 float sp=sin(M_PI_VALUE/180.0*sKalmanParam.Pitch);

 float cy=cos(M_PI_VALUE/180.0*sKalmanParam.Yaw);
 float sy=sin(M_PI_VALUE/180.0*sKalmanParam.Yaw);

 sKalman.Rk.SetElement(0,0,cy*cp);
 sKalman.Rk.SetElement(0,1,-cr*sy+sr*cy*sp);
 sKalman.Rk.SetElement(0,2,sr*sy+cr*cy*sp);

 sKalman.Rk.SetElement(1,0,sy*cp);
 sKalman.Rk.SetElement(1,1,cr*cy+sr*sy*sp);
 sKalman.Rk.SetElement(1,2,-sr*cy+cr*sy*sp);

 sKalman.Rk.SetElement(2,0,-sp);
 sKalman.Rk.SetElement(2,1,sr*cp);
 sKalman.Rk.SetElement(2,2,cr*cp);

 if (sKalman.FirstStep==true)
 {
  sKalman.FirstStep=false;
  double xk_1[12]={sKalmanParam.Mx,sKalmanParam.My,sKalmanParam.Mz,1,1,1,0,0,0,0,0,0};//показания, матрица вращения магнитомягких материалов и смещения показаний
  sKalman.Xk_1.SetElement(xk_1,12);
  sKalman.Rk_1=sKalman.Rk;
  sKalman.Pk_1.Unitary();
 }

 sKalman.dR=sKalman.Rk.Transpose()*sKalman.Rk_1;

 //матрица динамики
 sKalman.F.SetElement(0,0,sKalman.dR.GetElement(0,0));
 sKalman.F.SetElement(0,1,sKalman.dR.GetElement(0,1));
 sKalman.F.SetElement(0,2,sKalman.dR.GetElement(0,2));

 sKalman.F.SetElement(1,0,sKalman.dR.GetElement(1,0));
 sKalman.F.SetElement(1,1,sKalman.dR.GetElement(1,1));
 sKalman.F.SetElement(1,2,sKalman.dR.GetElement(1,2));

 sKalman.F.SetElement(2,0,sKalman.dR.GetElement(2,0));
 sKalman.F.SetElement(2,1,sKalman.dR.GetElement(2,1));
 sKalman.F.SetElement(2,2,sKalman.dR.GetElement(2,2));


 sKalman.F.SetElement(0,3,0);
 sKalman.F.SetElement(0,4,0);
 sKalman.F.SetElement(0,5,0);
 sKalman.F.SetElement(0,6,0);
 sKalman.F.SetElement(0,7,0);
 sKalman.F.SetElement(0,8,0);
 sKalman.F.SetElement(0,9,0);
 sKalman.F.SetElement(0,10,0);
 sKalman.F.SetElement(0,11,0);

 sKalman.F.SetElement(1,3,0);
 sKalman.F.SetElement(1,4,0);
 sKalman.F.SetElement(1,5,0);
 sKalman.F.SetElement(1,6,0);
 sKalman.F.SetElement(1,7,0);
 sKalman.F.SetElement(1,8,0);
 sKalman.F.SetElement(1,9,0);
 sKalman.F.SetElement(1,10,0);
 sKalman.F.SetElement(1,11,0);

 sKalman.F.SetElement(2,3,0);
 sKalman.F.SetElement(2,4,0);
 sKalman.F.SetElement(2,5,0);
 sKalman.F.SetElement(2,6,0);
 sKalman.F.SetElement(2,7,0);
 sKalman.F.SetElement(2,8,0);
 sKalman.F.SetElement(2,9,0);
 sKalman.F.SetElement(2,10,0);
 sKalman.F.SetElement(2,11,0);


 sKalman.F.SetElement(3,0,0);
 sKalman.F.SetElement(3,1,0);
 sKalman.F.SetElement(3,2,0);

 sKalman.F.SetElement(4,0,0);
 sKalman.F.SetElement(4,1,0);
 sKalman.F.SetElement(4,2,0);

 sKalman.F.SetElement(5,0,0);
 sKalman.F.SetElement(5,1,0);
 sKalman.F.SetElement(5,2,0);

 sKalman.F.SetElement(6,0,0);
 sKalman.F.SetElement(6,1,0);
 sKalman.F.SetElement(6,2,0);

 sKalman.F.SetElement(7,0,0);
 sKalman.F.SetElement(7,1,0);
 sKalman.F.SetElement(7,2,0);

 sKalman.F.SetElement(8,0,0);
 sKalman.F.SetElement(8,1,0);
 sKalman.F.SetElement(8,2,0);

 sKalman.F.SetElement(9,0,0);
 sKalman.F.SetElement(9,1,0);
 sKalman.F.SetElement(9,2,0);

 sKalman.F.SetElement(10,0,0);
 sKalman.F.SetElement(10,1,0);
 sKalman.F.SetElement(10,2,0);

 sKalman.F.SetElement(11,0,0);
 sKalman.F.SetElement(11,1,0);
 sKalman.F.SetElement(11,2,0);



 sKalman.F.SetElement(3,3,1);
 sKalman.F.SetElement(3,4,0);
 sKalman.F.SetElement(3,5,0);
 sKalman.F.SetElement(3,6,0);
 sKalman.F.SetElement(3,7,0);
 sKalman.F.SetElement(3,8,0);
 sKalman.F.SetElement(3,9,0);
 sKalman.F.SetElement(3,10,0);
 sKalman.F.SetElement(3,11,0);

 sKalman.F.SetElement(4,3,0);
 sKalman.F.SetElement(4,4,1);
 sKalman.F.SetElement(4,5,0);
 sKalman.F.SetElement(4,6,0);
 sKalman.F.SetElement(4,7,0);
 sKalman.F.SetElement(4,8,0);
 sKalman.F.SetElement(4,9,0);
 sKalman.F.SetElement(4,10,0);
 sKalman.F.SetElement(4,11,0);

 sKalman.F.SetElement(5,3,0);
 sKalman.F.SetElement(5,4,0);
 sKalman.F.SetElement(5,5,1);
 sKalman.F.SetElement(5,6,0);
 sKalman.F.SetElement(5,7,0);
 sKalman.F.SetElement(5,8,0);
 sKalman.F.SetElement(5,9,0);
 sKalman.F.SetElement(5,10,0);
 sKalman.F.SetElement(5,11,0);

 sKalman.F.SetElement(6,3,0);
 sKalman.F.SetElement(6,4,0);
 sKalman.F.SetElement(6,5,0);
 sKalman.F.SetElement(6,6,1);
 sKalman.F.SetElement(6,7,0);
 sKalman.F.SetElement(6,8,0);
 sKalman.F.SetElement(6,9,0);
 sKalman.F.SetElement(6,10,0);
 sKalman.F.SetElement(6,11,0);

 sKalman.F.SetElement(7,3,0);
 sKalman.F.SetElement(7,4,0);
 sKalman.F.SetElement(7,5,0);
 sKalman.F.SetElement(7,6,0);
 sKalman.F.SetElement(7,7,1);
 sKalman.F.SetElement(7,8,0);
 sKalman.F.SetElement(7,9,0);
 sKalman.F.SetElement(7,10,0);
 sKalman.F.SetElement(7,11,0);

 sKalman.F.SetElement(8,3,0);
 sKalman.F.SetElement(8,4,0);
 sKalman.F.SetElement(8,5,0);
 sKalman.F.SetElement(8,6,0);
 sKalman.F.SetElement(8,7,0);
 sKalman.F.SetElement(8,8,1);
 sKalman.F.SetElement(8,9,0);
 sKalman.F.SetElement(8,10,0);
 sKalman.F.SetElement(8,11,0);

 sKalman.F.SetElement(9,3,0);
 sKalman.F.SetElement(9,4,0);
 sKalman.F.SetElement(9,5,0);
 sKalman.F.SetElement(9,6,0);
 sKalman.F.SetElement(9,7,0);
 sKalman.F.SetElement(9,8,0);
 sKalman.F.SetElement(9,9,1);
 sKalman.F.SetElement(9,10,0);
 sKalman.F.SetElement(9,11,0);

 sKalman.F.SetElement(10,3,0);
 sKalman.F.SetElement(10,4,0);
 sKalman.F.SetElement(10,5,0);
 sKalman.F.SetElement(10,6,0);
 sKalman.F.SetElement(10,7,0);
 sKalman.F.SetElement(10,8,0);
 sKalman.F.SetElement(10,9,0);
 sKalman.F.SetElement(10,10,1);
 sKalman.F.SetElement(10,11,0);

 sKalman.F.SetElement(11,3,0);
 sKalman.F.SetElement(11,4,0);
 sKalman.F.SetElement(11,5,0);
 sKalman.F.SetElement(11,6,0);
 sKalman.F.SetElement(11,7,0);
 sKalman.F.SetElement(11,8,0);
 sKalman.F.SetElement(11,9,0);
 sKalman.F.SetElement(11,10,0);
 sKalman.F.SetElement(11,11,1);

 //этап предсказания
 sKalman.X=sKalman.F*sKalman.Xk_1;//предсказанное значение
 sKalman.P=(sKalman.F*sKalman.Pk_1)*(sKalman.F.Transpose());//+Q (пока не понимаю, где взять ковариацию внешнего воздействия)

 //этап корректировки
 double mx=sKalman.X.GetElement(0,0);
 double my=sKalman.X.GetElement(1,0);
 double mz=sKalman.X.GetElement(2,0);

 double w11=1;//sKalman.X.GetElement(3,0);
 double w22=1;//sKalman.X.GetElement(4,0);
 double w33=1;//sKalman.X.GetElement(5,0);
 double w12=0;//sKalman.X.GetElement(6,0);
 double w13=0;//sKalman.X.GetElement(7,0);
 double w23=0;//sKalman.X.GetElement(8,0);

 double h_item[12*3]={w11,w12,w13,   mx,0,0, my,mz,0,  1,0,0,
                      w12,w22,w23,   0,my,0, mx,0,mz,  0,1,0,
                      w13,w23,w33,   0,0,mz, 0,mx,my,  0,0,1};

 sKalman.H.SetElement(h_item,12*3);

 sKalman.M.SetElement(0,0,sKalmanParam.Mx);
 sKalman.M.SetElement(1,0,sKalmanParam.My);
 sKalman.M.SetElement(2,0,sKalmanParam.Mz);

 sKalman.Y=sKalman.M-sKalman.H*sKalman.X;

 sKalman.S=(sKalman.H*sKalman.P)*(sKalman.H.Transpose())+sKalman.Rk;

 sKalman.K=(sKalman.P*sKalman.H.Transpose())*(sKalman.S.GetInversion());

 sKalman.Xk=sKalman.X+sKalman.K*sKalman.Y;
 sKalman.Pk=(sKalman.Identity-sKalman.K*sKalman.H)*sKalman.P;

 sKalman.Xk_1=sKalman.Xk;
 sKalman.Pk_1=sKalman.Pk;
 sKalman.Rk_1=sKalman.Rk;

 //в коэффициентах Xk получаются смещения и элементы матрицы вращения

}
//----------------------------------------------------------------------------------------------------
//получить результаты работы фильтра
//----------------------------------------------------------------------------------------------------
CMatrix CFilterKalman_SoftAndHardIron::GetState(void)
{
 return(sKalman.Xk);
}

//----------------------------------------------------------------------------------------------------
//скоррекировать показания магнитометров
//----------------------------------------------------------------------------------------------------
CFilterKalman_SoftAndHardIron::SMeasure CFilterKalman_SoftAndHardIron::Correction(const SMeasure sMeasure_Input)
{
 double mx=sMeasure_Input.Mx;
 double my=sMeasure_Input.My;
 double mz=sMeasure_Input.Mz;
 //матрица влияния магнитомягких материалов
 double w11=sKalman.Xk.GetElement(3,0)+1;//прибавляем единичную матрицу, чтобы учесть сами показания
 double w22=sKalman.Xk.GetElement(4,0)+1;//прибавляем единичную матрицу, чтобы учесть сами показания
 double w33=sKalman.Xk.GetElement(5,0)+1;//прибавляем единичную матрицу, чтобы учесть сами показания
 double w12=sKalman.Xk.GetElement(6,0);
 double w13=sKalman.Xk.GetElement(7,0);
 double w23=sKalman.Xk.GetElement(8,0);
 //смещения нуля
 double bx=sKalman.Xk.GetElement(9,0);
 double by=sKalman.Xk.GetElement(10,0);
 double bz=sKalman.Xk.GetElement(11,0);

 CMatrix w(3,3);
 double w_item[3*3]={w11,w12,w13,
                     w12,w22,w23,
                     w13,w23,w33};
 w.SetElement(w_item,3*3);
 //матрица влияния магнитомягких материалов (обратная)
 CMatrix w_inv=w.GetInversion();

 CMatrix x(3,1);

 x.SetElement(0,0,mx-bx);
 x.SetElement(1,0,my-by);
 x.SetElement(2,0,mz-bz);

 CMatrix y(3,1);
 y=w_inv*x;

 SMeasure sMeasure;
 sMeasure.Mx=y.GetElement(0,0);
 sMeasure.My=y.GetElement(1,0);
 sMeasure.Mz=y.GetElement(2,0);

 return(sMeasure);
}

Пробую сделать фильтр с компенсацией магнитомягких материалов.

Вот тут есть статья: https://iopscience.iop.org/article/10.1088/1742-6596/1627/1/012028/pdf

В чём проблема? Вот тут есть вектор состояния Xk. В него входят показания магнитометров (Bc,kT), шесть элементов матрицы компенсации магнитомягких материалов (она симметричная) Wk и вектор смещений показаний магнитометров Vk.

Здесь получается прогнозный вектор состояния Xk/k-1. И всё бы ничего, но вот взаимосвязь Xk/k-1 с показаниями реального магнитометра осуществляется через матрицу Hk.

А она делается так:

л
л

И вот тут непонятно. Wk/k-1 - это элементы матрицы Xk/k-1? Но тогда получается, что H*Xk/k-1 - показания реального магнитометра - получается после раскрытия выражения как Wk/k-1xBc,kT+Wk/k-1*Bc,kT+Vk !!! То есть, тут по сути-то 2*Wk/k-1xBc,kT-V. И фильтр нихрена не сходится. И что это за физическая компенсация магнитомягкого материала такая? Где-то ошибка в матрице Hk у меня. Но где? Что я неверно сделал?

Отвечу сам себе. Матрицу Q выбросил. А матрицу R взял отсюда. https://habr.com/ru/articles/491476/

Я-то статью читал. Только вот фрагмента

Уже из этого ограничения вытекают проблемы. Кажется что 1/60 секунды - это довольно маленькое время (17 миллисекунд, если быть точным), однако в мире физики может случиться многое. Например, пуля, летящая сквозь тонкую стенку. Один кадр она с одной стороны стенки, а следующий кадр уже с другой. С точки зрения дискретной физики между ними не было контакта и пуля летит дальше.

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

я там не припомню. Стало быть, автор добавил апостериорно после моего вопроса.

Теперь, когда тела заняли свои новые позиции, нужно проверить не столкнулись ли они.

А как быть, если объект, например, пуля. И за 1/60 на позициях пули ни до, ни после интервала времени столкновения как бы и нет. Но в промежутке-то оно было - там стена стоит.

1
23 ...

Информация

В рейтинге
426-й
Откуда
Санкт-Петербург и область, Россия
Зарегистрирован
Активность