Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

飞行力学中坐标系定义

发表于 2018-12-10 | 更新于 2020-01-08

建立飞机的运动学模型的前提是建立合适的坐标系,在此基础上才能定义各种参数描述飞机的状态。下面介绍常用的坐标系及常用描述飞机状态的参数。

常用坐标系

地面固定坐标轴系($AX_gY_gZ_g$)

将地球视为椭球体,则地面固定坐标轴系定义为:

以椭球面上一点为坐标系原点$A$,$Z_g$轴与椭球法线重合,向下为正,$X_g$与$Y_g$轴位于过坐标原地的椭球切平面上,按右手法则建立,$X_g$轴与椭球短半轴重合(北向),$Y_g$轴与地球椭球的长半轴重合(东向)。

在研究坐标转换关系时,常使用飞机牵连铅垂地面固定坐标系$OX_gY_gZ_g$。其原点$O$位于飞机质心,三坐标轴平行于地面固定坐标轴系$AX_gY_gZ_g$的各个轴。飞机姿态——偏航、俯仰、滚转的定义即与飞机牵连铅垂地面固定坐标系有关。

机体坐标系(体轴系$OXYZ$)

机体坐标系定义为:

原点$O$位于质心,$O_X$平行于机身轴线或对称面机翼弦线指向前方(机头方向);$O_Y$垂直于对称面指向右翼;$O_Z$在飞机对称面内,垂直于$O_X$指向下方。符合右手系建立规定。

机体坐标系

图1 飞机牵连铅垂地面固定坐标系(OXgYgZg)与体轴系(OXYZ)

航迹坐标系($OX_kY_kZ_k$)

航迹坐标系定义:

原点$O$位于飞机质心,$OX_k$沿飞机速度方向;$OZ_k$在$OX_k$所在铅垂平面内,垂直于$OX_k$指向下方;$OY_k$垂直于$OX_k$、$OZ_k$ 所在平面指向右方;符合右手系建立规定。

航迹坐标系

图2 航迹坐标系(OXkYkZk)

气流坐标轴系(风轴系$OX_aY_aZ_a$)

气流坐标轴系又称速度坐标轴系,定义为:

原点$O$位于飞机质心,$OX_a$沿飞机速度方向;$OZ_a$在飞机对称面内,垂直于$OX_a$指向下方;$OY_a$垂直于$OX_a$、$OZ_a$ 所在平面指向右方;符合右手系建立规定。

气动力三个分量(升力、阻力、侧力)是根据风轴系定义的,其中升力与阻力分别沿$OZ_a$、$OX_a$的负向。

半机体坐标系($OX_iY_iZ_i$)

半机体坐标系定义为:

原点$O$位于质心,$OX_i$沿飞机速度向飞机对称面内投影方向;$OZ_i$在飞机对称面内,垂直于$OX_i$指向下方;$OY_i$垂直于$OX_i$、$OZ_i$ 所在平面指向右方;符合右手系建立规定。

半机体坐标

图3 风轴系(OXaYaZa)与半机体坐标系(OXiYiZi)

稳定性坐标系($OX_sY_sZ_s$)

稳定性坐标系定义为:

原点$O$位于质心,$OX_s$沿未受扰动的速度在对称面内的投影方向;$OY_s$在飞机对称面内,指向右;$OZ_s$对称平面内垂直于$OX_s$向下;符合右手系建立规定。

半机体坐标

图4 稳定性坐标系(OXsYsZs)

常用飞参

  • 机体坐标系相对于飞机牵连铅垂地面固定坐标系的夹角

    • 偏航角:机体坐标系$x$轴在水平面内投影与$x_g$的夹角,以$\psi$表示
    • 俯仰角:机体坐标系$x$轴与水平面的夹角,以$\theta$表示
    • 滚转角:过机体坐标系$x$轴的铅垂面与机体坐标系$z$轴的夹角,以$\phi$表示
  • 飞行速度矢量相对于体轴系的夹角

    • 迎角:速度矢量在飞机纵向对称面内投影与机体坐标系$x$轴夹角,以$\alpha$表示
    • 侧滑角:速度矢量与飞机纵向对称面的夹角,以$\beta$表示
  • 飞行速度矢量相对于地面的夹角

    • 爬升角:速度与地面水平面夹角,以$\gamma$表示
    • 航迹方位角:速度在地面水平面的投影与$x_g$夹角,以$\chi$表示

参考链接

  1. 无人机飞控通俗演义之 纷繁复杂的飞行力学, by 量子黑洞.
  2. 一起写飞行仿真之 六自由度动力学方程, by 量子黑洞.
  3. 飞行器飞行动力学(二)坐标系与夹角们, by 萝卜.
  4. Cesium中飞行器姿态控制,by jack huang.
  5. MathJax 支持的 Latex 符号总结(希腊字母和希伯来字母),by liyuanbhu
  6. 空间中三维矢量,by tina_ttl.
  7. JSBSim学习笔记(3)—— 基本概念,by 么的聊.

Debian系统安装NVIDIA驱动支持双显卡切换

发表于 2018-12-10

购买笔记本拥有Intel集成显卡和NVIDIA显卡,如何在Debian Linux下启用NVIDIA显卡是一个难题。幸运的是,通过bumblebee软件可在Linux下支持NVIDIA Optimus技术,实现Intel集成显卡和NVIDIA显卡之间的切换使用。

背景知识

NVIDIA Optimus

Optimus是NVIDIA针对笔记本电脑的显示切换技术。它可以实现笔记本电脑中独立显卡与主板内置显卡之间无缝、自动、实时的切换(用户无需重启或手动调整),从而实现能源的节约。

利用Optimus技术后,计算机的显示输出永远都只会通过集成式芯片组的显示核心。独立显卡的显示输出将会被废掉,有关的输出亦会发送到前者。由于显示输出的设备是固定的,所以黑屏现象将会被解决。额外的切换线路亦变得不需要,因为在不需要独立显示核心的时候,系统会索性断绝其电源供应。当系统的显示负载轻的时候,就会完全利用内置的显示核心。当负载增加后,系统就会打开独立显示核心作计算之用。协议分工方面由驱动程序负责,NVIDIA声称可以兼容所有的API。

Bumblebee

Bumblebee 致力于使 NVIDIA Optimus 在 GNU/Linux 系统上可用,实现两块不同的供电配置的显卡同时插入使用,共享同一个 framebuffer。

安装配置过程

禁止加载开源驱动nouveau

1
2
3
4
5
6
7
8
$ vi /etc/modprobe.d/nvidia-installer-disable-nouveau.conf

#上述文件不存在则新建,在文件中添加下面两行文字
blacklist nouveau
options nouveau modeset = 0

#系统重启后使用以下命令查看nouveau驱动是否被禁止
lsmod |grep -i nouveau

安装内核头文件

1
$ sudo apt-get install -y linux-headers-$(uname -r)

安装NVIDIA驱动

1
2
# 关于是否生存xorg.conf文件,选no
$ sudo apt-get install nvidia-driver nvidia-xconfig nvidia-kernel-dkms

安装双显卡切换解决方案包

1
$ apt-get install bumblebee-nvidia primus

添加当前用户到bumblebee用户组

1
$ adduser $USER bumblebee

修改bumblebee配置

1
2
3
4
5
6
7
8
9
10
11
12
$ vi /etc/bumeblebee/bumblebee.conf
: Driver=nvidia

#将/etc/bumeblebee/bumblebee.conf文件中的Driver=* 改成 =nvidia

$ vi /etc/bumblebee/xorg.conf.nvidia
:BusID "PCI:01:00:0"

#在/etc/bumblebee/xorg.conf.nvidia文件中,将Section“Device”部分添加PCI ID

# 可使用如下命令查看NVIDIA显卡的BUS ID
nvidia-xconfig --query-gpu-info | grep 'BusID : ' | cut -d ' ' -f6

重启进入桌面

如果无法进入桌面环境,则安装失败,进入高级修复使用如下命令进行清理。

1
$ sudo apt-get purge nvidia* bumblebee* prime*

bumblebee服务开机不会启动,设置开机启动即可。

1
$ update-rc.d -f bumblebee defaults

使用独显运行程序

bumblebee不能做到集显和独显之间自动切换,系统运行时默认使用集显,当你需要使用独显运行某个程序或者游戏的时候,终端执行如下命令即可:

