GenICam标准(四)

简介: GenICam标准(四)

8、可用的节点类型

    本章对每个可用的节点类型提供一个概要的描述,包括其功能、用途以及最关心的参数。另外,对于每个节点在 GenICam 标准的 XML 格式文件中的 layout ,会有一个正式的说明。这个格式文件可以用大多数 XML 编辑器来读,并且提供了语法检查和上下文相关的帮助,可以大大简化创建相机描述文件的工作。


   本文档中的 GenApiSchema_Version_1_0.xsd 指的是 GenApi schema version 1.0 。注意,随着标准版本的增长,可能会加入新的节点类型,元素和属性,不过,如果可能的话会保持向下兼容。

8.1.Node

    Node 类型包含其它节点类型共通的元素和属性。一个孤立的 Node 类型没什么用处,但是可以用于测试。下面是一个例子:

  <Node Name="Gain" NameSpace="Standard">
  <Extension>
    <MyElement>Something vendor specific</MyElement>
  </Extension>
  <ToolTip>The amplification of the camera</ToolTip>
  <Description>A more elborated description</Description>
  <DisplayName>Gain</DisplayName>
  <Visibility>Expert</Visibility>
  <EventID>12fc</EventID>
  <pIsImplemented>SomeNode1</pIsImplemented>
  <pIsAvailable>SomeNode2</pIsAvailable>
  <pIsLocked>SomeNode3</pIsLocked>
  <pError>NodeIndicatingAnError</pError>
  <ImposedAccessMode>RO</ImposedAccessMode>
  <pAlias>SomeNode4</pAlias>

   每个节点都有一个 Name 属性。Name 在相机描述文件内必须是唯一的。Name 可以是字符 [A-Z a-z 0-9] 的组合。格式也允许使用下划线,但是相机描述文件设计器不能使用下划线,因为参考实现把下划线用在自动生成的名称上。


   每个 Name 存在于一个命名空间(name space)中。通过节点的 NameSpace 属性和外框元素(参见 2.7 章)的 StandardNameSpace 属性的结合来标识命名空间。NameSpace 属性有两个可能的值:Custom 和 Standard 。如果是 Custom,可以用任何名字,只要在相机描述文件内是唯一的就行了。如果是 Standard,则必须用标准属性名列表(standard feature name lists)中提供的名字,列表对于下列相机类型可用(参见 2.9 章):


IIDC: 符合 1394 IIDC 标准(也叫 DCAM 标准)的相机


GEV: 符合 GigE Vision 标准的相机


CL: 符合 Camera Link 标准的相机


None: 未用任何标准


   可以用一个 <Extension> 元素来把自定义的数据加到相机描述文件中。<Extension> 元素内的所有元素都被忽略。

   <ToolTip> 元素给出了节点的一个短的说明。在由相机描述文件自动生成的参考文档中,也可以用这个元素作一个概要说明。

   <Description> 元素给出节点的更详细地说明。在由相机描述文件自动生成的参考文档中,也可以用这个元素作一个长的说明。

   <DisplayName> 元素让你定义属性的说明,可用来代替 Name 。

   <Visibility> 元素定义了要访问这个属性所需的用户级别。可能的级别有:Beginner(初学者)、Expert(专家)、Guru(大师) 和 Invisible(隐形人)。最后一个用来让一个属性在 API 中可见,但在 GUI 中不可见(参见第 8.2 节)。

   <EventID> 元素用来分发异步事件。一台相机可能发送一个事件包,以表示相机上一个或多个数据项的值发生了改变。GenICam 处理这个事件的方法是令数据项相应的节点无效。节点可以通过 EventID 找到,EventID 是一个 16 进制数值,和事件包一起由相机发过来。每个节点可以有一个 EventID 元素(可选)。

   <pIsImplemented>、<pIsAvaliable> 和 <pIsLocked> 元素包含实现一个 IInteger 接口的节点的名称。如果提供这些元素,它们会影响节点的访问模式,如第 2.5 章所述。

   <ImposedAccessMode> 元素可用来减少访问模式。

   <pAlias> 指向用不同的方式实现相同属性的另一个节点。这个属性主要用在 GUI :如果不是所有的成员都显示的话,一个 Category 可以用它的别名代替;如果一个整数和一个浮点数节点都表示一个属性的正的原始数值,则可以互为别名。

