【无人驾驶】带你了解无人驾驶里的gPTP时间同步服务器
【无人驾驶】带你了解无人驾驶里的gPTP时间同步服务器
京准电子科技官微——ahjzsz
一、时间同步要解决的问题
不知道大家还记得军训练习齐步走的场景吗?
齐步走的动作要领你还记得吗?
时钟同步的原理是类似的:
由此可见,如果要整个网络中的节点保持时钟同步,该网络必须解决以下问题:
相对时间同步:如下图所示,虽然在同一时刻A和B的绝对时间不同,但是相邻采样点之间的差值是相同的。也就是说,A和B对时间的度量是一致的(比如两个采样点之间的间隔A时钟测量出来是1ms,B时钟测量出来也是1ms)。它要求A和B的频率保持一致,又称为频率同步。
gPTP就是为了解决以上问题而诞生的。和其他校时协议不同的是,通过约束网络内的节点,它可以达到ns级的精度(6跳以内任意节点间最大时钟误差不超过1us),因此在车载、工业控制等对实时性要求较高的领域得到了应用。
二、gPTP的主要思想
AVB域内的每一个节点都是一个时钟,由以下两个角色组成:
下图是一个简单的gPTP网络拓扑图:
它包含两种类型的节点:
从上图还可以看到,时间信息是从主时钟出发,经由各个Bridge分发到所有的从节点。

gPTP中的主时钟,既可以默认指定,也可以通过BMCA(Best Master Clock Algorithm) 动态选取。 不过在车载或其他一些网络拓扑固定的应用场景中,一般不允许使用BMCA动态选取主时钟,而是默认指定。 这部分内容本文不做相关介绍,有需要可以查阅规范文档。
下图包含一个主时钟(Master time)和一个从时钟(Slave time),二者时间不同步。现在要把从时钟的时间校准到主时钟的时间,其中t1、t4为主时钟对应的时间,t2、t3为从时钟对应的时间。

