Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
6e766c5
Initial new changes
joshuaRiefman May 20, 2025
ee749a1
More things
joshuaRiefman May 20, 2025
f4c84ca
Current state
joshuaRiefman May 23, 2025
1937713
More updates
joshuaRiefman May 23, 2025
6e72815
Small changes
joshuaRiefman May 23, 2025
abab934
Add config to git
joshuaRiefman May 23, 2025
c67a49c
Asynchronous requests to update status
joshuaRiefman May 23, 2025
1eb1418
Initial command viewer
joshuaRiefman May 24, 2025
a8b01d5
Second iteration
joshuaRiefman May 24, 2025
dfa3ecf
Update Config with Protocol for type hinting
joshuaRiefman May 24, 2025
03b06ad
Refactor Docker panels
joshuaRiefman May 24, 2025
6c6a14d
Add Sunlink path to settings
joshuaRiefman May 24, 2025
71611e6
Update log widget
joshuaRiefman May 24, 2025
2bc6b72
Add Telemetry panel
joshuaRiefman May 24, 2025
4c8785f
Remove Docker tabs
joshuaRiefman May 27, 2025
d8d19d1
Remove Docker tabs (1)
joshuaRiefman May 27, 2025
362a3d2
Remove Docker tabs (2)
joshuaRiefman May 27, 2025
239d1aa
-
skrifana May 31, 2025
fa66960
-
skrifana May 31, 2025
bf7cdcf
-
skrifana May 31, 2025
4092ea8
-
skrifana May 31, 2025
cb0e6e1
-
skrifana May 31, 2025
17cfc7a
-
skrifana May 31, 2025
379e6d1
-
skrifana May 31, 2025
ec9ec66
-
skrifana May 31, 2025
ae6f8bc
-
skrifana May 31, 2025
9d5adb8
-
skrifana Sep 5, 2025
7236454
-
skrifana Sep 24, 2025
4e1a4b7
Merge remote-tracking branch 'origin/master' into aeroshell_config
skrifana Sep 28, 2025
55a1874
-
skrifana Oct 1, 2025
66d74ef
Undo changes to diagnostic_interface
joshuaRiefman Oct 1, 2025
a208241
Undo changes to pyproject and poetry
joshuaRiefman Oct 1, 2025
dea7213
Undo changes to diagnostic_interface
joshuaRiefman Oct 1, 2025
117527f
Undo changes to diagnostic_interface (1)
joshuaRiefman Oct 1, 2025
19aebe6
-
skrifana Oct 1, 2025
0ce70b9
Merge remote-tracking branch 'origin/aeroshell_config' into aeroshell…
skrifana Oct 1, 2025
39496a6
-
skrifana Oct 1, 2025
0d4b15e
undo unnecessary changes
skrifana Oct 1, 2025
b3215af
Update _car.py
skrifana Oct 2, 2025
8dcb18d
Update Model.py
skrifana Oct 2, 2025
11b1d34
Update ModelBuilder.py
skrifana Oct 2, 2025
f229a8b
Update Simulation.py
skrifana Oct 2, 2025
0b0e120
Fix a few things
joshuaRiefman Oct 4, 2025
d514438
Update Simulation.py
skrifana Oct 4, 2025
270b275
Add physics
joshuaRiefman Oct 4, 2025
2b1d498
Changes from Ruff linter
joshuaRiefman Oct 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion diagnostic_interface/canvas/realtime_canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from diagnostic_interface import settings
from PyQt5.QtWidgets import QMessageBox
import mplcursors
from datetime import timezone
from dateutil import tz


Expand Down
3 changes: 2 additions & 1 deletion diagnostic_interface/widgets/realtime_map_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def update_map(self, vertex_values: NDArray[float], latitudes: NDArray, longitud
touchZoom=False,
)

get_coord = lambda x: [latitudes[x], longitudes[x]]
def get_coord(x):
return [latitudes[x], longitudes[x]]

for i, (latitude, longitude, vertex_value) in enumerate(zip(latitudes, longitudes, vertex_values)):
color = mcolors.to_hex(cmap(norm(vertex_value)))
Expand Down
3 changes: 3 additions & 0 deletions micro_strategy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@

OptimizedSpeedsPath = Path(__file__).parent / "optimization_results" / "optimized_speeds_filtered.npy"

__all__ = [
"run_micro_simulation"
]
4 changes: 2 additions & 2 deletions prescriptive_interface/prescriptive_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@
from diagnostic_interface.widgets import SplashOverlay
from simulation.cmd.run_simulation import get_default_settings
from simulation.config import SimulationReturnType, SimulationHyperparametersConfig, InitialConditions
from pathlib import Path
from PyQt5.QtCore import QTimer
from PyQt5.QtCore import Qt