8.2.Category

   Category 节点用来组织要提供给用户的属性,它实现 ICategory 接口并继承所有的 Node 元素。它也提供一组指向包含在 category 中的属性的 <pFeature> 元素。Category 可以包含别的 Category ,从而形成一棵任意深度的树。


   有一个特殊的 Category 节点,带标准的名字 Root(脚注:属性 ICategory::Root 在所有标准命名空间中定义),它是 Category 树的根。用户可能想从这里开始浏览相机的属性。下面的例子创建如图 12 所示的节点图。

<Category Name="Root" NameSpace=”Standard” >
  <pFeature>ScalarFeatures</pFeature>
  <pFeature>Trigger</pFeature>
</Category>

<Category Name="ScalarFeatures" >
  <pFeature>Shutter</pFeature>
  <pFeature>Gain</pFeature>
  <pFeature>Offset</pFeature>
  <pFeature>WhiteBalance</pFeature>
</Category>

<Category Name="WhiteBalance" >
  <pFeature>RedGain</pFeature>
  <pFeature>BlueGain</pFeature>
</Category>

<Category Name="Trigger" >
  <pFeature>TriggerMode</pFeature>
  <pFeature>TriggerPolarity</pFeature>
</Category>

   注意,通过浏览目录树(category tree)来访问节点的用户可能只想看 Category 节点之下第一层的属性节点(features nodes)。图中更深的节点叫做实现节点(implementation nodes),只能通过名称或一种特殊的浏览模式得到,实现程序可能会提供这种浏览模式用于调试目的。要注意,在新发布的相机描述文件中,实现节点的名称和 layout 可能会发生变化,即使制造商声明它是向下兼容的(参见第 7.3 章)。

    图 12 A 个类别的树 (Figure 12 A tree of categories)

8.3.Register

   Register 节点映射到相机的寄存器空间中一个连续的字节数组。Register 节点实现 IRegister 接口,并从 Node 节点继承元素和属性。同时也向所有特殊的寄存器访问节点,例如 IntReg,StringRet 等等提供继承的元素。当然,Register 节点也可以实例化自身,以访问原始的二进制数据。下面是一个简单的例子:

<Register Name="SensorTemperature">
  <Address>0xff00</Address>
  <Length>4</Length>
  <AccessMode>RO</AccessMode>
  <pPort>Device</pPort>
  <Cachable>No</Cachable>
  <PollingTime>10000</PollingTime>
</Register>

   这里例子提供了相机传感器的温度。温度可以随时变化,所以是不能放入缓存的。如果显示的话,应该每 10.000 毫秒更新一次。


   <Address> 元素给出了寄存器在相机寄存器空间中的地址。

   <Length> 元素给出了寄存器的长度,单位是字节。

   <AccessMode> 元素可以取值 RW (read/write)、RO (read only) 或 WO(write only),表示访问属性。

   <pPort> 元素包含一个 Port 节点的名称,通过这个端口可以访问相机的寄存器空间(详见2.8.15)。

   <Cacheable> 元素可以取值 No(注:实际上应该是 NoCache )、WriteThrough 和 WriteAround 。其中 WriteThrough 意味着写到相机里的值也写入缓存;WriteAround的意思是只读这个值并写入缓存。我们举一个 IFloat::Gain 节点的例子来理解后一个动作,用户可以把任何值写入这个节点,但是再把这个值读回来的时候,会得到一个相机调整之后的值,相机调整这个值的目的是让内部的模数转换部分能够使用。注意,对任何实现来说,缓存都是一个可选的属性。

   <PollingTime> 元素表示推荐的读一个不能缓存的属性的 polling 时间间隔 [单位 ms ] , 注意,对任何实现来说,polling 是一个可选的属性,polling 时间仅仅是个暗示。

   一个寄存器可以有多个 <Address>、<pAddress> 和 / 或 <IntSwissKnife> 类型的入口,而不是单个 <Address> 入口,这些入口的值合起来,产生寄存器节点的地址。

   <pAddress> 元素指向实现一个 IInteger 接口的节点,提供最终地址的一部分。

   可用 <IntSwissKnife> 元素来把多个源计算生成地址的一部分(详见 2.8.12)。

   <pIndex Offset=”12”> 元素指向实现一个 IInteger 接口的节点,提供一个 index 。这个元素有一个属性 Offset 。这个 index 和 Offset 要加到地址上。

   <pInvalidator> 元素包含一个节点的名称。当发生变化的时候,会令该节点的内容无效,如 2.6 章所述。


   下面的例子显示了使用间接寻址机制的方法(同时参见图 13 )。