1
2
$ optirum command #使用独显运行command程序
$ optirum -b primus command #使用独显运行command程序,提升性能

参考链接

  1. kali 在支持双显卡切换机器宏碁(Acer)V3下安装NVIDIA驱动, by 不梦君.
  2. Installing-Nvidia-drivers-on-Kali-Linux, by europa502.
  3. NVIDIA Optimus, by wikipedia.
  4. 在Ubuntu上安装和配置Nvidia Optimus驱动, by Linux中国.
  5. Bumblebee,by archlinux.

Linux图形界面基础知识

发表于 2018-12-09 | 更新于 2018-12-10

Linux初学者经常分不清楚linux和X之间,X和Xfree86之间,X和KDE,GNOME等之间是什么关系。常常混淆概念,下面以易于理解的方式解释X,X11,XFREE,WM,KDE,GNOME等之间的关系。

Linux内核没有图形用户界面

与Windows操作系统内核集成图形用户界面不同,Linux内核没有图形用户界面,是一个基于命令行的操作系统。

linux和Xfree的关系就相当于当年的DOS和 WINDOWS3.0一样,windows3.0不是独立的操作系统,它只是DOS的扩充,是DOS下的应用程序级别的系统,不是独立的操作系统,同样 XFree只是linux下的一个应用程序而已。不是系统的一部分,但是X的存在可以方便用户使用电脑。

WINDOWS95及以后的版本就不一样了,他们 的图形界面是操作系统的一部分,图形界面在系统内核中就实现了,没有了图形界面windows就不成为windows了,但linux却不一样,没有图形 界面linux还是linux,很多装linux的WEB服务器就根本不装X服务器.这也WINDOWS和linux的重要区别之一。

X是协议,不是具体的某个软件

X 是协议,就像HTTP协议,IP协议一样。一个基于X的应用程序需要运行并显示内容时他就联 接到X服务器,开始用X协议和服务器交谈。

比如一个X应用程序要在屏幕上输出一个圆那么他就用X协议对X服务器说:喂!我需要在屏幕上画一个圆.X应用程 序只负责告诉X服务器在屏幕的什么地方用什么颜色画一个多大的圆,而具体的”画”的动作,比如这个圆如何生成,用什么显卡的驱动程序去指挥显卡完成等等工作是由X服务器来完成的。

X服务器还负责捕捉键盘和鼠标的动作,假设X服务器捕捉到鼠标的左键被按下了,他就告诉X应用程序:亲爱的应用程序先生,我发现 鼠标被按下了,您有什么指示吗?如果X应用程序被设计成当按下鼠标左健后再在屏幕上画一个正方形的话,X应用程序就对X服务器说:请再画一个正方形,当然 他会告诉服务器在什么地方用什么颜色画多大的正方形,但不关心具体怎么画–那是服务器的事情。

XFree86和Xorg是实现X协议的服务器程序

Xfree86就是这样一个去根据法规实现协议的 “交警”。他按照X协议的规定来完成X应用程序提交的在屏幕上显示的任务。当然不仅仅是某个特定的交警才可以去维护和实现这个法规,比如还可以由交通协管 员来实现交通法规,必要的时候警察也可以介入,当然前提是他们都要懂得交通法规,也就是要懂得协议。

所以实现X协议的软件也并不只有 XFree86,XFree86只是实现X协议的一个免费X服务器软件.商业上常用MOTIF,现在还有XORG,还有很多很小的由爱好者写的小的X服务器软件。

X和X11R6的关系

X11R6 实际上是 X Protocol version 11 Release 6
(X协议第11版第六次发行)的意思,就是说目前用的X协议是第11版的,然后经过了6次小的修正。

不同版本的X协议是不能通信的。就象我们现在IPV4和IPV6不能通信一样,不过不用担心,现在的X服务器软件和X应用程序都遵循X11R6。

X服务器和WM(window manager 窗口管理器)的关系

窗口管理器是一种X应用程序,它负责窗口最大化,最小化,移动,关闭窗口等。这些不是X服务器负责完成的。

KDE和GNOME

KDE 和GNOME是LINUX里最常用的图形界面操作环境,他们不仅仅是一个窗口管理器那么简单, KDE是K Desktop Environment 的缩写。他不仅是一个窗口管理器,还有很多配套的应用软件和方便使用的桌面环境,比如任务栏,开始菜单,桌面图标等等。

GNOME是GNU Network Object Model Environment 的缩写。和KDE一样,也是一个功能强大的综合环境。

另外在其它UNIX系统中,常常使用CDE作为这样一个环境。

其它的小型窗口管理器有: window maker,after step,blackbox,fvwm,fvwm2,等等都是常用的优秀窗口管理器。

linux图形界面层次关系总结

linux本身–>X服务器<-[通过X协议交谈]->窗口管理器(综合桌面环境)–>X应用程序。

Xfree86服务器的实现包括两个部分,一部分是和显卡直接打交道的低层,一部分是和X应用程序打交道的上层。

上层负责接收应用程序的请求和鼠标 键盘的动作。而和显卡直接打交道的底层负责指挥显卡生成图形,其实就是显卡驱动。上层接收到应用程序的请求后,将请求内容做适当处理,然后交给显卡驱动来 指挥 显卡完成画图的动作。

另外,上层的捕捉键盘和鼠标动作的部分会向应用程序提供鼠标和键盘的状态信息,应用程序接收到这些信息后决定是否再有相应的动作。

参考链接

  1. linux图形界面基本知识(X、X11、Xfree86、Xorg、GNOME、KDE), by huang_xw.

家用电器安全使用年限与折旧

发表于 2018-12-08

家用电器都有一定的安全使用年限,超过安全使用年限,家用电器因产品老化将产生如下问题,造成安全隐患:

  • 绝缘体老化,产生漏电,导致电磁污染
  • 元器件技术指标严重下降,导致有害物质泄漏,耗电量增加

那么家用电器的安全使用年限是多少呢?购买二手家用电器时如何折旧呢?

家用电器安全使用年限

有关家电安全使用年限的标准通则早已出台,但是针对不同产品的具体年限细则却迟迟未发布。原因主要在于不同产品的使用年限评估难度较大,不同地区的使用差异性也较大,因此就目前而言国内尚无明确的家电使用年限方面的规定,国际通行年限可作参考:

  • 电吹风:4年
  • 电热毯:6年
  • 电脑:6年
  • 吸尘器:8年
  • 煤气灶:8年
  • 电热水器:8年
  • 洗衣机:8年
  • 电视:8-10年
  • 空调:8-10年
  • 微波炉:10年
  • 电饭煲:10年
  • 电风扇:10年
  • 冰箱:12-16年

家用电器安全使用年限只是最高限定,如果在使用过程中不注意保养维护,也有可能缩减家用电器的使用寿命,这就要求用户在日常生活中需要注重维护保养,使家电处于良好的工作环境,确保家电安全“服役”。

家用电器老化特征

家用电器也有各自的老化特征,当出现以下老化特征时,建议及时保养或更换:

  1. 空调:如果使用多年的空调开始出现制冷或制热变慢,噪音过大,在开机时会出现霉味且出风伴有灰尘,流出黑水,那么用户就应该考虑更换一台新空调。老旧空调此时不仅耗费更多电量,出风还会带有细菌污垢,影响身体健康。

  2. 冰箱:平时运行良好的冰箱开始出现制冷效果差,噪音过大,甚至发生轻微颤动时,说明已经老化。若继续使用,耗电量将会加大,食物的储鲜功能也会退化,有时还会出现冰箱制冷剂泄露,污染食材环境的问题。

  3. 洗衣机:洗衣机使用超龄的现象在用户中最为常见,判断它已经超龄的方式也最为简单。通常来说,洗衣机出现渗水、漏水、漏电,噪音过大,衣物清洗不净等问题都是达到使用年限的表现,严重时甚至会发生爆炸事件。

  4. 电视机:虽然各种类型的平板、投影仪的市场占有率越来越高,但电视机仍然是每个家庭不可或缺的电器之一。日常使用电视时,屏幕色彩暗淡,画面模糊抖动,除了要考虑电视自身质量问题,还要查看电视使用时长是否已经超出使用年限。超龄服役的电视机除了耗电量增加外,自燃或爆炸事故也时有发生。

  5. 热水器:热水器超出使用年限后,在运行时会出现异常声音,安全装置也会发生功能异常问题,再加上内胆中日积月累的杂质污垢,不仅会污染水质,还可能因漏电对人体造成伤害。除此之外,超龄热水器还易出现漏水、保温性差以及因内部电器元件老化导致的短路、冒烟等故障。

一旦发现家中电器存在以上类似的老化特征时,最好提前更换产品,以免带来严重后果。据媒体公开报道,每年我国因家电触电伤亡人数超过1000人,因家电引起的火灾损失更加惊人,而这其中最典型的原因就是家电超龄“使用”。

家用电器折旧

家用电器折旧可简单按固定资产折旧方法中的直线法,根据家用电器安全使用年限逐年折旧。

固定资产折旧方法

固定资产折旧方法(Fixed-assets Depreciation Method),指将应提折旧总额在固定资产各使用期间进行分配时所采用的具体计算方法。折旧是指固定资产由于使用而逐渐磨损所减少的那部分价值。

固定资产的损耗有两种:

  • 有形损耗,也称作物质磨损,是由于使用而发生的机械磨损,以及由于自然力的作用所引起的自然损耗。
  • 无形损耗,也称精神磨损,是指科学进步以及劳动生产率提高等原因而引起的固定资产价值的损失。

一般情况下,当计算固定资产折旧时,要同时考虑这两种损耗。

固定资产折旧方法可分为三类:

直线法

直线法(straight-line method)根据固定资产在整个使用寿命中的磨损状态而确定的成本分配结构。直线法依据是,固定资产的使用强度比较平均,而且各期所取得的收入差距不大。在直线法下,折旧金额是时间的线性函数。

直线法折旧公式如下:

年折旧率 = (1 - 预计净残值率)÷ 预计使用寿命(年)× 100%

月折旧额 = 固定资产原价× 年折旧率 ÷ 12

其中,净残值是指预计固定资产清理报废时可收回的残值扣除清理费用后的数额。企业应根据固定资产的性质和使用方式,合理估计固定资产的净残值。

加速折旧法

加速折旧法也称为快速折旧法或递减折旧法。其特点是:在固定资产有效使用年限的前期多提折旧,后期则少提折旧。从而相对加快折旧的速度,以使固定资产成本在有效使用年限中加快得到补偿。在具体实务中,加速折旧方法又包括年数总和法和双倍余额递减法两种。

年数总和法计算公式如下:

年折旧率 = 尚可使用寿命/ 预计使用寿命的年数总和 × 100 %

月折旧额 = (固定资产原价 - 预计净残值 )× 年折旧率 ÷ 12

某设备预计使用5年,则预计使用寿命的年数总和为15(5+4+3+2+1)。第2年时尚可使用寿命为4,此年的年折旧率为4/15。

双倍余额递减法计算公式如下:

年折旧率 =2÷ 预计使用寿命(年)× 100%

月折旧额 = 固定资产净值 × 年折旧率 ÷ 12

产量法

产量法(production method)根据固定资产的产出量分配其成本的方法。产量法的依据是固定资产的使用寿命主要是受其使用量影响,其合理性取决于三个条件:

(1)固定资产的每期用量波动较大;

(2)固定资产使用期内的产出的每期用量波动较大;

(3)固定资产服务潜力的下降与其使用程序密切相关。

如果符合这三个条件,产量法是最符合配比原则的。反对产量法的人认为,估计固定资产的产出量比估计固定资产的使用年限更加困难,而且很难考虑功能损耗因素。

产量法计算公式如下:

单位工作量折旧额 = 固定资产原价 × ( 1 - 预计净残值率 )/ 预计总工作量

某项固定资产月折旧额 = 该项固定资产当月工作量 × 单位工作量折旧额

参考链接

  1. 家用电器的使用年限是多久?如何尽可能延长其寿命?,by 海尔智慧生活.
  2. 固定资产折旧方法,by 百度百科.

空战类游戏仿真的一些思考

发表于 2018-12-08 | 更新于 2018-12-18

空战类游戏仿真涉及飞机、导弹、诱饵弹三种关键元素。为了使游戏仿真接近真实,一方面要使飞机、导弹、诱饵弹的模型及其特效(如尾焰)尽量逼真,另一方面要使飞机、导弹、诱饵弹的运动控制模型尽量接近真实。飞机、导弹、诱饵弹的模型可以用3d建模软件构建,尾焰也可以用粒子系统进行模拟,但飞机、导弹、诱饵弹的运动控制模型比较复杂,是实现空战类游戏仿真的关键。下面分别介绍飞机、导弹、诱饵弹的建模仿真。

飞机的建模仿真

飞机的运动模型基于牛顿第二运动定律,即物体所受到的外力等于此物体的质量与加速度的乘积,而加速度与外力同方向。根据外部受力和力矩计算出各种惯性坐标系下的加速度和角加速度。将加速度和角加速度分别进行积分,则可以得出飞机在某个时间段内的速度变化量和角速度变化量,进一步积分便可得到位置变化量和角度的变化量,再通过积分过程中的坐标变换以及初始时刻的状态参数,便可获得任意时刻飞机的姿态、位置、速度等参数。

飞行员通过油门杆和操纵杆控制飞机的运动。油门杆决定飞机的推力,操纵杆则控制飞机的副翼、襟翼、尾翼,改变飞机所受合力矩,从而改变飞机姿态。飞行仿真采用同样原理,油门杆和操作杆的位移经过非线性函数变换改变飞机所受合力和合力矩,经飞机运动模型获得加速度和角加速度,再经积分获得任意时刻飞机的姿态、位置、速度等参数。

当使用键盘输入控制飞机时,应将键盘输入先虚拟成油门杆和操作杆。另外需要注意的是,油门杆不回中,操作杆则自动回中。

导弹的建模仿真

根据导弹的工作原理,导弹的建模仿真应分成三个方面:

  • 探测模型
  • 目标识别算法
  • 运动控制模型

诱饵弹的建模仿真

诱饵弹的运动模型比较简单,可运用牛顿第二运动定律分析得出。比较有难度的是诱饵弹的视觉特效建模。诱饵弹是一个变质量、不规则的发光体,如何3D建模有难度,不能像太阳一样直接用图片代替。

参考链接

  1. 无人机飞控通俗演义之 纷繁复杂的飞行力学, by 量子黑洞.
  2. 一起写飞行仿真之 六自由度动力学方程, by 量子黑洞.
  3. 飞行仿真–1.三维建模篇, by WFYX.
  4. 无人机飞控通俗演义之 无人机导航制导与控制, by WFYX.
  5. FLIGHTGEAR FLIGHT SIMULATOR, by flightgear.

计算机视觉研究范畴简介

发表于 2018-12-07

计算机视觉是一个跨领域的交叉学科,包括计算机科学(图形、算法、理论、系统、体系结构),数学(信息检索、机器学习),工程学(机器人、语音、自然语言处理、图像处理),物理学(光学 ),生物学(神经科学)和心理学(认知科学)等等。那么什么是计算机视觉呢?这里给出了几个比较严谨的定义:

  1. “对图像中的客观对象构建明确而有意义的描述”(Ballard&Brown,1982)
  2. “从一个或多个数字图像中计算三维世界的特性”(Trucco&Verri,1998)
  3. “基于感知图像做出对客观对象和场景有用的决策”(Sockman&Shapiro,2001)

研究范畴

视觉识别是计算机视觉的关键组成部分,如图像分类、定位和检测。神经网络和深度学习的最新进展极大地推动了这些最先进的视觉识别系统的发展。下面介绍 5 种主要的计算机视觉技术:

  • 图像分类

给定一组各自被标记为单一类别的图像,我们对一组新的测试图像的类别进行预测,并测量预测的准确性结果,这就是图像分类问题。图像分类问题需要面临以下几个挑战:

视点变化,尺度变化,类内变化,图像变形,图像遮挡,照明条件和背景杂斑

  • 对象检测

识别图像中的对象这一任务,通常会涉及到为各个对象输出边界框和标签。这不同于分类/定位任务——对很多对象进行分类和定位,而不仅仅是对个主体对象进行分类和定位。在对象检测中,你只有 2 个对象分类类别,即对象边界框和非对象边界框。例如,在汽车检测中,你必须使用边界框检测所给定图像中的所有汽车。

  • 目标跟踪

目标跟踪,是指在特定场景跟踪某一个或多个特定感兴趣对象的过程。传统的应用就是视频和真实世界的交互,在检测到初始对象之后进行观察。现在,目标跟踪在无人驾驶领域也很重要,例如 Uber 和特斯拉等公司的无人驾驶。

  • 语义分割

