toppers / hakoniwa-px4sim

PX4-compatible drone simulation with physics-based modeling in C, visualizations via game engines, headless operation, and automated test scenarios. Supports external parameterization and MATLAB/Simulink integration.
40 stars 12 forks source link

バッテリーのモデル化 #413

Open kenjihiranabe opened 2 weeks ago

kenjihiranabe commented 2 weeks ago

モデル策定案:

定数として、

$$ V_{bat} = voltage(full_charge, used_charge, i, temp); $$

さらに将来的には、放電回数による「劣化」も視野に入れる(最後のグラフ)。

マクニカの資料例 https://www.macnica.co.jp/business/semiconductor/articles/renesas/145231/

Image

Image

kenjihiranabe commented 2 weeks ago

平鍋担当である、モーターの電流計算を作りました。 これを積分して、上記の放電容量(used_charge)、の計算をしてください。> @tmori

https://github.com/toppers/hakoniwa-px4sim/blob/db433def7bb5a2faadc40a67600d0dadc0d9d83b/drone_physics/rotor_physics.cpp#L87

tmori commented 2 weeks ago

ありがとうございます! まずはバッテリモデルのクラス設計してみますね。

tmori commented 2 weeks ago

えいやで考えてみました。

Image

kenjihiranabe commented 2 weeks ago

お互いの考えがあってるか、補足してみました。 Image

tmori commented 2 weeks ago

Image

ここは、下図のようなモデルでVbatを求める認識ですね。

Image

tmori commented 2 weeks ago

Image

ここは、ローターの電流計算結果を積分するという認識ですね。

Image

tmori commented 2 weeks ago

Image ここは、Vbat × duty_rateなのかな?と思いましたが、どうでしょうか。

kenjihiranabe commented 2 weeks ago

あ、ですです、情報としての+で書きました、森さんの認識正しいです。

kenjihiranabe commented 2 weeks ago

電圧カーブは、C/C++ の関数としてコールバックを登録(もしくは Dependency Injection)するのがいい感じ。 多分、 《interface》 がそういうことを言っている?

tmori commented 2 weeks ago

電圧カーブは、C/C++ の関数としてコールバックを登録(もしくは Dependency Injection)するのがいい感じ。 多分、 《interface》 がそういうことを言っている?

はい、その通りです。 電圧カーブの関数インタフェースだけ決めておいて、関数実装はローダブルモジュール化して動的にローディングするのかなーっと思っています。

kenjihiranabe commented 2 weeks ago
英語の用語を統一したい。参考 https://web.mit.edu/evt/summary_battery_specifications.pdf https://www.pveducation.org/pvcdrom/battery-characteristics/battery-capacity 英語 日本語 単位 意味
Nominal Capacity 公称容量 Ah(アンペアアワー) バッテリーが供給できる理論上の電気量
Actual Capacity 実容量 Ah(アンペアアワー) 実際に使用可能な電気容量
Energy Capacity エネルギー容量 Wh(ワットアワー) バッテリーが蓄えられる電力量
Specific Energy エネルギー密度(重量) Wh/kg 単位重量あたりのエネルギー容量
Energy Density エネルギー密度(体積) Wh/L 単位体積あたりのエネルギー容量
State of Charge (SoC) 充電状態 % バッテリーの現在の充電レベル
State of Health (SoH) 劣化状態 % バッテリーの健全性を示す指標
Depth of Discharge (DoD) 放電深度 % 完全充電状態からの放電量
C-Rate C率 C(時間の逆数) バッテリーの充放電速度を示す比率
Cycle Life サイクル寿命 サイクル数 充放電可能な回数
Maximum Charge Current 最大充電電流 A(アンペア) 安全に充電できる最大電流値
Maximum Discharge Current 最大放電電流 A(アンペア) 安全に放電できる最大電流値
Rated Voltage 定格電圧 V(ボルト) バッテリーの公称電圧
Nominal Voltage 公称電圧 V(ボルト) バッテリーの標準的な動作電圧
Operating Voltage 動作電圧 V(ボルト) 実際の使用時の電圧範囲
Open Circuit Voltage 開回路電圧 V(ボルト) 無負荷時のバッテリー電圧
Cut-off Voltage カットオフ電圧 V(ボルト) 放電を停止する最低電圧
Float Voltage フロート電圧 V(ボルト) 満充電状態を維持する電圧
Internal Resistance 内部抵抗 Ω(オーム) バッテリー内部の電気抵抗
Power Density 出力密度 W/kg 単位重量あたりの最大出力
Available Capacity 利用可能容量 Ah(アンペアアワー) 現在使用可能な容量
Remaining Capacity 残存容量 Ah(アンペアアワー) 使用後に残っている容量
Design Capacity 設計容量 Ah(アンペアアワー) バッテリー設計時の目標容量
Usable Capacity 使用可能容量 Ah(アンペアアワー) 実際に使える容量範囲
Rated Capacity 定格容量 Ah(アンペアアワー) メーカーが保証する容量
Capacity Retention 容量保持率 % 経時変化後の容量維持率
Loss of Capacity 容量低下 %/時間 時間経過による容量減少率
Discharge Rate 放電レート A or C 単位時間当たりの放電量
Self-Discharge Rate 自己放電率 %/月 未使用時の自然な放電率
Discharge Efficiency 放電効率 % 放電時のエネルギー変換効率
Terminal Voltage 端子電圧 V(ボルト) 負荷接続時の実際の電圧
Voltage Drop 電圧降下 V(ボルト) 負荷による電圧の低下量
State of Function (SoF) 機能状態 % バッテリーの性能状態指標
kenjihiranabe commented 2 weeks ago

