前置知识
内部值:从ECU收到的响应信息中提取出的结果
物理值:内部值转换到诊断仪或其他设备上人类可读的值
正向计算:内部值–>物理值
反向计算:物理值–>内部值
根据compu-method的标签情况,计算内部值->物理值转换的规则
COMPU-METHOD | internal -> physical (response) use | physical -> internal (request) use |
---|---|---|
只有 COMPU-INTERNAL-TO-PHYS | COMPU-INTERNAL-TO-PHYS | COMPU-INTERNAL-TO-PHYS 逆运算 |
COMPU-INTERNAL-TO-PHYS 、 COMPU-PHYS-TO-INTERNAL 都有 | COMPU-INTERNAL-TO-PHYS | COMPU-PHYS-TO-INTERNAL |
只有 COMPU-PHYS-TO-INTERNAL | COMPU-PHYS-TO-INTERNAL 逆运算 | COMPU-PHYS-TO-INTERNAL |
COMPU-METHOD 一共有8种类型: IDENTICAL, LINEAR, SCALE-LINEAR, TEXTTABLE, COMPUCODE, TAB-INTP, RAT-FUNC , SCALE-RAT-FUNC。使用<CATEGORY>(必填)属性定义
1.IDENTICAL
它只传递输入值,因此内部值和物理值是相同的。即$f(x)=x$
对于这种类型,不允许使用数据对象 COMPU-INTERNAL-TO-PHYS 和 COMPU-PHYS-TOINTERNAL。
如果编码类型(在 DIAG-CODED-TYPE 的 BASE-TYPE-ENCODING 处)为 A_ASCIISTRING 或 A_UTF8STRING,则在解码或编码过程中应隐式完成与物理 BASE-DATA-TYPE A_UNICODE2STRING 之间的转换。
可用的数据类型:
Internal | Physical |
---|---|
A_INT32 | A_INT32 |
A_UINT32 | A_UINT32 |
A_FLOAT32 | A_FLOAT32 |
A_FLOAT64 | A_FLOAT64 |
A_BYTEFIELD | A_BYTEFIELD |
A_ASCIISTRING | A_ASCIISTRING |
A_UTF8STRING | A_UTF8STRING |
A_UNICODE2STRING | A_UNICODE2STRING |
2.Linear
线性函数,通俗点就是个一元一次方程。将输入值与一个因子相乘并加上偏移量。(可选)得出的总和可以除以一个无符号整数常量。 $$ f(x) = \frac {V_{N0} + V_{N1} * x} {V_{D0}} $$ 需要精确定义一个 <COMPU-SCALE>。它包含 <COMPU-RATIONAL-COEFFS>,其中声明了<COMPU-NUMERATOR>和 <COMPU-DENOMINATOR>。分母应包含两个值。第一个是偏移量$V_{N0}$,第二个是系数$V_{N1}$。如果存在分母,则应精确指定一个无符号整数值。可以使用 <COMPU-SCALE>的 LIMIT 来限制值域。
在这种情况下,如果需要反向计算,则应定义 <COMPU-INVERSE-VALUE>。
示例 $$ f(x) = \frac {1 + 2 * x} {3} $$
<COMPU-METHOD>
<CATEGORY>LINEAR</CATEGORY>
<COMPU-INTERNAL-TO-PHYS>
<COMPU-SCALES>
<COMPU-SCALE>
<LOWER-LIMIT>0</LOWER-LIMIT>
<UPPER-LIMIT>255</UPPER-LIMIT>
<COMPU-RATIONAL-COEFFS>
<COMPU-NUMERATOR>
<V>1</V>
<V>2</V>
</COMPU-NUMERATOR>
<COMPU-DENOMINATOR>
<V>3</V>
</COMPU-DENOMINATOR>
</COMPU-RATIONAL-COEFFS>
</COMPU-SCALE>
</COMPU-SCALES>
</COMPU-INTERNAL-TO-PHYS>
</COMPU-METHOD>
可用的数据类型:
Internal | Physical |
---|---|
A_INT32 | A_INT32 |
A_UINT32 | A_UINT32 |
A_FLOAT32 | A_FLOAT32 |
A_FLOAT64 | A_FLOAT64 |
3.Scale linear
分段线性函数。和Linear的区别是分区间的可以有不同的计算方式,比如(-∞,0]按$f(x) = x$计算,(0,+∞)按照$f(x)= -x$计算。需要注意的是区间之间的边界是不能重叠的。
$$ f(x) = \begin{cases} \frac{V_{N0}^1 + V_{N1}^1 \cdot x}{V_{D0}^1}, & x \in I_1 \\ … \\ \frac{V_{N0}^n + V_{N1}^n \cdot x}{V_{D0}^n}, & x \in I_n \end{cases} $$
同时对于分段线性函数反向计算的函数是有条件的;
-
相邻区间在公共边界上的值必须相等 (adjacent COMPU-SCALES shall have the same values on their common boundaries)
问题:如果相邻区间在边界点不连续,会导致:
-
多值映射:同一个内部值可能对应多个物理值
-
无法确定唯一解:反向计算时不知道应该用哪个区间
举例:
区间1: [0, 10], Y = 2X + 1
区间2: [10, 20], Y = 3X + 5
-
当 X = 10 时:
-
区间1: Y = 2×10 + 1 = 21
-
区间2: Y = 3×10 + 5 = 35
-
问题:X = 10 对应两个不同的 Y 值,无法确定唯一映射
-
-
所有区间的$V_{N1}$(斜率)必须同号或为0 (the $V_{N1}$ of all intervals shall have the same sign or shall be 0)
问题:如果不同区间的斜率符号不同,会导致:
-
非单调函数:函数不是严格递增或递减
-
多值映射:同一个物理值可能对应多个内部值
举例:
区间1: [0, 5], Y = 2X + 1 // 斜率为正
区间2: [5, 10], Y = -X + 15 // 斜率为负
-
当 Y = 8 时:
-
区间1: X = (8-1)/2 = 3.5
-
区间2: X = 15-8 = 7
-
问题:Y = 8 对应两个不同的 X 值
-
-
如果 $V_{N1}$ = 0,必须指定 COMPU-INVERSE-VALUE(If $V_{N1}$ = 0, COMPU-INVERSE-VALUE shall be specified)
问题:当 $V_{N1}$ = 0 时,函数变为常数函数 Y = $V_{N0}$
-
无法反向计算:无法从 Y 值反推 X 值
-
需要额外信息:必须明确指定反向映射关系
举例:
区间: [0, 10], Y = 0×X + 5 = 5
-
无论 X 取何值,Y 都等于 5
-
反向计算时,知道 Y = 5,但无法确定 X 的具体值
-
可用的数据类型:
Internal | Physical |
---|---|
A_INT32 | A_INT32 |
A_UINT32 | A_UINT32 |
A_FLOAT32 | A_FLOAT32 |
A_FLOAT64 | A_FLOAT64 |
示例
$$ f(x) = \begin{cases} 1 + 2x , x \in [0,2) \\ 3 + x , x \in [2,5) \\ 8,x \in [5,+∞) \end{cases} $$
<COMPU-METHOD>
<CATEGORY>SCALE-LINEAR</CATEGORY>
<COMPU-INTERNAL-TO-PHYS>
<COMPU-SCALES>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE="CLOSED">0</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE="OPEN">2</UPPER-LIMIT>
<COMPU-RATIONAL-COEFFS>
<COMPU-NUMERATOR>
<V>1</V>
<V>2</V>
</COMPU-NUMERATOR>
<COMPU-DENOMINATOR>
<V>1</V>
</COMPU-DENOMINATOR>
</COMPU-RATIONAL-COEFFS>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE="CLOSED">2</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE="OPEN">5</UPPER-LIMIT>
<COMPU-RATIONAL-COEFFS>
<COMPU-NUMERATOR>
<V>3</V>
<V>1</V>
</COMPU-NUMERATOR>
<COMPU-DENOMINATOR>
<V>1</V>
</COMPU-DENOMINATOR>
</COMPU-RATIONAL-COEFFS>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE="CLOSED">5</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE="INFINITE"/>
<COMPU-RATIONAL-COEFFS>
<COMPU-NUMERATOR>
<V>8</V>
<V>0</V>
</COMPU-NUMERATOR>
<COMPU-DENOMINATOR>
<V>1</V>
</COMPU-DENOMINATOR>
</COMPU-RATIONAL-COEFFS>
</COMPU-SCALE>
</COMPU-SCALES>
</COMPU-INTERNAL-TO-PHYS>
</COMPU-METHOD>
4.Rational function
有理函数,和线性函数的区别是:有理函数的分母是 X 的函数,而线性函数的分母是常数。有理函数的分子也不仅限于1次方了,可以是平方、立方、n次方了。
注意:这种类型不允许反向计算。
$$ f(x)=\frac{V_{N0}+ V_{N1}*x+V_{N2}*x^2+…+V_{Nn}*x^n}{V_{D0}+V_{D1}*x+V_{D2}*x^2+…+V_{Dm}*x^m} $$ 可用的数据类型:
Internal | Physical |
---|---|
A_INT32 | A_INT32 |
A_UINT32 | A_UINT32 |
A_FLOAT32 | A_FLOAT32 |
A_FLOAT64 | A_FLOAT64 |
示例 $$ f(x) = x^2, x \in [0,+∞) $$
<COMPU-METHOD>
<CATEGORY>RAT-FUNC</CATEGORY>
<COMPU-INTERNAL-TO-PHYS>
<COMPU-SCALES>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE="CLOSED">0</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE="INFINITE"/>
<COMPU-RATIONAL-COEFFS>
<COMPU-NUMERATOR>
<V>0</V>
<V>0</V>
<V>1</V>
</COMPU-NUMERATOR>
<COMPU-DENOMINATOR>
<V>1</V>
</COMPU-DENOMINATOR>
</COMPU-RATIONAL-COEFFS>
</COMPU-SCALE>
</COMPU-SCALES>
</COMPU-INTERNAL-TO-PHYS>
</COMPU-METHOD>
5.Scale rational function
分段有理函数,和分段线性函数类似,只是将线性函数换成了有理函数。区间的限制和分段线性函数是类似的。
注意:这种类型不允许反向计算。
$$ f(x) = \begin{cases} \frac{V_{N0}^1 + V_{N1}^1 x + V_{N2}^1 x^2 + \cdots + V_{Nn}^1 x^n}{V_{D0}^1 + V_{D1}^1 x + V_{D2}^1 x^2 + \cdots + V_{Dm}^1 x^m}, & x \in I_1 \\ \cdots \\ \frac{V_{N0}^k + V_{N1}^k x + V_{N2}^k x^2 + \cdots + V_{Nn}^k x^n}{V_{D0}^k + V_{D1}^k x + V_{D2}^k x^2 + \cdots + V_{Dm}^k x^m}, & x \in I_k \end{cases} $$
可用的数据类型:
Internal | Physical |
---|---|
A_INT32 | A_INT32 |
A_UINT32 | A_UINT32 |
A_FLOAT32 | A_FLOAT32 |
A_FLOAT64 | A_FLOAT64 |
示例 $$ f(x) = \begin{cases} x^2, x \in [0,2) \\ … \\ \frac{ 6 + x } { 2 }, x \in [2,+∞) \ \end{cases} $$
<COMPU-METHOD>
<CATEGORY>SCALE-RAT-FUNC</CATEGORY>
<COMPU-INTERNAL-TO-PHYS>
<COMPU-SCALES>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">0</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE = "OPEN">2</UPPER-LIMIT>
<COMPU-RATIONAL-COEFFS>
<COMPU-NUMERATOR>
<V>0</V>
<V>0</V>
<V>1</V>
</COMPU-NUMERATOR>
<COMPU-DENOMINATOR>
<V>1</V>
</COMPU-DENOMINATOR>
</COMPU-RATIONAL-COEFFS>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">2</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE = "INFINITE"/>
<COMPU-RATIONAL-COEFFS>
<COMPU-NUMERATOR>
<V>6</V>
<V>1</V>
</COMPU-NUMERATOR>
<COMPU-DENOMINATOR>
<V>2</V>
</COMPU-DENOMINATOR>
</COMPU-RATIONAL-COEFFS>
</COMPU-SCALE>
</COMPU-SCALES>
</COMPU-INTERNAL-TO-PHYS>
</COMPU-METHOD>
6.Text table
文本表格,可以理解成枚举类型,或者说字典。通常只需要指定<COMPU-INTERNAL-TO-PHYS>就可以在两个方向上使用。使用<UPPER-LIMIT> 和 <LOWER-LIMIT>定义一个区间。多个<COMPU-SCALE>可能会有区间重叠,需要按照odx的文档顺序处理,取第一个匹配的区间,可以定义一个<COMPU-DEFAULT-VALUE>作为默认物理值来应对不在任意区间的情况。在反向计算时,如果<COMPU-INVERSE-VALUE>存在就使用作为定义,不存在的话就用<LOWER-LIMIT>定义。与线性函数类似,一个物理值只能对应一个内部值。如果内部值是字符串类型,就不允许定义范围。如果明确指定了元素的<UPPER-LIMIT>,这个值必须等同于<LOWER-LIMIT>。
当有 <COMPU-PHYS-TO-INTERNAL> 指定了反向计算的规则时,物理值在<LOWER-LIMIT>中定义,<UPPER-LIMIT> 应该省略或者与<LOWER-LIMIT>相同。
多个<COMPU-SCALE>可能会有区间重叠,需要按照odx的文档顺序处理,取第一个匹配的区间的内部值。
可用的数据类型:
Internal | Physical |
---|---|
A_INT32 | A_UNICODE2STRING |
A_UINT32 | |
A_FLOAT32 | |
A_FLOAT64 | |
A_ASCIISTRING | |
A_UTF8STRING | |
A_BYTEFIELD | |
A_UNICODE2STRING |
示例
Internal | Physical |
---|---|
[0,5) | “OFF” |
[5,9) | “ON” |
[9,+∞) | “OVERLOAD” |
<COMPU-METHOD>
<CATEGORY>TEXTTABLE</CATEGORY>
<COMPU-INTERNAL-TO-PHYS>
<COMPU-SCALES>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">0</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE = "OPEN">5</UPPER-LIMIT>
<COMPU-INVERSE-VALUE>
<V>0</V>
</COMPU-INVERSE-VALUE>
<COMPU-CONST>
<VT>OFF</VT>
</COMPU-CONST>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">5</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE = "OPEN">9</UPPER-LIMIT>
<COMPU-INVERSE-VALUE>
<V>5</V>
</COMPU-INVERSE-VALUE>
<COMPU-CONST>
<VT>ON</VT>
</COMPU-CONST>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">9</LOWER-LIMIT>
<UPPER-LIMIT INTERVAL-TYPE = "INFINITE"/>
<COMPU-INVERSE-VALUE>
<V>9</V>
</COMPU-INVERSE-VALUE>
<COMPU-CONST>
<VT>OVERLOAD</VT>
</COMPU-CONST>
</COMPU-SCALE>
</COMPU-SCALES>
<COMPU-DEFAULT-VALUE>
<VT>UNDEF</VT>
</COMPU-DEFAULT-VALUE>
</COMPU-INTERNAL-TO-PHYS>
</COMPU-METHOD>
7.Tab interpolated
表格插值,这种类型的只有<LOWER-LIMIT>和 <COMPU-CONST/V >可用。<UPPER-LIMIT> 应该省略或者与<LOWER-LIMIT>相同。
正向计算(内部值 → 物理值)
-
查找区间:
输入的内部值 X,查找它落在哪两个相邻的 LOWER-LIMIT 之间。
例如,X=15 落在 10 和 20 之间。
-
线性插值:
用这两个点的物理值做线性插值:
$Y=Y_1+\frac{(X−X_1)}{(X_2−X_1)}×(Y_2−Y_1)$
其中 $(X_1,Y_1) $和 $(X_2,Y_2)$是区间两端的点。
如果 X 小于最小的 LOWER-LIMIT 或大于最大的,ODX 标准要求报错。
反向计算(物理值 → 内部值)
反向查找时,先在物理值区间查找,然后用线性插值公式反推 X
可用的数据类型:
Internal | Physical |
---|---|
A_INT32 | A_INT32 |
A_UINT32 | A_UINT32 |
A_FLOAT32 | A_FLOAT32 |
A_FLOAT64 | A_FLOAT64 |
示例
nternal | Physical |
---|---|
0 | 0 |
2 | 5 |
4 | 8 |
8 | 10 |
10 | 10 |
<COMPU-METHOD>
<CATEGORY>TAB-INTP</CATEGORY>
<COMPU-INTERNAL-TO-PHYS>
<COMPU-SCALES>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">0</LOWER-LIMIT>
<COMPU-CONST>
<V>0</V>
</COMPU-CONST>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">2</LOWER-LIMIT>
<COMPU-CONST>
<V>5</V>
</COMPU-CONST>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">4</LOWER-LIMIT>
<COMPU-CONST>
<V>8</V>
</COMPU-CONST>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">8</LOWER-LIMIT>
<COMPU-CONST>
<V>10</V>
</COMPU-CONST>
</COMPU-SCALE>
<COMPU-SCALE>
<LOWER-LIMIT INTERVAL-TYPE = "CLOSED">10</LOWER-LIMIT>
<COMPU-CONST>
<V>10</V>
</COMPU-CONST>
</COMPU-SCALE>
</COMPU-SCALES>
</COMPU-INTERNAL-TO-PHYS>
</COMPU-METHOD>
8.Computational code
计算代码。可以运行Java语言编写的代码。一般都不会使用
需要实现这样的一个接口。
public interface I_CompuCode {
public Object compute(Object input);
}
Java语言和ODX物理值映射的定义:
- A_INT32 to Integer
- A_UINT32 to Long
- A_FLOAT32 to Float
- A_FLOAT64 to Double
- A_BYTEFIELD to byte[]
- A_ASCIISTRING to String (Unicode)
- A_UTF8STRING to String (Unicode)
- A_UNICODE2STRING to String (Unicode)
这种方式可以使用所有的数据类型。<COMPU-SCALE>和<COMPU-DEFAULT-VALUE>不可用。
不能通过代码来进行反向计算。如果需要的话,可以指定<COMPU-INTERNAL-TO-PHYS>
有三种方式引用Java代码。
- .java代码源文件
- .class字节码文件
- .jar jar包文件
示例
-
Java文件
<COMPU-METHOD> <CATEGORY>COMPUCODE</CATEGORY> <COMPU-INTERNAL-TO-PHYS> <PROG-CODE> <CODE-FILE>myCompucode2.java</CODE-FILE> <SYNTAX>JAVA</SYNTAX> <REVISION>1.0</REVISION> </PROG-CODE> </COMPU-INTERNAL-TO-PHYS> <COMPU-PHYS-TO-INTERNAL> <PROG-CODE> <CODE-FILE>myCompucode2.java</CODE-FILE> <SYNTAX>JAVA</SYNTAX> <REVISION>1.0</REVISION> </PROG-CODE> </COMPU-PHYS-TO-INTERNAL> </COMPU-METHOD>
-
class文件
<COMPU-METHOD> <CATEGORY>COMPUCODE</CATEGORY> <COMPU-INTERNAL-TO-PHYS> <PROG-CODE> <CODE-FILE>myCompucode1</CODE-FILE> <SYNTAX>CLASS</SYNTAX> <REVISION>1.0</REVISION> </PROG-CODE> </COMPU-INTERNAL-TO-PHYS> </COMPU-METHOD>
-
Jar包
<COMPU-METHOD> <CATEGORY>COMPUCODE</CATEGORY> <COMPU-INTERNAL-TO-PHYS> <PROG-CODE> <CODE-FILE>allCompucode.jar</CODE-FILE> <SYNTAX>JAR</SYNTAX> <REVISION>1.0</REVISION> <ENTRYPOINT>myCompucode1</ENTRYPOINT> </PROG-CODE> </COMPU-INTERNAL-TO-PHYS> </COMPU-METHOD>