from qt_material import apply_stylesheet

config_dir = Path(__file__).parent.parent / "simulation" / "config"

from pathlib import Path
from prescriptive_interface import (SimulationTab, OptimizationTab, HtmlViewerTab, SimulationSettingsDict, OptimizationThread,
SimulationThread, MutableInitialConditions, InitialConditionsDialog)

config_dir = Path(__file__).parent.parent / "simulation" / "config"

my_speeds_dir = Path("prescriptive_interface/speeds_directory")
my_speeds_dir.mkdir(parents=True, exist_ok=True) # Create it if it doesn't exist

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ dependencies = [
"tomli>=2.2.1",
"tomli-w>=1.2.0",
"qt-material>=2.17",
"ubc-solar-physics==1.8.2",
"ubc-solar-physics==1.9.1",
]

[project.urls]
Expand Down
9 changes: 8 additions & 1 deletion simulation/config/BrightSide.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ max_acceleration = 6
max_deceleration = 6

[motor_config]
motor_type = "AdvancedMotor"
motor_type = "BasicMotor"
road_friction = 2.340e-02
tire_radius = 0.2032
vehicle_frontal_area = 1.1853
Expand All @@ -43,3 +43,10 @@ drag_coefficient = 1.166e-01

[motor_config.AdvancedMotor]
cornering_coefficient = 1.0

[aeroshell_config]
drag_lookup = {0 = 0.137601477, 18 = 0.2335363083, 36 = 0.5965968882, 54= 1.224448936, 72= 1.861868971, 90= 2.38148208, 108= 2.073196244, 126= 1.587471653, 144= 0.5564901716, 162= 0.2141437734, 180= 0.1386601712 }
down_lookup = {0=0.37526598, 18= 0.3378390168, 36= 0.576439927, 54= 0.8675973423, 72= 1.19551954, 90= 2.683269654, 108= 2.223002744, 126= 1.581662338, 144= 0.17190782, 162= 0.1882638387, 180= 0.2153506426 }



10 changes: 10 additions & 0 deletions simulation/config/models/_car.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ class AdvancedMotorConfig(MotorConfig):
cornering_coefficient: float


class AeroshellConfig(Config):
"""
Configuration object describing the aerodynamics forces (specifically drag and downforce) of a vehicle.
"""
model_config = ConfigDict(frozen=True)
drag_lookup: dict[float, float] #lookup table that corresponds angles to drag force, computed by a CFD
down_lookup: dict[float, float] #lookup table that corresponds angles to down force, computed by a CFD