计算机视觉的核心是分割,它将整个图像分成一个个像素组,然后对其进行标记和分类。特别地,语义分割试图在语义上理解图像中每个像素的角色(比如,识别它是汽车、摩托车还是其他的类别)。

  • 实例分割

除了语义分割之外,实例分割将不同类型的实例进行分类,比如用 5 种不同颜色来标记 5 辆汽车。分类任务通常来说就是识别出包含单个对象的图像是什么,但在分割实例时,我们需要执行更复杂的任务。我们会看到多个重叠物体和不同背景的复杂景象,我们不仅需要将这些不同的对象进行分类,而且还要确定对象的边界、差异和彼此之间的关系!

典型应用

计算机视觉领域已经衍生出了一大批快速成长的、有实际作用的应用,例如:

  • 人脸识别: Snapchat 和 Facebook 使用人脸检测算法来识别人脸。
  • 图像检索:Google Images 使用基于内容的查询来搜索相关图片,算法分析查询图像中的内容并根据最佳匹配内容返回结果。
  • 游戏和控制:使用立体视觉较为成功的游戏应用产品是:微软 Kinect。
  • 监测:用于监测可疑行为的监视摄像头遍布于各大公共场所中。
  • 生物识别技术:指纹、虹膜和人脸匹配仍然是生物识别领域的一些常用方法。
  • 智能汽车:计算机视觉仍然是检测交通标志、灯光和其他视觉特征的主要信息来源。

前沿研究

  • 超分辨率重建 (Image Super-Resolution)
  • 图像着色 (Image Colorization)
  • “看图说话” (Image Caption)
  • 人像复原 (Sketch Inversion)
  • 图像自动生成

参考文献

  1. 详解计算机视觉五大技术:图像分类、对象检测、目标跟踪、语义分割和实例分割…, by AI科技大本营
  2. 「无中生有」计算机视觉探奇, by 魏秀参

三维建模方法简介

发表于 2018-12-05 | 更新于 2022-12-19

三维建模是一种常用技术,奈何心向往之,却没有时间去系统学习,也没有做出过一个作品。下面将我看到的一些好的有关三维建模的资料记录一下,以做备忘。

三维建模方法

选择软件

当前三维软件层出不穷,既有商业级的3ds MAX、MAYA、Creator,也有免费使用的Blender、MilkShape。

下载蓝图

飞行仿真的三维模型主要有飞行器、机场建筑等。和大多数虚拟现实中使用的模型一样,并不需要CAD级别的精度,一般是下载一些图片或飞机整体蓝图作为蓝本,采用多边形建模的方法分部建模。蓝图下载网址首推:

the‑blueprints.com

这里免费提供各种汽车、国内外飞机、船舶的三视图图纸下载。

多边形建模

采用下载的蓝图,作为贴图放置在相应的投影平面上,然后采用多边形建模的方法画出各部分细节。多边形建模的思想就是采用一个诸如一个最接近的多边形,进行点线面的操作就可以绘制出复杂的飞机外形。

多边形建模从最基本的外形开始变形,可以从点线面及整体四个级别的操作,在越需要突出外形细节处用越多的点,通过建立网格模型,然后使用网格平滑功能生成平滑的曲面模型。

建模时不能有重复的点线面等几何体,否则即使表面上已经贴好了材质,但载入程序后,往往会因为Z向深度冲突的原因产生闪烁效果。其细节取决于您的需求,需要花费大量的时间。

贴图

真实世界的模型带有各种彩色并具有光泽度。完成了几何体的建模对于一个模型来说只完成了一小半工作,还需要给模型添加材质。

与一般的模型不同,飞行器出于气动设计的考虑,其表面模型一般成流线型的曲面,且部件组成复杂,界线较难区分,即使是UVW贴图也难以胜任。因此,对飞行器的贴图主要采用3ds MAX的UVW展开贴图技术贴图。

一个模型最好只有一个贴图,因为贴图数目过多零散会影响计算机载入三维模型时间和效率。因此,一般将整个模型各个部件组合为一个多边形,各部件为元素,待完成UVW贴图后再分离成单独的部件。UVW展开贴图有多重形式,如长方体展开(即按六个视图投影)、平面展开等,按需选择。

在一张贴图上展开整个模型的UV坐标显然是有限的,需要根据现实精度调整各个部分的贴图大小。保存这些展开的贴图坐标并渲染输出UV模板图像文件。UV模板图像其实就是整个模型的贴图的界线图像,通过Photoshop等图像处理软件处理,采用尽可能真实的图像放置在对应的区域。最后将材质赋给对象即完成贴图渲染。

数据导出

直接采用3ds MAX绘制的三维模型当然是.max格式,它不能为外界程序读取。这时就需要根据自己的开发环境选择导出的数据格式,比如用开源的OSG做仿真开发,就需要OSGExp插件的支持,导成.ive、.osg、.osgb等格式即可。但无论导出何种格式,切记保证模型质心与建模的原点不能相差不远,还要注意光照、贴图格式以及单位问题。

参考链接

  1. 飞行仿真–1.三维建模篇,by WFYX.
  2. 调整边缘画笔工具怎么用?,by zhihu.

深度强化学习研究笔记

发表于 2018-11-26 | 更新于 2022-04-16

深度强化学习Deep Reinforcement Learning是将深度学习与强化学习结合起来,从而实现从Perception感知到Action动作的端对端学习End-to-End Learning的一种全新的算法。深度强化学习具备使机器人实现真正完全自主地学习一种甚至多种技能的潜力。

深度强化学习的起源

深度强化学习是深度学习与强化学习相结合的产物。

深度学习

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

深度学习是机器学习中一种基于对数据进行表征学习的算法。观测值(例如一幅图像)可以使用多种方式来表示,如每个像素强度值的向量,或者更抽象地表示成一系列边、特定形状的区域等。而使用某些特定的表示方法更容易从实例中学习任务(例如,人脸识别或面部表情识别)。深度学习的好处是用非监督式或半监督式的特征学习和分层特征提取高效算法来替代手工获取特征。

表征学习的目标是寻求更好的表示方法并创建更好的模型来从大规模未标记数据中学习这些表示方法。表示方法来自神经科学,并松散地创建在类似神经系统中的信息处理和对通信模式的理解上,如神经编码,试图定义拉动神经元的反应之间的关系以及大脑中的神经元的电活动之间的关系。

至今已有数种深度学习框架,如深度神经网络、卷积神经网络和深度置信网络和递归神经网络已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

另外,“深度学习”已成为类似术语,或者说是神经网络的品牌重塑。

深度神经网络

深度神经网络是一种具备至少一个隐层的神经网络。与浅层神经网络类似,深度神经网络也能够为复杂非线性系统提供建模,但多出的层次为模型提供了更高的抽象层次,因而提高了模型的能力。

深度神经网络(Deep Neural Networks, DNN)是一种判别模型,可以使用反向传播算法进行训练。权重更新可以使用下式进行随机梯度下降法求解:

$$\Delta w_{ij}(t+1)=\Delta w_{ij}(t) + \eta\frac{\partial C}{\partial w_{ij}}$$

其中,$\eta$为学习率,$C$为代价函数。这一函数的选择与学习的类型(例如监督学习、无监督学习、增强学习)以及激活函数相关。例如,为了在一个多分类问题上进行监督学习,通常的选择是使用ReLU作为激活函数,而使用交叉熵作为代价函数。Softmax函数定义为${\displaystyle p_{j}={\frac {\exp(x_{j})}{\sum {k}\exp(x{k})}}}$,其中 ${\displaystyle p_{j}}$代表类别 ${\displaystyle j}$的概率,而 ${\displaystyle x_{j}}$和 ${\displaystyle x_{k}}$分别代表对单元 ${\displaystyle j}$ 和 ${\displaystyle k}$的输入。交叉熵定义为 $C = -\sum_j d_j \log(p_j)$ ,其中 ${\displaystyle d_{j}}$代表输出单元${\displaystyle j}$的目标概率, ${\displaystyle p_{j}}$代表应用了激活函数后对单元 ${\displaystyle j}$的概率输出。

强化学习

在人工智能领域,一般用智能体Agent表示一个具备行为能力的物体,比如机器人,无人车等等。而强化学习则研究智能体Agent和环境Environment之间交互过程如何取得任务的成功。