<Integer Name="BaseAddress">
  <Value>0xff00</Value>
</Integer>

<IntReg Name="Gain">
  <Address>0x04</Address>
  <pAddress>BaseAddress</pAddress>
  <Length>4</Length>
  <AccessMode>RW</AccessMode>
  <pPort>Device</pPort>
  <Sign>Unsigned</Sign>
  <Endianess>LittleEndian</Endianess>
</IntReg>

<IntReg Name="Offset">
  <Address>0x08</Address>
  <pAddress>BaseAddress</pAddress>
  <Length>4</Length>
  <AccessMode>RW</AccessMode>
  <pPort>Device</pPort>
  <Sign>Unsigned</Sign>
  <Endianess>LittleEndian</Endianess>
</IntReg>

    用一个 C/C++ 结构体来模拟这个例子:

struct { // BaseAddress 0xff00
  uint32_t Reserved;
  uint32_t Gain; // Offset 0x04
  uint32_t Offset; // Offset 0x08
};

    结构体的基地址从一个叫 BaseAddress 的常量整数节点得到,本节点用一个 <pAddress> 元素和它关联。结构体的每个元素( Gain 和 Offset )都有一个偏移地址,可以用一个 <Address> 元素把基地址和偏移地址相加。

   图 13 间接寻址:映射一个 C/C++ 结构体(Figure 13 Indirect addressing: mapping a C/C++ struct)


   注意,对于 1394 DCAM 兼容相机来说,这一机制使用非常频繁。这类相机的整个标准寄存器都有一个共同基地址,运行时必须要通过 IEEE 1212 配置 ROM 结构来得到(参见 ConfRom 节点类型)。

8.4.数组和选择器

Arrays and Selectors

    前一节所述的间接寻址也用于访问数组。下面的例子显示了这样做的方法(同时参见图 14):

<Integer Name="LUTIndex">
  <Value>0</Value>
  <Min>0</Min>
  <Max>255</Max>
  <pSelected>LUTEntry</pSelected>
</Integer>

<IntReg Name="LUTEntry">
  <IntSwissKnife Name="LUTEntryAddress">
    <pVariable Name="INDEX">LUTIndex</pVariable>
    <Formula>0xff00 + INDEX * 4</Formula>
  </IntSwissKnife>
  <Length>4</Length>
  <AccessMode>RW</AccessMode>
  <pPort>Device</pPort>
  <Sign>Unsigned</Sign>
  <Endianess>LittleEndian</Endianess>
</IntReg>

   一个 LUT 入口元素可用作 LUT 内的指针。这个元素的地址要通过一个内嵌的元素来计算,计算公式为:BaseAddress + LUTIndex × sizeof (LUTEntry) 。LUTIndex 是一个 “浮动的” 整数节点,没有联接到相机,相反,它从开始,可以被用户在 <Min> 和 <Max> 的范围内改变。


