ubc-solar-physics 1.4.1__tar.gz → 1.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/.github/workflows/build_and_publish.yaml +4 -4
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/PKG-INFO +3 -3
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/_version.py +4 -9
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/motor/__init__.py +3 -1
- ubc_solar_physics-1.5.0/physics/models/motor/advanced_motor.py +196 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/motor/base_motor.py +2 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/motor/basic_motor.py +33 -14
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/pyproject.toml +4 -4
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/ubc_solar_physics.egg-info/PKG-INFO +3 -3
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/ubc_solar_physics.egg-info/SOURCES.txt +1 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/ubc_solar_physics.egg-info/requires.txt +1 -1
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/.github/pull_request_template.md +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/.github/workflows/run_tests.yaml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/.gitignore +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/.readthedocs.yaml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/Cargo.lock +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/Cargo.toml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/LICENSE +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/README.md +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/data.png +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/Makefile +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/_generate_version.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/docs_requirements.txt +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/make.bat +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/README.md +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/api.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/conf.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/environment/gis.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/environment/index.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/environment/meteorology.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/index.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/models/arrays.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/models/battery.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/models/index.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/models/lvs.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/models/motor.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/docs/source/models/regen.rst +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/battery_model_examples/battery_config.toml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/battery_model_examples/battery_model_example.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/battery_model_examples/data_py.png +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/battery_model_examples/data_rust.png +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/data_query/current.csv +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/data_query/poetry.lock +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/data_query/pyproject.toml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/data_query/query_data.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/data_query/voltage.csv +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/kalman_filter_examples/battery_config.toml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/kalman_filter_examples/current.csv +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/kalman_filter_examples/kalman_filter_example.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/kalman_filter_examples/voltage.csv +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/environment.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/gis/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/gis/base_gis.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/gis/gis.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/gis/gis.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/gis.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology/base_meteorology.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology/clouded_meteorology.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology/irradiant_meteorology.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology/meteorology.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/lib.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/arrays/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/arrays/arrays.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/arrays/base_array.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/arrays/basic_array.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/arrays.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/base_battery.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/basic_battery.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/battery.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/battery_config.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/battery_config.toml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/battery_model.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/kalman_filter.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/constants.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/lvs/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/lvs/base_lvs.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/lvs/basic_lvs.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/lvs/lvs.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/lvs.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/motor/motor.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/motor.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/regen/__init__.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/regen/base_regen.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/regen/basic_regen.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/regen/regen.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/regen.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models.rs +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/setup.cfg +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/tests/battery_config.toml +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/tests/kalman_filter_tests/current.csv +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/tests/kalman_filter_tests/test_basic_kalman_filter.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/tests/kalman_filter_tests/test_filter_real_data.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/tests/kalman_filter_tests/voltage.csv +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/tests/test_versioning.py +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/ubc_solar_physics.egg-info/dependency_links.txt +0 -0
- {ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/ubc_solar_physics.egg-info/top_level.txt +0 -0
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/.github/workflows/build_and_publish.yaml
RENAMED
@@ -20,12 +20,12 @@ jobs:
|
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- name: Checkout
|
23
|
-
uses: actions/checkout@
|
23
|
+
uses: actions/checkout@v4
|
24
24
|
with:
|
25
25
|
fetch-depth: 0 # Required to fetch full history including tags, so setuptools_scm can determine version
|
26
26
|
|
27
27
|
- name: Setup Python
|
28
|
-
uses: actions/setup-python@
|
28
|
+
uses: actions/setup-python@v4
|
29
29
|
with:
|
30
30
|
python-version: '3.9'
|
31
31
|
|
@@ -59,7 +59,7 @@ jobs:
|
|
59
59
|
fetch-depth: 0 # Required to fetch full history including tags, so setuptools_scm can determine version
|
60
60
|
|
61
61
|
- name: Set up Python
|
62
|
-
uses: actions/setup-python@
|
62
|
+
uses: actions/setup-python@v4
|
63
63
|
|
64
64
|
# We run `python -m setuptools_scm` and `git status` for debugging purposes, to verify that
|
65
65
|
# setuptools_scm is properly identifying the version based on the tag
|
@@ -92,7 +92,7 @@ jobs:
|
|
92
92
|
run: cibuildwheel --output-dir dist
|
93
93
|
env:
|
94
94
|
CIBW_ARCHS_MACOS: "x86_64 arm64" # Make sure both x86_64 and arm64 wheels are built for macOS
|
95
|
-
CIBW_ENVIRONMENT: 'PATH="$HOME/.cargo/bin:$PATH"'
|
95
|
+
CIBW_ENVIRONMENT: 'PATH="$HOME/.cargo/bin:$PATH" MACOSX_DEPLOYMENT_TARGET="10.12"'
|
96
96
|
CIBW_ENVIRONMENT_WINDOWS: 'PATH="$UserProfile\.cargo\bin;$PATH"'
|
97
97
|
CIBW_BEFORE_BUILD: >
|
98
98
|
pip install -U setuptools-rust &&
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.1
|
2
2
|
Name: ubc-solar-physics
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.5.0
|
4
4
|
Summary: UBC Solar's Simulation Environment
|
5
5
|
Author: Fisher Xue, Mihir Nimgade, Chris Chang, David Widjaja, Justin Hua, Ilya Veksler, Renu Rajamagesh, Ritchie Xia, Erik Langille, Chris Aung, Nicolas Ric, Ishaan Trivedi, Jason Liang, Felix Toft, Mack Wilson, Jonah Lee, Tamzeed Quazi, Joshua Riefman
|
6
6
|
Author-email: UBC Solar <strategy@ubcsolar.com>
|
@@ -50,7 +50,7 @@ Requires-Dist: jaraco.classes==3.4.0
|
|
50
50
|
Requires-Dist: jaraco.context==5.3.0
|
51
51
|
Requires-Dist: jaraco.functools==4.0.2
|
52
52
|
Requires-Dist: keyring==25.3.0
|
53
|
-
Requires-Dist: llvmlite
|
53
|
+
Requires-Dist: llvmlite
|
54
54
|
Requires-Dist: markdown-it-py==3.0.0
|
55
55
|
Requires-Dist: mdurl==0.1.2
|
56
56
|
Requires-Dist: more-itertools==10.4.0
|
@@ -1,13 +1,8 @@
|
|
1
|
-
# file generated by
|
1
|
+
# file generated by setuptools_scm
|
2
2
|
# don't change, don't track in version control
|
3
|
-
|
4
|
-
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
|
5
|
-
|
6
3
|
TYPE_CHECKING = False
|
7
4
|
if TYPE_CHECKING:
|
8
|
-
from typing import Tuple
|
9
|
-
from typing import Union
|
10
|
-
|
5
|
+
from typing import Tuple, Union
|
11
6
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
12
7
|
else:
|
13
8
|
VERSION_TUPLE = object
|
@@ -17,5 +12,5 @@ __version__: str
|
|
17
12
|
__version_tuple__: VERSION_TUPLE
|
18
13
|
version_tuple: VERSION_TUPLE
|
19
14
|
|
20
|
-
__version__ = version = '1.
|
21
|
-
__version_tuple__ = version_tuple = (1,
|
15
|
+
__version__ = version = '1.5.0'
|
16
|
+
__version_tuple__ = version_tuple = (1, 5, 0)
|
@@ -0,0 +1,196 @@
|
|
1
|
+
import numpy as np
|
2
|
+
from haversine import haversine, Unit
|
3
|
+
from numpy.typing import NDArray
|
4
|
+
from physics.models.motor import BasicMotor
|
5
|
+
|
6
|
+
|
7
|
+
class AdvancedMotor(BasicMotor):
|
8
|
+
def __init__(self, **kwargs):
|
9
|
+
super().__init__(**kwargs)
|
10
|
+
self.cornering_coefficient = 15 # tuned to Day 1 and 3 FSGP data
|
11
|
+
|
12
|
+
def calculate_energy_in(self, required_speed_kmh, gradients, wind_speeds, tick, coords):
|
13
|
+
"""
|
14
|
+
A function which takes in array of elevation, array of wind speed, required
|
15
|
+
speed, returns the consumed energy.
|
16
|
+
|
17
|
+
:param np.ndarray required_speed_kmh: (float[N]) required speed array in km/h
|
18
|
+
:param np.ndarray gradients: (float[N]) gradient at parts of the road
|
19
|
+
:param np.ndarray wind_speeds: (float[N]) speeds of wind in m/s, where > 0 means against the direction of the vehicle
|
20
|
+
:param float tick: length of 1 update cycle in seconds
|
21
|
+
:param np.ndarray coords: ([float[N,2]) The lat,lon coordinate of the car at each tick
|
22
|
+
:returns: (float[N]) energy expended by the motor at every tick
|
23
|
+
:rtype: np.ndarray
|
24
|
+
|
25
|
+
"""
|
26
|
+
net_force, required_angular_speed_rads = self.calculate_net_force(required_speed_kmh, wind_speeds, gradients)
|
27
|
+
|
28
|
+
cornering_work = self.calculate_cornering_losses(required_speed_kmh, coords, tick)
|
29
|
+
|
30
|
+
motor_output_energies = required_angular_speed_rads * net_force * self.tire_radius * tick + cornering_work
|
31
|
+
motor_output_energies = np.clip(motor_output_energies, a_min=0, a_max=None)
|
32
|
+
|
33
|
+
e_m = self.calculate_motor_efficiency(required_angular_speed_rads, motor_output_energies, tick)
|
34
|
+
e_mc = self.calculate_motor_controller_efficiency(required_angular_speed_rads, motor_output_energies, tick)
|
35
|
+
|
36
|
+
motor_controller_input_energies = motor_output_energies / (e_m * e_mc)
|
37
|
+
|
38
|
+
# Filter out and replace negative energy consumption as 0
|
39
|
+
motor_controller_input_energies = np.where(motor_controller_input_energies > 0,
|
40
|
+
motor_controller_input_energies, 0)
|
41
|
+
|
42
|
+
return motor_controller_input_energies
|
43
|
+
|
44
|
+
def calculate_cornering_losses(self, required_speed_kmh, coords, tick):
|
45
|
+
"""
|
46
|
+
Calculate the energy losses due to cornering based on vehicle speed and trajectory.
|
47
|
+
|
48
|
+
:param np.ndarray required_speed_kmh: (float[N]) Required speed array in km/h
|
49
|
+
:param np.ndarray coords: (float[N, 2]) Array containing latitude and longitude coordinates of the car at each tick
|
50
|
+
:param float tick: Length of one update cycle in seconds
|
51
|
+
:returns: (float[N]) Energy loss due to cornering at each tick
|
52
|
+
:rtype: np.ndarray
|
53
|
+
"""
|
54
|
+
required_speed_ms = required_speed_kmh / 3.6
|
55
|
+
cornering_radii = self.calculate_radii(coords)
|
56
|
+
|
57
|
+
centripetal_lateral_force = self.vehicle_mass * (required_speed_ms ** 2) / cornering_radii
|
58
|
+
centripetal_lateral_force = np.clip(centripetal_lateral_force, a_min=0, a_max=10000)
|
59
|
+
|
60
|
+
slip_angles_degrees = self.get_slip_angle_for_tire_force(centripetal_lateral_force)
|
61
|
+
slip_angles_radians = np.radians(slip_angles_degrees)
|
62
|
+
slip_distances = np.tan(slip_angles_radians) * required_speed_ms * tick
|
63
|
+
|
64
|
+
return slip_distances * centripetal_lateral_force * self.cornering_coefficient
|
65
|
+
|
66
|
+
def calculate_radii(self, coords):
|
67
|
+
"""
|
68
|
+
Calculate the cornering radii for a given set of waypoints.
|
69
|
+
|
70
|
+
:param np.ndarray coords: (float[N, 2]) Array containing latitude and longitude coordinates of the car's path
|
71
|
+
:returns: (float[N]) Array of cornering radii at each waypoint
|
72
|
+
:rtype: np.ndarray
|
73
|
+
"""
|
74
|
+
|
75
|
+
# pop off last coordinate if first and last coordinate are the same
|
76
|
+
repeated_last_coordinate = False
|
77
|
+
if np.array_equal(coords[0], coords[len(coords) - 1]):
|
78
|
+
coords = coords[:-1]
|
79
|
+
repeated_last_coordinate = True
|
80
|
+
|
81
|
+
cornering_radii = np.empty(len(coords))
|
82
|
+
for i in range(len(coords)):
|
83
|
+
# if the next point or previous point is out of bounds, wrap the index around the array
|
84
|
+
i2 = (i - 1) % len(coords)
|
85
|
+
i3 = (i + 1) % len(coords)
|
86
|
+
current_point = coords[i]
|
87
|
+
previous_point = coords[i2]
|
88
|
+
next_point = coords[i3]
|
89
|
+
|
90
|
+
x1 = 0
|
91
|
+
y1 = 0
|
92
|
+
x2, y2 = self.calculate_meter_distance(current_point, previous_point)
|
93
|
+
x3, y3 = self.calculate_meter_distance(current_point, next_point)
|
94
|
+
cornering_radii[i] = self.radius_of_curvature(x1, y1, x2, y2, x3, y3)
|
95
|
+
|
96
|
+
# If the last coordinate was removed, duplicate the first radius value to the end of the array
|
97
|
+
if repeated_last_coordinate:
|
98
|
+
cornering_radii = np.append(cornering_radii, cornering_radii[0])
|
99
|
+
|
100
|
+
# ensure that super large radii are bounded by a large number, like 10000
|
101
|
+
cornering_radii = np.where(np.isnan(cornering_radii), 10000, cornering_radii)
|
102
|
+
cornering_radii = np.where(cornering_radii > 10000, 10000, cornering_radii)
|
103
|
+
|
104
|
+
return cornering_radii
|
105
|
+
|
106
|
+
def generate_slip_angle_lookup(self, min_degrees, max_degrees, num_elements):
|
107
|
+
"""
|
108
|
+
Generate a lookup table of slip angles and corresponding tire forces using Pacejka's Magic Formula.
|
109
|
+
|
110
|
+
https://www.edy.es/dev/docs/pacejka-94-parameters-explained-a-comprehensive-guide/
|
111
|
+
|
112
|
+
:param float min_degrees: Minimum slip angle in degrees
|
113
|
+
:param float max_degrees: Maximum slip angle in degrees
|
114
|
+
:param int num_elements: Number of discrete elements in the lookup table
|
115
|
+
:returns: (float[num_elements], float[num_elements]) Arrays of slip angles (degrees) and corresponding tire forces (Newtons)
|
116
|
+
:rtype: tuple[np.ndarray, np.ndarray]
|
117
|
+
"""
|
118
|
+
|
119
|
+
b = .25 # Stiffness
|
120
|
+
c = 2.2 # Shape
|
121
|
+
d = 2.75 # Peak
|
122
|
+
e = 1.0 # Curvature
|
123
|
+
|
124
|
+
fz = self.vehicle_mass * 9.81 # Newtons
|
125
|
+
|
126
|
+
slip_angles = np.linspace(min_degrees, max_degrees, num_elements)
|
127
|
+
tire_forces = fz * d * np.sin(
|
128
|
+
c * np.arctan(b * slip_angles - e * (b * slip_angles - np.arctan(b * slip_angles))))
|
129
|
+
|
130
|
+
return slip_angles, tire_forces
|
131
|
+
|
132
|
+
def get_slip_angle_for_tire_force(self, desired_tire_force):
|
133
|
+
slip_angles, tire_forces = self.generate_slip_angle_lookup(0, 70, 100000)
|
134
|
+
|
135
|
+
# Use the numpy interpolation function to find slip angle for the given tire force
|
136
|
+
estimated_slip_angle = np.interp(desired_tire_force, tire_forces, slip_angles)
|
137
|
+
|
138
|
+
return estimated_slip_angle
|
139
|
+
|
140
|
+
@staticmethod
|
141
|
+
def calculate_meter_distance(coord1: NDArray, coord2: NDArray):
|
142
|
+
"""
|
143
|
+
Calculate the x and y distance in meters between two latitude-longitude coordinates.
|
144
|
+
|
145
|
+
:param tuple coord1: (float[2]) The (latitude, longitude) coordinates of the first point
|
146
|
+
:param tuple coord2: (float[2]) The (latitude, longitude) coordinates of the second point
|
147
|
+
:returns: (float[2]) The x (longitude) and y (latitude) distances in meters
|
148
|
+
:rtype: tuple
|
149
|
+
"""
|
150
|
+
lat1, lon1 = coord1
|
151
|
+
lat2, lon2 = coord2
|
152
|
+
|
153
|
+
# Base coordinate
|
154
|
+
coord_base = (lat1, lon1)
|
155
|
+
# Coordinate for latitude difference (keep longitude the same)
|
156
|
+
coord_lat = (lat2, lon1)
|
157
|
+
# Coordinate for longitude difference (keep latitude the same)
|
158
|
+
coord_long = (lat1, lon2)
|
159
|
+
|
160
|
+
# Calculate y distance (latitude difference)
|
161
|
+
y_distance = haversine(coord_base, coord_lat, unit=Unit.METERS)
|
162
|
+
# Calculate x distance (longitude difference)
|
163
|
+
x_distance = haversine(coord_base, coord_long, unit=Unit.METERS)
|
164
|
+
|
165
|
+
if lat2 < lat1:
|
166
|
+
y_distance = -y_distance
|
167
|
+
if lon2 < lon1:
|
168
|
+
x_distance = -x_distance
|
169
|
+
|
170
|
+
return x_distance, y_distance
|
171
|
+
|
172
|
+
@staticmethod
|
173
|
+
def radius_of_curvature(x1, y1, x2, y2, x3, y3):
|
174
|
+
"""
|
175
|
+
Uses the circumcircle the radius of curvature of a circle passing through three points.
|
176
|
+
|
177
|
+
:param float x1: X-coordinate of the first point
|
178
|
+
:param float y1: Y-coordinate of the first point
|
179
|
+
:param float x2: X-coordinate of the second point
|
180
|
+
:param float y2: Y-coordinate of the second point
|
181
|
+
:param float x3: X-coordinate of the third point
|
182
|
+
:param float y3: Y-coordinate of the third point
|
183
|
+
:returns: Radius of curvature of the circle passing through the three points
|
184
|
+
:rtype: float
|
185
|
+
"""
|
186
|
+
numerator = np.sqrt(
|
187
|
+
((x3 - x2) ** 2 + (y3 - y2) ** 2) *
|
188
|
+
((x1 - x3) ** 2 + (y1 - y3) ** 2) *
|
189
|
+
((x2 - x1) ** 2 + (y2 - y1) ** 2)
|
190
|
+
)
|
191
|
+
|
192
|
+
denominator = 2 * abs(
|
193
|
+
((x2 - x1) * (y1 - y3) - (x1 - x3) * (y2 - y1))
|
194
|
+
)
|
195
|
+
|
196
|
+
return numerator / denominator
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import math
|
2
2
|
import numpy as np
|
3
|
-
|
3
|
+
from numpy.typing import NDArray
|
4
4
|
from physics.models.motor.base_motor import BaseMotor
|
5
5
|
from physics.models.constants import ACCELERATION_G, AIR_DENSITY
|
6
6
|
|
@@ -33,7 +33,7 @@ class BasicMotor(BaseMotor):
|
|
33
33
|
# print("torque experienced by motor: {} Nm".format(self.constant_torque))
|
34
34
|
|
35
35
|
@staticmethod
|
36
|
-
def calculate_motor_efficiency(motor_angular_speed, motor_output_energy, tick):
|
36
|
+
def calculate_motor_efficiency(motor_angular_speed, motor_output_energy, tick, *args, **kwargs):
|
37
37
|
"""
|
38
38
|
|
39
39
|
Calculates a NumPy array of motor efficiency from NumPy array of operating angular speeds and NumPy array
|
@@ -98,19 +98,20 @@ class BasicMotor(BaseMotor):
|
|
98
98
|
|
99
99
|
return e_mc
|
100
100
|
|
101
|
-
def
|
101
|
+
def calculate_net_force(self,
|
102
|
+
required_speed_kmh: NDArray,
|
103
|
+
wind_speeds: NDArray,
|
104
|
+
gradients: NDArray
|
105
|
+
) -> tuple[NDArray, NDArray]:
|
102
106
|
"""
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
:
|
111
|
-
:returns: (float[N]) energy expended by the motor at every tick
|
112
|
-
:rtype: np.ndarray
|
113
|
-
|
107
|
+
Calculate the net force on the car, and the required wheel angular velocity.
|
108
|
+
Currently, considers:
|
109
|
+
1. Rolling resistance of the wheels on the road
|
110
|
+
2. Drag force (wind + forward velocity)
|
111
|
+
3. Acceleration force (a = F / m)
|
112
|
+
4. Gravitational force (force to go uphill)
|
113
|
+
|
114
|
+
:return: net force in N, wheel angular velocity in rad/s
|
114
115
|
"""
|
115
116
|
required_speed_ms = required_speed_kmh / 3.6
|
116
117
|
|
@@ -129,6 +130,24 @@ class BasicMotor(BaseMotor):
|
|
129
130
|
|
130
131
|
net_force = road_friction_array + drag_forces + g_forces + acceleration_force
|
131
132
|
|
133
|
+
return net_force, required_angular_speed_rads
|
134
|
+
|
135
|
+
def calculate_energy_in(self, required_speed_kmh, gradients, wind_speeds, tick, **kwargs):
|
136
|
+
"""
|
137
|
+
|
138
|
+
Create a function which takes in array of elevation, array of wind speed, required
|
139
|
+
speed, returns the consumed energy.
|
140
|
+
|
141
|
+
:param np.ndarray required_speed_kmh: (float[N]) required speed array in km/h
|
142
|
+
:param np.ndarray gradients: (float[N]) gradient at parts of the road
|
143
|
+
:param np.ndarray wind_speeds: (float[N]) speeds of wind in m/s, where > 0 means against the direction of the vehicle
|
144
|
+
:param float tick: length of 1 update cycle in seconds
|
145
|
+
:returns: (float[N]) energy expended by the motor at every tick
|
146
|
+
:rtype: np.ndarray
|
147
|
+
|
148
|
+
"""
|
149
|
+
net_force, required_angular_speed_rads = self.calculate_net_force(required_speed_kmh, wind_speeds, gradients)
|
150
|
+
|
132
151
|
motor_output_energies = required_angular_speed_rads * net_force * self.tire_radius * tick
|
133
152
|
motor_output_energies = np.clip(motor_output_energies, a_min=0, a_max=None)
|
134
153
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# This file is maintained according to STG Specification #2: Physics Publishing
|
2
2
|
|
3
3
|
[build-system]
|
4
|
-
requires = ["setuptools
|
4
|
+
requires = ["setuptools<75", "setuptools-scm<8.2.0", "setuptools-rust"]
|
5
5
|
build-backend = "setuptools.build_meta"
|
6
6
|
|
7
7
|
[project]
|
@@ -60,7 +60,7 @@ dependencies = [
|
|
60
60
|
"jaraco.context==5.3.0",
|
61
61
|
"jaraco.functools==4.0.2",
|
62
62
|
"keyring==25.3.0",
|
63
|
-
"llvmlite
|
63
|
+
"llvmlite",
|
64
64
|
"markdown-it-py==3.0.0",
|
65
65
|
"mdurl==0.1.2",
|
66
66
|
"more-itertools==10.4.0",
|
@@ -104,7 +104,7 @@ py-limited-api = "auto" # Default value, can be omitted
|
|
104
104
|
|
105
105
|
[tool.cibuildwheel]
|
106
106
|
archs = "auto" # Automatically detects architectures (e.g., x86, ARM)
|
107
|
-
skip = ["pp*", "*-musllinux_*", "*-win32"] # Skip PyPy (only want CPython), Musllinux, win32 wheels
|
107
|
+
skip = ["pp*", "*-musllinux_*", "*-win32", "*i686"] # Skip PyPy (only want CPython), Musllinux, win32, i686 wheels
|
108
108
|
manylinux-x86_64-image = "manylinux2014"
|
109
109
|
manylinux-i686-image = "manylinux2014"
|
110
|
-
manylinux-aarch64-image = "manylinux2014"
|
110
|
+
manylinux-aarch64-image = "manylinux2014"
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.1
|
2
2
|
Name: ubc-solar-physics
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.5.0
|
4
4
|
Summary: UBC Solar's Simulation Environment
|
5
5
|
Author: Fisher Xue, Mihir Nimgade, Chris Chang, David Widjaja, Justin Hua, Ilya Veksler, Renu Rajamagesh, Ritchie Xia, Erik Langille, Chris Aung, Nicolas Ric, Ishaan Trivedi, Jason Liang, Felix Toft, Mack Wilson, Jonah Lee, Tamzeed Quazi, Joshua Riefman
|
6
6
|
Author-email: UBC Solar <strategy@ubcsolar.com>
|
@@ -50,7 +50,7 @@ Requires-Dist: jaraco.classes==3.4.0
|
|
50
50
|
Requires-Dist: jaraco.context==5.3.0
|
51
51
|
Requires-Dist: jaraco.functools==4.0.2
|
52
52
|
Requires-Dist: keyring==25.3.0
|
53
|
-
Requires-Dist: llvmlite
|
53
|
+
Requires-Dist: llvmlite
|
54
54
|
Requires-Dist: markdown-it-py==3.0.0
|
55
55
|
Requires-Dist: mdurl==0.1.2
|
56
56
|
Requires-Dist: more-itertools==10.4.0
|
@@ -81,6 +81,7 @@ physics/models/lvs/base_lvs.py
|
|
81
81
|
physics/models/lvs/basic_lvs.py
|
82
82
|
physics/models/lvs/lvs.rs
|
83
83
|
physics/models/motor/__init__.py
|
84
|
+
physics/models/motor/advanced_motor.py
|
84
85
|
physics/models/motor/base_motor.py
|
85
86
|
physics/models/motor/basic_motor.py
|
86
87
|
physics/models/motor/motor.rs
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/battery_model_examples/data_py.png
RENAMED
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/battery_model_examples/data_rust.png
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/kalman_filter_examples/current.csv
RENAMED
File without changes
|
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/examples/kalman_filter_examples/voltage.csv
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/environment/meteorology/meteorology.rs
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/battery_config.py
RENAMED
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/physics/models/battery/battery_config.toml
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/ubc_solar_physics.egg-info/dependency_links.txt
RENAMED
File without changes
|
{ubc_solar_physics-1.4.1 → ubc_solar_physics-1.5.0}/ubc_solar_physics.egg-info/top_level.txt
RENAMED
File without changes
|