Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2A collection of blocks useful for aerodynamics. 

3""" 

4import math 

5 

6import numpy as np 

7from modypy.model import Block, Port, signal_method 

8 

9 

10class Propeller(Block): 

11 """A block representing a propeller. 

12 

13 The block has two inputs: 

14 

15 ``speed_rps`` 

16 The speed of the propeller in revolutions per second 

17 ``density`` 

18 The density of the air 

19 

20 It provides three outputs: 

21 

22 ``thrust`` 

23 The total scalar thrust generated by the propeller 

24 ``torque`` 

25 The total torque required by the propeller 

26 ``power`` 

27 The total power required by the propeller 

28 

29 The magnitudes of thrust, torque and power are determined by the following 

30 formulae:: 

31 

32 F = ct(n)*rho*D^5*n^2 

33 tau = cp(n)/(2*pi)*rho*D^5*n^2 

34 P = cp(n)*rho*D^5*n^3 

35 

36 Here, 

37 - ``ct(n)`` is the thrust coefficient at speed ``n``, 

38 - ``cp(n)`` is the power coefficient at speed ``n``, and 

39 - ``D`` is the diameter. 

40 """ 

41 

42 def __init__(self, 

43 parent, 

44 thrust_coefficient, 

45 power_coefficient, 

46 diameter): 

47 Block.__init__(self, parent) 

48 if not callable(thrust_coefficient): 

49 thrust_coeff_value = thrust_coefficient 

50 thrust_coefficient = (lambda n: thrust_coeff_value) 

51 if not callable(power_coefficient): 

52 power_coeff_value = power_coefficient 

53 power_coefficient = (lambda n: power_coeff_value) 

54 

55 self.thrust_coefficient = thrust_coefficient 

56 self.power_coefficient = power_coefficient 

57 self.diameter = diameter 

58 

59 self.speed_rps = Port() 

60 self.density = Port() 

61 

62 @signal_method 

63 def thrust(self, data): 

64 """Function used to calculate the ``thrust`` output 

65 """ 

66 speed_rps = self.speed_rps(data) 

67 density = self.density(data) 

68 return self.thrust_coefficient(speed_rps) \ 

69 * density * self.diameter ** 4 * speed_rps ** 2 

70 

71 @signal_method 

72 def torque(self, data): 

73 """Function used to calculate the ``torque`` output 

74 """ 

75 speed_rps = self.speed_rps(data) 

76 density = self.density(data) 

77 return self.power_coefficient(speed_rps) / (2 * math.pi) * \ 

78 density * self.diameter ** 5 * speed_rps ** 2 

79 

80 @signal_method 

81 def power(self, data): 

82 """Function used to calculate the ``power`` output 

83 """ 

84 speed_rps = self.speed_rps(data) 

85 density = self.density(data) 

86 return self.power_coefficient(speed_rps) * \ 

87 density * self.diameter ** 5 * np.abs(speed_rps ** 3) 

88 

89 

90class Thruster(Block): 

91 """A block representing a thruster. 

92 

93 A thruster converts scalar thrust and torque to thrust and torque vectors. 

94 The thrust is considered to work in a (constant) thrust direction, 

95 determined by the thrust axis. 

96 

97 Torque is combined thrust along the thrust axis and torque due to the thrust 

98 working at the end of a (constant) arm relative to the center of gravity 

99 (CoG) of a rigid body. 

100 

101 The block has two inputs: 

102 - The scalar thrust in the direction of the thrust axis, and 

103 - the scalar torque along the thrust axis. 

104 

105 The block has six outputs: 

106 - The thrust vector (3 components), and 

107 - the torque vector (3 components). 

108 

109 It is configured by 

110 - the thrust axis (vector X,Y,Z), 

111 - the thrust arm (vector X,Y,Z), and 

112 - the turning direction (scalar: +1 or -1). 

113 

114 The right-hand rule applied to the thrust axis gives the positive direction 

115 of the thruster. Torque acts in the *opposite* direction, i.e. if the 

116 thruster turns clockwise, torque acts counter-clockwise. 

117 """ 

118 

119 def __init__(self, 

120 parent, 

121 vector, 

122 arm, 

123 direction=1): 

124 Block.__init__(self, parent) 

125 self.vector = vector 

126 self.arm = arm 

127 self.direction = direction 

128 

129 self.scalar_thrust = Port() 

130 self.scalar_torque = Port() 

131 

132 @signal_method(shape=3) 

133 def thrust_vector(self, data): 

134 """Function used to calculate the ``thrust_vector`` output 

135 """ 

136 thrust = self.scalar_thrust(data) 

137 thrust_vector = self.vector * thrust 

138 return thrust_vector 

139 

140 @signal_method(shape=3) 

141 def torque_vector(self, data): 

142 """Function used to calculate the ``torque_vector`` output 

143 """ 

144 thrust = self.scalar_thrust(data) 

145 torque = self.scalar_torque(data) 

146 

147 thrust_vector = self.vector * thrust 

148 torque_vector = self.direction * self.vector * torque + \ 

149 np.cross(self.arm, thrust_vector) 

150 

151 return torque_vector