This repository has been archived by the owner on Nov 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchloe.py
132 lines (106 loc) · 5.04 KB
/
chloe.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
print("Getting data from OCV-SOC file...")
#data_ocv_charge = pd.read_csv("charging_OCV_curve.csv", sep=';', header=None)
data_ocv_charge = pd.read_excel("data/Cha_Dis_OCV_SOC_Data.xlsx", header=1, usecols="B:C", skiprows=0) # voir les trucs à rajouter en arg de read_excel
print("data_ocv_charge (head):")
print(data_ocv_charge.head())
#data_ocv_discharge = pd.read_csv("discharging_OCV_curve.csv", sep=';', header=None)
data_ocv_discharge = pd.read_excel("data/Cha_Dis_OCV_SOC_Data.xlsx", header=1, usecols="E:F", skiprows=0) # voir les trucs à rajouter en arg de read_excel
data_ocv_discharge.columns = ['data_SOC', 'data_U']
print("data_ocv_discharge (head):")
print(data_ocv_discharge.head())
data_hppc_chg = pd.read_excel("data/EVE_HPPC_1_25degree_CHG-injectionTemplate.xlsx", header=3, usecols="A:D")
data_hppc_chg.columns = ['seconds', 'voltage', 'current_inv', 'SOC_true']
print("data_hppc_chg (head):")
print(data_hppc_chg.head())
data_hppc_dsg = pd.read_excel("data/EVE_HPPC_1_25degree_DSG-injectionTemplate.xlsx", header=3, usecols="A:D")
data_hppc_dsg.columns = ['seconds', 'voltage', 'current_inv', 'SOC_true']
print("data_hppc_dsg (head):")
print(data_hppc_dsg.head())
#input("Press Enter to continue...")
# Dataset files are in "./data/Scenario-{nb}/{filename}.xlsx"
# the directory "./data/" is in the gitignore to prevent uploading the confidential dataset to the repo
files = [
"Scenario-1/GenerateTestData_S1_Day0to4.xlsx",
"Scenario-1/GenerateTestData_S1_Day4to7.xlsx",
"Scenario-2/GenerateTestData_S2_Day0to4.xlsx",
"Scenario-2/GenerateTestData_S2_Day4to7.xlsx",
"Scenario-3/GenerateTestData_S3_Day0to4.xlsx",
"Scenario-3/GenerateTestData_S3_Day4to7.xlsx",
"Scenario-4/GenerateTestData_S4_Day0to4.xlsx",
"Scenario-4/GenerateTestData_S4_Day4to7.xlsx"
]
# add additional files to the list here above
for i in range(len(files)):
print(f"{i}. {files[i]}")
data_choice: int = int(input(f"Select data file: "))
print("Reading data from file:", files[data_choice],"...")
# read file with these (hardcoded) specific columns placement and headers:
data = pd.read_excel("data/"+files[int(data_choice)], usecols="B:D,G", skiprows=[0,3],header=1) # read file situated in ./data/Scenario-{nb}/{filename}.xlsx
print(data.head()) # look the first few lines of the dataframe to manually verify the data has been read correctly
input("Press Enter to continue...")
# Dataframe has columns: "Voltage", "Current_inv", "SOC_true", and "Temp"
# Extraction des colonnes par index
voltage_data = data['Voltage'].values
current_data = data['Current_inv'].values
soc_true_data = data['SOC_true'].values
temp_data = data['Temp'].values
# Paramètres de la batterie
nominal_capacity = 280.0 # Capacité nominale en Ah (ajuster en fonction de la batterie)
dt = 1.0 # Pas de temps en secondes
initial_SoC = soc_true_data[0] # SoC initial
# Initialisation du filtre de Kalman
SoC_est = np.array([[initial_SoC]])
P = np.array([[1]])
Q = np.array([[1e-5]])
R = np.array([[0.1]])
# Modèle de tension utilisant les courbes de charge et décharge
def voltage_model(SOC, current, temperature, mode="discharge"):
if mode == "charge":
soc_ocv = data_ocv_charge["data_SOC"].values
voltage_ocv = data_ocv_charge["data_U"].values
else:
soc_ocv = data_ocv_discharge["data_SOC"].values
voltage_ocv = data_ocv_discharge["data_U"].values
# Interpolation de la tension en fonction du SoC
V_oc = np.interp(SOC, soc_ocv, voltage_ocv)
# Ajustement selon la température et le courant
R_int = 0.01 # Valeur de résistance interne (ajuster selon le modèle)
return V_oc - current * R_int
# Jacobienne de la transition d'état (approximation pour le SoC)
def jacobian_state_transition():
return np.array([[1]])
# Jacobienne de la mesure
def jacobian_measurement_function():
return np.array([[1]])
# Boucle de simulation
num_steps = len(voltage_data)
print(f"Nombre total d'étapes : {num_steps}")
SoC_values = []
for t in range(num_steps):
current = current_data[t]
measured_voltage = voltage_data[t]
temperature = temp_data[t]
# Prédiction
SoC_pred = SoC_est - np.array([[current * dt / nominal_capacity]])
F = jacobian_state_transition()
P_pred = F @ P @ F.T + Q
# Tension prédite (choix entre charge/décharge selon le courant)
mode = "charge" if current > 0 else "discharge" # > rather than < ?
voltage_pred = voltage_model(SoC_pred[0, 0], current, temperature, mode=mode)
# Mise à jour (filtrage)
H = jacobian_measurement_function()
K = P_pred @ H.T @ np.linalg.inv(H @ P_pred @ H.T + R)
SoC_est = SoC_pred + K @ np.array([[measured_voltage - voltage_pred]])
P = (np.eye(len(P)) - K @ H) @ P_pred
# Stocker la valeur estimée de SoC
SoC_values.append(SoC_est[0, 0])
# Affichage des résultats
plt.plot(range(num_steps), SoC_values, label="Estimation SoC")
plt.xlabel("Temps (s)")
plt.ylabel("État de Charge (SoC)")
plt.title("Estimation du SoC avec un Filtre de Kalman Étendu")
plt.legend()
plt.show()