9d065080ff6f43bf9c600add1320cca8.png

 图 14 访问 LUT 阵列(Figure 14 Accessing a LUT array)


   之所以可以用 LUTIndex 来选择一个特定的 LUTEntry ,是因为 LUTIndex 节点有一个 <pSelected> 元素。实现 IInteger 或 IEnumeration 接口的节点可以有任意数目的 pSelected 入口,这表明,基于选择器节点(selector node)的值,被选择的节点(selected nodes)会表现出不同的值。关于一个节点是否是选择器,以及哪些是被选择的节点的信息,可以用 ISelector 接口得到,这个接口有对应的方法 IsSelector 和 GetSelectedFeatures 。例如,用这个接口,GUI 可以显示一个 LUTEntries 的列表,因为它知道如果从 min 到 max 运行 LUTIndex(选择器),就可以从 LUTEntry(被选择)得到一组不同的值。


   注意,利用多个索引,选择器和间接寻址方法可用来访问多维数组(multidimensional arrays)。

8.5.Integer, IntReg, MaskedIntReg

   IInteger 接口提供访问有符号的 64 位整型变量的方法,这个变量有一个受 Minimum、Maximum 和 Increment 参数制约的 Value ,公式为:Value = Minimum + i × Increment,并且有

image.png


   IntReg 节点映射到按字节对齐的整数寄存器。它从 Register 节点继承元素和属性,下面是映射到一个双字节无符号整数的一个例子。注意,这个变量有如下的约束参数:Minimum = 0,Maximum = 65535,Increment = 1 。

<IntReg Name="Gain">
  <Address>0x1234</Address>
  <Length>2</Length>
  <AccessMode>RW</AccessMode>
  <pPort>Device</pPort>
  <Sign>Unsigned</Sign>
  <Endianess>BigEndian</Endianess>
</IntReg>

 <Sign> 元素可以取值 Singed 或 Unsigned 。注意,无符号的 int64 不可用。

   <Endianess> 元素可以取值 LittleEndian 或 BigEndian ,表示的是以传输层的观点看到的设备的字节序。传输层必须尽量不去改变这个字节序。实现程序必须知道自己是运行在 little-endian 还是 big-endian 的机器上。


   有时候一组整数不是按字节对齐的,但是合并在一个寄存器内。在这种情况下,可以使用 MaskedIntReg ,它从 Register 节点继承元素和属性。下面的 XML 代码所表示的例子中,一个 12 位整数被封装在一个双字节寄存器。<LSB> 和 <MSB> 元素分别表示最低有效位和最高有效位。

<MaskedIntReg Name="Offset">
  <Address>0x2345</Address>
  <Length>2</Length>
  <AccessMode>RW</AccessMode>
  <pPort>Device</pPort>
  <LSB>11</LSB>
  <MSB>0</MSB>
  <Sign>Unsigned</Sign>
  <Endianess>BigEndian</Endianess>
</MaskedIntReg>

    对于只需要一位的情况 —— 对于存在性查询很常见 —— 你可以用一个 <Bit> 入口,来取代 <LSB> 和 <MSB> 元素。

<MaskedIntReg Name="OffsetInq">
  <Address>0x2345</Address>
  <Length>2</Length>
  <AccessMode>RW</AccessMode>
  <pPort>Device</pPort>
  <Bit>15</Bit>
  <Sign>Unsigned</Sign>
  <Endianess>BigEndian</Endianess>
</MaskedIntReg>

  一个 32 位整数的 big-endian 和 little-endian 字节序的区别如下所示:

   LSB 是对应 20 的位。注意,对于 big-endian。表达式 MSB ≤ LSB 总是 true ;而对 little-endian 则相反,是 LSB ≤ MSB 。


   Integer 节点类型用来合并来自不同源的 Value、Minimum、Maximum 和 Increment 参数。它从 Node 节点继承元素和属性。这些限定的参数,既可以是由 <Min>、<Max> 和 <Inc> 元素给出的常量,也可以是通过 <pMin>、<pMax> 和 <pInc> 元素指向别的 IInteger 节点的指针。


   通常从另一个节点来的值用 <pValue> 元素。另外,在一个 <Value> 元素内可以给定一个常量。在这种情况下,节点是一个 “浮动的” 变量,用户可以在允许的范围内设置任何值,给定的常量就是开始的值。下面的 Index 节点是一个典型的例子,可以给它赋值 0,2,4,…,254 :

<Integer Name="Index">
  <Value>0</Value>
  <Min>0</Min>
  <Max>255</Max>
  <Inc>2</Inc>
</Integer>

   <Representation> 元素提示显示数字的方法,如果这个元素是 Linear 或 Logarithmic ,则应该实现一个有适当动作的滑块(slider);如果是 Boolean,应该用复选框(checkbox);PureNumber 意味着要用一个只显示 10 进制数字的编辑框;HexNumber 的话用一个显示 16 进制数字的编辑框。


   Integer、IntReg 和 MaskedInt 节点也可以有一个 <pSelected> 元素。参见 2.8.4。

8.6.StructReg

   常用 MaskedInt 节点来从寄存器取得一段位域。如果每一位都用一个完整的 MaskedInt 入口,相机描述文件内将有很多不必要的重复数据,因为对于不同的 MaskedInt 入口,它们大多数的元素是相同的,例如 <pPort> 元素、<Endianess> 元素等等。


   为克服这个缺点,引入了 StructReg 节点,下面是一个例子:

<StructReg Comment="VFormat7InqReg">
  <ToolTip>Inquiry register for video format 7 color codes</ToolTip>
  <Address>0x14</Address>
  <pAddress>VFormat7ModeCsrBase</pAddress>
  <Length>4</Length>
  <AccessMode>RO</AccessMode>
  <pPort>Device</pPort>
  <Endianess>BigEndian</Endianess>
  <StructEntry Name="VFormat7Mono8InqReg">
    <ToolTip>Inquiry for ColorCode Mono8</ToolTip>
    <Bit>31</Bit>
  </StructEntry>
  <StructEntry Name="VFormat7YUV422InqReg">
    <ToolTip>Inquiry for ColorCode YUV8 422</ToolTip>
    <Bit>29</Bit>
  </StructEntry>
  <StructEntry Name="VFormat7Raw8InqReg">
    <Bit>24</Bit>
  </StructEntry>
</StructReg>

   StructReg 拥有和 MaskedInt 相同的元素。另外它还有一个或多个 <StructEntry> 元素,可用来再包含和 MaskedInt 一样的元素。预处理器用一组 MaskedInt 节点代替 StructReg 节点:根据每个 <StructEntry> 元素创建一个 MaskedInt 节点,这个 MaskedInt 节点从 StructEntry 元素取得 Name 属性、所有的子元素,加上未在 <StructEntry> 元素中出现的 StructReg 节点的所有元素。因此,根据上面的例子生成的 MaskedInt 节点看起来向这个样子。

<MaskedInt Name="VFormat7Mono8InqReg ">
  <Address>0x14</Address>
  <pAddress>VFormat7ModeCsrBase</pAddress>
  <Length>4</Length>
  <AccessMode>RO</AccessMode>
  <pPort>Device</pPort>
  <Endianess>BigEndian</Endianess>
  <ToolTip>Inquiry for ColorCode Mono8</ToolTip>
  <Bit>31</Bit>
</MaskedInt>

   注意,<ToolTip> 元素是从 <StructEntry> 而不是 <StructReg> 得到的。与之相对,名叫 VFormat7Raw8InqReg 的入口要从 <StructReg> 继承 <ToolTip> 元素,因为它没有自己的。<StructReg> 有一个 Comment 属性用于描述。

8.7.Boolean

    Boolean 节点把 <OnValue> 元素的整数值映射为 true ,把 <OffValue> 的值映射为 false 。Boolean 节点实现 IBoolean 接口,并从 Node 节点继承元素和属性。下面的例子显示了为一个 Trigger 节点使用这个功能的方法,在 GUI 上,这个节点可表示为一个复选框。

<Boolean Name="Trigger">
  <pValue>TriggerReg</pValue>
  <OnValue>1</OnValue>
  <OffValue>0</OffValue>
</Boolean>

<IntReg Name="TriggerReg">
  <Address>0x6789</Address>
  <Length>1</Length>
  <AccessMode>RW</AccessMode>
  <pPort>Device</pPort>
  <Sign>Unsigned</Sign>
  <Endianess>BigEndian</Endianess>
</IntReg>

8.8.Command

    Icommand 接口让用户提交一个命令,方法是调用 Execute,然后调用 IsDone 来判断执行是否完成。

   相应的 Command 节点继承 Node 节点的元素和属性。


   另外,它有一个 CommandValue 元素,这个元素有一个整型常量,这个常量要写入一个由 pValue 元素指向的节点,写入就是提交这条命令。IsDone 读返回的值并返回 false,直到返回的值等于命令的值。为了可以用一个浮动的 Command 节点来代替 pValue 元素,也允许一个 Value 元素。或者,也可以从 pCommandValue 得到命令值。提供一个 <PollingTime> 入口以便处理自动清除的命令。

8.9.Float, FloatReg

   Ifloat 接口的定义和前面所说的 IInteger 很相似。它有一个由 Minimum 和 Maximum 参数限定的 Value ,但与整数不同的是,它没有 increment 。另外,Ifloat 提供一个 Unit ,这仅仅是个用来显示用途的字符串。


   建立 Float 节点的方法和 Integer 类似,它有 <Value>、<Min>、<Max> 或 <pValue>、<pMin>、<pMax>。另外,它可以有一个 <Representation> 元素,这个元素可以取值 Linear 和 Logarithmic ,还有一个 <Unit> 元素,它有一个字符串。下面是一个例子:

<Float Name="Exposure">
  <pValue>ExposureReg</pValue>
  <Min>0.02</Min>
  <Max>10.0</Max>
  <Unit>ms</Unit>
  <Representation>PureNumber</Representation>
  <DisplayNotation>Fixed</DisplayNotation>
  <DisplayPrecision>3</DisplayPrecision>
</Float>

   可以用 FloatReg 从按字节对齐的寄存器中取出一个浮点值。FloatReg 从 Register 节点继承元素和属性。它还有一个 <Endianess> 元素。Length 可以是 4 个字节(单精度浮点)或 8 个字节(双精度浮点),数字格式必须符合 IEEE standard 754-1985 。

参考

GenIcam标准(一)

GenIcam标准(二)

GenIcam标准(三)

GenIcam标准(四)

GenIcam标准(五)

GenIcam标准(六)

GenIcam标准介绍


GenIcam标准(一)

GenIcam标准(二)

GenIcam标准(三)

GenIcam标准(四)

GenIcam标准(五)

GenIcam标准(六)

目录
相关文章
|
4月前
|
安全 程序员 编译器
|
21天前
|
XML 数据格式 索引
GenICam标准(五)
GenICam标准(五)
23 2
|
21天前
|
XML 缓存 编解码
GenICam标准(三)
GenICam标准(三)
23 1
|
21天前
|
XML 缓存 安全
GenICam标准(二)
GenICam标准(二)
34 1
|
21天前
|
XML API 数据格式
GenICam标准(一)
GenICam标准(一)
31 1
|
21天前
|
API 索引
GenICam标准(六)
GenICam标准(六)
27 0
|
2月前
|
Web App开发 人工智能 前端开发
你想成为什么样的人,你就要以什么样的标准来要求自己
志在成为“前端第一人”,专注Web前端开发,精通HTML/CSS/JS,擅长各浏览器兼容性处理。熟悉Node.js及前端框架如React、Vue。强调团队协作,项目管理和优化,使用Git等工具。热衷新技术,如Vue与MUI结合,自动化工具Webpack、Gulp。具备接口调试和服务器配置能力,曾实现微信支付功能,开发多端商城及大型项目。现致力于AI集成,如ChatGPT和Kimi,运用Python进行数据处理。
28 0
|
11月前
|
API 数据格式
IIIF 标准
IIIF 标准
228 0
|
自然语言处理 数据管理
数据标准和数据规范到底有什么区别???
数据标准和数据规范到底有什么区别???
|
C语言 C++
C 和C++语言的标准
C 和C++语言的标准
305 0