-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tools: added Carbonix Param Auto Check python script
This script will check the parameter validation to Arduplane for below files. libraries/AP_HAL_ChibiOS/hwdef/CubeOrange-Ottano/defaults.parm', 'libraries/AP_HAL_ChibiOS/hwdef/CubeOrange-Volanti/defaults.parm', 'libraries/AP_HAL_ChibiOS/hwdef/CarbonixCommon/defaults.parm'] SW-159
- Loading branch information
Showing
1 changed file
with
195 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
import os | ||
import xml.etree.ElementTree as ET | ||
|
||
# Load the XML file | ||
tree = ET.parse('Tools/autotest/param_metadata/apm.pdef.xml') | ||
root = tree.getroot() | ||
|
||
# Define the paths to the file to compare | ||
text_file_paths = ['libraries/AP_HAL_ChibiOS/hwdef/CubeOrange-Ottano/defaults.parm', | ||
'libraries/AP_HAL_ChibiOS/hwdef/CubeOrange-Volanti/defaults.parm', | ||
'libraries/AP_HAL_ChibiOS/hwdef/CarbonixCommon/defaults.parm'] | ||
|
||
# Define default path | ||
text_default_file_path = () | ||
|
||
return_status = 0 | ||
|
||
# Create a dictionary to store parameter names, | ||
# ranges, values, and other properties | ||
param_dict = {} | ||
|
||
# Iterate through the XML tree and populate | ||
# the dictionary for parameters with ranges | ||
# or bitmask values | ||
for param_elem in root.iter('param'): | ||
param_name_with_prefix = param_elem.get('name') | ||
param_name = param_name_with_prefix.replace( | ||
'ArduPlane:', '') # Remove "ArduPlane:" prefix | ||
|
||
# if there is any field name Readonly whose value is true, skip it | ||
readonly_elem = param_elem.find(".//field[@name='ReadOnly']") | ||
if readonly_elem is not None: | ||
readonly_value = readonly_elem.text | ||
if readonly_value == 'True': | ||
param_dict[param_name] = {'type': 'ReadOnly', 'values': 'True'} | ||
continue | ||
|
||
# If 'values' element does not exist, | ||
# look for 'field' element with | ||
# name="Range" | ||
range_elem = param_elem.find(".//field[@name='Range']") | ||
if range_elem is not None: | ||
range_values = range_elem.text.split() | ||
if len(range_values) == 2: | ||
try: | ||
range_values = [float(val) for val in range_values] | ||
param_dict[param_name] = { | ||
'type': 'Range', 'values': range_values} | ||
except ValueError: | ||
param_dict[param_name] = None | ||
else: | ||
param_dict[param_name] = None | ||
else: | ||
param_range = param_elem.find('values') | ||
|
||
# If 'values' element exists, it's | ||
# a parameter with values | ||
if param_range is not None: | ||
param_values = { | ||
value.get('code'): value.text | ||
for value in param_range.findall('value') | ||
} | ||
# Check if values can be converted | ||
# to int or float | ||
parsed_values = [] | ||
for code, val in param_values.items(): | ||
try: | ||
parsed_val = int(code) | ||
except ValueError: | ||
try: | ||
parsed_val = float(code) | ||
except ValueError: | ||
parsed_val = None | ||
parsed_values.append(parsed_val) | ||
try: | ||
parsed_val = int(val) | ||
except ValueError: | ||
try: | ||
parsed_val = float(val) | ||
except ValueError: | ||
parsed_val = None | ||
|
||
parsed_values.append(parsed_val) | ||
parsed_values = list( | ||
filter(lambda item: item is not None, parsed_values)) | ||
param_dict[param_name] = { | ||
'type': 'values', 'values': str(parsed_values)} | ||
else: | ||
# Look for 'field' element with the | ||
# specified name attribute "Bitmask" | ||
field_elem = param_elem.find(".//field[@name='Bitmask']") | ||
if field_elem is not None: | ||
field_values = field_elem.text.split(',') | ||
field_values = [value.strip().split(':')[0] | ||
for value in field_values] | ||
param_dict[param_name] = { | ||
'type': 'Bitmask', 'values': field_values} | ||
else: | ||
param_dict[param_name] = {'type': 'Int', 'values': None} | ||
|
||
# Initialize an empty dictionary to store the data | ||
para_default_dict = {} | ||
|
||
if text_default_file_path and os.path.exists(text_default_file_path): | ||
para_default_dict = dict( | ||
line.strip().replace('@READONLY', '').split(' ', 1) | ||
for line in open(text_default_file_path) | ||
if line.strip() and not line.strip().startswith('#') | ||
) | ||
else: | ||
print(f"Text file '{text_default_file_path}' does not exist.") | ||
|
||
for text_file_path in text_file_paths: | ||
# Check if the text file exists | ||
if not text_file_path or not os.path.exists(text_file_path): | ||
print(f"Text file '{text_file_path}' does not exist.") | ||
else: | ||
# Load the text file and check parameter names and values | ||
print(f"Checking parameters in '{text_file_path}'...") | ||
with open(text_file_path, 'r') as file: | ||
for line in file: | ||
if line.strip() == '' or line.strip().startswith('#') or line.strip().startswith('@'): | ||
continue | ||
temp_line = line.strip().split('#', 1)[0] | ||
param_name, param_value = temp_line.strip().split(',') | ||
if param_name in param_dict: | ||
param_info = param_dict[param_name] | ||
if param_info is not None: | ||
param_type = param_info['type'] | ||
param_values = param_info['values'] | ||
if param_type == 'ReadOnly': | ||
print( | ||
f"Parameter '{param_name}' is read-only " | ||
f"shouldn't be in the param file." | ||
) | ||
return_status = 1 | ||
# Check if the parameter value is different from default | ||
if ( | ||
param_name in para_default_dict | ||
and str(param_value).replace(" ", "") | ||
!= str(para_default_dict[param_name]).replace(" ", "") | ||
): | ||
print( | ||
f"Parameter '{param_name}' has a " | ||
f"different value from default: {param_value} " | ||
f": {para_default_dict[param_name]}" | ||
) | ||
return_status = 1 | ||
elif param_type == 'ReadOnly': | ||
print( | ||
f"Parameter '{param_name}' is read-only " | ||
f"shouldn't be in the param file." | ||
) | ||
return_status = 1 | ||
elif param_type == 'values': | ||
# Check if the parameter value is in the list of values | ||
if param_value not in param_values: | ||
print( | ||
f"Parameter '{param_name}' " | ||
f"has an invalid value: {param_value} " | ||
f": {param_values}" | ||
) | ||
return_status = 1 | ||
elif param_type == 'range': | ||
# Check if the parameter value is in the range | ||
if ( | ||
float(param_value) < param_values[0] | ||
or float(param_value) > param_values[1] | ||
): | ||
print( | ||
f"Parameter '{param_name}' has an " | ||
f"out-of-range value: {param_value}" | ||
) | ||
return_status = 1 | ||
elif param_type == 'bitmask': | ||
# Check if the parameter value is in the list of values | ||
if param_value not in param_values: | ||
print( | ||
f"Parameter '{param_name}' has an " | ||
f"invalid value: {param_value}" | ||
) | ||
return_status = 1 | ||
else: | ||
print( | ||
f"Parameter '{param_name}' has no " | ||
f"defined range or values in the XML." | ||
) | ||
return_status = 1 | ||
else: | ||
print(f"Parameter '{param_name}' does not exist in the XML.") | ||
return_status = 1 | ||
print(f'Finished checking parameters in {text_file_path}.') | ||
|
||
if return_status == 1: | ||
exit(return_status) |