Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
应用背景
请参考背景.
应用需求
请参考需求.
Dubbo架构
请参考架构.
服务配置
请参考应用.
参考链接
- Apache Dubbo,by apache.
在今天全球强调科研创新的年代,为何科学的进步与上个世纪相比,却明显进步缓慢呢?也许有人反驳,当今庞大的科研人员,层出不穷的科研成果,极大的物质财富,难道不是科学技术的进步带来的吗?与上个世纪相比,哪里进步缓慢了呢?诚然,当前科技在进步在繁荣,但这种进步繁荣是应用科学的繁荣,而不是基础科学的繁荣。如果将科学比作一棵大树,那么基础科学就是树干,枝干和树叶就是应用科学。树干的粗细决定了树枝和树叶的繁荣,不幸的是,当前基础科学已经很久没有大的进步了。基础科学的进步靠牛顿、麦克斯韦、爱因斯坦这样的天才,而应用科学的进步则靠广大的普通科研人员。那么作为一名普通的从事应用科学研究的科研人员,如何才能有所创新有所进步呢?
作为一名普通的科研人员,可能经常会有一闪而过的灵光。然而要将这一闪而过的灵光变成切实可行的创新是一个痛苦的过程。这一闪而过的灵光可能涉及很多学科知识,而大部分科研人员不是全才,可能仅在某一方面有过人之处,那么如何试验验证这一灵光就成了大难题。幸运的是,有了Matlab及其推广的基于模型的设计思想,未来应用科学方面的科研创新将不再困难。
有人说,Matlab除了不会生孩子,其他都能干。诚然,Matlab就是广大科研人员的神兵利器。Matlab或许比不上某些领域的专业软件,但胜在全面,该有的都有。科研人员只需掌握它,就可解决至少80%的问题,极大地提高科研效率。
最近在研究各种控制算法,需要安装树莓派和PX4的硬件支持包,发现最新的Matlab 2019b安装PX4硬件支持包比较方便,但无法安装树莓派硬件支持包,而Matlab 2018b则没有这样的问题。
Matlab 2019b无法下载树莓派硬件支持包的问题,可通过Matlab官方提供的下载工具解决,下载地址为Download Hardware Support Packages and Optional Features。
基于模型的设计(Model-Based Design,简称MBD)是一种数学及可视化的方法,可以用来处理复杂控制系统、信号处理及通讯系统的设计。基于模型的设计可以用在运动控制、工业设计、航天以及车辆应用中。基于模型的设计也是嵌入式系统设计的方法论。
基于模型的设计类似于基于组件的图形用户界面开发,可极大地提高开发的效率,并保证程序的健壮性。
基于模型的设计是一种较有效率的设计方式,在支援开发过程(V模型)的同时,在设计过程中建立了沟通用的共同框架。若用这种方式设计控制系统,开发会分为以下四步骤:
基于模型的设计和传统的设计方法论有很大的不同。设计者在使用基于模型的设计时,不需使用复杂的架构以及繁多的软件代码,只需利用基于模型的设计来定义系统模型,再配合连续及离散的架构方块来产生进阶的机能特性。使用仿真工具建立的模型可以进行快速应用程序开发、软件测试和验证。不但强化了测试以及验证的程序。有些情形下,可以将这个新的设计方法配合硬件在环的仿真,测试系统的动态效应,不但速度更快,也比传统的设计方法论更加有效率。
基于模型设计的主要步骤如下:
基于模型的设计相较于传统开发方式的优点有:
支持MBD开发的工具主要有:
使用强化学习实现机器人的连续控制,策略梯度方法是首选。下面即对强化学习中策略梯度方法进行总结。
不同强化学习算法最重要的区分点之一就是智能体是否能完整了解或学习到所在环境的模型。 环境的模型是指一个预测状态转换和奖励的函数。
有模型学习最大的优势在于智能体能够 提前考虑来进行规划,走到每一步的时候,都提前尝试未来可能的选择,然后明确地从这些候选项中进行选择。智能体可以把预先规划的结果提取为学习策略。这其中最著名的例子就是 AlphaZero。这个方法起作用的时候,可以大幅度提升采样效率 —— 相对于那些没有模型的方法。
有模型学习最大的缺点就是智能体往往不能获得环境的真实模型。如果智能体想在一个场景下使用模型,那它必须完全从经验中学习,这会带来很多挑战。最大的挑战就是,智能体探索出来的模型和真实模型之间存在误差,而这种误差会导致智能体在学习到的模型中表现很好,但在真实的环境中表现得不好(甚至很差)。基于模型的学习从根本上讲是非常困难的,即使你愿意花费大量的时间和计算力,最终的结果也可能达不到预期的效果。
使用模型的算法叫做有模型学习,不基于模型的叫做免模型学习。虽然免模型学习放弃了有模型学习在样本效率方面的潜在收益,但是他们往往更加易于实现和调整。
异策略(off-policy)的代表算法Q-learning,亦称SarasMax,其采样的策略(用于执行,behavior policy) 和更新Q值的策略(用于评估,target policy)不一样,行为策略为贪心策略,而target policy为确定性策略,即选择最Q值最优的action。
同策略(on-policy)的代表算法Sarsa,亦称on-line Q-learning,其采样的策略(用于执行,behavior policy) 和更新Q值的策略(用于评估,target policy)一样,行为策略和目标策略均为贪心策略。Sarsa的每次Q值更新需要知道前一步的状态(state)、前一步的动作(action)、奖赏值(reward)、当前状态(state)、将要执行的动作(action),由此得名Sarsa算法。
在计算机科学中,在线机器学习是一种机器学习的方法,其中数据按顺序可用,并且用于在每个步骤中为将来的数据更新我们的最佳预测器,而不是通过学习生成最佳预测器的批处理学习技术 一次对整个训练数据集。 在线学习是机器学习领域中的一种常用技术,在该领域中,计算无法训练整个数据集是不可行的,因此需要核心算法。 它也用于算法必须动态适应数据中的新模式的情况下,或者在数据本身随时间而变的情况下(例如,股价预测)使用。 在线学习算法可能易于遭受灾难性干扰,这一问题可以通过增量学习方法来解决。
在机器学习中,采用离线学习的系统在初始训练阶段完成后不会改变其对目标函数的近似值。这些系统通常也是渴望学习的示例。
在在线学习中,只有一组可能的元素是已知的,而在离线学习中,学习者则知道这些元素的标识以及它们显示的顺序。
在机器人学习领域,目前主要有三类有效的免模型的深度强化学习算法:
PPO算法是TRPO(Trust Region Policy Optimization)算法的近似,该算法更能适应大规模的运算,是目前最主流的DRL算法,同时面向离散控制和连续控制,在OpenAI Five上取得了巨大成功。但是PPO是一种on-policy的算法,也就是PPO面临着严重的sample inefficiency,需要巨量的采样才能学习,这对于真实的机器人训练来说,是无法接受的。
DDPG及其拓展则是DeepMind开发的面向连续控制的off policy算法,相对PPO 更sample efficient。DDPG训练的是一种确定性策略deterministic policy,即每一个state下都只考虑最优的一个动作。
Soft Actor-Critic (SAC)是面向Maximum Entropy Reinforcement learning 开发的一种off policy算法,和DDPG相比,Soft Actor-Critic使用的是随机策略stochastic policy,相比确定性策略具有一定的优势(具体后面分析)。Soft Actor-Critic在公开的benchmark中取得了非常好的效果,并且能直接应用到真实机器人上。
下表给出强化学习常用符号定义。
符号 | 含义 |
---|---|
$s \in \mathcal{S}$ | 状态。 |
$a \in \mathcal{A}$ | 动作。 |
$r \in \mathcal{R}$ | 回报。 |
$S_{t}, A_{t}, R_{t}$ | 一个轨迹中第t个时间步对应的状态、动作以及回报。我可能会偶尔使用$s_t,a_t,r_t$来代替。 |
$\gamma$ | 折扣因子;用于惩罚未来回报中的不确定性;$0<γ≤1$。 |
$G_{t}$ | 累积回报;或者说累积折扣回报;$G_{t}=\sum_{k=0}^{\infty} \gamma^{k} R_{t+k+1}$。 |
$P\left(s^{\prime}, r\vert s, a\right)$ | 在当前状态s下采取动作a后转移到下一个状态 s′ 并得到回报 r 的概率。 |
$\pi(a\vert s)$ | 随机策略(智能体行为逻辑);$\pi_{\theta}( .)$代表由θ参数化的策略。 |
$μ(s)$ | 确定性策略;虽然也可以把确定性策略记为$π(s)$,但是采用一个不同的字母可以让我们更容易分辨一个策略到底是确定性的还是随机的。π或者μ都是强化学习算法要学习的目标。 |
$V(s)$ | 状态-值函数衡量状态s的期望累积回报;$V_{w}( .)$代表由w参数化的状态-值函数。 |
$V^{\pi}(s)$ | 当智能体遵循策略π时状态s的期望累积回报;$V^{\pi}(s)=\mathbb{E}{a \sim \pi}\left[G{t}\vert S_{t}=s\right]$ |
$Q(s,a)$ | 动作-值函数,与状态-值函数类似,但是它衡量在状态s下采取动作a后的期望累积回报;$Q_{w}( .)$代表由w参数化的动作-值函数。 |
$Q^{\pi}(s, a)$ | 与$V^{\pi}(s)$类似,当智能体遵循策略π时,在状态s下采取动作a后的期望累积回报;$Q^{\pi}(s, a)=\mathbb{E}{a \sim \pi}\left[G{t}\vert S_{t}=s,A_{t}=a\right]$ |
$A(s, a)$ | 优势函数,$A(s,a)=Q(s,a)−V(s)$;可以认为优势函数是加强版本的动作-值函数,但是由于它采用状态-值函数作为基准使得它具有更小的方差。 |
强化学习的目标是为智能体找到一个最优的行为策略从而获取最大的回报。策略梯度方法主要特点在于直接对策略进行建模并优化。策略通常被建模为由θ参数化的函数$\pi_{\theta}(a | s)$。回报(目标)函数的值受到该策略的直接影响,因而可以采用很多算法来对θ进行优化来最大化回报(目标)函数。
回报(目标)函数定义如下:
$$ J(\theta)=E_{\tau \sim \pi_{\theta}} [R(\tau)]=\sum_{s \in \mathcal{S}} d^{\pi}(s) V^{\pi}(s)=\sum_{s \in \mathcal{S}} d^{\pi}(s) \sum_{a \in \mathcal{A}} \pi_{\theta}(a | s) Q^{\pi}(s, a) $$
其中$d^{\pi}(s)$代表由$\pi_{\theta}$引出的马尔科夫链的平稳分布(π下的在线策略状态分布)。
使用梯度上升方法,我们可以将参数 $\theta$ 往梯度 $\nabla_{\theta} J(\theta)$ 给出的方向进行改变从而去找到最优的 $\theta$ 使得其对应的策略 $\pi_{\theta}$ 能够给智能体带来最大的期望累积回报。
$$\theta_{k+1} = \theta_k + \alpha \left. \nabla_{\theta} J(\pi_{\theta}) \right|_{\theta_k}.$$
策略性能的梯度 $\nabla_{\theta} J(\pi_{\theta})$ ,通常被称为 策略梯度 ,优化策略的算法通常被称为 策略算法 。
$$\begin{aligned} \nabla_\theta J(\theta) &\propto \sum_{s \in \mathcal{S}} d^\pi(s) \sum_{a \in \mathcal{A}} Q^\pi(s, a) \nabla_\theta \pi_\theta(a \vert s) &\ &= \sum_{s \in \mathcal{S}} d^\pi(s) \sum_{a \in \mathcal{A}} \pi_\theta(a \vert s) Q^\pi(s, a) \frac{\nabla_\theta \pi_\theta(a \vert s)}{\pi_\theta(a \vert s)} &\ &= \mathbb{E}_\pi [Q^\pi(s, a) \nabla_\theta \ln \pi_\theta(a \vert s)] & \scriptstyle{\text{; 因为 } (\ln x)’ = 1/x} \end{aligned}$$
$\mathbb{E}{\pi}$代表$\mathbb{E}{s \sim d_{\pi}, a \sim \pi_{\theta}}$,下标表示遵循策略$\pi_{\theta}$(在线策略)时状态以及动作的分布。
DDPG(Lillicrap, et al., 2015)是深度确定性策略梯度(Deep Deterministic Policy Gradient)的缩写,是一个结合了DPG以及DQN的无模型离线演员-评论家算法。DQN(深度Q网络)通过经验回访以及冻结目标网络的方式来稳定Q函数的训练过程。原始的DQN算法只能在离散的动作空间上使用,DDPG算法在学习一个确定性策略的同时通过演员-评论家框架将其扩展到连续的动作空间中。
最近在研究编写飞行动力学模型,发现需要使用很多用于插值的数据,这些数据可以是一维向量、二维表格或三维数据。在代码中直接硬编码存储是不合适的,降低程序的灵活性。直接使用文本文档存储也不合适,这些插值数据明显具有结构化的特征。于是想到用XML来存储表示这些数据。下面总结介绍XML解析相关知识。
可扩展标记语言(英语:Extensible Markup Language,简称:XML)是一种标记语言。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。如何定义这些标记,既可以选择国际通用的标记语言,比如HTML,也可以使用像XML这样由相关人士自由决定的标记语言,这就是语言的可扩展性。XML是从标准通用标记语言(SGML)中简化修改出来的。它主要用到的有可扩展标记语言、可扩展样式语言(XSL)、XBRL和XPath等。
XML定义结构、存储信息、传送信息。下例为小张发送给大元的便条,存储为XML。
1 | <?xml version="1.0"?> |
每个XML文档都由XML序言开始,在前面的代码中的第一行就是XML序言,。这一行代码会告诉解析器或浏览器这个文件应该按照XML规则进行解析。
但是,根元素到底叫<小纸条>还是<小便条>,则是由文档类型定义(DTD)或XML纲要(XML Schema)定义的。如果DTD规定根元素必须叫<小便条>,那么若写作<小纸条>就不符合要求。这种不符合DTD或XML纲要的要求的XML文档,被称作不合法的XML,反之则是合法的XML。
XML文件的第二行并不一定要包含文档元素;如果有注释或者其他内容,文档元素可以迟些出现。
C++类型XML解析器有:
推荐使用TinyXML2。
软件开发文档是软件开发过程的输出产物。软件开发过程的不同阶段将产生不同的软件开发文档。例如:软件需求分析阶段将产生软件需求规格说明书,软件概要设计阶段将产生概要设计说明书,软件详细设计阶段将产生详细设计说明书。按照软件工程的原则,软件开发过程输出这些文档的目的是为了保障软件开发的质量,确保软件项目能够按时完成,并保质保量。下面重点介绍各类软件开发文档的编写方法。
软件过程模型是软件过程的简化表示。典型的软件过程模型有:瀑布模型、增量式开发模型和面向服用的软件工程模型。以瀑布模型为例,其涉及的开发活动如图1所示。
各个开发活动对应产出的软件开发文档主要有:
近年来C++发展很快,出现了一些新的语法和特性。熟练掌握这些语法和特性,可提高编写C++代码的效率。下面即简要介绍这些C++语法和特性。
在类声明中,会出现const=0语法,如下所示:
1 | class Weapon |
在此处 =0 说明该类成员函数是一个纯虚函数。而将const放在成员函数之后,表示该成员函数禁止修改该类的数据成员(mutable成员除外)。如果您无意中修改了该类的数据成员,编译器会报告一个错误。
最近在编写一个飞行力学的类库,随着类数量的增加,代码越来越复杂,质量越来越难以控制,因此引入单元测试,通过自动化测试以保障代码质量,防止因代码修改引入新的Bug。C++已经有一些成熟的代码测试框架,例如:Google Test, Boost.Test, CppUnit, Cute,等等。通过综合分析和比较,最终选择Catch2测试框架。选择该测试框架的原因是其够轻量级,够简单。
Catch2是轻量级的C++的多范式测试框架。 它也支持Objective-C(也许还有C)。 它主要作为单个头文件分发,尽管某些扩展可能需要其他头文件。
使用Catch进行单元测试,只需简单掌握TEST_CASE、REQUIRE、SECTION三个宏即可编写绝大部分的测试用例。简单示例如下:
1 | TEST_CASE( "vectors can be sized and resized", "[vector]" ) { |
上述示例中,对于每个SECTION,TEST_CASE都是从头开始执行的,因此,当我们进入每个部分时,我们知道vector的大小为5,容量至少为5。通过REQUIRE宏在顶层确保vector大小和容量的正确性。这是可行的,因为SECTION宏包含一个if语句,该语句回调Catch来查看是否应执行该节。 通过TEST_CASE,每次运行都会执行一个叶子部分。 其他部分将被跳过。 下次执行下一个部分,依此类推,直到没有新的部分为止。
四元数是由爱尔兰数学家威廉·卢云·哈密顿在1843年创立出的数学概念。单位四元数(Unit quaternion)可以用于表示三维空间里的旋转。它与常用的另外两种表示方式(三维正交矩阵和欧拉角)是等价的,但是避免了欧拉角表示法中的万向锁问题。比起三维正交矩阵表示,四元数表示能够更方便地给出旋转的转轴与旋转角。
欧拉角(Euler Angles)是一种描述三维旋转的方式,根据欧拉旋转定理,任何一个旋转都可以用三个旋转的参数来表示。但欧拉角的描述方式有很多种,并没有一个统一标准。对于定义一个欧拉角,需要明确的内容包括:
顺序 | 飞行器 | 望远镜 | 符号 | 角速度 |
---|---|---|---|---|
第一 | heading | azimuth | $θ$ | yaw |
第二 | attitude | elevation | $ϕ$ | pitch |
第三 | bank | tilt | $ψ$ | roll |
对于两个三维点 $p_1(x_1, y_1, z_1)$,$p_2(x_2,y_2,z_2)$,由点 $p_1$ 经过旋转矩阵 $R$ 旋转到 $p_2$,则有:
$$R = \left[ \begin{matrix}
r_{11} & r_{12} & r_{13}\
r_{21} & r_{22} & r_{23}\
r_{31} & r_{32} & r_{33}
\end{matrix} \right]$$
$$\left[ \begin{matrix}
x_2 \
y_2 \
z_2
\end{matrix} \right] = R
\left[ \begin{matrix}
x_1 \
y_1 \
z_1
\end{matrix} \right]$$
注:旋转矩阵为正交矩阵$RR^T=E$
$$R_x(\theta) = \left[ \begin{matrix}
1 & 0 & 0\
0 & cos\theta & -sin\theta\
0 & sin\theta & cos\theta
\end{matrix} \right]$$
$$R_y(\theta) = \left[ \begin{matrix}
cos\theta & 0 & sin\theta\
0 & 1 & 0\
-sin\theta & 0 & cos\theta
\end{matrix} \right]$$
$$R_z(\theta) = \left[ \begin{matrix}
cos\theta & -sin\theta & 0\
sin\theta & cos\theta & 0\
0 & 0 & 1
\end{matrix} \right]$$
任何一个旋转可以表示为依次绕着三个旋转轴旋三个角度的组合。这三个角度称为欧拉角。
设三个轴$x,y,z$的欧拉角分别为$θ_x,θ_y,θ_z$,正弦值、余弦值分别为$s_x, c_x, s_y, c_y, s_z, c_z$那么旋转矩阵为:
$$R(\theta_x,\theta_y,\theta_z)=R_z(\theta_z)R_y(\theta_y)R_x(\theta_x) = \left[ \begin{matrix}
c_y c_z & c_z s_x s_y - c_x s_z & s_x s_z + c_x c_z s_y\
c_y s_z & c_x c_z + s_x s_y s_z & c_x s_y s_z - c_z s_z\
-s_y & c_y s_x & c_x c_y
\end{matrix} \right]$$
$$R = \left[ \begin{matrix}
r_{11} & r_{12} & r_{13}\
r_{21} & r_{22} & r_{23}\
r_{31} & r_{32} & r_{33}
\end{matrix} \right] = \left[ \begin{matrix}
c_y c_z & c_z s_x s_y - c_x s_z & s_x s_z + c_x c_z s_y\
c_y s_z & c_x c_z + s_x s_y s_z & c_x s_y s_z - c_z s_z\
-s_y & c_y s_x & c_x c_y
\end{matrix} \right]$$
解方程可得:
$$\theta_x = atan2(r_{32}, r_{33})$$
$$\theta_y = atan2(-r_{31}, \sqrt{r_{32}^2+r_{33}^2})$$
$$\theta_z = atan2(r_{21}, r_{11})$$
注意:atan2()为C++中的函数,atan2(y,x) 求的是y/x的反正切,其返回值为[-pi,+pi]之间的一个数。
三维空间的任意旋转,都可以用绕三维空间的某个轴旋转过某个角度来表示,即所谓的Axis-Angle表示方法。这种表示方法里,Axis可用一个三维向量$(x,y,z)$来表示,$θ$可以用一个角度值来表示,直观来讲,一个四维向量$(θ,x,y,z)$就可以表示出三维空间任意的旋转。注意,这里的三维向量$(x,y,z)$只是用来表示axis的方向朝向,因此更紧凑的表示方式是用一个单位向量来表示方向axis,而用该三维向量的长度来表示角度值$θ$。这样以来,可以用一个三维向量$(θ∗x,θ∗y,θ∗z)$就可以表示出三维空间任意的旋转,前提是其中$(x,y,z)$是单位向量。这就是旋转向量(Rotation Vector)的表示方式,OpenCV里大量使用的就是这种表示方法来表示旋转(见OpenCV相机标定部分的rvec)。
$$(cos \frac{\theta}{2}, xsin \frac{\theta}{2}, ysin \frac{\theta}{2}, z*sin \frac{\theta}{2})$$
已知四元数:
$$\mathbf{q} = q_0 + q_1 i + q_2 j + q_3 k = [s, \mathbf{v}]$$
利用Rodrigues公式可以由四元数求得旋转矩阵R:
$$R = \left[ \begin{matrix}
1 - 2 q_2^2 - 2 q_3^2 & 2q_1 q_2 - 2q_0 q_3 & 2 q_1 q_3 + 2 q_0 q_2 \
2q_1 q_2 + 2q_0 q_3 & 1 - 2 q_1^2 - 2 q_3^2 & 2 q_2 q_3 - 2 q_0 q_1 \
2 q_1 q_3 - 2 q_0 q_2 & 2 q_2 q_3 + 2 q_0 q_1 & 1 - 2 q_1^2 - 2 q_2^2
\end{matrix} \right ]$$
给出其中一种情况的计算方法:
$$q_0 = \frac{\sqrt{1+r_{11}+r_{22}+r_{33}}}{2}$$
$$q_1 = \frac{r_{32}-r_{23}}{4q_0}$$
$$q_2 = \frac{r_{13}-r_{31}}{4q_0}$$
$$q_3 = \frac{r_{21}-r_{12}}{4q_0}$$
其中要满足 $q_0 \neq 0$,$1+r_{11}+r_{22}+r_{33}>0$,即 $1+tr(R)>0$
假设坐标系O1上的点P1(x1, y1, z1), 存在变换矩阵R, 可计算P1点在坐标系O2上的坐标值为P2(x2, y2, z2):
$$P2=R∗P1$$
矩阵R对应的四元数为q, 则使用四元数计算为:
首先三维空间点用一个虚四元数来描述:P1=[0, x1, y1, z1], P2=[0, x2, y2, z2]
则P2和P1将计算关系为:
$$P_2=qP_1q^{-1}$$