mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-27 10:17:45 +08:00
Mixers: raise exception when geom file is incomplete
pylint format
This commit is contained in:
committed by
Beat Küng
parent
cb8d951a7e
commit
d46c37be79
@@ -13,7 +13,7 @@ Cm = 0.05
|
|||||||
|
|
||||||
[[rotors]]
|
[[rotors]]
|
||||||
name = "front_right"
|
name = "front_right"
|
||||||
position = [0.707107, 0.707107, 0.0]
|
position = [0.707107, 0.707107]#, 0.0]
|
||||||
direction = "CCW"
|
direction = "CCW"
|
||||||
|
|
||||||
[[rotors]]
|
[[rotors]]
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ def parse_geom_toml(filename):
|
|||||||
Parses toml geometry file and returns a dictionary with curated list of rotors
|
Parses toml geometry file and returns a dictionary with curated list of rotors
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import toml
|
|
||||||
|
|
||||||
# Load toml file
|
# Load toml file
|
||||||
d = toml.load(filename)
|
d = toml.load(filename)
|
||||||
|
|
||||||
@@ -79,6 +77,16 @@ def parse_geom_toml(filename):
|
|||||||
else:
|
else:
|
||||||
default = {}
|
default = {}
|
||||||
|
|
||||||
|
# Check info section
|
||||||
|
if 'info' not in d:
|
||||||
|
raise AttributeError('{}: Error, missing info section'.format(filename))
|
||||||
|
|
||||||
|
# Check info section
|
||||||
|
for field in ['name', 'key', 'description']:
|
||||||
|
if field not in d['info']:
|
||||||
|
raise AttributeError('{}: Error, unspecified info field "{}"'.format(filename, field))
|
||||||
|
|
||||||
|
|
||||||
# Convert rotors
|
# Convert rotors
|
||||||
rotor_list = []
|
rotor_list = []
|
||||||
if 'rotors' in d:
|
if 'rotors' in d:
|
||||||
@@ -89,20 +97,28 @@ def parse_geom_toml(filename):
|
|||||||
if field in default:
|
if field in default:
|
||||||
r[field] = default[field]
|
r[field] = default[field]
|
||||||
else:
|
else:
|
||||||
print(filename + ': Error, unspecified field ' + field + ' for rotor ' + r['name'])
|
raise AttributeError('{}: Error, unspecified field "{}" for rotor "{}"'
|
||||||
|
.format(filename, field, r['name']))
|
||||||
|
|
||||||
# Check fields
|
# Check direction field
|
||||||
r['direction'] = r['direction'].upper()
|
r['direction'] = r['direction'].upper()
|
||||||
if r['direction'] not in ['CW', 'CCW']:
|
if r['direction'] not in ['CW', 'CCW']:
|
||||||
print(filename + ': Error, invalid direction value "' + r['direction'] + '" for rotor ' + r['name'])
|
raise AttributeError('{}: Error, invalid direction value "{}" for rotor "{}"'
|
||||||
|
.format(filename, r['direction'], r['name']))
|
||||||
|
|
||||||
|
# Check vector3 fields
|
||||||
|
for field in ['position', 'axis']:
|
||||||
|
if len(r[field]) != 3:
|
||||||
|
raise AttributeError('{}: Error, field "{}" for rotor "{}"'
|
||||||
|
.format(filename, field, r['name']) +
|
||||||
|
' must be an array of length 3')
|
||||||
|
|
||||||
# Add rotor to list
|
# Add rotor to list
|
||||||
rotor_list.append(r)
|
rotor_list.append(r)
|
||||||
|
|
||||||
# Clean dictionary
|
# Clean dictionary
|
||||||
geom = {'info': d['info'],
|
geom = {'info': d['info'],
|
||||||
'rotors': rotor_list}
|
'rotors': rotor_list}
|
||||||
|
|
||||||
return geom
|
return geom
|
||||||
|
|
||||||
@@ -111,7 +127,7 @@ def torque_matrix(center, axis, dirs, Ct, Cm):
|
|||||||
Compute torque generated by rotors
|
Compute torque generated by rotors
|
||||||
'''
|
'''
|
||||||
# normalize rotor axis
|
# normalize rotor axis
|
||||||
ax = axis / np.linalg.norm(axis, axis=1)[:,np.newaxis]
|
ax = axis / np.linalg.norm(axis, axis=1)[:, np.newaxis]
|
||||||
torque = Ct * np.cross(center, ax) - Cm * ax * dirs
|
torque = Ct * np.cross(center, ax) - Cm * ax * dirs
|
||||||
return torque
|
return torque
|
||||||
|
|
||||||
@@ -124,7 +140,7 @@ def geom_to_torque_matrix(geom):
|
|||||||
Am = torque_matrix(center=np.array([rotor['position'] for rotor in geom['rotors']]),
|
Am = torque_matrix(center=np.array([rotor['position'] for rotor in geom['rotors']]),
|
||||||
axis=np.array([rotor['axis'] for rotor in geom['rotors']]),
|
axis=np.array([rotor['axis'] for rotor in geom['rotors']]),
|
||||||
dirs=np.array([[1.0 if rotor['direction'] == 'CCW' else -1.0]
|
dirs=np.array([[1.0 if rotor['direction'] == 'CCW' else -1.0]
|
||||||
for rotor in geom['rotors']]),
|
for rotor in geom['rotors']]),
|
||||||
Ct=np.array([[rotor['Ct']] for rotor in geom['rotors']]),
|
Ct=np.array([[rotor['Ct']] for rotor in geom['rotors']]),
|
||||||
Cm=np.array([[rotor['Cm']] for rotor in geom['rotors']])).T
|
Cm=np.array([[rotor['Cm']] for rotor in geom['rotors']])).T
|
||||||
return Am
|
return Am
|
||||||
@@ -134,7 +150,7 @@ def thrust_matrix(axis, Ct):
|
|||||||
Compute thrust generated by rotors
|
Compute thrust generated by rotors
|
||||||
'''
|
'''
|
||||||
# Normalize rotor axis
|
# Normalize rotor axis
|
||||||
ax = axis / np.linalg.norm(axis, axis=1)[:,np.newaxis]
|
ax = axis / np.linalg.norm(axis, axis=1)[:, np.newaxis]
|
||||||
thrust = Ct * ax
|
thrust = Ct * ax
|
||||||
return thrust
|
return thrust
|
||||||
|
|
||||||
@@ -175,8 +191,8 @@ def normalize_mix_px4(B):
|
|||||||
Normalize mix for PX4
|
Normalize mix for PX4
|
||||||
This is for compatibility only and should ideally not be used
|
This is for compatibility only and should ideally not be used
|
||||||
'''
|
'''
|
||||||
B_norm = np.linalg.norm(B,axis=0)
|
B_norm = np.linalg.norm(B, axis=0)
|
||||||
B_max = np.abs(B).max(axis=0)
|
B_max = np.abs(B).max(axis=0)
|
||||||
|
|
||||||
# Same scale on roll and pitch
|
# Same scale on roll and pitch
|
||||||
B_norm[0] = max(B_norm[0], B_norm[1]) / np.sqrt(B.shape[0] / 2.0)
|
B_norm[0] = max(B_norm[0], B_norm[1]) / np.sqrt(B.shape[0] / 2.0)
|
||||||
@@ -193,7 +209,7 @@ def normalize_mix_px4(B):
|
|||||||
B_norm[5] = B_max[5]
|
B_norm[5] = B_max[5]
|
||||||
|
|
||||||
# Normalize
|
# Normalize
|
||||||
B_norm[np.abs(B_norm)<1e-3] = 1
|
B_norm[np.abs(B_norm) < 1e-3] = 1
|
||||||
B_px = (B / B_norm)
|
B_px = (B / B_norm)
|
||||||
|
|
||||||
return B_px
|
return B_px
|
||||||
@@ -287,9 +303,9 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument('-o', dest='outputfile',
|
parser.add_argument('-o', dest='outputfile',
|
||||||
help='output header file')
|
help='output header file')
|
||||||
parser.add_argument('--normalize', help='Use normalized mixers (compatibility mode)',
|
parser.add_argument('--normalize', help='Use normalized mixers (compatibility mode)',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
parser.add_argument('--sixdof', help='Use 6dof mixers',
|
parser.add_argument('--sixdof', help='Use 6dof mixers',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Find toml files
|
# Find toml files
|
||||||
@@ -331,8 +347,8 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
# Generate header file
|
# Generate header file
|
||||||
header = generate_mixer_multirotor_header(geom_list,
|
header = generate_mixer_multirotor_header(geom_list,
|
||||||
use_normalized_mix=args.normalize,
|
use_normalized_mix=args.normalize,
|
||||||
use_6dof=args.sixdof)
|
use_6dof=args.sixdof)
|
||||||
# print(header)
|
# print(header)
|
||||||
|
|
||||||
# Write header file
|
# Write header file
|
||||||
|
|||||||
Reference in New Issue
Block a user