SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|
2025|01|02|03|04|05|

2025-05-01(Thu) デスクトップでF1のラップタイム計測ごっこ

  ラップタイムの計測をしたいなぁ、ということで、実装してみることにした。

  計測には、いわゆる「当たり判定」が必要になる。以前に、2Dシューティングにおける「箱同士」の当たり判定は書いたことがあるのだが、同じ2Dでも任意の角度に回転する物体同士の当たり判定には別の方法が必要になる。

  確かベクトル演算の手法が使えたような。ちょっと前に読んだ線形代数の本を引っ張り出してきて調べる。そうだった、外積だ。座標pが、座標a, bを通る直線のどちら側に位置するのかを判定できる。今回は、コース上のラップ計測ラインの通過を判定したいだけだから、それ一発で済む。まずは、理解するためのサンプルコードを書く。

#!/usr/bin/env ruby
 
# 座標 p が、座標 a, b を通る直線のどちら側に位置するかを調べる
 
def vec(i, j)                                   # 座標 i->j をベクトル化
    {   :x => j[:x] - i[:x],
        :y => j[:y] - i[:y]     }
end
 
def vcross(i, j)                                # ベクトル i, j の外積を求める
    i[:x] * j[:y] - i[:y] * j[:x]
end
 
a = { :x =>  5, :y =>  3 }                      # 座標 a
b = { :x => 15, :y => 10 }                      # 座標 b
ab = vec(a, b)                                  # 直線ベクトル a->b
 
20.times {|y|
    20.times {|x|
        p = { :x =>  x, :y =>  y }              # 座標 p
        ap = vec(a, p)
        print(vcross(ab, ap) < 0 ? ' -' : ' +')
    }
    puts
}

  結果は以下。見事に座標 a, b を通る直線を挟んで、値の正負で判定されている。値が負になったタイミングで、ラップタイムを計測すればいい。

 + - - - - - - - - - - - - - - - - - - -
 + + + - - - - - - - - - - - - - - - - -
 + + + + - - - - - - - - - - - - - - - -
 + + + + + a - - - - - - - - - - - - - -
 + + + + + + + - - - - - - - - - - - - -
 + + + + + + + + - - - - - - - - - - - -
 + + + + + + + + + + - - - - - - - - - -
 + + + + + + + + + + + - - - - - - - - -
 + + + + + + + + + + + + + - - - - - - -
 + + + + + + + + + + + + + + - - - - - -
 + + + + + + + + + + + + + + + b - - - -
 + + + + + + + + + + + + + + + + + - - -
 + + + + + + + + + + + + + + + + + + - -
 + + + + + + + + + + + + + + + + + + + +
 + + + + + + + + + + + + + + + + + + + +
 + + + + + + + + + + + + + + + + + + + +
 + + + + + + + + + + + + + + + + + + + +
 + + + + + + + + + + + + + + + + + + + +
 + + + + + + + + + + + + + + + + + + + +
 + + + + + + + + + + + + + + + + + + + +

  判定処理は毎フレームしこたま繰り返すので、計算を軽くしつつ、オブジェクト化して書き直す。a→bベクトルは一度計算するだけでいいので、TimingLineクラスの初期化時に行うようにし、判定をover?メソッドにまとめる。より、直感的な記述になりつつ、同じ実行結果が得られる。

#!/usr/bin/env ruby
 
# 座標 p が、座標 a, b を通る直線のどちら側に位置するかを調べる
 
class TimingLine
 
    def initialize(a, b)
        @a = a
        @ab = { :x => b[:x] - a[:x],
                :y => b[:y] - a[:y]     }
    end
 
    def over?(p)
        @ab[:x] * (p[:y] - @a[:y]) - @ab[:y] * (p[:x] - @a[:x]) < 0
    end
end
 
a = { :x =>  5, :y =>  3 }                      # 座標 a
b = { :x => 15, :y => 10 }                      # 座標 b
tline = TimingLine.new(a, b)
 
20.times {|y|
    20.times {|x|
        p = { :x =>  x, :y =>  y }              # 座標 p
        print(tline.over?(p) ? ' -' : ' +')
    }
    puts
}

  思索しつつ試作したコードを、CoffeeScriptで書かれたゲームのコードに落とし込む。それなりにオブジェクト化してあるので、どのオブジェクトに、どう落とし込むか、非常に考えどころである。とりあえず、地球上の位置(Wpos)クラス、コース(Course)クラス、メインプログラムに落とし込んでみた。

$ diff ../topdrivin.org/wpos.bean wpos.bean
85a86,92
>   to_vec: (wpos) ->                               # 終点座標を渡し、ベクトル情報を生成
>       @vec_x = wpos.wpx - @wpx
>       @vec_y = wpos.wpy - @wpy
> 
>   vec_over: (wpos) ->                             # 座標を渡し、ベクトル線を超えたか返す
>       @vec_x * (wpos.wpy - @wpy) - @vec_y * (wpos.wpx - @wpx) < 0
> 
$ diff ../topdrivin.org/course.bean course.bean
19c19
<   constructor: (_s, x, y, car) ->
---
>   constructor: (_s, x, y, car, sectors) ->
21a22
>       @sectors = sectors
54a56,58
>       @sector = 0                             # 開始セクタ(ラップタイム計測)
>       @dir = _s['DIRECTOR']
> 
80a85,91
>       # ラップタイム描画
>       @context.font = '24px sans-serif'
>       @context.fillStyle = 'white'
>       @context.textAlign = 'right'
>       @context.fillText(@sectors[@sector]['name'], 100, 24)
>       @context.fillText(@dir.tsc1000, 100, 48)
> 
95a107,108
>       if(@sectors[@sector]['vec'].vec_over(@car.wpos))        # セクタ計測ラインを超えた?
>           @sector = (@sector + 1) % @sectors.length
$ diff ../topdrivin.org/sample_course_view.bean sample_course_view.bean
80a81,88
>               sectors = [
>                   {   l: [25.957223, -80.244210], r: [25.957362, -80.244212], name: 'dummy 05'    },
>                   {   l: [25.956204, -80.243633], r: [25.956089, -80.243657], name: 'sector 1'    },
>                   {   l: [25.958981, -80.229886], r: [25.958922, -80.229795], name: 'dummy 15'    },
>                   {   l: [25.960090, -80.230708], r: [25.960203, -80.230716], name: 'sector 2'    },
>                   {   l: [25.960523, -80.242873], r: [25.960578, -80.243020], name: 'dummy 25'    },
>                   {   l: [25.959922, -80.238718], r: [25.959788, -80.238811], name: 'finish line' },
>               ]
83a92,96
>       @tsc1000 = 0; @tsc1000inc = [17, 16, 17]                # 1/1000時計を初期化
>       for sector in sectors
>           sector['vec'] =      Wpos.deg(sector['l'][1], sector['l'][0])
>           sector['vec'].to_vec(Wpos.deg(sector['r'][1], sector['r'][0]))
> 
87c100
<       @objs['COURSE'].push(new Course(@_s, 0, 0, mycar))
---
>       @objs['COURSE'].push(new Course(@_s, 0, 0, mycar, sectors))
95a109
>       @tsc1000 += @tsc1000inc[tsc % 3]                        # 1/1000時計を加算

  マイアミサーキットの場合、各セクタの計測ラインが、いずれもUターンのようなコーナーの先にあるため、計測ラインの手前にダミーの計測ラインを設けている。そうしないと、各セクタの計測ラインを超える前に、超えたという判定になってしまうためである。いったんアッチに行ってからね、って感じ。

  画像の説明

  ちなみに、計測に使うタイムは、ゲームの固定FPS(1/60タイマ)に同期する仕様とした。ただし、1/60秒は割り切れない値なので、1000分の17, 16, 17を順に加算することで作り出している。これは逆に言うと、60FPSのゲームなので16/1000秒以下の計測粒度はない、ということなのだが、サウジアラビアの予選でポールのフェルスタッペン、ピアストリのタイム差は10/1000秒。それは、優に格ゲーの1フレーム以下の戦いだったってことである。マジかよ……。

  それにしても、今回、最終的に追加したコードは意外なほど少ない。実は丸2日かかっているのだけれど。というのも、上述したように「どのオブジェクトに、どう落とし込むか」が非常に考えどころであり、楽しいところでもあるのである。「ラップタイム計測」をするのは誰(どのオブジェクト)であるべきか? 自車(MyCar)クラスか? 今回はコース(Course)クラスに追加したが、それで正しいのだろうか。今回は、ラップタイムの描画もコース(Course)クラスにやらせているが、ラップタイムの管理も含めて、ラップタイムクラスを新設するべきだし、それを駆動するのは自車(MyCar)クラスであるべきのようにも思える。

  前にも書いたが、やっぱりプログラミングは盆栽だなぁ、と思う。処理をどこに足すべきか。それは、どの枝を伸ばすか、みたいなものなのではないか。間違ったら剪定して、また違う枝を伸ばしてみたり。