実スペック例:(書きで、Specs のタブ) https://genstattu.com/gens-ace-2200mah-3s-60c-11-1v-g-tech-lipo-battery-pack-with-deans-plug/

今回のパラメータ(11.1V に使ったスペック、仕様のプルダウン) https://jp.robotshop.com/products/111v-3000mah-40c-3s-lipo-battery

tmori commented 1 week ago

バッテリーのコンフィグパラメータ、ひとまず、以下で実装進めます。 まずは動くものを作ってみます。

      "battery": {
        "vendor": "None",
        "NominalCapacity": 11.1,
        "ActualCapacity": 11.1
      },
tmori commented 1 week ago

インタフェースは一旦、こうしました。

#ifndef _IDISCHARGE_DYNAMICS_HPP_
#define _IDISCHARGE_DYNAMICS_HPP_

namespace hako::assets::drone {

class IDischargeDynamics {
public:
    virtual ~IDischargeDynamics() {};
    virtual double get_discharged() = 0;
};
}

#endif /* _IDISCHARGE_DYNAMICS_HPP_ */
tmori commented 1 week ago

ローターのダイナミクスで継承して計算します。

class RotorDynamics : public hako::assets::drone::IRotorDynamics, public hako::assets::drone::IDischargeDynamics, public ICsvLog {
private:
    double param_rad_per_sec_max = 6000.0;
    double param_tr = 1.0;
    double param_kr = 1.0;
    bool battery_dynamics = false;
    RotorBatteryModelConstants constants;
    DroneRotorSpeedType speed;
    DroneRotorSpeedType next_speed;
    double delta_time_sec;
    double total_time_sec;
    double discharged_value;

