0%

Selected notes from ROB 501 and ME 564.
$\{x_i\}^b_a$ denotes set $\{x_a, x_{a+1}, \ldots, x_b\}$

Algebraic Structures

Operation

  • Definition: an (binary, closed) operation $\ast$ on a set $S$ is a mapping of $S\times S\rightarrow S$
  • Commutative: $x\ast y=y\ast x,\;\forall x,y\in S$
  • Associative: $(x\ast y)\ast z=x\ast (y\ast z),\;\forall x,y,z\in S$

Group

  • Definition: a group is a pair $(\mathcal{S},\ast)$ with following axioms
    1. $\ast$ is associative on $\mathcal{S}$
    2. (Identity element) $\exists e\in \mathcal{S}\text{ s.t. }x\ast e=e\ast x=x,\;\forall x\in \mathcal{S}$
    3. (Inverse element) $\forall x\in \mathcal{S}, \exists x’ \in \mathcal{S}\text{ s.t. }x\ast x’=x’\ast x=e$
  • Abelian: a group is called abelian group if $\ast$ is also commutative
Read more »

WIP. Progress: (ME 561 @ Week4; ME 564 @ 0%)
This note combines content from ME 564 Linear Systems and ME 561 Discrete Digital Control
In this note, $f\in\mathbb{F}^\mathbb{G}$ stands for a function with domain in $\mathbb{G}$ and co-domain in $\mathbb{F}$, i.e. $f:\mathbb{F}\rightarrow\mathbb{G}$, $H(x)$ generally stands for Heaviside function (step function)

Transforms

Laplace Transform

  • Definition: $F(s)=\mathcal{L}\{f(t)\}(s)=\int^\infty_0 f(t)e^{-st}\mathrm{d}t$

    Note that the transform is not well defined for all functions in $\mathbb{C}^\mathbb{R}$. And the transform is only valid for $s$ in a region of convergence, which is usually separated by 0.

  • Laplace Transform is a linear map from $(\mathbb{C}^\mathbb{R}, \mathbb{C})$ to $(\mathbb{C}^\mathbb{C}, \mathbb{C})$ and it’s one-to-one.
  • Properties: (see Wikipedia or this page for full list)
    • Derivative: $f’(t) \xleftrightarrow{\mathcal{L}} sF(s)-f(0^-)$
    • Integration: $\int^t_0 f(\tau)d\tau \xleftrightarrow{\mathcal{L}} \frac{1}{s}F(s)$
    • Delay: $f(t-a)H(t-a) \xleftrightarrow{\mathcal{L}} e^{-as}F(s)$
    • Convolution: $\int^t_0 f(\tau)g(t-\tau)\mathrm{d}\tau \xleftrightarrow{\mathcal{L}} F(s)G(s)$
  • Stationary Value: $\lim\limits_{t\to 0} f(t) = \lim\limits_{s\to \infty} sF(s), \lim\limits_{t\to \infty} f(t) = \lim\limits_{s\to 0} sF(s)$
Read more »

之前碰到过很多终端工具可以显示非常好看的进度条,或者显示丰富的颜色,甚至还有的直接可以在终端通过字符绘制UI(a.k.a. TUI),我一直都很好奇是怎么做到的。之后又知道了curses这个Python库和它的一些高层封装(例如asciimatics),然后最终在Stack Overflow里面查到了这些都是通过特殊的终端控制符来实现的。本文就介绍这些终端控制符的使用方法,他们很适合用来写一个简单无依赖的TUI。如果需要更复杂和全面的TUI功能,还是最好使用封装好的库。

ASCII 控制符

在最开始接触编程的时候,如果你学的是C,那你一定很熟悉\n,这就是一个”换行“的转义字符,代表终端光标令起一行。有时你还会碰到\r,这是”回车“。“回车”这个名字来源于打字机时代,在使用打字机的时候,如果你需要新起一行,那么需要的操作是:转动滚筒把纸往外抽一行,再把字车(相当与打印机的打印头)移到最左端。这两个操作的名字分别是“换行”和“回车”。因此严格来说另起一行的字符串应该是\r\n,这也是Windows的标准,而在Unix中则简化成\n会自动执行回车。

