Skip to content

Commit 7d1843a

Browse files
authored
Merge pull request #8 from ARRC-Rocket/enh/actuator
Implement actuator module
2 parents df3ea41 + 13f53f0 commit 7d1843a

22 files changed

Lines changed: 1566 additions & 746 deletions

docs/examples/halcyon_flight_sim_roll_throttle.ipynb renamed to docs/examples/halcyon_flight_sim_active_control.ipynb

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,11 @@
4444
" Accelerometer,\n",
4545
" Environment,\n",
4646
" Flight,\n",
47-
" Function,\n",
48-
" GnssReceiver,\n",
4947
" Gyroscope,\n",
5048
" Rocket,\n",
5149
")\n",
5250
"from rocketpy.motors import CylindricalTank, Fluid, HybridMotor\n",
5351
"from rocketpy.motors.tank import MassFlowRateBasedTank\n",
54-
"from rocketpy.tools import quaternions_to_spin\n",
5552
"\n",
5653
"plt.style.use(\"seaborn-v0_8-colorblind\")"
5754
]
@@ -284,30 +281,36 @@
284281
"outputs": [],
285282
"source": [
286283
"def tvc_controller_function(\n",
287-
" time, sampling_rate, state, state_history, observed_variables, tvc, sensors\n",
284+
" time,\n",
285+
" sampling_rate,\n",
286+
" state,\n",
287+
" state_history,\n",
288+
" observed_variables,\n",
289+
" thrust_vector_control,\n",
290+
" sensors,\n",
288291
"):\n",
289292
" # state = [x, y, z, vx, vy, vz, e0, e1, e2, e3, wx, wy, wz]\n",
290293
"\n",
291294
" # print(time)\n",
292295
"\n",
293-
" tvc.gimbal_angle_x = 0\n",
294-
" tvc.gimbal_angle_y = 0\n",
296+
" thrust_vector_control.gimbal_angle_x = 0\n",
297+
" thrust_vector_control.gimbal_angle_y = 0\n",
295298
" # Return variables of interest to be saved in the observed_variables list\n",
296299
" return (\n",
297300
" time,\n",
298-
" tvc.gimbal_angle_x,\n",
299-
" tvc.gimbal_angle_y,\n",
301+
" thrust_vector_control.gimbal_angle_x,\n",
302+
" thrust_vector_control.gimbal_angle_y,\n",
300303
" )\n",
301304
"\n",
302305
"\n",
303-
"tvc, tvc_controller = HALCYON.add_tvc(\n",
304-
" gimbal_range=10,\n",
306+
"thrust_vector_control, tvc_controller = HALCYON.add_thrust_vector_control(\n",
307+
" controller_function=tvc_controller_function,\n",
305308
" sampling_rate=100,\n",
309+
" max_gimbal_angle=10,\n",
306310
" gimbal_rate_limit=100,\n",
307-
" controller_function=tvc_controller_function,\n",
308311
" return_controller=True,\n",
309312
")\n",
310-
"tvc.info()\n",
313+
"thrust_vector_control.x.info()\n",
311314
"tvc_controller.info()"
312315
]
313316
},
@@ -373,17 +376,14 @@
373376
" )\n",
374377
"\n",
375378
" # Return variables of interest to be saved in the observed_variables list\n",
376-
" return (\n",
377-
" time,\n",
378-
" roll_control.roll_torque,\n",
379-
" )\n",
379+
" return (time, roll_control.roll_torque, gyro_data, accel_data)\n",
380380
"\n",
381381
"\n",
382382
"roll_control, roll_controller = HALCYON.add_roll_control(\n",
383-
" max_roll_torque=10,\n",
384-
" sampling_rate=100,\n",
385-
" torque_rate_limit=100,\n",
386383
" controller_function=roll_controller_function,\n",
384+
" sampling_rate=100,\n",
385+
" max_roll_torque=10,\n",
386+
" torque_rate_limit=1000,\n",
387387
" return_controller=True,\n",
388388
")\n",
389389
"roll_control.info()\n",
@@ -408,33 +408,26 @@
408408
" # state = [x, y, z, vx, vy, vz, e0, e1, e2, e3, wx, wy, wz]\n",
409409
"\n",
410410
" # Throttle command: 0.5 Hz sinusoid, centered at 0.8, amplitude 0.2\n",
411-
" throttle_control.throttle = 0.8 + 0.2 * np.sin(2 * np.pi * 0.5 * time)\n",
411+
" throttle_command = 0.8 + 0.2 * np.sin(2 * np.pi * 0.5 * time)\n",
412+
" throttle_control.throttle = throttle_command\n",
413+
" throttle_actual = throttle_control.throttle\n",
412414
"\n",
413415
" # Return variables of interest to be saved in the observed_variables list\n",
414416
" return (\n",
415417
" time,\n",
416-
" throttle_control.throttle,\n",
417-
" )"
418-
]
419-
},
420-
{
421-
"cell_type": "code",
422-
"execution_count": null,
423-
"metadata": {},
424-
"outputs": [],
425-
"source": [
418+
" throttle_command,\n",
419+
" throttle_actual,\n",
420+
" )\n",
421+
"\n",
422+
"\n",
426423
"throttle_obj, throttle_controller = HALCYON.add_throttle_control(\n",
427424
" controller_function=throttle_controller_function,\n",
428425
" sampling_rate=100,\n",
429426
" throttle_range=(0.0, 1.0),\n",
430427
" throttle_rate_limit=100,\n",
431-
" initial_throttle=1.0,\n",
428+
" throttle_time_constant=0.5,\n",
432429
" return_controller=True,\n",
433-
" clamp=True,\n",
434-
")\n",
435-
"print(\"has add_throttle_control:\", hasattr(HALCYON, \"add_throttle_control\"))\n",
436-
"print(\"has throttle_control:\", hasattr(HALCYON, \"throttle_control\"))\n",
437-
"print(\"throttle_control:\", getattr(HALCYON, \"throttle_control\", None))"
430+
")"
438431
]
439432
},
440433
{
@@ -461,22 +454,24 @@
461454
" verbose=False,\n",
462455
")\n",
463456
"# test_flight.plots.attitude_data()\n",
464-
"# ===== 先看 throttle 有沒有真的變 =====\n",
457+
"# ===== Plot commanded throttle vs filtered actuator output =====\n",
465458
"obs = np.array(throttle_controller.observed_variables)\n",
466459
"\n",
467460
"t_cmd = obs[:, 0]\n",
468461
"th_cmd = obs[:, 1]\n",
462+
"th_act = obs[:, 2]\n",
469463
"\n",
470464
"plt.figure()\n",
471-
"plt.plot(t_cmd, th_cmd, label=\"Throttle\")\n",
465+
"plt.plot(t_cmd, th_cmd, label=\"Throttle command\")\n",
466+
"plt.plot(t_cmd, th_act, label=\"Filtered throttle\")\n",
472467
"plt.xlabel(\"Time (s)\")\n",
473468
"plt.ylabel(\"Throttle\")\n",
474-
"plt.title(\"Throttle Command\")\n",
469+
"plt.title(\"Throttle Command vs Actuator Output\")\n",
475470
"plt.legend()\n",
476471
"plt.grid()\n",
477472
"plt.show()\n",
478473
"\n",
479-
"# ===== 再看推力有沒有跟著變 =====\n",
474+
"# ===== Then check thrust response =====\n",
480475
"plt.figure()\n",
481476
"plt.plot(\n",
482477
" test_flight.net_thrust[:, 0], test_flight.net_thrust[:, 1], label=\"Effective Thrust\"\n",
@@ -491,15 +486,6 @@
491486
"time1, ax, ay, az = zip(*accelerometer_clean.measured_data)\n",
492487
"time2, gx, gy, gz = zip(*gyro_clean.measured_data)\n",
493488
"\n",
494-
"# plt.plot(time1, ax, label=\"Accelerometer X\")\n",
495-
"# plt.plot(time1, ay, label=\"Accelerometer Y\")\n",
496-
"# plt.plot(time1, az, label=\"Accelerometer Z\")\n",
497-
"# plt.xlabel(\"Time (s)\")\n",
498-
"# plt.ylabel(\"Acceleration (m/s^2)\")\n",
499-
"# plt.legend()\n",
500-
"# plt.grid()\n",
501-
"# plt.show()\n",
502-
"\n",
503489
"plt.plot(time2, gx, label=\"Gyroscope X\")\n",
504490
"plt.plot(time2, gy, label=\"Gyroscope Y\")\n",
505491
"plt.plot(time2, gz, label=\"Gyroscope Z\")\n",
@@ -532,7 +518,7 @@
532518
],
533519
"metadata": {
534520
"kernelspec": {
535-
"display_name": "Python 3",
521+
"display_name": ".venv (3.14.3.final.0)",
536522
"language": "python",
537523
"name": "python3"
538524
},
@@ -546,7 +532,7 @@
546532
"name": "python",
547533
"nbconvert_exporter": "python",
548534
"pygments_lexer": "ipython3",
549-
"version": "3.12.10"
535+
"version": "3.14.3"
550536
}
551537
},
552538
"nbformat": 4,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class _RollActuatorPrints:
2+
"""Class that contains all roll actuator prints."""
3+
4+
def __init__(self, roll_actuator):
5+
"""Initializes _RollActuatorPrints class
6+
7+
Parameters
8+
----------
9+
roll_actuator: rocketpy.RollActuator
10+
Instance of the RollActuator class.
11+
12+
Returns
13+
-------
14+
None
15+
"""
16+
self.roll_actuator = roll_actuator
17+
18+
def basics(self):
19+
"""Prints information of the roll actuator."""
20+
print(f"Information of {self.roll_actuator.name}:")
21+
print("----------------------------------")
22+
print(f"Torque demand rate: {self.roll_actuator.demand_rate} Hz")
23+
print(
24+
f"Torque range: {self.roll_actuator.actuator_range[0]:.2f} to {self.roll_actuator.actuator_range[1]:.2f} N·m"
25+
)
26+
print(f"Torque rate limit: {self.roll_actuator.actuator_rate_limit} N·m/s")
27+
print(
28+
f"Torque clamping: {'Enabled' if self.roll_actuator.clamp else 'Disabled'}"
29+
)
30+
print(f"Torque time constant: {self.roll_actuator.actuator_time_constant} sec")
31+
print(f"Current roll torque: {self.roll_actuator.roll_torque:.2f} N·m")
32+
33+
def all(self):
34+
"""Prints all information of the roll actuator."""
35+
self.basics()

rocketpy/prints/roll_control_prints.py

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class _ThrottleActuatorPrints:
2+
def __init__(self, throttle_actuator):
3+
"""Initializes _ThrottleActuatorPrints class
4+
5+
Parameters
6+
----------
7+
throttle_actuator: rocketpy.ThrottleActuator
8+
Instance of the ThrottleActuator class.
9+
10+
Returns
11+
-------
12+
None
13+
"""
14+
self.throttle_actuator = throttle_actuator
15+
16+
def basics(self):
17+
"""Prints information of the throttle actuator."""
18+
print(f"Information of {self.throttle_actuator.name}:")
19+
print("----------------------------------")
20+
print(f"Throttle demand rate: {self.throttle_actuator.demand_rate} Hz")
21+
print(
22+
f"Throttle range: {self.throttle_actuator.actuator_range[0]:.2f} to {self.throttle_actuator.actuator_range[1]:.2f}"
23+
)
24+
print(f"Throttle rate limit: {self.throttle_actuator.actuator_rate_limit}")
25+
print(
26+
f"Throttle Clamping: {'Enabled' if self.throttle_actuator.clamp else 'Disabled'}"
27+
)
28+
print(
29+
f"Throttle time constant: {self.throttle_actuator.actuator_time_constant} sec"
30+
)
31+
print(f"Current throttle: {self.throttle_actuator.throttle:.2f}")
32+
33+
def all(self):
34+
"""Prints all information of the throttle actuator."""
35+
self.basics()

rocketpy/prints/throttle_control_prints.py

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class _ThrustVectorActuatorPrints:
2+
"""Class that contains all thrust vector actuator prints."""
3+
4+
def __init__(self, thrust_vector_actuator):
5+
"""Initializes _ThrustVectorActuatorPrints class
6+
7+
Parameters
8+
----------
9+
thrust_vector_actuator: rocketpy.ThrustVectorActuator
10+
Instance of the thrust vector actuator class.
11+
12+
Returns
13+
-------
14+
None
15+
"""
16+
self.thrust_vector_actuator = thrust_vector_actuator
17+
18+
def basics(self):
19+
"""Prints information of the thrust vector actuator."""
20+
print(f"Information of {self.thrust_vector_actuator.name}:")
21+
print("----------------------------------")
22+
print(f"Gimbal demand rate: {self.thrust_vector_actuator.demand_rate} Hz")
23+
print(
24+
f"Gimbal range: {self.thrust_vector_actuator.actuator_range[0]:.2f} to {self.thrust_vector_actuator.actuator_range[1]:.2f} deg"
25+
)
26+
print(
27+
f"Gimbal rate limit: {self.thrust_vector_actuator.actuator_rate_limit} deg/sec"
28+
)
29+
print(
30+
f"Gimbal clamping: {'Enabled' if self.thrust_vector_actuator.clamp else 'Disabled'}"
31+
)
32+
print(
33+
f"Gimbal time constant: {self.thrust_vector_actuator.actuator_time_constant} sec"
34+
)
35+
print(
36+
f"Current gimbal angle: {self.thrust_vector_actuator.gimbal_angle:.2f} deg"
37+
)
38+
39+
def all(self):
40+
"""Prints all information of the thrust vector actuator."""
41+
self.basics()

rocketpy/prints/tvc_prints.py

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from rocketpy.rocket.actuator.actuator import Actuator
2+
from rocketpy.rocket.actuator.roll import RollActuator
3+
from rocketpy.rocket.actuator.throttle import ThrottleActuator
4+
from rocketpy.rocket.actuator.thrust_vector import ThrustVectorActuator

0 commit comments

Comments
 (0)