强化学习与环境的交互过程如图1所示。在某个时间点,智能体Agent会获得观察值(Observation)和反馈值(Reward),然后根据这些选择下一步的动作(Action)。

强化学习示意图

图1 强化学习示意图

在整个过程中,任务的目标是获取尽可能多的Reward,这是任务的目标。而在每个时间片,Agent都是根据当前的观察来确定下一步的动作。观察Observation的集合就作为Agent的所处的状态State,因此,状态State和动作Action存在映射关系,也就是一个state可以对应一个action,或者对应不同动作的概率(常常用概率来表示,概率最高的就是最值得执行的动作)。状态与动作的关系其实就是输入与输出的关系,而状态State到动作Action的过程就称之为一个策略Policy,一般用 $\pi$ 表示,也就是需要找到以下关系:
$$a=\pi(s)$$
或者
$$\pi(a|s)$$

其中a是action,s是state。第一种是一一对应的表示,第二种是概率的表示。

1
强化学习的任务就是找到一个最优的策略Policy从而使Reward最多。

强化学习的训练一开始从采用随机策略进行试验开始,可获得一系列的状态,动作和反馈:
$${s_1,a_1,r_1,s_2,a_2,r_2,…,s_t,a_t,r_t}$$
根据这一系列样本,强化学习从中改进策略,使得任务反馈Reward越来越多。

强化学习分类

在Model-free 算法里面,最为常见的分类方案是根据模型的表示方式来对算法进行分类。在这种分类方法中,RL算法可以划分为3个类别:

  • Critic-only,在Critic-only 类算法中,模型只有值评估函数。
  • Actor-only,在Actor-only类算法中,模型是通过一个策略函数 $\pi(a_t|s_t)$ 来表示
  • Actor-critic, 在Actor-critic 算法中,模型通过同时学习值评估函数以及策略函数一起强化算法。

强化学习分类

图2 强化学习分类

第二种分类方式是根据模型的学习特性来区分的,一般可以分为:

  • On-policy
  • Off-policy

强化学习分类

图3 强化学习分类

强化学习模型假设

强化学习的研究建立在经典物理学基础上,基于以下两种假设:

  1. 时间是可以分割成一个一个时间片的,并且有完全的先后顺序。
  2. 上帝不掷筛子!如果输入是确定的,那么输出也一定是确定的。

强化学习与马尔科夫决策过程

MDP基于这样一种假设:未来只取决于当前。

一个状态$S_t$是Markov当且仅当
$$P(s_{t+1}|s_t)=P(s_{t+1}|s_t,s_{t-1},…s_1,s_0)$$

P为概率。简单的说就是下一个状态仅取决于当前的状态和当前的动作。注意这里的状态是完全可观察的全部的环境状态(也就是上帝视角)。

增强学习的问题都可以模型化为MDP的问题。

一个基本的MDP可以用(S,A,P)来表示,S表示状态,A表示动作,P表示状态转移概率,也就是根据当前的状态$s_t$和$a_t$转移到$s_{t+1}$的概率。如果我们知道了转移概率P,也就是称为我们获得了模型Model,有了模型,未来就可以求解,那么获取最优的动作也就有可能,这种通过模型来获取最优动作的方法也就称为Model-based的方法。但是现实情况下,很多问题是很难得到准确的模型的,因此就有Model-free的方法来寻找最优的动作。

强化学习的回报Result

既然一个状态对应一个动作,或者动作的概率,而有了动作,下一个状态也就确定了。这就意味着每个状态可以用一个确定的值来进行描述。可以由此判断一个状态是好的状态还是不好的状态。

状态的好坏其实等价于对未来回报的期望。因此,引入回报Return来表示某个时刻t的状态将具备的回报:

$$G_t = R_{t+1} + \lambda R_{t+2} + … = \sum_{k=0}^\infty\lambda^kR_{t+k+1}$$

上面R是Reward反馈,λ是discount factor折扣因子,一般小于1,就是说一般当下的反馈是比较重要的,时间越久,影响越小。

那么实际上除非整个过程结束,否则显然我们无法获取所有的reward来计算出每个状态的Return,因此,再引入一个概念价值函数Value Function,用value function $v(s)$来表示一个状态未来的潜在价值。

从定义上看,value function就是回报的期望:
$$v(s) = \mathbb E[G_t|S_t = s]
$$

引出价值函数,对于获取最优的策略Policy这个目标,我们就会有两种方法:

  • 直接优化策略$\pi(a|s)$或者$a = \pi(s)$使得回报更高
  • 通过估计value function来间接获得优化的策略。道理很简单,既然我知道每一种状态的优劣,那么我就知道我应该怎么选择了,而这种选择就是我们想要的策略。

把值函数展开:

$$\begin{aligned}
v(s) & = \mathbb E[G_t|S_t = s] \\
& = \mathbb E[R_{t+1}+\lambda R_{t+2} + \lambda ^2R_{t+3} + …|S_t = s] \\
& = \mathbb E[R_{t+1}+\lambda (R_{t+2} + \lambda R_{t+3} + …)|S_t = s] \\
& = \mathbb E[R_{t+1} + \lambda G_{t+1}|S_t = s] \\
& = \mathbb E[R_{t+1} + \lambda v(S_{t+1})|S_t = s]
\end{aligned}
$$

因此:

$$v(s) = \mathbb E[R_{t+1} + \lambda v(S_{t+1})|S_t = s]$$

上面这个公式就是Bellman方程的基本形态。从公式上看,当前状态的价值和下一步的价值以及当前的反馈Reward有关。它表明Value Function是可以通过迭代来进行计算的!!!

Action-Value function 动作价值函数

前面我们引出了价值函数,考虑到每个状态之后都有多种动作可以选择,每个动作之下的状态又多不一样,我们更关心在某个状态下的不同动作的价值。显然。如果知道了每个动作的价值,那么就可以选择价值最大的一个动作去执行了。这就是Action-Value function $Q^\pi(s,a)$。那么同样的道理,也是使用reward来表示,只是这里的reward和之前的reward不一样,这里是执行完动作action之后得到的reward,之前state对应的reward则是多种动作对应的reward的期望值。显然,动作之后的reward更容易理解。

动作价值函数就为如下表示:
$$\begin{aligned}
Q^\pi(s,a) & = \mathbb E[r_{t+1} + \lambda r_{t+2} + \lambda^2r_{t+3} + … |s,a] \\
& = \mathbb E_{s^\prime}[r+\lambda Q^\pi(s^\prime,a^\prime)|s,a]
\end{aligned}$$

这里要说明的是动作价值函数的定义,加了$\pi$,也就是说是在策略下的动作价值。因为对于每一个动作而已,都需要由策略根据当前的状态生成,因此必须有策略的支撑。而前面的价值函数则不一定依赖于策略。当然,如果定义$v^\pi(s)$则表示在策略$\pi$下的价值。

Optimal value function 最优价值函数

能计算动作价值函数是不够的,因为我们需要的是最优策略,现在求解最优策略等价于求解最优的value function,找到了最优的value function,自然而然策略也就是找到。(当然,这只是求解最优策略的一种方法,也就是value-based approach,由于DQN就是value-based,因此这里只讲这部分,以后我们会看到还有policy-based和model-based方法。一个就是直接计算策略函数,一个是估计模型,也就是计算出状态转移函数,从而整个MDP过程得解)

这里以动作价值函数来分析。

首先是最优动作价值函数和一般的动作价值函数的关系:

$$\begin{aligned}
Q^(s,a) &= \max_\pi Q^\pi(s,a)\\
& = \mathbb E_{s^\prime}[r+\lambda \max _{a^\prime}Q^
(s^\prime,a^\prime)|s,a]
\end{aligned}
$$

也就是最优的动作价值函数就是所有策略下的动作价值函数的最大值。通过这样的定义就可以使最优的动作价值的唯一性,从而可以求解整个MDP。

下面介绍基于Bellman方程的两个最基本的算法,策略迭代和值迭代。

策略迭代Policy Iteration

Policy Iteration的目的是通过迭代计算value function 价值函数的方式来使policy收敛到最优。

Policy Iteration本质上就是直接使用Bellman方程而得到的:

$$
\begin{aligned}
v_{k+1}(s) &\overset{.}{=} \mathbb E_{\pi}[R_{t+1}+\gamma v {k}(S{t+1})|S_t=s]\\
&=\sum_{a}{\pi(a|s)}\sum_{s^\prime,r}{p(s^\prime,r|s,a)[r+\gamma v_k(s^\prime)]}
\end{aligned}
$$

那么Policy Iteration一般分成两步:

  1. Policy Evaluation 策略评估。目的是更新Value Function,或者说更好的估计基于当前策略的价值
  2. Policy Improvement 策略改进。 使用 greedy policy 产生新的样本用于第一步的策略评估。

策略迭代算法示意图

图4 策略迭代算法示意图

本质上就是使用当前策略产生新的样本,然后使用新的样本更好的估计策略的价值,然后利用策略的价值更新策略,然后不断反复。理论可以证明最终策略将收敛到最优。

具体算法:

策略迭代算法

图5 策略迭代算法

那么这里要注意的是policy evaluation部分。这里的迭代很重要的一点是需要知道state状态转移概率p。也就是说依赖于model模型。而且按照算法要反复迭代直到收敛为止。所以一般需要做限制。比如到某一个比率或者次数就停止迭代。那么需要特别说明的是不管是策略迭代还是值迭代都是在理想化的情况下(上帝视角)推导出来的算法,本质上并不能直接应用,因为依赖Model。

Value Iteration 价值迭代

Value Iteration则是使用Bellman 最优方程得到:
$$
\begin{aligned}
v_{}(s) & = \max_{a} \mathbb E_{\pi}[R_{t+1}+\gamma v _{}(S_{t+1})|S_t=s,A_t=a]\\
& = \max_{a} \sum_{s^\prime,r}p(s^\prime,r|s,a)[r+\gamma v_*(s^\prime)]
\end{aligned}
$$

然后改变成迭代形式:

$$
\begin{aligned}
v_{k+1}(s) &\overset{.}{=} \max_{a} \mathbb E_{\pi}[R_{t+1}+\gamma v {k}(S{t+1})|S_t=s,A_t=a]\\
& = \max_{a} \sum_{s^\prime,r}p(s^\prime,r|s,a)[r+\gamma v_k(s^\prime)]
\end{aligned}
$$

value iteration的算法如下:

值迭代算法

图6 值迭代算法

Policy Iteration和Value Iteration有什么本质区别?

policy iteration使用bellman方程来更新value,最后收敛的value 即$v_\pi$是当前policy下的value值(所以叫做对policy进行评估),目的是为了后面的policy improvement得到新的policy。

而value iteration是使用bellman 最优方程来更新value,最后收敛得到的value即$v_*$就是当前state状态下的最优的value值。因此,只要最后收敛,那么最优的policy也就得到的。因此这个方法是基于更新value的,所以叫value iteration。

从上面的分析看,value iteration较之policy iteration更直接。不过问题也都是一样,需要知道状态转移函数p才能计算。本质上依赖于模型,而且理想条件下需要遍历所有的状态,这在稍微复杂一点的问题上就基本不可能了。

Q-Learning

Q Learning的思想完全根据value iteration得到。但要明确一点是value iteration每次都对所有的Q值更新一遍,也就是所有的状态和动作。但事实上在实际情况下我们没办法遍历所有的状态,还有所有的动作,我们只能得到有限的系列样本。因此,只能使用有限的样本进行操作。那么,怎么处理?Q Learning提出了一种更新Q值的办法:

$$Q(S_{t},A_{t}) \leftarrow Q(S_{t},A_{t})+\alpha({R_{t+1}+\lambda \max aQ(S{t+1},a)} - Q(S_t,A_t))$$

虽然根据value iteration计算出target Q值,但是这里并没有直接将这个Q值(是估计值)直接赋予新的Q,而是采用渐进的方式类似梯度下降,朝target迈近一小步,取决于α,这就能够减少估计误差造成的影响。类似随机梯度下降,最后可以收敛到最优的Q值。

具体的算法如下:

Q学习算法

图7 Q学习算法

Exploration and Exploitation 探索与利用

回到policy的问题,那么要选择怎样的policy来生成action呢?有两种做法:

  • 随机的生成一个动作

  • 根据当前的Q值计算出一个最优的动作,这个policy\pi称之为greedy policy贪婪策略。也就是

$$\pi(S_{t+1}) = arg\max aQ(S{t+1},a)$$

使用随机的动作就是exploration,也就是探索未知的动作会产生的效果,有利于更新Q值,获得更好的policy。而使用greedy policy也就是target policy则是exploitation,利用policy,这个相对来说就不好更新出更好的Q值,但可以得到更好的测试效果用于判断算法是否有效。

将两者结合起来就是所谓的$\epsilon-greedy$策略,$\epsilon$一般是一个很小的值,作为选取随机动作的概率值。可以更改$\epsilon$的值从而得到不同的exploration和exploitation的比例。

这里需要说明的一点是使用$\epsilon-greedy$策略是一种极其简单粗暴的方法,对于一些复杂的任务采用这种方法来探索未知空间是不可取的。因此,最近有越来越多的方法来改进这种探索机制。

深度强化学习

深度强化学习始于DeepMind在NIPS 2013上发表的Playing Atari with Deep Reinforcement Learning一文,在该文中第一次提出Deep Reinforcement Learning 这个名称,并且提出DQN(Deep Q-Network)算法,实现从纯图像输入完全通过学习来玩Atari游戏的成果。

之后DeepMind在Nature上发表了改进版的DQN文章Human-level Control through Deep Reinforcement Learning,引起了广泛的关注,Deep Reinfocement Learning 从此成为深度学习领域的前沿研究方向。

维度灾难

对简单问题可使用表格来表示Q(s,a),但是这个在现实的很多问题上是几乎不可行的,因为状态实在是太多。使用表格的方式根本存不下。

以计算机玩Atari游戏为例,计算机玩Atari游戏的要求是输入原始图像数据,也就是210x160像素的图片,然后输出几个按键动作。总之就是和人类的要求一样,纯视觉输入,然后让计算机自己玩游戏。那么这种情况下,到底有多少种状态呢?有可能每一秒钟的状态都不一样。因为,从理论上看,如果每一个像素都有256种选择,那么就有:
$$
256^{210\times 160}
$$

这简直是天文数字。所以,我们是不可能通过表格来存储状态的。我们有必要对状态的维度进行压缩,解决办法就是 价值函数近似Value Function Approximation

价值函数近似Value Function Approximation

什么是价值函数近似呢?说起来很简单,就是用一个函数来表示Q(s,a)。即
$$Q(s,a) = f(s,a)$$

$f$可以是任意类型的函数,比如线性函数:

$$Q(s,a) = w_1s + w_2a + b$$

其中$w_1$,$w_2$,$b$是函数$f$的参数。

通过函数表示,我们就可以无所谓s到底是多大的维度,反正最后都通过矩阵运算降维输出为单值的Q。

这就是价值函数近似的基本思路。

如果我们就用$w$来统一表示函数$f$的参数,那么就有

$$Q(s,a) = f(s,a,w)$$

为什么叫近似,因为我们并不知道Q值的实际分布情况,本质上就是用一个函数来近似Q值的分布,所以,也可以说是

$$Q(s,a)\approx f(s,a,w)$$

Q值神经网络化——DQN算法

意思很清楚,就是我们用一个深度神经网络来表示这个函数$f$。

以DQN为例,输入是经过处理的4个连续的84x84图像,然后经过两个卷积层,两个全连接层,最后输出包含每一个动作Q值的向量。

神经网络的训练是一个最优化问题,最优化一个损失函数loss function,也就是标签和网络输出的偏差,目标是让损失函数最小化。为此,我们需要有样本,巨量的有标签数据,然后通过反向传播使用梯度下降的方法来更新神经网络的参数。

如何为Q网络提供有标签的样本?答案就是利用Q-Learning算法。目标Q值作为标签,使Q值趋近于目标Q值。于是Q网络训练的损失函数就是:

DQN损失函数

图8 DQN损失函数

上面公式是$s^\prime$, $a^\prime$即下一个状态和动作。这里用了David Silver的表示方式,看起来比较清晰。
既然确定了损失函数,也就是cost,确定了获取样本的方式。那么DQN的整个算法也就成型了!

这里分析第一个版本的DQN,也就是NIPS 2013提出的DQN。

DQN算法

图9 DQN算法

具体的算法主要涉及到Experience Replay,也就是经验池的技巧,就是如何存储样本及采样问题。