主要流程如下:
从上面的流程可以看到,传输延时path_delay的精度/稳定性会影响校时精度。而传输延时又可以划分为:各段链路传输时间总和 + 中间节点转发导致的驻留时间(缓存时间)。
我们首先看下时间度量的原理:时间是基于晶振的震荡周期进行度量的,如果一个晶振的震荡频率是10Hz,也就是说每100ms震荡一次,震荡10次代表过了1秒,震荡600次代表经过了1分钟。
但是晶振并非绝对稳定的,受温度等因素影响,震荡频率可能发生变化,震荡周期也就变得不准了。而晶振的使用者(时钟)并不知道这些变化,只是傻傻的计数,震荡10次为1s,震荡600次为1分钟。如果现实世界的1s内该晶振少震荡了一次(某两次震荡之间的间隔变成了200ms),那么该时钟的1s就对应现实世界中的1.1s;如果某两次震荡的时间间隔变成了50ms(多震荡了一次),那么该时钟的1s就对应现实世界中的0.95s。
相对时间同步,要求从时钟的频率和主时钟一致。我们可以通过下面的方式估算晶振的变化,并动态调整。 如下图所示,分别在t1、tn时刻对主时钟和从时钟进行采样,采样值分别记为t1_master、tn_master、t1_slave、tn_slave,可以得到下面的比例:
ratio = (tn_slave – t1_slave) / (tn_master – t1_master)
理想情况下,ratio的值应该是1,如果大于1,说明从时钟走的快了,如果小于1,说明走的慢了。从时钟可以根据该值调整自己的频率。
三、影响校时精度的因素
其实不同的校时协议,原理都大同小异。为什么gPTP可以达到ns级别的精度? 我们不妨先看下影响校时精度的因素以及gPTP的对策。
前面提到的校时流程中,我们假设传输时延是对称的,即报文从A传到B和从B传到A耗时相同,实际情况中,路径有可能是不对称的,如下图所示,tms和tsm有可能是不相等的。这会导致校时误差。
gPTP对策:
对于Bridge设备,从接收报文到转发报文所消耗的时间(中间可能经过缓存),称为驻留时间。该值会具有一定的随机性,从而影响校时精度。
gPTP对策:Bridge设备必须具有测量驻留时间的能力,在转发报文的时候,需要将驻留时间累加在PTP报文的矫正域中(correctionField)。
前面提到的t1、t2、t3、t4等采样时刻的值,应该在哪里产生呢?
常规的做法是在应用层采样,如下图蓝色传输线路所示:在发送端,报文在应用层(PTP校时应用)产生后,需要经过协议栈缓冲,然后才发送到网络上;在接收端,报文要经过协议栈缓冲,才能到达接收者(PTP校时应用)。这样存在下面两个问题,而这都会影响时间同步的精度:
为了达到高精度的时间同步,必须消除软件带来的不确定因素,这就要求必须把时间采集点放在最靠近传输介质的地方。
gPTP对策:
晶振频率越高,误差越小,校时越精确。 gPTP要求晶振频率不小于25MHz,误差不大于100PPM(每天8.64s误差)。 gPTP的要求并不算高,主要是考虑到成本因素,要求太高不利于推广。
IEEE 1588支持两种路径延时测量方式:End-to-End(E2E) 和 Peer-to-Peer(P2P),二者不能在同一个网络中共存。
在End-to-End机制中,强调的是两个支持PTP的端点(一个master port,一个slave port)之间的延时,这两个端点可能是直接相连的,也可能中间穿插了普通的交换机、时间敏感的透明时钟(TC),在通信双方看来,信息都是在master port 和slave port之间传输,所以最终slave测量到的传输延时是从master到slave的端到端延时。
在Peer-to-Peer机制中,要求网络内所有节点必须支持P2P,所以它强调的是相邻相邻节点间的通信,最终测量的是相邻节点间的传输延时。
二者主要区别如下图所示:
gPTP要求使用P2P方式,并且要求网络中所有设备都支持PTP协议,路径传输延时测量只在相邻节点间进行。它使用Pdelay_Req、Pdelay_Resp、Pdelay_Resp_Follow_Up消息来测量路径传输延时。
注意Peer-to-Peer中没有使用Sync报文,而是专门为路径测量新建了几个报文,降低了复杂度。
具体流程如下:
在Peer-to-Peer机制中,不仅节点A会主动发起测量请求,节点B也会主动发起测量请求,也就是说,每个节点都知道和自己紧挨着的节点的传输延时(Peer-to-Peer的名字也是这样来的)。不过有的场景下(比如固定主时钟的情况),可能会禁止master port进行路径测量。
PTP时钟可以分为两类:One-Step Clock和Two-Step Clock。
还记得下图Follow_Up消息的作用吗? 它只是为了把t1的值传给slave节点。这种时钟就是Two-Step Clock, 它的事件报文(Sync等)中不携带时间信息,需要用另外一条普通报文传输时间信息(用来描述上一条事件报文是在什么时候发送的)。
如果t1能在Sync报文本身中传递给slave节点,就节省了一条报文,如下图所示,这是One-step clock的做法。这种时钟对硬件要求比Two-step clocks高,成本也比较高。
理论上来讲,同一个网络内可以存在两种类型的时钟,并且时钟类型不会影响校时精度。 gPTP要求使用Two-step时钟,因为这种机制对硬件要求较低,方便后续扩展,以及在现有的网络中普及。
以下图为例介绍gPTP时间同步过程,为了表述方便,这里做两点假设:
校时流程如下:
由上面的校时流程可以看出,整个校时过程像水面的波纹一样从Grandmaster开始向外一层层的扩散,每个节点只关注自己和上级节点的传输延时,Bridge负责将中间路径的传输延时和缓存时间逐段累加到矫正域。
如下图所示,主时钟在时刻master_t1发出校时信号Sync_1,从时钟接收到该信号的时候,记录两个值:
根据前面介绍的相对时钟同步原理,可以通过下面的公式判断自己的频率和主时钟是否保持一致:
ratio = (slave_tn – slave_t1) / (slave_tn’ – slave_t1’)
理想情况下,ratio的值应该是1,如果大于1,说明从时钟走的快了,如果小于1,说明走的慢了。从时钟可以根据该值调整自己的频率。
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build
我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s
您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame