如何在C+&#x2B中进行数值集成的基本示例
我认为大多数人都知道如何在计算机编程中执行数值派生(如限制 - > 0;阅读:“限制接近零”)。
//example code for derivation of position over time to obtain velocity
float currPosition, prevPosition, currTime, lastTime, velocity;
while (true)
{
prevPosition = currPosition;
currPosition = getNewPosition();
lastTime = currTime;
currTime = getTimestamp();
// Numerical derivation of position over time to obtain velocity
velocity = (currPosition - prevPosition)/(currTime - lastTime);
}
// since the while loop runs at the shortest period of time, we've already
// achieved limit --> 0;
这是大多数推导编程的基本构建块。
我该如何使用积分进行操作?我将用于循环并添加或什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在物理,映射,机器人技术,游戏,死刑和控制的代码中的数值派生和集成
请注意我在下面使用“估算“ VS”测量”一词。差异很重要。
例如:您可以在获得速度或速度(m/s)估计的时间上 der 位置测量(M),并且您可以集成相对于获得位置或位移(M)估计的速度或速度测量(M/s)。
例如,下表是正确的。例如,阅读第二行,例如:“如果您采用速度测量的导数,则会获得加速度估计,如果您进行它积分,您将获得一个位置估计。”
有关混蛋,快照或浮游,crack和流行音乐,请参阅:。
1。数值派生
记住,派生在XY图上获得该行的 slope ,
dy/dx
。常规表格为(y_new -y_old)/(x_new -x_old)
。为了从您获得重复位置测量的系统中获取速度估计(例如时间。您的 y轴是位置,而您的 x轴是时间,因此
dy/dx
是简单的(position_new-position_old) /(time_new -time_old)
。单位检查显示这可能是米/sec
,这确实是速度的单位。在代码中,这将是这样的,对于仅在1维中测量位置的系统:
2。数值集成
数值集成在曲线下获得 ,
dy*dx下的区域
,在XY图上。做到这一点的最佳方法之一称为梯形集成,在其中您将平均dy
读取并乘以dx
。看起来像这样:(y_old + y_new)/2 *(x_new -x_old)
。为了从您获得重复的速度测量的系统中获得位置估计(例如:您正在尝试估算旅行的距离,而仅读取汽车上的速度表) ,您必须随着时间的推移将速度测量值集成。您的 y轴是速度,而您的 X轴是时间,所以
(y___old + y_new)/2 *(x_new-x_new-x_old)
>仅是velocity_old + velocity_new)/2 *(time_new -time_old)
。单位检查显示这可能是米/sec * sec =米
,这确实是距离的单位。在代码中,看起来像这样。请注意,数值集成获得了一个小时间隔的距离。要获得对旅行的总距离的估计值,您必须总和所有的距离估计值。
另请参见: https://en.wikipedia.org/wiki/wiki/numerical_integration_integration 。
进一步:
高分辨率时间戳
要执行以上操作,您需要一种获得时间戳的好方法。我使用以下各种技术:
在C ++中,使用我的
uint64_t nanos()
。如果在C 或 C ++中使用Linux,请使用我的
uint64_t nanos()使用
clock_getTime()
在此处。更好的是,我将其包装到了一个不错的
timinglib
linux的库中,在我的回购在这里:这里代码>来自Timing.h的宏:
如果使用微控制器,则需要从计时器或计数器寄存器中读取一个递增的定期计数器,或者您已配置为以稳定的固定速率增量。例如:在arduino上:使用
micros()
获得具有4-US分辨率的微秒时间戳(默认情况下,可以更改)。在STM32或其他上,您需要配置自己的计时器/计数器。使用高数据样本速率
在样本循环中尽快采取数据样本是一个好主意,因为这样您就可以平均得出的许多样本要实现:
4^n
样品通过n
分辨率提高了样本分辨率。例如:请参阅:
https://1.bp.blogspot.com/srndpqdiemu/u3hbqfdowii/aaaaaaaaaaaaaa2q/1c45z1unsfc/s1600600以高样本速率采样很好。您可以对这些样品进行基本过滤。
如果您以高速率处理原始样品,则在高样本原始样本上进行数值推导最终将衍生出大量噪声,从而产生噪声衍生估计。这不是很好。最好对过滤样品进行推导:例如:100或1000个快速样本的平均值。但是,在高样本原始样品上进行数值集成,但是,因为正如Edgar Bonet所说的,“集成在整合时,您得到的样本越多,噪音平均越好。”这与我上面的笔记有关。
但是,仅使用过滤后的样品进行数值集成和数值推导就可以了。
使用合理的控制回路速率
控制回路速率不应太快。 样本率越高越好,因为您可以过滤它们以减少噪声。但是,控制回路速率 ,不是一定越好,因为控制回路速率有一个最佳位置。如果您的控制循环速率太慢,则系统的频率响应速度较慢,并且对环境的响应不会足够快,并且控制循环速率太快了,最终它只是对示例噪声的响应< /em>而不是在测量数据中进行实际更改。
因此,即使您有1 kHz的样本率,也不需要快速地进行过度采样和过滤数据,也不需要快速,因为读数的噪声在很小的时间间隔内的真实传感器太大。使用 10 Hz〜100 Hz 的任何地方使用控制环,也许最多可用于具有干净数据的简单系统。在某些情况下,您可以更快地走,但是 50 Hz 在控制系统中非常普遍。更复杂的系统和/或更无偿的传感器测量值通常慢> 必须是,控制回路必须为 1〜10 Hz 左右。例如,自动驾驶汽车非常复杂,经常在仅10 Hz的控制循环。
方法
为了完成上述,独立的测量和滤波循环和控制循环,您需要一种执行精确有效的环时时间的 和多任务。
如果需要在C或C ++ 中进行Linux中的重复循环,请使用上面的我的
timinglib
。我有一个sleep_until_us()
在linux中使用重复loop的演示。代码> 1 kHz至100 kHz 在这里。如果在微控制器上使用裸机(无操作系统)作为计算平台,请使用基于 timestamp的合作多任务执行您的控制循环和其他循环,例如测量环路,根据需要。在此处查看我的详细答案:如何进行高分辨率,基于时间戳,非块,单线读取的合作多任务。
完整的数字集成和多任务示例
我有一个数值集成的深入示例 和合作多任务在裸机系统上使用我的
create> create_task_timer()
我宏中观点。卡尔曼(Kalman)
进行了良好的测量过滤器,您可能需要一个Kalman过滤器,也许是“无知的Kalman过滤器”或UKF,因为显然它们是“无知的”,因为它们“不臭”。
另请参阅
Numerical derivation and integration in code for physics, mapping, robotics, gaming, dead-reckoning, and controls
Pay attention to where I use the words "estimate" vs "measurement" below. The difference is important.
Ex: you can derive position measurements (m) with respect to time to obtain speed or velocity (m/s) estimates, and you can integrate speed or velocity measurements (m/s) with respect to time to obtain position or displacement (m) estimates.
The following table is true, for example. Read the 2nd line, for instance, as: "If you take the derivative of a velocity measurement with respect to time, you get an acceleration estimate, and if you take its integral, you get a position estimate."
For jerk, snap or jounce, crackle, and pop, see: https://en.wikipedia.org/wiki/Fourth,_fifth,_and_sixth_derivatives_of_position.
1. numerical derivation
Remember, derivation obtains the slope of the line,
dy/dx
, on an x-y plot. The general form is(y_new - y_old)/(x_new - x_old)
.In order to obtain a velocity estimate from a system where you are obtaining repeated position measurements (ex: you are taking GPS readings periodically), you must numerically derivate your position measurements over time. Your y-axis is position, and your x-axis is time, so
dy/dx
is simply(position_new - position_old)/(time_new - time_old)
. A units check shows this might bemeters/sec
, which is indeed a unit for velocity.In code, that would look like this, for a system where you're only measuring position in 1-dimension:
2. numerical integration
Numerical integration obtains the area under the curve,
dy*dx
, on an x-y plot. One of the best ways to do this is called trapezoidal integration, where you take the averagedy
reading and multiply bydx
. This would look like this:(y_old + y_new)/2 * (x_new - x_old)
.In order to obtain a position estimate from a system where you are obtaining repeated velocity measurements (ex: you are trying to estimate distance traveled while only reading the speedometer on your car), you must numerically integrate your velocity measurements over time. Your y-axis is velocity, and your x-axis is time, so
(y_old + y_new)/2 * (x_new - x_old)
is simplyvelocity_old + velocity_new)/2 * (time_new - time_old)
. A units check shows this might bemeters/sec * sec = meters
, which is indeed a unit for distance.In code, that would look like this. Notice that the numerical integration obtains the distance traveled over that one tiny time interval. To obtain an estimate of the total distance traveled, you must sum all of the individual estimates of distance traveled.
See also: https://en.wikipedia.org/wiki/Numerical_integration.
Going further:
high-resolution timestamps
To do the above, you'll need a good way to obtain timestamps. Here are various techniques I use:
In C++, use my
uint64_t nanos()
function here.If using Linux in C or C++, use my
uint64_t nanos()
function which usesclock_gettime()
here. Even better, I have wrapped it up into a nicetiminglib
library for Linux, in my eRCaGuy_hello_world repo here:Here is the
NS_TO_SEC()
macro from timing.h:If using a microcontroller, you'll need to read an incrementing periodic counter from a timer or counter register which you have configured to increment at a steady, fixed rate. Ex: on Arduino: use
micros()
to obtain a microsecond timestamp with 4-us resolution (by default, it can be changed). On STM32 or others, you'll need to configure your own timer/counter.use high data sample rates
Taking data samples as fast as possible in a sample loop is a good idea, because then you can average many samples to achieve:
4^n
samples increases your sample resolution byn
bits of resolution. For example:See:
So, sampling at high sample rates is good. You can do basic filtering on these samples.
If you process raw samples at a high rate, doing numerical derivation on high-sample-rate raw samples will end up derivating a lot of noise, which produces noisy derivative estimates. This isn't great. It's better to do the derivation on filtered samples: ex: the average of 100 or 1000 rapid samples. Doing numerical integration on high-sample-rate raw samples, however, is fine, because as Edgar Bonet says, "when integrating, the more samples you get, the better the noise averages out." This goes along with my notes above.
Just using the filtered samples for both numerical integration and numerical derivation, however, is just fine.
use reasonable control loop rates
Control loop rates should not be too fast. The higher the sample rates, the better, because you can filter them to reduce noise. The higher the control loop rate, however, not necessarily the better, because there is a sweet spot in control loop rates. If your control loop rate is too slow, the system will have a slow frequency response and won't respond to the environment fast enough, and if the control loop rate is too fast, it ends up just responding to sample noise instead of to real changes in the measured data.
Therefore, even if you have a sample rate of 1 kHz, for instance, to oversample and filter the data, control loops that fast are not needed, as the noise from readings of real sensors over very small time intervals will be too large. Use a control loop anywhere from 10 Hz ~ 100 Hz, perhaps up to 400+ Hz for simple systems with clean data. In some scenarios you can go faster, but 50 Hz is very common in control systems. The more-complicated the system and/or the more-noisy the sensor measurements, generally, the slower the control loop must be, down to about 1~10 Hz or so. Self-driving cars, for instance, which are very complicated, frequently operate at control loops of only 10 Hz.
loop timing and multi-tasking
In order to accomplish the above, independent measurement and filtering loops, and control loops, you'll need a means of performing precise and efficient loop timing and multi-tasking.
If needing to do precise, repetitive loops in Linux in C or C++, use the
sleep_until_ns()
function from mytiminglib
above. I have a demo of mysleep_until_us()
function in-use in Linux to obtain repetitive loops as fast as1 KHz to 100 kHz
here.If using bare-metal (no operating system) on a microcontroller as your compute platform, use timestamp-based cooperative multitasking to perform your control loop and other loops such as measurements loops, as required. See my detailed answer here: How to do high-resolution, timestamp-based, non-blocking, single-threaded cooperative multi-tasking.
full, numerical integration and multi-tasking example
I have an in-depth example of both numerical integration and cooperative multitasking on a bare-metal system using my
CREATE_TASK_TIMER()
macro in my Full coulomb counter example in code. That's a great demo to study, in my opinion.Kalman filters
For robust measurements, you'll probably need a Kalman filter, perhaps an "unscented Kalman Filter," or UKF, because apparently they are "unscented" because they "don't stink."
See also