-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.xml
110 lines (110 loc) · 18.8 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Ramblings from Hao</title>
<link>https://haodongnj.github.io/haodongnj/</link>
<description>Recent content on Ramblings from Hao</description>
<generator>Hugo</generator>
<language>zh-CN</language>
<lastBuildDate>Sun, 28 Jul 2024 21:57:36 +0800</lastBuildDate>
<atom:link href="https://haodongnj.github.io/haodongnj/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Virtual time,多进程共享虚拟时间原型验证</title>
<link>https://haodongnj.github.io/haodongnj/post/virtual_time/</link>
<pubDate>Sun, 28 Jul 2024 21:57:36 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/virtual_time/</guid>
<description>周末抽空想了想数据回放的时间戳问题,想到了一个比较有意思的方案,就是使用虚拟时间。所以就尝试采用多进程共享虚拟时间的方式来劫持系统时间戳,尝试满足数据回放过程中的功能代码对系统时间戳需求。
一般而言,像ROS或者DDS的消息数据都是带有时间戳的,比如录制时间戳,消息内部header中保存的数据源时间戳或者数据对应的有效时刻的时间戳等等 对于实际生产环境中的功能逻辑代码,可能会依赖于系统时间戳来进行一些逻辑判断,比如超时判断,定时器;又或者对不同来源(不同topic、不同帧率)的时间戳的消息进行时间戳对齐或者插值等等,这些都是对时间戳的依赖。而如果软件没有对获取时间戳的接口进行封装,那么在采用类似于Pub/Sub的方式对数据回放的时候,就会出现问题,因为数据回放的时间戳是不可控的,可能会导致功能逻辑的错误。 对于单进程的数据回放程序,可以使用消息录制时的时间戳来作为虚拟的仿真系统时间戳,这样的话,原有的代码逻辑就可以直接使用这个时间戳来进行仿真 对于多进程节点,数据通过类似于DDS Pub/Sub的方式进行传输,那么就需要对时间戳进行额外的处理;对系统时间戳进行劫持,然后通过共享内存的方式来共享虚拟时间戳是一个看上去能走通的方案(当然,未必是最优的) 实现的思路非常简单,那就是可以根据消息对应的录制时间戳和消息内部的时间戳(其实一般前者应该就够了),来更新虚拟的时间戳,并将这个虚拟时间戳通过共享内存的方式共享给其他进程。这样的话,其他进程就可以通过读取共享内存的方式来获取虚拟时间戳。
该虚拟时间戳,可以通过劫持libc中的gettimeofday、clock_gettime等函数来实现,这样的话,就可以在不修改原有代码的情况下,来实现对系统时间戳的劫持;这可以通过将动态库指定到LD_PRELOAD的方式来实现。
具体原型代码实现可见 Virtual timestamp。该实现仅为虚拟时间戳多进程更新和共享的原型验证,实际应用中还需要考虑更多的问题,比如定时器回调的处理,进程异常退出后共享内存的释放等等。
其实ROS在设计中是采用 /clock topic 来发布时间戳的(ROS 2 Design: Clock and Time),这个主要受到网络通信延时的影响。共享内存的方式有可能会更快,不过没有考虑多机通信的情况。一般回放数据的时候,都是在一个机器上进行的,所以这个问题应该不大;要是真的有多机通信的需求,也估计还得靠消息传递的方式来实现。
时间戳在回放过程中是个比较重要的问题,这影响到功能逻辑的正确性。例如Timestamps and rosbags: discussing an alternative to clock and use_sim_time这里就谈到了录制消息时间戳乱序的问题,里面提到需要对文件进行后处理,来保证时间戳的顺序性。所以关于回放过程中的时间戳问题,还是要根据具体的应用场景来进行设计。</description>
</item>
<item>
<title>Cling Jupyter Notebook</title>
<link>https://haodongnj.github.io/haodongnj/post/cling-jupyter-notebook/</link>
<pubDate>Tue, 20 Feb 2024 21:05:21 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/cling-jupyter-notebook/</guid>
<description>Cling Jupyter Notebook 最近开始学习C++20相关的特性,需要经常性地写一些代码进行验证工作,试用了一下cling,感觉不错,记录一下。
之前也留意到xeus-cling项目,尝试了用conda拉取失败,遂放弃,自己动手编译吧。
编译 按照Readme来编译还是有点小坑的,主要有以下:
cmake 指令问题,大小写有点坑,这个issue算是解决了。 OOM问题:需要编译cling和root-project的llvm工程,如果采用多线程编译的话,笔记本32G的内存还是会有内存不够用的情况。将线程数量调小就可以避免,问题不大。编译完成后,cling-build目录竟然有95GB。 Jupyter notebook 默认的安装目录为/usr/local,不过Jupyter相关的文件并没有安装到这个目录下,需要自己到工程目录下去找 cling/tools/Jupyter。
自行安装配置好Python3的venv后,按照ReadMe的说明配置一下就可以。
如果要尝试一下C++20的特性,可以参考#520为Jupyter notebook增加 C++20 的入口。不过需要留意一下编译时gcc的版本,笔者用的Debian 12自带的默认gcc版本为12.2,支持大部分C++20的语言特性。gcc对C++语言标准的支持可参考C++20 Support in GCC。
效果 #include &lt;ranges&gt; #include &lt;numeric&gt; #include &lt;vector&gt; #include &lt;iostream&gt; namespace views = std::views; namespace ranges = std::ranges; std::vector ints{0, 1, 2, 3, 4}; auto rv = ints | views::reverse ; for(auto i : rv){ std::cout &lt;&lt; i &lt;&lt; &quot; &quot;; } 参考 Using cling to interpret C++ code ROOT </description>
</item>
<item>
<title>Know how to access name in templated base classes</title>
<link>https://haodongnj.github.io/haodongnj/post/know_how_to_access_name_in_templated_base_classes/</link>
<pubDate>Sun, 26 Feb 2023 15:16:00 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/know_how_to_access_name_in_templated_base_classes/</guid>
<description>模板基类成员如何在继承类中访问 如题,最近在C++标准库的学习过程中,产生了这样的疑问。标准库中解决这个问题一共有3种方式:
用using来指明该成员为依赖名称(dependent name) 直接把带模板参数的基类作用于成员名称前 采用this指针来指明该名称依赖于实例化后的类 这3种方式实际上都是在告知编译器,该成员是一个依赖名称,需要在实例化后才能找到。
但是为什么呢?找寻了很久才发现了满意的答案。
Short answer: in order to make x a dependent name, so that lookup is deferred until the template parameter is known.</description>
</item>
<item>
<title>Kalman Filter小结</title>
<link>https://haodongnj.github.io/haodongnj/post/kf/</link>
<pubDate>Mon, 07 Mar 2022 22:03:22 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/kf/</guid>
<description>卡尔曼滤波小结 最近复习了一下卡尔曼滤波,并在Coursera上完成了课程与练习1,做些简单的笔记备忘。
1. 线性卡尔曼滤波 简单来说,对于一个线性系统的状态,可以通过模型计算获取到一个基于模型的预测状态,再通过实际测量的值来纠正系统的状态。
通过模型来更新状态 系统的控制方程为: $$ \check{x}_k = F_{k-1} \hat{x}{k-1} + G{k-1}u_{k-1} $$
更新状态协方差矩阵: $$ \check{P}_{k}= F_{k-1} \hat{P}{k-1} F{k-1}^{T} + L_{k-1} Q_{k-1} L_{k-1}^{T} $$</description>
</item>
<item>
<title>台式机折腾记</title>
<link>https://haodongnj.github.io/haodongnj/post/ryzen-5900x-pc/</link>
<pubDate>Mon, 21 Jun 2021 22:36:50 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/ryzen-5900x-pc/</guid>
<description>配置 趁着618攒了一台主机,犹豫了很久还是决定上车AMD,配置如下:
CPU: AMD Ryzen-9 5900x 主板:TUF Gaming X570-Plus WIFI 硬盘: 1TB SSD KC2500 4TB HDD 西部数据蓝盘 Fury 32GB DDR4 3600MHz 美商海盗船AIR540中塔机箱 美商海盗船HX1200,1200W电源 GTX 750Ti显卡(等矿难) 装机的过程略去不表。记录一些配置工作:</description>
</item>
<item>
<title>Richardson-Lucy Deconvolution</title>
<link>https://haodongnj.github.io/haodongnj/post/rl-deconvolve/</link>
<pubDate>Wed, 03 Feb 2021 00:38:40 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/rl-deconvolve/</guid>
<description>RL反卷积都干了些啥 RL反卷积是通过迭代的方法来优化损失函数,利用噪声性质和成像系统的点分布函数(Point Spread Function)对图像进行去噪的一种方法。 损失函数是啥样的呢?
$$ J(O) = \Sigma(O**PSF - I \cdot ln(O ** PSF)) $$
且有:
$J$,损失函数,为最小化的目标 $O(x,y)$,不受椒盐噪声和点分布函数模糊效应影响的理想原始图像 $PSF(x,y)$,Point Spread Function,点分布函数 $I(x,y)$,实际拍摄到的图像 $**$,二维卷积 $\cdot$,按元素相乘 既然要优化$J(O)$,那么就对O求导:</description>
</item>
<item>
<title>关于我</title>
<link>https://haodongnj.github.io/haodongnj/about/</link>
<pubDate>Sun, 30 Aug 2020 22:21:34 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/about/</guid>
<description> E-mail : [email protected] Telegram : HaoDongNJ Linkedin: https://www.linkedin.com/in/hao-dong-91240297/ </description>
</item>
<item>
<title>树莓派实时内核编译与测试</title>
<link>https://haodongnj.github.io/haodongnj/post/rpi-rt-kernel/</link>
<pubDate>Wed, 12 Jun 2019 23:50:56 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/rpi-rt-kernel/</guid>
<description>1. 简介 本文档主要根据LeMaRiva的博客内容整理并基于最新的rt分支代码复现,简述以下2个方面:
如何为树莓派编译实时内核 测试实时内核的进程调度延时性能 实验所需硬件:
树莓派3B 8G TF卡 2. 编译 1.获取代码和工具:
# From LeMaRiva mkdir rpi-rt cd rpi-rt mkdir rt-kernel # 用于存放编译产生的文件 cd rt-kernel mkdir boot cd .</description>
</item>
<item>
<title>从伯德图说起</title>
<link>https://haodongnj.github.io/haodongnj/post/bodeplot/</link>
<pubDate>Fri, 31 Aug 2018 00:43:25 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/bodeplot/</guid>
<description>在当初学《自动控制原理》的时候,并没有去理解公式背后的意义,囫囵吞枣式地做题、计算、画图。现在想来,传递函数的计算、根轨迹的绘制甚至是伯德图的快速绘制方法都记不得了,但是在实践和仿真中,对于概念的理解更深入了些,所以写下。本文从伯德图说起,讲了以下3个方面:
伯德图表示什么 开环伯德图表示什么 伯德积分定理意味着什么 伯德图表示什么 伯德图是从频域的概念来描述系统的性质、表现的。如果我们考虑最简单的系统——比例环节:
$$G_{p} = K_{p}$$
当 $K_{p} = 1$ 时,其传递函数如下图所示:
那么这张图代表什么呢?代表着任意频率的正弦信号通过比例环节之后输出的信号的幅值依然不变——增益为0dB;同时输出信号和输入信号是同相位的,没有相位延迟。
那么如果我们考虑常见的一阶惯性环节呢:
$$ G_{rc} = \frac{1}{T_{s}s + 1} $$
令$T_{s}=0.1$时,一节惯性环节的伯德图是什么样子的呢?
可见,一阶惯性环节在低频处的增益近似为0dB,而随着频率的增加,增益逐渐下降,而相位也随着频率的增加而滞后,相位滞后的极限为90°。其实一阶惯性环节这样的传递特性对应于电阻电容串联的电路,系统输入为施加在串联阻容上的电压;系统输出为电容两端的电压。如果输入电压为直流电压,那么电容的稳态电压就是直流电压;而如果施加低频正弦电压,那么输出的信号的衰减和相位滞后就会很小;而如果施加高频正弦信号的话,那么输出信号的幅度相对于输入信号就会产生衰减,相位滞后也会随之增大。</description>
</item>
<item>
<title>Windows的MATLAB中用C语言写SFunction的一些坑</title>
<link>https://haodongnj.github.io/haodongnj/post/matlab-sfunction/</link>
<pubDate>Mon, 09 Jul 2018 23:46:03 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/matlab-sfunction/</guid>
<description>1.测试环境 操作系统:Windows 10, 64bit 编译器:MinGW64 32位系统请下载对应的32位版本 MATLAB2017a 2017a之后会略有不同 2. 配置环境与流程 下载编译器MinGW64,对于64位系统而言,需要下载个安装器,可以安装相应版本的gcc编译器,我选择的是gcc-4.9.4,在测试环境中可以正常运行
安装器是mingw-w64-install,安装时注意选择64位,同时安装完了还有一个坑:空格。 下载器默认的安装路径&quot;C:Files-w64_64-4.9.4-win32-seh-rt_v5-rev0&quot;是包含有空格的,MATLAB并不能识别该路径,所以可以把mingw64移动到不含空格的路径下,比如&quot;C:&quot;。 验证一下:
setenv('MW_MINGW64_LOC','C:\mingw64') % 先配置环境 mex -setup 输出如下图所示,这样MinGW编译器就配置好了。
3. a + b 编译测试 setenv('MW_MINGW64_LOC','C:\mingw64') myFunctionName = 'SFunctionName' def = legacy_code('initialize'); def.</description>
</item>
<item>
<title>C Language Implementation for Proportional-Resonant Controller</title>
<link>https://haodongnj.github.io/haodongnj/post/pr-control/</link>
<pubDate>Fri, 22 Jun 2018 02:13:54 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/pr-control/</guid>
<description>1. Introduction to Proportional-Resonant Controller First, let&rsquo;s see the transfer function of PR controller and its bode diagram:
$$ G_{PR}(s)=K_{p} + \frac{K_{r}s}{s^{2} + \omega_{r}^2} $$</description>
</item>
<item>
<title>Discretization method(离散化方法)</title>
<link>https://haodongnj.github.io/haodongnj/post/descretization-method/</link>
<pubDate>Fri, 27 Oct 2017 01:58:28 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/descretization-method/</guid>
<description>离散化方法的笔记 最近看论文中发现,分析系统的稳定性问题总免不了在s域先分析一下,然后再在z域上分析一下。可是很多论文对于离散化方法却略去不提,直接给出推导出的结果。所以笔者就寻找总结了一下各种离散化方法,总结一下。学通信或者测量的同学,专门学过数字信号处理的话,应该很熟悉的。
1. 后向差分 后向差分的映射关系为:
$$ s \leftarrow \frac{z-1}{Tz} $$
从s平面到z平面上来看的话,这实际上是将s平面的左半平面映射到z平面的以(0.5,0)为圆心,半径为0.5的圆中。所以原来稳定的系统,经过后向差分之后,一定是稳定的,因为该圆在单位圆内;而原来不稳定的系统,有可能被映射到单位圆中,即可能存在原来不稳定的系统经过后向差分离散化之后,是稳定的。
参考文献中有s平面映射到z平面的图,方便理解,有需要的同学可以查看。
2. 前向差分 前向差分的映射关系为:
$$ s \leftarrow \frac{z-1}{T} $$
从s平面到z平面上来看,其实是将左半平面映射到了z平面上直线 $z=1$ 的左边平面上。所以原来在s域上稳定的系统经过前向差分之后的离散系统可能是不稳定的。
3. Tustin Method(双线性变换方法:Bilinear Transform) 双线性变换方法的映射关系为:</description>
</item>
<item>
<title>稳定性和振荡的频域理解</title>
<link>https://haodongnj.github.io/haodongnj/post/stability-in-frequency-domain/</link>
<pubDate>Fri, 31 Mar 2017 01:57:46 +0800</pubDate>
<guid>https://haodongnj.github.io/haodongnj/post/stability-in-frequency-domain/</guid>
<description>系统截止频率对应的相角与-180°相差的度数成为相角裕度,为何?
因为所谓相角裕度与增益裕度都是基于频域的控制系统稳定性指标。倘若系统的开环传递函数的截止频率相移为-180°,那么由于负反馈对于正弦波自带180°的相位滞后,那么对于系统而言就相当于正反馈,则系统将处于自激振荡状态。举个简单的例子,前向通道和反馈通道分别为积分环节:
fw = tf(1, [1, 0]); fd = fw ; sys = feedback(fw, fd); impulse(sys) 可以看到,系统的脉冲响应是周期为6.28的正弦波,即当存在轻微扰动时,系统就会进入自激振荡状态(因为系统临界稳定);而当系统的输入为0的时候,是输出也为0, 这可以理解为系统无能量输入,所以系统也就不会输出响应。想起模电中运用正反馈构成自激振荡电路的原理,实际工作环境中存在着能量的传播,所以自激振荡电路总能产生振荡的正弦波。理解这一点,对数稳定判据以及奈奎斯特稳定判据就很好理解了。
考虑下图显示的典型的反馈控制系统框图,如果将反馈处切开,那么从给定(Setpoint)到反馈的传递函数实际上就是自控概念中的开环传递函数了。
对于正弦信号而言,开环传递函数的幅频特性实际上反映的是反馈回来的信号的放大倍数(也可能是缩小)和相角延迟,这个和系统的稳定性有着密切的关系。如果反馈回来的信号为-180°,并且增益也比较大(大于等于1),那么系统就自然不会稳定。然而在实际系统中,由于功率(能量)的限制,噪声的影响,自激振荡这种状态就很好解释了。
毕竟开环传递函数研究的是反馈相当于系统给定的性质,把握了这句话,电工出身的人所说的环路增益研究系统稳定性就很好理解了。:)</description>
</item>
<item>
<title>Archives</title>
<link>https://haodongnj.github.io/haodongnj/archives/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>https://haodongnj.github.io/haodongnj/archives/</guid>
<description></description>
</item>
</channel>
</rss>