ubc-solar-physics 1.7.10__cp313-cp313-win_amd64.whl → 1.8.0__cp313-cp313-win_amd64.whl

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.
physics/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.7.10'
16
- __version_tuple__ = version_tuple = (1, 7, 10)
15
+ __version__ = version = '1.8.0'
16
+ __version_tuple__ = version_tuple = (1, 8, 0)
@@ -24,6 +24,11 @@ class BaseGIS(ABC):
24
24
  def get_path(self) -> np.ndarray:
25
25
  raise NotImplementedError
26
26
 
27
+ @staticmethod
28
+ @abstractmethod
29
+ def calculate_speeds_and_position(speeds_kmh: NDArray, track_speeds, path_distances, dt):
30
+ raise NotImplementedError
31
+
27
32
  @abstractmethod
28
33
  def calculate_current_heading_array(self) -> np.ndarray:
29
34
  raise NotImplementedError
@@ -33,6 +38,7 @@ class BaseGIS(ABC):
33
38
  average_lap_speeds: ArrayLike,
34
39
  simulation_dt: int,
35
40
  driving_allowed: ArrayLike,
36
- idle_time: int
41
+ idle_time: int,
42
+ laps_per_speed: int
37
43
  ) -> NDArray[float]:
38
44
  raise NotImplementedError
@@ -34,21 +34,9 @@ class GIS(BaseGIS):
34
34
  self.path_time_zones = route_data['time_zones']
35
35
  self.num_unique_coords = route_data['num_unique_coords']
36
36
 
37
- if current_coord is not None:
38
- if not np.array_equal(current_coord, origin_coord):
39
- logging.warning("Current position is not origin position. Modifying path data.\n")
40
-
41
- # We need to find the closest coordinate along the path to the vehicle position
42
- current_coord_index = GIS._find_closest_coordinate_index(current_coord, self.path)
43
-
44
- # All coords before the current coordinate should be discarded
45
- self.path = self.path[current_coord_index:]
46
- self.path_elevations = self.path_elevations[current_coord_index:]
47
- self.path_time_zones = self.path_time_zones[current_coord_index:]
48
-
49
- self.path_distances = calculate_path_distances(self.path)
37
+ self.path_distances = calculate_path_distances(self.path)[:self.num_unique_coords]
50
38
  self.path_length = np.cumsum(calculate_path_distances(self.path[:self.num_unique_coords]))[-1]
51
- self.path_gradients = calculate_path_gradients(self.path_elevations, self.path_distances)
39
+ self.path_gradients = calculate_path_gradients(self.path_elevations[:self.num_unique_coords], self.path_distances)
52
40
 
53
41
  @staticmethod
54
42
  def process_KML_file(route_file):
@@ -83,12 +71,58 @@ class GIS(BaseGIS):
83
71
  """
84
72
  return physics_rs.closest_gis_indices_loop(distances, self.path_distances)
85
73
 
74
+ def calculate_speeds_and_position(self, speeds_kmh: NDArray, track_speeds: NDArray, dt: int):
75
+ try:
76
+ return physics_rs.calculate_speeds_and_position(speeds_kmh, self.path_distances, track_speeds, dt)
77
+
78
+ except Exception:
79
+ return self._py_calculate_speeds_and_position(speeds_kmh, track_speeds, dt)
80
+
81
+ def _py_calculate_speeds_and_position(self, speeds_kmh: NDArray, track_speeds: NDArray, dt: int):
82
+ """
83
+ Given the original, lap-averaged `speeds_kmh` and an array of speed deviations in km/h for each track index,
84
+ compute the position and actual speed as simulation-time arrays.
85
+
86
+ :param speeds_kmh: Lap-averaged speeds in km/h.
87
+ :param track_speeds: A speed deviation in km/h for each track index. Expects the mean to be at 0.
88
+ :param dt:
89
+ :return:
90
+ """
91
+ result = []
92
+ actual_speeds_kmh = []
93
+
94
+ with tqdm(total=len(speeds_kmh), file=sys.stdout, desc="Calculating closest GIS indices") as pbar:
95
+ distance_travelled = 0
96
+ track_index = 0
97
+
98
+ for lap_speed in speeds_kmh:
99
+ if lap_speed > 0:
100
+ actual_speed = lap_speed + track_speeds[track_index]
101
+ else:
102
+ actual_speed = 0
103
+
104
+ actual_speeds_kmh.append(actual_speed)
105
+ distance_travelled += actual_speed * dt
106
+
107
+ while distance_travelled > self.path_distances[track_index]:
108
+ distance_travelled -= self.path_distances[track_index]
109
+ track_index += 1
110
+
111
+ if track_index >= len(self.path_distances):
112
+ track_index = 0
113
+
114
+ result.append(track_index)
115
+ pbar.update(1)
116
+
117
+ return np.array(result), np.array(actual_speeds_kmh)
118
+
86
119
  def calculate_driving_speeds(
87
120
  self,
88
121
  average_lap_speeds: ArrayLike,
89
122
  simulation_dt: int,
90
123
  driving_allowed: ArrayLike,
91
- idle_time: int
124
+ idle_time: int,
125
+ laps_per_speed: int
92
126
  ) -> NDArray[float]:
93
127
  """
94
128
  Generate valid driving speeds as a simulation-time array given a set of average speeds for each
@@ -105,6 +139,7 @@ class GIS(BaseGIS):
105
139
  are allowed to drive, and `False` is when we are not. Requires that (at least) the first element is
106
140
  `False` due to the race beginning in the morning before we are allowed to drive.
107
141
  :param idle_time: The length of time to pause driving upon processing a "0m/s" average speed.
142
+ :param laps_per_speed: The amount of laps that we expect to use with each speed value.
108
143
  :return: A simulation-time array of driving speeds in m/s, or an error if there weren't enough
109
144
  laps provided to fill the entire simulation time.
110
145
  """
@@ -112,7 +147,7 @@ class GIS(BaseGIS):
112
147
  np.array(average_lap_speeds).astype(np.float64),
113
148
  simulation_dt,
114
149
  np.array(driving_allowed).astype(bool),
115
- self.path_length,
150
+ self.path_length * laps_per_speed,
116
151
  idle_time
117
152
  )
118
153
 
@@ -26,6 +26,44 @@ pub fn rust_closest_gis_indices_loop(
26
26
  result
27
27
  }
28
28
 
29
+ pub fn calculate_speeds_and_position(
30
+ speeds_kmh: ArrayView1<'_, f64>,
31
+ path_distances: ArrayView1<'_, f64>,
32
+ track_speeds: ArrayView1<'_, f64>,
33
+ simulation_dt: u32,
34
+ ) -> (Vec<usize>, Vec<f64>) {
35
+ let mut track_index: usize = 0;
36
+ let mut distance_travelled: f64 = 0.0;
37
+ let n = path_distances.len();
38
+
39
+ let mut result: Vec<usize> = Vec::with_capacity(speeds_kmh.len());
40
+ let mut actual_speeds_kmh: Vec<f64> = Vec::with_capacity(speeds_kmh.len());
41
+
42
+ for &speed in speeds_kmh {
43
+ let actual_speed = if speed > 0.0 {
44
+ speed + track_speeds[track_index]
45
+ } else {
46
+ 0.0
47
+ };
48
+
49
+ actual_speeds_kmh.push(actual_speed);
50
+ distance_travelled += actual_speed * simulation_dt as f64;
51
+
52
+ while distance_travelled > path_distances[track_index] {
53
+ distance_travelled -= path_distances[track_index];
54
+ track_index += 1;
55
+
56
+ if track_index >= n {
57
+ track_index = 0;
58
+ }
59
+ }
60
+
61
+ result.push(track_index);
62
+ }
63
+
64
+ (result, actual_speeds_kmh)
65
+ }
66
+
29
67
  ///
30
68
  /// Generate valid driving speeds as a simulation-time array given a set of average speeds for each
31
69
  /// simulated lap.
physics/lib.rs CHANGED
@@ -5,7 +5,7 @@ use pyo3::types::PyModule;
5
5
 
6
6
  pub mod environment;
7
7
  pub mod models;
8
- use crate::environment::gis::gis::{rust_closest_gis_indices_loop, get_driving_speeds};
8
+ use crate::environment::gis::gis::{rust_closest_gis_indices_loop, get_driving_speeds, calculate_speeds_and_position};
9
9
  use crate::environment::meteorology::meteorology::{rust_calculate_array_ghi_times, rust_closest_weather_indices_loop, rust_weather_in_time};
10
10
  use crate::models::battery::battery::update_battery_state;
11
11
 
@@ -135,6 +135,29 @@ fn rust_simulation(_py: Python, m: &PyModule) -> PyResult<()> {
135
135
  (py_soc_array, py_voltage_array)
136
136
  }
137
137
 
138
+ #[pyfn(m)]
139
+ #[pyo3(name = "calculate_speeds_and_position")]
140
+ fn calculate_speeds_and_position_py<'py>(
141
+ py: Python<'py>,
142
+ speeds_kmh_py: PyReadwriteArray1<'py, f64>,
143
+ path_distances_py: PyReadwriteArray1<'py, f64>,
144
+ track_speeds_py: PyReadwriteArray1<'py, f64>,
145
+ simulation_dt: u32,
146
+ ) -> (&'py PyArray1<usize>, &'py PyArray1<f64>) {
147
+ let speeds_kmh = speeds_kmh_py.as_array();
148
+ let path_distances = path_distances_py.as_array();
149
+ let track_speeds = track_speeds_py.as_array();
150
+ let (gis_indices, actual_speeds_kmh): (Vec<usize>, Vec<f64>) = calculate_speeds_and_position(
151
+ speeds_kmh,
152
+ path_distances,
153
+ track_speeds,
154
+ simulation_dt,
155
+ );
156
+ let gis_indices_py = PyArray::from_vec(py, gis_indices);
157
+ let actual_speeds_kmh_py = PyArray::from_vec(py, actual_speeds_kmh);
158
+ (gis_indices_py, actual_speeds_kmh_py)
159
+ }
160
+
138
161
  #[pyfn(m)]
139
162
  #[pyo3(name = "get_driving_speeds")]
140
163
  fn py_get_driving_speeds<'py>(
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ubc-solar-physics
3
- Version: 1.7.10
3
+ Version: 1.8.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>
@@ -1,17 +1,17 @@
1
- physics_rs.cp313-win_amd64.pyd,sha256=IODXdEkbXlIreLGKM8HZrnQYxR1Vsl4D5h1FlG0e_nA,403968
1
+ physics_rs.cp313-win_amd64.pyd,sha256=dHh6gGtEaGbluby1Py82Vfk3OGKSHmPmsQTFwuIFhRk,402432
2
2
  physics/__init__.py,sha256=jRV9J_eGh0vNXEfFrILqcM6xxVjyqm3XwKAg1B1IPBs,183
3
- physics/_version.py,sha256=zbyvF0vz47l4h-H6959cL3Wr3-3fvCmzNwo4YNvowmQ,429
3
+ physics/_version.py,sha256=P0uRCDtksTUMKDoGUCP6kcRBv2l_AtXyHqJM2GKICUI,427
4
4
  physics/environment.rs,sha256=OghmBkvHLZvzzuVsXUmV2lR3X_tEwuB9sT2TGZLQC6E,36
5
- physics/lib.rs,sha256=bvDbtWtLCH-YGSgvzsdKj-S7QVySc3sree6GUqfs-m0,7332
5
+ physics/lib.rs,sha256=NgFabJsnZKqZ9qWDA4xuT1vHnhai3xhn1vhSLl4-rBM,8347
6
6
  physics/models.rs,sha256=747ABP-D1XKxA6X_MNh1PbmST0zsxpxhP_pEWjbR46c,63
7
7
  physics/environment/__init__.py,sha256=se_LVo4aWZKcZgbbK1KwwhHG8SH2zS1g6TEPw0GOZSs,225
8
8
  physics/environment/environment.rs,sha256=-VztdV2_GSlRbyIV_Pt6gKPVxpuNXpjLgAmoervonLg,34
9
9
  physics/environment/gis.rs,sha256=9R7G0cjf5PxQAz-CSryA6-KGfrh1eSwRhJ6qF8KfjDE,12
10
10
  physics/environment/meteorology.rs,sha256=naWb7qYrtMkCE_tLAkM474fmxaufhCkyhy3TTUQ4Yw4,20
11
11
  physics/environment/gis/__init__.py,sha256=SjqhVjuDbZln636zOFROq1tWPfadghkuYz8aheflyxA,96
12
- physics/environment/gis/base_gis.py,sha256=BsrF-r67XMwhjeKqB3zuNOmiC4jFV7HXfpZ_g6ZPASE,1084
13
- physics/environment/gis/gis.py,sha256=jESOVeHvBRxA1SXTLrjbLo5eqH1AmMmHNm1FVLY5FTU,13580
14
- physics/environment/gis/gis.rs,sha256=nyCekzEJCJTpm4Zy6shIm0AEoGsk6TljP-j7KlLn-38,4978
12
+ physics/environment/gis/base_gis.py,sha256=gBoMRFx2OcGhMv4-6GUPdzF64kHDn_szZp53Gpf8_Q4,1290
13
+ physics/environment/gis/gis.py,sha256=1_WFrmGhYa120kXNdfYISxlz1Pb1PQuE0M56bFkcQtk,14937
14
+ physics/environment/gis/gis.rs,sha256=ay9jlparnvHnfYLxNWfsbVqdQVxH-RnqL4fGGdkOVqE,6098
15
15
  physics/environment/meteorology/__init__.py,sha256=mvjJw_0nNLIdh80F_yTaRC3Sw3oI-z1L0J5cOK_ei0k,157
16
16
  physics/environment/meteorology/base_meteorology.py,sha256=n0JsEXQLuciEatQp_S0QBXd_HQzCY5LeIQeVKgl5O-8,2487
17
17
  physics/environment/meteorology/clouded_meteorology.py,sha256=kaMUuQ42P-uvuzpyN8-l0NPk2AxvlfYZAdnxc0CHfuE,28265
@@ -50,8 +50,8 @@ physics/models/regen/base_regen.py,sha256=lY44jrTSHEo8Xv7hKCjo4C3Jx0PUgilyITHwQc
50
50
  physics/models/regen/basic_regen.py,sha256=SZl7nj75w-3uczfNfaZAMtcC4WO8M2mTmwbnB0HmrtU,2402
51
51
  physics/models/regen/regen.rs,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  physics_rs/__init__.pyi,sha256=e34ADL3WjwR8ioVMwa0iDxgbgqUXrwNZvk_WVmrlkho,4346
53
- ubc_solar_physics-1.7.10.dist-info/LICENSE,sha256=1Vq7OikLHh7N0xsmTPHCmPkOxk1AXrMK9k1a1icQFlk,1087
54
- ubc_solar_physics-1.7.10.dist-info/METADATA,sha256=xDRYcUanrdpqeTSW_n1hoWM1GqM1TkJ740D_auWWH0s,5145
55
- ubc_solar_physics-1.7.10.dist-info/WHEEL,sha256=B1Vx2aiwhHpmSjbD9_IfE3D3lmEDXobmECRsgquMEQo,101
56
- ubc_solar_physics-1.7.10.dist-info/top_level.txt,sha256=jBZ5oyp1QQOrKodHG2UH9PMPEiZtza_q3y6fp3lEmQs,19
57
- ubc_solar_physics-1.7.10.dist-info/RECORD,,
53
+ ubc_solar_physics-1.8.0.dist-info/LICENSE,sha256=1Vq7OikLHh7N0xsmTPHCmPkOxk1AXrMK9k1a1icQFlk,1087
54
+ ubc_solar_physics-1.8.0.dist-info/METADATA,sha256=rC2TxVHjfSVobDcaAbVxvOnrHBYNFQwWs1PfmwFoKnw,5144
55
+ ubc_solar_physics-1.8.0.dist-info/WHEEL,sha256=B1Vx2aiwhHpmSjbD9_IfE3D3lmEDXobmECRsgquMEQo,101
56
+ ubc_solar_physics-1.8.0.dist-info/top_level.txt,sha256=jBZ5oyp1QQOrKodHG2UH9PMPEiZtza_q3y6fp3lEmQs,19
57
+ ubc_solar_physics-1.8.0.dist-info/RECORD,,