由于玩Atari采集的样本是一个时间序列,样本之间具有连续性,如果每次得到样本就更新Q值,受样本分布影响,效果会不好。因此,一个很直接的想法就是把样本先存起来,然后随机采样如何?这就是Experience Replay的意思。按照脑科学的观点,人的大脑也具有这样的机制,就是在回忆中学习。

那么上面的算法看起来那么长,其实就是反复试验,然后存储数据。接下来数据存到一定程度,就每次随机采用数据,进行梯度下降!

DQN的三大改进方法

大幅度提升DQN玩Atari性能的主要就是Double DQN,Prioritised Replay还有Dueling Network三大方法。

  • Double DQN:目的是减少因为max Q值计算带来的计算偏差,或者称为过度估计(over estimation)问题,用当前的Q网络来选择动作,用目标Q网络来计算目标Q。
  • Prioritised replay:也就是优先经验的意思。优先级采用目标Q值与当前Q值的差值来表示。优先级高,那么采样的概率就高。
  • Dueling Network:将Q网络分成两个通道,一个输出V,一个输出A,最后再合起来得到Q。如下图所示(引用自Dueling Network论文)。这个方法主要是idea很简单但是很难想到,然后效果一级棒,因此也成为了ICML的best paper。

策略梯度

Policy Gradient的方法的基本思想是通过评价动作action的好坏,来调整该action的出现概率。最基本的Policy Gradient的损失函数Loss就是:

$$loss = -log(\pi)*Q$$

这里先以Q值来指代对动作的评价。

Robot Learning的发展路径

Robot Learning从目前来看,经过了以下研究思路的发展:

(1)利用传统的控制算法结合深度学习来实现机器人端到端的控制。这个方法主要是以Guided Policy Search(GPS)为首。这个方法是Sergey Levine提出的,通过与传统方法结合,确实可以让机器人学习出一些有意思的技能,但是有个根本问题摆在面前,就是传统方法通常需要知道整个系统的模型,而这在实际的机器人中非常难以适用。就比如四轴飞行器的控制,我们可以通过外部的Vicon设备来精确的定位四轴飞行器的位置,从而实现对其精确控制,但是在户外,我们根本就做不到这点,也就无法精确建模。因此,还依赖传统方法是没有出路的,我们使用深度学习就是要抛弃传统方法的弊端。

(2)深度增强学习DRL。由于DeepMind在DRL取得了巨大成功,而DRL就是面向决策与控制问题,特别适用于机器人,因此想在机器人上使用DRL是一种必然的想法。Google Brain团队(依然以Sergey Levine为首)做出了一些进展,在我们之前的专栏文章中也有分析最前沿 之 谷歌的协作机械臂 - 知乎专栏 。但是在使用DRL之后,DRL的弊端也就显现出来了,那就是需要大量的尝试来获取数据。对于这个问题,在机器人仿真环境还好,但是在真实的机器人上就根本没办法这么做了。为了解决这个问题,也就引出来下面两个研究思路。

(3)迁移学习Transfer Learning。既然在真实环境不行,而仿真环境可以,那么是不是可以先在仿真环境中训练好,再把知识迁移到真实机器人上。Google Deepmind在这一块做了一些不错的工作,提出了Progressive Neural Net和PathNet,验证了迁移的可能性。而且很显然的,仿真环境越真实,迁移效果会越好。那么,搞一个非常仿真的环境就非常有意义了。这不,Nvidia 刚刚推出Isaac机器人模拟系统,确实是对Robot Learning的研究注入了一剂强心剂。

(4)Imitation Learning 模仿学习/Few Shot Learning 少样本学习/ Meta Learning 学会学习。这是另一条思路,那就是尽量减少数据的使用量。我们如果能够教机器人几次机器人就能学会技能那么问题也能解决。而这一块也就是OpenAI (依然是Sergey Levine)那帮人在如火如荼的研究的方向。而且特别是Meta Learning,直指通用人工智能的核心。如果能够在Meta Learning上取得突破,那么本身会是革命性的。

因此,Robot Learning发展到这里,把研究的方向就聚焦到第三和第四点上了,并且也取得了一定的成果,但是显然还有非常多的工作可以去做。

参考链接

  1. 深度学习, by wikipedia.
  2. DQN 从入门到放弃1 DQN与增强学习, by Flood Sung.
  3. DQN 从入门到放弃2 增强学习与MDP, by Flood Sung.
  4. DQN 从入门到放弃3 价值函数与Bellman方程, by Flood Sung.
  5. DQN 从入门到放弃4 动态规划与Q-Learning,by Flood Sung.
  6. DQN从入门到放弃5 深度解读DQN算法, by Flood Sung.
  7. DQN从入门到放弃6 DQN的各种改进, by Flood Sung.
  8. DQN从入门到放弃7 连续控制DQN算法-NAF,by Flood Sung.
  9. 最前沿:机器人学习Robot Learning的发展,by Flood Sung.
  10. 简单的交叉熵损失函数,你真的懂了吗?,by 红色石头.
  11. Markov decision process,by wikipedia.
  12. openai spinningup,by LJ147.
  13. 深度强化学习发展史,by JQWang2048.
  14. 强化学习简介 (Introduction of Reinforcement Learning),by 范叶亮.
  15. 【写在复现之前】强化学习常用算法分类,by Firework.
  16. 强化学习中无处不在的贝尔曼最优性方程,背后的数学原理知多少?,by 亚希伯恩•菲.
  17. DQN从入门到放弃6 DQN的各种改进,by Flood Sung.
  18. Dueling DQN,by 小小何先生.
  19. 强化学习笔记(六)- 策略梯度,by Hazza Cheng.
  20. 目前,人工智能各个流派发展现状如何?,by zhihu.

wiringPi学习笔记

发表于 2018-11-24 | 更新于 2018-12-21

wiringPi 库是由 Gordon Henderson 所编写并维护的一个用 C 语言写成的类库。起初,主要是作为 BCM2835 芯片的 GPIO 库。而现在,已经非常丰富,除了 GPIO 库,还包括了I2C 库、SPI 库、UART 库和软件 PWM 库等。

由于其与 Arduino 的“wiring”系统较为类似,故以此命名。它是采用 GNU LGPLv3许可证的,可以在 C 或 C++上使用,而且在其他编程语言上也有对应的扩展。

wiringPi 库包含了一个命令行工具 gpio,它可以用来设置 GPIO 管脚,可以用来读写GPIO 管脚,甚至可以在 Shell 脚本中使用来达到控制 GPIO 管脚的目的。

下载、编译和测试wiringPi

  1. 下载并编译wiringPi
    1
    2
    3
    git clone git://git.drogon.net/wiringPi
    cd wiringPi
    ./build
  2. 测试wiringPi是否安装成功
    打开命令终端,可以通过 gpio 命令来检查 wiringPi 是否安装成功,运行下面的命令:
    1
    2
    gpio –v
    gpio readall
    运行上述第二条命令将得到树莓派的 GPIO 接口之间的对应关系。

gpio管脚定义

使用wiringPi

在使用wiringPi之前,应首先对wiringPi进行设置。

wiringPi设置函数

wiringPi设置函数如下:

1
2
3
4
int wiringPiSetup (void) ;
int wiringPiSetupGpio (void) ;
int wiringPiSetupPhys (void) ;
int wiringPiSetupSys (void) ;

wiringPiSetup (void) 函数

该函数初始化wiringPi,假定程序将使用wiringPi的管脚定义图。具体管脚映射,可以通过gpio readall命令来查看。该函数需要root权限。

wiringPiSetupGpio (void) 函数

该函数与wiringPiSetup函数类似,区别在于假定程序使用的是Broadcom的GPIO管脚定义,而没有重新映射。该函数需要root权限,需要注意v1和v2版本的树莓派是不同的。

wiringPiSetupPhys (void) 函数

该函数与wiringPiSetup函数类似,区别在于允许程序使用物理管脚定义,但仅支持P1接口。该函数需要root权限。

wiringPiSetupSys (void) 函数

该函数初始化wiringPi,使用/sys/class/gpio接口,而不是直接通过操作硬件来实现。该函数可以使用非root权限用户,在此种模式下的管脚号是Broadcom的GPIO管脚号,不wiringPiSetupGpio函数类似,需要注意v1和v2板子的不同。