    void run_discharge(double vbat, double omega, double duty_rate)
    {
        double current = drone_physics::rotor_current(
                            vbat, /* battery voltage in volt [V]*/
                            this->constants.R, /* resistance in ohm [V/A] */
                            this->constants.K, /* back electromotive force coeff in [N m/A] */
                            omega, /* angular velocity in [rad/sec] */
                            duty_rate /* 0.0-1.0 (ratio of PWM) */
                            );
        this->discharged_value += current * this->delta_time_sec;
    }
    void run(double control, double vbat) override
    {
        this->run_discharge(vbat, this->speed.data, control);
        this->next_speed.data =   (
                                    drone_physics::rotor_omega_acceleration(vbat, constants.R, constants.Cq, constants.J, constants.K, constants.D, speed.data, control)
                                  ) * this->delta_time_sec
                                + this->speed.data;
        // Cap the next speed at the maximum RPS if it exceeds it
        if (this->next_speed.data > this->param_rad_per_sec_max) {
            this->next_speed.data = this->param_rad_per_sec_max;
        }
        // Ensure the next speed does not fall below the minimum RPS (assuming 0 for this example)
        else if (this->next_speed.data < 0) {
            this->next_speed.data = 0;
        }
        this->speed.data = this->next_speed.data;
        this->total_time_sec += this->delta_time_sec;
    }
tmori commented 1 week ago

飛行させた時の、放電量をプロットしてみました。

Image

tmori commented 1 week ago

ここまでの修正をコミット。

https://github.com/toppers/hakoniwa-px4sim/commit/cfa1fb2f7e8c021fc2306f830cacb33df4971dca

tmori commented 1 week ago

次はバッテリのダイナミクスを作ります。

tmori commented 1 week ago

この図の放電電流をどう決めるかは悩みどころですね。 固定ではなくて、ドローンの負荷で変わるんですよね、きっと。 ひとまず、最初は固定の放電電流であるとして実装してみます。 あと、グラフは単純に、リニアに変化する形で。

Image

tmori commented 1 week ago

バッテリ実装を追加しました。

https://github.com/toppers/hakoniwa-px4sim/commit/f3c6f7f305e4334ce7d3d997250d4806909823a8

tmori commented 1 week ago

バッテリーつけて動かしてみました。

多分、バッテリー電圧モデルがうまくいってないので、すぐに落ちちゃいますね。。 どうも9.5V以下になると、推力が重力に勝てなくなるみたい。

高度

Image

バッテリー電圧

Image

kenjihiranabe commented 1 week ago

あってるように思います。 確か、新しいphysics にした時に、11.1V でホバーの電圧、ようやく確保だった。フルduty でも、回転数を2倍にできる電圧はなかったと記憶していて、14.8 V の方がいいか迷った。

でも、バッテリーの減りが早すぎない?フル電圧はもっと長時間続かないといけない。

tmori commented 1 week ago

@kenjihiranabe バッテリーの減りが早い原因を調べ始めてます。

確認ですけれど、電流値はプラス/マイナスになるんですよね。 Image

実際にシミュレーションして、ドローン飛行を色々とやってみた時のローターの電流値をグラフ化してみました。

Image

マイナスの電流の場合も放電している状態であるので、電流は絶対値で積分して放電量を求めるべきなのですよね?

Image

tmori commented 1 week ago

調査状況

パラメータ情報

 "R": 0.12,
"Cq": 3.0e-8,
"K": 3.28e-3,
"D": 0.0,
 "J": 8.12e-6
"HoveringRpm": 13827.38146

ホバリング時の Rad/Secは、約 1447 です。

バッテリ電圧のパラメータ

バッテリ電圧は、以下の式で計算しています。

Vbat = 初期電圧 - { (初期電圧 - 終了電圧) / 容量 } * 現在の放電量[Ah]

電流値計算式

 return (Vbat * duty_rate  - K * omega)/R;

シミュレーション結果

Duty

Image

ローター回転数(Rad/Sec)

Image

ローターの電流値[A]

Image

Vbatの値

Image

kenjihiranabe commented 1 week ago

確認ですが、 容量:3.0Ah は、1時間=3600秒間、3.0A 流せる量。

tmori commented 1 week ago

確認ですが、 容量:3.0Ah は、1時間=3600秒間、3.0A 流せる量。

ですよね。こちらの情報を参考にしました。

https://jp.robotshop.com/products/111v-3000mah-40c-3s-lipo-battery

kenjihiranabe commented 1 week ago

なので、上のグラフ、40秒間、ずっと電圧が下がり続けるのはなぜだろう。電圧モデルですが、容量尽きるまでずっとフラットにしてみては?

tmori commented 1 week ago

ローターの電流値[A]の検証

以下の計算式で求めた結果とシミュレーション結果が一致するかどうか