Read more »

近来由于项目需要,接触了一下一直没去了解过的Python异步语法,发现和之前我熟悉的C#有很多不同。在深入Python的异步逻辑之后,由于Python在语法上保留了很多语言机制的细节(比如成员函数的self参数),我反而对C#的异步有了更深的了解。这里就来重新梳理一下各种并行方法的区别,以及他们在C#和Python上实现的区别。(这里只讨论单机的并行机制。)

总的来说,并行机制主要有进程(Process)、线程(Thread)和协程(Coroutine),其并行实现的开销依次递减,但是他们对每个任务的鲁棒性也是依次递减的。进程是操作系统资源分配的最小单元,线程则是能够被CPU并行处理的最小单元,而协程则是目前实现“并行”的最简单方法。一个进程中可以有多个线程,而一个线程中可以有多个协程。他们具体在特性上有以下区别

进程线程协程
独立内存堆××
独立处理器(可硬件并行)×
独立上下文×
独立栈、寄存器状态
Read more »

Cython提供了很多方法来搭建C/C++内存和Python对象间的桥梁,但是官方的教程只介绍了一些基础的方法。这篇文章就介绍一下我在各个场合学到和用到的Cython封装(多维)数组的技巧。一般而言这个桥梁会分为两部分,Python与Cython和Cython与C/C++。其中Python中的数组主要形式是listarray.arraynumpy.ndarray;Cython中的数组形式有[:,:,:]Memoryview/Buffer)和cython.view.array;C/C++的数组形式有**(指针)、vectorEigen::Vector/Matrix

本篇介绍的主要内容也来自于Cython的文档:Typed Memoryviews

Read more »

这次来介绍一下Cython中的特殊函数定义,Cython相比Python本身的特殊函数之外还增加了一些新的函数,用来满足对C特性的支持,其中有些内容还经常令人混淆。关于Python中特殊变量和特殊函数名的内容,请参考Python官方文档

def, cdefcpdef

首先最开始需要分清的便是Cython中的三种函数类型。def定义的对象(包括变量、函数、类型)都是普通的Python对象,是Python可以直接调用的,因此其参数都只能是Python类型或对象;cdef定义的对象则是C/C++层面的,可以直接用C/C++对象作为参数,因此不能被普通Python代码调用,这样减少了很多overhead因此可以提高运行效率。另外尽管cdef的函数不是Python对象,无法当作变量使用,但还是可以获取函数指针的。而cpdef则是同时兼具两方面特性,其本质是用cdef定义函数后再用def定义一个函数封装,使得在Cython中调用时可以调用高效的cdef版本,而在Python中调用的是与Python兼容的def版本。

Read more »

用Cython也用了很有一段时间了,这次就介绍一下它的最重要功能——使用Cython来封装C/C++代码。最基本的封装方法可以参见Cython文档中的相关页面:Interfacing with External C CodeUsing C++ in Cython,本文介绍主要是比较重要和常用的Cython/C++交互特性,而自定义Python拓展类(而不是封装现有C++)的一些操作可以参考官方教程

封装C++代码时,最重要的关键词就是extern,在定义函数时使用这个关键字就说明该声明是外部的,而使用cdef extern from语句就能指定声明对应的头文件。例如如果要封装函数func,对应的Cython语句是

1
2
cdef extern from "func.c":
void func(int arg)
Read more »

