package matsubara.carcontroller; import matsubara.gear.*; /** *タイトル: THSシミュレータ
*説明: プリウスのハイブリッドシステム(THS)の心臓部、遊星歯車機構のシミュレーション
*著作権: Copyright (c) 2002 m.matsubara
* @author m.matsubara * @version 1.2.0 */ public class ThsController extends CarController { PlanetaryGear m_planetaryGear; boolean m_bGasoline; boolean m_bMotor; boolean m_bKaisei; double m_rBatterySOC = 60.0; // HVバッテリー残量(SOC = State of charge); boolean m_bEngineRequest = false; // HVバッテリーが足りないとき(40%未満)ON → 50%になるまで boolean m_bPowerSaveMode = false; // いわゆるカメ // THS 動作モード /** エネルギーの流れなし */ public static final int thsStop = 0; /** 停止で充電 */ public static final int thsStopAndEngine = 1; /** モーターのみで発進 */ public static final int thsStart = 2; /** 通常運転 */ public static final int thsNormal = 3; /** 通常運転(オーバードライブ・モーターと発電機の役割が逆転) */ public static final int thsNormalOD = 4; /** 全開加速(エンジン+モーター) */ public static final int thsFullAccel = 5; /** 全開加速(エンジン+モーター) */ public static final int thsFullAccelOD = 6; /** 回生ブレーキ */ public static final int thsKaisei = 7; /** 回生ブレーキ+エンジンは発電機の負荷で動いている */ public static final int thsKaiseiAndEngine = 8; /** モーターのみで発進 */ public static final int thsBackAndEngine = 9; /** 動作モード */ int m_nThsMode = thsStop; /** * ThsController の初期化 * @param nPlanetaryGearX プラネタリギアを描くときのX座標 * @param nPlanetaryGearY プラネタリギアを描くときのX座標 * @param nPlanetaryGearSize プラネタリギアを描くときのサイズ(半径) */ public ThsController(int nPlanetaryGearX, int nPlanetaryGearY, int nPlanetaryGearSize) throws EPlanetaryGear { super(); m_planetaryGear = new PlanetaryGear(nPlanetaryGearX, nPlanetaryGearY, nPlanetaryGearSize, 30, 23, 78, 4, 4); // 動力分割機構 setFuel(50); // 燃料満タン } /** * シフトポジションの設定(安全装置付き♪) * 安全装置(?)が付いているためDレンジからいきなり P や R に入ったりしない。 * @param sShiftPosition 新しいシフトポジション */ public void setShiftPosition(String sShiftPosition) { double rSpeed = getSpeed(); if (sShiftPosition.equals("P")) { if (rSpeed == 0) super.setShiftPosition(sShiftPosition); else super.setShiftPosition("N"); } else if (sShiftPosition.equals("R")) { if (rSpeed <= 3) super.setShiftPosition(sShiftPosition); // else // super.setShiftPosition("N"); } else if (sShiftPosition.equals("N")) super.setShiftPosition(sShiftPosition); else if (sShiftPosition.equals("D") || sShiftPosition.equals("B")) { if (rSpeed >= -3) super.setShiftPosition(sShiftPosition); // else // super.setShiftPosition("N"); } } /** * 車の状態をシミュレートする * @param rMilliSec 経過秒数 * @param nAccel アクセルの踏み込み量(%) * @param nBrake ブレーキの踏み込み量(%) */ protected void driveInternal(double rMilliSec, int nAccel, int nBrake) { String sShiftPosition = getShiftPosition(); if (getFuel() <= 0) { // インチキだがガス欠判断 nAccel = 0; nBrake = 30; } if (sShiftPosition.equals("D")) driveInternal_D_B(rMilliSec, nAccel, nBrake); else if (sShiftPosition.equals("B")) driveInternal_D_B(rMilliSec, nAccel, nBrake); else if (sShiftPosition.equals("R")) driveInternal_R(rMilliSec, nAccel, nBrake); else if (sShiftPosition.equals("P")) driveInternal_P(rMilliSec, nAccel, nBrake); else driveInternal_N(rMilliSec, nAccel, nBrake); // N レンジ m_bMotor = (m_nThsMode == thsStart) || (m_nThsMode == thsFullAccel) || (m_nThsMode == thsFullAccelOD) || (m_nThsMode == thsBackAndEngine); m_bKaisei = (m_nThsMode == thsKaisei) || (m_nThsMode == thsKaiseiAndEngine); m_bGasoline = (m_nThsMode == thsFullAccel) || (m_nThsMode == thsFullAccelOD) || (m_nThsMode == thsNormal) || (m_nThsMode == thsNormalOD) || (m_nThsMode == thsStopAndEngine)|| (m_nThsMode == thsBackAndEngine); if (m_rBatterySOC > 80.0) m_rBatterySOC = 80.0; if ((m_bEngineRequest == false) && (m_rBatterySOC < 45)) { m_bEngineRequest = true; System.out.println("m_bEngineRequest = true"); } if (m_rBatterySOC < 40) m_bPowerSaveMode = true; if ((m_bEngineRequest != false) && (m_rBatterySOC >= 50)) { m_bEngineRequest = false; m_bPowerSaveMode = false; System.out.println("m_bEngineRequest = false"); } } private double engineRpm(double rTargetEngineRpm, double rMilliSec) { // 回転数の制御 double rEngineRpm = m_planetaryGear.getPlaCarrierSpeed(); if (rEngineRpm < rTargetEngineRpm) { rEngineRpm += (rMilliSec / 1000) * 1000; if (rEngineRpm > rTargetEngineRpm) rEngineRpm = rTargetEngineRpm; } else if (rEngineRpm > rTargetEngineRpm) { rEngineRpm -= (rMilliSec / 1000) * 2000; if (rEngineRpm < rTargetEngineRpm) rEngineRpm = rTargetEngineRpm; } return rEngineRpm; } /** * Pレンジの時のシミュレーション * @param rMilliSec 経過秒数 * @param nAccel アクセルの踏み込み量(%) * @param nBrake ブレーキの踏み込み量(%) */ private void driveInternal_P(double rMilliSec, int nAccel, int nBrake) { m_nThsMode = thsStop; // THS各目標値 double rTargetEngineRpm = 0; // エンジンの状態 if (nAccel >= 5) { // エンジン燃焼 rTargetEngineRpm = 1000 + nAccel * 500 / 100 ; } // バッテリーの状態が悪いとき if (m_bEngineRequest) { if (rTargetEngineRpm < 1250) rTargetEngineRpm = 1250; rTargetEngineRpm = 1250; m_nThsMode = thsStopAndEngine; m_rBatterySOC += 0.00010 * rMilliSec; } // 回転数の制御 double rEngineRpm = engineRpm(rTargetEngineRpm, rMilliSec); m_planetaryGear.setRingGearSpeed(0); m_planetaryGear.setPlaCarrierSpeed(rEngineRpm); m_planetaryGear.move(rMilliSec / 100); } /** * Rレンジの時のシミュレーション * @param rMilliSec 経過秒数 * @param nAccel アクセルの踏み込み量(%) * @param nBrake ブレーキの踏み込み量(%) */ private void driveInternal_R(double rMilliSec, int nAccel, int nBrake) { m_nThsMode = thsStop; // THS各現状値 double rSpeed = getSpeed(); // THS各目標値 double rTargetSpeed = - 5 - (double)(nAccel * 35 / 100); double rTargetEngineRpm = 0; if (m_bEngineRequest) { if (rTargetSpeed < -16) rTargetSpeed = -16; rTargetEngineRpm = 1200; } if (m_bPowerSaveMode == false && m_bEngineRequest && rSpeed < -5) // エンジン回転要求があっても速度が -5km/h より速いときはエンジンを回さない。 rTargetEngineRpm = 0; double rEngineRpm = engineRpm(rTargetEngineRpm, rMilliSec); // 加速・自然減速の計算 m_bMotor = true; m_nThsMode = thsStart; if (rSpeed > rTargetSpeed) { // 加速の計算 rSpeed += (rTargetSpeed - rSpeed) * rMilliSec / 1000 * 0.15; if (rSpeed < rTargetSpeed) rSpeed = rTargetSpeed; } else { rSpeed += 2.20 * rMilliSec / 1000; if (rSpeed > rTargetSpeed) rSpeed = rTargetSpeed; if (rSpeed < -10) m_nThsMode = thsKaisei; } if (rEngineRpm > 1000) m_nThsMode = thsBackAndEngine; // ブレーキの判断 if (isParkingBrake() && nBrake < 50) nBrake = 50; // パーキングブレーキを普通のブレーキの50%とみなす。 if (nBrake > 5) { rSpeed += 0.25 * nBrake * rMilliSec / 1000; if (rSpeed > 0) rSpeed = 0; if (rSpeed < -10) m_nThsMode = thsKaisei; else m_nThsMode = thsStop; } // エンジンが回転していて速度が0の時 if (rEngineRpm > 1000 && rSpeed == 0) m_nThsMode = thsStopAndEngine; if (m_nThsMode == thsStart) m_rBatterySOC -= rSpeed * -0.0000030 * rMilliSec; else if (m_nThsMode == thsKaisei) m_rBatterySOC += rSpeed * -0.0000010 * rMilliSec; else if (m_nThsMode == thsBackAndEngine) m_rBatterySOC += 0.0000020 * rMilliSec; else if (m_nThsMode == thsStopAndEngine) m_rBatterySOC += 0.00010 * rMilliSec; // double rTyreDiameter = 165 * 0.65 * 2 + 15 * 25.4;