 return (Vbat * duty_rate  - K * omega)/R;

計算

シミュレーションが10秒時点でホバリングしており、安定しているので、この時点のデータをベースにして、机上計算結果とシミュレーション結果が一致しているかチェックする。

なので、電流値は、18.9 A となるので、机上で計算した値とほぼ一致している。

(10.8 0.65 - (3.28e-3 1448)) / 0.12

tmori commented 1 week ago

なので、上のグラフ、40秒間、ずっと電圧が下がり続けるのはなぜだろう。

バッテリの電圧モデルを単純化して、以下のようにリニアに減る形にしているためですね。

Image

電圧モデルですが、容量尽きるまでずっとフラットにしてみては?

放電容量が 3Ah に達する時間がどうなるかだと思うのですが、 ホバリングしている場合、シミュレーション結果として、1個のローターの電流値は 20A でした。 4個で80Aになります。

そうすると1秒あたり 80Asで、容量は3Ahだから、3600x3As となり、2.25分(=3x45秒)で容量尽きると思うのですが。。

tmori commented 1 week ago

ドローンの連続飛行時間は30分程度とよく聞くので、 そうすると、3Ah の容量だと、ローター全部で 6Aで、 1ローターあたり、1.5A くらいなのかなと思えてきました...。

うーむ。

kenjihiranabe commented 1 week ago

↑二つ上の計算だけど、

そうすると1秒あたり 80Asで、容量は3Ahだから、3600As となり、45秒で容量尽きると思うのですが。。

ちょっと違っていて、この3倍ですね。(容量の3 を掛ける) それでも、3分もたないか。

いま、3cellなので、4cell にして、14.8V, 容量を 4Ah にスペックアップしようか。 そうすると、パワーアップして電流が減り、かつ容量も増えて、10分くらいもたないかな。

tmori commented 1 week ago

↑二つ上の計算だけど、

そうすると1秒あたり 80Asで、容量は3Ahだから、3600As となり、45秒で容量尽きると思うのですが。。

ちょっと違っていて、この3倍ですね。(容量の3 を掛ける) それでも、3分もたないか。

いま、3cellなので、4cell にして、14.8V, 容量を 4Ah にスペックアップしようか。 そうすると、パワーアップして電流が減り、かつ容量も増えて、10分くらいもたないかな。

あ、セル数の考え方を入れてませんでした。 並列で接続しているんですかね。

セル数をパラメータで入れられるようにしてみます。

kenjihiranabe commented 1 week ago

直列です。でも容量増えますよ。

tmori commented 1 week ago

なるほど、理解できてきました。1セル3.7 Vなんですね。

ここ見ると、直列もありですが、並列と直列を合わせたのもあるみたいですね。

https://drone-under500.com/drone/technology/drone-battery-lithium-polymer/

tmori commented 1 week ago

コンフィグのバリエーションが複雑になりそうなので、セル数はやめておきます。。

全体としての計算結果をパラメータに指定してもらうことにします。

tmori commented 1 week ago

いま、3cellなので、4cell にして、14.8V, 容量を 4Ah にスペックアップしようか。 そうすると、パワーアップして電流が減り、かつ容量も増えて、10分くらいもたないかな。

ちょっとわからなくなりました。

1cell 3.7Vを4個直列接続したら、14.8V になりますが、Vbatは値を大きする方向に作用するので、電流値は減らないような気がしました。

実際に計測してみると、PID制御のせいか、20Aのままですね。

Image

ただ、寿命は伸びました。

Image

(微妙に下降しているな。。

tmori commented 1 week ago

任意の電圧モデル

定義方法:BatteryModelCsvFilePathに、CSVファイルパスを指定する。

      "battery": {
        "vendor": "None",
        "BatteryModelCsvFilePath": "./battery_model.csv",
        "VoltageLevelGreen": 11.1, 
        "VoltageLevelYellow": 9.5,
        "CapacityLevelYellow": 2.5, 
        "NominalVoltage": 14.8,
        "NominalCapacity": 5.0,
        "EODVoltage": 3.0
      },

定義例:コメントつけれます。

# Discharge Capacity (Ah), Voltage Level (V)
0.0, 14.8
0.1, 13.5
0.2, 13.0
0.3, 12.8
0.4, 12.7
0.5, 12.6
0.6, 12.5
0.8, 12.3
1.0, 12.1
1.5, 11.8
2.0, 11.5
2.5, 11.2
3.0, 11.0
3.1, 10.0
3.2, 8.0
3.3, 6.0
3.4, 4.5
3.5, 3.5
3.6, 3.0
3.7, 3.0
5.0, 3.0

グラフ化すると: Image

実験結果:うまくいったぽいよ。 Image