Python作为一门胶水语言,它与C/C++之间的兼容性(Interoperability)我认为是它相比其他动态语言脱颖而出的最大原因。Python原生支持的是与C语言的接口,Python的发行版自带有Python.h头文件,里面提供了在C中调用Python和反过来在Python中调用C的接口定义。但是C++就不一样了,虽然C++ ⇔ C ⇔ Python的通道是可行的,但是想要完整兼容C++的特性的话需要很多额外的重复代码(boilerplate)。因此相应针对Python/C++绑定的库也就应运而生了,我所了解的库主要有四个:Boost.PythonCythonpybind11SWIG。虽然网上也有不少比较三者的页面,但是我觉得都不够详细,这篇博客就介绍一下我基于使用这几个库的经验比较。

上面说到的这些库我基本都有接触过,其中用过的有pybind11和Cython,分别用在了我正在写的CGALPCL的绑定上。另外二者则是在其他库的代码中有读过(如Caffe和CGAL的官方绑定)。总的来说,Boost.Python和pybind11主要用于给现有C++代码提供Python绑定,并且不用学习新的语法;SWIG提供一个给C++代码编写多种语言绑定的框架,它本质上是一种代码生成器,基于SWIG自定义的语法;Cython则是基于Python的C/C++代码封装器,其本质也是代码生成器,但是Cython的语法是Python的超集,也就是说Python的代码可以零成本移植到Cython中。

Read more »

最近在研究ROS节点(ROS Node)的参数设置方式,由于系统比较复杂,并且会变得更加复杂,因此需要一个统一的参数设置方式。这里就比较一下四种参数获取方案的区别~

命令行/文件输入

由于ROS节点本身也只是普通的可执行程序,因此它可以正常地从启动参数中读取参数,另外也可以从配置文件中读取参数。这两种方法都是常规程序读取参数的方法。从命令行中读取参数有C++的Boost.Program_options库和Python的argparse的库,用来解析命令行参数输入,支持可选参数、重复参数、参数分组等等。而从文件输入的话,常见的设置格式有jsonyamltoml甚至ini等等。从这些文件中读取比较灵活,但是无法利用ROS框架,并且需要自行统一格式。

参数服务器

ROS中很有名的支持参数设置的结构是参数服务器,参数服务器是一个包含在master结点里的集中式字典结构,在ROS的Wiki上有介绍:中文|英文。参数服务器也可以从文件中读取参数,文件格式是yaml,读取的方式是在.launch文件中添加<rosparam>标签,并指定键值或者文件路径。

Read more »

最近我已经将KDE Neon作为主力系统之一了,Plasma桌面真的是太好用了!于是给家里的主机也装上了Neon,这篇文章就记录一下安装配置和美化的过程啦~

系统安装及Boot设置

双系统安装

安装Neon还是非常简单的,直接从官网下载系统镜像,烧进U盘正常安装即可。不过由于我选择的是与Windows双系统安装,因此需要手动分区。这里要纠正一下之前安装双系统博文中的分区方式。现在的Linux系统实际上只需要给根目录/分区就可以了,/home分区以前建议单独分区的原因是为了便于系统的更改,这样在修改系统分区之后(如重装系统)还能保留/home底下的文件,但其实现在很多系统已经能做到重装并保留/home分区了,这时对于我这小硬盘的笔记本来说反而导致空间利用不灵活。而交换分区/swap也是没有必要的,交换分区的存在类似于Windows下的虚拟内存,用硬盘的一部分来虚拟内存,避免内存不足的情况。新Linux可以利用交换文件完成类似功能,因此不必专门给/swap分区。(不过我猜专门给它分个区可能能提高性能?)。最后最关键的是不要给/boot分区了,/boot分区是为了保证boot文件区不被占满,以致无法正常启动。利用EFI方式启动的系统只需要有efi分区即可,而且多个系统可以利用同一个EFI分区。因此只需告诉安装器使用EFI分区作为启动分区,关于EFI的详细信息请看后文~

分区的时候还看到了之前的系统里有标记为msr的分区,是Windows的预留分区,好像具体没啥用。这里贴一篇考据文章

Read more »