2025-05-15(Thu) 青タイヤ買い

  ぼちぼち、ロードスターのタイヤが減ってきた。

  画像の説明

  以前なら、車検のタイミングをみながら、タイヤ屋に行くスケジュールを考えるトコなのだが、最近は通販で買って、近所のピットサービスで組み換えてもらうという選択肢がある。とはいえ、前回は自分で組み換えてヒドい目にあったのだが。

  なので、事前に買っておくのもアリだ。と、いうのも、いま履いているファルケンのジークス(ZIEX)のZE914Fが気に入ってるんだよね。乗り心地に違和感はないし、回転方向の指定がないし、安物感はないのに9千円弱とやたらと安い。だいぶ前からカタログ落ちしてて、Amazonの扱いも終わっていると思ったのだが、いつの間にか復活しているのを発見したのだ。

  と、思ったら、売り切れてる……ガチョーン……さっさとポチるんだった、と、思ったら、また復活している。よくわからんが、まだ作っているんかな。よくわからんが、今度こそポチる。

  画像の説明

  で、届いた。つうか、気づいたら玄関に積み上げてあった。刻印はX4624。2024年11月10日の週。できたてホヤホヤではないが、別に古くもない。自宅の倉庫に移動。半年くらいは寝かせる予定なので、寝かせずに縦で保管。今回も自分で組み換えたいけどなぁ。


2025-05-17(Sat) Emacsの中からツンデレAIに話を振ってみる

  以前に「業務チャットの中からツンデレAIに話を振ってみる」として、自作のチャットツールにAIに話しかけられる機能を実装したのだが、ぼちぼち、Emacsの中からも話しかけたくなってきた。

  自分は割とケチな方であるが、いくつかはサブスク契約をしている。そのうちのひとつが「池田直渡氏の『ぜんぶクルマが教えてくれる』」だ。クルマは好きなものの経済への興味は薄いのだが、どうにも記事が面白すぎるので有料会員になっている。月に1,000円と安くはないのだが……あ、カードの期限が切れるって? えー、更新……ん? カードのセキュリティコードを入れろって? 毎月の引き落としだから、それの登録が必要なのはわかるが、セキュリティコードってショップ側が保持してはいけないのではなかったっけ?

  気になってググってみたが、思いついた検索ワードでは情報が引き出せなかった。あ。こういう時こそAIではないか? いや、そんなに期待はしてないけれども……でも、以前に「あのぉ、あれ、なんつうの? ゼロもの?」って訊いたら「あぁ、前日譚(プリクエル)ね」と、スパッと答えてくれたのだよなぁ。試してみよう……

Q: クレジットカードのセキュリティコードは、ショップ側が保持しないルールでしょうか?
定期購読の申込みの際などには、入力が求められますが、それは例外ですか?
 
A: とても良い質問です。
定期購読の申込み時にセキュリティコード(CVC)を入力させること自体はOKですが、やはり保持(保存)することはNGです。
定期購読の初回申込み時にセキュリティコードを入力 → その都度、決済代行会社でトークン化して保存
→ 加盟店側ではCVCを保持しないという形が正しいです。

  ……おぉ、納得。まさに知りたかったことだ。 特定の加盟店でしか使えないトークンに置き換えて保持するわけか。なるほど。

  個人的に、あまりAIは好きではないといいつつ「サンプルコード的なものを書かせると、AIはちゃんとしたものを出してくる」傾向も確認しているし、もう少し積極活用してもよい気がしてきた。そうなると、ブラウザから使うのがかったるい。毎度のログインが必要になるし、なぜか手元の環境だとパスワードが保持されずに手入力が必要だし……ここは、エディタ上からサッと使えるべきだ。

  つうわけで「lina」コマンドを作ってみた。以前に作ったngsライブラリを使えば、基本、これだけ。

