1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AGL の can-low-level を読んでみる①(デコード・エンコード)

Last updated at Posted at 2023-03-12

AGL とは?

Automotive Grade Linux (以下、AGL) という コネクテッドカーに活用するオープンプラットフォームを開発する OSSのプロジェクト。
コネクテッドカーに関する 知見がつまっています。

can-low-level とは?

CAN 通信を、以下のような簡単なコマンドで解析できるようにするツール(リンクはこちら)。

まずは subscribe で サブスクライブ。

入力 > low-can subscribe { "event": "doors.driver.open" }
出力結果 > ON-REPLY 1:low-can/subscribe: {"jtype":"afb-reply","request":{"status":"success","uuid":"a18fd375-b6fa-4c0e-a1d4-9d3955975ae8"}}

イベントを検知すると、以下のような結果が出てくる

出力結果 > ON-EVENT low-can/messages.doors.driver.open({"event":"low-can\/messages.doors.driver.open","data":{"name":"messages.doors.driver.open","value":true, "timestamp": 1505812906020023},"jtype":"afb-event"})

そのコードがこちらにあります。
自分もまだコードを読んでいる途中なんですが、最初は分からなかったことだらけだったので、こうして記事にしてその概要をまとめようとしています。

では、そのコードを読んでみましょう。。。

の、前に OpenXC という知識が必要になるので、その説明をします。

OpenXC

コードを読む前に、前提知識として この OSS には OpenXC という 自動車用API とも言える OSS を知っておく必要があります。

簡単に説明する(間違っていたらご指摘ください)と、CAN 通信ではデータフレームにデータを積み込めるんですが、そのメッセージはあくまでも bit 形式 で送られてくるので、その中に key-value でいうところの key などをつめこんでいては、容量がすぐ大量になってしまいます(CAN-FD はあるんでしょうけど)。
なので、最初にCAN 通信で送る データフレームのフォーマットを決めといておいて(何bit目にはどのデータが何bit入っている。など)、CAN 通信自体では データのみ(key-value でいうところの value のみ)を送るようにしています。

その送り方が、

に書いてあります。

スクリーンショット 2023-03-13 0.31.12.png

このような部分です。上の画像で言うと、0x102 が CAN 通信のデータフレーム全体でいうところの 位置を示していて、その中での bit の位置・bit の長さが bit_position, bit_size に書いてあります。さらに、その bit の結果の offset が そこから足し引きをする数値・factor が掛け算をする数値に、generic_name が 先ほどの説明で出てきたところの key に当たる情報になっています。

OpenXC では、このようなデータのフォーマットを先に決めといて、それに従って 集めた車の情報から key を取り除いた value のみのデータフレームを作り CAN 通信で送信し、受け取った方はその メッセージを 上のフォーマットでデコードして必要な情報を取得します。

データフレームのデコード・エンコードをコードから読んでみよう!

ここまでで、OpenXC について説明したのですが、そのデータのデコード・エンコードを読んでみましょう。
復習になりますが、データフレームのデコード・エンコードはそれぞれ、

エンコード : 車の情報を集めて、その value を 上記のフォーマット情報に従って埋め込み、新しいデータフレームを作成する。

→ 車の情報を埋め込んだデータフレームの作成

デコード  : エンコードされた情報と上記のフォーマット情報に従って、エンコードされたデータフレームの bit の位置情報・長さから必要な情報を取得する。

→ エンコードされた情報から必要な情報を取得

のような内容になります。

それぞれが書かれた場所は、デコードだと /low-can-binding/can/can-decoder.cpp にあり、エンコードだと /low-can-binding/can/can-encoder.cpp にあります。

では、コードを読んでみましょう!
まずは、エンコードから読んでみます。エンコードをしているコードは、build_message になるんですが、その中で呼び出されている build_frame が重要です。build_frame 内にある

can-encoder.cpp
	for(const auto& sig: signal->get_message()->get_signals())
		encode_data(sig, data, false, factor, offset);

で、車載データを受け取り for文で回し、それを encode_data しています(data 部分にエンコードした情報が入っていきます)。
この encode_data の関数内の最後の部分で、

can-encoder.cpp
	for(size_t i = new_start_byte; i <= new_end_byte ; i++)
		data[i] = data[i] | data_signal[i-new_start_byte];

で、該当するビットの部分にデータを挿入しています。
こうやって、車のデータをデータフレームにつめ込んでいます。

次に、デコードを見てみます。
デコードするときは、データフレームの情報のみならず、

スクリーンショット 2023-03-13 0.56.26.png

の jsonファイルから、デコードする情報の bit位置・bit長さ・offset・factor そして、decodeの方法( decoder_t::decode_boolean )・上記の説明でいうところの key (generic_name)を取得して、必要な情報を取得します。
ここではちょうど出てきた decode_boolean を見てみます。

can-decoder.cpp
openxc_DynamicField decoder_t::decode_boolean(signal_t& signal, std::shared_ptr<message_t> message, bool* send)
{
	float value = decoder_t::parse_signal_bitfield(signal, message);
	AFB_DEBUG("Decoded message from parse_signal_bitfield: %f", value);
	openxc_DynamicField decoded_value = build_DynamicField(value == 0.0 ? false : true);

	// Don't send if they is no changes
	if ((signal.get_last_value() == value && !signal.get_send_same()) || !*send )
		*send = false;

	signal.set_last_value(value);


	return decoded_value;
}

なんとなく、boolean を取得して、それを返しているのが分かるのではないでしょうか?
parse_signal_bitfield も内容を見れば分かるので、マイナスの時の対応 が少し複雑くらいなだけで、基本的には データフレーム( message_t )から bit位置とbit長さを取得して、データを返しているだけです。

ここまでで、データのエンコードとデコードを見てみました。
今回はここまでにします。
ここまで読んでいただいて、ありがとうございました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?