前置知识

内部值:从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} $$

同时对于分段线性函数反向计算的函数是有条件的;

  1. 相邻区间在公共边界上的值必须相等 (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 值,无法确定唯一映射

  2. 所有区间的$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 值

  3. 如果 $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>相同。

正向计算(内部值 → 物理值)

  1. 查找区间:

    输入的内部值 X,查找它落在哪两个相邻的 LOWER-LIMIT 之间。

    例如,X=15 落在 10 和 20 之间。

  2. 线性插值:

​ 用这两个点的物理值做线性插值:

​ $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物理值映射的定义:

  1. A_INT32 to Integer
  2. A_UINT32 to Long
  3. A_FLOAT32 to Float
  4. A_FLOAT64 to Double
  5. A_BYTEFIELD to byte[]
  6. A_ASCIISTRING to String (Unicode)
  7. A_UTF8STRING to String (Unicode)
  8. A_UNICODE2STRING to String (Unicode)

这种方式可以使用所有的数据类型。<COMPU-SCALE>和<COMPU-DEFAULT-VALUE>不可用。

不能通过代码来进行反向计算。如果需要的话,可以指定<COMPU-INTERNAL-TO-PHYS>

有三种方式引用Java代码。

  1. .java代码源文件
  2. .class字节码文件
  3. .jar jar包文件

示例

  1. 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>
    
  2. 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>
    
  3. 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>