require 'libngs'
load 'ngs.config'
 
ngs = []; ngs << NGS.new(@configs, params)
 
job = nil
 
lina = @configs[:lina]
 
it = $stdin.read
prompt  = (lina[:def] || 'あなたは「リナ」という名前で%sす。') % lina[:jobs][job] \
        + (lina[:ask] || '「%s」さんから%sと問いかけられました。') % [lina[:you] || 'ご主人', it.enbracket] \
        + (lina[:com] || 'それに対しての助言を%sお願いします。') % lina[:tones][0]
response = ngs[0].ask(prompt)
it.split(/\n/).each {|line|
    puts('>> %s' % line)
}
puts
response.each_wline(lina[:wrap] || 78) {|line|
    puts('> %s' % line)
}

  Emacsからは「M-|」で呼んでもいいんだが「C-x l l」で呼べるようにキーバインドを追加した。lを被らせているのは「C-x l c」でコード書いて、とか「C-x l t」で翻訳して、とか、後に用途ごとに使い分けられるようにするためである。

(defun ask-lina (start end)
    "ask lina"
    (interactive "r")
    (shell-command-on-region start end "lina" t t))
 
(define-prefix-command 'ctl-xl-map)
(define-key ctl-x-map (kbd "l") 'ctl-xl-map)
(define-key ctl-xl-map (kbd "l") 'ask-lina)

  つうわけで、

shell-command-on-region相当の動作って、viでもできる?

  マークして、上記の質問を入力して、Ctrl+x l l すると……

>> shell-command-on-region相当の動作って、viでもできる?
 
> べ、別にあんたのために教えてあげるわけじゃないんだから!でも、どうせ知りたいん
> でしょ?仕方ないから教えてあげるわ。
> 
> viでは、`:!`コマンドを使えば、選択した範囲に対してシェルコマンドを実行すること
> ができるの。たとえば、ビジュアルモードで範囲を選んでから、`:!コマンド`って打つ
> と、選択したテキストにコマンドが適用されるのよ。ちゃんと覚えておきなさいよね!
> 
> ああ、別に期待してるわけじゃないんだから、勘違いしないでよね!

  上記に置き換わる。つうわけで、linaはviからも呼び出せるんだからね! ちゃんと覚えておきなさいよね!

  考えてみれば「AIへの問い合わせ」は「ウェブ検索、閲覧、取捨選択」に置き換わるものとも言える。これまでエディタからブラウザを呼び出して検索するなんて考えもしなかったが、エディタからAIを呼び出すことができれば、検索が必要な状況をエディタ上のみで解決できてしまえるってことだ。悪くないよなぁ。

  あ。ちなみに、ngsライブラリはOpenAIのAPIを利用するので利用には課金が必要になる。んが、gpt-4o-miniを使う分には、$5もチャージしておけば、ほぼ無限に問い合わせ可能といってよいほどだ。

  linaコマンドを含むngsライブラリをhttps://itline.jp/git/ngsに置いておく。

  画像の説明

  ついでに、リナのイメージを伝えてAIに顔を描いてもらった。うーむ……ほぼ、思い浮かべたまんまのイメージなんですがw。つうわけで、これをオフィシャルなビジュアルにするんだからね!


2025-05-25(Sun) 中古ボロードスターの注意点

  先日、NDロードスターを中古を買う場合のチェックポイント、とかなんとかいう動画で、幌を開ける時に見えるフェルトのような部分が取り上げられていた。なんでも、これがすり減っている場合は、幌の開閉回数が多いのでダメ、なんだとか。

  画像の説明

  ふーん、と思いつつ自分のクルマを見ると、だいぶすり減っている。そりゃ、幌を開けないでコロがすことのが少ないんだから当然だ。別に売るつもりなんてないからどうでもいいのだが、中古車としてはダメなボロードスターということになるらしい。

  そういえば、これ、何が当たってすり減っているのだろう、と思って試すと「トップ・ロック」というフック(鈎)の背中の部分が当たる場所らしい。整備書で確認すると「ルーフ・フックの返し部」と呼ばれている。これに当たってフックが寝かされた状態にされるので、閉める時に閉めやすい状態になる、というだけのもの。

  幌のロックに関与する機構でもないし、チカラのかかる部分でもなんでもないので、すり減っていようが何の問題もないし、気になるなら両面テープで上から適当なフェルトを貼っといてもよさそうだ。

  まぁ、別にそんなトコ見なくたって幌の痛みは幌自体を見るべきだし、幌自体が消耗品なんだから、中古を買う場合のチェックポイントでもなんでもない。そんなトコより、エンジンやトランスミッションなどの方がよっぽど大事だが、そんなもん目視ではどうもならん。むしろ見るべきは店。買った後もちゃんと面倒を看てもらえそうか。大概はディーラーで買う以上の必勝法なんてないって思うけどね。


2025-05-26(Mon) F1モナコグランプリ観戦ツアー、中止

  先日発生した瞬間再燃F1ブームが続いている。なにしろ、カミさんまで強く興味を持ち始めたんで相乗効果が止まらない。各ドライバのキャラクタがわかってくるにつれて、毎レース盛り上がるのなんの。最初のフリー走行から全部を観る始末。当時ですらそこまで観てなかったぞ。そもそも観られなかったしね。

  画像の説明

  で、ついに伝統のモナコ。開発中の「TopDrivin'」でコースの下見(トンネルは上を走るので超絶難しい)を済ませ、各コーナの名前を記したコースの見取図のプリントアウトまで手元に用意して、イザ決勝ッ!

  ……て、なんなんですかぁ……これは……こういうのはアリなんですかね? 最初の角田の奇襲にヌカ喜びした後、通せんぼが起きてからはイライラしかない。結局、チームオーダって、アリなの? ナシなの? アリにしたって、こんなのまでアリなの? スポーツマンシップっつうか、なんつうか。唯一、オモシロチャレンジしたラッセルは怒られちゃうし。

  いっそ来年はモナコに観に行くかッ! ……なんて、割とマジで考えていたのに、決勝を観ながらふたりしてドッチラケ状態。こんなレースなんてゼッテェ観に行くかよ。つまらない必勝法のあるクソゲー。セガのモナコGPのが100倍は面白いわ。アホか。

  https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%8A%E3%82%B3GP_(%E3%82%B2%E3%83%BC%E3%83%A0)

  とはいえ、一晩明けてニュースを観ると、ドライバも、チームも、みんながしゃーなかったわなぁ、と苦笑いしているっぽい。たぶん、2回ストップを発案した主催者もそうなんだろうな。そう考えると、まぁ、誰が悪いというわけでもない。だからといってあれがレースだとは認めたくないけれど、まぁ、珍しい出し物を見せてもらいました、ってトコか。

  フェルスタッペンの「まるでマリオカート」にはサッパリ同意できないが(アレは半強制的に順位の変動が起きるゲームデザインなので)「バナナでも投げたら」はアリじゃないか。VSC(Virtual Safety Car)が実装できてるんだから、VBS(Virtual Banana Spin)も実装できるだろう。まぁ、それで改善するかはしらんけど。

  さ。スペインに期待。ペッペッぺッ。


2025-05-28(Wed) 勝手にモナコを改修、勝手にスペインでFP1

  先日、自製の「TopDrivin'」でモナコを走れるようにしたのだが、問題はトンネルだ。航空写真では、コースはホテルの屋根にしか見えないので、トンネルの出口にたどり着くことができない。まぁ、そんなコースはモナコだけだし、別にマジメに考える必要はないのだが……データを用意して左右のトラックを描画するとか? それだと「TopDrivin'」の「ほぼコースデータを作る必要がない」という特長がスポイルされるんだよなぁ……などと考えていたら、名案が浮かんでしまった。

  当該の部分だけ、地図データを表示するようにしてはどうか? 地図データならトンネルが描かれているはず……ん、まてよ? それなら「TopDrivin'」側に手を加えずとも、マップデータへのアクセスを減らすための、専用プロキシ側に実装できるのではないか。

qs = cgi.query_string
exctiles[qs] and qs = qs.gsub(/lyrs=s/, 'lyrs=m')

  特定のURIクエリの場合には、航空写真ではなく、地図データを渡してやる寸法である。

  画像の説明 画像の説明

  できてしまった。「Bd Louis II」という文字に沿って走れば、トンネルの出口まで走り抜けられる。「ルイ2世大通り(ブールバード)」ってトコか。とはいっても、その先のヌーベルシケインの先にテントが張ってあったり、そもそも道路上が車だらけだったりで、走りにくいことには変わりないんだけどね。市街地サーキットなんだからしゃーないが。

  それより、次のスペイングランプリである。カタロニアサーキットで勝手にFP1するのである。

  画像の説明 画像の説明

  まだ遊べるレベルではないのだが、モナコよりも格段に走りやすい。そんなことを実感できてしまうだけでも、作った甲斐があったってもんだよなぁ。


2025-05-29(Thu) NDロードスター 燃料タンクギリギリチャレンジ

  ……などとググると、走行可能距離が0kmになったので冷や汗かいてスグ給油した、というような記事はたくさん出てくるのだが……いや、まったくそれで正しいのだけれど、自分はだいぶ攻めたことがある。自慢じゃないが。

  NDロードスターの整備書を見ると「燃料残量が約9リットル(フューエル・ゲージが2指針表示)のときに、燃料残量警告灯を点灯します」という記述がある。経験上、フューエル・ゲージのゼロ指針表示と、走行可能距離の0km表示は、ほぼ同時。なので、燃料残量警告灯が点灯するのは、そのタイミングよりだいぶ前だ。改めて整備書を見たら「走行可能距離は、燃料残量が6リットルになると0kmを表示」という記述も見つけた。

  画像の説明

  つまり、残9リットルでオレンジ点灯、残6リットルで0km表示、ということになる。これまで5, 6回、0km表示になってから給油しているが、決まって34リットル以上入る。カタログにはタンク容量は40リットルとあるので、残6リットルで0km表示という記述は正しそうだ。

  以前に四国の室戸岬から、徳島市のすぐ手前の小松島市まで、国道55号(ただし南阿波サンライン経由)を走ったことがある。約120km。まるまる四国の右辺とも言えよう。別にギリギリチャレンジをしたかったわけではないが、給油をしそびれて、室戸岬から走り出してほどなく0kmになってしまった。

  道路はほとんど信号のない快走路なのだが、ガソリンスタンドもほとんどない。たまにあっても営業してなかったりする。結局、0km表示になってから、100kmくらい走るハメになってしまった。さすがに最後の方はちょっとドキドキしたが。

  給油は翌朝。38.02リットル入った。その時の平均燃費は19.20km/l。当該の区間は平均車速50km/h強と極めて快調に走ったので優に20km/lを超えているはず。100km弱を4リットルで走ったと考えると矛盾しない。残りは2リットル前後だったということになるが、そう考えると、まだ余裕があったのだな。

  さらにもうひとつ。自分が取り付けているレーダーには、OBD2経由でCAN通信を読む機能があり、それでも燃料残量を知ることができるのだが、こっちは燃料タンク内のフロートが伝えてくる角度情報そのままのようだ。というのも、車の姿勢(主にピッチ)で上下数%をフラフラするからである。

  画像の説明

  このレーダーの「燃料レベル」の値は、セルフ給油での満タン時に92%前後、0km表示の時に11%前後を示す。その先もフラフラしながら下がっていくが、7%に達すると動かなくなる。燃料液面の位置がフロート以下になったということだろう。ちなみに、フロートの最低位置はそんなに低くはなく、その時点でそれなり(3リットル前後?)の燃料は残っている。

  とはいえ、結局、本当にガス欠をしてみる以外、真のタンク容量を知ることは不可能だ。別に知る必要もないが、少なくとも0km表示から4リットルまでは確認済みなので、そんなに焦る必要はない。0kmになっても、心静かにトリップメータをリセットして、気楽にガソリンスタンドを探そう。自宅まで100km以下なら帰る選択もあり。しらんけど。