class RegenConfig(Config):
"""
Configuration object describing the regenerative braking systems of a vehicle.
Expand All @@ -123,5 +132,6 @@ class CarConfig(Config):
battery_config: BatteryConfig
motor_config: MotorConfig
regen_config: RegenConfig
aeroshell_config: AeroshellConfig

name: str
4 changes: 4 additions & 0 deletions simulation/model/Model.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from physics.models.battery import BaseBattery
from physics.models.lvs import BaseLVS
from physics.models.motor import BaseMotor
from physics.models.aeroshell import Aeroshell
from physics.models.regen import BaseRegen
from physics.environment.gis import BaseGIS
from physics.environment.meteorology import BaseMeteorology
Expand All @@ -36,6 +37,7 @@ def __init__(
array: BaseArray,
battery: BaseBattery,
motor: BaseMotor,
aeroshell: Aeroshell,
regen: BaseRegen,
lvs: BaseLVS,
gis: BaseGIS,
Expand All @@ -56,6 +58,7 @@ def __init__(
:param BaseArray array: An instance of `BaseArray` representing the solar array to be simulated.
:param BaseBattery battery: An instance of `BaseBattery` representing the batter pack to be simulated.
:param BaseMotor motor: An instance of `BaseMotor` representing the motor to be simulated.
:param Aeroshell aeroshell: An instance of the Aeroshell class that represents the drag and down force calculations
:param BaseRegen regen: An instance of `BaseRegen` representing the regenerative braking system to be simulated.
:param BaseLVS lvs: An instance of `BaseLVS` representing the low-voltage systems to be simulated.
:param BaseGIS gis: An instance of `BaseGIS` which characterizes geographical information about the simulation.
Expand All @@ -72,6 +75,7 @@ def __init__(
self.simulation_dt = simulation_dt
self.solar_array = array
self.motor = motor
self.aeroshell = aeroshell
self.regen = regen
self.battery = battery
self.gis = gis
Expand Down
5 changes: 5 additions & 0 deletions simulation/model/ModelBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from physics.models.battery import BaseBattery, BasicBattery, EquivalentCircuitBatteryModel, BatteryModelConfig
from physics.models.lvs import BaseLVS, BasicLVS
from physics.models.motor import BaseMotor, BasicMotor, AdvancedMotor
from physics.models.aeroshell import Aeroshell
from physics.models.regen import BaseRegen, BasicRegen
from physics.environment.gis import BaseGIS, GIS
from physics.environment.meteorology import (
Expand Down Expand Up @@ -70,6 +71,7 @@ def __init__(self, cache: Cache = None):
self.gis: Optional[BaseGIS] = None
self.meteorology: Optional[BaseMeteorology] = None
self.motor: Optional[BaseMotor] = None
self.aeroshell: Optional[Aeroshell] = None
self.battery: Optional[BaseBattery] = None
self.regen: Optional[BaseRegen] = None
self.max_acceleration: Optional[float] = None
Expand Down Expand Up @@ -424,6 +426,8 @@ def compile(self):
**self._car_config.motor_config.model_dump()
)

self.aeroshell = Aeroshell(**self._car_config.aeroshell_config.model_dump())

self.regen = BasicRegen(self._car_config.vehicle_config.vehicle_mass)

self.num_laps = self.route_data.tiling
Expand Down Expand Up @@ -474,6 +478,7 @@ def get(self) -> Model:
array=self.array,
battery=self.battery,
motor=self.motor,
aeroshell=self.aeroshell,
lvs=self.lvs,
regen=self.regen,
gis=self.gis,
Expand Down
16 changes: 13 additions & 3 deletions simulation/model/Simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def __init__(self, model):
self.tick_array = None
self.time_zones = None
self.distances = None
self.drag_force = None
self.down_force = None
self.cumulative_distances = None
self.closest_gis_indices = None
self.closest_weather_indices = None
Expand All @@ -73,6 +75,7 @@ def __init__(self, model):
self.time_in_motion = None
self.final_soc = None
self.map_data_indices = None
self.wind_attack_angles = None

def run_simulation_calculations(self, speed_kmh: NDArray, track_speeds: NDArray) -> None:
"""
Expand Down Expand Up @@ -175,6 +178,12 @@ def run_simulation_calculations(self, speed_kmh: NDArray, track_speeds: NDArray)
self.wind_speeds = get_array_directional_wind_speed(
self.gis_vehicle_bearings, self.absolute_wind_speeds, self.wind_directions
)
#get the wind attack angles
self.wind_attack_angles = self.model.meteorology.wind_direction - (self.gis_vehicle_bearings + 180) #convert azimuthal angle to meteorological convention

# with calculated wind_speeds, we can now calculate (aerodynamic) drag and down forces in order to pass into motor model calculations
self.drag_force = self.model.aeroshell.calculate_drag(self.wind_speeds, self.wind_attack_angles, self.speed_kmh/3.6)
self.down_force = self.model.aeroshell.calculate_down(self.wind_speeds, self.wind_attack_angles, self.speed_kmh/3.6)

# Get an array of solar irradiance at every coordinate and time
self.solar_irradiances = self.model.meteorology.calculate_solar_irradiances(
Expand All @@ -192,10 +201,8 @@ def run_simulation_calculations(self, speed_kmh: NDArray, track_speeds: NDArray)
self.model.simulation_dt
)

coords = self.model.gis.get_path()[:self.model.gis.num_unique_coords]
coords_at_each_tick = coords[self.closest_gis_indices]
self.motor_consumed_energy = self.model.motor.calculate_energy_in(
self.speed_kmh, self.gradients, self.wind_speeds, self.model.simulation_dt, coords_at_each_tick
self.speed_kmh, self.gradients, self.drag_force, self.down_force, self.model.simulation_dt
)

self.array_produced_energy = self.model.solar_array.calculate_produced_energy(
Expand Down Expand Up @@ -344,6 +351,9 @@ def get_results(
"map_data_indices": self.map_data_indices,
"path_coordinates": self.model.gis.get_path(),
"raw_soc": self.raw_soc,
"drag_force": self.drag_force,
"down_force": self.down_force,
"wind_attack_angles": self.wind_attack_angles,
}

if "default" in requested_properties or requested_properties == "default":
Expand Down
5 changes: 1 addition & 4 deletions simulation/optimization/genetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,6 @@ def __init__(
# Bind the value of each gene to be between 0 and 1 as chromosomes should be normalized.
gene_space = {"low": 0.0, "high": 1.0}

# Add a time delay between generations (used for debug purposes)
delay_after_generation = 0.0

# Store diversity of generation per optimization iteration
self.diversity = []

Expand Down Expand Up @@ -392,7 +389,7 @@ def get_initial_population(

"""

population_file = population_directory / "initial_population.npz"
population_file = "initial_population.npz"
arrays_from_cache = 0
new_initial_population = None

Expand Down
28 changes: 15 additions & 13 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.