在此种模式下,在运行程序前,您需要通过/sys/class/gpio接口导出要使用的管脚。你可以在一个独立的shell脚本中来导出将要使用的管脚,或者使用系统的system()函数来调用GPIO命令。

软件 PWM 库

wiringPi 中包含了一个软件驱动的 PWM (Pulse Width Modulation, 脉冲宽度调节)处理库,可以在任意的树莓派 GPIO 上输出 PWM 信号。

但是也有一些限制。为了维护较低的 CPU 使用率,最小的脉冲宽度是 100 微秒,结合默认的建议值为 100,那么最小的 PWM 频率是 100Hz。如果需要更高的频率,可以使用更低的数值。如果看脉冲宽度的驱动代码,你会发现低于 100 微秒,wiringPi 是在软件循环中实现的,这就意味着 CPU 使用率将会动态增加,从而使得控制其他管脚成为不可能。

需要注意的是,当其他程序运行在更高的实时的优先级,Linux 可能会影响产生信号的精度。尽管有这些限制,控制 LED 或电机还是可以的。

使用前,需要包含相应的文件:

1
2
#include <wiringPi.h>
#include <softPwm.h>

当编译程序时,必须加上 pthread 库,如下:

1
gcc –o myprog myprog.c –lwiringPi –lpthread

必须使用 wiringPiSetup()、 wiringPiSetupGpio()或者 wiringPiSetupPhys()函数来初始化 wiringPi。

wiringPiSetupSys()是不够快的,因此,必须使用 sudo 命令来运行程序。

softPwmCreate 函数

该函数的原型为:int softPwmCreate(int pin, int initialValue, int pwmRange);

该函数将会创建一个软件控制的 PWM 管脚。可以使用任何一个 GPIO 管脚 , pwmRange 参数可以为 0(关)~100(全开)。

返回值为 0,代表成功,其他值,代表失败。

softPwmWrite 函数

该函数的原型为: void softPwmWrite(int pin, int value);

该函数将会更新指定管脚的 PWM 值。value 参数的范围将会被检查,如果指定的管脚之前没有通过 softPwmCreate 初始化,将会被忽略。

wiringPi核心函数

pinMode函数

该函数的原型为: void pinMode(int pin, int mode);

使用该函数可以将某个管脚讴置为 INPUT(输入)、 OUTPUT(输出)、 PWM_OUTPUT(脉冲输出)或者 GPIO_CLOCK(GPIO 时钟)。

需要注意的是仅有管脚 1(BCM_GPIO 18)支持 PWM_OUTPUT 模式,仅有管脚 7(BCM_GPIO 4)支持 CLOCK 输出模式。

在 Sys 模式下,返个函数没有影响。你可以通过调用 gpio 命令在 shell 脚本中来设置管脚的模式。

digitalWrite 函数

该函数的原型为: void digitalWrite(int pin, int value);

使用该函数可以向指定的管脚写入 HIGH(高)或者 LOW(低),写入前,需要将管脚设置为输出模式。

wiringPi 将任何的非 0 值作为 HIGH (高)来对待,因此, 0 是唯一能够代表 LOW (低)的数值。

digitalRead 函数

该函数原型: digitalRead(int pin);

使用该函数可以读取指定管脚的值,读取到的值为HIGH(1)或者LOW(0),该值取决于该管脚的逻辑电平的高低。

时间函数

delay 函数

该函数的原型为:void delay(unsigned int howLong);

该函数将会中断程序执行至少 howLong 毫秒。因为 Linux 是多任务的原因,中断时间可能会更长。需要注意的是,最长的延迟值是一个无符号 32 位整数,其大约为 49 天。

delayMicroseconds 函数

该函数的原型为:void delayMicroseconds(unsigned int howLong);

该函数将会中断程序执行至少 howLong 微秒。因为 Linux 是一个多任务的系统,因此中断时间可能会更长。需要注意的是,最长的延迟值是一个无符号 32 位整数,其大约为 71分钟。

延迟低于100 微秒,将会使用硬件循环来实现;超过 100 微秒,将会使用系统的nanosleep()函数来实现。

优先级/时间/线程

wiringPiISR 函数

该函数的原型为:int wiringPiISR(int pin, int edgeType, void (*function)(void));

该函数会在指定管脚注册一个中断事件的函数,当指定管脚发生中断事件时,会自动调用该函数。

edgeType 参数可以为 INT_EDGE_FALLING(下降沿)、INT_EDGE_RISING(上升沿)、INT_EDGE_BOTH(上升沿或者下降沿)或者 INT_EDGE_SETUP。如果是INT_EDGE_SETUP,将不会初始化该管脚,因为它假定已经在别处设置过该管脚(比如使用 gpio 命令),但是,如果指定另外的类型,指定管脚将会被导出并初始化。完成此操作使用的是 gpio 命令,所以,必须保证 gpio 命令是可用的。

注册函数在中断触发时,将会被调用。在调用注册函数前,中断事件将会从分配器中清除,所以,即使有后续的触发发生,在处理完成前,也不会错过此次触发。(当然,如果在正在处理触发时,有不止一个的中断发生,已经发生的中断将会被忽略)。

I2C库

wiringPi 包含了一个 I2C 库,来让您能够更轻松的使用树莓派的板上 I2C 接口。在使用 I2C 接口之前,您可能需要使用 gpio 命令来加载 I2C 驱劢到内核中:

1
gpio load i2c

如果你需要的波特率是 100Kbps,那么您可以使用如下命令设置波特率为1000Kbps:

1
gpio load i2c 1000

使用 I2C 库,需要包含 wiringPiI2C.h 文件。并且编译时,同样需要使用-lwiringPi 来连接到 wiringPi 库。

您仍然可以使用标准的系统命令来检测 I2C 设备,如 i2cdetect 命令,需要注意的是,在 v1 版本的树莓派上是 0,v2 版本上是 1,如下:

1
2
3
ls /dev/i2c-1
# 注意i2c-1后面的编码1
i2cdetect –y 1

当然,您也可以使用 gpio 命令来调用 i2cdetect 命令,从而检测 I2C 讴备,返样就不用在乎您的树莓派版本了,如下:

1
gpio i2cdetect

wiringPiI2CSetup 函数

该函数的原型为:int wiringPiI2CSetup(int devId);

该函数使用指定设备标示号来初始化 I2C 系统。参数 devId 是 I2C 设备的地址,可以通过 i2cdetect 命令可以查到该地址。该函数会获取树莓派的版本并依据此打开/dev 目录下对应的讴备。

返回值是标准的 Linux 文件句柄,如果有错误,则返回-1。

比如,流行的 MCP23017 GPIO 扩展器的设备 ID 是 0x20,所以,你需要将这个数值传递给 wiringPiI2CSetup()。

wiringPiI2CWrite 函数

该函数的原型为:int wiringPiI2CWrite(int fd, int data);

简单的设备写操作。一些设备可以接受数据,而不需要发送任何内部寄存器地址。

wiringPiI2CRead 函数

该函数的原型为:int wiringPiI2CRead(int fd);

简单的设备读操作。一些设备可以直接读取,而不需要发送任何寄存器地址。

wiringPiI2CWriteReg8 和 wiringPiI2CWriteReg16 函数

该函数的原型为:

int wiringPiI2CWriteReg8(int fd, int reg, int data); int wiringPiI2CWriteReg16(int fd, int reg, int data);

使用返两个函数,可以写一个 8 位或 16 位数值到指定的设备寄存器。

wiringPiI2CReadReg8 和 wiringPiI2CReadReg16 函数

该函数的原型为:

int wiringPiI2CReadReg8(int fd, int reg); int wiringPiI2CReadReg16(int fd, int reg);

使用返两个函数,可以从指定的设备寄存器读取一个 8 位或 16 位的数值。

参考链接

  1. 树莓派 wiringPi 用户手册 , by 科技爱好者博客
  2. Wiring Pi
  3. Pthreads 入门教程,by hanbingyan.

人工智能——人类科技再次飞跃的门槛

发表于 2018-11-21 | 更新于 2019-01-17

人工智能的研究历史有着一条从以“推理”为重点,到以“知识”为重点,再到以“学习”为重点的自然、清晰的脉络。机器学习则是实现人工智能的一个途径,即以机器学习为手段解决人工智能中的问题。

问题的提出

问题的分析

解决方案

总结

参考文献

  1. 机器学习, by wikipedia.
上一页1…464748…53下一页

Jack Huang

523 日志
67 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse