From f6ccce30fb1b93b8249b327db837de4a541dedbc Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 12:00:52 -0300 Subject: [PATCH 01/14] DOC: better documentation of HibridMotor docstring --- rocketpy/motors/hybrid_motor.py | 35 +++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/rocketpy/motors/hybrid_motor.py b/rocketpy/motors/hybrid_motor.py index a4468bc26..d23812ddb 100644 --- a/rocketpy/motors/hybrid_motor.py +++ b/rocketpy/motors/hybrid_motor.py @@ -45,12 +45,15 @@ class HybridMotor(Motor): The total mass of the motor structure, including chambers and tanks, when it is empty and does not contain any propellant. HybridMotor.propellant_initial_mass : float - Total propellant initial mass in kg. + Total propellant initial mass in kg. This is the sum of the initial + mass of fluids in each tank and the initial mass of the solid grains. HybridMotor.total_mass : Function Total motor mass in kg as a function of time, defined as the sum - of propellant and dry mass. + of the dry mass (motor's structure mass) and the propellant mass, which + varies with time. HybridMotor.propellant_mass : Function - Total propellant mass in kg as a function of time. + Total propellant mass in kg as a function of time, this includes the + mass of fluids in each tank and the mass of the solid grains. HybridMotor.total_mass_flow_rate : Function Time derivative of propellant total mass in kg/s as a function of time as obtained by the thrust source. @@ -345,18 +348,19 @@ def exhaust_velocity(self): @funcify_method("Time (s)", "Mass (kg)") def propellant_mass(self): """Evaluates the total propellant mass of the motor as the sum - of each tank mass and the grains mass. + of fluids mass in each tank and the grains mass. Returns ------- Function - Total propellant mass of the motor, in kg. + Total propellant mass of the motor as a function of time, in kg. """ return self.solid.propellant_mass + self.liquid.propellant_mass @cached_property def propellant_initial_mass(self): - """Returns the initial propellant mass of the motor. + """Returns the initial propellant mass of the motor. See the docs of the + HybridMotor.propellant_mass property for more information. Returns ------- @@ -367,8 +371,8 @@ def propellant_initial_mass(self): @funcify_method("Time (s)", "mass flow rate (kg/s)", extrapolation="zero") def mass_flow_rate(self): - """Evaluates the mass flow rate of the motor as the sum of each tank - mass flow rate and the grains mass flow rate. + """Evaluates the mass flow rate of the motor as the sum of mass flow + rates from all tanks and the solid grains mass flow rate. Returns ------- @@ -486,6 +490,21 @@ def propellant_I_33(self): @funcify_method("Time (s)", "Inertia I_12 (kg m²)") def propellant_I_12(self): + """Inertia tensor 12 component of the propellant, the inertia is + relative to the e_1 and e_2 axes, centered at the instantaneous + propellant center of mass. + + Returns + ------- + Function + Propellant inertia tensor 12 component at time t. + + Notes + ----- + This is assumed to be zero due to axial symmetry of the motor. This + could be improved in the future to account for the fact that the + motor is not perfectly symmetric. + """ return 0 @funcify_method("Time (s)", "Inertia I_13 (kg m²)") From 4733c19e8ae96057139ef8dd3c17e1a966be8f23 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 12:14:11 -0300 Subject: [PATCH 02/14] DOC: better documentation of LiquidMotor docstring --- rocketpy/motors/liquid_motor.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/rocketpy/motors/liquid_motor.py b/rocketpy/motors/liquid_motor.py index d89157e72..ec6b286ca 100644 --- a/rocketpy/motors/liquid_motor.py +++ b/rocketpy/motors/liquid_motor.py @@ -40,11 +40,10 @@ class LiquidMotor(Motor): The total mass of the motor structure, including chambers and tanks, when it is empty and does not contain any propellant. LiquidMotor.propellant_initial_mass : float - Total propellant initial mass in kg, includes - fuel and oxidizer. + Total propellant initial mass in kg, includes fuel and oxidizer. LiquidMotor.total_mass : Function Total motor mass in kg as a function of time, defined as the sum - of propellant and dry mass. + of propellant mass and the motor's dry mass (i.e. structure mass). LiquidMotor.propellant_mass : Function Total propellant mass in kg as a function of time, includes fuel and oxidizer. @@ -260,12 +259,19 @@ def exhaust_velocity(self): ------- self.exhaust_velocity : Function Gas exhaust velocity of the motor. + + Notes + ----- + The exhaust velocity is computed as the ratio of the thrust and the + mass flow rate. Therefore, this will vary with time if the mass flow + rate varies with time. """ return self.thrust / (-1 * self.mass_flow_rate) @funcify_method("Time (s)", "Propellant Mass (kg)") def propellant_mass(self): - """Evaluates the mass of the motor as the sum of each tank mass. + """Evaluates the mass of the motor as the sum of fluids mass in each + tank, which may include fuel and oxidizer and usually vary with time. Returns ------- @@ -281,7 +287,8 @@ def propellant_mass(self): @cached_property def propellant_initial_mass(self): - """Property to store the initial mass of the propellant. + """Property to store the initial mass of the propellant, this includes + fuel and oxidizer. Returns ------- @@ -292,8 +299,9 @@ def propellant_initial_mass(self): @funcify_method("Time (s)", "Mass flow rate (kg/s)", extrapolation="zero") def mass_flow_rate(self): - """Evaluates the mass flow rate of the motor as the sum of each tank - mass flow rate. + """Evaluates the mass flow rate of the motor as the sum of mass flow + rate from each tank, which may include fuel and oxidizer and usually + vary with time. Returns ------- @@ -317,12 +325,12 @@ def mass_flow_rate(self): def center_of_propellant_mass(self): """Evaluates the center of mass of the motor from each tank center of mass and positioning. The center of mass height is measured relative to - the motor nozzle. + the origin of the motor's coordinate system. Returns ------- Function - Center of mass of the motor, in meters. + Position of the propellant center of mass, in meters. """ total_mass = 0 mass_balance = 0 From 5387b49fe1de779984b768e5b8a0835bb2284921 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 12:38:50 -0300 Subject: [PATCH 03/14] DOC: better documentation of Motor abstract class --- rocketpy/motors/motor.py | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/rocketpy/motors/motor.py b/rocketpy/motors/motor.py index 2fda0c267..f7bf08e7e 100644 --- a/rocketpy/motors/motor.py +++ b/rocketpy/motors/motor.py @@ -39,12 +39,14 @@ class Motor(ABC): The total mass of the motor structure, including chambers and tanks, when it is empty and does not contain any propellant. Motor.propellant_initial_mass : float - Total propellant initial mass in kg. + Total propellant initial mass in kg, including solid, liquid and gas + phases. Motor.total_mass : Function Total motor mass in kg as a function of time, defined as the sum - of propellant and dry mass. + of propellant mass and the motor's dry mass (i.e. structure mass). Motor.propellant_mass : Function - Total propellant mass in kg as a function of time. + Total propellant mass in kg as a function of time, including solid, + liquid and gas phases. Motor.total_mass_flow_rate : Function Time derivative of propellant total mass in kg/s as a function of time as obtained by the thrust source. @@ -378,7 +380,7 @@ def exhaust_velocity(self): """ pass - @funcify_method("Time (s)", "total mass (kg)") + @funcify_method("Time (s)", "Total mass (kg)") def total_mass(self): """Total mass of the motor as a function of time. It is defined as the propellant mass plus the dry mass. @@ -386,11 +388,11 @@ def total_mass(self): Returns ------- Function - Total mass as a function of time. + Motor total mass as a function of time. """ return self.propellant_mass + self.dry_mass - @funcify_method("Time (s)", "propellant mass (kg)") + @funcify_method("Time (s)", "Propellant mass (kg)") def propellant_mass(self): """Total propellant mass as a Function of time. @@ -403,11 +405,10 @@ def propellant_mass(self): self.total_mass_flow_rate.integral_function() + self.propellant_initial_mass ) - @funcify_method("Time (s)", "mass dot (kg/s)", extrapolation="zero") + @funcify_method("Time (s)", "Mass dot (kg/s)", extrapolation="zero") def total_mass_flow_rate(self): - """Time derivative of propellant mass. Assumes constant exhaust - velocity. The formula used is the opposite of thrust divided by - exhaust velocity. + """Time derivative of the propellant mass as a function of time. The + formula used is the opposite of thrust divided by exhaust velocity. Returns ------- @@ -427,10 +428,8 @@ def total_mass_flow_rate(self): Notes ----- This function computes the total mass flow rate of the motor by - dividing the thrust data by a constant approximation of the exhaust - velocity. - This approximation of the total mass flow rate is used in the - following manner by the child Motor classes: + dividing the thrust data by the exhaust velocity. This is an + approximation, and it is used by the child Motor classes as follows: - The ``SolidMotor`` class uses this approximation to compute the grain's mass flow rate; @@ -449,7 +448,7 @@ def total_mass_flow_rate(self): @property @abstractmethod def propellant_initial_mass(self): - """Propellant initial mass in kg. + """Propellant initial mass in kg, including solid, liquid and gas phases Returns ------- @@ -478,8 +477,8 @@ def center_of_mass(self): @abstractmethod def center_of_propellant_mass(self): """Position of the propellant center of mass as a function of time. - The position is specified as a scalar, relative to the motor's - coordinate system. + The position is specified as a scalar, relative to the origin of the + motor's coordinate system. Returns ------- @@ -501,7 +500,7 @@ def I_11(self): Notes ----- The e_1 direction is assumed to be the direction perpendicular to the - motor body axis. + motor body axis. Also, due to symmetry, I_11 = I_22. References ---------- @@ -540,7 +539,8 @@ def I_22(self): Notes ----- The e_2 direction is assumed to be the direction perpendicular to the - motor body axis, and perpendicular to e_1. + motor body axis, and perpendicular to e_1. Also, due to symmetry, + I_22 = I_11. References ---------- @@ -667,6 +667,7 @@ def I_23(self): ---------- https://en.wikipedia.org/wiki/Moment_of_inertia """ + # wrt = with respect to # Propellant inertia tensor 23 component wrt propellant center of mass propellant_I_23 = self.propellant_I_23 From a26c9c925a8faa337148fe714cbce3e8ace18438 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 13:52:48 -0300 Subject: [PATCH 04/14] DOC: better documentation of SolidMotor class --- rocketpy/motors/solid_motor.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index c92f95007..761fbd2c0 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -65,8 +65,10 @@ class SolidMotor(Motor): SolidMotor.grain_initial_mass : float Initial mass of each grain in kg. SolidMotor.dry_mass : float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, bulkheads, + screws, and others. This should be taken when the motor is empty and + does not contain any propellant. You should not double count a component + that is already accounted for in the rocket class. SolidMotor.propellant_initial_mass : float Total propellant initial mass in kg. SolidMotor.total_mass : Function @@ -78,8 +80,8 @@ class SolidMotor(Motor): Time derivative of propellant total mass in kg/s as a function of time as obtained by the thrust source. SolidMotor.center_of_mass : Function - Position of the motor center of mass in - meters as a function of time. + Position of the motor center of mass in meters as a function of time, + with respect to the motor's coordinate system. See :doc:`Positions and Coordinate Systems ` for more information regarding the motor's coordinate system. @@ -421,7 +423,8 @@ def mass_flow_rate(self): @mass_flow_rate.setter def mass_flow_rate(self, value): - """Sets the mass flow rate of the motor. + """Sets the mass flow rate of the motor. This includes all the grains + burning all at once. Parameters ---------- @@ -432,10 +435,10 @@ def mass_flow_rate(self, value): ------- None """ - self._mass_flow_rate = value.reset("Time (s)", "grain mass flow rate (kg/s)") + self._mass_flow_rate = value.reset("Time (s)", "Grain mass flow rate (kg/s)") self.evaluate_geometry() - @funcify_method("Time (s)", "center of mass (m)", "linear") + @funcify_method("Time (s)", "Center of Propellant Mass (m)", "linear") def center_of_propellant_mass(self): """Position of the propellant center of mass as a function of time. The position is specified as a scalar, relative to the motor's From 8686524c9a7e3a75729497e8e76470216ae9b4b4 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 14:00:36 -0300 Subject: [PATCH 05/14] DOC: fix the "tank mass" terminology --- rocketpy/motors/tank.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketpy/motors/tank.py b/rocketpy/motors/tank.py index 0b7069141..022afed0e 100644 --- a/rocketpy/motors/tank.py +++ b/rocketpy/motors/tank.py @@ -36,7 +36,7 @@ class Tank(ABC): of time. Tank.net_mass_flow_rate : Function Net mass flow rate of the tank in kg/s as a function of time, also - understood as time derivative of the tank mass. + understood as time derivative of the fluids mass. Tank.liquid_volume : Function Volume of the liquid inside the Tank in m^3 as a function of time. Tank.gas_volume : Function From 575adbe47c7701154727b3efad86693dcd037130 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 15:13:11 -0300 Subject: [PATCH 06/14] DOC: improve Rocket class docstrings --- rocketpy/rocket/rocket.py | 207 +++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 113 deletions(-) diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index f491d27c1..2ef9998b2 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -19,7 +19,6 @@ class Rocket: - """Keeps rocket information. Attributes @@ -35,6 +34,19 @@ class Rocket: See :doc:`Positions and Coordinate Systems ` for more information regarding the rocket's coordinate system. + Rocket.center_of_mass_without_motor : int, float + Position, in m, of the rocket's center of mass without motor + relative to the rocket's coordinate system. This does not include + the motor or propellant mass. + Rocket.motor_center_of_mass_position : Function + Position, in meters, of the motor's center of mass relative to the user + defined rocket coordinate system. This is a function of time since the + propellant mass decreases with time. For more information, see the + :doc:`Positions and Coordinate Systems `. + Rocket.motor_center_of_dry_mass_position : float + Position, in meters, of the motor's center of dry mass (i.e. center of + mass without propellant) relative to the user defined rocket coordinate + system. This is constant since the motor dry mass is constant. Rocket.coordinate_system_orientation : string String defining the orientation of the rocket's coordinate system. The coordinate system is defined by the rocket's axis of symmetry. @@ -46,7 +58,7 @@ class Rocket: coordinate system is defined with the rocket's axis of symmetry pointing from the rocket's nose cone to the rocket's tail. Rocket.mass : float - Rocket's mass without propellant in kg. + Rocket's mass without motor and propellant, measured in kg. Rocket.center_of_mass : Function Position of the rocket's center of mass, including propellant, relative to the user defined rocket reference system. @@ -116,6 +128,36 @@ class Rocket: :doc:`Positions and Coordinate Systems ` for more information regarding the rocket's coordinate system. Expressed in meters as a function of time. + Rocket.I_11_without_motor : float + Rocket's inertia tensor 11 component without any motors, in kg*m^2. This + is the same value that is passed in the Rocket.__init__() method. + Rocket.I_22_without_motor : float + Rocket's inertia tensor 22 component without any motors, in kg*m^2. This + is the same value that is passed in the Rocket.__init__() method. + Rocket.I_33_without_motor : float + Rocket's inertia tensor 33 component without any motors, in kg*m^2. This + is the same value that is passed in the Rocket.__init__() method. + Rocket.I_12_without_motor : float + Rocket's inertia tensor 12 component without any motors, in kg*m^2. This + is the same value that is passed in the Rocket.__init__() method. + Rocket.I_13_without_motor : float + Rocket's inertia tensor 13 component without any motors, in kg*m^2. This + is the same value that is passed in the Rocket.__init__() method. + Rocket.I_23_without_motor : float + Rocket's inertia tensor 23 component without any motors, in kg*m^2. This + is the same value that is passed in the Rocket.__init__() method. + Rocket.dry_I_11 : float + Rocket's inertia tensor 11 component with unloaded motor,in kg*m^2. + Rocket.dry_I_22 : float + Rocket's inertia tensor 22 component with unloaded motor,in kg*m^2. + Rocket.dry_I_33 : float + Rocket's inertia tensor 33 component with unloaded motor,in kg*m^2. + Rocket.dry_I_12 : float + Rocket's inertia tensor 12 component with unloaded motor,in kg*m^2. + Rocket.dry_I_13 : float + Rocket's inertia tensor 13 component with unloaded motor,in kg*m^2. + Rocket.dry_I_23 : float + Rocket's inertia tensor 23 component with unloaded motor,in kg*m^2. """ def __init__( @@ -138,15 +180,15 @@ def __init__( mass : int, float Rocket total mass without motor in kg. inertia : tuple, list - Tuple or list containing the rocket's dry mass inertia tensor - components, in kg*m^2. + Tuple or list containing the rocket's inertia tensor components, + in kg*m^2. This should be measured without motor and propellant. Assuming e_3 is the rocket's axis of symmetry, e_1 and e_2 are - orthogonal and form a plane perpendicular to e_3, the dry mass - inertia tensor components must be given in the following order: - (I_11, I_22, I_33, I_12, I_13, I_23), where I_ij is the - component of the inertia tensor in the direction of e_i x e_j. - Alternatively, the inertia tensor can be given as - (I_11, I_22, I_33), where I_12 = I_13 = I_23 = 0. + orthogonal and form a plane perpendicular to e_3, the inertia tensor + components must be given in the following order: (I_11, I_22, I_33, + I_12, I_13, I_23), where I_ij is the component of the inertia tensor + in the direction of e_i x e_j. Alternatively, the inertia tensor can + be given as (I_11, I_22, I_33), where I_12 = I_13 = I_23 = 0. This + can also be called as "rocket dry inertia tensor". power_off_drag : int, float, callable, string, array Rocket's drag coefficient when the motor is off. Can be given as an entry to the Function class. See help(Function) for more @@ -217,13 +259,9 @@ def __init__( self.thrust_eccentricity_y = 0 self.thrust_eccentricity_x = 0 - # Parachute data initialization + # Parachute, Aerodynamic and Rail buttons data initialization self.parachutes = [] - - # Aerodynamic data initialization self.aerodynamic_surfaces = Components() - - # Rail buttons data initialization self.rail_buttons = Components() self.cp_position = 0 @@ -249,7 +287,7 @@ def __init__( self.cp_position = 0 # Set by self.evaluate_static_margin() # Create a, possibly, temporary empty motor - # self.motors = Components() # currently unused since only one motor is supported + # self.motors = Components() # currently unused, only 1 motor is supported self.add_motor(motor=EmptyMotor(), position=0) # Important dynamic inertial quantities @@ -273,18 +311,19 @@ def __init__( self.prints = _RocketPrints(self) self.plots = _RocketPlots(self) - return None - @property def nosecones(self): + """A list containing all the noses currently added to the rocket.""" return self.aerodynamic_surfaces.get_by_type(NoseCone) @property def fins(self): + """A list containing all the fins currently added to the rocket.""" return self.aerodynamic_surfaces.get_by_type(Fins) @property def tails(self): + """A list with all the tails currently added to the rocket""" return self.aerodynamic_surfaces.get_by_type(Tail) def evaluate_total_mass(self): @@ -305,11 +344,9 @@ def evaluate_total_mass(self): print("Please associate this rocket with a motor!") return False - # Calculate total mass by summing up propellant and dry mass self.total_mass = self.mass + self.motor.total_mass - self.total_mass.set_outputs("Total Mass (Rocket + Propellant) (kg)") - - # Return total mass + self.total_mass.set_outputs("Total Mass (Rocket + Motor + Propellant) (kg)") + self.total_mass.set_title("Total Mass (Rocket + Motor + Propellant)") return self.total_mass def evaluate_dry_mass(self): @@ -330,10 +367,9 @@ def evaluate_dry_mass(self): print("Please associate this rocket with a motor!") return False - # Calculate total dry mass: motor (without propellant) + rocket + # Calculate total dry mass: motor (without propellant) + rocket mass self.dry_mass = self.mass + self.motor.dry_mass - # Return total mass return self.dry_mass def evaluate_center_of_mass(self): @@ -348,74 +384,63 @@ def evaluate_center_of_mass(self): See :doc:`Positions and Coordinate Systems ` for more information. """ - # Compute center of mass position self.center_of_mass = ( self.center_of_mass_without_motor * self.mass + self.motor_center_of_mass_position * self.motor.total_mass ) / self.total_mass self.center_of_mass.set_inputs("Time (s)") self.center_of_mass.set_outputs("Center of Mass Position (m)") - + self.center_of_mass.set_title( + "Center of Mass Position (includes motor and propellant)" + ) return self.center_of_mass def evaluate_center_of_dry_mass(self): - """Evaluates rocket center dry of mass (i.e. without propellant) - position relative to user defined rocket reference system. + """Evaluates rocket center dry of mass (i.e. rocket + motor without + propellant) position relative to user defined rocket reference system. Returns ------- self.center_of_dry_mass_position : int, float - Rocket's center of dry mass position relative to user defined rocket - reference system. See - :doc:`Positions and Coordinate Systems ` for - more information. + Rocket's center of dry mass position (with unloaded motor) """ - # Compute center of mass position self.center_of_dry_mass_position = ( self.center_of_mass_without_motor * self.mass + self.motor_center_of_dry_mass_position * self.motor.dry_mass ) / self.dry_mass - return self.center_of_dry_mass_position def evaluate_reduced_mass(self): - """Calculates and returns the rocket's total reduced mass. The - reduced mass is defined as the product of the propellant mass - and the mass of the rocket without propellant, divided by the - sum of the propellant mass and the rocket mass. The function - returns an object of the Function class and is defined as a + """Calculates and returns the rocket's total reduced mass. The reduced + mass is defined as the product of the propellant mass and the rocket dry + mass (i.e. with unloaded motor), divided by the loaded rocket mass. + The function returns an object of the Function class and is defined as a function of time. Returns ------- self.reduced_mass : Function - Function of time expressing the reduced mass of the rocket, - defined as the product of the propellant mass and the mass - of the rocket without propellant, divided by the sum of the - propellant mass and the rocket mass. + Function of time expressing the reduced mass of the rocket. """ + # TODO: add tests for reduced_mass values # Make sure there is a motor associated with the rocket if self.motor is None: print("Please associate this rocket with a motor!") return False - # Retrieve propellant mass as a function of time - motor_mass = self.motor.propellant_mass - - # retrieve constant rocket mass without propellant - mass = self.dry_mass - - # calculate reduced mass - self.reduced_mass = motor_mass * mass / (motor_mass + mass) + # Get nicknames + prop_mass = self.motor.propellant_mass + dry_mass = self.dry_mass + # calculate reduced mass and return it + self.reduced_mass = prop_mass * dry_mass / (prop_mass + dry_mass) self.reduced_mass.set_outputs("Reduced Mass (kg)") - - # Return reduced mass + self.reduced_mass.set_title("Reduced Mass") return self.reduced_mass def evaluate_thrust_to_weight(self): - """Evaluates thrust to weight as a Function of time. - - Uses g = 9.80665 m/s² as nominal gravity for weight calculation. + """Evaluates thrust to weight as a Function of time. This is defined as + the motor thrust force divided by rocket weight. The gravitational + acceleration is assumed constants and equal to 9.80665 m/s^2. Returns ------- @@ -424,6 +449,7 @@ def evaluate_thrust_to_weight(self): self.thrust_to_weight = self.motor.thrust / (9.80665 * self.total_mass) self.thrust_to_weight.set_inputs("Time (s)") self.thrust_to_weight.set_outputs("Thrust/Weight") + self.thrust_to_weight.set_title("Thrust to Weight ratio") def evaluate_static_margin(self): """Calculates and returns the rocket's static margin when @@ -455,21 +481,20 @@ def evaluate_static_margin(self): self.static_margin = (self.center_of_mass - self.cp_position) / ( 2 * self.radius ) - self.static_margin *= ( - self._csys - ) # Change sign if coordinate system is upside down + # Change sign if coordinate system is upside down + self.static_margin *= self._csys self.static_margin.set_inputs("Time (s)") self.static_margin.set_outputs("Static Margin (c)") self.static_margin.set_title("Static Margin") self.static_margin.set_discrete( lower=0, upper=self.motor.burn_out_time, samples=200 ) - return None def evaluate_dry_inertias(self): """Calculates and returns the rocket's dry inertias relative to the rocket's center of mass. The inertias are saved and returned - in units of kg*m². + in units of kg*m². This does not consider propellant mass but does take + into account the motor dry mass. Returns ------- @@ -537,7 +562,6 @@ def evaluate_dry_inertias(self): self.dry_I_13 = self.I_13_without_motor + self.motor.dry_I_13 self.dry_I_23 = self.I_23_without_motor + self.motor.dry_I_23 - # Return inertias return ( self.dry_I_11, self.dry_I_22, @@ -582,7 +606,7 @@ def evaluate_inertias(self): """ # Get masses prop_mass = self.motor.propellant_mass # Propellant mass as a function of time - dry_mass = self.dry_mass # Constant rocket dry mass without propellant + dry_mass = self.dry_mass # Constant rocket mass without motor # Compute axes distances CM_to_CDM = self.center_of_mass - self.center_of_dry_mass_position @@ -665,7 +689,6 @@ def add_motor(self, motor, position): self.evaluate_reduced_mass() self.evaluate_thrust_to_weight() self.evaluate_static_margin() - return None def add_surfaces(self, surfaces, positions): """Adds one or more aerodynamic surfaces to the rocket. The aerodynamic @@ -703,7 +726,6 @@ def add_surfaces(self, surfaces, positions): self.aerodynamic_surfaces.add(surfaces, positions) self.evaluate_static_margin() - return None def add_tail( self, top_radius, bottom_radius, length, position, radius=None, name="Tail" @@ -739,17 +761,11 @@ def add_tail( tail : Tail Tail object created. """ - # Modify reference radius if not provided radius = self.radius if radius is None else radius - - # Create new tail as an object of the Tail class + # Create tail, adds it to the rocket and returns it tail = Tail(top_radius, bottom_radius, length, radius, name) - - # Add tail to aerodynamic surfaces self.add_surfaces(tail, position) - - # Return self return tail def add_nose(self, length, kind, position, bluffness=0, name="Nose Cone"): @@ -785,7 +801,6 @@ def add_nose(self, length, kind, position, bluffness=0, name="Nose Cone"): nose : Nose Nose cone object created. """ - # Create a nose as an object of NoseCone class nose = NoseCone( length=length, kind=kind, @@ -794,11 +809,7 @@ def add_nose(self, length, kind, position, bluffness=0, name="Nose Cone"): bluffness=bluffness, name=name, ) - - # Add nose to the list of aerodynamic surfaces self.add_surfaces(nose, position) - - # Return self return nose def add_fins(self, *args, **kwargs): @@ -911,8 +922,6 @@ def add_trapezoidal_fins( # Add fin set to the list of aerodynamic surfaces self.add_surfaces(fin_set, position) - - # Return the created aerodynamic surface return fin_set def add_elliptical_fins( @@ -974,17 +983,9 @@ def add_elliptical_fins( fin_set : EllipticalFins Fin set object created. """ - - # Modify radius if not given, use rocket radius, otherwise use given. radius = radius if radius is not None else self.radius - - # Create a fin set as an object of EllipticalFins class fin_set = EllipticalFins(n, root_chord, span, radius, cant_angle, airfoil, name) - - # Add fin set to the list of aerodynamic surfaces self.add_surfaces(fin_set, position) - - # Return self return fin_set def add_parachute( @@ -1051,13 +1052,8 @@ def add_parachute( noise_signal and noisyPressureSignal which are filled in during Flight simulation. """ - # Create a parachute parachute = Parachute(name, cd_s, trigger, sampling_rate, lag, noise) - - # Add parachute to list of parachutes self.parachutes.append(parachute) - - # Return self return self.parachutes[-1] def set_rail_buttons( @@ -1096,7 +1092,6 @@ def set_rail_buttons( rail_buttons : RailButtons RailButtons object created """ - # Create a rail buttons object buttons_distance = abs(upper_button_position - lower_button_position) rail_buttons = RailButtons( buttons_distance=buttons_distance, angular_position=angular_position @@ -1108,8 +1103,7 @@ def add_cm_eccentricity(self, x, y): """Moves line of action of aerodynamic and thrust forces by equal translation amount to simulate an eccentricity in the position of the center of mass of the rocket relative to its - geometrical center line. Should not be used together with - add_cp_eccentricity and add_thrust_eccentricity. + geometrical center line. Parameters ---------- @@ -1124,16 +1118,16 @@ def add_cm_eccentricity(self, x, y): ------- self : Rocket Object of the Rocket class. + + Notes + ----- + Should not be used together with add_cp_eccentricity and + add_thrust_eccentricity. """ - # Move center of pressure to -x and -y self.cp_eccentricity_x = -x self.cp_eccentricity_y = -y - - # Move thrust center by -x and -y self.thrust_eccentricity_y = -x self.thrust_eccentricity_x = -y - - # Return self return self def add_cp_eccentricity(self, x, y): @@ -1155,11 +1149,8 @@ def add_cp_eccentricity(self, x, y): self : Rocket Object of the Rocket class. """ - # Move center of pressure by x and y self.cp_eccentricity_x = x self.cp_eccentricity_y = y - - # Return self return self def add_thrust_eccentricity(self, x, y): @@ -1182,11 +1173,8 @@ def add_thrust_eccentricity(self, x, y): self : Rocket Object of the Rocket class. """ - # Move thrust line by x and y self.thrust_eccentricity_y = x self.thrust_eccentricity_x = y - - # Return self return self def info(self): @@ -1197,11 +1185,8 @@ def info(self): ------- None """ - # All prints self.prints.all() - return None - def all_info(self): """Prints out all data and graphs available about the Rocket. @@ -1209,9 +1194,5 @@ def all_info(self): ------- None """ - - # All prints and plots self.info() self.plots.all() - - return None From 8eb1a5738cc057519cddcfaf1ea792d15343921b Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 15:17:04 -0300 Subject: [PATCH 07/14] ENH: use of f-string in rocket prints --- rocketpy/prints/rocket_prints.py | 36 ++++++++------------------------ 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/rocketpy/prints/rocket_prints.py b/rocketpy/prints/rocket_prints.py index a3150ac02..842252a3c 100644 --- a/rocketpy/prints/rocket_prints.py +++ b/rocketpy/prints/rocket_prints.py @@ -22,8 +22,6 @@ def __init__(self, rocket): """ self.rocket = rocket - pass - def inertia_details(self): """Print inertia details. @@ -32,43 +30,27 @@ def inertia_details(self): None """ print("\nInertia Details\n") - print("Rocket Mass: {:.3f} kg".format(self.rocket.mass)) - print("Rocket Dry Mass: {:.3f} kg (With Motor)".format(self.rocket.dry_mass)) + print("Rocket Mass: {self.rocket.mass:.3f} kg") + print(f"Rocket Dry Mass: {self.rocket.dry_mass:.3f} kg (with unloaded motor)") + print(f"Rocket Mass: {self.rocket.total_mass(0):.3f} kg (With Propellant)") print( - "Rocket Mass: {:.3f} kg (With Propellant)".format(self.rocket.total_mass(0)) + f"Rocket Inertia (with unloaded motor) 11: {self.rocket.dry_I_11:.3f} kg*m2" ) print( - "Rocket Inertia (with motor, but without propellant) 11: {:.3f} kg*m2".format( - self.rocket.dry_I_11 - ) + f"Rocket Inertia (with unloaded motor) 22: {self.rocket.dry_I_22:.3f} kg*m2" ) print( - "Rocket Inertia (with motor, but without propellant) 22: {:.3f} kg*m2".format( - self.rocket.dry_I_22 - ) + f"Rocket Inertia (with unloaded motor) 33: {self.rocket.dry_I_33:.3f} kg*m2" ) print( - "Rocket Inertia (with motor, but without propellant) 33: {:.3f} kg*m2".format( - self.rocket.dry_I_33 - ) + f"Rocket Inertia (with unloaded motor) 12: {self.rocket.dry_I_12:.3f} kg*m2" ) print( - "Rocket Inertia (with motor, but without propellant) 12: {:.3f} kg*m2".format( - self.rocket.dry_I_12 - ) + f"Rocket Inertia (with unloaded motor) 13: {self.rocket.dry_I_13:.3f} kg*m2" ) print( - "Rocket Inertia (with motor, but without propellant) 13: {:.3f} kg*m2".format( - self.rocket.dry_I_13 - ) + f"Rocket Inertia (with unloaded motor) 23: {self.rocket.dry_I_23:.3f} kg*m2" ) - print( - "Rocket Inertia (with motor, but without propellant) 23: {:.3f} kg*m2".format( - self.rocket.dry_I_23 - ) - ) - - return None def rocket_geometrical_parameters(self): """Print rocket geometrical parameters. From c4c8f64e44b52730a705f409bd7cf08ccee476d6 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 28 Oct 2023 15:48:40 -0300 Subject: [PATCH 08/14] DOC: fix the rocket mass definition in utilities --- rocketpy/utilities.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/rocketpy/utilities.py b/rocketpy/utilities.py index 78992ffb6..b5e72abcb 100644 --- a/rocketpy/utilities.py +++ b/rocketpy/utilities.py @@ -1,8 +1,8 @@ import traceback import warnings -import numpy as np import matplotlib.pyplot as plt +import numpy as np from scipy.integrate import solve_ivp from .environment.environment import Environment @@ -517,11 +517,11 @@ def create_dispersion_dictionary(filename): def apogee_by_mass(flight, min_mass, max_mass, points=10, plot=True): """Returns a Function object that estimates the apogee of a rocket given - its dry mass. The function will use the rocket's mass as the independent - variable and the estimated apogee as the dependent variable. The function - will use the rocket's environment and inclination to estimate the apogee. - This is useful when you want to adjust the rocket's mass to reach a - specific apogee. + its mass (no motor). The function will use the rocket's mass as the + independent variable and the estimated apogee as the dependent variable. + The function will use the rocket's environment and inclination to estimate + the apogee. This is useful when you want to adjust the rocket's mass to + reach a specific apogee. Parameters ---------- @@ -529,8 +529,8 @@ def apogee_by_mass(flight, min_mass, max_mass, points=10, plot=True): Flight object containing the rocket's flight data min_mass : int The minimum value of mass to calculate the apogee, by default 3. This - value should be the minimum dry mass of the rocket, therefore, a - positive value is expected. + value should be the minimum rocket's mass, therefore, a positive value + is expected. max_mass : int The maximum value of mass to calculate the apogee, by default 30. points : int, optional @@ -544,7 +544,7 @@ def apogee_by_mass(flight, min_mass, max_mass, points=10, plot=True): ------- rocketpy.Function Function object containing the estimated apogee as a function of the - rocket's dry mass. + rocket's mass (without motor nor propellant). """ rocket = flight.rocket @@ -581,8 +581,8 @@ def apogee(mass): def liftoff_speed_by_mass(flight, min_mass, max_mass, points=10, plot=True): """Returns a Function object that estimates the liftoff speed of a rocket - given its dry mass. The function will use the rocket's mass as the - independent variable and the estimated liftoff speed as the dependent + given its mass (without motor). The function will use the rocket's mass as + the independent variable and the estimated liftoff speed as the dependent variable. The function will use the rocket's environment and inclination to estimate the liftoff speed. This is useful when you want to adjust the rocket's mass to reach a specific liftoff speed. @@ -593,8 +593,8 @@ def liftoff_speed_by_mass(flight, min_mass, max_mass, points=10, plot=True): Flight object containing the rocket's flight data min_mass : int The minimum value of mass to calculate the liftoff speed, by default 3. - This value should be the minimum dry mass of the rocket, therefore, a - positive value is expected. + This value should be the minimum mass of the rocket (without a motor), + therefore, a positive value is expected. max_mass : int The maximum value of mass to calculate the liftoff speed, by default 30. points : int, optional @@ -608,7 +608,7 @@ def liftoff_speed_by_mass(flight, min_mass, max_mass, points=10, plot=True): ------- rocketpy.Function Function object containing the estimated liftoff speed as a function of - the rocket's dry mass. + the rocket's mass (without motor nor propellant). """ rocket = flight.rocket From 52f66b56e7a871def3d8b3ee189e73e21ec5fcba Mon Sep 17 00:00:00 2001 From: Guilherme Date: Wed, 8 Nov 2023 05:02:47 -0300 Subject: [PATCH 09/14] DOC: accepts commit suggestion Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> --- rocketpy/rocket/rocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index 2ef9998b2..ad466e21b 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -313,7 +313,7 @@ def __init__( @property def nosecones(self): - """A list containing all the noses currently added to the rocket.""" + """A list containing all the nose cones currently added to the rocket.""" return self.aerodynamic_surfaces.get_by_type(NoseCone) @property From 56ff690f98ab60d292e27b3aade440e01f9c54b1 Mon Sep 17 00:00:00 2001 From: Guilherme Date: Wed, 8 Nov 2023 05:03:22 -0300 Subject: [PATCH 10/14] DOC: accepts commit suggestion Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> --- rocketpy/rocket/rocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index ad466e21b..99cdc018b 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -391,7 +391,7 @@ def evaluate_center_of_mass(self): self.center_of_mass.set_inputs("Time (s)") self.center_of_mass.set_outputs("Center of Mass Position (m)") self.center_of_mass.set_title( - "Center of Mass Position (includes motor and propellant)" + "Center of Mass Position (Rocket + Motor + Propellant)" ) return self.center_of_mass From ee44405bd51065cbd67b227dc09bff60b0315ec8 Mon Sep 17 00:00:00 2001 From: Guilherme Date: Wed, 8 Nov 2023 05:04:17 -0300 Subject: [PATCH 11/14] DOC: accepts commit suggestion Co-authored-by: MateusStano <69485049+MateusStano@users.noreply.github.com> --- rocketpy/rocket/rocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index 99cdc018b..dfaa77d08 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -606,7 +606,7 @@ def evaluate_inertias(self): """ # Get masses prop_mass = self.motor.propellant_mass # Propellant mass as a function of time - dry_mass = self.dry_mass # Constant rocket mass without motor + dry_mass = self.dry_mass # Constant rocket mass with motor, without propellant # Compute axes distances CM_to_CDM = self.center_of_mass - self.center_of_dry_mass_position From 8d0169ec64c8228196cd6d14ff883f907ace0045 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Thu, 9 Nov 2023 16:12:22 -0300 Subject: [PATCH 12/14] DOC: Update dry_mass documentation for all motor classes --- rocketpy/motors/hybrid_motor.py | 13 +++++++++---- rocketpy/motors/liquid_motor.py | 13 +++++++++---- rocketpy/motors/motor.py | 20 ++++++++++++++------ rocketpy/motors/solid_motor.py | 6 ++++-- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/rocketpy/motors/hybrid_motor.py b/rocketpy/motors/hybrid_motor.py index d23812ddb..7613c0b6b 100644 --- a/rocketpy/motors/hybrid_motor.py +++ b/rocketpy/motors/hybrid_motor.py @@ -42,8 +42,10 @@ class HybridMotor(Motor): HybridMotor.liquid : LiquidMotor Liquid motor object that composes the hybrid motor. HybridMotor.dry_mass : float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, bulkheads, + screws, tanks, and others. This should be taken when the motor is + empty and does not contain any propellant. You should not double + count a component that is already accounted for in the rocket class. HybridMotor.propellant_initial_mass : float Total propellant initial mass in kg. This is the sum of the initial mass of fluids in each tank and the initial mass of the solid grains. @@ -202,8 +204,11 @@ def __init__( .. seealso:: :doc:`Thrust Source Details ` dry_mass : int, float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, + bulkheads, screws, tanks, and others. This should be taken when the + motor is empty and does not contain any propellant. You should not + double count a component that is already accounted for in the rocket + class. dry_inertia : tuple, list Tuple or list containing the motor's dry mass inertia tensor components, in kg*m^2. This inertia is defined with respect to the diff --git a/rocketpy/motors/liquid_motor.py b/rocketpy/motors/liquid_motor.py index ec6b286ca..ba0f8940c 100644 --- a/rocketpy/motors/liquid_motor.py +++ b/rocketpy/motors/liquid_motor.py @@ -37,8 +37,10 @@ class LiquidMotor(Motor): List containing the motor's added tanks and their respective positions. LiquidMotor.dry_mass : float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, bulkheads, + screws, tanks, and others. This should be taken when the motor is empty + and does not contain any propellant. You should not double count a + component that is already accounted for in the rocket class. LiquidMotor.propellant_initial_mass : float Total propellant initial mass in kg, includes fuel and oxidizer. LiquidMotor.total_mass : Function @@ -174,8 +176,11 @@ def __init__( .. seealso:: :doc:`Thrust Source Details ` dry_mass : int, float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, + bulkheads, screws, tanks, and others. This should be taken when the + motor is empty and does not contain any propellant. You should not + double count a component that is already accounted for in the rocket + class. dry_inertia : tuple, list Tuple or list containing the motor's dry mass inertia tensor components, in kg*m^2. This inertia is defined with respect to the diff --git a/rocketpy/motors/motor.py b/rocketpy/motors/motor.py index f7bf08e7e..c7d07aa21 100644 --- a/rocketpy/motors/motor.py +++ b/rocketpy/motors/motor.py @@ -36,8 +36,10 @@ class Motor(ABC): :doc:`Positions and Coordinate Systems ` for more information. Motor.dry_mass : float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, bulkheads, + screws, tanks, and others. This should be taken when the motor is empty + and does not contain any propellant. You should not double count a + component that is already accounted for in the rocket class. Motor.propellant_initial_mass : float Total propellant initial mass in kg, including solid, liquid and gas phases. @@ -176,8 +178,11 @@ def __init__( .. seealso:: :doc:`Thrust Source Details ` dry_mass : int, float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, + bulkheads, screws, tanks, and others. This should be taken when the + motor is empty and does not contain any propellant. You should not + double count a component that is already accounted for in the rocket + class. center_of_dry_mass_position : int, float The position, in meters, of the motor's center of mass with respect to the motor's coordinate system when it is devoid of propellant. @@ -1104,8 +1109,11 @@ def __init__( coordinate system. See :doc:`Positions and Coordinate Systems ` dry_mass : int, float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, + bulkheads, screws, tanks, and others. This should be taken when the + motor is empty and does not contain any propellant. You should not + double count a component that is already accounted for in the rocket + class. propellant_initial_mass : int, float The initial mass of the propellant in the motor. center_of_dry_mass_position : int, float, optional diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index 761fbd2c0..3341ff266 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -228,8 +228,10 @@ def __init__( nozzle_radius : int, float Motor's nozzle outlet radius in meters. dry_mass : int, float - The total mass of the motor structure, including chambers - and tanks, when it is empty and does not contain any propellant. + The total mass of the motor structure, including chambers, + bulkheads, screws, and others. This should be taken when the motor + is empty and does not contain any propellant. You should not double + count a component that is already accounted for in the rocket class. dry_inertia : tuple, list Tuple or list containing the motor's dry mass inertia tensor components, in kg*m^2. This inertia is defined with respect to the From 8eb039d332ed4ef71c5d9ef04b537468ddff80b7 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sun, 12 Nov 2023 18:38:55 -0300 Subject: [PATCH 13/14] DOC: improve docs based on latest review. - Refined input parameters for apogee and liftoff speed calculations - Inertia definition in the Rocket class - Change the Motor.dry_mass definition - Avoid repetition of dry_mass definitions - Add a few for docstrings --- rocketpy/motors/hybrid_motor.py | 35 +++++++++++++++++++++++++++---- rocketpy/motors/liquid_motor.py | 10 ++++----- rocketpy/motors/motor.py | 14 ++++++++----- rocketpy/motors/solid_motor.py | 5 +---- rocketpy/rocket/rocket.py | 11 ++++++---- rocketpy/utilities.py | 37 ++++++++++++++++++++------------- 6 files changed, 75 insertions(+), 37 deletions(-) diff --git a/rocketpy/motors/hybrid_motor.py b/rocketpy/motors/hybrid_motor.py index 7613c0b6b..c52d25612 100644 --- a/rocketpy/motors/hybrid_motor.py +++ b/rocketpy/motors/hybrid_motor.py @@ -42,10 +42,7 @@ class HybridMotor(Motor): HybridMotor.liquid : LiquidMotor Liquid motor object that composes the hybrid motor. HybridMotor.dry_mass : float - The total mass of the motor structure, including chambers, bulkheads, - screws, tanks, and others. This should be taken when the motor is - empty and does not contain any propellant. You should not double - count a component that is already accounted for in the rocket class. + Same as in Motor class. See the :class:`Motor ` docs. HybridMotor.propellant_initial_mass : float Total propellant initial mass in kg. This is the sum of the initial mass of fluids in each tank and the initial mass of the solid grains. @@ -514,10 +511,40 @@ def propellant_I_12(self): @funcify_method("Time (s)", "Inertia I_13 (kg m²)") def propellant_I_13(self): + """Inertia tensor 13 component of the propellant, the inertia is + relative to the e_1 and e_3 axes, centered at the instantaneous + propellant center of mass. + + Returns + ------- + Function + Propellant inertia tensor 13 component at time t. + + Notes + ----- + This is assumed to be zero due to axial symmetry of the motor. This + could be improved in the future to account for the fact that the + motor is not perfectly symmetric. + """ return 0 @funcify_method("Time (s)", "Inertia I_23 (kg m²)") def propellant_I_23(self): + """Inertia tensor 23 component of the propellant, the inertia is + relative to the e_2 and e_3 axes, centered at the instantaneous + propellant center of mass. + + Returns + ------- + Function + Propellant inertia tensor 23 component at time t. + + Notes + ----- + This is assumed to be zero due to axial symmetry of the motor. This + could be improved in the future to account for the fact that the + motor is not perfectly symmetric. + """ return 0 def add_tank(self, tank, position): diff --git a/rocketpy/motors/liquid_motor.py b/rocketpy/motors/liquid_motor.py index ba0f8940c..91422132f 100644 --- a/rocketpy/motors/liquid_motor.py +++ b/rocketpy/motors/liquid_motor.py @@ -37,10 +37,7 @@ class LiquidMotor(Motor): List containing the motor's added tanks and their respective positions. LiquidMotor.dry_mass : float - The total mass of the motor structure, including chambers, bulkheads, - screws, tanks, and others. This should be taken when the motor is empty - and does not contain any propellant. You should not double count a - component that is already accounted for in the rocket class. + Same as in Motor class. See the :class:`Motor ` docs. LiquidMotor.propellant_initial_mass : float Total propellant initial mass in kg, includes fuel and oxidizer. LiquidMotor.total_mass : Function @@ -275,8 +272,9 @@ def exhaust_velocity(self): @funcify_method("Time (s)", "Propellant Mass (kg)") def propellant_mass(self): - """Evaluates the mass of the motor as the sum of fluids mass in each - tank, which may include fuel and oxidizer and usually vary with time. + """Evaluates the total propellant mass of the motor as the sum of fluids + mass in each tank, which may include fuel and oxidizer and usually vary + with time. Returns ------- diff --git a/rocketpy/motors/motor.py b/rocketpy/motors/motor.py index c7d07aa21..b951e8724 100644 --- a/rocketpy/motors/motor.py +++ b/rocketpy/motors/motor.py @@ -36,10 +36,14 @@ class Motor(ABC): :doc:`Positions and Coordinate Systems ` for more information. Motor.dry_mass : float - The total mass of the motor structure, including chambers, bulkheads, - screws, tanks, and others. This should be taken when the motor is empty - and does not contain any propellant. You should not double count a - component that is already accounted for in the rocket class. + The mass of the motor when devoid of any propellants, measured in + kilograms (kg). It encompasses the structural weight of the motor, + including the combustion chamber, nozzles, tanks, and fasteners. + Excluded from this measure are the propellants and any other elements + that are dynamically accounted for in the `mass` parameter of the rocket + class. Ensure that mass contributions from components shared with the + rocket structure are not recounted here. This parameter does not vary + with time. Motor.propellant_initial_mass : float Total propellant initial mass in kg, including solid, liquid and gas phases. @@ -410,7 +414,7 @@ def propellant_mass(self): self.total_mass_flow_rate.integral_function() + self.propellant_initial_mass ) - @funcify_method("Time (s)", "Mass dot (kg/s)", extrapolation="zero") + @funcify_method("Time (s)", "Mass flow rate (kg/s)", extrapolation="zero") def total_mass_flow_rate(self): """Time derivative of the propellant mass as a function of time. The formula used is the opposite of thrust divided by exhaust velocity. diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index 3341ff266..921dc3d7c 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -65,10 +65,7 @@ class SolidMotor(Motor): SolidMotor.grain_initial_mass : float Initial mass of each grain in kg. SolidMotor.dry_mass : float - The total mass of the motor structure, including chambers, bulkheads, - screws, and others. This should be taken when the motor is empty and - does not contain any propellant. You should not double count a component - that is already accounted for in the rocket class. + Same as in Motor class. See the :class:`Motor ` docs. SolidMotor.propellant_initial_mass : float Total propellant initial mass in kg. SolidMotor.total_mass : Function diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index dfaa77d08..029f90c24 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -181,7 +181,9 @@ def __init__( Rocket total mass without motor in kg. inertia : tuple, list Tuple or list containing the rocket's inertia tensor components, - in kg*m^2. This should be measured without motor and propellant. + in kg*m^2. This should be measured without motor and propellant so + that the inertia reference point is the + `center_of_mass_without_motor`. Assuming e_3 is the rocket's axis of symmetry, e_1 and e_2 are orthogonal and form a plane perpendicular to e_3, the inertia tensor components must be given in the following order: (I_11, I_22, I_33, @@ -396,8 +398,9 @@ def evaluate_center_of_mass(self): return self.center_of_mass def evaluate_center_of_dry_mass(self): - """Evaluates rocket center dry of mass (i.e. rocket + motor without - propellant) position relative to user defined rocket reference system. + """Evaluates the rocket's center of dry mass (i.e. rocket with motor but + without propellant) position relative to user defined rocket reference + system. Returns ------- @@ -440,7 +443,7 @@ def evaluate_reduced_mass(self): def evaluate_thrust_to_weight(self): """Evaluates thrust to weight as a Function of time. This is defined as the motor thrust force divided by rocket weight. The gravitational - acceleration is assumed constants and equal to 9.80665 m/s^2. + acceleration is assumed constant and equals to 9.80665 m/s^2. Returns ------- diff --git a/rocketpy/utilities.py b/rocketpy/utilities.py index b5e72abcb..9f7cf3265 100644 --- a/rocketpy/utilities.py +++ b/rocketpy/utilities.py @@ -527,12 +527,16 @@ def apogee_by_mass(flight, min_mass, max_mass, points=10, plot=True): ---------- flight : rocketpy.Flight Flight object containing the rocket's flight data - min_mass : int - The minimum value of mass to calculate the apogee, by default 3. This - value should be the minimum rocket's mass, therefore, a positive value - is expected. - max_mass : int - The maximum value of mass to calculate the apogee, by default 30. + min_mass : float + The minimum value for the rocket's mass to calculate the apogee, given + in kilograms (kg). This value should be the minimum rocket's mass, + therefore, a positive value is expected. See the Rocket.mass attribute + for more details. + max_mass : float + The maximum value for the rocket's mass to calculate the apogee, given + in kilograms (kg). This value should be the maximum rocket's mass, + therefore, a positive value is expected and it should be higher than the + min_mass attribute. See the Rocket.mass attribute for more details. points : int, optional The number of points to calculate the apogee between the mass boundaries, by default 10. Increasing this value will refine the @@ -591,16 +595,21 @@ def liftoff_speed_by_mass(flight, min_mass, max_mass, points=10, plot=True): ---------- flight : rocketpy.Flight Flight object containing the rocket's flight data - min_mass : int - The minimum value of mass to calculate the liftoff speed, by default 3. - This value should be the minimum mass of the rocket (without a motor), - therefore, a positive value is expected. - max_mass : int - The maximum value of mass to calculate the liftoff speed, by default 30. + min_mass : float + The minimum value for the rocket's mass to calculate the out of rail + speed, given in kilograms (kg). This value should be the minimum + rocket's mass, therefore, a positive value is expected. See the + Rocket.mass attribute for more details. + max_mass : float + The maximum value for the rocket's mass to calculate the out of rail + speed, given in kilograms (kg). This value should be the maximum + rocket's mass, therefore, a positive value is expected and it should be + higher than the min_mass attribute. See the Rocket.mass attribute for + more details. points : int, optional The number of points to calculate the liftoff speed between the mass - boundaries, by default 10. Increasing this value will refine the results, - but will also increase the computational time. + boundaries, by default 10. Increasing this value will refine the + results, but will also increase the computational time. plot : bool, optional If True, the function will plot the results, by default True. From 90d489cd3eb80ed4c96da856ecba4d09fa3a7562 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sun, 12 Nov 2023 18:47:51 -0300 Subject: [PATCH 14/14] DOC: Update motor classes to include same dry_mass parameter as in Motor class --- rocketpy/motors/hybrid_motor.py | 6 +----- rocketpy/motors/liquid_motor.py | 6 +----- rocketpy/motors/motor.py | 12 ++---------- rocketpy/motors/solid_motor.py | 5 +---- rocketpy/prints/rocket_prints.py | 6 ++++-- 5 files changed, 9 insertions(+), 26 deletions(-) diff --git a/rocketpy/motors/hybrid_motor.py b/rocketpy/motors/hybrid_motor.py index c52d25612..1ef07859a 100644 --- a/rocketpy/motors/hybrid_motor.py +++ b/rocketpy/motors/hybrid_motor.py @@ -201,11 +201,7 @@ def __init__( .. seealso:: :doc:`Thrust Source Details ` dry_mass : int, float - The total mass of the motor structure, including chambers, - bulkheads, screws, tanks, and others. This should be taken when the - motor is empty and does not contain any propellant. You should not - double count a component that is already accounted for in the rocket - class. + Same as in Motor class. See the :class:`Motor ` docs dry_inertia : tuple, list Tuple or list containing the motor's dry mass inertia tensor components, in kg*m^2. This inertia is defined with respect to the diff --git a/rocketpy/motors/liquid_motor.py b/rocketpy/motors/liquid_motor.py index 91422132f..8fc3c4fce 100644 --- a/rocketpy/motors/liquid_motor.py +++ b/rocketpy/motors/liquid_motor.py @@ -173,11 +173,7 @@ def __init__( .. seealso:: :doc:`Thrust Source Details ` dry_mass : int, float - The total mass of the motor structure, including chambers, - bulkheads, screws, tanks, and others. This should be taken when the - motor is empty and does not contain any propellant. You should not - double count a component that is already accounted for in the rocket - class. + Same as in Motor class. See the :class:`Motor ` docs. dry_inertia : tuple, list Tuple or list containing the motor's dry mass inertia tensor components, in kg*m^2. This inertia is defined with respect to the diff --git a/rocketpy/motors/motor.py b/rocketpy/motors/motor.py index b951e8724..1a8d75f1c 100644 --- a/rocketpy/motors/motor.py +++ b/rocketpy/motors/motor.py @@ -182,11 +182,7 @@ def __init__( .. seealso:: :doc:`Thrust Source Details ` dry_mass : int, float - The total mass of the motor structure, including chambers, - bulkheads, screws, tanks, and others. This should be taken when the - motor is empty and does not contain any propellant. You should not - double count a component that is already accounted for in the rocket - class. + Same as in Motor class. See the :class:`Motor ` docs center_of_dry_mass_position : int, float The position, in meters, of the motor's center of mass with respect to the motor's coordinate system when it is devoid of propellant. @@ -1113,11 +1109,7 @@ def __init__( coordinate system. See :doc:`Positions and Coordinate Systems ` dry_mass : int, float - The total mass of the motor structure, including chambers, - bulkheads, screws, tanks, and others. This should be taken when the - motor is empty and does not contain any propellant. You should not - double count a component that is already accounted for in the rocket - class. + Same as in Motor class. See the :class:`Motor ` docs propellant_initial_mass : int, float The initial mass of the propellant in the motor. center_of_dry_mass_position : int, float, optional diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index 921dc3d7c..f809777b3 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -225,10 +225,7 @@ def __init__( nozzle_radius : int, float Motor's nozzle outlet radius in meters. dry_mass : int, float - The total mass of the motor structure, including chambers, - bulkheads, screws, and others. This should be taken when the motor - is empty and does not contain any propellant. You should not double - count a component that is already accounted for in the rocket class. + Same as in Motor class. See the :class:`Motor ` docs dry_inertia : tuple, list Tuple or list containing the motor's dry mass inertia tensor components, in kg*m^2. This inertia is defined with respect to the diff --git a/rocketpy/prints/rocket_prints.py b/rocketpy/prints/rocket_prints.py index 842252a3c..603e66a9a 100644 --- a/rocketpy/prints/rocket_prints.py +++ b/rocketpy/prints/rocket_prints.py @@ -30,9 +30,11 @@ def inertia_details(self): None """ print("\nInertia Details\n") - print("Rocket Mass: {self.rocket.mass:.3f} kg") + print(f"Rocket Mass: {self.rocket.mass:.3f} kg (without motor)") print(f"Rocket Dry Mass: {self.rocket.dry_mass:.3f} kg (with unloaded motor)") - print(f"Rocket Mass: {self.rocket.total_mass(0):.3f} kg (With Propellant)") + print( + f"Rocket Loaded Mass: {self.rocket.total_mass(0):.3f} kg (with loaded motor)" + ) print( f"Rocket Inertia (with unloaded motor) 11: {self.rocket.dry_I_11:.3f} kg*m2" )