diff --git a/AntennaTracker/ReleaseNotes.txt b/AntennaTracker/ReleaseNotes.txt index 9c93be93dce76..7253aa75668e1 100644 --- a/AntennaTracker/ReleaseNotes.txt +++ b/AntennaTracker/ReleaseNotes.txt @@ -1,4 +1,40 @@ ArduPilot Antenna Tracker Release Notes: +------------------------------------------------------------------ +Release 4.7.0-beta4 30-Apr-2026 + +Changes from 4.7.0-beta3 + +1) Board specific changes + +- VUAV-TinyV7 board added (@viewpro-caijie, PR:32058) + +2) Driver changes + +- LSM6DSV16X IMU from ST is now supported (@zebulon-86, PR:32574) +- MMP581 driver handles data corruption better (@peterbarker, PR:32171) + +3) Library changes + +- AC_PID: NTF and NEF parameters metadata includes 0 as a valid value (@IamPete1, PR:32898) +- AC_WPNav: BendyRuler altitude bug fixed (@hunt0r, PR:32892) +- AP_Arming: E-stop value is taken into account (@IamPete1, PR:32705) +- AP_GPS: SBF driver improvement in Do Not Use values (@UAVcihang, PR:32642) +- AP_Math: S-Curve bugs fixed (@lthall, PR: 32730) +- RC_Channel: RCx_PROTOCOLS metadata updated with SITLUDP option (@peterbarker, PR:32778) + +4) Plane specific changes + +- AP_IOMCU: Throttle will not output on failsafe while disarmed (@IamPete1, PR:32912) + +5) Sub specific changes + +- Lights servo channels defaults fixed (@ES-Alexander, PR:32764) +- Remote leak detector MAVLink interface support added (@ES-Alexander, PR:32614) + +6) Rover specific changes + +- Power limiting UX improved (@stephendade, PR:32788) + ------------------------------------------------------------------ Release 4.7.0-beta3 10-Apr-2026 diff --git a/AntennaTracker/version.h b/AntennaTracker/version.h index a8caa9771f72e..79e557bc2c4ed 100644 --- a/AntennaTracker/version.h +++ b/AntennaTracker/version.h @@ -6,10 +6,10 @@ #include "ap_version.h" -#define THISFIRMWARE "AntennaTracker V4.7.0-beta3" +#define THISFIRMWARE "AntennaTracker V4.7.0-beta4" // the following line is parsed by the autotest scripts -#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+2 +#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+3 #define FW_MAJOR 4 #define FW_MINOR 7 diff --git a/ArduCopter/ReleaseNotes.txt b/ArduCopter/ReleaseNotes.txt index 720c0ec97885a..ee2fc69d36a07 100644 --- a/ArduCopter/ReleaseNotes.txt +++ b/ArduCopter/ReleaseNotes.txt @@ -1,4 +1,40 @@ ArduPilot Copter Release Notes: +------------------------------------------------------------------ +Release 4.7.0-beta4 30-Apr-2026 + +Changes from 4.7.0-beta3 + +1) Board specific changes + +- VUAV-TinyV7 board added (@viewpro-caijie, PR:32058) + +2) Driver changes + +- LSM6DSV16X IMU from ST is now supported (@zebulon-86, PR:32574) +- MMP581 driver handles data corruption better (@peterbarker, PR:32171) + +3) Library changes + +- AC_PID: NTF and NEF parameters metadata includes 0 as a valid value (@IamPete1, PR:32898) +- AC_WPNav: BendyRuler altitude bug fixed (@hunt0r, PR:32892) +- AP_Arming: E-stop value is taken into account (@IamPete1, PR:32705) +- AP_GPS: SBF driver improvement in Do Not Use values (@UAVcihang, PR:32642) +- AP_Math: S-Curve bugs fixed (@lthall, PR: 32730) +- RC_Channel: RCx_PROTOCOLS metadata updated with SITLUDP option (@peterbarker, PR:32778) + +4) Plane specific changes + +- AP_IOMCU: Throttle will not output on failsafe while disarmed (@IamPete1, PR:32912) + +5) Sub specific changes + +- Lights servo channels defaults fixed (@ES-Alexander, PR:32764) +- Remote leak detector MAVLink interface support added (@ES-Alexander, PR:32614) + +6) Rover specific changes + +- Power limiting UX improved (@stephendade, PR:32788) + ------------------------------------------------------------------ Release 4.7.0-beta3 10-Apr-2026 diff --git a/ArduCopter/version.h b/ArduCopter/version.h index b57711e9fa0e0..20047fa63a92b 100644 --- a/ArduCopter/version.h +++ b/ArduCopter/version.h @@ -6,10 +6,10 @@ #include "ap_version.h" -#define THISFIRMWARE "ArduCopter V4.7.0-beta3" +#define THISFIRMWARE "ArduCopter V4.7.0-beta4" // the following line is parsed by the autotest scripts -#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+2 +#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+3 #define FW_MAJOR 4 #define FW_MINOR 7 diff --git a/ArduPlane/ReleaseNotes.txt b/ArduPlane/ReleaseNotes.txt index 2c8657e2461ae..57f0f20e6079b 100644 --- a/ArduPlane/ReleaseNotes.txt +++ b/ArduPlane/ReleaseNotes.txt @@ -1,4 +1,40 @@ ArduPilot Plane Release Notes: +------------------------------------------------------------------ +Release 4.7.0-beta4 30-Apr-2026 + +Changes from 4.7.0-beta3 + +1) Board specific changes + +- VUAV-TinyV7 board added (@viewpro-caijie, PR:32058) + +2) Driver changes + +- LSM6DSV16X IMU from ST is now supported (@zebulon-86, PR:32574) +- MMP581 driver handles data corruption better (@peterbarker, PR:32171) + +3) Library changes + +- AC_PID: NTF and NEF parameters metadata includes 0 as a valid value (@IamPete1, PR:32898) +- AC_WPNav: BendyRuler altitude bug fixed (@hunt0r, PR:32892) +- AP_Arming: E-stop value is taken into account (@IamPete1, PR:32705) +- AP_GPS: SBF driver improvement in Do Not Use values (@UAVcihang, PR:32642) +- AP_Math: S-Curve bugs fixed (@lthall, PR: 32730) +- RC_Channel: RCx_PROTOCOLS metadata updated with SITLUDP option (@peterbarker, PR:32778) + +4) Plane specific changes + +- AP_IOMCU: Throttle will not output on failsafe while disarmed (@IamPete1, PR:32912) + +5) Sub specific changes + +- Lights servo channels defaults fixed (@ES-Alexander, PR:32764) +- Remote leak detector MAVLink interface support added (@ES-Alexander, PR:32614) + +6) Rover specific changes + +- Power limiting UX improved (@stephendade, PR:32788) + ------------------------------------------------------------------ Release 4.7.0-beta3 10-Apr-2026 diff --git a/ArduPlane/version.h b/ArduPlane/version.h index 39d716cf2b4a9..adb5a69305e2a 100644 --- a/ArduPlane/version.h +++ b/ArduPlane/version.h @@ -6,10 +6,10 @@ #include "ap_version.h" -#define THISFIRMWARE "ArduPlane V4.7.0-beta3" +#define THISFIRMWARE "ArduPlane V4.7.0-beta4" // the following line is parsed by the autotest scripts -#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+2 +#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+3 #define FW_MAJOR 4 #define FW_MINOR 7 diff --git a/ArduSub/GCS_MAVLink_Sub.cpp b/ArduSub/GCS_MAVLink_Sub.cpp index 7f747ad7a6bef..09d68cded1221 100644 --- a/ArduSub/GCS_MAVLink_Sub.cpp +++ b/ArduSub/GCS_MAVLink_Sub.cpp @@ -736,16 +736,14 @@ void GCS_MAVLINK_Sub::handle_message(const mavlink_message_t &msg) break; } - // This adds support for leak detectors in a separate enclosure - // connected to a mavlink enabled subsystem + // Remote leak sensor support (e.g. in a separate enclosure), via MAVLink status messages. case MAVLINK_MSG_ID_SYS_STATUS: { - uint32_t MAV_SENSOR_WATER = 0x20000000; mavlink_sys_status_t packet; mavlink_msg_sys_status_decode(&msg, &packet); if ((msg.sysid == gcs().sysid_this_mav()) && - (packet.onboard_control_sensors_enabled & MAV_SENSOR_WATER) && - !(packet.onboard_control_sensors_health & MAV_SENSOR_WATER) - ) { + (packet.onboard_control_sensors_present & MAV_SYS_STATUS_EXTENSION_USED) && + (packet.onboard_control_sensors_enabled_extended & MAV_SYS_STATUS_SENSOR_LEAK) && + !(packet.onboard_control_sensors_health_extended & MAV_SYS_STATUS_SENSOR_LEAK)) { sub.leak_detector.set_detect(); } break; diff --git a/ArduSub/Parameters.h b/ArduSub/Parameters.h index e37bda26fb09a..ec259666dfc2a 100644 --- a/ArduSub/Parameters.h +++ b/ArduSub/Parameters.h @@ -461,7 +461,7 @@ static const struct AP_Param::defaults_table_struct defaults_table[] = { #if AP_BARO_PROBE_EXT_PARAMETER_ENABLED { "BARO_PROBE_EXT", 768}, #endif - { "SERVO9_FUNCTION", 59}, // k_rcin9, lights 1 + { "SERVO9_FUNCTION", 181}, // k_lights1 { "SERVO10_FUNCTION", 7}, // k_mount_tilt #endif }; diff --git a/ArduSub/ReleaseNotes.txt b/ArduSub/ReleaseNotes.txt index e2b4688f514f1..4fd599da1a911 100644 --- a/ArduSub/ReleaseNotes.txt +++ b/ArduSub/ReleaseNotes.txt @@ -1,4 +1,40 @@ ArduPilot Sub Release Notes: +------------------------------------------------------------------ +Release 4.7.0-beta4 30-Apr-2026 + +Changes from 4.7.0-beta3 + +1) Board specific changes + +- VUAV-TinyV7 board added (@viewpro-caijie, PR:32058) + +2) Driver changes + +- LSM6DSV16X IMU from ST is now supported (@zebulon-86, PR:32574) +- MMP581 driver handles data corruption better (@peterbarker, PR:32171) + +3) Library changes + +- AC_PID: NTF and NEF parameters metadata includes 0 as a valid value (@IamPete1, PR:32898) +- AC_WPNav: BendyRuler altitude bug fixed (@hunt0r, PR:32892) +- AP_Arming: E-stop value is taken into account (@IamPete1, PR:32705) +- AP_GPS: SBF driver improvement in Do Not Use values (@UAVcihang, PR:32642) +- AP_Math: S-Curve bugs fixed (@lthall, PR: 32730) +- RC_Channel: RCx_PROTOCOLS metadata updated with SITLUDP option (@peterbarker, PR:32778) + +4) Plane specific changes + +- AP_IOMCU: Throttle will not output on failsafe while disarmed (@IamPete1, PR:32912) + +5) Sub specific changes + +- Lights servo channels defaults fixed (@ES-Alexander, PR:32764) +- Remote leak detector MAVLink interface support added (@ES-Alexander, PR:32614) + +6) Rover specific changes + +- Power limiting UX improved (@stephendade, PR:32788) + ------------------------------------------------------------------ Release 4.7.0-beta3 10-Apr-2026 diff --git a/ArduSub/version.h b/ArduSub/version.h index fed32e416307a..20d80c1000879 100644 --- a/ArduSub/version.h +++ b/ArduSub/version.h @@ -6,10 +6,10 @@ #include "ap_version.h" -#define THISFIRMWARE "ArduSub V4.7.0-beta3" +#define THISFIRMWARE "ArduSub V4.7.0-beta4" // the following line is parsed by the autotest scripts -#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+2 +#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+3 #define FW_MAJOR 4 #define FW_MINOR 7 diff --git a/Rover/ReleaseNotes.txt b/Rover/ReleaseNotes.txt index 2abc17e68b0d8..d9dd29174715b 100644 --- a/Rover/ReleaseNotes.txt +++ b/Rover/ReleaseNotes.txt @@ -1,4 +1,40 @@ ArduPilot Rover Release Notes: +------------------------------------------------------------------ +Release 4.7.0-beta4 30-Apr-2026 + +Changes from 4.7.0-beta3 + +1) Board specific changes + +- VUAV-TinyV7 board added (@viewpro-caijie, PR:32058) + +2) Driver changes + +- LSM6DSV16X IMU from ST is now supported (@zebulon-86, PR:32574) +- MMP581 driver handles data corruption better (@peterbarker, PR:32171) + +3) Library changes + +- AC_PID: NTF and NEF parameters metadata includes 0 as a valid value (@IamPete1, PR:32898) +- AC_WPNav: BendyRuler altitude bug fixed (@hunt0r, PR:32892) +- AP_Arming: E-stop value is taken into account (@IamPete1, PR:32705) +- AP_GPS: SBF driver improvement in Do Not Use values (@UAVcihang, PR:32642) +- AP_Math: S-Curve bugs fixed (@lthall, PR: 32730) +- RC_Channel: RCx_PROTOCOLS metadata updated with SITLUDP option (@peterbarker, PR:32778) + +4) Plane specific changes + +- AP_IOMCU: Throttle will not output on failsafe while disarmed (@IamPete1, PR:32912) + +5) Sub specific changes + +- Lights servo channels defaults fixed (@ES-Alexander, PR:32764) +- Remote leak detector MAVLink interface support added (@ES-Alexander, PR:32614) + +6) Rover specific changes + +- Power limiting UX improved (@stephendade, PR:32788) + ------------------------------------------------------------------ Release 4.7.0-beta3 10-Apr-2026 diff --git a/Rover/version.h b/Rover/version.h index 558a92999d3e0..e8366c725fcda 100644 --- a/Rover/version.h +++ b/Rover/version.h @@ -6,10 +6,10 @@ #include "ap_version.h" -#define THISFIRMWARE "ArduRover V4.7.0-beta3" +#define THISFIRMWARE "ArduRover V4.7.0-beta4" // the following line is parsed by the autotest scripts -#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+2 +#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+3 #define FW_MAJOR 4 #define FW_MINOR 7 diff --git a/Tools/AP_Bootloader/board_types.txt b/Tools/AP_Bootloader/board_types.txt index a4a15d7d71e87..8ed341b213176 100644 --- a/Tools/AP_Bootloader/board_types.txt +++ b/Tools/AP_Bootloader/board_types.txt @@ -571,6 +571,7 @@ AP_HW_CUAV-X25-EVO 7002 # IDs 7100-7109 reserved for V-UAV AP_HW_VUAV-V7pro 7100 +AP_HW_VUAV-TinyV7 7101 # IDs 7110-7119 reserved for AEROFOX AP_HW_AEROFOX_H7 7110 diff --git a/Tools/AP_Periph/ReleaseNotes.txt b/Tools/AP_Periph/ReleaseNotes.txt index c74ee3ade8eec..f194276a71b92 100644 --- a/Tools/AP_Periph/ReleaseNotes.txt +++ b/Tools/AP_Periph/ReleaseNotes.txt @@ -1,4 +1,40 @@ ArduPilot AP_Periph Release Notes +------------------------------------------------------------------ +Release 4.7.0-beta4 30-Apr-2026 + +Changes from 4.7.0-beta3 + +1) Board specific changes + +- VUAV-TinyV7 board added (@viewpro-caijie, PR:32058) + +2) Driver changes + +- LSM6DSV16X IMU from ST is now supported (@zebulon-86, PR:32574) +- MMP581 driver handles data corruption better (@peterbarker, PR:32171) + +3) Library changes + +- AC_PID: NTF and NEF parameters metadata includes 0 as a valid value (@IamPete1, PR:32898) +- AC_WPNav: BendyRuler altitude bug fixed (@hunt0r, PR:32892) +- AP_Arming: E-stop value is taken into account (@IamPete1, PR:32705) +- AP_GPS: SBF driver improvement in Do Not Use values (@UAVcihang, PR:32642) +- AP_Math: S-Curve bugs fixed (@lthall, PR: 32730) +- RC_Channel: RCx_PROTOCOLS metadata updated with SITLUDP option (@peterbarker, PR:32778) + +4) Plane specific changes + +- AP_IOMCU: Throttle will not output on failsafe while disarmed (@IamPete1, PR:32912) + +5) Sub specific changes + +- Lights servo channels defaults fixed (@ES-Alexander, PR:32764) +- Remote leak detector MAVLink interface support added (@ES-Alexander, PR:32614) + +6) Rover specific changes + +- Power limiting UX improved (@stephendade, PR:32788) + ------------------------------------------------------------------ Release 4.7.0-beta3 10-Apr-2026 diff --git a/Tools/AP_Periph/version.h b/Tools/AP_Periph/version.h index 515703b143336..3d12c6026b59d 100644 --- a/Tools/AP_Periph/version.h +++ b/Tools/AP_Periph/version.h @@ -7,7 +7,7 @@ #include "ap_version.h" #include -#define THISFIRMWARE "AP_Periph 4.7.0-beta3" +#define THISFIRMWARE "AP_Periph 4.7.0-beta4" // defines needed due to lack of GCS includes #ifndef HAVE_ENUM_FIRMWARE_VERSION_TYPE @@ -17,7 +17,7 @@ #endif // the following line is parsed by the autotest scripts -#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+2 +#define FIRMWARE_VERSION 4,7,0,FIRMWARE_VERSION_TYPE_BETA+3 #define FW_MAJOR 4 #define FW_MINOR 7 diff --git a/Tools/IO_Firmware/iofirmware_cube_dshot_highpolh.bin b/Tools/IO_Firmware/iofirmware_cube_dshot_highpolh.bin index d9cad7f0ca76b..a99f648741897 100755 Binary files a/Tools/IO_Firmware/iofirmware_cube_dshot_highpolh.bin and b/Tools/IO_Firmware/iofirmware_cube_dshot_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_cube_dshot_lowpolh.bin b/Tools/IO_Firmware/iofirmware_cube_dshot_lowpolh.bin index 2e181269c0e30..6b6553d64e1c1 100755 Binary files a/Tools/IO_Firmware/iofirmware_cube_dshot_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_cube_dshot_lowpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_cube_highpolh.bin b/Tools/IO_Firmware/iofirmware_cube_highpolh.bin index f23e2095b7629..b44bbbbc8e3b0 100755 Binary files a/Tools/IO_Firmware/iofirmware_cube_highpolh.bin and b/Tools/IO_Firmware/iofirmware_cube_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_cube_lowpolh.bin b/Tools/IO_Firmware/iofirmware_cube_lowpolh.bin index 82aabcbe57288..ffb8795a8a3df 100755 Binary files a/Tools/IO_Firmware/iofirmware_cube_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_cube_lowpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_cubered.bin b/Tools/IO_Firmware/iofirmware_cubered.bin index a1419000c1693..6960fb17a01ad 100755 Binary files a/Tools/IO_Firmware/iofirmware_cubered.bin and b/Tools/IO_Firmware/iofirmware_cubered.bin differ diff --git a/Tools/IO_Firmware/iofirmware_dshot_highpolh.bin b/Tools/IO_Firmware/iofirmware_dshot_highpolh.bin index 65c8298b29da3..8de7632ee3361 100755 Binary files a/Tools/IO_Firmware/iofirmware_dshot_highpolh.bin and b/Tools/IO_Firmware/iofirmware_dshot_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_dshot_lowpolh.bin b/Tools/IO_Firmware/iofirmware_dshot_lowpolh.bin index c52a18b84b63b..429490d225f0a 100755 Binary files a/Tools/IO_Firmware/iofirmware_dshot_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_dshot_lowpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_highpolh.bin b/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_highpolh.bin index 40cd87a955ba2..ed341856dfa97 100644 Binary files a/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_highpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_lowpolh.bin b/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_lowpolh.bin index be59d5439a7c8..d4fe6750e7b61 100644 Binary files a/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_8MHz_dshot_lowpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_8MHz_highpolh.bin b/Tools/IO_Firmware/iofirmware_f103_8MHz_highpolh.bin index c0be42428df23..2f8bab6e6f54d 100755 Binary files a/Tools/IO_Firmware/iofirmware_f103_8MHz_highpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_8MHz_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_8MHz_lowpolh.bin b/Tools/IO_Firmware/iofirmware_f103_8MHz_lowpolh.bin index f401975944518..0909a0597a4ed 100755 Binary files a/Tools/IO_Firmware/iofirmware_f103_8MHz_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_8MHz_lowpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_dshot_highpolh.bin b/Tools/IO_Firmware/iofirmware_f103_dshot_highpolh.bin index de8758ba4a1aa..3d38f587f6549 100755 Binary files a/Tools/IO_Firmware/iofirmware_f103_dshot_highpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_dshot_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_dshot_lowpolh.bin b/Tools/IO_Firmware/iofirmware_f103_dshot_lowpolh.bin index 0a4d24564454a..42aa706befb39 100755 Binary files a/Tools/IO_Firmware/iofirmware_f103_dshot_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_dshot_lowpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_highpolh.bin b/Tools/IO_Firmware/iofirmware_f103_highpolh.bin index b05367f7ac12f..6fdd28296ce1b 100755 Binary files a/Tools/IO_Firmware/iofirmware_f103_highpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_f103_lowpolh.bin b/Tools/IO_Firmware/iofirmware_f103_lowpolh.bin index 25bfa7c11a95a..227b5af40ac13 100755 Binary files a/Tools/IO_Firmware/iofirmware_f103_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_f103_lowpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_highpolh.bin b/Tools/IO_Firmware/iofirmware_highpolh.bin index 1e153bef3d121..1cd928c49d17f 100755 Binary files a/Tools/IO_Firmware/iofirmware_highpolh.bin and b/Tools/IO_Firmware/iofirmware_highpolh.bin differ diff --git a/Tools/IO_Firmware/iofirmware_lowpolh.bin b/Tools/IO_Firmware/iofirmware_lowpolh.bin index dabf7c39dc114..190adf98a9488 100755 Binary files a/Tools/IO_Firmware/iofirmware_lowpolh.bin and b/Tools/IO_Firmware/iofirmware_lowpolh.bin differ diff --git a/Tools/autotest/helicopter.py b/Tools/autotest/helicopter.py index 683790ff12422..3d05e315376fd 100644 --- a/Tools/autotest/helicopter.py +++ b/Tools/autotest/helicopter.py @@ -39,6 +39,12 @@ def default_speedup(self): def is_heli(self): return True + def subgroupvarptr_activation_params(self): + ret = super(AutoTestHelicopter, self).subgroupvarptr_activation_params() + # AC_CustomControl is disabled on heli (AC_CUSTOMCONTROL_MULTI_ENABLED is false) + ret.pop("CC_TYPE", None) + return ret + def rc_defaults(self): ret = super(AutoTestHelicopter, self).rc_defaults() ret[8] = 1000 diff --git a/Tools/autotest/vehicle_test_suite.py b/Tools/autotest/vehicle_test_suite.py index 8c4b08eb7fe4f..df933e2d58c11 100644 --- a/Tools/autotest/vehicle_test_suite.py +++ b/Tools/autotest/vehicle_test_suite.py @@ -2597,6 +2597,23 @@ def test_adsb_send_threatening_adsb_message(self, here, offset_ne=None): 17 # squawk ) + def subgroupvarptr_activation_params(self): + '''Return parameters to set (before restarting SITL) to activate + AP_SUBGROUPVARPTR backends, making their parameters visible in the + parameter download. Only entries whose key appears in the htree will + be applied. Subclasses may call super() and pop entries that are not + compiled in for their vehicle type.''' + return { + "CAM1_TYPE": 8, # AP_Camera: RunCam backend + "PRX1_TYPE": 10, # AP_Proximity: SITL backend + "RNGFND1_TYPE": 100, # AP_RangeFinder: SIM backend + "BATT2_MONITOR": 4, # AP_BattMonitor: instance 1 (Analog V+I) + "FILT1_TYPE": 1, # AP_Filter: NotchFilter backend + "TEMP1_TYPE": 8, # AP_TemperatureSensor: SHT3X (simulated in SITL) + "GEN_TYPE": 1, # AP_Generator: IE_650_800 backend + "CC_TYPE": 2, # AC_CustomControl: PID backend (ArduCopter) + } + def test_parameter_documentation_get_all_parameters(self): xml_filepath = os.path.join(self.buildlogs_dirpath(), "apm.pdef.xml") @@ -2620,6 +2637,14 @@ def test_parameter_documentation_get_all_parameters(self): target_system = self.sysid_thismav() target_component = 1 + # Activate AP_SUBGROUPVARPTR backends whose type params appear in the + # documented parameter set, so their params are visible in the download. + # customise_SITL_commandline() below restarts SITL without wiping + # EEPROM, so these settings persist into the restarted instance. + for name, value in self.subgroupvarptr_activation_params().items(): + if name in htree: + self.set_parameter(name, value) + self.customise_SITL_commandline([ "--unhide-groups" ]) @@ -12808,10 +12833,48 @@ def test_parameters_mis_total(self): raise NotAchievedException("MAVProxy failed to get parameter") self.stop_mavproxy(mavproxy) + def test_subgroupvarptr_annotated(self): + '''Check that every AP_SUBGROUPVARPTR entry in the source tree has + @Group: and @Path: annotations immediately preceding it. Without + these annotations param_parse.py cannot discover the backend + parameters, so documentation mismatches would never be caught.''' + failures = [] + skip_dirs = {'modules', 'build', '.git', 'docs'} + for dirpath, dirnames, filenames in os.walk(self.rootdir()): + dirnames[:] = [d for d in dirnames if d not in skip_dirs] + for filename in filenames: + if not filename.endswith('.cpp'): + continue + filepath = os.path.join(dirpath, filename) + lines = pathlib.Path(filepath).read_text().splitlines() + for i, line in enumerate(lines): + if not line.strip().startswith('AP_SUBGROUPVARPTR'): + continue + has_group = False + has_path = False + for j in range(i - 1, max(i - 5, -1), -1): + prev = lines[j].strip() + if not prev: + continue + if '@Group:' in prev: + has_group = True + elif '@Path:' in prev: + has_path = True + if not prev.startswith('//'): + break + if not (has_group and has_path): + failures.append("%s:%d" % (os.path.relpath(filepath, self.rootdir()), i + 1)) + for f in failures: + self.progress("AP_SUBGROUPVARPTR missing @Group:/@Path: at %s" % f) + if failures: + raise NotAchievedException("AP_SUBGROUPVARPTR entries missing @Group:/@Path: annotations") + def test_parameter_documentation(self): '''ensure parameter documentation is valid''' self.start_subsubtest("Check all parameters are documented") self.test_parameter_documentation_get_all_parameters() + self.start_subsubtest("Check AP_SUBGROUPVARPTR entries have documentation annotations") + self.test_subgroupvarptr_annotated() def Parameters(self): '''general small tests for parameter system''' diff --git a/Tools/bootloaders/VUAV-TinyV7_bl.bin b/Tools/bootloaders/VUAV-TinyV7_bl.bin new file mode 100755 index 0000000000000..e0665f2ed1d76 Binary files /dev/null and b/Tools/bootloaders/VUAV-TinyV7_bl.bin differ diff --git a/Tools/bootloaders/VUAV-TinyV7_bl.hex b/Tools/bootloaders/VUAV-TinyV7_bl.hex new file mode 100644 index 0000000000000..173aeee05bf56 --- /dev/null +++ b/Tools/bootloaders/VUAV-TinyV7_bl.hex @@ -0,0 +1,2382 @@ +:020000040800F2 +:1000000000060020E1020008E3020008E302000805 +:10001000E3020008E3020008E3020008E30200082C +:10002000E3020008E3020008E30200081170000880 +:10003000E3020008E3020008E3020008E30200080C +:10004000E3020008E3020008E3020008E3020008FC +:10005000E3020008E30200081D7F0008497F000852 +:10006000757F0008A17F0008CD7F000815460008B5 +:100070003D4600086946000895460008C14600084C +:10008000E946000815470008E3020008E3020008FB +:10009000E3020008E3020008E3020008F97F000819 +:1000A000E3020008E3020008E3020008E30200089C +:1000B000E3020008E3020008E3020008E30200088C +:1000C000E3020008E3020008E3020008E30200087C +:1000D000E3020008E3020008E3020008E30200086C +:1000E0005D800008E3020008E3020008E302000864 +:1000F000E3020008E3020008E302000841470008A9 +:10010000E3020008D1800008E5800008E30200084F +:10011000E3020008E3020008E3020008E30200082B +:100120006D47000895470008C1470008ED470008E3 +:1001300019480008E3020008E3020008E30200088F +:10014000E3020008E3020008E3020008E3020008FB +:10015000414800086D48000899480008E30200087B +:10016000E3020008E3020008E3020008E3020008DB +:10017000E3020008FD7B0008E3020008E302000838 +:10018000E3020008E3020008E3020008E3020008BB +:10019000E3020008E3020008E3020008E3020008AB +:1001A000E3020008E3020008E3020008E30200089B +:1001B000E3020008E3020008E3020008E30200088B +:1001C000E3020008E3020008E3020008E30200087B +:1001D000E3020008E97B0008E3020008E3020008EC +:1001E000E3020008E3020008E3020008E30200085B +:1001F000E3020008E3020008E3020008E30200084B +:10020000E3020008E3020008E3020008E30200083A +:10021000E3020008E3020008E3020008E30200082A +:10022000E3020008E3020008E3020008E30200081A +:10023000E3020008E3020008E3020008E30200080A +:10024000E3020008E3020008E3020008E3020008FA +:10025000E3020008E3020008E3020008E3020008EA +:10026000E3020008E3020008E3020008E3020008DA +:10027000E3020008E3020008E3020008E3020008CA +:10028000E3020008E3020008E3020008E3020008BA +:10029000E3020008E3020008E3020008E3020008AA +:1002A000E3020008E3020008E3020008E30200089A +:1002B000E3020008E3020008E3020008E30200088A +:1002C000E3020008E3020008E3020008E30200087A +:1002D000E3020008E3020008E3020008E30200086A +:1002E00002E000F000F8FEE772B6374880F30888B5 +:1002F000364880F3098836483649086040F20000E5 +:10030000CCF200004EF63471CEF200010860BFF36B +:100310004F8FBFF36F8F40F20000C0F2F0004EF637 +:100320008851CEF200010860BFF34F8FBFF36F8F8B +:100330004FF00000E1EE100A4EF63C71CEF20001E3 +:100340000860062080F31488BFF36F8F06F0C2FEAA +:1003500006F040F84FF055301F491B4A91423CBF10 +:1003600041F8040BFAE71D49184A91423CBF41F895 +:10037000040BFAE71A491B4A1B4B9A423EBF51F83D +:10038000040B42F8040BF8E700201849184A914280 +:100390003CBF41F8040BFAE706F0DAFE06F09EF8DF +:1003A000144C154DAC4203DA54F8041B8847F9E7A6 +:1003B00000F0C4F9114C124DAC4203DA54F8041B9E +:1003C0008847F9E706F0C2BE0006002000220020A0 +:1003D0000000000808ED00E00000002000060020FA +:1003E0005894000800220020642200206822002087 +:1003F00044590020E0020008E0020008E002000882 +:10040000E00200082DE9F04F2DED108AC1F80CD064 +:10041000D0F80CD0BDEC108ABDE8F08F002383F338 +:1004200011882846A047002005F0B6FDFEE705F03C +:1004300041FD00DFFEE7000053B94AB9002908BFBB +:1004400000281CBF4FF0FF314FF0FF3000F074B9AF +:10045000ADF1080C6DE904CE00F006F8DDF804E01B +:10046000DDE9022304B070472DE9F047089D0446FA +:100470008E46002B4DD18A42944669D9B2FA82F257 +:1004800052B101FA02F3C2F1200120FA01F10CFA93 +:1004900002FC41EA030E94404FEA1C48210CBEFBCB +:1004A000F8F61FFA8CF708FB16E341EA034306FB54 +:1004B00007F199420AD91CEB030306F1FF3080F0E3 +:1004C0001F81994240F21C81023E63445B1AA4B230 +:1004D000B3FBF8F008FB103344EA034400FB07F7D2 +:1004E000A7420AD91CEB040400F1FF3380F00A8113 +:1004F000A74240F207816444023840EA0640E41B08 +:1005000000261DB1D4400023C5E900433146BDE8B3 +:10051000F0878B4209D9002D00F0EF800026C5E955 +:10052000000130463146BDE8F087B3FA83F6002E6D +:100530004AD18B4202D3824200F2F980841A61EBE5 +:10054000030301209E46002DE0D0C5E9004EDDE703 +:1005500002B9FFDEB2FA82F2002A40F09280A1EBEB +:100560000C014FEA1C471FFA8CFE0126200CB1FB40 +:10057000F7F307FB131140EA01410EFB03F0884239 +:1005800008D91CEB010103F1FF3802D2884200F2C6 +:10059000CB804346091AA4B2B1FBF7F007FB101158 +:1005A00044EA01440EFB00FEA64508D91CEB0404F6 +:1005B00000F1FF3102D2A64500F2BB800846A4EB51 +:1005C0000E0440EA03409CE7C6F12007B34022FA3C +:1005D00007FC4CEA030C20FA07F401FA06F31C436B +:1005E000F9404FEA1C4900FA06F3B1FBF9F8200C78 +:1005F0001FFA8CFE09FB181140EA014108FB0EF0BE +:10060000884202FA06F20BD91CEB010108F1FF3A0D +:1006100080F08880884240F28580A8F10208614419 +:10062000091AA4B2B1FBF9F009FB101144EA014127 +:1006300000FB0EFE8E4508D91CEB010100F1FF34D2 +:100640006CD28E456AD90238614440EA0840A0FB6A +:100650000294A1EB0E01A142C846A64656D353D040 +:100660005DB1B3EB080261EB0E0101FA07F722FA64 +:1006700006F3F1401F43C5E9007100263146BDE88D +:10068000F087C2F12003D8400CFA02FC21FA03F3F0 +:10069000914001434FEA1C471FFA8CFEB3FBF7F071 +:1006A00007FB10360B0C43EA064300FB0EF69E4296 +:1006B00004FA02F408D91CEB030300F1FF382FD22F +:1006C0009E422DD9023863449B1B89B2B3FBF7F6D7 +:1006D00007FB163341EA034106FB0EF38B4208D9B0 +:1006E0001CEB010106F1FF3816D28B4214D9023EF1 +:1006F0006144C91A46EA004638E72E46284605E70F +:100700000646E3E61846F8E64B45A9D2B9EB0208DF +:1007100064EB0C0E0138A3E74646EAE7204694E76F +:100720004046D1E7D0467BE7023B614432E73046A2 +:1007300009E76444023842E7704700BF38B501F06A +:10074000E9F901F07DFB06F06DFB054606F056FC6D +:100750000446D0B90F4B9D4219D001339D4241F25E +:10076000883504BF01240025002006F065FB0CB18C +:1007700000F078F801F038FB00F026FD08B100F039 +:1007800071F8284600F01CF9F9E70025ECE705466A +:10079000EAE700BF010007B008B501F08DF9A0F14C +:1007A00020035842584108BD07B541F21203022107 +:1007B00001A8ADF8043001F09DF903B05DF804FB29 +:1007C00038B5302383F31188174803680BB105F05F +:1007D000C7FC0023154A4FF47A71134805F0B6FCA4 +:1007E000002383F31188124C236813B12368013B63 +:1007F0002360636813B16368013B63600D4D2B7820 +:1008000033B963687BB9022001F04EFA322363608A +:100810002B78032B07D163682BB9022001F044FA2F +:100820004FF47A73636038BD68220020C107000866 +:100830008823002080220020084B187003280CD841 +:10084000DFE800F008050208022001F01DBA0220CE +:1008500001F008BA024B00225A6070478022002043 +:1008600088230020F8B5504B504A1C4619680131C6 +:1008700000F0998004339342F8D162684C4B9A425D +:1008800040F291804B4B9B6803F1006303F500330A +:100890009A4280F08880002001F056F90220FFF78C +:1008A000CBFF454B0021D3F8E820C3F8E810D3F87C +:1008B0001021C3F81011D3F81021D3F8EC20C3F89D +:1008C000EC10D3F81421C3F81411D3F81421D3F881 +:1008D000F020C3F8F010D3F81821C3F81811D3F89A +:1008E0001821D3F8802042F00062C3F88020D3F8AA +:1008F000802022F00062C3F88020D3F88020D3F853 +:10090000802042F00072C3F88020D3F8802022F0CB +:100910000072C3F88020D3F8803072B64FF0E02325 +:10092000C3F8084DD4E90004BFF34F8FBFF36F8FB6 +:10093000224AC2F88410BFF34F8F536923F48033E7 +:100940005361BFF34F8FD2F8803043F6E076C3F3A4 +:10095000C905C3F34E335B0103EA060C29464CEA92 +:1009600081770139C2F87472F9D2203B13F1200F5C +:10097000F2D1BFF34F8FBFF36F8FBFF34F8FBFF332 +:100980006F8F536923F4003353610023C2F8503250 +:10099000BFF34F8FBFF36F8F302383F311888546EA +:1009A00080F308882047F8BD0000020820000208F4 +:1009B000FFFF0108002200200044025800ED00E083 +:1009C0002DE9F04F93B0B44B2022FF2100900AA8EC +:1009D0009D6801F0B3F9B14A1378A3B90121B04879 +:1009E00011700360302383F3118803680BB105F0A5 +:1009F000B7FB0023AB4A4FF47A71A94805F0A6FB78 +:100A0000002383F31188009B13B1A74B009A1A604F +:100A1000A64A1378032B03D000231370A24A536015 +:100A20004FF0000A009CD3465646D146012001F003 +:100A30002BF924B19C4B1B68002B00F02682002070 +:100A400001F03AF80390039B002BF2DB012001F048 +:100A500009F9039B213B1F2BE8D801A252F823F090 +:100A6000E10A0008090B00089D0B00082D0A000888 +:100A70002D0A00082D0A00082F0C0008FF0D0008A1 +:100A8000190D00087B0D0008A30D0008C90D000812 +:100A90002D0A0008DB0D00082D0A00084D0E000885 +:100AA000810B00082D0A0008910E0008ED0A0008CD +:100AB000810B00082D0A00087B0D00082D0A000894 +:100AC0002D0A00082D0A00082D0A00082D0A00082A +:100AD0002D0A00082D0A00082D0A00089D0B0008A9 +:100AE0000220FFF759FE002840F0F981009B022107 +:100AF00005A8BAF1000F08BF1C4641F21233ADF849 +:100B0000143000F0F7FF91E74FF47A7000F0D4FF53 +:100B1000071EEBDB0220FFF73FFE0028E6D0013F77 +:100B2000052F00F2DE81DFE807F0030A0D1013360F +:100B30000523042105A8059300F0DCFF17E004213C +:100B40005548F9E704215A48F6E704215948F3E7E4 +:100B50004FF01C08404608F1040800F0F7FF04219C +:100B6000059005A800F0C6FFB8F12C0FF2D10120C6 +:100B70004FF0000900FA07F747EA0B0B5FFA8BFB0F +:100B800001F028F926B10BF00B030B2B08BF002452 +:100B9000FFF70AFE4AE704214748CDE7002EA5D01B +:100BA0000BF00B030B2BA1D10220FFF7F5FD07463D +:100BB00000289BD00120002600F0C6FF0220FFF78E +:100BC0003BFE1FFA86F8404600F0CEFF0446B0B167 +:100BD000039940460136A1F140025142514100F0D3 +:100BE000D3FF0028EDD1BA46044641F21213022188 +:100BF00005A83E46ADF8143000F07CFF16E7254608 +:100C00000120FFF719FE244B9B68AB4207D9284609 +:100C100000F09CFF013040F067810435F3E70025C8 +:100C2000224BBA463E461D701F4B5D60A8E7002E62 +:100C30003FF45CAF0BF00B030B2B7FF457AF02209C +:100C4000FFF7FAFD322000F037FFB0F10008FFF6A1 +:100C50004DAF18F003077FF449AF0F4A08EB0503C7 +:100C6000926893423FF642AFB8F5807F3FF73EAFC0 +:100C7000124BB845019323DD4FF47A7000F01CFF4E +:100C80000390039A002AFFF631AF039A0137019BC4 +:100C900003F8012BEDE700BF002200208423002091 +:100CA00068220020C107000888230020802200203D +:100CB00004220020082200200C2200208422002090 +:100CC000C820FFF769FD074600283FF40FAF1F2D2E +:100CD00011D8C5F120020AAB25F003008449424532 +:100CE000184428BF4246019201F002F8019AFF2100 +:100CF0007F4801F023F84FEAA803C8F387027C4934 +:100D00002846019301F022F8064600283FF46DAF13 +:100D1000019B05EB830533E70220FFF73DFD00282B +:100D20003FF4E4AE00F04EFF00283FF4DFAE0027B2 +:100D3000B846704B9B68BB4218D91F2F11D80A9B2D +:100D400001330ED027F0030312AA134453F8203CBA +:100D500005934046042205A9043701F009F98046AD +:100D6000E7E7384600F0F2FE0590F2E7CDF8148090 +:100D7000042105A800F0BEFE02E70023642104A8B8 +:100D8000049300F0ADFE00287FF4B0AE0220FFF720 +:100D900003FD00283FF4AAAE049800F009FF059077 +:100DA000E6E70023642104A8049300F099FE0028DC +:100DB0007FF49CAE0220FFF7EFFC00283FF496AED4 +:100DC000049800F0F7FEEAE70220FFF7E5FC0028B0 +:100DD0003FF48CAE00F006FFE1E70220FFF7DCFCF9 +:100DE00000283FF483AE05A9142000F001FF074658 +:100DF0000421049004A800F07DFE3946B9E73220B2 +:100E000000F05AFE071EFFF671AEBB077FF46EAE10 +:100E1000384A07EB0903926893423FF667AE022017 +:100E2000FFF7BAFC00283FF461AE27F003074F44F8 +:100E3000B9453FF4A5AE484609F1040900F086FE25 +:100E40000421059005A800F055FEF1E74FF47A70F3 +:100E5000FFF7A2FC00283FF449AE00F0B3FE0028E3 +:100E600044D00A9B01330BD008220AA9002000F0CD +:100E70006DFF00283AD02022FF210AA800F05EFF73 +:100E8000FFF792FC1C4805F08DF813B0BDE8F08F19 +:100E9000002E3FF42BAE0BF00B030B2B7FF426AE92 +:100EA0000023642105A8059300F01AFE07460028D8 +:100EB0007FF41CAE0220FFF76FFC804600283FF451 +:100EC00015AEFFF771FC41F2883005F06BF805981C +:100ED00000F0B4FF46463C4600F07CFFA6E506461F +:100EE0004EE64FF0000901E6BA467EE637467CE65C +:100EF0008422002000220020A0860100704700000C +:100F000070470000704700002DE9F04100F5803780 +:100F1000044616463B7C5BB9C0681030204400F0A4 +:100F2000E7FEE5683544B5F5004FE56002D816B137 +:100F3000BDE8F081DEB905F07F0605F11000002163 +:100F4000C6F180062044F6B232462E4400F0F6FE8A +:100F5000A06804F11008324600F10060414600F537 +:100F6000003005F0FDFC30B901233B74E0E74FF49D +:100F700000463546ECE7A26805F1100140463244D0 +:100F80002144A260E268521BE26000F0B1FE022040 +:100F9000BDE8F04100F088BE183000F0E9BC000068 +:100FA00010B5044601F000F8204610BD10B5044607 +:100FB00000F0FAFF204610BDC0B2A0F14103052B9E +:100FC00002D83738C0B27047A0F16103052B94BF37 +:100FD00057383038F6E7000070B504461546084625 +:100FE00003220C4900F08EFE014688B908346E1CBD +:100FF00015F91100FFF7E0FF024616F91100013163 +:10100000FFF7DAFF102940EA021004F8010BEFD1D4 +:1010100070BD00BF808A00082DE9F04FADF53F7D1F +:101020000746416801222AA802F0A0FE002840F0ED +:1010300087800646824681461125DFF80C81DFF85D +:101040000CB101AB4FF4805241462AA802F0EEFFEA +:10105000002875D1019AB2F5805F71D8002A65D059 +:101060000446019A9442ECD2282D0FD008DC132DAF +:101070002DD01E2D39D0112D13D00134A4B2F0E79C +:10108000322D2DD0372D2FD02D2DF6D13B68121BB0 +:1010900008EB040138461B692D259847BDF804402C +:1010A000EBE7121B022A09D9594608EB040000F0AD +:1010B00029FE18B902342825A4B2DEE718F8043056 +:1010C0003A2B3DD00A2B1CBFA1461325D5E718F8B3 +:1010D00004300A2B34D03A2B04BFA2463225CCE789 +:1010E00018F80430202BC8D0264618F804300A2BF4 +:1010F0001AD1AAEB090208EB090102A811254F2A0F +:1011000028BF4F2207F0A8FCA21B08EB060116A877 +:101110004F2A28BF4F2207F09FFC3B6816AA02A95E +:10112000DB6838469847A8E71E25A6E73B6838469F +:1011300004491B69984701200DF53F7DBDE8F08FFC +:101140000020F9E7828B000890230020848A0008A1 +:1011500000F1180110B5044686B00846019100F070 +:10116000F1FB2046FFF758FF60B1019902A800F09B +:1011700049FC102204F1080102A807F02DFCB0FA86 +:1011800080F0400906B010BD70B504460025EEB2EF +:10119000304600F0E9FC58B100213046013500F03E +:1011A000F3FC08B9002070BD022000F07DFDEEE7E1 +:1011B0002046FFF731FF0028F4D004F58034207C6E +:1011C00080F00100EFE70000F0B5C9B005F042FE85 +:1011D00000F006FF18B90025284649B0F0BD694661 +:1011E0002A4802F0E5FF00284BD1294C204603F0A5 +:1011F0000FF8284803F00CF8274803F009F82146B7 +:10120000224803F081F80028E5D1702000F0C6FEE6 +:10121000064610B1214B44600360336830469B683A +:101220009847054600282ED01A4F1948394603F032 +:101230006BF805460028CED1194800F0AFFE0446F1 +:1012400038B1184B4760036000F58033C0E90255A0 +:101250001D74236820469B689847054628B10E49AF +:101260000C4803F051F80028B5D1336830465B686C +:1012700098471CB1236820465B68984700F098FEA9 +:10128000AAE70025FAE70446EFE700BF888A0008CE +:10129000988A0008AF8A0008C58A0008E88A000812 +:1012A00014000100048B00082DE9F04FD44A8DB0E2 +:1012B0000B68D0F804A001931A440368D14E1A4475 +:1012C000D1F81C90DFF8B4C3DFF8B4B3D0E902342E +:1012D000634003EA0A03634013444A6802920AEB3C +:1012E0007363029CC84A2244C468224484688AEA20 +:1012F00004051D40654015448A68039203EB35558B +:10130000039CC24A2244846822448AEA03042C4093 +:1013100084EA0A041444CA6805EBF43404921644BF +:1013200083EA0502224056445A4032440E6905962B +:1013300004EBB222059FB64E3E441E4485EA0403E8 +:1013400013406B4033444E69069602EB7363069F6D +:10135000B04E3E442E4484EA02051D4065403544AB +:101360008E69079603EB3555079FAB4E3E442644E6 +:1013700082EA03042C4054403444A84E4E4405EB0A +:10138000F434164483EA050222405A4032440E6A7D +:10139000089604EBB222089FA14E3E441E4485EA03 +:1013A000040313406B4033444E6A099602EB7363A7 +:1013B000099F9C4ED1F830E03E44D1F83880F34488 +:1013C0002E4484EA02051D40654035448E6AA6F528 +:1013D000244703EB35550A964F3F274482EA03041E +:1013E0002C4054403C44CF6A0B9705EBF4340B9EE1 +:1013F0008D4F3744029E174483EA050222405A402B +:101400003A448A4F774404EBB2221F4485EA04032E +:1014100013406B403B444F6BBC4402EB7363654429 +:1014200084EA020C0CEA030C8CEA040C6544DFF835 +:1014300054C2C44403EB3555A44482EA03042C404F +:1014400054406444D1F83CC0794905EBF43461441C +:10145000114483EA050222405A400A44754904EBCC +:10146000B2223144079E194484EA02032B406340B0 +:101470000B44714902EBF36331440B9E0D4482EA45 +:1014800003012140514029446C4D03EBF151354497 +:10149000019E254483EA010414405C402C44684DBD +:1014A00001EBB4443544069E154481EA04021A4017 +:1014B0004A402A44634D04EB323235440A9E1D44AF +:1014C00084EA02030B4063402B445F4D02EBF3635D +:1014D0003544059E0D4482EA0301214051402944D0 +:1014E0005A4D03EBF1516544254483EA010414404D +:1014F0005C402C44564D01EBB4443544099E1544E0 +:1015000081EA04021A404A402A44524D04EB323226 +:101510003544049E1D4484EA02030B4063402B447F +:101520004D4D02EBF36345440D4482EA0301214033 +:1015300051402944494D03EBF1513544089E2C4458 +:1015400083EA010515405D402C44454D01EBB44450 +:101550003544039E2A4481EA04051D404D402A4437 +:10156000404D04EB32323D442B4484EA020593445F +:101570000D4065402B443C4D02EBF3633544069E21 +:10158000294482EA0305254055402944374D03EBA1 +:10159000F1514D442C4483EA010515405D4025443A +:1015A00001EBB54581EA050404EA03024A405A44C6 +:1015B000A6F5B82B089E05EB3232ABF2BE6B544059 +:1015C0005B4423442A4C344402EB33730B9E0C449B +:1015D00085EA020159402144264C344403EB715101 +:1015E000029E254482EA03044C402544224C444494 +:1015F00001EB3545144483EA01026A40224443E08A +:1016000078A46AD7EECEBDC156B7C7E8DB702024F8 +:10161000AF0F7CF52AC68747134630A8019546FDD3 +:10162000D8988069AFF7448BBED75C892211906B44 +:101630002108B44962251EF640B340C0515A5E26C7 +:10164000AAC7B6E95D102FD65314440281E6A1D88B +:10165000C8FBD3E7E6CDE121D60737C3870DD5F424 +:10166000ED145A4505E9E3A9F8A3EFFCD9026F6729 +:1016700081F6718722619D6D0C38E5FD937198FDAF +:101680008A4C2A8D8E4379A6934C344405EB722202 +:10169000059E1C4481EA0503534023448F4C344487 +:1016A00002EB33730A9E0C4485EA0201594021443F +:1016B0008B4C4C4403EB7151254482EA03044C40AB +:1016C0002C44884D354401EB3444019E154483EA93 +:1016D000010262402A44844D3D4404EB72221D44C1 +:1016E00081EA040353402B44804D354402EB3373AD +:1016F000049E294484EA02055D4029447C4D35441A +:1017000003EB7151079E254482EA03044C402C44AC +:10171000784D354401EB3444099E2A4483EA01059F +:1017200065401544744A324404EB7525039E134406 +:1017300081EA04026A401A44704B734405EB32722A +:101740000B4484EA0501514019446D4B634402EB9C +:1017500071511C4485EA02034B401C44694B3344DD +:1017600001EB3444019E1D4482EA010363402B4493 +:10177000654D04EB73233544069E154463EA01026C +:1017800062402A44614D03EBB2624D4462EA0409AF +:1017900029445F4D89EA0309454449442C445D4D81 +:1017A00002EBB1513544049E61EA03081D4488EA06 +:1017B0000208444401EB744464EA02034B402B44A6 +:1017C000554D04EBF323754463EA010E15448EEA8C +:1017D000040E0EEB0502514D03EBB262354462EA92 +:1017E000040E29440A9D8EEA030EA5F580164C4D81 +:1017F0007144A6F6833602EBB151264461EA030434 +:1018000054403444029E01EB7444354464EA0206B9 +:101810001D444E407319089E424D04EBF32335449A +:1018200063EA01061544664072193F4D03EBB2624C +:10183000654462EA040629443C4D5E403144079EFB +:1018400002EBB151354461EA03062C44384D564051 +:101850003D443444059E1D4401EB744464EA020394 +:101860004B402B44334D04EBF32335440B9E15447E +:1018700063EA010262402A442F4D03EBB262354411 +:10188000039E0D4462EA0401594029442B4D02EBAA +:10189000B15135442A4E254461EA030454402C4496 +:1018A000099D01EB74442E4464EA02051E4485EA56 +:1018B00001039D1903681A440AEB040303EBF523A3 +:1018C0000260436083681C44C36819448460C1603B +:1018D0000DB0BDE8F08F00BF44EABEA4A9CFDE4B37 +:1018E000604BBBF670BCBFBEC67E9B28FA27A1EA40 +:1018F0008530EFD4051D880439D0D4D9E599DBE6CD +:10190000F87CA21F6556ACC4442229F497FF2A43F1 +:10191000A72394AB39A093FCC3595B6592CC0C8F81 +:10192000D15D84854F7EA86FE0E62CFE144301A3B1 +:10193000A111084E827E53F735F23ABDBBD2D72AA9 +:1019400091D386EB094B036003F18833436003F1C5 +:101950002943A3F59613A3F68B638360A3F1883321 +:10196000C3600023C0E90433704700BF012345670B +:101970002DE9F8431446026905460E46E300C2F31A +:10198000C50800F118079B18036122BF43690133A2 +:10199000436112F4FC7F436903EB5473436114D039 +:1019A000C8F1400907EB08004C4504D22246BDE8C7 +:1019B000F84307F021B8403C4A464E4407F01CF873 +:1019C000444439462846FFF76FFCA04606EB04095D +:1019D000B8F13F0FA9EB08010AD94022384607F0B9 +:1019E0000BF839462846A8F14008FFF75DFCEFE701 +:1019F000A1096FF03F02384602FB014206EB81115C +:101A0000D5E7000070B50B6901F1180506460C46D4 +:101A1000C3F3C503EA18501C8022EA54C3F13F0205 +:101A2000072A1FD8002100F089F929462046FFF730 +:101A30003BFC38220021284600F080F92369294622 +:101A40002046236563696365FFF72EFC214610225B +:101A5000304606F0D1FF204658220021BDE87040F4 +:101A600000F06CB9C3F137020021E5E70F4B70B508 +:101A70001B780C460133DBB2012B11D80C4D4FF40F +:101A80007A732968A2FB033222460E6A0146284671 +:101A9000B047844204D1074B002201201A7070BD68 +:101AA0004FF4FA7004F07EFA0020F8E710220020CC +:101AB000683B0020BC330020002307B5024601210B +:101AC0000DF107008DF80730FFF7D0FF20B19DF82A +:101AD000070003B05DF804FB4FF0FF30F9E70000AA +:101AE0000A46042108B5FFF7C1FF80F00100C0B22B +:101AF000404208BD30B4054C0A46014623682046E2 +:101B0000DD69034BAC4630BC604700BF683B00203A +:101B1000A086010070B50A4E00240A4D04F0C4FEF0 +:101B2000308028683388834208D904F0B9FE2B68D6 +:101B300004440133B4F5003F2B60F2D370BD00BF05 +:101B4000BE3300209033002004F088BF00F1006015 +:101B500000F500300068704700F10060920000F569 +:101B6000003004F0FDBE0000054B1A68054B1B88D1 +:101B70009B1A834202D9104404F092BE00207047A1 +:101B800090330020BE33002038B50446074D29B1FC +:101B900028682044BDE8384004F09ABE28682044F4 +:101BA00004F084FE0028F3D038BD00BF903300203D +:101BB0000020704700F1FF5000F58F10D0F80008AA +:101BC00070470000064991F8243033B10023082201 +:101BD000086A81F82430FFF7BFBF0120704700BFBB +:101BE00094330020014B1868704700BF0010005C60 +:101BF000194B01380322084470B51D68174BC5F313 +:101C00000B042D0C1E88A6420BD15C680A46013CD1 +:101C1000824213460FD214F9016F4EB102F8016BE4 +:101C2000F6E7013A03F10803ECD181420B4602D2F8 +:101C30002C2203F8012B0424094A1688AE4204D151 +:101C4000984284BF967803F8016B013C02F10402CC +:101C5000F3D1581A70BD00BF0010005C14220020A0 +:101C6000448B0008022804D1054B4FF400029A610E +:101C700070470128FCD1034B4FF48012F7E700BFF7 +:101C80000000025800040258022803D1044B8022AD +:101C90009A6170470128FCD1024B1022F8E700BF7F +:101CA0000000025800040258022805D1064A536970 +:101CB00083F08003536170470128FCD1034A5369C4 +:101CC00083F01003F6E700BF00000258000402583A +:101CD00070B504464FF47A764CB1412C254628BFA6 +:101CE000412506FB05F0641B04F05CF9F4E770BDC8 +:101CF000002310B5934203D0CC5CC4540133F9E700 +:101D000010BD0000013810B510F9013F3BB191F949 +:101D100000409C4203D11AB10131013AF4E71AB1F3 +:101D200091F90020981A10BD1046FCE703460246C0 +:101D3000D01A12F9011B0029FAD170470244034658 +:101D4000934202D003F8011BFAE770472DE9F843EC +:101D50001F4D14460746884695F8242052BBDFF8ED +:101D600070909CB395F824302BB92022FF2148466F +:101D70002F62FFF7E3FF95F824004146C0F1080207 +:101D800005EB8000A24228BF2246D6B29200FFF7A0 +:101D9000AFFF95F82430A41B17441E449044E4B2CE +:101DA000F6B2082E85F82460DBD1FFF70BFF002880 +:101DB000D7D108E02B6A03EB82038342CFD0FFF731 +:101DC00001FF0028CBD10020BDE8F8830120FBE70C +:101DD00094330020024B1A78024B1A70704700BFF0 +:101DE000BC3300201022002010B5114C114803F024 +:101DF00009FC21460F4803F031FC24684FF47A7047 +:101E0000D4F89020D2F8043843F00203C2F8043822 +:101E1000FFF75EFF0849204603F02EFDD4F890201E +:101E2000D2F8043823F00203C2F8043810BD00BF12 +:101E3000F8920008683B00200093000870470000FB +:101E40002DE9F04771B6464B01201D68454BB3F8AC +:101E5000008000231A46194602F0C6FD0446802081 +:101E600004F09EFE0746002862D0002C60D03E4E53 +:101E7000ADB24FF0800A7369284643F0C0637361C6 +:101E8000D6F8143143F0C063C6F8143104F008FDED +:101E900005EB080200FB05F34FF4D06C50434FF004 +:101EA0003D0E984233D93269520144D4D6F81021FC +:101EB000510140D4216803F100628A602268D76032 +:101EC0002268C2F804A02268C2F800C0D4F80090CA +:101ED000D9F8002042F00102C9F80020D4F800909F +:101EE000D9F8002022F01E02C9F80020D4F8009092 +:101EF000D9F80020D207FBD494F80C9080336168A5 +:101F00000EFA09F20A60CCE7002004F0A7FD204693 +:101F100002F0AAFD384604F07FFE134B5A6942F0E6 +:101F2000C0625A61D3F8142142F0C062C3F8142190 +:101F300061B6BDE8F0870D4B9A6A42F400729A626E +:101F40009A6A42F400429A6261B60026012004F0C7 +:101F500085FDB045D8D9A819013604F0B9FCF8E7D9 +:101F600090330020BE3300200020005200ED00E03E +:101F700030B50A44084D91420DD011F8013B58404C +:101F8000082340F30004013B2C4013F0FF0384EAD4 +:101F90005000F6D1EFE730BD2083B8ED0121884233 +:101FA00038BF084604F034BE08B104F035BE7047AF +:101FB00010B5084C01220849002001F0B3FE237837 +:101FC0003BB1064803F05EFA044803F091FA00239F +:101FD000237010BDC0330020548B0008A0360020B1 +:101FE0001D482DE9F041036D2BB901224FF48051BA +:101FF000503004F055FF194E33780BB1FFF7D8FF7E +:102000000324174F4FF00008134D15492846C7F811 +:10201000048003F05FFA284603F098F848B1013CC9 +:10202000284603F065FA14F0FF04EED12046347020 +:102030000FE00C4901220C4801F074FE014618B172 +:10204000284603F01FFAEAE7084800F011F80120DB +:102050003070BDE8F08100BFA0360020C033002002 +:102060002C220020548B0008C4330020588B000819 +:102070000FB4002004B07047006870470346006842 +:10208000596870470B0A017043700B0C090E83707E +:10209000C1707047110A027003714170110C120E69 +:1020A0008170C2701A0A42711A0C1B0E8271C371C0 +:1020B00070470000C36A0239023B8B4283BF4389E9 +:1020C000006C01FB0300002070470000C2F30723EF +:1020D0008A76CB760378032B01BF120C0A75120A9D +:1020E0004A75704700F10B010022D30143EA520305 +:1020F00010F8012B52FA83F38842DAB2F5D1104678 +:102100007047000010B541780446002001310246B6 +:102110004901022A16BFA35C032203EBC03302F17C +:1021200001021EBF9BB203EB500398B29142F0D85C +:1021300010BD000002684AB1134613F8011B1F29A5 +:102140000DD93A29F9D1911C8B4202D04FF0FF30C2 +:1021500070471278302AF9D1036000207047014B94 +:10216000187870471036002038B50D46044618B967 +:10217000092000232B6038BD0368002BF8D01A78A3 +:10218000002AF5D08188DA889142F1D1587804F09C +:10219000A5F810F00100EBD12368EBE738B50D4648 +:1021A00040F25231144602F0B9F9FF2807D9012C48 +:1021B0000BD9030A022468702B70204638BD30B159 +:1021C000002CFAD001242870F7E70024F5E7044634 +:1021D000F3E700002DE9F8430026D0F8008005461B +:1021E0000C468E76836B002B4AD098F80030042B77 +:1021F0004BD133463546402720E0B7F5187F80F0B5 +:10220000C480F90606F1010608BF0237D05B023729 +:102210002BB900F5205292B2B2F5006F0DD305F143 +:102220001A01C5F1FF0240EA03402144FFF7B6FF5F +:10223000002800F0AA80054400200346D8F81020AA +:1022400092F82310B142D8D8002B40F09E80002D88 +:1022500000F09B8000232544AB766373D8F81020F0 +:10226000137903F03701DB0621730BD402F1380038 +:10227000FFF704FFC4E9000193896381D3892381B7 +:10228000BDE8F88300200146F4E7C36C01335ED15A +:10229000EA6B00232E26551E184615F8011F013043 +:1022A00020290CD0052908BFE521092804D10B2BD2 +:1022B0009EBFE71801337E73E718013379730B284B +:1022C000EBD1E11800204873A17E00294BD1002BEF +:1022D00040D06FF00C0604F10D000825361B3318B2 +:1022E00010F8011B002938D02E298BB24AD0A3F157 +:1022F0004101192903D8117B0D4200D0203303730B +:10230000EDE7B9F1000F05D100F520539BB2B3F50D +:10231000006F0BD307F11A01C7F1FF0240EA094031 +:102320002144FFF73BFF48B10744002002368146B5 +:10233000D8F80C30985B0028E3D13846B9F1000F8B +:102340004FF0000218BF002023189A76A0E7B1468C +:102350003746EDE73F23A3760123234400219976F6 +:10236000137B03B96373D37A02F11C0003F03F03BC +:1023700023730023FFF780FE20606360D38A6381AC +:10238000138B7CE710250B46B9E73F230125A37685 +:1023900060E7000038B50546002435F8020B08B99F +:1023A000204638BD02F0EEF86308C2B203EBC43336 +:1023B00012FA83F39AB2C0F3072303EB520303EB41 +:1023C000C2339CB2E9E7000037B5C37804461BB9B5 +:1023D0000025284603B030BD00F14C01826C01237A +:1023E0004078019103F0A0FF054680B9A36BE0702F +:1023F000A06C226BC31A9342EAD2A3780199022BF4 +:10240000E6D102440123607803F08EFFE1E7012565 +:10241000DFE7000038B5836C05460C468B4210D0D0 +:10242000FFF7D2FF60B92246012305F14C0168781D +:1024300003F056FF00281CBF4FF0FF340120AC64AE +:1024400038BD0020FCE7000038B500230446C37007 +:102450004FF0FF338364FFF7DDFF00284BD1B4F862 +:102460004A524AF655239D4207D10B22254904F1D1 +:102470004C0006F0B1FA00283FD094F84C30EB2B1A +:1024800003D01833DBB2012B2ED84AF655239D42D8 +:1024900006D108221C4904F19E0006F09DFA48B3BB +:1024A000B4F85730B3F5007F1ED194F85930DBB142 +:1024B0005A1E1A4218D1B4F85A30ABB194F85C30B5 +:1024C000013B012B10D8B4F85D306BB1B4F85F302C +:1024D0007F2B06D804F16C00FFF7CEFDB0F5803FEE +:1024E00002D3B4F8623053B94AF6552085420CBF86 +:1024F0000220032038BD0420FCE70120FAE7002079 +:10250000F8E700BF848B0008908B000802392DE9A2 +:10251000F04701F007044FF0010A466C05460AFA3D +:1025200004F41746984606EB1136C1F3C809E4B225 +:10253000314628460136FFF76DFF18B10120BDE88E +:10254000F087994605EB090292F84C30234214BFFC +:1025500001210021414513D06340013F82F84C30F6 +:1025600085F803A0EBD0640014F0FF04EAD109F170 +:10257000010301244FF00009B3F5007FE1D1D7E753 +:102580000220DCE701290246F8B50C4640F28C80B7 +:102590000668F36A8B4240F287803378013B032B55 +:1025A00000F28280DFE803F00229384B04EB540587 +:1025B000B16B304601EB5521FFF72CFF10B14FF006 +:1025C000FF30F8BD6F1CC5F30805B16B30463544CC +:1025D00001EB572195F84C50FFF71CFF0028EED176 +:1025E000C7F30807E3073E4496F84C0045EA00208D +:1025F0004CBF0009C0F30B00E3E7B16B304601EBC1 +:102600001421FFF707FF0028D9D1640004F4FF74F8 +:102610002644B6F84C00D4E7B16B304601EBD41138 +:10262000FFF7F8FE0028CAD1A40006F14C0004F41C +:10263000FE742044FFF720FD20F07040C1E7D0E990 +:102640000430D57953EA000101D0916801B95DBB2E +:102650009168022DA4EB01010DD1013B728940F17B +:10266000FF305B0A43EAC053B3FBF2F399421BD835 +:102670001CD0601CA5E7032D02D193698B42F8D8CA +:10268000D3699BB9B16B304601EBD411FFF7C2FEA1 +:10269000002894D1A0004C3600F4FE703044FFF7BF +:1026A000EBFC20F000408CE701208AE76FF000404F +:1026B00087E70000F8B5066804460D463378042B1A +:1026C0000CBF4FF080524FF400128A4201D8022012 +:1026D000F8BDCA06FBD182680163D2B9022B13D8B8 +:1026E0003389B3EB551FF2D9F36BA363A36B62631A +:1026F000002BECD003EB55234C36C5F30805002026 +:10270000A3633544E563E3E7F36BC271002BE7D0C5 +:102710001A4677897F02BD42114604D23046FFF740 +:10272000C9FCA063E2E72046FFF72CFF431C0246EA +:1027300006D00128CBD9F36A8342C8D9ED1BEAE75A +:102740000120C5E701292DE9F04706460C4617464A +:1027500008D9C36A8B4205D90378022B62D003D80B +:10276000012B22D0022552E0033B012BFAD8816BCA +:1027700001EBD411FFF74EFE0546002847D1A40017 +:1027800006F14C0304F4FE741C443378042B07D088 +:10279000204627F07047FFF76FFC00F070400743BA +:1027A00039462046FFF76EFC2FE001EB5108816BA4 +:1027B00001EB5821FFF72EFE054640BB14F0010443 +:1027C00006F14C0908F1010AC8F3080808BFFBB27A +:1027D00030461FBF19F8083003F00F023B0103F029 +:1027E000F00318BF134309F808300123B16BF370ED +:1027F00001EB5A21FFF70EFE054640B9CAF3080A5D +:1028000044B1C7F3071709F80A700123F37028468B +:10281000BDE8F08719F80A30C7F3032723F00F0348 +:102820001F43F0E7816B01EB1421FFF7F3FD054631 +:102830000028ECD1640006F14C0304F4FF741F552A +:102840001919C7F307274F70DFE70000F8B50446F2 +:102850000E461746E3690BB91846F8BD012BA6EBE7 +:102860000305206814BFAA1C3A46691CFFF76AFFDB +:102870000028F2D1E369013BE361EBE701292DE98F +:10288000F84306460C461746056802D80220BDE804 +:10289000F883EB6A8B42F9D97AB9A14621463046D2 +:1028A000A046FFF76FFE0446B0B92B78042B02D187 +:1028B000002F43D1F7710020E9E72B78042B02D1D8 +:1028C000C379022BE9D04FF0FF3239462846FFF793 +:1028D00039FF0028E1D0DAE70128D7D0421C01D126 +:1028E0000120D4E72B78042B19D1EA6AAB69023AAC +:1028F00093421CD308F10102A2420CD02B78042B86 +:1029000008D10023A2EB090249462846FFF7FEFD45 +:102910000028BCD1A146EB6AA342BFD8C5E700227C +:1029200041462846FFF70EFF0028DED0AFE701330F +:10293000AB612B7943F001032B71DBE7F3798BB9A2 +:10294000B468BC4202D10223F371B4E72146304699 +:10295000FFF718FE012899D9431CC1D001348442E5 +:10296000EFD0A8E7032BA6D1B368BB42A3D8B269C6 +:102970001344BB429FD3E6E770B5C3790446032BEB +:1029800006D181688369CD18A94203D10023E37180 +:10299000002070BD4E1C20683246FFF7D3FE002891 +:1029A000F7D13146F0E700002DE9F74305460191E4 +:1029B000FFF70AFD0446002849D105F14C090199A9 +:1029C00028464FF40072FFF775FB2146A8640746BE +:1029D0004846FFF7B3F96C896402B4F5004F28BF8D +:1029E0004FF40044B4F5007F2FD9204604F018F9C5 +:1029F000804630B122460021640A0026FFF79EF986 +:102A000009E06408EEE72346BA194146687803F006 +:102A10008BFC18B926446B899E42F4D3404604F0DF +:102A20000FF96889801B18BF012003B0BDE8F0834F +:102A300001366B899E42F4D20123BA19494668785F +:102A400003F072FC0028F3D0EBE70026F1E7012049 +:102A5000EBE70000F8B50446FFF7B6FC0546002892 +:102A600042D12378032B37D12779012F34D104F1B8 +:102A70004C0601464FF400723046FFF75FF95523CC +:102A80004122722184F84A32AA2304F50D7084F899 +:102A90004F2084F84B32522384F8301284F84C30A3 +:102AA00084F84D30612384F8311284F84E3084F874 +:102AB0003332A16984F83222FFF7E4FA616904F540 +:102AC0000E70FFF7DFFA626B3B46314601326078E9 +:102AD000A26403F029FC257100226078114603F0FE +:102AE00047FC003818BF0120F8BD000000232DE985 +:102AF000F0430B6085B00F461546FFF71BFB061E23 +:102B0000C0F2B281804B53F82640002C00F0AE8119 +:102B10003C6005F0FE0523786BB1607803F0DEFBC6 +:102B2000C70708D41DB110F0040500D00A252846B7 +:102B300005B0BDE8F0830023F0B22370607003F0AD +:102B4000B9FBC10700F194810DB14207EED4002119 +:102B50002046FFF779FC022840F099806E4604F287 +:102B6000122304F25221324618461033FFF784FA3A +:102B700042F8040B8B42F7D1002556F8041B0029BC +:102B80007DD02046FFF760FC012879D80128A26C8F +:102B900040F0C08004F1570304F18C0113F8015B8D +:102BA000002D7BD18B42F9D1B4F8B430B3F5807FDE +:102BB00074D194F8B830092B70D104F19400FFF768 +:102BC0005DFA4FF0FF33171841F10001BB4275EB7E +:102BD000010363D304F1A000FFF74EFA94F8BA3072 +:102BE0002063012BA37059D194F8B99003FA09F925 +:102BF0001FFA89F36381002B50D0444B04F1A800E5 +:102C0000FFF73AFA0646984248D8831C626304F1FB +:102C1000A400E362FFF730FA00EB020804F19C0025 +:102C2000C4F84080FFF728FA10441FFA89F2A06325 +:102C300006FB02F313EB080345EB05029F4271EB21 +:102C400002032BD32E4604F1AC00FFF715FAE06324 +:102C500065B96389B34221D9E16B2046FFF72AFAAF +:102C600081192046FFF7D6FB98B90136631993F80E +:102C70004C30812B14D02035C5F30805E8E703203C +:102C80000135042D7FF479AF042807D101E0042831 +:102C900001D101254BE701287FF678AF0D2546E7E6 +:102CA00005F1140004F14C063044FFF7E5F9012862 +:102CB0000546F3D9E36A8342F0D96189821E236C09 +:102CC00002FB01336364A16B204601EBD511FFF7D2 +:102CD000A1FB0028DDD105F07F0006EB8000FFF7A7 +:102CE000CBF9431C03D00135A842ECD0D6E704252C +:102CF000C4E90500064A257000251388E561013303 +:102D00009BB21380E38012E714360020FDFFFF7FA3 +:102D100018360020B4F85730B3F5007FBED1B4F8B0 +:102D2000626026B904F17000FFF7A6F9064694F830 +:102D30005C302663591EA3700129AFD894F859500E +:102D40006581002DAAD0691E2942A7D1B4F85D8003 +:102D500018F00F0FA4F80880A0D1B4F85F0018B9DC +:102D600004F16C00FFF788F9B4F85A10002995D0E7 +:102D700006FB03FE01EB181CF44460458ED3A0EB68 +:102D80000C00A842B0FBF5F388D33E48834285D8B7 +:102D90004FF6F57083426DD903259F1C114402EB59 +:102DA0000C03032DE7626263A16323644CD1B4F882 +:102DB000763053EA08037FF471AFBB0004F178006A +:102DC000FFF75AF9E06303F2FF13B6EB532FFFF45A +:102DD00065AF4FF0FF33032DC4E905334FF0800397 +:102DE000237187D1B4F87C30012B83D1511C20464C +:102DF000FFF710FB00287FF47DAFB4F84A224AF6B3 +:102E0000552320719A427FF475AF1F4B04F14C009B +:102E1000FFF732F998427FF46DAF03F1FF5304F5E9 +:102E20000C70FFF729F903F50053203398427FF423 +:102E300061AF04F50D70FFF71FF9A06104F50E7086 +:102E4000FFF71AF9606155E7B8F1000F3FF426AFBC +:102E50007144022D4FEA4703E1631EBFD91907F001 +:102E6000010303EB5103AEE70B2560E60C255EE69C +:102E700003255CE640F6F575AB428CBF02250125C3 +:102E80008BE700BFF5FFFF0F525261412DE9F84F6C +:102E900007460568884649B96E69C6B1EB6AB34210 +:102EA00098BF0126AB69A3B9002405E0FFF76AFBD0 +:102EB0000128044603D801242046BDE8F88F421CAF +:102EC00000F0D280EB6A8342F6D84646EAE7012654 +:102ED000E8E72A78EB6A042A40F08380A6F1020A28 +:102EE000023B4FF0010B9A4528BF4FF0000AD14634 +:102EF000696C284601EB1931FFF78CFA00283BD1A9 +:102F000009F00703EA6AC9F3C8010BFA03F3901E3C +:102F1000DBB26A184C4609F1010992F84C20814550 +:102F200002EA030233BF5B0000234FF40071DBB2FF +:102F300028BF9946B2B90234631E0333BCD80123BB +:102F4000214628461A46FFF7E1FA0228B3D00128A5 +:102F500000F08A80B8F1000F13D10223FB71002822 +:102F6000A9D130E0CA450AD0002BD2D10131B1F548 +:102F7000007FBDD20123CCE74FF0FF34DCE7002413 +:102F8000DAE7FB79022B07D1731CA342E7D0BB68B9 +:102F9000F31ABB610323FB7108F10102FB69A24232 +:102FA00005D113B10133FB61D9E70223FBE70BB96C +:102FB0000123FB61224641463846FFF747FC0028C3 +:102FC0004FD10123FB61EA6AAB69023A6C6193421B +:102FD0009CBF03F1FF33AB612B7943F001032B71ED +:102FE0006AE7464514D1741C3846A34298BF0224B0 +:102FF0002146FFF7C7FA01283FF45DAF431C33D0E9 +:10300000E0B16B69012B03D9EA6A934238BF1E46CF +:1030100034460134EB6AA34203D8012E7FF644AF55 +:10302000022421463846FFF7ADFA48B101283FF4A3 +:1030300042AF013018D0B442EBD135E7002CE7D0D5 +:103040004FF0FF3221462846FFF77CFB48B9B8F124 +:10305000000FB8D0224641462846FFF773FB0028F0 +:10306000B1D001287FF427AF4FF0FF3424E70000F0 +:103070002DE9F84306680446076B89463378203704 +:10308000042B0CBF4FF080534FF40013BB429CBF86 +:1030900000238363836B73B1C7F30808B8F1000F93 +:1030A0003CD10133416B836339B93389B3EB571F8B +:1030B00034D80023A36304200AE07389013B13EA98 +:1030C00057232BD1FFF75EFA0128054602D80220CC +:1030D000BDE8F883421C01D10120F9E7F36A83427D +:1030E00016D8B9F1000FE4D0616B2046FFF7CEFE91 +:1030F0000546C8B10128EAD0431CEDD00146304650 +:10310000FFF752FC0028E7D1E37943F00403E371B1 +:10311000294630466563FEF7CDFFA0634C3600209C +:1031200027634644E663D3E70720D1E7F8B50E46A8 +:10313000002104460768FFF7BDFA98B90546A16B60 +:103140003846FFF767F968B93A78E36B042A1B78C9 +:103150000CD11B060ED5054601212046FFF788FF3E +:103160000028ECD0042808BF072006E0E52B01D09A +:10317000002BF0D10135B542EED1F8BDC16C4B1C2E +:103180002DE9F04104460568066B1FD1E5274FF095 +:103190000108A16B2846FFF73DF998B92A78E36B3F +:1031A000042A09BF1A781F7002F07F021A7085F88E +:1031B0000380236BB3420DD200212046FFF758FF56 +:1031C0000028E6D0042808BF022003E0FFF772FAC7 +:1031D0000028DBD0BDE8F0812DE9F041054600680C +:1031E000A96B0669FFF716F9044620B9EB6B1A784C +:1031F000852A03D002242046BDE8F081324603F13F +:10320000200153F8040B8B4242F8040BF9D1777874 +:1032100001377F01A7F16003B3F5007FEAD80021F1 +:103220002846FFF725FF04280446E3D00028E2D112 +:10323000A96B2868FFF7EEF804460028DBD1EB6B9A +:103240001A78C02AD6D106F1200203F1200153F8E2 +:10325000040B8B4242F8040BF9D196F823300F226D +:103260002C33B3FBF2F3B7EB431FC3D34FF040084B +:1032700000212846FFF7FCFE04280446BAD00028A7 +:10328000B9D1A96B2868FFF7C5F804460028B2D168 +:10329000EB6B1A78C12AADD1B8F5187F09D206EBCD +:1032A000080203F1200153F8040B8B4242F8040B8F +:1032B000F9D108F120084745DAD8B8F5187F9AD82F +:1032C0003046FEF71FFF7388834294D092E70000D8 +:1032D0000B68002210B5036004460B6A83604B6ADA +:1032E000C261C37123F0FF03896AC0E90432C1647B +:1032F000FFF7E0F920B92046BDE81040FFF76CBFAA +:1033000010BD0000F8B50368054601271C6920467A +:10331000FEF7F8FEA070000A6678E0702846E96CB7 +:10332000FFF7C8F920B1022828BF0220C0B2F8BDBB +:10333000A96B2868FFF76EF80028F4D1EB6B04F155 +:10334000200254F8041B944243F8041BF9D12B6863 +:10335000DF70002EE7D000212846013EFFF788FEEF +:10336000E0E700002DE9F8434FF0FF080646076844 +:10337000042445464FF6FF79B16B11B9002C73D088 +:1033800063E03846FFF746F8044600285DD1F06B4D +:103390000378002B6ED03A78042A11D1852B4DD1B9 +:1033A000336B3046F364FFF717FF044600284CD117 +:1033B0003B691B7903F03F03B3712046BDE8F883F6 +:1033C000C27AE52B02F03F02B27143D02E2B41D0DE +:1033D00022F0200108293DD00F2A40D1590637D5C7 +:1033E00003F0BF05336B90F80D80F364437B4345D6 +:1033F00030D1428B72BB03780D21FC6823F040036F +:10340000DFF874E0013B4B4301211EF801CB30F89B +:103410000CC009B3FF2B1DD824F813C0614601333B +:1034200001320D2AF1D10278520605D521B1FF2BC8 +:1034300010D8002224F81320013DEDB200213046BF +:10344000FFF716FE0446002896D00023B363B4E7C6 +:10345000AB42CBD0FF25F1E7CC45E1D0FAE72DB95F +:10346000FEF740FE404501D10024A6E74FF0FF33B0 +:10347000F364A2E70424E8E72C8C00082DE9F04F60 +:10348000002187B00446D0F80090FFF713F980467A +:1034900070B999F80030042B33D1D9F80C00FEF73D +:1034A00079FF07462046FFF75DFF054620B18046BD +:1034B000404607B0BDE8F08FD9F810309A8CBA4278 +:1034C000F0D193F823B040265D4506D1D9F80C30F1 +:1034D00033F81530002BE5D1EAE7F106D9F81030C2 +:1034E00008BF0236985B01F04DF8D9F80C308246DF +:1034F00033F8150001F046F88245D3D10236013584 +:10350000E2E74FF0FF0A4FF0FF3B5546C4F84CB0DE +:10351000A16B4846FEF77EFF00285CD1E66B37784A +:10352000002F77D0F27AE52F02F03F03A37103D08A +:10353000120704D50F2B04D0C4F84CB04FE00F2B6A +:1035400054D194F84B3058063FD4790645D5236BB7 +:1035500007F0BF0796F80DA0E364737B53453ED197 +:10356000738B002B3BD135780121D9F80C3005F055 +:103570003F0501930D23013D5D43284B13F8012BBB +:10358000B25A71B3FF2D059329D81046049200F06A +:10359000F9FF6B1C03900293019B33F8150000F0B8 +:1035A000F1FF039981421AD1049A029D1146059BAD +:1035B0001B4A9342E2D133785A0604D519B1019BD4 +:1035C00033F815305BB97D1EEDB200212046FFF7C0 +:1035D0004FFD00289CD080466AE7BD42BDD0FF2544 +:1035E000F3E74FF6FF708242E2D0F8E72DB930469C +:1035F000FEF778FD50453FF45BAF94F84B30DB07A6 +:103600009AD40B2204F14001304605F0E5F9002878 +:1036100092D14DE74FF004084AE700BF2C8C000818 +:10362000398C00082DE9F04F90F84BB099B0044662 +:103630001BF0A00540F068810668F26832F815308A +:10364000002B4AD13378042B40F087800F230E35AE +:103650002046B5FBF3F5A91CFFF768FD814600285D +:1036600077D1236B0135A3EB4515E3795A07E56460 +:1036700035D523F004032046E371FFF77DF950BBF5 +:103680004FF0FF32616B2046FFF7E0F818BBA368EC +:103690002BB3214604A8FFF71BFEE0B970894FF455 +:1036A0000071D4E90423E0FB01233069C4E9042359 +:1036B0003830FEF7EFFC3069D4E904232830FEF7F8 +:1036C000E9FCE379326904A843F0010382F8213070 +:1036D000FFF718FE18B181463BE00135AEE7D6E9A9 +:1036E0000354402200212046FEF728FB85230121B8 +:1036F00040222370C0234FF0C10C04EB010884F872 +:10370000203000231E469E46571C04F802C0F0B22B +:10371000023204F807E021B135F8131009B1013382 +:10372000DBB20F0AA15408F802700232D706F2D1B8 +:1037300035F813700136002FE6D184F82330831C4E +:1037400028466370FEF726FE84F82400000A84F8F9 +:103750002500484619B0BDE8F08F04F140070DF18F +:10376000100A1BF0010F97E807008AE8070000F035 +:10377000D38040234FF0010884F84B30BC46F368F7 +:10378000B8F1050F9AE80700ACE803002CF8022B0B +:103790004FEA12428CF8002059D9981E424630F860 +:1037A000021F002942D10DF10F0C072102F00F0E6C +:1037B000914612090EF13000392888BF0EF137000A +:1037C00001390CF8010902D0B9F10F0FEED818AB8E +:1037D0007E205A1802F8580C38460022914206D032 +:1037E00010F801CB02F1010EBCF1200F31D104F130 +:1037F0003F0C072902F1010297BF18AB202058188F +:10380000013198BF10F8580C072A0CF80200F0D9C3 +:103810002046FFF733FE8146002878D108F10108E1 +:10382000B8F1640FAAD14FF0070992E74FF0100CDE +:1038300001F0010E49080EEB4202D30344BF82F4AB +:10384000883282F02102BCF1010CF1D1A7E7424697 +:10385000A9E77246C2E7216B2046A1EB4511FEF7AE +:1038600029FF814600287FF474AF4FF6FF78384671 +:10387000FEF738FC0190A16B3046FEF7CBFD814688 +:1038800000287FF466AFE36BE9B2019A4FF00D0CAC +:10389000D6F80CE05A734FF00F02DFF8E0A0DA72AE +:1038A0004A1E18730CFB02F284469876D87640457F +:1038B0001AF8019B0CF1010C18BF3EF8120003EB43 +:1038C000090B18BF013203F809004FEA102900283C +:1038D00008BF4046BCF10D0F8BF80190E7D1404581 +:1038E00002D03EF812200AB941F0400119700123BC +:1038F00000212046F370FFF7BBFB814600287FF4D0 +:1039000028AF013DB7D11BE04FF0060921E704289D +:103910007FF41FAF84F84BB01BF0020F20461BBF93 +:103920000C350D210125B5FBF1F518BF01352946F0 +:10393000FFF7FCFB814600287FF40BAF013D8AD1E5 +:10394000A16B3046FEF766FD814600287FF401AF8B +:1039500001462022E06BFEF7F1F9E36B03CF18601C +:103960005960BA7839889A72198194F84B30E26BB1 +:1039700003F0180313730123F370EAE62C8C00089C +:1039800010B504460A463430FEF776FB886004F131 +:103990003800FEF773FBC2E9040194F8213003F00C +:1039A0000203D3710023D36110BD000003284B8BA9 +:1039B00004BF8A8A43EA0243184670472DE9F04F54 +:1039C0000B7899B0044689462F2BD0F800B001D06F +:1039D0005C2B09D14A461378914601322F2BFAD03D +:1039E0005C2BF8D0002301E0DBF81C30A36000233F +:1039F000E3619BF80030042B1ED1A368E3B1DBF830 +:103A00002030214604A82362DBF824306362DBF80F +:103A10002830A362FFF75CFC0346002854D1DBF892 +:103A2000102002F13800FEF727FBC4E9040392F8E6 +:103A3000213003F00203E37199F800301F2B00F2EC +:103A4000358180230021204684F84B3019B0BDE831 +:103A5000F04FFEF72FBE49460B78894601312F2BD8 +:103A6000FAD05C2BF8D01F2B8CBF00250425012F2A +:103A70002FD113882E2B31D1002322F8173004F1D7 +:103A800040029F428CBF2E21202101330B2B02F8D4 +:103A9000011BF6D145F02005204684F84B50FFF776 +:103AA000EDFC94F84B30002800F0E78004280BD19F +:103AB000990603F0040240F1DC80002A00F0F68051 +:103AC0008023002084F84B3019B0BDE8F08F042526 +:103AD000CDE7022F02D153882E2BCAD0911E87BB6F +:103AE000002322F81730002F00F0118132F8130064 +:103AF000194601332028F9D009B92E2801D145F003 +:103B00000305901E30F817302E2B01D0013FF9D15C +:103B10004FF020334FF0000A6364D0462364C4F8AA +:103B200047300823481C32F811600090F6B1202E6F +:103B300003D02E2E0DD1B84210D045F003050099C8 +:103B4000F0E731F81730202B01D02E2BC8D1013FE0 +:103B5000C5E79A4505D20099B9423BD10B2B30D12C +:103B600001E00B2B27D145F003050B2394F84020EF +:103B7000E52A04BF052284F84020082B04BF4FEA41 +:103B800088085FFA88F808F00C030C2B03D008F0C3 +:103B90000303032B01D145F00205A8073FF57CAFD5 +:103BA00018F0010F18BF45F0100518F0040F18BFEA +:103BB00045F0080570E70099B94202D045F00305C9 +:103BC000D4D84FEA88080B234FF0080A00975FFA11 +:103BD00088F8B4E77F2E15D9304640F25231CDE94E +:103BE000022345F00203019300F098FC10F0800FCF +:103BF0000646DDE9022316D000F07F0646498E5DB9 +:103C0000019D46B331464548CDE9012304F00EFF3E +:103C1000DDE90123F8B9A6F1410189B219291ED8BD +:103C200048F0020810E0FF28EAD9591E8A4503D35C +:103C300045F003059A4682E704EB0A01000A0AF1FF +:103C4000010A019D81F8400004EB0A010AF1010A12 +:103C500081F8406073E745F003055F26F4E7A6F1BD +:103C6000610189B219299EBF203E48F00108B6B211 +:103C7000EAE7002A08BF052026E75A073FF524AFE8 +:103C8000A379DB0645D59BF80000042835D1A3684D +:103C90002146E27923622369DBF8100023F0FF0359 +:103CA00013436362E36CA362FFF76AFE2368002795 +:103CB000DA6819F8010B00283FF409AF40F25231DD +:103CC000009200F04BFC054608B31F28009A7FF6CF +:103CD000FEAE2F283FF4BFAE5C283FF4BCAE7F2879 +:103CE00005D801460E4804F0A1FE009A78B9FF2FCE +:103CF0000DD022F817500137DBE7216B0BF14C0395 +:103D0000C1F308011944FFF751FEA060CEE7062079 +:103D1000DAE60520D8E600BFAC8B0008A58B0008CA +:103D20009C8B00081FB5CDE9001003A81446039131 +:103D3000FEF700FA002815DB0B4A52F820300BB1D1 +:103D400000211970019B0BB10021197042F820303D +:103D50002CB1002201A96846FEF7C8FE04462046A1 +:103D600004B010BD0B24FAE7143600202DE9F0470B +:103D700098B0904605460191002800F0528102F06B +:103D80003F0603A901A83246FEF7B0FE002840F026 +:103D90004681039B4FF48C60049302F041FF074679 +:103DA000002800F04081039B00F500720199D86063 +:103DB00004A81A61FFF702FE044620B99DF95B30A2 +:103DC000002BB8BF062418F01C0F00F0CD80002C8B +:103DD0004CD0042C40D104A8FFF724FC0446002852 +:103DE0003AD146F00806039B1A78042A40F08380F3 +:103DF000186929462B60FFF7C3FD039B1E22002193 +:103E000018690230FDF79AFF039C00211A222069ED +:103E10002630FDF793FF236920221A71246902F0EE +:103E200039FF0146012208342046FEF72BF9039B97 +:103E300004A81B6983F82120FFF764FA044658B9E7 +:103E4000A96801B302462846FEF718FDAB68039A3D +:103E50000446013B5361B4B1384602F0F1FE0CB1A7 +:103E600000232B60204618B0BDE8F0879DF816307F +:103E700013F0110F40F0848018F0040F40F0C98057 +:103E800018F0080FAFD1039A31071399936C48BF0C +:103E900046F04006E964AB641078042872D1069BB2 +:103EA0009DF817102B62089B106923F0FF030B434A +:103EB00029466B62179BAB62FFF762FDDDF80CA031 +:103EC0000024002205F15008BAF806302146404689 +:103ED000C5F800A0AB80002385F8306085F831403C +:103EE0006C64C5E90E234FF40072FDF727FFB2069C +:103EF00053D40024B0E702F0CDFE014600901398A1 +:103F00000E30FEF7BFF8139800991630FEF7BAF896 +:103F1000039C13992078FFF749FD20230022804657 +:103F2000CB7220461399FEF7D1F8139B0022012192 +:103F30001A775A779A77DA77039BD970B8F1000F1E +:103F4000A1D0414604A8D3F84890FEF797FC044658 +:103F5000002881D149460398FEF75CFA039B04468A +:103F600008F1FF30586176E7002C7FF475AF9DF8BB +:103F70001630DC064FD418F0020F84D0D80782D553 +:103F8000072469E7FFF712FD0023A86001F11C0078 +:103F9000FEF772F86B61286190E7D5E9046956EA8B +:103FA0000903A6D0BAF80AA0A9684FEA4A2AC5E9C7 +:103FB0000E69B24574EB09031BD300242964002C5D +:103FC0007FF44AAFC6F30803002B92D0039C20462F +:103FD000FEF770F808B3760A0123414646EAC9564F +:103FE00082196A64607802F07BF9041E18BF01240C +:103FF00032E72846FEF7C6FAB6EB0A06014669F133 +:104000000009012803D9431CD3D10124D6E7022497 +:10401000D4E7082420E704241EE702241CE7044612 +:104020001EE709241EE711241CE700002DE9F04FCC +:10403000994685B00023884603A90446C9F8003094 +:104040001646FEF791F8054680BB94F831506DBBDB +:1040500094F8303013F00103009300F0A68004F1CF +:10406000500AD4E90432D4E90E011B1A62EB0102B2 +:10407000B34272F1000238BF1E46BEB1D4E90E1041 +:10408000C1F30803002B40F08280039B5A894B0A3E +:10409000013A43EAC0531A401BD151EA000309D147 +:1040A000A06801280DD8022584F83150284605B0B3 +:1040B000BDE8F08F216C20460192FEF763FA019A69 +:1040C000EFE7431C04D10123009D84F83130EDE774 +:1040D0002064DDF80CB0216C5846FDF7EBFF00289A +:1040E000E1D0B6F5007F02EB000731D3BBF80A1030 +:1040F00002EB5620730A88429BF8010088BF8B1A96 +:104100003A464146019302F0EBF80028DBD194F9DE +:104110003020019B002A0BDA606CC01B984207D24A +:104120004FF40072514608EB4020FDF7E1FD019B82 +:104130005F02D9F80030F61BB8443B44C9F80030A0 +:10414000D4E90E32DB1942F10002C4E90E3294E7E1 +:10415000626CBA421AD094F93030002B0DDA012388 +:1041600051469BF8010002F0DFF80028ABD194F82B +:10417000303003F07F0384F83030039801233A464F +:104180005146407802F0ACF800289CD16764A16BDE +:104190004046C1F30801C1F500775144B74228BF3A +:1041A00037463A46FDF7A4FDC3E707257EE7000042 +:1041B00070B596B00E460022019002A901A8FEF744 +:1041C00095FC0446E0B94FF48C6002F029FD0546E9 +:1041D000D8B1029B00F500720199D86002A81A615B +:1041E000FFF7ECFB044640B99DF95330002B0ADB86 +:1041F0001EB1314602A8FDF7EDFF284602F020FD72 +:10420000204616B070BD0624F7E71124F8E7000039 +:1042100070B5B8B00222019003A901A8FEF766FCB0 +:10422000044608BB039B4FF48C60109302F0F8FC2B +:104230000546002866D0039B00F500720199D860FE +:1042400010A81A61FFF7BAFB044650B99DF88B30ED +:10425000980655D4190653D49DF84630DA0706D58A +:104260000724284602F0ECFC204638B070BD039BC2 +:1042700004931878042814D104A91869FFF780FB67 +:10428000069E9DF84630DB0610D410A8FEF776FF98 +:1042900004460028E5D156BB0398FEF7DBFB044635 +:1042A000DFE71F99FFF782FB0646EAE7039BDA691F +:1042B000B242D5D024930021269624A81B78042B43 +:1042C00001BFDDE90823CDE928239DF817308DF8DB +:1042D0009730FEF7EFF904460028C2D124A8FFF773 +:1042E00041F804460028BBD00428BAD1CDE70246E5 +:1042F000314604A8FEF7C2FA04460028B1D1CBE744 +:104300000624AEE71124AFE7F0B5BDB0CDE900104B +:104310006846FDF70FFF022203A901A8FEF7E6FB9E +:104320000446002841D1039B4FF48C60149302F0A3 +:1043300077FC0546002800F0EE80039B00F5007234 +:1043400014AE0199D8601A613046FFF737FB044676 +:1043500040BB9DF89B3013F0A00F40F0D880039B2A +:10436000009F1A78042A68D11B6904AC03F1400C41 +:104370001868083353F8041C2246634503C21446E8 +:10438000F6D15022314628A8FDF7B2FC394628A8BC +:10439000FFF714FB044600284CD12A9A169B9A4238 +:1043A00006D00824284602F04BFC20463DB0F0BD64 +:1043B000349A209B9A42F4D128A8FFF733F9044697 +:1043C0000028EFD1039B04AF1B6993F801E093F839 +:1043D00023C09C8C3A46083303CAB24243F8080C07 +:1043E00043F8041C1746F5D1039B28A81B6983F8E2 +:1043F00001E0039B1A6982F823C01A6982F82440FD +:10440000240A82F825401A691379D9065CBF43F063 +:1044100020031371FEF776FF04460028C2D1304610 +:10442000FEF7ACFE04460028BCD10398FEF712FB51 +:104430000446B7E70428B5D1BEE7239A04AB02F1DE +:10444000200C1068083252F8041C1C46624503C454 +:104450002346F6D15022314628A8FDF749FC3946BB +:1044600028A8FFF7ABFA044600284CD12A9A169BDD +:104470009A4296D1349A209B9A4292D128A8FFF76B +:10448000D1F8044600288DD137990DF11D030DF1A7 +:104490002D0001F10D0253F8044B834242F8044B06 +:1044A000F9D11888012710809B7893709DF81B30F4 +:1044B000039CDA0658BF43F02003CB72E770CB7A37 +:1044C000DB06ACD5169A2A9B9A42A8D02078FFF733 +:1044D0006DFA01462046FDF7EDFD0146C8B12046C4 +:1044E000FDF798FF044600287FF45CAF039890F82E +:1044F0006D302E2B93D12A9A00F16C01FDF7E6FD69 +:10450000039BDF708BE704287FF44CAFB6E70624EB +:1045100048E7022446E7112447E700007F2810B54A +:1045200001D880B210BDB0F5803F13D240F25233B3 +:1045300099420FD10849002231F8024B93B28442CC +:1045400003D103F18000C0B2ECE70132802AF3D13D +:104550001346F6E70020E5E7EC8E00087F280DD92A +:1045600040F25233994208D1FF2806D800F10040AA +:10457000034B803833F8100070470020704700BFAD +:10458000EC8E0008B0F5803FF0B522D21F4A83B20E +:104590001F49B0F5805F28BF0A46141D34F8042C6B +:1045A0002146AAB1934213D334F8025C2E0AEFB22B +:1045B00052FA85F5A84222DA082E09D8DFE806F07B +:1045C000050A10121416181A1C00801A34F810303C +:1045D0001846F0BD981A00F001001B1A9BB2F7E7CD +:1045E000103BFBE7203BF9E7303BF7E71A3BF5E7E9 +:1045F0000833F3E7503BF1E7A3F5E353EEE7043468 +:10460000002ECBD101EB4702C7E700BF3C8C00086E +:10461000308E000808B5074B074A196801F03D01C4 +:10462000996053680BB190689847BDE8084002F064 +:1046300027BD00BF000002401C36002008B5084B13 +:104640001968890901F03D018A019A60054AD36819 +:104650000BB110699847BDE8084002F011BD00BFDA +:10466000000002401C36002008B5084B1968090CF0 +:1046700001F03D010A049A60054A53690BB1906943 +:104680009847BDE8084002F0FBBC00BF00000240B4 +:104690001C36002008B5084B1968890D01F03D0152 +:1046A0008A059A60054AD3690BB1106A9847BDE83C +:1046B000084002F0E5BC00BF000002401C360020AC +:1046C00008B5074B074A596801F03D01D960536AA4 +:1046D0000BB1906A9847BDE8084002F0D1BC00BF1A +:1046E000000002401C36002008B5084B59688909B3 +:1046F00001F03D018A01DA60054AD36A0BB1106B03 +:104700009847BDE8084002F0BBBC00BF0000024073 +:104710001C36002008B5084B5968090C01F03D0112 +:104720000A04DA60054A536B0BB1906B9847BDE8F9 +:10473000084002F0A5BC00BF000002401C3600206B +:1047400008B5084B5968890D01F03D018A05DA600A +:10475000054AD36B0BB1106C9847BDE8084002F0D6 +:104760008FBC00BF000002401C36002008B5074B7C +:10477000074A196801F03D019960536C0BB1906CC8 +:104780009847BDE8084002F07BBC00BF000402402F +:104790001C36002008B5084B1968890901F03D0155 +:1047A0008A019A60054AD36C0BB1106D9847BDE839 +:1047B000084002F065BC00BF000402401C36002027 +:1047C00008B5084B1968090C01F03D010A049A600C +:1047D000054A536D0BB1906D9847BDE8084002F053 +:1047E0004FBC00BF000402401C36002008B5084B37 +:1047F0001968890D01F03D018A059A60054AD36D5B +:104800000BB1106E9847BDE8084002F039BC00BFFC +:10481000000402401C36002008B5074B074A5968BF +:1048200001F03D01D960536E0BB1906E9847BDE821 +:10483000084002F025BC00BF000402401C360020E6 +:1048400008B5084B5968890901F03D018A01DA6011 +:10485000054AD36E0BB1106F9847BDE8084002F0CF +:104860000FBC00BF000402401C36002008B5084BF6 +:104870005968090C01F03D010A04DA60054A536FDA +:104880000BB1906F9847BDE8084002F0F9BB00BF3C +:10489000000402401C36002008B5084B5968890DF9 +:1048A00001F03D018A05DA60054AD36F13B1D2F8F1 +:1048B00080009847BDE8084002F0E2BB00040240D7 +:1048C0001C36002000230C4910B51A460B4C0B6017 +:1048D00054F82300026001EB430004334260402B94 +:1048E000F6D1074A4FF0FF339360D360C2F8083423 +:1048F000C2F80C3410BD00BF1C360020EC8F00083D +:10490000000002400F28F8B510D9102810D0112847 +:1049100011D0122808D10F240720DFF8C8E00126A3 +:10492000DEF80050A04208D9002653E00446F4E720 +:104930000F240020F1E70724FBE706FA00F73D42C9 +:104940004AD1264C4FEA001C3D4304EB00160EEB07 +:10495000C000CEF80050C0E90123FBB273B120487B +:10496000D0F8D83043F00103C0F8D830D0F8003187 +:1049700043F00103C0F80031D0F8003117F47F4F45 +:104980000ED01748D0F8D83043F00203C0F8D83022 +:10499000D0F8003143F00203C0F80031D0F8003104 +:1049A00054F80C00036823F01F030360056815F03A +:1049B0000105FBD104EB0C033D2493F80CC05F68A8 +:1049C00004FA0CF43C6021240560446112B1987B28 +:1049D00000F04EFB3046F8BD0130A3E7EC8F000835 +:1049E000004402581C36002010B5302484F311888E +:1049F000FFF788FF002383F3118810BD10B504462C +:104A0000807B00F04BFB01231549627B03FA02F225 +:104A10000B6823EA0203DAB20B6072B9114AD2F8CA +:104A2000D81021F00101C2F8D810D2F8001121F0FD +:104A30000101C2F80011D2F8002113F47F4F0ED10A +:104A4000084BD3F8D82022F00202C3F8D820D3F8BC +:104A5000002122F00202C3F80021D3F8003110BD7A +:104A60001C3600200044025808B5302383F3118817 +:104A7000FFF7C4FF002383F3118808BD836CC26A6B +:104A80008B42506810B506D95A1E4C0002EB410308 +:104A9000B3FBF4F3184410BD01F001038A0748BFCB +:104AA00043F002034A0748BF43F008030A0748BF20 +:104AB00043F00403CA0648BF43F010038A06426B62 +:104AC00048BF43F0200313434363704710B5074CBE +:104AD000204600F0F3FC064B0022C4E91023054BEE +:104AE000A364054BE363054BE36410BDA0360020CF +:104AF0000070005200B4C404F4360020F4380020E2 +:104B0000C36A0BB9104BC3620379012B11D10F4B50 +:104B100098420ED10E4BD3F8D42042F48032C3F821 +:104B2000D420D3F8FC2042F48032C3F8FC20D3F820 +:104B3000FC30436C00221A65DA621A605A605A62CD +:104B40004FF0FF329A637047EC900008A0360020C7 +:104B5000004402580379012B1BD0436C00221A65D4 +:104B6000DA621A605A605A624FF0FF329A63094B58 +:104B700098420ED1084BD3F8D42022F48032C3F8E7 +:104B8000D420D3F8FC2022F48032C3F8FC20D3F8E0 +:104B9000FC307047A03600200044025810B5446C29 +:104BA0000649FFF76BFF6060236842F2107043F024 +:104BB00003032360BDE8104001F0F4B9801A060039 +:104BC0000129F8B5466C0B4F09D175680A493D407B +:104BD000FFF754FF054345F480557560F8BD7468D0 +:104BE00006493C40FFF74AFF044344F48054746094 +:104BF000F4E700BF00ECFFFF80F0FA0240787D018F +:104C0000436C00225A601A6070470000426C012910 +:104C1000536823F4404304D0022905D001B95360FE +:104C2000704743F48043FAE743F40043F7E700009A +:104C3000436C41F480519A60D9605A6B1206FCD5DE +:104C400080229A637047000010B541F48851446C8B +:104C5000A260E160616B11F04502FBD0A26311F02C +:104C6000040203D0FFF718FF012010BD6169104650 +:104C70001960FAE710B541F48851446CA260E16014 +:104C8000616B11F04502FBD0A26311F0050203D065 +:104C9000FFF702FF012010BD616910461960FAE7B5 +:104CA00073B5134604460E46302282F31188426CD7 +:104CB000D26B32B14FF0FF314030019301F07EF9F9 +:104CC000019B606C00220265C263C262456B15F4F1 +:104CD000807504D185F31188012002B070BD4FF0BA +:104CE000FF31816382F31188012E06D90C21204601 +:104CF00002B0BDE87040FFF7BDBF1046EDE7000011 +:104D000073B5446C0E4600250192616BA163256565 +:104D1000E562FFF7C1FE012E07D9019B2A460C214F +:104D200002B0BDE87040FFF7A5BF02B070BD000043 +:104D300010B541F49851446CA260E160616B11F0D0 +:104D40004502FBD0A26311F03F0203D0FFF7A4FE9F +:104D5000012010BD216A10461960E1695960A169FE +:104D600099606169D960F4E72DE9F7430446019140 +:104D7000006D01A91746984602F0AAF806460028D9 +:104D80004AD0626C2046DDF804905568C5F30905E9 +:104D900001356B00A56CB5FBF3F54FF47A73B5FBE9 +:104DA000F3F55D43556200F04FFB50BB636C4FF071 +:104DB000FF3201254146C3F8589020461D659A638D +:104DC0004FF49572DA6342F207029F62DA62E36C93 +:104DD0000A9AFFF74FFFA0B9E26C104B11680B4025 +:104DE0007BB929462046FFF75BFF054648B92E46AA +:104DF0003A460199206D02F0A3F8304603B0BDE8B1 +:104E0000F0833A460199206D02F09AF8E26C012194 +:104E10002046FFF775FFF0E70126EEE708E0FFFD0B +:104E20002DE9F7431F46436C01924FF47A725D6897 +:104E300004468846C5F3090501356E00856CB5FB4F +:104E4000F6F5B5FBF2F555435D6200F0FDFA20B1D1 +:104E50000125284603B0BDE8F0837E0201A9206D3C +:104E6000324602F035F805460028F1D0636C019A0D +:104E7000D4F84C909A6501221A654FF0FF329A637C +:104E80004FF49572DA639E62236BDB064B4658BF84 +:104E90004FEA4828012F42461BD912212046FFF72E +:104EA000E9FEC0B9D9F80020104B13409BB9636CE0 +:104EB00042F2930239462046DA62E26CFFF7F0FED6 +:104EC000804640B932460199206D454602F038F8D7 +:104ED000BFE71121E2E732460199206D02F030F878 +:104EE000E26C39462046FFF70BFFB2E708E0FFFD12 +:104EF0002DE9F3411F46436C01924FF47A725D68CD +:104F000004468846C5F3090501356E00856CB5FB7E +:104F1000F6F5B5FBF2F555435D6200F095FA20B168 +:104F20000125284602B0BDE8F0817E0201A9206D6E +:104F3000324602F013F805460028F1D0636C019A5E +:104F40009A6501221A654FF0FF329A634FF48D7211 +:104F5000DA639E62236BE66CDB06334658BF4FEA8A +:104F60004828012F424619D919212046FFF782FE11 +:104F7000B0B932680F4B134093B9636C42F291029F +:104F800039462046DA62E26CFFF78AFE064638B9F7 +:104F900001993546206D02F01DF8C2E71821E4E7BB +:104FA0000199206D02F016F8E26C39462046FFF7B1 +:104FB000A7FEB6E708E0FFFD12F0030F2DE9F04170 +:104FC00007460C4615461E4617D00E44B44202D181 +:104FD0000020BDE8F0810123FA6B21463846FFF737 +:104FE0001FFF0028F5D128464FF40072F96B05F534 +:104FF00000750134FCF77CFEE8E7BDE8F041FFF7FF +:105000000FBF000012F0030F2DE9F04107460C46D8 +:1050100015461E4617D00E44B44202D10020BDE80A +:10502000F08129464FF40072F86B05F50075FCF726 +:105030005FFE0123FA6B21463846FFF759FF00282F +:10504000EDD10134E8E7BDE8F041FFF751BF0000C2 +:1050500000207047302310B583F311880024436C7F +:1050600040302146DC6300F0B7FF84F3118810BDA7 +:10507000090100F16043012203F56143C9B283F8DD +:10508000001300F01F039A4043099B0003F16043A3 +:1050900003F56143C3F880211A60704700F01F03D5 +:1050A00001229A40430900F160409B0000F56140F5 +:1050B00003F1604303F56143C3F88020C3F8802106 +:1050C000002380F8003370470379052B05BF836AFE +:1050D000002001204B6004BF4FF400730B60704749 +:1050E00070B55D1E866A04460D44B54205D9436B12 +:1050F00043F080034363012070BD06250571FFF76F +:105100005BFF05232371F7E770B55D1E866A0446D1 +:105110000D44B54205D9436B43F08003436301203E +:1051200070BD07250571FFF76DFF05232371F7E7B4 +:1051300038B505790446052D05D108230371FFF71D +:1051400087FF257138BD0120FCE700000323F0B57F +:10515000037185B00446FFF721FD00222046114669 +:10516000FFF766FD4FF4D57203AB08212046FFF729 +:1051700081FD0246B8B901232363039BC3F30323D4 +:10518000012B09D103AB37212046FFF773FD18B976 +:10519000A44B039A1340ABB120460125FFF730FD25 +:1051A0000223237137E103AB002237212046FFF7AA +:1051B00061FD28B99B4A039B1A40002A00F0A78092 +:1051C00002232363236B03F00F03022B40F0A9801B +:1051D0006425954E42F2107000F0E4FE03AB3246B7 +:1051E00001212046FFF730FD0028D5D1039B002B7D +:1051F00080F293805A0003D5236B43F0100323639E +:10520000002204F1080302212046FFF791FD024627 +:105210000028C1D104F1380303212046FFF72AFDFD +:105220000028B9D104F11805A26B092120462B46AC +:10523000FFF77EFD0028AFD102ABA26B072120460D +:10524000FFF718FD06460028A6D1236B03F00F03D5 +:10525000022B40F08F807E227F21284603F052F9F6 +:10526000012840F28780E76B42F2107000F09AFE4E +:1052700008234FF40072394620460096FFF774FD6C +:10528000002889D1384603F08BF9236BA06203F024 +:105290000F03022B72D103AB644A06212046FFF7AD +:1052A000E9FC002871D15F49039B1940B1FA81F1F3 +:1052B00049092046FFF784FC02AB4FF4007210212D +:1052C0002046FFF7D7FC054600287FF465AF554E12 +:1052D000029B33427FF460AF236B13F00E0F03F099 +:1052E0000F0273D0022A7FF457AFE36A19780129BD +:1052F00000F09480022900F09380002900F089805A +:105300004B4F2046FFF782FC03AB3A4676E011464E +:1053100020462263FFF78CFC54E7013D7FF45AAF2F +:105320003AE7444D6426444A3E4F012B18BF1546C8 +:1053300003AB002237212046FFF79CFC00287FF4B6 +:105340002BAF039B3B427FF427AF03AB2A462921B7 +:105350002046FFF779FC00287FF41EAF039B002B4B +:10536000FFF648AF013E3FF417AF42F2107000F075 +:1053700019FEDDE7284603F0E7F886E77E227F2165 +:105380002846E66B03F0BEF808B9002191E7002338 +:1053900040223146204600930623FFF7E5FC002813 +:1053A000F3D1B3895BBA9B07EFD5244B402231463A +:1053B000204600930623FFF7D7FC0028E5D1317C77 +:1053C00001F00F010F3918BF012172E7E36A197864 +:1053D000F9B101297FF4E0AE2046FFF717FC03ABDB +:1053E000A26B37212046FFF745FC00287FF4D4AE9E +:1053F000039B33427FF4D0AE03AB0222062120464A +:10540000FFF738FC00287FF4C7AE039B33427FF4DC +:10541000C3AE05232371284605B0F0BD084F70E7E1 +:10542000084F6EE708E0FFFD0080FFC00001B903F0 +:105430000000B7030080FF5000001080F1FFFF80E4 +:105440000001B7030002B70337B504460C4D01ABAA +:10545000A26B0D212046FFF70DFC78B9019B2B4272 +:105460000BD1C3F34323042B08D0053B022B04D8F4 +:105470004FF47A7000F096FDE9E7012003B030BDEB +:1054800008E0FFFD70B53023054683F311880379EA +:105490000024022B03D184F31188204670BD04231D +:1054A000037184F311880226FFF7CEFF04462846D5 +:1054B000FFF7A6FB2E71F0E7FFF708BB044B036074 +:1054C0000123037100234363C0E90A33704700BF1F +:1054D000F490000810B53023044683F31188C162AC +:1054E000FFF70EFB02230020237180F3118810BD0B +:1054F00010B53023044683F31188FFF72BFB0023FC +:105500000122E362227183F3118810BD02684368AF +:105510001143016003B118477047000013B5406B99 +:1055200000F58054D4F8A4381A681178042914D1ED +:10553000017C022911D11979012312898B40134270 +:105540000BD101A94C3002F00BFFD4F8A44802465D +:10555000019B2179206800F0DFF902B010BD000046 +:10556000143002F08DBE00004FF0FF33143002F013 +:1055700087BE00004C3002F05FBF00004FF0FF33E9 +:105580004C3002F059BF0000143002F05BBE000046 +:105590004FF0FF31143002F055BE00004C3002F0E5 +:1055A0002BBF00004FF0FF324C3002F025BF00004F +:1055B0000020704710B500F58054D4F8A4381A685C +:1055C0001178042917D1017C022914D159790123BA +:1055D00052898B4013420ED1143002F0EDFD024689 +:1055E00048B1D4F8A4484FF4407361792068BDE80D +:1055F000104000F07FB910BD406BFFF7DBBF00002B +:10560000704700007FB5124B012504260446036055 +:105610000023057400F1840243602946C0E9023387 +:105620000C4B0290143001934FF44073009602F03B +:105630009FFD094B04F69442294604F14C00029464 +:10564000CDE900634FF4407302F066FE04B070BD14 +:1056500018910008F95500081D5500080A68302304 +:1056600083F311880B790B3342F823004B79133302 +:1056700042F823008B7913B10B3342F8230000F575 +:105680008053C3F8A41802230374002080F3118808 +:105690007047000038B5037F044613B190F85430CA +:1056A000ABB90125201D0221FFF730FF04F11400E2 +:1056B0006FF00101257700F0B5FC04F14C0084F88F +:1056C00054506FF00101BDE8384000F0ABBC38BD6C +:1056D00010B5012104460430FFF718FF002323779B +:1056E00084F8543010BD000038B50446002514304D +:1056F00002F056FD04F14C00257702F025FE201D36 +:1057000084F854500121FFF701FF2046BDE83840DE +:10571000FFF750BF90F8803003F06003202B06D1D4 +:1057200090F881200023212A03D81F2A06D80020C0 +:105730007047222AFBD1C0E91D3303E0034A4267C8 +:1057400007228267C3670120704700BF3422002010 +:1057500037B500F58055D5F8A4381A6811780429B2 +:105760001AD1017C022917D11979012312898B40A2 +:10577000134211D100F14C04204602F0A5FE58B1AD +:1057800001A9204602F0ECFDD5F8A4480246019B91 +:105790002179206800F0C0F803B030BD01F10B039F +:1057A000F0B550F8236085B004460D46FEB13023B5 +:1057B00083F3118804EB8507301D0821FFF7A6FE4F +:1057C000FB6806F14C005B691B681BB1019002F09D +:1057D000D5FD019803A902F0C3FD024648B1039B21 +:1057E0002946204600F098F8002383F3118805B07D +:1057F000F0BDFB685A691268002AF5D01B8A013B8C +:105800001340F1D104F18002EAE70000133138B50A +:1058100050F82140ECB1302383F3118804F5805314 +:10582000D3F8A4281368527903EB8203DB689B69E1 +:105830005D6845B104216018FFF768FE294604F150 +:10584000140002F0C3FC2046FFF7B4FE002383F3EC +:10585000118838BD7047000001F010BD01234022BF +:10586000002110B5044600F8303BFCF767FA00232E +:10587000C4E9013310BD000010B53023044683F3A2 +:1058800011882422416000210C30FCF757FA204691 +:1058900001F016FD02230020237080F3118810BD53 +:1058A00070B500EB8103054650690E461446DA6078 +:1058B00018B110220021FCF741FAA06918B110229A +:1058C0000021FCF73BFA31462846BDE8704001F064 +:1058D000FDBD000083682022002103F0011310B5F4 +:1058E000044683601030FCF729FA2046BDE81040DA +:1058F00001F078BEF0B4012500EB810447898D40AA +:10590000E4683D43A469458123600023A26063608D +:10591000F0BC01F095BE0000F0B4012500EB81045D +:1059200007898D40E4683D43646905812360002355 +:10593000A2606360F0BC01F00BBF000070B50223F1 +:1059400000250446242203702946C0F888500C30F4 +:1059500040F8045CFCF7F2F9204684F8705001F03E +:1059600049FD63681B6823B129462046BDE87040A5 +:10597000184770BD0378052B10B504460AD080F88F +:105980008C300523037043681B680BB104219847D2 +:105990000023A36010BD00000178052906D190F80E +:1059A0008C20436802701B6803B1184770470000E1 +:1059B00070B590F87030044613B1002380F8703051 +:1059C00004F18002204601F031FE63689B68B3B9A0 +:1059D00094F8803013F0600535D00021204602F0A5 +:1059E00023F90021204602F013F963681B6813B104 +:1059F000062120469847062384F8703070BD204663 +:105A000098470028E4D0B4F88630A26F9A4288BF45 +:105A1000A36794F98030A56F002B4FF0300380F21C +:105A20000381002D00F0F280092284F8702083F3B6 +:105A3000118800212046D4E91D23FFF76DFF0023C4 +:105A400083F31188DAE794F8812003F07F0343EAB7 +:105A5000022340F20232934200F0C58021D8B3F510 +:105A6000807F48D00DD8012B3FD0022B00F09380CF +:105A7000002BB2D104F1880262670222A267E367B9 +:105A8000C1E7B3F5817F00F09B80B3F5407FA4D1DF +:105A900094F88230012BA0D1B4F8883043F002038F +:105AA00032E0B3F5006F4DD017D8B3F5A06F31D009 +:105AB000A3F5C063012B90D86368204694F8822038 +:105AC0005E6894F88310B4F88430B047002884D01E +:105AD000436863670368A3671AE0B3F5106F36D0B5 +:105AE00040F6024293427FF478AF5C4B6367022337 +:105AF000A3670023C3E794F88230012B7FF46DAFD6 +:105B0000B4F8883023F00203A4F88830C4E91D55A6 +:105B1000E56778E7B4F88030B3F5A06F0ED194F85C +:105B20008230204684F88A3001F0C2FC63681B682A +:105B300013B1012120469847032323700023C4E9B1 +:105B40001D339CE704F18B0363670123C3E72378CC +:105B5000042B10D1302383F311882046FFF7BAFEBF +:105B600085F311880321636884F88B5021701B68CA +:105B70000BB12046984794F88230002BDED084F891 +:105B80008B300423237063681B68002BD6D002215E +:105B900020469847D2E794F8843020461D0603F04B +:105BA0000F010AD501F034FD012804D002287FF44A +:105BB00014AF2B4B9AE72B4B98E701F01BFDF3E753 +:105BC00094F88230002B7FF408AF94F8843013F0FF +:105BD0000F01B3D01A06204602D502F03DF8ADE71A +:105BE00002F02EF8AAE794F88230002B7FF4F5AE8D +:105BF00094F8843013F00F01A0D01B06204602D584 +:105C000002F012F89AE702F003F897E7142284F8FA +:105C1000702083F311882B462A4629462046FFF739 +:105C200069FE85F31188E9E65DB1152284F87020DC +:105C300083F3118800212046D4E91D23FFF75AFE83 +:105C4000FDE60B2284F8702083F311882B462A4648 +:105C500029462046FFF760FEE3E700BF48910008B1 +:105C6000409100084491000838B590F8703004461F +:105C7000002B3ED0063BDAB20F2A34D80F2B32D895 +:105C8000DFE803F03731310822323131313131313F +:105C900031313737856FB0F886309D4214D2C368F2 +:105CA0001B8AB5FBF3F203FB12556DB9302383F366 +:105CB00011882B462A462946FFF72EFE85F31188C8 +:105CC0000A2384F870300EE0142384F870303023F7 +:105CD00083F31188002320461A461946FFF70AFE6F +:105CE000002383F3118838BDC36F03B198470023A5 +:105CF000E7E70021204601F097FF0021204601F050 +:105D000087FF63681B6813B1062120469847062366 +:105D1000D7E7000010B590F870300446142B29D056 +:105D200017D8062B05D001D81BB110BD093B022B9B +:105D3000FBD80021204601F077FF0021204601F02A +:105D400067FF63681B6813B1062120469847062346 +:105D500019E0152BE9D10B2380F87030302383F341 +:105D6000118800231A461946FFF7D6FD002383F356 +:105D70001188DAE7C3689B695B68002BD5D1C36FD4 +:105D800003B19847002384F87030CEE7002382687F +:105D9000037503691B6899689142FBD25A680360D6 +:105DA0004260106058607047002382680375036981 +:105DB0001B6899689142FBD85A6803604260106082 +:105DC0005860704708B50846302383F311880A7D70 +:105DD0000023052A06D8DFE802F00B050503120EA2 +:105DE000826913604FF0FF338361FFF7CFFF002319 +:105DF00083F3118808BD8269936801339360D0E909 +:105E0000003213605A60EDE7FFF7C0BF054BD96859 +:105E100008751868026853601A600122D86002751C +:105E2000FAF7F0BAF83800200C4B30B5DD684B1C9F +:105E300087B004460FD02B46094A684600F086F921 +:105E40002046FFF7E3FF009B13B1684600F088F996 +:105E5000A86907B030BDFFF7D9FFF9E7F83800208F +:105E6000C55D000838B50C4D04468161EB6881685A +:105E70009A68914203D8BDE83840FFF787BF1846BB +:105E8000FFF792FF01230146EC6020462375BDE831 +:105E90003840FAF7B7BA00BFF8380020044B1A6848 +:105EA000DB6890689B68984294BF0020012070478F +:105EB000F8380020084B10B51C68D8682268536079 +:105EC0001A600122DC602275FFF76EFF0146204652 +:105ED000BDE81040FAF796BAF838002038B501232B +:105EE000084C00252370656002F088FB02F0AEFBD1 +:105EF0000549064802F082FC0223237085F31188CD +:105F000038BD00BF603B002050910008F8380020E9 +:105F100000F05CB9034A516853685B1A9842FBD899 +:105F2000704700BF001000E08B6002230861084644 +:105F30008B8270478368A3F1840243F8142C0269B2 +:105F400043F8442C426943F8402C094A43F8242C76 +:105F5000C268A3F1200043F8182C022203F80C2C8D +:105F6000002203F80B2C034A43F8102C704700BFA3 +:105F70001D040008F838002008B5FFF7DBFFBDE876 +:105F80000840FFF741BF0000024BDB6898610F201B +:105F9000FFF73CBFF8380020302383F31188FFF768 +:105FA000F3BF000008B50146302383F311880820B1 +:105FB000FFF73AFF002383F3118808BD054BDB6828 +:105FC00021B1036098610320FFF72EBF4FF0FF302F +:105FD000704700BFF838002003682BB10022026030 +:105FE00018469961FFF710BF70470000064BDB6849 +:105FF00039B1426818605A60136043600420FFF7AB +:1060000013BF4FF0FF307047F83800200368984204 +:1060100006D01A680260506018469961FFF7F4BE16 +:106020007047000038B504460D462068844200D110 +:1060300038BD036823605C608561FFF7E5FEF4E727 +:10604000036810B59C68A2420CD85C688A600B603B +:106050004C602160596099688A1A9A604FF0FF334A +:10606000836010BD121B1B68ECE700000A2938BFD3 +:106070000A2170B504460D460A26601902F0B8FAE6 +:1060800002F0A0FA041BA54203D8751C04462E4654 +:10609000F3E70A2E04D90120BDE8704002F0EEBB00 +:1060A00070BD0000F8B5144B0D460A2A4FF00A07E0 +:1060B000D96103F11001826038BF0A224160196979 +:1060C0001446016048601861A81802F081FA02F0D5 +:1060D00079FA431B0646A34206D37C1C281927469F +:1060E000354602F085FAF2E70A2F04D90120BDE80F +:1060F000F84002F0C3BBF8BDF8380020F8B50646FA +:106100000D4602F05FFA0F4A134653F8107F9F4284 +:1061100006D12A4601463046BDE8F840FFF7C2BF27 +:10612000D169BB68441A2C1928BF2C46A34202D956 +:106130002946FFF79BFF224631460348BDE8F84059 +:10614000FFF77EBFF838002008390020C0E903239C +:10615000002310B45DF8044B4361FFF7CFBF00008C +:1061600010B5194C236998420DD08168D0E90032EE +:1061700013605A609A680A449A60002303604FF0E3 +:10618000FF33A36110BD0268234643F8102F53600C +:106190000022026022699A4203D1BDE8104002F059 +:1061A00021BA936881680B44936002F00BFA22696C +:1061B000E1699268441AA242E4D91144BDE8104052 +:1061C000091AFFF753BF00BFF83800202DE9F04748 +:1061D000DFF8BC8008F110072C4ED8F8105002F000 +:1061E000F1F9D8F81C40AA68031B9A423ED814441F +:1061F0004FF00009D5E90032C8F81C4013605A601E +:10620000C5F80090D8F81030B34201D102F0EAF995 +:1062100089F31188D5E9033128469847302383F361 +:1062200011886B69002BD8D002F0CCF96A69A0EB19 +:10623000040982464A450DD2022002F01FFB0022CB +:10624000D8F81030B34208D151462846BDE8F0478F +:10625000FFF728BF121A2244F2E712EB0909294678 +:10626000384638BF4A46FFF7EBFEB5E7D8F810309E +:10627000B34208D01444C8F81C00211AA960BDE834 +:10628000F047FFF7F3BEBDE8F08700BF08390020F4 +:10629000F838002038B502F095F9054AD2E90845EA +:1062A000031B181945F10001C2E9080138BD00BF00 +:1062B000F838002010B560B9074804790368053C38 +:1062C0009B6818BF0124984708B144F00404204695 +:1062D00010BD0124FBE700BFA0360020FFF7EABF96 +:1062E0002DE9F047884617469A460446B0B90D4E48 +:1062F0003579052D05D003240DE0013D15F0FF058E +:106300000ED03268534639463046D2F81490424691 +:10631000C8470028F1D12046BDE8F0870424FAE7F9 +:106320000124F8E7A03600202DE9F04788461746FB +:106330009A460446B0B90D4E3579052D05D0032493 +:106340000DE0013D15F0FF050ED032685346394689 +:106350003046D2F818904246C8470028F1D120466E +:10636000BDE8F0870424FAE70124F8E7A03600200E +:1063700037B50C46154670B951B101290BD1074804 +:10638000694603681B6A984710B9019B04462B6055 +:10639000204603B030BD0424FAE700BFA036002039 +:1063A00000207047FEE70000704700004FF0FF300C +:1063B000704700004B6843608B688360CB68C360A4 +:1063C0000B6943614B6903628B6943620B6803602D +:1063D0007047000008B53C4B40F2FF713B48D3F8D2 +:1063E00088200A43C3F88820D3F8882022F4FF626B +:1063F00022F00702C3F88820D3F88820D3F8E020E1 +:106400000A43C3F8E020D3F808210A43C3F808215F +:106410002F4AD3F808311146FFF7CCFF00F5806012 +:1064200002F11C01FFF7C6FF00F5806002F13801A0 +:10643000FFF7C0FF00F5806002F15401FFF7BAFFDB +:1064400000F5806002F17001FFF7B4FF00F5806095 +:1064500002F18C01FFF7AEFF00F5806002F1A801A8 +:10646000FFF7A8FF00F5806002F1C401FFF7A2FF6B +:1064700000F5806002F1E001FFF79CFF00F580600D +:1064800002F1FC01FFF796FF02F58C7100F58060C8 +:10649000FFF790FF01F078FC0E4BD3F8902242F00A +:1064A0000102C3F89022D3F8942242F00102C3F80B +:1064B00094220522C3F898204FF06052C3F89C2024 +:1064C000054AC3F8A02008BD004402580000025845 +:1064D0005C91000800ED00E01F00080308B501F022 +:1064E00035FEFFF7FBFC104BD3F8DC2042F04002F6 +:1064F000C3F8DC20D3F8042122F04002C3F80421C1 +:10650000D3F80431094B1A6842F008021A601A687D +:1065100042F004021A6000F065FD00F045FBBDE8A2 +:10652000084000F0B5B800BF004402580018024807 +:1065300001207047002070477047000002290CD0EE +:10654000032904D00129074818BF00207047032AF7 +:1065500005D8054800EBC20070470448704700208A +:10656000704700BF5C93000844220020109300088D +:1065700070B59AB005460846144601A900F0C2F865 +:1065800001A8FBF7D3FB431C0022C6B25B001046F8 +:10659000C5E9003423700323023404F8013C01AB45 +:1065A000D1B202348E4201D81AB070BD13F8011B6B +:1065B000013204F8010C04F8021CF1E708B530239D +:1065C00083F311880348FFF7C3F8002383F311888E +:1065D00008BD00BF683B002090F8803003F01F0228 +:1065E000012A07D190F881200B2A03D10023C0E9AA +:1065F0001D3315E003F06003202B08D1B0F8843080 +:106600002BB990F88120212A03D81F2A04D8FFF73C +:1066100081B8222AEBD0FAE7034A42670722826751 +:10662000C3670120704700BF3B22002007B5052942 +:1066300017D8DFE801F0191603191920302383F366 +:106640001188104A01210190FFF72AF901980221CF +:106650000D4AFFF725F90D48FFF746F8002383F3AD +:10666000118803B05DF804FB302383F311880748D9 +:10667000FFF710F8F2E7302383F311880348FFF7A0 +:1066800027F8EBE7B0920008D4920008683B00209E +:1066900038B50C4D0C4C2A460C4904F10800FFF7A4 +:1066A00067FF05F1CA0204F110000949FFF760FF16 +:1066B00005F5CA7204F118000649BDE83840FFF735 +:1066C00057BF00BF40540020442200209092000891 +:1066D0009A920008A592000870B5044608460D4637 +:1066E000FBF724FBC6B22046013403780BB91846E9 +:1066F00070BD32462946FBF705FB0028F3D1012087 +:10670000F6E700002DE9F84F05460C46FBF70EFBB7 +:106710002D49C6B22846FFF7DFFF08B10436F6B2AE +:106720002A492846FFF7D8FF08B11036F6B2632E83 +:106730000DD8DFF89490DFF894A0DFF89C80DFF8A4 +:106740009CB0234F2E7846B92670BDE8F88F2946B5 +:106750002046BDE8F84F02F077B9252E30D1072248 +:1067600049462846FBF7CEFA70B93B6807350B342B +:1067700044F80B3C7B6844F8073C3B8924F8033C15 +:10678000BB7A04F8013CDDE7082251462846FBF7B6 +:10679000B9FAA8B9A21C0F4B19780232090911F8ED +:1067A000081002F8041C13F8011B01F00F015B45EF +:1067B00011F8081002F8031CEED118340835C1E7AF +:1067C000013504F8016BBDE77C930008A592000831 +:1067D0008493000800E8F11F909300080CE8F11F73 +:1067E000BFF34F8F044B1A695107FCD1D3F8102126 +:1067F0005207F8D1704700BF0020005208B50D4B7A +:106800001B78ABB9FFF7ECFF0B4BDA68D10704D567 +:106810000A4A5A6002F188325A60D3F80C21D20732 +:1068200006D5064AC3F8042102F18832C3F80421D0 +:1068300008BD00BF9E56002000200052230167457E +:1068400008B5114B1B78F3B9104B1A69510703D5E2 +:10685000DA6842F04002DA60D3F81021520705D519 +:10686000D3F80C2142F04002C3F80C21FFF7B8FF27 +:10687000064BDA6842F00102DA60D3F80C2142F0EC +:106880000102C3F80C2108BD9E56002000200052D2 +:106890000F289ABF00F58060400400207047000078 +:1068A0004FF4003070470000102070470F2808B5E3 +:1068B0000BD8FFF7EDFF00F500330268013204D179 +:1068C00004308342F9D1012008BD0020FCE700001C +:1068D0000F2838B505463FD8FFF782FF1F4CFFF75A +:1068E0008DFF4FF0FF3307286361C4F814311DD8C2 +:1068F0002361FFF775FF030243F02403E360E368BD +:1069000043F08003E36023695A07FCD42846FFF76D +:1069100067FFFFF7BDFF4FF4003100F09DFA2846F6 +:10692000FFF78EFFBDE83840FFF7C0BFC4F8103155 +:10693000FFF756FFA0F108031B0243F02403C4F83D +:106940000C31D4F80C3143F08003C4F80C31D4F886 +:1069500010315B07FBD4D9E7002038BD002000527E +:106960002DE9F84F04460D46104644EA0203DE06C0 +:1069700002D00020BDE8F88F20F01F00DFF8D4B06F +:10698000DFF8D4A0FFF73AFF05EB0008454503D137 +:106990000120FFF755FFEDE720222946204602F0AF +:1069A0001BF810B920342035F0E7234604F120020B +:1069B0001F68791CDDD104339342F9D104F1784387 +:1069C0002048214EB3F5801F204B38BF184603F1F5 +:1069D000F80332BFD946D1461E46FFF701FF0760D4 +:1069E000A4EB050C336805F11C0143F0020333608E +:1069F0002B1FD9F8007017F00507FAD153F8042FB0 +:106A00008B424CF80320F4D1BFF34F8FFFF7E8FE21 +:106A10004FF0FF330360336823F002033360BFF3AA +:106A20004F8F0B4BC3F85C42BFF34F8FBFF36F8F99 +:106A300020222946204601F0CFFF0028B2D0384658 +:106A4000A7E700BF142100520C200052142000526E +:106A500000ED00E0102000521021005210B5084C4B +:106A6000237828B11BB9FFF7C9FE0123237010BD9D +:106A7000002BFCD02070BDE81040FFF7E1BE00BF46 +:106A80009E5600202DE9F04F0D4685B0814658B145 +:106A900011F00D0614BF2022082211F00803019303 +:106AA00004D0431E03426AD0002435E0002E37D0C4 +:106AB00009F11F0121F01F094FF00108324F05F0C5 +:106AC0000403DFF8D0A005EA080BBBF1000F32D0B9 +:106AD0007869C0072FD408F101080C37B8F1060F08 +:106AE000F3D19EB9294D4946A819019201F0D0FD74 +:106AF000044600283AD11836019A782EF3D1494637 +:106B000001F0C6FD0446002830D1019A49462048CC +:106B100001F0BEFD044668BB204605B0BDE8F08F1D +:106B20000029C9D101462846029201F0B1FD044670 +:106B3000E0B9029AC0E713B178694107CBD5AC0739 +:106B400002D578698007C6D5019911B17869010726 +:106B5000C1D51820494600FB08A0CDE9022301F069 +:106B600097FD0446DDE902230028B4D04A460021FF +:106B7000204601E04A460021FBF7E0F8CCE7024658 +:106B8000002E95D198E700BFA4930008D0560020AE +:106B9000A0560020B85600200021FFF773BF000068 +:106BA0000121FFF76FBF0000F8B5144D012418272D +:106BB000134E40F2FF3200210120FBF7BFF807FB24 +:106BC000046001342A6955F80C1F01F04DFD062CB4 +:106BD000F5D137254FF4C0542046FFF7E1FF0146B9 +:106BE00028B122460748BDE8F84001F03DBDC4EB9E +:106BF000C404013D4FEAD404EED1F8BDA4930008CB +:106C0000B8560020A05600200421FFF73BBF00002B +:106C10004843FFF7C1BF000008B101F0ABBD7047AA +:106C2000B0F5805F10B5044607D8FFF7EDFF28B92F +:106C30002046BDE81040FFF7AFBF002010BD0000A8 +:106C4000FFF7EABF70B5AAB140EA010313F01F03D2 +:106C50000FD1094C0144A5686D0706D52568A842E7 +:106C600003D366683544A94204D903330C34122B8C +:106C7000F1D10022104670BDA493000808B501F0C0 +:106C800041FE034AD2E90032C01842EB010108BDBF +:106C900048570020434BD3E900232DE9F341134328 +:106CA0007CD0FFF7EBFF404A00230027F9F7C4FB35 +:106CB00006460D463D4A0023F9F7BEFB0023144665 +:106CC00030462946394AF9F7B7FB4FF461613C2356 +:106CD000ADF80170B4FBF1F5B4FBF3F601FB15411F +:106CE00003FB16464624B1FBF3F1314BF6B28DF8A7 +:106CF000004098423CD84FF0640C4FF4C87EA30784 +:106D000004F26C7225D1B2FBFCF30CFB132313BB12 +:106D1000B2FBFEF30EFB1322B2FA82F35B0903F21D +:106D20006D18621C8045D2B217D90FB18DF80040A2 +:106D30000022204C4FF00C0C17460CFB0343D4B23E +:106D4000013213F804C084450CD8A0EB0C000127D5 +:106D5000F5E70023E3E70123E1E7A0EB0800144691 +:106D60000127CCE70FB18DF80140431C8DF80230AC +:106D70009DF80100431C9DF800005038400640EA91 +:106D800043509DF8023040EA034040EA560040EA92 +:106D9000C52040EA411002B0BDE8F0814FF4041074 +:106DA000F9E700BF4857002040420F008051010022 +:106DB00090230B00EC9300080244074BD2B210B5AD +:106DC000904200D110BD441C00B253F8200041F89D +:106DD000040BE0B2F4E700BF504000580E4B30B552 +:106DE0001C6F240405D41C6F1C671C6F44F4004402 +:106DF0001C670A4C02442368D2B243F480732360B8 +:106E0000074B904200D130BD441C51F8045B00B2E6 +:106E100043F82050E0B2F4E700440258004802581A +:106E20005040005807B5012201A90020FFF7C4FF18 +:106E3000019803B05DF804FB13B50446FFF7F2FFB9 +:106E4000A04205D0012201A900200194FFF7C6FF4E +:106E500002B010BD704700000144BFF34F8F064BD6 +:106E6000884204D3BFF34F8FBFF36F8F7047C3F8CF +:106E70005C022030F4E700BF00ED00E00144BFF306 +:106E80004F8F064B884204D3BFF34F8FBFF36F8FF2 +:106E90007047C3F870022030F4E700BF00ED00E057 +:106EA00070B5054616460C4601201021FFF7B0FECE +:106EB000286046733CB1204636B1FFF7A5FE2B682B +:106EC000186000B19C6070BDFFF76AFEF7E7000034 +:106ED000F8B50F461546044648B905F11F010126CD +:106EE000386821F01F01FFF7B7FF3046F8BD427B3D +:106EF00029463868FFF7A6FE06460028EDD13B6814 +:106F00006360A368AB4210D213B12068FFF784FE20 +:106F1000637B28462BB1FFF777FE206020B9A06085 +:106F2000E3E7FFF73DFEF8E7A560206805F11F01E4 +:106F3000012621F01F013860FFF78EFF2673D4E78A +:106F400010B5044640B10068884205D1606808B1B8 +:106F5000FAF7CEFE0023237310BD0000F8B50F46EC +:106F60001446054648B904F11F010126386821F08E +:106F70001F01FFF783FF3046F8BD427B214638688A +:106F8000FFF760FE06460028EDD1AB68A34210D2A1 +:106F900013B12868FFF740FE6B7B20462BB1FFF74B +:106FA00033FE286020B9A860E5E7FFF7F9FDF8E7B0 +:106FB000AC60396819B122462868FAF799FE28684A +:106FC00004F11F01012621F01F013860FFF756FF71 +:106FD0002E73D0E720B103688B4204BF00230373F4 +:106FE00070470000034B1A681AB9034AD2F8D0243C +:106FF0001A607047505700200040025808B5FFF74C +:10700000F1FF024B1868C0F3806008BD50570020A4 +:10701000EFF30983054968334A6B22F001024A63A2 +:1070200083F30988002383F31188704700EF00E0A1 +:10703000302080F3118862B60D4B0E4AD96821F4D6 +:10704000E0610904090C0A430B49DA60D3F8FC201B +:1070500042F08072C3F8FC20084AC2F8B01F1168E1 +:1070600041F0010111602022DA7783F82200704795 +:1070700000ED00E00003FA0555CEACC5001000E0BD +:10708000302310B583F311880E4B5B6813F4006353 +:1070900014D0F1EE103AEFF309844FF08073683C9E +:1070A000E361094BDB6B236684F30988FEF7F6FE88 +:1070B00010B1064BA36110BD054BFBE783F31188AC +:1070C000F9E700BF00ED00E000EF00E02F0400084A +:1070D0003204000870B5BFF34F8FBFF36F8F1A4AA9 +:1070E0000021C2F85012BFF34F8FBFF36F8F536967 +:1070F00043F400335361BFF34F8FBFF36F8FC2F878 +:107100008410BFF34F8FD2F8803043F6E074C3F39E +:10711000C900C3F34E335B0103EA0406014646EAA5 +:1071200081750139C2F86052F9D2203B13F1200F6A +:10713000F2D1BFF34F8F536943F480335361BFF3F0 +:107140004F8FBFF36F8F70BD00ED00E0FEE70000D2 +:10715000214B2248224A70B5904237D3214BC11EA1 +:10716000DA1C121A22F003028B4238BF00220021DF +:10717000FAF7E4FD1C4A0023C2F88430BFF34F8FB6 +:10718000D2F8803043F6E074C3F3C900C3F34E3342 +:107190005B0103EA0406014646EA81750139C2F83B +:1071A0006C52F9D2203B13F1200FF2D1BFF34F8F75 +:1071B000BFF36F8FBFF34F8FBFF36F8F0023C2F802 +:1071C0005032BFF34F8FBFF36F8F70BD53F8041B66 +:1071D00040F8041BC0E700BFBC94000844590020DD +:1071E000445900204459002000ED00E0074BD3F83B +:1071F000D81021EA0001C3F8D810D3F8002122EA00 +:107200000002C3F80021D3F800317047004402584F +:1072100070B5D0E9244300224FF0FF359E6804EB9F +:1072200042135101D3F80009002805DAD3F8000908 +:1072300040F08040C3F80009D3F8000B002805DABD +:10724000D3F8000B40F08040C3F8000B0132631804 +:107250009642C3F80859C3F8085BE0D24FF0011317 +:10726000C4F81C3870BD0000890141F020010161A3 +:1072700003699B06FCD41220FEF74CBE10B50A4CE5 +:107280002046FEF7EBFA094BC4F89030084BC4F8DF +:107290009430084C2046FEF7E1FA074BC4F89030D2 +:1072A000064BC4F8943010BD54570020000008402D +:1072B00028940008F057002000000440349400088F +:1072C00070B503780546012B5CD1434BD0F8904054 +:1072D000984258D1414B0E216520D3F8D82042F076 +:1072E0000062C3F8D820D3F8002142F00062C3F84E +:1072F0000021D3F80021D3F8802042F00062C3F8C7 +:107300008020D3F8802022F00062C3F88020D3F8D8 +:107310008030FDF7ADFE324BE360324BC4F80038ED +:107320000023D5F89060C4F8003EC02323604FF4DA +:107330000413A3633369002BFCDA01230C203361AF +:10734000FEF7E8FD3369DB07FCD41220FEF7E2FD0F +:107350003369002BFCDA00262846A660FFF758FFA9 +:107360006B68C4F81068DB68C4F81468C4F81C685B +:1073700083BB1D4BA3614FF0FF336361A36843F0F0 +:107380000103A36070BD194B9842C9D1134B4FF054 +:107390008060D3F8D82042F00072C3F8D820D3F828 +:1073A000002142F00072C3F80021D3F80021D3F885 +:1073B000802042F00072C3F88020D3F8802022F0B1 +:1073C0000072C3F88020D3F88030FFF70FFF0E2142 +:1073D0004D209EE7064BCDE754570020004402584D +:1073E0004014004003002002003C30C0F057002051 +:1073F000083C30C0F8B5D0F89040054600214FF069 +:1074000000662046FFF730FFD5F8941000234FF0B8 +:1074100001128F684FF0FF30C4F83438C4F81C28CC +:1074200004EB431201339F42C2F80069C2F8006BBB +:10743000C2F80809C2F8080BF2D20B68D5F8902000 +:10744000C5F89830636210231361166916F01006B0 +:10745000FBD11220FEF75EFDD4F8003823F4FE6362 +:10746000C4F80038A36943F4402343F01003A36138 +:107470000923C4F81038C4F814380B4BEB604FF0F4 +:10748000C043C4F8103B094BC4F8003BC4F8106972 +:10749000C4F80039D5F8983003F1100243F4801392 +:1074A000C5F89820A362F8BD04940008408000103D +:1074B000D0F8902090F88A10D2F8003823F4FE63B8 +:1074C00043EA0113C2F80038704700002DE9F84381 +:1074D00000EB8103D0F890500C468046DA680FFA32 +:1074E00081F94801166806F00306731E022B05EBAE +:1074F00041134FF0000194BFB604384EC3F8101B7F +:107500004FF0010104F1100398BF06F1805601FA13 +:1075100003F3916998BF06F5004600293AD0578ACF +:1075200004F15801374349016F50D5F81C180B433B +:107530000021C5F81C382B180127C3F81019A740E3 +:107540005369611E9BB3138A928B9B08012A88BFE3 +:107550005343D8F89820981842EA034301F14002B7 +:107560002146C8F89800284605EB82025360FFF7D1 +:107570007BFE08EB8900C3681B8A43EA84534834C6 +:107580001E4364012E51D5F81C381F43C5F81C78E2 +:10759000BDE8F88305EB4917D7F8001B21F400413B +:1075A000C7F8001BD5F81C1821EA0303C0E704F153 +:1075B0003F030B4A2846214605EB83035A60FFF739 +:1075C00053FE05EB4910D0F8003923F40043C0F80E +:1075D0000039D5F81C3823EA0707D7E700800010E8 +:1075E00000040002D0F894201268C0F89820FFF739 +:1075F0000FBE00005831D0F8903049015B5813F4A9 +:10760000004004D013F4001F0CBF0220012070477B +:107610004831D0F8903049015B5813F4004004D051 +:1076200013F4001F0CBF02200120704700EB810102 +:10763000CB68196A0B6813604B6853607047000091 +:1076400000EB810330B5DD68AA691368D36019B90E +:10765000402B84BF402313606B8A1468D0F89020BD +:107660001C4402EB4110013C09B2B4FBF3F4634348 +:10767000033323F0030343EAC44343F0C043C0F899 +:10768000103B2B6803F00303012B0ED1D2F808380E +:1076900002EB411013F4807FD0F8003B14BF43F09D +:1076A000805343F00053C0F8003B02EB4112D2F884 +:1076B000003B43F00443C2F8003B30BD2DE9F041EC +:1076C000D0F8906005460C4606EB4113D3F8087BD2 +:1076D0003A07C3F8087B08D5D6F814381B0704D539 +:1076E00000EB8103DB685B689847FA071FD5D6F883 +:1076F0001438DB071BD505EB8403D968CCB98B693B +:10770000488A5A68B2FBF0F600FB16228AB918685C +:10771000DA6890420DD2121AC3E90024302383F3B1 +:10772000118821462846FFF78BFF84F31188BDE8B6 +:10773000F081012303FA04F26B8923EA02036B81CF +:10774000CB68002BF3D021462846BDE8F04118470E +:1077500000EB81034A0170B5DD68D0F890306C69A8 +:107760002668E66056BB1A444FF40020C2F81009A0 +:107770002A6802F00302012A0AB20ED1D3F80808DF +:1077800003EB421410F4807FD4F8000914BF40F0DA +:10779000805040F00050C4F8000903EB4212D2F8C8 +:1077A000000940F00440C2F800090122D3F834086F +:1077B00002FA01F10143C3F8341870BD19B9402E23 +:1077C00084BF4020206020681A442E8A8419013C1E +:1077D000B4FBF6F440EAC44040F00050C6E70000B5 +:1077E0002DE9F843D0F8906005460C464F0106EBB2 +:1077F0004113D3F8088918F0010FC3F808891CD089 +:10780000D6F81038DB0718D500EB8103D3F80CC08D +:10781000DCF81430D3F800E0DA68964530D2A2EBF9 +:107820000E024FF000091A60C3F80490302383F36E +:107830001188FFF78DFF89F3118818F0800F1DD094 +:10784000D6F834380126A640334217D005EB84031E +:107850000134D5F89050D3F80CC0E4B22F44DCF8D2 +:10786000142005EB0434D2F800E05168714514D3BC +:10787000D5F8343823EA0606C5F83468BDE8F8833D +:10788000012303FA01F2038923EA02030381DCF8EE +:107890000830002BD1D09847CFE7AEEB0103BCF8FE +:1078A0001000834228BF0346D7F8180980B2B3EB13 +:1078B000800FE3D89068A0F1040959F8048FC4F848 +:1078C0000080A0EB09089844B8F1040FF5D81844DB +:1078D0000B4490605360C8E72DE9F84FD0F8905002 +:1078E00004466E69AB691E4016F480586E6103D081 +:1078F000BDE8F84FFEF722B8002E12DAD5F8003EA8 +:107900009B0705D0D5F8003E23F00303C5F8003EE1 +:10791000D5F80438204623F00103C5F80438FEF7F3 +:107920003BF8370505D52046FFF772FC2046FEF7E9 +:1079300021F8B0040CD5D5F8083813F0060FEB6821 +:1079400023F470530CBF43F4105343F4A053EB6083 +:1079500031071BD56368DB681BB9AB6923F00803EB +:10796000AB612378052B0CD1D5F8003E9A0705D0E2 +:10797000D5F8003E23F00303C5F8003E2046FEF78D +:107980000BF86368DB680BB120469847F30200F1FF +:10799000BA80B70226D5D4F8909000274FF0010A9C +:1079A00009EB4712D2F8003B03F44023B3F5802FD4 +:1079B00011D1D2F8003B002B0DDA62890AFA07F3E5 +:1079C00022EA0303638104EB8703DB68DB6813B1FE +:1079D0003946204698470137D4F89430FFB29B6867 +:1079E0009F42DDD9F00619D5D4F89000026AC2F39F +:1079F0000A1702F00F0302F4F012B2F5802F00F024 +:107A0000CA80B2F5402F09D104EB8303002200F5B0 +:107A10008050DB681B6A974240F0B0803003D5F895 +:107A2000185835D5E90303D500212046FFF746FE57 +:107A3000AA0303D501212046FFF740FE6B0303D5BF +:107A400002212046FFF73AFE2F0303D503212046EB +:107A5000FFF734FEE80203D504212046FFF72EFE8F +:107A6000A90203D505212046FFF728FE6A0203D5A7 +:107A700006212046FFF722FE2B0203D507212046D0 +:107A8000FFF71CFEEF0103D508212046FFF716FE85 +:107A9000700340F1A780E90703D500212046FFF7D6 +:107AA0009FFEAA0703D501212046FFF799FE6B0729 +:107AB00003D502212046FFF793FE2F0703D50321AC +:107AC0002046FFF78DFEEE0603D504212046FFF782 +:107AD00087FEA80603D505212046FFF781FE69062B +:107AE00003D506212046FFF77BFE2A0603D5072192 +:107AF0002046FFF775FEEB0574D520460821BDE84A +:107B0000F84FFFF76DBED4F890904FF0000B4FF098 +:107B1000010AD4F894305FFA8BF79B689F423FF6D6 +:107B200038AF09EB4713D3F8002902F44022B2F52D +:107B3000802F20D1D3F80029002A1CDAD3F800299D +:107B400042F09042C3F80029D3F80029002AFBDB59 +:107B50003946D4F89000FFF787FB22890AFA07F329 +:107B600022EA0303238104EB8703DB689B6813B1DC +:107B70003946204698470BF1010BCAE7910701D11E +:107B8000D0F80080072A02F101029CBF03F8018BA4 +:107B90004FEA18283FE704EB830300F58050DA68CA +:107BA000D2F818C0DCF80820DCE9001CA1EB0C0CB2 +:107BB00000218F4208D1DB689B699A683A449A6039 +:107BC0005A683A445A6029E711F0030F01D1D0F8FE +:107BD00000808C4501F1010184BF02F8018B4FEA5E +:107BE0001828E6E7BDE8F88F08B50348FFF774FEEC +:107BF000BDE80840FFF744BA5457002008B50348D1 +:107C0000FFF76AFEBDE80840FFF73ABAF0570020D8 +:107C1000D0F8903003EB4111D1F8003B43F400134E +:107C2000C1F8003B70470000D0F8903003EB4111E1 +:107C3000D1F8003943F40013C1F80039704700004F +:107C4000D0F8903003EB4111D1F8003B23F400133E +:107C5000C1F8003B70470000D0F8903003EB4111B1 +:107C6000D1F8003923F40013C1F80039704700003F +:107C7000064BD3F8DC200243C3F8DC20D3F8042100 +:107C80001043C3F80401D3F804317047004402588C +:107C900008B53C4B4FF0FF31D3F8802062F0004232 +:107CA000C3F88020D3F8802002F00042C3F880207F +:107CB000D3F88020D3F88420C3F88410D3F884202C +:107CC0000022C3F88420D3F88400D86F40F0FF402E +:107CD00040F4FF0040F4DF4040F07F00D867D86FE9 +:107CE00020F0FF4020F4FF0020F4DF4020F07F0070 +:107CF000D867D86FD3F888006FEA40506FEA5050C9 +:107D0000C3F88800D3F88800C0F30A00C3F88800DD +:107D1000D3F88800D3F89000C3F89010D3F89000FF +:107D2000C3F89020D3F89000D3F89400C3F89410CF +:107D3000D3F89400C3F89420D3F89400D3F89800B3 +:107D4000C3F89810D3F89800C3F89820D3F8980097 +:107D5000D3F88C00C3F88C10D3F88C00C3F88C20B7 +:107D6000D3F88C00D3F89C00C3F89C10D3F89C1077 +:107D7000C3F89C20D3F89C30FCF7A4FDBDE8084074 +:107D800000F0B8B90044025808B50122534BC3F8BB +:107D90000821534BD3F8F42042F00202C3F8F42038 +:107DA000D3F81C2142F00202C3F81C210222D3F8AE +:107DB0001C314C4BDA605A689104FCD54A4A1A606F +:107DC00001229A60494ADA6000221A614FF4404267 +:107DD0009A61444B9A699204FCD51A6842F4807205 +:107DE0001A603F4B1A6F12F4407F04D04FF4803278 +:107DF0001A6700221A671A6842F001021A60384BAB +:107E00001A685007FCD500221A611A6912F038026C +:107E1000FBD1012119604FF0804159605A67344A03 +:107E2000DA62344A1A611A6842F480321A602C4BC2 +:107E30001A689103FCD51A6842F480521A601A68D5 +:107E40009204FCD52C4A2D499A6200225A63196388 +:107E500001F57C01DA6301F2E71199635A64284A5B +:107E60001A64284ADA621A6842F0A8521A601C4B57 +:107E70001A6802F02852B2F1285FF9D148229A61BB +:107E80004FF48862DA6140221A621F4ADA641F4A9C +:107E90001A651F4A5A651F4A9A6532231E4A1360A3 +:107EA000136803F00F03022BFAD10D4A136943F054 +:107EB00003031361136903F03803182BFAD14FF051 +:107EC0000050FFF7D5FE4FF08040FFF7D1FE4FF096 +:107ED0000040BDE80840FFF7CBBE00BF0080005166 +:107EE000004402580048025800C000F0020000019F +:107EF0000000FF0100889008222040006302090171 +:107F0000470E0508DD0BBF01200000200000011016 +:107F10000910E00000010110002000524FF0B042B3 +:107F200008B5D2F8883003F00103C2F8883023B1D5 +:107F3000044A13680BB150689847BDE80840FFF742 +:107F40009FB800BFC45800204FF0B04208B5D2F827 +:107F5000883003F00203C2F8883023B1044A9368E2 +:107F60000BB1D0689847BDE80840FFF789B800BF5B +:107F7000C45800204FF0B04208B5D2F8883003F062 +:107F80000403C2F8883023B1044A13690BB1506965 +:107F90009847BDE80840FFF773B800BFC4580020F9 +:107FA0004FF0B04208B5D2F8883003F00803C2F8A9 +:107FB000883023B1044A93690BB1D0699847BDE872 +:107FC0000840FFF75DB800BFC45800204FF0B04232 +:107FD00008B5D2F8883003F01003C2F8883023B116 +:107FE000044A136A0BB1506A9847BDE80840FFF78E +:107FF00047B800BFC45800204FF0B04310B5D3F8C5 +:10800000884004F47872C3F88820A30604D5124A85 +:10801000936A0BB1D06A9847600604D50E4A136B79 +:108020000BB1506B9847210604D50B4A936B0BB1EB +:10803000D06B9847E20504D5074A136C0BB1506C1E +:108040009847A30504D5044A936C0BB1D06C9847AC +:10805000BDE81040FFF714B8C45800204FF0B043FB +:1080600010B5D3F8884004F47C42C3F88820620538 +:1080700004D5164A136D0BB1506D9847230504D5EE +:10808000124A936D0BB1D06D9847E00404D50F4AA6 +:10809000136E0BB1506E9847A10404D50B4A936E32 +:1080A0000BB1D06E9847620404D5084A136F0BB128 +:1080B000506F9847230404D5044A936F0BB1D06FD7 +:1080C0009847BDE81040FEF7DBBF00BFC458002052 +:1080D00008B50348FCF7BEFFBDE80840FEF7D0BF77 +:1080E000A036002008B500F061FCBDE80840FEF7AE +:1080F000C7BF0000062108B50846FCF7B9FF0621F6 +:108100000720FCF7B5FF06210820FCF7B1FF062188 +:108110000920FCF7ADFF06210A20FCF7A9FF062184 +:108120001720FCF7A5FF06212820FCF7A1FF092155 +:108130007A20FCF79DFF09213120FCF799FF0721E8 +:108140003220BDE80840FCF793BF000008B5FFF7F8 +:108150009FFD00F0F3FBFDF7AFF9FDF77DFBFDF7A9 +:108160004FFAFEF7E9F9BDE8084000F029BA00002F +:1081700030B50433039C0172002104FB0325C16068 +:10818000C0E90653049B0363059BC0E90000C0E9F6 +:108190000422C0E90842C0E90A11436330BD00006F +:1081A0000022416AC260C0E90411C0E90A226FF0EE +:1081B0000101FDF737BF0000D0E90432934201D13D +:1081C000C2680AB9181D704700207047036919601A +:1081D0000021C2680132C260C269134482699342BD +:1081E000036124BF436A0361FDF710BF38B504463D +:1081F0000D46E3683BB162690020131D1268A3625B +:108200001344E36207E0237A33B929462046FDF799 +:10821000EDFE0028EDDA38BD6FF00100FBE700004D +:10822000C368C269013BC3604369134482699342D6 +:10823000436124BF436A436100238362036B03B13C +:108240001847704770B53023044683F31188866A57 +:108250003EB9FFF7CBFF054618B186F311882846D3 +:1082600070BDA36AE26A13F8015B9342A36202D372 +:108270002046FFF7D5FF002383F31188EFE70000C6 +:108280002DE9F84F04460E46174698464FF0300940 +:1082900089F311880025AA46D4F828B0BBF1000F55 +:1082A00009D141462046FFF7A1FF20B18BF3118889 +:1082B0002846BDE8F88FD4E90A12A7EB050B521A3D +:1082C000934528BF9346BBF1400F1BD9334601F1BC +:1082D000400251F8040B914243F8040BF9D1A36A10 +:1082E000403640354033A362D4E90A239A4202D390 +:1082F0002046FFF795FF8AF31188BD42D8D289F353 +:108300001188C9E730465A46F9F7F2FCA36A5E4481 +:108310005D445B44A362E7E710B5029C043301723D +:1083200003FB0421C460C0E906130023C0E90A333B +:10833000039B0363049BC0E90000C0E90422C0E979 +:108340000842436310BD0000026A6FF00101C26081 +:10835000426AC0E904220022C0E90A22FDF762BE97 +:10836000D0E904239A4201D1C26822B9184650F8D4 +:10837000043B0B60704700231846FAE7C3680021EE +:10838000C2690133C3604369134482699342436104 +:1083900024BF436A4361FDF739BE000038B5044687 +:1083A0000D46E3683BB1236900201A1DA262E26911 +:1083B0001344E36207E0237A33B929462046FDF7E8 +:1083C00015FE0028EDDA38BD6FF00100FBE7000074 +:1083D00003691960C268013AC260C26913448269C4 +:1083E0009342036124BF436A036100238362036BEA +:1083F00003B118477047000070B530230D4604469E +:10840000114683F31188866A2EB9FFF7C7FF10B1B2 +:1084100086F3118870BDA36A1D70A36AE26A0133F6 +:108420009342A36204D3E16920460439FFF7D0FFE9 +:10843000002080F31188EDE72DE9F84F04460D4642 +:10844000904699464FF0300A8AF311880026B346C9 +:10845000A76A4FB949462046FFF7A0FF20B187F32E +:1084600011883046BDE8F88FD4E90A073A1AA8EB1C +:108470000607974228BF1746402F1BD905F1400336 +:1084800055F8042B9D4240F8042BF9D1A36A4036DD +:108490004033A362D4E90A239A4204D3E169204617 +:1084A0000439FFF795FF8BF311884645D9D28AF33B +:1084B0001188CDE729463A46F9F71AFCA36A3D44EC +:1084C0003E443B44A362E5E7D0E904239A4217D136 +:1084D000C3689BB1836A8BB1043B9B1A0ED01360B7 +:1084E000C368013BC360C3691A4483699A4202614D +:1084F00024BF436A03610023836201231846704747 +:108500000023FBE701F01F03F0B502F01F0456093A +:108510005A1C0123B6EB511F50F8265003FA02F300 +:108520004FEA511703F1FF333DBF50F82720C4F144 +:108530002000134003EA05003BBF03FA00F225FACE +:1085400004F0E0401043F0BD70B57E227F21054667 +:10855000FFF7D8FF18B1012819D0002070BD3E22C6 +:1085600049212846FFF7CEFF2F2204463121284615 +:10857000FFF7C8FF06460134502202365321284631 +:10858000B440FFF7BFFF093804FA00F0E6E73022F5 +:1085900045212846FFF7B6FF01308002DEE70000E4 +:1085A00090F8D63090F8D7201B0403EB026390F8C4 +:1085B000D42090F8D500134403EB0020704700004E +:1085C00000F0CAB9014B586A704700BF000C004068 +:1085D000034B002258631A610222DA60704700BF21 +:1085E000000C0040014B0022DA607047000C004094 +:1085F000014B5863704700BF000C0040024B034A18 +:108600001A60034A5A607047A45800204859002055 +:1086100000000220074B494210B55C68201A084050 +:108620001968821A8A4203D3A24201D85A6010BD47 +:108630000020FCE7A458002008B5302383F31188FC +:10864000FFF7E8FF002383F3118808BD04480121E8 +:10865000044B03600023C0E901330C3000F016B96D +:10866000AC58002039860008CB1D083A23F00703D8 +:10867000591A521A012110B4D2080024C0E900434B +:1086800084600C301C605A605DF8044B00F0FEB84A +:108690002DE9F84F364ECD1D0F46002818BF06466F +:1086A000082A4FEAD50538BF082206F10C08341D08 +:1086B0009146404600F006F909F10701C9F1000EA4 +:1086C000224624686CB9404600F006F93368CBB303 +:1086D00008224946E8009847044698B340E90267F3 +:1086E00030E004EB010CD4F804A00CEA0E0C0AF103 +:1086F0000100ACF1080304EBC0009842E0D9A0EB04 +:108700000C0CB5EBEC0F4FEAEC0BD9D89C421CD209 +:1087100004F10802AB45A3EB02024FEAE2026260F9 +:1087200009D9691CED43206803EBC1025D44556023 +:1087300043F8310022601C465F60404644F8086BF5 +:1087400000F0CAF82046BDE8F88FAA45216802D19A +:1087500011602346EFE7013504EBC50344F83510FB +:1087600003F10801401AC01058601360F1E700BF20 +:10877000AC580020F8B550F8043C044650F8085CAA +:10878000A0F1080607332F1D0C35DB0840F8043C28 +:10879000284600F097F83B469F421A6801D0B34242 +:1087A00028D20AB1964225D244F8082C54F8042C59 +:1087B0001E60013254F8081C06EBC200814206D14B +:1087C0004868024444F8042C0A6844F8082C5868A5 +:1087D000411C03EBC1018E4207D154F8042C013235 +:1087E00002445A6054F8082C1A602846BDE8F84044 +:1087F00000F072B81346CFE7FEE7000070B51B4BE0 +:108800000025044686B058600E4685620163FEF777 +:108810000FFC04F11003A560E562C4E904334FF0D6 +:10882000FF33C4E90044C4E90635FFF7CBFE2B460D +:10883000024604F134012046C4E9082380230C4A8F +:108840002565FDF771FB01230A4AE060009203757C +:10885000684672680192B268CDE90223064BCDE901 +:108860000435FDF789FB06B070BD00BF603B0020FA +:108870004094000845940008F9870008024AD36A2A +:108880001843D062704700BFF8380020C0E90000EC +:10889000816070478368013B002B10B583600CDA60 +:1088A000074BDC684368A061206063601C60446023 +:1088B0000520FDF7ABFAA06910BD0020FCE700BF62 +:1088C000F838002008B5302383F31188FFF7E2FF62 +:1088D000002383F3118808BD08B5302383F3118882 +:1088E00083680133002B836007DC036800211A686A +:1088F000026050601846FDF7B5FA002383F3118833 +:1089000008BD000038B5EFF311859DB9EFF305847C +:10891000C4F30804302334B183F31188FDF7BAFCA3 +:1089200085F3118838BD83F31188FDF7B3FC84F318 +:10893000118838BDBDE83840FDF7ACBC0023054ABE +:1089400019460133102BC2E9001102F10802F8D1D7 +:10895000704700BFC4580020114BD3F8E82042F004 +:108960000802C3F8E820D3F8102142F00802C3F847 +:1089700010210C4AD3F81031D36B43F00803D363B2 +:10898000C722094B9A624FF0FF32DA6200229A61E5 +:108990005A63DA605A6001225A611A60704700BF58 +:1089A000004402580010005C000C0040094A08B561 +:1089B0001169D3680B40D9B29B076FEA01011161BD +:1089C00007D5302383F31188FDF7A2FA002383F340 +:1089D000118808BD000C004010B5013902449042D6 +:1089E00001D1002005E0037811F8014FA34201D026 +:1089F000181B10BD0130F2E7884210B501EB0204EC +:108A000002D98442234607D8431EA14208D011F858 +:108A1000012B03F8012FF8E7024401468A4200D1F6 +:108A200010BD13F8014D02F8014DF7E7C9B2034636 +:108A300010F8012B1AB18A42F9D118467047002963 +:108A400018BF0023F9E70000034611F8012B03F8D3 +:108A5000012B002AF9D1704710B50139034632B114 +:108A600011F8014F03F8014B013A002CF7D11A44D9 +:108A70000021934200D110BD03F8011BF9E700006B +:108A80004D4435002D2D0A002F6172647570696C9C +:108A90006F742E6162696E002F6172647570696C0B +:108AA0006F742D7665726966792E6162696E002F2A +:108AB0006172647570696C6F742D666C6173682E79 +:108AC0006162696E002F6172647570696C6F742DDC +:108AD000666C61736865642E6162696E00000000F7 +:108AE0000000000000000000050F0008A10F0008B2 +:108AF00051110008D90F0008990F0008000000006C +:108B000000000000010F0008AD0F000889110008E7 +:108B1000FD0E0008090F000853544D333248373F0B +:108B20003F3F0053544D3332483733782F37327834 +:108B30000053544D3332483734332F3735332F37C2 +:108B40003530000001105A00031059000120580070 +:108B5000032056002F00000053756363657373662E +:108B6000756C6C79206D6F756E7465642053444329 +:108B70006172642028736C6F77646F776E3D257522 +:108B8000290A0000EB7690455846415420202000E9 +:108B90004641543332202020000000002A3A3C3E57 +:108BA0007C223F7F002B2C3B3D5B5D0043554541C4 +:108BB0004141414345454549494941414592924FCB +:108BC0004F4F5555594F554F9C4F9E9F41494F55BB +:108BD000A5A5A6A7A8A9AAABACADAEAFB0B1B2B3DC +:108BE000B4414141B8B9BABBBCBDBEBFC0C1C2C32C +:108BF000C4C54141C8C9CACBCCCDCECFD1D14545E2 +:108C00004549494949D9DADBDCDD49DF4FE14F4FBE +:108C10004F4FE6E8E85555555959EEEFF0F1F2F3AC +:108C2000F4F5F6F7F8F9FAFBFCFDFEFF0103050782 +:108C3000090E10121416181C1E00000061001A0301 +:108C4000E0001703F8000703FF00010078010001AE +:108C5000300132010601390110014A012E0179016A +:108C6000060180014D0043028101820182018401DD +:108C7000840186018701870189018A018B018B01AB +:108C80008D018E018F019001910191019301940159 +:108C9000F60196019701980198013D029B019C0104 +:108CA0009D0120029F01A001A001A201A201A40137 +:108CB000A401A601A701A701A901AA01AB01AC016A +:108CC000AC01AE01AF01AF01B101B201B301B3011B +:108CD000B501B501B701B801B801BA01BB01BC01CA +:108CE000BC01BE01F701C001C101C201C301C40141 +:108CF000C501C401C701C801C701CA01CB01CA012E +:108D0000CD011001DD0101008E01DE011201F30130 +:108D10000300F101F401F401F8012801220212011B +:108D20003A020900652C3B023B023D02662C3F02E1 +:108D300040024102410246020A0153024000810101 +:108D40008601550289018A0158028F015A02900159 +:108D50005C025D025E025F029301610262029401A5 +:108D60006402650266026702970196016A02622C3C +:108D70006C026D026E029C01700271029D01730211 +:108D800074029F0176027702780279027A027B02EE +:108D90007C02642C7E027F02A60181028202A9016C +:108DA0008402850286028702AE014402B101B2014B +:108DB00045028D028E028F0290029102B7017B0361 +:108DC0000300FD03FE03FF03AC03040086038803D6 +:108DD00089038A03B1031103C2030200A303A3039F +:108DE000C4030803CC0303008C038E038F03D80352 +:108DF0001801F2030A00F903F303F403F503F60381 +:108E0000F703F703F903FA03FA03300420035004CD +:108E10001007600422018A043601C1040E01CF0448 +:108E20000100C004D00444016105260400000000D4 +:108E30007D1D0100632C001E9601A01E5A01001F1B +:108E40000806101F0606201F0806301F0806401FD0 +:108E50000606511F0700591F521F5B1F541F5D1F3D +:108E6000561F5F1F601F0806701F0E00BA1FBB1F32 +:108E7000C81FC91FCA1FCB1FDA1FDB1FF81FF91F2E +:108E8000EA1FEB1FFA1FFB1F801F0806901F080632 +:108E9000A01F0806B01F0400B81FB91FB21FBC1FD7 +:108EA000CC1F0100C31FD01F0206E01F0206E51FF2 +:108EB0000100EC1FF31F0100FC1F4E2101003221B5 +:108EC00070211002842101008321D0241A05302C46 +:108ED0002F04602C0201672C0601752C0201802CE6 +:108EE0006401002D260841FF1A030000C700FC00A2 +:108EF000E900E200E400E000E500E700EA00EB0042 +:108F0000E800EF00EE00EC00C400C500C900E60078 +:108F1000C600F400F600F200FB00F900FF00D600E6 +:108F2000DC00F800A300D800D7009201E100ED00BA +:108F3000F300FA00F100D100AA00BA00BF00AE00B1 +:108F4000AC00BD00BC00A100AB00BB009125922588 +:108F5000932502252425C100C200C000A900632575 +:108F6000512557255D25A200A5001025142534257F +:108F70002C251C2500253C25E300C3005A2554253B +:108F800069256625602550256C25A400F000D000D9 +:108F9000CA00CB00C8003101CD00CE00CF0018259B +:108FA0000C2588258425A600CC008025D300DF0071 +:108FB000D400D200F500D500B500FE00DE00DA00D6 +:108FC000DB00D900FD00DD00AF00B400AD00B10052 +:108FD0001720BE00B600A700F700B800B000A80038 +:108FE000B700B900B300B200A025A00010000240F5 +:108FF000080002400008024000000B002800024068 +:10900000080002400408024006010C004000024033 +:10901000080002400808024010020D0058000240FB +:10902000080002400C08024016030E0070000240C7 +:109030000C0002401008024000040F0088000240AB +:109040000C0002401408024006051000A000024077 +:109050000C0002401808024010061100B80002403F +:109060000C0002401C08024016072F0010040240AA +:10907000080402402008024000083800280402408A +:109080000804024024080240060939004004024056 +:109090000804024028080240100A3A00580402401E +:1090A000080402402C080240160B3B0070040240EA +:1090B0000C04024030080240000C3C0088040240CE +:1090C0000C04024034080240060D4400A004024093 +:1090D0000C04024038080240100E4500B80402405B +:1090E0000C0402403C080240160F4600010000003C +:1090F0000000000000000000316500083565000830 +:109100004D51000885540008E1500008095100083D +:1091100031510008C9500008000000007D550008CA +:1091200069550008A5550008915500089D5500088F +:10913000895500087555000861550008B1550008AB +:10914000000000000100000000000000633000008B +:109150004C91000850390020603B00200040806A9C +:1091600080000000AAAAAAAA00000064FFFF000075 +:109170000000000000A00A0001050000110000002E +:10918000AAAAAAAA00040000FFFF00000000000035 +:10919000000000000400AA0200000000AAAAAAAA77 +:1091A00004005500FFFF000000000000CCCC0C00C4 +:1091B0002000000000000000AAAAAAAA10000000D7 +:1091C000FFFF0000000C0000000000001000000085 +:1091D00000000000AAAAAAAA10000000FFFF0000D9 +:1091E000000000000000000000000000000000007F +:1091F000AAAAAAAA00000000FFFF000000000000C9 +:10920000000000000000000000000000AAAAAAAAB6 +:1092100000000000FFFF0000000000000000000050 +:109220000000000000000000AAAAAAAA0000000096 +:10923000FFFF000000000000000000000000000030 +:1092400000000000AAAAAAAA00000000FFFF000078 +:10925000000000000000000000000000000000000E +:10926000AAAAAAAA00000000FFFF00000000000058 +:10927000000000000000000000000000AAAAAAAA46 +:1092800000000000FFFF00000000000000000000E0 +:109290004172647550696C6F740025424F415244AD +:1092A000252D424C002553455249414C25000000D4 +:1092B00002000000000000009D5700080D58000843 +:1092C0004000400010540020205400200200000004 +:1092D00000000000030000000000000055580008D6 +:1092E00000000000100000003054002000000000CA +:1092F000010000000000000054570020010102009E +:109300002D6600083D650008D9650008BD650008A8 +:10931000430000001893000809024300020100C046 +:1093200032090400000102020100052400100105B9 +:10933000240100010424020205240600010705821D +:10934000030800FF09040100020A000000070501EC +:1093500002400000070581024000000012000000EA +:1093600064930008120110010200004009124157E5 +:1093700000020102030100000403090425424F41D9 +:1093800052442500565541562D54696E7956370082 +:10939000303132333435363738394142434445462B +:1093A0000000000000000020000002000200000099 +:1093B000000000300000040008000000000000244D +:1093C00000000800040000000004000000FC000091 +:1093D00002000000000004300080000008000000CF +:1093E0000000003800000100010000001F1C1F1ECB +:1093F0001F1E1F1F1E1F1E1F1F1D1F1E1F1E1F1F84 +:109400001E1F1E1F00000000B1590008695C000803 +:10941000155D0008400040008C5800208C5800204A +:10942000010000009C580020800000004001000066 +:10943000080000000001000000100000080000000B +:109440006D61696E0069646C650000001C70FF7FCF +:109450000100000000000000BD1B00000000000033 +:1094600000001E0000000000FF00000000000000DF +:10947000188B000883040000238B000850040000B0 +:10948000318B000801000000000000000096000081 +:109490000000080096000000000800000400000022 +:1094A00078930008000000000000000000000000A9 +:0C94B000000000000000000000000000B0 +:00000001FF diff --git a/Tools/scripts/decode_devid.py b/Tools/scripts/decode_devid.py index 3a432403e4be5..64bf56c7d8c72 100755 --- a/Tools/scripts/decode_devid.py +++ b/Tools/scripts/decode_devid.py @@ -110,6 +110,7 @@ def num(s): 0x3B : "DEVTYPE_INS_ICM45686", 0x3C : "DEVTYPE_INS_SCHA63T", 0x3D : "DEVTYPE_INS_IIM42653", + 0x3E : "DEVTYPE_INS_LSM6DSV", } baro_types = { diff --git a/libraries/AC_CustomControl/AC_CustomControl.cpp b/libraries/AC_CustomControl/AC_CustomControl.cpp index dd4a13611bde4..831a275d85ca9 100644 --- a/libraries/AC_CustomControl/AC_CustomControl.cpp +++ b/libraries/AC_CustomControl/AC_CustomControl.cpp @@ -31,7 +31,8 @@ const AP_Param::GroupInfo AC_CustomControl::var_info[] = { // parameters for empty controller. only used as a template, no need for param table // AP_SUBGROUPVARPTR(_backend, "1_", 6, AC_CustomControl, _backend_var_info[0]), - // parameters for PID controller + // @Group: 2_ + // @Path: AC_CustomControl_PID.cpp AP_SUBGROUPVARPTR(_backend, "2_", 7, AC_CustomControl, _backend_var_info[1]), AP_GROUPEND diff --git a/libraries/AC_PID/AC_PID.cpp b/libraries/AC_PID/AC_PID.cpp index 5087a42540e80..3ac8e09763ee2 100644 --- a/libraries/AC_PID/AC_PID.cpp +++ b/libraries/AC_PID/AC_PID.cpp @@ -84,14 +84,14 @@ const AP_Param::GroupInfo AC_PID::var_info[] = { // @Param: NTF // @DisplayName: PID Target notch filter index // @Description: PID Target notch filter index - // @Range: 1 8 + // @Range: 0 8 // @User: Advanced AP_GROUPINFO("NTF", 15, AC_PID, _notch_T_filter, 0), // @Param: NEF // @DisplayName: PID Error notch filter index // @Description: PID Error notch filter index - // @Range: 1 8 + // @Range: 0 8 // @User: Advanced AP_GROUPINFO("NEF", 16, AC_PID, _notch_E_filter, 0), #endif diff --git a/libraries/AC_WPNav/AC_WPNav_OA.cpp b/libraries/AC_WPNav/AC_WPNav_OA.cpp index 0098eb55ab617..347b00bb1956e 100644 --- a/libraries/AC_WPNav/AC_WPNav_OA.cpp +++ b/libraries/AC_WPNav/AC_WPNav_OA.cpp @@ -242,7 +242,7 @@ bool AC_WPNav_OA::update_wpnav() return false; } - // Convert global destination to NEU vector and pass directly to position controller + // Convert global destination to NED vector and pass directly to position controller Vector2f destination_ne_m; if (!_oa_destination.get_vector_xy_from_origin_NE_m(destination_ne_m)) { // this should never happen because we can only get here if we have an EKF origin @@ -251,7 +251,7 @@ bool AC_WPNav_OA::update_wpnav() } float target_alt_loc_alt_m = 0; UNUSED_RESULT(target_alt_loc.get_alt_m(target_alt_loc.get_alt_frame(), target_alt_loc_alt_m)); - Vector3p destination_ned_m{destination_ne_m.x, destination_ne_m.y, target_alt_loc_alt_m}; + Vector3p destination_ned_m{destination_ne_m.x, destination_ne_m.y, -target_alt_loc_alt_m}; // pass the desired position directly to the position controller _pos_control.input_pos_NED_m(destination_ned_m, terrain_d_m, 10.0); diff --git a/libraries/AP_Arming/AP_Arming.cpp b/libraries/AP_Arming/AP_Arming.cpp index 0ce5f86815ac2..a31ba97036815 100644 --- a/libraries/AP_Arming/AP_Arming.cpp +++ b/libraries/AP_Arming/AP_Arming.cpp @@ -1777,6 +1777,13 @@ bool AP_Arming::arm_checks(AP_Arming::Method method) } #endif + // Run estop check again, here in the arm checks there is no need + // bypass the check if arm emergency stop aux function is setup + if (SRV_Channels::get_emergency_stop()) { + check_failed(true, "Motors Emergency Stopped"); + return false; + } + // ensure the GPS drivers are ready on any final changes if (check_enabled(Check::GPS_CONFIG)) { if (!AP::gps().prepare_for_arming()) { diff --git a/libraries/AP_Baro/AP_Baro_BMP581.cpp b/libraries/AP_Baro/AP_Baro_BMP581.cpp index c8afb69ca6705..fa7e4119c3d36 100644 --- a/libraries/AP_Baro/AP_Baro_BMP581.cpp +++ b/libraries/AP_Baro/AP_Baro_BMP581.cpp @@ -146,10 +146,20 @@ bool AP_Baro_BMP581::init() void AP_Baro_BMP581::timer(void) { uint8_t buf[6]; + uint8_t buf2[6]; + // read twice, make sure results are consistent; corruption has + // been seen from data on this sensor if (!_dev->read_registers(BMP581_REG_TEMP_DATA_XLSB, buf, sizeof(buf))) { return; } + if (!_dev->read_registers(BMP581_REG_TEMP_DATA_XLSB, buf2, sizeof(buf2))) { + return; + } + if (memcmp(buf, buf2, ARRAY_SIZE(buf)) != 0) { + // we didn't get the same data twice. Reject. + return; + } WITH_SEMAPHORE(_sem); diff --git a/libraries/AP_GPS/AP_GPS_SBF.cpp b/libraries/AP_GPS/AP_GPS_SBF.cpp index da3a9e62dc170..c2c10a6e98fd4 100644 --- a/libraries/AP_GPS/AP_GPS_SBF.cpp +++ b/libraries/AP_GPS/AP_GPS_SBF.cpp @@ -590,15 +590,11 @@ AP_GPS_SBF::process_message(void) check_new_itow(temp.TOW, sbf_msg.length); - constexpr double floatDNU = -2e-10f; constexpr uint8_t errorBits = 0x8F; // Bits 0-1 are aux 1 baseline // Bits 2-3 are aux 2 baseline // Bit 7 is attitude not requested -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" // suppress -Wfloat-equal as it's false positive when testing for DNU values if (((temp.Error & errorBits) == 0) - && (temp.Cov_HeadHead != floatDNU)) { -#pragma GCC diagnostic pop + && !is_DNU(temp.Cov_HeadHead)) { state.gps_yaw_accuracy = sqrtf(temp.Cov_HeadHead); state.have_gps_yaw_accuracy = true; } else { @@ -628,12 +624,9 @@ AP_GPS_SBF::process_message(void) } case BaseVectorGeod: { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" // suppress -Wfloat-equal as it's false positive when testing for DNU values const msg4028 &temp = sbf_msg.data.msg4028u; // just breakout any consts we need for Do Not Use (DNU) reasons - constexpr double doubleDNU = -2e-10; constexpr uint16_t uint16DNU = 65535; check_new_itow(temp.TOW, sbf_msg.length); @@ -652,7 +645,7 @@ AP_GPS_SBF::process_message(void) state.rtk_age_ms = (temp.info.CorrAge != 65535) ? ((uint32_t)temp.info.CorrAge) * 10 : 0; // copy the position as long as the data isn't DNU, we require NED, and heading before accepting any of it - if ((temp.info.DeltaEast != doubleDNU) && (temp.info.DeltaNorth != doubleDNU) && (temp.info.DeltaUp != doubleDNU) && + if (!is_DNU(temp.info.DeltaEast) && !is_DNU(temp.info.DeltaNorth) && !is_DNU(temp.info.DeltaUp) && (temp.info.Azimuth != uint16DNU)) { state.rtk_baseline_y_mm = temp.info.DeltaEast * 1e3; @@ -675,7 +668,6 @@ AP_GPS_SBF::process_message(void) state.have_gps_yaw = false; } -#pragma GCC diagnostic pop break; } } diff --git a/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6C/hwdef.dat b/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6C/hwdef.dat index d3a981edf8005..e75130c9fd2bd 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6C/hwdef.dat +++ b/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6C/hwdef.dat @@ -231,10 +231,13 @@ define AP_COMPASS_IST8310_INTERNAL_BUS_PROBING_ENABLED 0 SPIDEV bmi055_g SPI1 DEVID1 BMI055_G_CS MODE3 10*MHZ 10*MHZ SPIDEV bmi055_a SPI1 DEVID2 BMI055_A_CS MODE3 10*MHZ 10*MHZ SPIDEV icm42688 SPI1 DEVID3 ICM42688_CS MODE3 2*MHZ 8*MHZ +# alternative to icm42688, using the same SPI bus and CS line +SPIDEV lsm6dsv SPI1 DEVID4 ICM42688_CS MODE3 2*MHZ 8*MHZ SPIDEV ramtron SPI2 DEVID1 FRAM_CS MODE3 8*MHZ 8*MHZ # 2 IMUs IMU Invensensev3 SPI:icm42688 ROTATION_PITCH_180_YAW_90 +IMU LSM6DSV SPI:lsm6dsv ROTATION_PITCH_180_YAW_90 IMU BMI055 SPI:bmi055_a SPI:bmi055_g ROTATION_PITCH_180 # BMI055 is replaced by BMI088 on the lastest hardware revision # They use the same CPU signal pins diff --git a/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6X/hwdef.dat b/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6X/hwdef.dat index 396599565520f..ac9ac3a80823e 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6X/hwdef.dat +++ b/libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6X/hwdef.dat @@ -285,6 +285,10 @@ PI5 TIM8_CH1 TIM8 RCININT PULLDOWN LOW BARO BMP388 I2C:2:0x76 BARO BMP388 I2C:0:0x77 +# barometers (Holybro 6X more recent versions) +BARO BMP581 I2C:2:0x46 +BARO BMP581 I2C:0:0x46 + # barometers (CUAV 6X) BARO ICP201XX I2C:0:0x64 BARO ICP201XX I2C:2:0x63 diff --git a/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/README.md b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/README.md new file mode 100644 index 0000000000000..4816d7be93213 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/README.md @@ -0,0 +1,209 @@ +# VUAV-V7Tiny Flight Controller + +The VUAV-V7Tiny flight controller is manufactured and sold by [V-UAV](http://www.v-uav.com/). + +## Features + +- STM32H743 microcontroller +- Two IMUs: ICM45686,BMI088 +- Internal IST8310 magnetometer +- Internal ICP-20100 barometer +- Internal RGB LED +- MicroSD card slot port +- 1 ESC connector power input and current sensor input +- 5 UARTs and 1 USB ports +- 12 PWM output ports +- 1 I2C and 1 CAN ports +- Safety switch port +- Buzzer port +- RC IN port + +## Pinout + +![VUAV-TinyV7-Connectors](VUAV-TinyV7-Connectors.png) + +![VUAV-TinyV7-Pinouts](VUAV-TinyV7-Pinouts.png) + +## UART Mapping + +- SERIAL0 -> USB +- SERIAL1 -> UART2 (MAVLink2, Telem1) (DMA enabled) +- SERIAL2 -> UART5 (MAVLink2, Telem2) (DMA enabled) +- SERIAL3 -> UART1 (GPS1) (DMA enabled) +- SERIAL4 -> UART3 (GPS2) (DMA enabled) +- SERIAL5 -> UART7 (User defined, marked Telem3) (DMA enabled) +- SERIAL6 -> USB2 (virtual port on same connector) + +The Telem1 port has RTS/CTS pins, the other UARTs do not have RTS/CTS. + +## Connectors + +### TELEM1 port + +| Pin | Signal | Volt | +| :--: | :-------: | :---: | +| 1 | VCC | +5V | +| 2 | TX2 (OUT) | +3.3V | +| 3 | RX2 (IN) | +3.3V | +| 4 | CTS | +3.3V | +| 5 | RTS | +3.3V | +| 6 | GND | GND | + +### TELEM2/ADC port + +| Pin | Signal | Volt | +| :--: | :-------: | :---------: | +| 1 | VCC | +5V | +| 2 | TX5 (OUT) | +3.3V | +| 3 | RX5 (IN) | +3.3V | +| 4 | ADC_3V3 | up to +3.3V | +| 5 | ADC_6V6 | up to +3.3V | +| 6 | GND | GND | + +### TELEM3/ADC port + +NOTE: RX7 is pinned out here and on the ESC connector + +| Pin | Signal | Volt | +| :--: | :-------: | :---: | +| 1 | VCC | +5V | +| 2 | TX7 (OUT) | +3.3V | +| 3 | RX7 (IN) | +3.3V | +| 4 | GND | GND | + +### GPS1/I2C2 port + +| Pin | Signal | Volt | +| :--: | :----------: | :-------------: | +| 1 | VCC | +5V | +| 2 | TX1 (OUT) | +3.3V | +| 3 | RX1 (IN) | +3.3V | +| 4 | SCL I2C2 | +3.3V (pullups) | +| 5 | SDA I2C2 | +3.3V (pullups) | +| 6 | SafetyButton | +3.3V | +| 7 | SafetyLED | +3.3V | +| 8 | - | - | +| 9 | Buzzer | +3.3V | +| 10 | GND | GND | + +### GPS2/I2C2 port + +| Pin | Signal | Volt | +| :--: | :-------: | :-------------: | +| 1 | VCC | +5V | +| 2 | TX3 (OUT) | +3.3V | +| 3 | RX3 (IN) | +3.3V | +| 4 | SCL I2C2 | +3.3V (pullups) | +| 5 | SDA I2C2 | +3.3V (pullups) | +| 6 | GND | GND | + +### CAN1 port + +| Pin | Signal | Volt | +| :--: | :----: | :--: | +| 1 | VCC | +5V | +| 2 | CAN_H | +24V | +| 3 | CAN_L | +24V | +| 4 | GND | GND | + +### I2C port + +| Pin | Signal | Volt | +| :--: | :------: | :------------: | +| 1 | VCC | +5V | +| 2 | SCL I2C4 | +3.3 (pullups) | +| 3 | SDA I2C4 | +3.3 (pullups) | +| 4 | GND | GND | + +### POWER + +| Pin | Signal | Volt | +| :--: | :-----: | :---------: | +| 1 | VCC IN | +5V | +| 2 | VCC IN | +3.3V | +| 3 | CURRENT | up to +3.3V | +| 4 | VOLTAGE | up to +3.3V | +| 5 | GND | GND | +| 6 | GND | GND | + +### ESC + +| Pin | Signal | Volt | +| :--: | :--------: | :---------: | +| 1 | BAT VCC IN | +6V to 26V | +| 2 | CURRENT | up to +3.3V | +| 3 | UART7_RX | +3.3V | +| 4 | PWM9 | +3.3V | +| 5 | PWM10 | +3.3V | +| 6 | PWM11 | +3.3V | +| 7 | PWM12 | +3.3V | +| 8 | GND | GND | + +## RC Input + +The RC input is configured on the RCIN pin at one end of the servo rail. This pin supports all unidirectional RC protocols. For bidirectional protocols, such as CRSF/ELRS, any SERIAL port can be set to protocol "23" and the receiver can be connected to its RX and TX pins as described in [RC control systems](https://ardupilot.org/rover/docs/common-rc-systems.html). + +## PWM Output + +The VUAV-V7Tiny supports up to 12 PWM outputs and all PWM protocols. Outputs 1-8 support bidirectional Dshot protocol. All 8 PWM outputs use a three-row design: the top row is GND, the middle rows are connected together, and the bottom row is the signal line. Outputs 9-12 do not support Dshot and are located at the ESC interface. + +The 12 PWM outputs are in 4 groups: + +- PWM 1, 2, 3 and 4 in group1 +- PWM 5, 6, 7 and 8 in group2 +- PWM 9, 10 in group3 +- PWM 11, 12 in group4 + +Channels within the same group need to use the same output rate. If any channel in a group uses DShot, then all channels in that group need to use DShot. + +## GPIOs + +All 12 PWM channels can be used for GPIO functions (relays, buttons, RPM etc). + +The pin numbers for these PWM channels in ArduPilot are shown below: + +| PWM Channels | Pin | PWM Channels | Pin | +| :----------: | :--: | :----------: | :--: | +| PWM1 | 50 | PWM7 | 56 | +| PWM2 | 51 | PWM8 | 57 | +| PWM3 | 52 | PWM9 | 58 | +| PWM4 | 53 | PWM10 | 59 | +| PWM5 | 54 | PWM11 | 60 | +| PWM6 | 55 | PWM12 | 61 | + +## Analog inputs + +The VUAV-V7Tiny flight controller has 6 Analog inputs + +- ADC Pin18-> Battery Current +- ADC Pin4 -> Battery Voltage +- ADC Pin19 -> ADC 3V3 Sense +- ADC Pin5 -> ADC 6V6 Sense +- ADC Pin10 -> Battery Voltage input on ESC connector +- ADC Pin8 -> Servo Voltage + +## Battery Monitor Configuration + +The board has voltage and current inputs sensor on the POWER and ESC connector. + +The correct battery setting parameters are: + +Enable POWER monitor: + +- BATT_MONITOR 4 +- BATT_VOLT_PIN 4 +- BATT_CUR_PIN 8 +- BATT_VOLT_MULT 20 +- BATT_AMP_PERVLT 24 + +Enable ESC battery monitor (if used) : + +- BATT2_MONITOR 3 +- BATT2_VOLT_PIN 10 +- BATT2_VOLT_MULT 10.09 + +## Loading Firmware + +The firmware can be found at [ArduPilot Firmware Server](https://firmware.ardupilot.org). Click on the corresponding type, such as Plane or Copter, then select the version folder, and finally select the folder labeled "VUAV-TinyV7". + +The board comes pre-installed with an ArduPilot compatible bootloader, allowing the loading of \*.apj firmware files with any ArduPilot compatible ground station. diff --git a/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/VUAV-TinyV7-Connectors.png b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/VUAV-TinyV7-Connectors.png new file mode 100644 index 0000000000000..5c49eb12d60bf Binary files /dev/null and b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/VUAV-TinyV7-Connectors.png differ diff --git a/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/VUAV-TinyV7-Pinouts.png b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/VUAV-TinyV7-Pinouts.png new file mode 100644 index 0000000000000..98a4781181b7b Binary files /dev/null and b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/VUAV-TinyV7-Pinouts.png differ diff --git a/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/defaults.parm b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/defaults.parm new file mode 100644 index 0000000000000..e86e648b0b161 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/defaults.parm @@ -0,0 +1,3 @@ +BRD_HEAT_TARG 45 + +CAN_P1_DRIVER 1 diff --git a/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/hwdef-bl.dat b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/hwdef-bl.dat new file mode 100644 index 0000000000000..31db312ef84f1 --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/hwdef-bl.dat @@ -0,0 +1,63 @@ +# hw definition file for processing by chibios_hwdef.py +# for H743 bootloader + +# MCU class and specific type +MCU STM32H7xx STM32H743xx + +# board ID. See Tools/AP_Bootloader/board_types.txt +APJ_BOARD_ID AP_HW_VUAV-TinyV7 + +# crystal frequency +OSCILLATOR_HZ 16000000 + +FLASH_SIZE_KB 2048 + +# bootloader is installed at zero offset +FLASH_RESERVE_START_KB 0 + +FLASH_BOOTLOADER_LOAD_KB 128 + +PB0 LED_RED OUTPUT OPENDRAIN HIGH # red +PB4 LED_ACTIVITY OUTPUT OPENDRAIN HIGH # blue +PA7 LED_BOOTLOADER OUTPUT OPENDRAIN HIGH # green +define HAL_LED_ON 0 + +# order of UARTs (and USB) +SERIAL_ORDER OTG1 + +PA11 OTG_FS_DM OTG1 +PA12 OTG_FS_DP OTG1 + +PA13 JTMS-SWDIO SWD +PA14 JTCK-SWCLK SWD + +# FATFS support: +define CH_CFG_USE_MEMCORE 1 +define CH_CFG_USE_HEAP 1 +define CH_CFG_USE_SEMAPHORES 0 +define CH_CFG_USE_MUTEXES 1 +define CH_CFG_USE_DYNAMIC 1 +define CH_CFG_USE_WAITEXIT 1 +define CH_CFG_USE_REGISTRY 1 + +# microSD support +PC8 SDMMC1_D0 SDMMC1 +PC9 SDMMC1_D1 SDMMC1 +PC10 SDMMC1_D2 SDMMC1 +PC11 SDMMC1_D3 SDMMC1 +PC12 SDMMC1_CK SDMMC1 +PD2 SDMMC1_CMD SDMMC1 + +define FATFS_HAL_DEVICE SDCD1 + +DMA_PRIORITY SDMMC* + +# enable FAT filesystem support (needs a microSD defined via SDMMC) +define HAL_OS_FATFS_IO 1 +define AP_BOOTLOADER_FLASH_FROM_SD_ENABLED 1 + +# Add CS pins to ensure they are high in bootloader +PA15 IMU1_G_CS CS +PB5 IMU1_A_CS CS +PC1 IMU2_CS CS +PE2 FRAM_CS CS diff --git a/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/hwdef.dat b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/hwdef.dat new file mode 100644 index 0000000000000..3a5d643a5811c --- /dev/null +++ b/libraries/AP_HAL_ChibiOS/hwdef/VUAV-TinyV7/hwdef.dat @@ -0,0 +1,228 @@ +# hw definition file for processing by chibios_hwdef.py + +# MCU class and specific type +MCU STM32H7xx STM32H743xx + +# crystal frequency +OSCILLATOR_HZ 16000000 + +# board ID. See Tools/AP_Bootloader/board_types.txt +APJ_BOARD_ID AP_HW_VUAV-TinyV7 + +FLASH_SIZE_KB 2048 + +# with 2M flash we can afford to optimize for speed +env OPTIMIZE -O2 + +# bootloader takes first sector +FLASH_RESERVE_START_KB 128 + +# ChibiOS system timer +STM32_ST_USE_TIMER 5 + +# order of UARTs (and USB) +SERIAL_ORDER OTG1 USART2 UART5 USART1 USART3 UART7 OTG2 + +# USB +PA11 OTG_FS_DM OTG1 +PA12 OTG_FS_DP OTG1 + +# UARTs +# USART2 is telem1 +PD6 USART2_RX USART2 +PD5 USART2_TX USART2 +PD3 USART2_CTS USART2 +PD4 USART2_RTS USART2 + +# UART5 is telem2 +PB12 UART5_RX UART5 +PB13 UART5_TX UART5 + +# USART1 is GPS1 +PA10 USART1_RX USART1 +PA9 USART1_TX USART1 + +# USART3 is GPS2 +PD9 USART3_RX USART3 +PD8 USART3_TX USART3 + +# UART7 is telem3 +PE7 UART7_RX UART7 +PE8 UART7_TX UART7 + +# debug pins +PA13 JTMS-SWDIO SWD +PA14 JTCK-SWCLK SWD + +# SPI1 - sensors1 - baro1 +PB3 SPI1_SCK SPI1 +PA6 SPI1_MISO SPI1 +PD7 SPI1_MOSI SPI1 + +# SPI4 - sensors2 - fram +PE12 SPI4_SCK SPI4 +PE13 SPI4_MISO SPI4 +PE14 SPI4_MOSI SPI4 + + +# sensor CS +PA15 IMU1_G_CS CS +PB5 IMU1_A_CS CS +PC1 IMU2_CS CS +PE2 FRAM_CS CS + +# I2C buses + +# I2C1 is on I2C1 port +PB8 I2C1_SCL I2C1 +PB9 I2C1_SDA I2C1 + +# I2C2 on I2C2 port +PB10 I2C2_SCL I2C2 +PB11 I2C2_SDA I2C2 + +# I2C4 is on GPS1 port +PB6 I2C4_SCL I2C4 +PB7 I2C4_SDA I2C4 + +# order of I2C buses +I2C_ORDER I2C1 I2C2 I2C4 + +NODMA I2C* +define STM32_I2C_USE_DMA FALSE +define HAL_I2C_INTERNAL_MASK 1 + +# enable pins +PE6 VDD_3V3_SENSORS_EN OUTPUT LOW +PE3 VDD_5V_HIPOWER_EN OUTPUT LOW + +# PWM AUX channels +PA0 TIM2_CH1 TIM2 PWM(1) GPIO(50) BIDIR +PA1 TIM2_CH2 TIM2 PWM(2) GPIO(51) +PA2 TIM2_CH3 TIM2 PWM(3) GPIO(52) BIDIR +PA3 TIM2_CH4 TIM2 PWM(4) GPIO(53) +PD12 TIM4_CH1 TIM4 PWM(5) GPIO(54) BIDIR +PD13 TIM4_CH2 TIM4 PWM(6) GPIO(55) +PD14 TIM4_CH3 TIM4 PWM(7) GPIO(56) BIDIR +PD15 TIM4_CH4 TIM4 PWM(8) GPIO(57) +PE9 TIM1_CH1 TIM1 PWM(9) GPIO(58) +PE11 TIM1_CH2 TIM1 PWM(10) GPIO(59) +PB14 TIM12_CH1 TIM12 PWM(11) GPIO(60) NODMA +PB15 TIM12_CH2 TIM12 PWM(12) GPIO(61) NODMA + +# PWM output for buzzer +PE5 TIM15_CH1 TIM15 GPIO(77) ALARM + +# RC input +PC7 TIM8_CH2 TIM8 RCININT PULLDOWN LOW + +# analog in +PC4 BATT_VOLTAGE_SENS ADC1 SCALE(1) +PA4 BATT_CURRENT_SENS ADC1 SCALE(1) + +PC0 BATT2_VOLTAGE_SENS ADC1 SCALE(1) + +PA5 SPARE1_ADC1 ADC1 SCALE(1) +PB1 SPARE2_ADC1 ADC1 SCALE(2) + +PC3 VDD_5V_SENS ADC1 SCALE(2) + +PC5 FMU_SERVORAIL_VCC_SENS ADC1 SCALE(3) + + +# Pin for PWM Voltage Selection, 0 means 3.3v, 1 means 5v, 3.3v default +PC6 PWM_VOLT_SEL OUTPUT LOW GPIO(79) +define HAL_GPIO_PWM_VOLT_PIN 79 +define HAL_GPIO_PWM_VOLT_3v3 0 + +# CAN bus +PD0 CAN1_RX CAN1 +PD1 CAN1_TX CAN1 + +# GPIOs +PA8 HEATER_EN OUTPUT LOW GPIO(80) +define HAL_HEATER_GPIO_PIN 80 +define HAL_HAVE_IMU_HEATER 1 + +PE10 VDD_BRICK_nVALID INPUT PULLUP +PE15 VBUS_nVALID INPUT PULLUP + +PE4 VDD_5V_HIPOWER_nOC INPUT PULLUP + +# SPI devices +SPIDEV imu1 SPI4 DEVID1 IMU2_CS MODE3 2*MHZ 16*MHZ +SPIDEV bmi088_a SPI1 DEVID1 IMU1_A_CS MODE3 10*MHZ 10*MHZ +SPIDEV bmi088_g SPI1 DEVID2 IMU1_G_CS MODE3 10*MHZ 10*MHZ +SPIDEV ramtron SPI4 DEVID2 FRAM_CS MODE3 5*MHZ 5*MHZ + +# baro +BARO ICP201XX I2C:0:0x63 + +# three IMUs +IMU Invensensev3 SPI:imu1 ROTATION_PITCH_180 +IMU BMI088 SPI:bmi088_a SPI:bmi088_g ROTATION_ROLL_180 + +define HAL_DEFAULT_INS_FAST_SAMPLE 3 + +# compass +define AP_COMPASS_PROBING_ENABLED 1 +define AP_COMPASS_IST8310_INTERNAL_BUS_PROBING_ENABLED 0 + +COMPASS IST8310 I2C:0:0x0E false ROTATION_YAW_180 +COMPASS QMC5883L I2C:0:0xD false ROTATION_PITCH_180_YAW_90 + +# microSD support +PC8 SDMMC1_D0 SDMMC1 +PC9 SDMMC1_D1 SDMMC1 +PC10 SDMMC1_D2 SDMMC1 +PC11 SDMMC1_D3 SDMMC1 +PC12 SDMMC1_CK SDMMC1 +PD2 SDMMC1_CMD SDMMC1 + +# red LED marked as B/E +PB0 LED_R1 OUTPUT OPENDRAIN HIGH GPIO(0) +PA7 LED_G1 OUTPUT OPENDRAIN LOW GPIO(1) +PB4 LED_B1 OUTPUT OPENDRAIN HIGH GPIO(2) + +define AP_NOTIFY_GPIO_LED_RGB_RED_PIN 0 +define AP_NOTIFY_GPIO_LED_RGB_GREEN_PIN 1 +define AP_NOTIFY_GPIO_LED_RGB_BLUE_PIN 2 + +# use pixracer style 3-LED indicators +define AP_NOTIFY_GPIO_LED_RGB_ENABLED 1 + +# enable RAMTROM parameter storage +define HAL_STORAGE_SIZE 32768 +define HAL_WITH_RAMTRON 1 + +# allow to have have a dedicated safety switch pin +define HAL_HAVE_SAFETY_SWITCH 1 +PB2 LED_SAFETY OUTPUT +PC13 SAFETY_IN INPUT PULLDOWN + +# build ABIN for flash-from-bootloader support: +env BUILD_ABIN False + +# enable FAT filesystem support (needs a microSD defined via SDMMC) +define HAL_OS_FATFS_IO 1 + +# enable DFU reboot for installing bootloader +# note that if firmware is build with --secure-bl then DFU is +# disabled +ENABLE_DFU_BOOT 1 + +DMA_PRIORITY TIM2* SDMMC* ADC* SPI1* TIM*UP* +DMA_NOSHARE SPI1* TIM*UP* + +# Enable Sagetech MXS ADSB transponder +define HAL_ADSB_SAGETECH_MXS_ENABLED HAL_ADSB_ENABLED + +# define default battery setup +define HAL_BATT_MONITOR_DEFAULT 4 +define HAL_BATT_CURR_PIN 8 +define HAL_BATT_VOLT_PIN 4 +define HAL_BATT_CURR_SCALE 24 +define HAL_BATT_VOLT_SCALE 20 + +define HAL_BATT2_VOLT_PIN 3 +define HAL_BATT2_VOLT_SCALE 10.09 diff --git a/libraries/AP_IOMCU/iofirmware/mixer.cpp b/libraries/AP_IOMCU/iofirmware/mixer.cpp index 7277c56cdf55d..32f482b146be0 100644 --- a/libraries/AP_IOMCU/iofirmware/mixer.cpp +++ b/libraries/AP_IOMCU/iofirmware/mixer.cpp @@ -24,6 +24,8 @@ #define ANGLE_SCALE ((int32_t)4500) #define RANGE_SCALE ((int32_t)1000) +extern const AP_HAL::HAL& hal; + /* return a RC input value scaled from -4500 to 4500 */ @@ -141,6 +143,11 @@ void AP_IOMCU_FW::run_mixer(void) } } + // Never output throttle if the vehicle was disarmed when we last heard from the FMU + if (!hal.util->get_soft_armed()) { + throttle = 0; + } + for (uint8_t i=0; i. + */ +/* + driver for ST LSM6DSV16X IMU + + Uses HAODR mode-1 for high-accuracy ODR (1000-8000 Hz) and + continuous FIFO for burst reads. Digital filters auto-adapt to ODR + so no per-rate AAF register reconfiguration is needed. + + fast sampling is controlled via INS_FAST_SAMPLE / INS_GYRO_RATE + with base rate 1000 Hz. + */ + +#include "AP_InertialSensor_LSM6DSV.h" + +#include +#include + +#include +#include +#include + +extern const AP_HAL::HAL& hal; + +namespace { + +// Enable the second-stage digital low-pass filter (LPF2) on the +// accelerometer output. Bandwidth is set by LSM6DSV_ACCEL_LPF2_BW. +#ifndef LSM6DSV_ACCEL_LPF2_ENABLED +#define LSM6DSV_ACCEL_LPF2_ENABLED 1 +#endif + +// LPF2 bandwidth selection written to CTRL8 HP_LPF2_XL_BW bits [7:5]. +// When CTRL9.LPF2_XL_EN = 1 these select the second-stage cutoff: +// 0x00 = ODR/4 0x20 = ODR/10 0x40 = ODR/20 0x60 = ODR/45 +// 0x80 = ODR/100 0xA0 = ODR/200 0xC0 = ODR/400 0xE0 = ODR/800 +#ifndef LSM6DSV_ACCEL_LPF2_BW +#define LSM6DSV_ACCEL_LPF2_BW 0x20 // ODR/10 → 200 Hz @ 2 kHz ODR +#endif + +// ---- FIFO control registers (R/W) ---- +#define LSM6DSV_REG_FIFO_CTRL1 0x07 // FIFO watermark threshold [7:0] +#define LSM6DSV_REG_FIFO_CTRL2 0x08 // FIFO watermark threshold [8], compression +#define LSM6DSV_REG_FIFO_CTRL3 0x09 // FIFO gyro/accel batch data rate +#define LSM6DSV_REG_FIFO_CTRL4 0x0A // FIFO mode selection + +#define LSM6DSV_FIFO_CTRL3_BDR_DISABLED 0x00 +#define LSM6DSV_FIFO_CTRL4_MODE_BYPASS 0x00 +#define LSM6DSV_FIFO_CTRL4_MODE_CONTINUOUS 0x06 + +// ---- WHO_AM_I register (R) ---- +#define LSM6DSV_REG_WHO_AM_I 0x0F +#define LSM6DSV_ID_LSM6DSV16X 0x70 + +// ---- Accelerometer control register 1 (R/W) ---- +// [6:4] OP_MODE_XL: operating mode [3:0] ODR_XL: output data rate +#define LSM6DSV_REG_CTRL1 0x10 + +// ---- Gyroscope control register 2 (R/W) ---- +// [6:4] OP_MODE_G: operating mode [3:0] ODR_G: output data rate +#define LSM6DSV_REG_CTRL2 0x11 + +// ---- Control register 3 (R/W) ---- +#define LSM6DSV_REG_CTRL3 0x12 +#define LSM6DSV_CTRL3_BDU (1U << 6) // block data update +#define LSM6DSV_CTRL3_IF_INC (1U << 2) // auto-increment address +#define LSM6DSV_CTRL3_SW_RESET (1U << 0) // software reset + +// [4] OP_MODE: 0=high-performance, 1=high-accuracy ODR +#define LSM6DSV_CTRL_MODE_HAODR 0x10 + +// ---- Control register 6 — gyro full-scale selection (R/W) ---- +// [3:0] FS_G: gyroscope full-scale +#define LSM6DSV_REG_CTRL6 0x15 +#define LSM6DSV_CTRL6_FS_G_125DPS 0x00 +#define LSM6DSV_CTRL6_FS_G_250DPS 0x01 +#define LSM6DSV_CTRL6_FS_G_500DPS 0x02 +#define LSM6DSV_CTRL6_FS_G_1000DPS 0x03 +#define LSM6DSV_CTRL6_FS_G_2000DPS 0x04 +#define LSM6DSV_CTRL6_FS_G_4000DPS 0x0C + +// ---- Control register 8 — accel full-scale & LPF2 BW (R/W) ---- +// [7:5] HP_LPF2_XL_BW [1:0] FS_XL: accelerometer full-scale +#define LSM6DSV_REG_CTRL8 0x17 +#define LSM6DSV_CTRL8_FS_XL_2G 0x00 +#define LSM6DSV_CTRL8_FS_XL_4G 0x01 +#define LSM6DSV_CTRL8_FS_XL_8G 0x02 +#define LSM6DSV_CTRL8_FS_XL_16G 0x03 + +// ---- Control register 9 — accel LPF2 enable (R/W) ---- +#define LSM6DSV_REG_CTRL9 0x18 +#define LSM6DSV_CTRL9_LPF2_XL_EN (1U << 3) + +// ---- FIFO status registers (R) ---- +#define LSM6DSV_REG_FIFO_STATUS1 0x1B // DIFF_FIFO [7:0] +#define LSM6DSV_REG_FIFO_STATUS2 0x1C // flags + DIFF_FIFO [8] +#define LSM6DSV_FIFO_STATUS2_DIFF_FIFO_8 (1U << 0) + +// ---- Status register (R) ---- +#define LSM6DSV_REG_STATUS 0x1E +#define LSM6DSV_STATUS_XLDA (1U << 0) // accel data available +#define LSM6DSV_STATUS_GDA (1U << 1) // gyro data available +#define LSM6DSV_STATUS_TDA (1U << 2) // temperature data available + +// ---- Data output registers (R) ---- +#define LSM6DSV_REG_OUT_TEMP_L 0x20 // temperature output (16-bit) +#define LSM6DSV_REG_OUTX_L_G 0x22 // gyro XYZ output (6 bytes) +#define LSM6DSV_REG_OUTX_L_A 0x28 // accel XYZ output (6 bytes) + +// ---- HAODR configuration register (R/W) ---- +// [1:0] HAODR_SEL: high-accuracy ODR mode selection +#define LSM6DSV_REG_HAODR_CFG 0x62 +#define LSM6DSV_HAODR_CFG_MODE1 0x01 + +// HAODR mode-1 ODR codes (written to CTRL1/CTRL2 ODR_XL/ODR_G [3:0]) +#define LSM6DSV_MODE1_ODR_125HZ 0x06 +#define LSM6DSV_MODE1_ODR_250HZ 0x07 +#define LSM6DSV_MODE1_ODR_500HZ 0x08 +#define LSM6DSV_MODE1_ODR_1000HZ 0x09 +#define LSM6DSV_MODE1_ODR_2000HZ 0x0A +#define LSM6DSV_MODE1_ODR_4000HZ 0x0B +#define LSM6DSV_MODE1_ODR_8000HZ 0x0C + +// ---- FIFO data output registers (R) ---- +#define LSM6DSV_REG_FIFO_DATA_OUT_TAG 0x78 // FIFO tag byte +#define LSM6DSV_REG_FIFO_DATA_OUT_X_L 0x79 // FIFO data start + +// ---- SPI protocol ---- +#define LSM6DSV_SPI_READ_FLAG 0x80 + +// ---- Driver timing constants ---- +#define LSM6DSV_DEFAULT_BACKEND_RATE_HZ 1000 +#define LSM6DSV_INIT_MAX_TRIES 5 +#define LSM6DSV_RESET_TIMEOUT_MS 100 +#define LSM6DSV_DATA_READY_TIMEOUT_MS 20 +#define LSM6DSV_POWERUP_DELAY_MS 5 + +// ---- FIFO sizing ---- +#define LSM6DSV_PRIMARY_FIFO_WATERMARK_WORDS 2 +#define LSM6DSV_FIFO_MAX_DRAIN_WORDS 32 +#define LSM6DSV_FIFO_BURST_WORDS 16 + +// temperature update interval in milliseconds +#define LSM6DSV_TEMPERATURE_UPDATE_MS 100 + +// ---- Temperature conversion ---- +#define LSM6DSV_TEMPERATURE_ZERO_C 25.0f +#define LSM6DSV_TEMPERATURE_SENSITIVITY 256.0f // LSB/°C + +// ---- Accelerometer sensitivity (mg/LSB → m/s²) ---- +#define LSM6DSV_ACCEL_SCALE_2G (GRAVITY_MSS * 2.0f / 32768.0f) +#define LSM6DSV_ACCEL_SCALE_4G (GRAVITY_MSS * 4.0f / 32768.0f) +#define LSM6DSV_ACCEL_SCALE_8G (GRAVITY_MSS * 8.0f / 32768.0f) +#define LSM6DSV_ACCEL_SCALE_16G (GRAVITY_MSS * 16.0f / 32768.0f) + +// ---- Gyroscope sensitivity per ST datasheet (mdps/LSB → rad/s) ---- +#define LSM6DSV_GYRO_SCALE_125DPS radians(4.375f / 1000.0f) +#define LSM6DSV_GYRO_SCALE_250DPS radians(8.75f / 1000.0f) +#define LSM6DSV_GYRO_SCALE_500DPS radians(17.50f / 1000.0f) +#define LSM6DSV_GYRO_SCALE_1000DPS radians(35.0f / 1000.0f) +#define LSM6DSV_GYRO_SCALE_2000DPS radians(70.0f / 1000.0f) +#define LSM6DSV_GYRO_SCALE_4000DPS radians(140.0f / 1000.0f) + +struct PACKED RawFifoWord { + uint8_t tag; + le16_t axis[3]; +}; + +static_assert(sizeof(RawFifoWord) == 7, "RawFifoWord must be 7 bytes"); +constexpr uint16_t LSM6DSV_FIFO_BURST_BUFFER_SIZE = LSM6DSV_FIFO_BURST_WORDS * sizeof(RawFifoWord) + 1; + +} + +AP_InertialSensor_LSM6DSV::AP_InertialSensor_LSM6DSV(AP_InertialSensor &imu, + AP_HAL::OwnPtr dev, + enum Rotation rotation) + : AP_InertialSensor_Backend(imu) + , _dev(std::move(dev)) + , _rotation(rotation) + , _accel_scale(LSM6DSV_ACCEL_SCALE_16G) + , _gyro_scale(LSM6DSV_GYRO_SCALE_2000DPS) +{ +} + +AP_InertialSensor_LSM6DSV::~AP_InertialSensor_LSM6DSV() +{ + if (_fifo_buffer != nullptr) { + hal.util->free_type(_fifo_buffer, LSM6DSV_FIFO_BURST_BUFFER_SIZE, + AP_HAL::Util::MEM_DMA_SAFE); + } +} + +AP_InertialSensor_Backend *AP_InertialSensor_LSM6DSV::probe(AP_InertialSensor &imu, + AP_HAL::OwnPtr dev, + enum Rotation rotation) +{ + if (!dev) { + return nullptr; + } + + auto *sensor = NEW_NOTHROW AP_InertialSensor_LSM6DSV(imu, std::move(dev), rotation); + if (sensor == nullptr) { + return nullptr; + } + + if (!sensor->init()) { + delete sensor; + return nullptr; + } + + return sensor; +} + +void AP_InertialSensor_LSM6DSV::start() +{ + // pre-fetch instance numbers for checking fast sampling settings + if (!_imu.get_gyro_instance(gyro_instance) || !_imu.get_accel_instance(accel_instance)) { + return; + } + + // determine fast sampling rate (SPI only) + _backend_rate_hz = LSM6DSV_DEFAULT_BACKEND_RATE_HZ; + if (enable_fast_sampling(accel_instance) && get_fast_sampling_rate() > 1) { + _fast_sampling = (_dev->bus_type() == AP_HAL::Device::BUS_TYPE_SPI); + } + if (_fast_sampling) { + _backend_rate_hz = calculate_backend_rate(LSM6DSV_DEFAULT_BACKEND_RATE_HZ); + } + _backend_period_us = 1000000UL / _backend_rate_hz; + + if (!_imu.register_accel(accel_instance, _backend_rate_hz, _dev->get_bus_id_devtype(DEVTYPE_INS_LSM6DSV)) || + !_imu.register_gyro(gyro_instance, _backend_rate_hz, _dev->get_bus_id_devtype(DEVTYPE_INS_LSM6DSV))) { + return; + } + + { + WITH_SEMAPHORE(_dev->get_semaphore()); + if (!write_register(LSM6DSV_REG_FIFO_CTRL1, 0x00, true) || + !write_register(LSM6DSV_REG_FIFO_CTRL2, 0x00, true) || + !write_register(LSM6DSV_REG_FIFO_CTRL3, LSM6DSV_FIFO_CTRL3_BDR_DISABLED, true) || + !write_register(LSM6DSV_REG_FIFO_CTRL4, LSM6DSV_FIFO_CTRL4_MODE_BYPASS, true)) { + return; + } + if (!configure_primary_fifo()) { + return; + } + + // re-configure ODR registers for the target sampling rate + const uint8_t odr = odr_code_for_rate(_backend_rate_hz); + write_register(LSM6DSV_REG_CTRL1, LSM6DSV_CTRL_MODE_HAODR | odr, true); + write_register(LSM6DSV_REG_CTRL2, LSM6DSV_CTRL_MODE_HAODR | odr, true); + configure_primary_fifo(); + } + + set_gyro_orientation(gyro_instance, _rotation); + set_accel_orientation(accel_instance, _rotation); + + _fifo_buffer = static_cast(hal.util->malloc_type(LSM6DSV_FIFO_BURST_BUFFER_SIZE, + AP_HAL::Util::MEM_DMA_SAFE)); + if (_fifo_buffer == nullptr) { + AP_HAL::panic("LSM6DSV: Unable to allocate FIFO buffer"); + } + + periodic_handle = _dev->register_periodic_callback(_backend_period_us, + FUNCTOR_BIND_MEMBER(&AP_InertialSensor_LSM6DSV::poll_data, void)); +} + +bool AP_InertialSensor_LSM6DSV::update() +{ + update_accel(accel_instance); + update_gyro(gyro_instance); + return true; +} + +bool AP_InertialSensor_LSM6DSV::get_output_banner(char* banner, uint8_t banner_len) +{ + snprintf(banner, banner_len, "IMU%u: LSM6DSV16X %s sampling %.1fkHz", + gyro_instance, + _fast_sampling ? "fast" : "normal", + _backend_rate_hz * 0.001f); + return true; +} + +bool AP_InertialSensor_LSM6DSV::init() +{ + _dev->set_read_flag(LSM6DSV_SPI_READ_FLAG); + return hardware_init(); +} + +bool AP_InertialSensor_LSM6DSV::hardware_init() +{ + hal.scheduler->delay(LSM6DSV_POWERUP_DELAY_MS); + + WITH_SEMAPHORE(_dev->get_semaphore()); + _dev->set_speed(AP_HAL::Device::SPEED_LOW); + if (!_dev->setup_checked_registers(14, 20)) { + return false; + } + + for (uint8_t attempt = 0; attempt < LSM6DSV_INIT_MAX_TRIES; attempt++) { + if (!check_whoami()) { + continue; + } + + switch (_lsm6dsv_type) { + case LSM6DSV_Type::LSM6DSV16X: + _gyro_scale = LSM6DSV_GYRO_SCALE_2000DPS; + _accel_scale = LSM6DSV_ACCEL_SCALE_16G; + break; + } + + if (!reset_device()) { + continue; + } + + if (!configure_gyro()) { + continue; + } + + if (!configure_accel()) { + continue; + } + + if (!write_register(LSM6DSV_REG_HAODR_CFG, LSM6DSV_HAODR_CFG_MODE1, true)) { + continue; + } + + if (!write_register(LSM6DSV_REG_CTRL1, LSM6DSV_CTRL_MODE_HAODR | LSM6DSV_MODE1_ODR_1000HZ, true)) { + continue; + } + + if (!write_register(LSM6DSV_REG_CTRL2, LSM6DSV_CTRL_MODE_HAODR | LSM6DSV_MODE1_ODR_1000HZ, true)) { + continue; + } + + if (!write_register(LSM6DSV_REG_CTRL3, LSM6DSV_CTRL3_BDU | LSM6DSV_CTRL3_IF_INC, true)) { + continue; + } + + if (!write_register(LSM6DSV_REG_FIFO_CTRL4, 0x00, true)) { + continue; + } + + if (!wait_for_data_ready()) { + continue; + } + + _dev->set_speed(AP_HAL::Device::SPEED_HIGH); + return true; + } + + _dev->set_speed(AP_HAL::Device::SPEED_HIGH); + return false; +} + +bool AP_InertialSensor_LSM6DSV::check_whoami() +{ + if (!read_registers(LSM6DSV_REG_WHO_AM_I, &_whoami, 1)) { + return false; + } + + switch (_whoami) { + case LSM6DSV_ID_LSM6DSV16X: + _lsm6dsv_type = LSM6DSV_Type::LSM6DSV16X; + return true; + } + + return false; +} + +bool AP_InertialSensor_LSM6DSV::reset_device() +{ + if (!write_register(LSM6DSV_REG_CTRL3, LSM6DSV_CTRL3_SW_RESET)) { + return false; + } + + const uint32_t start_ms = AP_HAL::millis(); + while (AP_HAL::millis() - start_ms < LSM6DSV_RESET_TIMEOUT_MS) { + uint8_t ctrl3 = 0; + hal.scheduler->delay(1); + if (!read_registers(LSM6DSV_REG_CTRL3, &ctrl3, 1)) { + continue; + } + if ((ctrl3 & LSM6DSV_CTRL3_SW_RESET) == 0) { + return true; + } + } + + return false; +} + +bool AP_InertialSensor_LSM6DSV::configure_gyro() +{ + return write_register(LSM6DSV_REG_CTRL6, LSM6DSV_CTRL6_FS_G_2000DPS, true); +} + +bool AP_InertialSensor_LSM6DSV::configure_accel() +{ +#if LSM6DSV_ACCEL_LPF2_ENABLED + const uint8_t ctrl8 = LSM6DSV_CTRL8_FS_XL_16G | LSM6DSV_ACCEL_LPF2_BW; + return write_register(LSM6DSV_REG_CTRL8, ctrl8, true) && + write_register(LSM6DSV_REG_CTRL9, LSM6DSV_CTRL9_LPF2_XL_EN, true); +#else + return write_register(LSM6DSV_REG_CTRL8, LSM6DSV_CTRL8_FS_XL_16G, true); +#endif +} + +bool AP_InertialSensor_LSM6DSV::configure_primary_fifo() +{ + const uint8_t odr = odr_code_for_rate(_backend_rate_hz); + const uint8_t fifo_ctrl3 = uint8_t((odr << 4) | odr); + + return write_register(LSM6DSV_REG_FIFO_CTRL1, + uint8_t(LSM6DSV_PRIMARY_FIFO_WATERMARK_WORDS & 0xFFU), + true) && + write_register(LSM6DSV_REG_FIFO_CTRL2, 0x00, true) && + write_register(LSM6DSV_REG_FIFO_CTRL3, fifo_ctrl3, true) && + write_register(LSM6DSV_REG_FIFO_CTRL4, LSM6DSV_FIFO_CTRL4_MODE_CONTINUOUS, true); +} + +uint8_t AP_InertialSensor_LSM6DSV::odr_code_for_rate(uint16_t rate_hz) const +{ + switch (rate_hz) { + case 8000: return LSM6DSV_MODE1_ODR_8000HZ; + case 4000: return LSM6DSV_MODE1_ODR_4000HZ; + case 2000: return LSM6DSV_MODE1_ODR_2000HZ; + case 1000: + default: return LSM6DSV_MODE1_ODR_1000HZ; + } +} + +// calculate the backend sample rate accounting for fast sampling +// multiplier and loop rate constraints +uint16_t AP_InertialSensor_LSM6DSV::calculate_backend_rate(uint16_t base_rate_hz) const +{ + // constrain the gyro rate to be at least the loop rate + uint8_t min_mult = 1; + if (get_loop_rate_hz() > base_rate_hz) { + min_mult = 2; + } + if (get_loop_rate_hz() > base_rate_hz * 2) { + min_mult = 4; + } + const uint8_t mult = constrain_int16(get_fast_sampling_rate(), min_mult, 8); + return constrain_int16(base_rate_hz * mult, base_rate_hz, 8000); +} + +bool AP_InertialSensor_LSM6DSV::fifo_tag_supported_for_primary(const FifoTag tag) +{ + return tag == FifoTag::GyroNC || tag == FifoTag::AccelNC; +} + +AP_InertialSensor_LSM6DSV::FifoTag AP_InertialSensor_LSM6DSV::decode_fifo_tag(const uint8_t raw_tag) +{ + switch ((raw_tag >> 3) & 0x1FU) { + case 0x00: + return FifoTag::Empty; + case 0x01: + return FifoTag::GyroNC; + case 0x02: + return FifoTag::AccelNC; + case 0x03: + return FifoTag::Temperature; + case 0x04: + return FifoTag::Timestamp; + case 0x05: + return FifoTag::CfgChange; + case 0x06: + return FifoTag::AccelNC_T2; + case 0x07: + return FifoTag::AccelNC_T1; + case 0x08: + return FifoTag::Accel2xC; + case 0x09: + return FifoTag::Accel3xC; + case 0x0A: + return FifoTag::GyroNC_T2; + case 0x0B: + return FifoTag::GyroNC_T1; + case 0x0C: + return FifoTag::Gyro2xC; + case 0x0D: + return FifoTag::Gyro3xC; + case 0x1D: + return FifoTag::RouteExt; + default: + return FifoTag::Unsupported; + } +} + +uint8_t AP_InertialSensor_LSM6DSV::decode_fifo_tag_count(const uint8_t raw_tag) +{ + return (raw_tag >> 1) & 0x03U; +} + +bool AP_InertialSensor_LSM6DSV::wait_for_data_ready() +{ + for (uint8_t i = 0; i < LSM6DSV_DATA_READY_TIMEOUT_MS; i++) { + uint8_t status = 0; + hal.scheduler->delay(1); + if (!read_registers(LSM6DSV_REG_STATUS, &status, 1)) { + continue; + } + if ((status & LSM6DSV_STATUS_GDA) != 0 && + (status & LSM6DSV_STATUS_XLDA) != 0) { + return true; + } + } + + return false; +} + +bool AP_InertialSensor_LSM6DSV::read_registers(uint8_t reg, uint8_t *data, uint8_t len) +{ + return _dev->read_registers(reg, data, len); +} + +bool AP_InertialSensor_LSM6DSV::write_register(uint8_t reg, uint8_t value, bool checked) +{ + return _dev->write_register(reg, value, checked); +} + +bool AP_InertialSensor_LSM6DSV::read_fifo_status(FifoFrame &frame, uint32_t now_us) +{ + uint8_t fifo_status[2] {}; + if (!read_registers(LSM6DSV_REG_FIFO_STATUS1, fifo_status, sizeof(fifo_status))) { + _inc_accel_error_count(accel_instance); + _inc_gyro_error_count(gyro_instance); + return false; + } + + frame.unread_words = fifo_status[0] | + (((fifo_status[1] & LSM6DSV_FIFO_STATUS2_DIFF_FIFO_8) != 0U) ? 0x100U : 0U); + + return true; +} + +bool AP_InertialSensor_LSM6DSV::read_fifo_words_block(const uint16_t n_words, uint32_t now_us) +{ + if (_fifo_buffer == nullptr || n_words == 0 || n_words > LSM6DSV_FIFO_BURST_WORDS) { + return false; + } + + _fifo_buffer[0] = LSM6DSV_REG_FIFO_DATA_OUT_TAG | LSM6DSV_SPI_READ_FLAG; + // zero MOSI payload for SPI full-duplex read + memset(_fifo_buffer + 1, 0, n_words * sizeof(RawFifoWord)); + if (!_dev->transfer_fullduplex(_fifo_buffer, n_words * sizeof(RawFifoWord) + 1)) { + _inc_accel_error_count(accel_instance); + _inc_gyro_error_count(gyro_instance); + return false; + } + + return true; +} + +bool AP_InertialSensor_LSM6DSV::consume_fifo_word(FifoFrame &frame, SampleFrame &sample, const uint8_t *raw_word) +{ + RawFifoWord raw; + memcpy(&raw, raw_word, sizeof(raw)); + + frame.tag = decode_fifo_tag(raw.tag); + frame.tag_count = decode_fifo_tag_count(raw.tag); + + if (!fifo_tag_supported_for_primary(frame.tag)) { + return true; + } + + const Vector3f axes{ + float(int16_t(le16toh(raw.axis[0]))), + float(int16_t(le16toh(raw.axis[1]))), + float(int16_t(le16toh(raw.axis[2]))), + }; + + switch (frame.tag) { + case FifoTag::GyroNC: + sample.gyro = axes * _gyro_scale; + break; + case FifoTag::AccelNC: + sample.accel = axes * _accel_scale; + break; + default: + return false; + } + + return true; +} + +uint16_t AP_InertialSensor_LSM6DSV::drain_fifo(uint32_t now_us) +{ + FifoFrame frame{}; + + if (!read_fifo_status(frame, now_us)) { + return 0; + } + + if (frame.unread_words == 0) { + return 0; + } + + uint16_t samples_published = 0; + uint16_t drained = 0; + + while (drained < frame.unread_words && drained < LSM6DSV_FIFO_MAX_DRAIN_WORDS) { + const uint16_t remaining = MIN(uint16_t(frame.unread_words - drained), + uint16_t(LSM6DSV_FIFO_MAX_DRAIN_WORDS - drained)); + const uint16_t block_words = MIN(remaining, LSM6DSV_FIFO_BURST_WORDS); + + if (!read_fifo_words_block(block_words, now_us)) { + break; + } + + const uint8_t *raw_word = _fifo_buffer + 1; + for (uint16_t i = 0; i < block_words; i++, raw_word += sizeof(RawFifoWord)) { + if (!consume_fifo_word(frame, frame.sample, raw_word)) { + return samples_published; + } + drained++; + if (frame.tag == FifoTag::GyroNC) { + publish_gyro_sample(frame.sample); + samples_published++; + frame.sample.gyro.zero(); + } else if (frame.tag == FifoTag::AccelNC) { + publish_accel_sample(frame.sample); + frame.sample.accel.zero(); + } + } + } + + if (samples_published > 0) { + _dev->adjust_periodic_callback(periodic_handle, _backend_period_us); + } + + return samples_published; +} + +void AP_InertialSensor_LSM6DSV::publish_gyro_sample(SampleFrame &sample) +{ + _rotate_and_correct_gyro(gyro_instance, sample.gyro); + _notify_new_gyro_raw_sample(gyro_instance, sample.gyro); +} + +void AP_InertialSensor_LSM6DSV::publish_accel_sample(SampleFrame &sample) +{ + _rotate_and_correct_accel(accel_instance, sample.accel); + _notify_new_accel_raw_sample(accel_instance, sample.accel); + update_temperature(); +} + +void AP_InertialSensor_LSM6DSV::check_register_monitor() +{ + _dev->set_speed(AP_HAL::Device::SPEED_LOW); + AP_HAL::Device::checkreg reg; + if (!_dev->check_next_register(reg)) { + log_register_change(_dev->get_bus_id(), reg); + _inc_accel_error_count(accel_instance); + _inc_gyro_error_count(gyro_instance); + } + _dev->set_speed(AP_HAL::Device::SPEED_HIGH); +} + +void AP_InertialSensor_LSM6DSV::update_temperature() +{ + const uint32_t now_ms = AP_HAL::millis(); + if (now_ms - _temperature_last_ms < LSM6DSV_TEMPERATURE_UPDATE_MS) { + return; + } + _temperature_last_ms = now_ms; + + uint8_t tbuf[2]; + if (!read_registers(LSM6DSV_REG_OUT_TEMP_L, tbuf, sizeof(tbuf))) { + _inc_accel_error_count(accel_instance); + return; + } + const int16_t temperature_raw = int16_t(uint16_t(tbuf[0] | (tbuf[1] << 8))); + const float temp_degc = LSM6DSV_TEMPERATURE_ZERO_C + temperature_raw / LSM6DSV_TEMPERATURE_SENSITIVITY; + _publish_temperature(accel_instance, temp_degc); +} + +void AP_InertialSensor_LSM6DSV::poll_data() +{ + drain_fifo(AP_HAL::micros()); + check_register_monitor(); +} diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_LSM6DSV.h b/libraries/AP_InertialSensor/AP_InertialSensor_LSM6DSV.h new file mode 100644 index 0000000000000..e1943cfc97e9e --- /dev/null +++ b/libraries/AP_InertialSensor/AP_InertialSensor_LSM6DSV.h @@ -0,0 +1,119 @@ +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +#pragma once + +#include +#include + +#include "AP_InertialSensor.h" +#include "AP_InertialSensor_Backend.h" + +#ifndef LSM6DSV_DEFAULT_ROTATION +#define LSM6DSV_DEFAULT_ROTATION ROTATION_NONE +#endif + +class AP_InertialSensor_LSM6DSV : public AP_InertialSensor_Backend { +public: + enum class LSM6DSV_Type : uint8_t { + LSM6DSV16X, + }; + + static AP_InertialSensor_Backend *probe(AP_InertialSensor &imu, + AP_HAL::OwnPtr dev, + enum Rotation rotation=LSM6DSV_DEFAULT_ROTATION); + + ~AP_InertialSensor_LSM6DSV() override; + + void start() override; + bool update() override; + bool get_output_banner(char* banner, uint8_t banner_len) override; + +private: + enum class FifoTag : uint8_t { + Empty = 0x00, + GyroNC = 0x01, + AccelNC = 0x02, + Temperature = 0x03, + Timestamp = 0x04, + CfgChange = 0x05, + AccelNC_T2 = 0x06, + AccelNC_T1 = 0x07, + Accel2xC = 0x08, + Accel3xC = 0x09, + GyroNC_T2 = 0x0A, + GyroNC_T1 = 0x0B, + Gyro2xC = 0x0C, + Gyro3xC = 0x0D, + RouteExt = 0x1D, + Unsupported = 0xFF, + }; + + struct SampleFrame { + Vector3f gyro; + Vector3f accel; + }; + + struct FifoFrame { + SampleFrame sample; + FifoTag tag; + uint16_t unread_words; + uint8_t tag_count; + }; + + AP_InertialSensor_LSM6DSV(AP_InertialSensor &imu, + AP_HAL::OwnPtr dev, + enum Rotation rotation); + + bool init(); + bool hardware_init(); + bool check_whoami(); + bool reset_device(); + bool configure_gyro(); + bool configure_accel(); + bool configure_primary_fifo(); + bool wait_for_data_ready(); + + bool read_registers(uint8_t reg, uint8_t *data, uint8_t len); + bool write_register(uint8_t reg, uint8_t value, bool checked=false); + bool read_fifo_status(FifoFrame &frame, uint32_t now_us); + bool read_fifo_words_block(uint16_t n_words, uint32_t now_us); + bool consume_fifo_word(FifoFrame &frame, SampleFrame &sample, const uint8_t *raw_word); + uint16_t drain_fifo(uint32_t now_us); + void publish_gyro_sample(SampleFrame &sample); + void publish_accel_sample(SampleFrame &sample); + void check_register_monitor(); + void update_temperature(); + uint8_t odr_code_for_rate(uint16_t rate_hz) const; + uint16_t calculate_backend_rate(uint16_t base_rate_hz) const; + + static bool fifo_tag_supported_for_primary(FifoTag tag); + static FifoTag decode_fifo_tag(uint8_t raw_tag); + static uint8_t decode_fifo_tag_count(uint8_t raw_tag); + + void poll_data(); + + AP_HAL::OwnPtr _dev; + AP_HAL::Device::PeriodicHandle periodic_handle; + enum Rotation _rotation; + float _accel_scale; + float _gyro_scale; + uint8_t _whoami; + uint32_t _temperature_last_ms; + uint16_t _backend_rate_hz; + uint32_t _backend_period_us; + bool _fast_sampling = false; + LSM6DSV_Type _lsm6dsv_type; + uint8_t *_fifo_buffer; +}; diff --git a/libraries/AP_Math/SCurve.cpp b/libraries/AP_Math/SCurve.cpp index 35234608aa103..a0cb697073624 100644 --- a/libraries/AP_Math/SCurve.cpp +++ b/libraries/AP_Math/SCurve.cpp @@ -55,7 +55,7 @@ void SCurve::init() is_arc_segment = false; seg_delta.zero(); - seg_length = 0.0; + seg_length = 0.0f; arc = {}; } @@ -84,7 +84,7 @@ void SCurve::calculate_track(const Vector3p &origin, const Vector3p &destination const Vector2f chord = seg_delta.xy(); const float chord_length = seg_delta.xy().length(); - if (!is_positive(chord_length) || fabsf(wrap_PI(arc_ang_rad)) < radians(1.0)) { + if (!is_positive(chord_length) || fabsf(wrap_PI(arc_ang_rad)) < radians(1.0f)) { // straight segment is_arc_segment = false; arc.angle_rad = 0.0f; @@ -98,7 +98,7 @@ void SCurve::calculate_track(const Vector3p &origin, const Vector3p &destination arc.radius_ne = fabsf(chord_length / (2.0f * fabsf(sinf(arc.angle_rad * 0.5f)))); const float center_offset = safe_sqrt(sq(arc.radius_ne) - sq(chord_length * 0.5f)); // perpendicular offset from chord to circle center const float turn_dir = is_negative(arc.angle_rad) ? -1.0f : 1.0f; // -1 for CCW, 1 for CW - const float center_side = (is_positive(wrap_PI(fabsf(arc.angle_rad)))) ? 1.0f : -1.0f; // -1 for CCW, 1 for CW + const float center_side = (is_positive(wrap_PI(fabsf(arc.angle_rad)))) ? 1.0f : -1.0f; // 1 for |angle| < PI, -1 for |angle| > PI if (!is_zero(arc.radius_ne) && !is_zero(chord_length)) { arc.center_ne = chord * 0.5f + Vector2f(-chord.y, chord.x) * (center_side * turn_dir * center_offset / chord_length); arc.length_ne = arc.radius_ne * fabsf(arc.angle_rad); @@ -294,7 +294,7 @@ void SCurve::set_speed_max(float speed_xy, float speed_up, float speed_down) // add to constant velocity segment to end at the correct position const float dP = MAX(0.0f, Pend - segment[SEG_DECEL_END].end_pos); - const float t15 = dP / segment[SEG_CONST].end_vel; + const float t15 = is_positive(segment[SEG_CONST].end_vel) ? dP / segment[SEG_CONST].end_vel : 0.0f; for (uint8_t i = SEG_CONST; i <= SEG_DECEL_END; i++) { segment[i].end_time += t15; segment[i].end_pos += dP; @@ -321,14 +321,14 @@ void SCurve::set_speed_max(float speed_xy, float speed_up, float speed_down) float t2 = 0; float t4 = 0; float t6 = 0; - float jerk_time = MIN(powf((fabsf(vel_max - segment[SEG_ACCEL_END].end_vel) * M_PI) / (4 * snap_max), 1/3), jerk_max * M_PI / (2 * snap_max)); - if ((vel_max < segment[SEG_ACCEL_END].end_vel) && (jerk_time*12.0f < L/segment[SEG_ACCEL_END].end_vel)) { + float jerk_time = MIN(powf((fabsf(vel_max - segment[SEG_ACCEL_END].end_vel) * M_PI) / (4.0f * snap_max), 1.0f / 3.0f), jerk_max * M_PI / (2.0f * snap_max)); + if ((vel_max < segment[SEG_ACCEL_END].end_vel) && (jerk_time * 12.0f < L / segment[SEG_ACCEL_END].end_vel)) { // we have a problem here with small segments. calculate_path(snap_max, jerk_max, vel_max, accel_max, segment[SEG_ACCEL_END].end_vel, L * 0.5f, Jm, tj, t6, t4, t2); Jm = -Jm; - } else if ((vel_max > segment[SEG_ACCEL_END].end_vel) && (L/(jerk_time*12.0f) > segment[SEG_ACCEL_END].end_vel)) { - float Vm = MIN(vel_max, L/(jerk_time*12.0f)); + } else if ((vel_max > segment[SEG_ACCEL_END].end_vel) && (L / (jerk_time * 12.0f) > segment[SEG_ACCEL_END].end_vel)) { + float Vm = MIN(vel_max, L / (jerk_time * 12.0f)); calculate_path(snap_max, jerk_max, segment[SEG_ACCEL_END].end_vel, accel_max, Vm, L * 0.5f, Jm, tj, t2, t4, t6); } @@ -372,7 +372,7 @@ void SCurve::set_speed_max(float speed_xy, float speed_up, float speed_down) // add to constant velocity segment to end at the correct position const float dP = MAX(0.0f, Pend - segment[SEG_DECEL_END].end_pos); - const float t15 = dP / segment[SEG_CONST].end_vel; + const float t15 = is_positive(segment[SEG_CONST].end_vel) ? dP / segment[SEG_CONST].end_vel : 0.0f; for (uint8_t i = SEG_CONST; i <= SEG_DECEL_END; i++) { segment[i].end_time += t15; segment[i].end_pos += dP; @@ -454,7 +454,7 @@ float SCurve::set_origin_speed_max(float speed) // add to constant velocity segment to end at the correct position const float dP = MAX(0.0f, seg_length - segment[SEG_DECEL_END].end_pos); - const float t15 = dP / segment[SEG_CONST].end_vel; + const float t15 = is_positive(segment[SEG_CONST].end_vel) ? dP / segment[SEG_CONST].end_vel : 0.0f; for (uint8_t i = SEG_CONST; i <= SEG_DECEL_END; i++) { segment[i].end_time += t15; segment[i].end_pos += dP; @@ -509,7 +509,7 @@ void SCurve::set_destination_speed_max(float speed) // add to constant velocity segment to end at the correct position const float dP = MAX(0.0f, seg_length - segment[SEG_DECEL_END].end_pos); - const float t15 = dP / segment[SEG_CONST].end_vel; + const float t15 = is_positive(segment[SEG_CONST].end_vel) ? dP / segment[SEG_CONST].end_vel : 0.0f; for (uint8_t i = SEG_CONST; i <= SEG_DECEL_END; i++) { segment[i].end_time += t15; segment[i].end_pos += dP; @@ -668,7 +668,7 @@ void SCurve::project_scurve_onto_track(float scurve_A1, float scurve_V1, float s float SCurve::time_end() const { if (num_segs != segments_max) { - return 0.0; + return 0.0f; } return segment[SEG_DECEL_END].end_time; } @@ -677,7 +677,7 @@ float SCurve::time_end() const float SCurve::get_time_remaining() const { if (num_segs != segments_max) { - return 0.0; + return 0.0f; } return segment[SEG_DECEL_END].end_time - time; } @@ -686,7 +686,7 @@ float SCurve::get_time_remaining() const float SCurve::get_accel_finished_time() const { if (num_segs != segments_max) { - return 0.0; + return 0.0f; } return segment[SEG_ACCEL_END].end_time; } @@ -705,7 +705,7 @@ bool SCurve::braking() const float SCurve::time_accel_end() const { if (num_segs != segments_max) { - return 0.0; + return 0.0f; } return segment[SEG_ACCEL_END].end_time; } @@ -715,7 +715,7 @@ float SCurve::time_accel_end() const float SCurve::time_decel_start() const { if (num_segs != segments_max) { - return 0.0; + return 0.0f; } return segment[SEG_DECEL_START].end_time; } @@ -723,17 +723,17 @@ float SCurve::time_decel_start() const // increment the internal time void SCurve::advance_time(float dt) { - time = MIN(time+dt, time_end()); + time = MIN(time + dt, time_end()); } // calculate the jerk, acceleration, velocity and position at the provided time void SCurve::get_jerk_accel_vel_pos_at_time(float time_now, float &Jt_out, float &At_out, float &Vt_out, float &Pt_out) const { // start with zeros as function is void and we want to guarantee all outputs are initialised - Jt_out = 0; - At_out = 0; - Vt_out = 0; - Pt_out = 0; + Jt_out = 0.0f; + At_out = 0.0f; + Vt_out = 0.0f; + Pt_out = 0.0f; if (num_segs != segments_max) { return; } @@ -801,7 +801,7 @@ void SCurve::calc_javp_for_segment_const_jerk(float time_now, float J0, float A0 void SCurve::calc_javp_for_segment_incr_jerk(float time_now, float tj, float Jm, float A0, float V0, float P0, float &Jt, float &At, float &Vt, float &Pt) const { if (!is_positive(tj)) { - Jt = 0.0; + Jt = 0.0f; At = A0; Vt = V0; Pt = P0; @@ -819,7 +819,7 @@ void SCurve::calc_javp_for_segment_incr_jerk(float time_now, float tj, float Jm, void SCurve::calc_javp_for_segment_decr_jerk(float time_now, float tj, float Jm, float A0, float V0, float P0, float &Jt, float &At, float &Vt, float &Pt) const { if (!is_positive(tj)) { - Jt = 0.0; + Jt = 0.0f; At = A0; Vt = V0; Pt = P0; @@ -888,7 +888,7 @@ void SCurve::add_segments(float L) // Vm - maximum constant velocity // L - Length of the path // tj_out, t2_out, t4_out, t6_out are the segment durations needed to achieve the kinematic path specified by the input variables -void SCurve::calculate_path(float Sm, float Jm, float V0, float Am, float Vm, float L,float &Jm_out, float &tj_out, float &t2_out, float &t4_out, float &t6_out) +void SCurve::calculate_path(float Sm, float Jm, float V0, float Am, float Vm, float L, float &Jm_out, float &tj_out, float &t2_out, float &t4_out, float &t6_out) { // init outputs Jm_out = 0.0f; @@ -911,18 +911,21 @@ void SCurve::calculate_path(float Sm, float Jm, float V0, float Am, float Vm, fl return; } - float tj = Jm * M_PI / (2 * Sm); - float At = MIN(MIN(Am, - (Vm - V0) / (2.0f * tj) ), - (L + 4.0f * V0 * tj) / (4.0f * sq(tj)) ); + float tj = Jm * M_PI / (2.0f * Sm); + float At = MIN(MIN(Am, + (Vm - V0) / (2.0f * tj) ), + (L - 4.0f * V0 * tj) / (4.0f * sq(tj)) ); + if (!is_positive(At)) { + return; + } if (fabsf(At) < Jm * tj) { if (is_zero(V0)) { // we do not have a solution for non-zero initial velocity tj = MIN( MIN( MIN( tj, - powf((L * M_PI) / (8.0 * Sm), 1.0/4.0) ), - powf((Vm * M_PI) / (4.0 * Sm), 1.0/3.0) ), - safe_sqrt((Am * M_PI) / (2.0 * Sm)) ); - Jm = 2.0 * Sm * tj / M_PI; + powf((L * M_PI) / (8.0f * Sm), 1.0f / 4.0f) ), + powf((Vm * M_PI) / (4.0f * Sm), 1.0f / 3.0f) ), + safe_sqrt((Am * M_PI) / (2.0f * Sm)) ); + Jm = 2.0f * Sm * tj / M_PI; Am = Jm * tj; } else { // When doing speed change we use fixed tj and adjust Jm for small changes @@ -938,7 +941,7 @@ void SCurve::calculate_path(float Sm, float Jm, float V0, float Am, float Vm, fl // solution = 2 - t6 t4 t2 = 0 1 0 t2_out = 0.0f; t4_out = MIN(-(V0 - Vm + Am * tj + (Am * Am) / Jm) / Am, MAX(((Am * Am) * (-3.0f / 2.0f) + safe_sqrt((Am * Am * Am * Am) * (1.0f / 4.0f) + (Jm * Jm) * (V0 * V0) + (Am * Am) * (Jm * Jm) * (tj * tj) * (1.0f / 4.0f) + Am * (Jm * Jm) * L * 2.0f - (Am * Am) * Jm * V0 + (Am * Am * Am) * Jm * tj * (1.0f / 2.0f) - Am * (Jm * Jm) * V0 * tj) - Jm * V0 - Am * Jm * tj * (3.0f / 2.0f)) / (Am * Jm), ((Am * Am) * (-3.0f / 2.0f) - safe_sqrt((Am * Am * Am * Am) * (1.0f / 4.0f) + (Jm * Jm) * (V0 * V0) + (Am * Am) * (Jm * Jm) * (tj * tj) * (1.0f / 4.0f) + Am * (Jm * Jm) * L * 2.0f - (Am * Am) * Jm * V0 + (Am * Am * Am) * Jm * tj * (1.0f / 2.0f) - Am * (Jm * Jm) * V0 * tj) - Jm * V0 - Am * Jm * tj * (3.0f / 2.0f)) / (Am * Jm))); - t4_out = MAX(t4_out, 0.0); + t4_out = MAX(t4_out, 0.0f); t6_out = 0.0f; } } else { @@ -952,7 +955,7 @@ void SCurve::calculate_path(float Sm, float Jm, float V0, float Am, float Vm, fl // solution = 7 - t6 t4 t2 = 1 1 1 t2_out = Am / Jm - tj; t4_out = MIN(-(V0 - Vm + Am * tj + (Am * Am) / Jm) / Am, MAX(((Am * Am) * (-3.0f / 2.0f) + safe_sqrt((Am * Am * Am * Am) * (1.0f / 4.0f) + (Jm * Jm) * (V0 * V0) + (Am * Am) * (Jm * Jm) * (tj * tj) * (1.0f / 4.0f) + Am * (Jm * Jm) * L * 2.0f - (Am * Am) * Jm * V0 + (Am * Am * Am) * Jm * tj * (1.0f / 2.0f) - Am * (Jm * Jm) * V0 * tj) - Jm * V0 - Am * Jm * tj * (3.0f / 2.0f)) / (Am * Jm), ((Am * Am) * (-3.0f / 2.0f) - safe_sqrt((Am * Am * Am * Am) * (1.0f / 4.0f) + (Jm * Jm) * (V0 * V0) + (Am * Am) * (Jm * Jm) * (tj * tj) * (1.0f / 4.0f) + Am * (Jm * Jm) * L * 2.0f - (Am * Am) * Jm * V0 + (Am * Am * Am) * Jm * tj * (1.0f / 2.0f) - Am * (Jm * Jm) * V0 * tj) - Jm * V0 - Am * Jm * tj * (3.0f / 2.0f)) / (Am * Jm))); - t4_out = MAX(t4_out, 0.0); + t4_out = MAX(t4_out, 0.0f); t6_out = t2_out; } } @@ -1064,7 +1067,7 @@ void SCurve::add_segment_incr_jerk(uint8_t &index, float tj, float Jm) if (!is_positive(tj)) { add_segment(index, segment[index - 1].end_time, SegmentType::CONSTANT_JERK, - 0.0, + 0.0f, segment[index - 1].end_accel, segment[index - 1].end_vel, segment[index - 1].end_pos); @@ -1093,7 +1096,7 @@ void SCurve::add_segment_decr_jerk(uint8_t &index, float tj, float Jm) if (!is_positive(tj)) { add_segment(index, segment[index - 1].end_time, SegmentType::CONSTANT_JERK, - 0.0, + 0.0f, segment[index - 1].end_accel, segment[index - 1].end_vel, segment[index - 1].end_pos); diff --git a/libraries/AP_Math/tests/test_scurve.cpp b/libraries/AP_Math/tests/test_scurve.cpp index 22b1a0beda59f..73f6842f7128f 100644 --- a/libraries/AP_Math/tests/test_scurve.cpp +++ b/libraries/AP_Math/tests/test_scurve.cpp @@ -5,18 +5,244 @@ #include #include -TEST(LinesScurve, test_calculate_path) +// Test inputs and expected outputs for each code path in calculate_path. +// +// With Sm=62.8319, Jm=10: tj ≈ 0.25, Jm*tj ≈ 2.5 +// At = MIN(Am, (Vm-V0)/(2*tj), (L - 4*V0*tj)/(4*tj²)) +// ≈ MIN(Am, (Vm-V0)/0.5, (L-V0)/0.25) +// +// Paths exercised: +// B: V0 >= Vm +// C: At <= 0 (requires L < V0 approx, sign fix path) +// D: At0, solution=0 +// G: At0, solution=2 +// H: At>=Jm*tj, solution=5 +// I: At>=Jm*tj, solution=7 +struct PathTest { + const char *name; + float Sm, Jm, V0, Am, Vm, L; + float exp_Jm, exp_tj, exp_t2, exp_t4, exp_t6; +}; + +static const PathTest path_tests[] = { + + // ---- Path B: V0 >= Vm ---- + {"B1_exact", 62.8319, 10, 10, 5, 10, 100, 0, 0, 0, 0, 0}, + {"B2_just", 62.8319, 10, 5.1, 5, 5, 100, 0, 0, 0, 0, 0}, + {"B3_mid", 62.8319, 10, 20, 5, 10, 100, 0, 0, 0, 0, 0}, + {"B4_low", 62.8319, 10, 3, 5, 2, 100, 0, 0, 0, 0, 0}, + + // ---- Path C: At <= 0 (sign fix) ---- + {"C1_just", 62.8319, 10, 5, 5, 10, 4.9, 0, 0, 0, 0, 0}, + {"C2_deep", 62.8319, 10, 8, 5, 10, 5, 0, 0, 0, 0, 0}, + {"C3_v3", 62.8319, 10, 3, 5, 10, 2.9, 0, 0, 0, 0, 0}, + {"C4_hiV0", 62.8319, 10, 9, 5, 10, 8, 0, 0, 0, 0, 0}, + + // ---- Path D: At0, solution=0 ---- + {"F1_nearC", 62.8319, 10, 5, 5, 10, 5.1, 1.60006297f, 0.24999982f, 0, 0, 0}, + {"F2_mid", 62.8319, 10, 1, 5, 10, 1.5, 8.00002861f, 0.24999982f, 0, 0, 0}, + {"F3_v2", 62.8319, 10, 2, 5, 10, 2.3, 4.80003214f, 0.24999982f, 0, 0, 0}, + {"F4_amBind", 62.8319, 10, 0.5, 2, 10, 0.8, 4.80001593f, 0.24999982f, 0, 0, 0}, + + // ---- Path G: At0, solution=2 ---- + {"G1_deep", 62.8319, 10, 1, 2, 10, 50, 8.00000572f, 0.24999982f, 0, 4.00000000f, 0}, + {"G2_mod", 62.8319, 10, 0.5, 2, 10, 10, 8.00000572f, 0.24999982f, 0, 2.16227818f, 0}, + {"G3_nearF", 62.8319, 10, 2, 2, 10, 10, 8.00000572f, 0.24999982f, 0, 1.50000060f, 0}, + {"G4_loV0", 62.8319, 10, 0.1, 2, 10, 50, 8.00000572f, 0.24999982f, 0, 4.44999981f, 0}, + + // ---- Path H: At>=Jm*tj, solution=5 ---- + {"H1_nearI", 62.8319, 10, 0, 5, 3.7, 100, 10.0f, 0.24999982f, 0.24598742f, 0, 0.24598742f}, + {"H2_mid", 62.8319, 10, 0, 5, 3.5, 100, 10.0f, 0.24999982f, 0.22966957f, 0, 0.22966957f}, + {"H3_shortL", 62.8319, 10, 0, 5, 10, 1.5, 10.0f, 0.24999982f, 0.12905994f, 0, 0.12905994f}, + {"H4_v0p", 62.8319, 10, 2, 5, 5.5, 100, 10.0f, 0.24999982f, 0.22966957f, 0, 0.22966957f}, + + // ---- Path I: At>=Jm*tj, solution=7 ---- + {"I1_nearH", 62.8319, 10, 0, 5, 3.8, 100, 10.0f, 0.24999982f, 0.25000018f, 0.01000018f, 0.25000018f}, + {"I2_deep", 62.8319, 10, 0, 5, 10, 100, 10.0f, 0.24999982f, 0.25000018f, 1.25000024f, 0.25000018f}, + {"I3_v0p", 62.8319, 10, 2, 5, 10, 100, 10.0f, 0.24999982f, 0.25000018f, 0.85000020f, 0.25000018f}, + {"I4_lowAm", 62.8319, 10, 0, 3, 5, 100, 10.0f, 0.24999982f, 0.05000019f, 1.11666679f, 0.05000019f}, +}; + +// Segment state used to integrate through the profile +struct SegState { + float A, V, P; +}; + +// Integrate an increasing-jerk segment (raised cosine from 0 to Jm) +static SegState seg_incr_jerk(SegState s, float tj, float Jm) +{ + if (tj <= 0) return s; + const float Alpha = Jm * 0.5f; + const float Beta = M_PI / tj; + const float AT = Alpha * tj; + const float VT = Alpha * (sq(tj) * 0.5f - 2.0f / sq(Beta)); + const float PT = Alpha * ((-1.0f / sq(Beta)) * tj + (1.0f / 6.0f) * powf(tj, 3.0f)); + return {s.A + AT, + s.V + s.A * tj + VT, + s.P + s.V * tj + 0.5f * s.A * sq(tj) + PT}; +} + +// Integrate a constant-jerk segment +static SegState seg_const_jerk(SegState s, float t, float J) +{ + if (t <= 0) return s; + return {s.A + J * t, + s.V + s.A * t + 0.5f * J * sq(t), + s.P + s.V * t + 0.5f * s.A * sq(t) + (1.0f / 6.0f) * J * powf(t, 3.0f)}; +} + +// Integrate a decreasing-jerk segment (raised cosine from Jm to 0) +static SegState seg_decr_jerk(SegState s, float tj, float Jm) +{ + if (tj <= 0) return s; + const float Alpha = Jm * 0.5f; + const float Beta = M_PI / tj; + const float AT = Alpha * tj; + const float VT = Alpha * (sq(tj) * 0.5f - 2.0f / sq(Beta)); + const float PT = Alpha * ((-1.0f / sq(Beta)) * tj + (1.0f / 6.0f) * powf(tj, 3.0f)); + const float A2T = Jm * tj; + const float V2T = Jm * sq(tj); + const float P2T = Alpha * ((-1.0f / sq(Beta)) * 2.0f * tj + (4.0f / 3.0f) * powf(tj, 3.0f)); + return {(s.A - AT) + A2T, + (s.V - VT) + (s.A - AT) * tj + V2T, + (s.P - PT) + (s.V - VT) * tj + 0.5f * (s.A - AT) * sq(tj) + P2T}; +} + +// Integrate a 3-segment jerk block: incr, const, decr +static SegState seg_jerk_block(SegState s, float tj, float Jm, float Tcj, float &peak_A) +{ + s = seg_incr_jerk(s, tj, Jm); + peak_A = MAX(peak_A, fabsf(s.A)); + s = seg_const_jerk(s, Tcj, Jm); + peak_A = MAX(peak_A, fabsf(s.A)); + s = seg_decr_jerk(s, tj, Jm); + peak_A = MAX(peak_A, fabsf(s.A)); + return s; +} + +TEST(SCurveCalcPath, coverage_and_outputs) { - // this test doesn't do much... float Jm_out, tj_out, t2_out, t4_out, t6_out; - SCurve::calculate_path(62.8319, 10, 0, 5, 10, 100, - Jm_out, tj_out, t2_out, t4_out, t6_out); - EXPECT_FLOAT_EQ(Jm_out, 10); - EXPECT_FLOAT_EQ(t2_out, 0.25000018); - EXPECT_FLOAT_EQ(t4_out, 1.2500002); - EXPECT_FLOAT_EQ(t6_out, 0.25000018); + + for (const auto &t : path_tests) { + SCurve::calculate_path(t.Sm, t.Jm, t.V0, t.Am, t.Vm, t.L, + Jm_out, tj_out, t2_out, t4_out, t6_out); + + EXPECT_FLOAT_EQ(Jm_out, t.exp_Jm) << "Jm mismatch: " << t.name; + EXPECT_FLOAT_EQ(tj_out, t.exp_tj) << "tj mismatch: " << t.name; + EXPECT_FLOAT_EQ(t2_out, t.exp_t2) << "t2 mismatch: " << t.name; + EXPECT_FLOAT_EQ(t4_out, t.exp_t4) << "t4 mismatch: " << t.name; + EXPECT_FLOAT_EQ(t6_out, t.exp_t6) << "t6 mismatch: " << t.name; + } } +// Verify that calculate_path outputs, when applied through add_segments logic, +// produce a full path that: +// - total distance == 2*L (add_segments calls calculate_path with L*0.5) +// - peak velocity <= Vm +// - peak acceleration <= Am +// - output jerk <= input Jm +// - final velocity == V0 (returns to initial speed) +// - final acceleration == 0 +// +// add_segments builds: +// Accel half: jerk_block(tj, +Jm, t2) + const(t4, 0) + jerk_block(tj, -Jm, t6) +// Coast: const(t_coast, 0) where t_coast fills remaining distance at Vm +// Decel half: jerk_block(tj, -Jm, t6) + const(t4, 0) + jerk_block(tj, +Jm, t2) +TEST(SCurveCalcPath, constraints) +{ + const float tol = 1.0e-3f; + float Jm_out, tj_out, t2_out, t4_out, t6_out; + + for (const auto &t : path_tests) { + SCurve::calculate_path(t.Sm, t.Jm, t.V0, t.Am, t.Vm, t.L, + Jm_out, tj_out, t2_out, t4_out, t6_out); + + // skip zero-output cases (paths B, C) + if (is_zero(Jm_out) && is_zero(tj_out)) { + continue; + } + + // jerk limit: output Jm must not exceed input Jm + EXPECT_LE(Jm_out, t.Jm + tol) << "Jm exceeded: " << t.name; + + // --- Accel half --- + float peak_A = 0.0f; + SegState s = {0.0f, t.V0, 0.0f}; + + // accel up: jerk_block(tj, +Jm, t2) + s = seg_jerk_block(s, tj_out, Jm_out, t2_out, peak_A); + float peak_V = s.V; + + // coast within accel half: const(t4, 0) + s = seg_const_jerk(s, t4_out, 0.0f); + peak_V = MAX(peak_V, s.V); + + // accel down: jerk_block(tj, -Jm, t6) + s = seg_jerk_block(s, tj_out, -Jm_out, t6_out, peak_A); + + // end of accel half: acceleration should be ~0 + EXPECT_NEAR(s.A, 0.0f, tol) << "accel half final A non-zero: " << t.name; + + const float accel_half_P = s.P; + const float cruise_V = s.V; + + // --- Coast segment (fill remaining distance at cruise velocity) --- + const float L_total = 2.0f * t.L; + const float coast_dist = MAX(0.0f, L_total - 2.0f * accel_half_P); + float t_coast = 0.0f; + if (cruise_V > 0.0f) { + t_coast = coast_dist / cruise_V; + } + s = seg_const_jerk(s, t_coast, 0.0f); + peak_V = MAX(peak_V, s.V); + + // --- Decel half (mirror of accel) --- + // decel down: jerk_block(tj, -Jm, t6) + s = seg_jerk_block(s, tj_out, -Jm_out, t6_out, peak_A); + + // coast within decel half: const(t4, 0) + s = seg_const_jerk(s, t4_out, 0.0f); + + // decel up: jerk_block(tj, +Jm, t2) + s = seg_jerk_block(s, tj_out, Jm_out, t2_out, peak_A); + + // --- Check constraints --- + + // total distance must match 2*L + EXPECT_NEAR(s.P, L_total, tol) << "distance mismatch: " << t.name + << " P=" << s.P << " expected=" << L_total; + + // final velocity must return to V0 + EXPECT_NEAR(s.V, t.V0, tol) << "final velocity mismatch: " << t.name + << " V=" << s.V << " V0=" << t.V0; + + // final acceleration must be zero + EXPECT_NEAR(s.A, 0.0f, tol) << "final accel non-zero: " << t.name; + + // peak velocity must not exceed Vm + EXPECT_LE(peak_V, t.Vm + tol) << "velocity exceeded Vm: " << t.name + << " peak_V=" << peak_V << " Vm=" << t.Vm; + + // peak acceleration must not exceed Am + EXPECT_LE(peak_A, t.Am + tol) << "accel exceeded Am: " << t.name + << " peak_A=" << peak_A << " Am=" << t.Am; + } +} AP_GTEST_MAIN() int hal = 0; //weirdly the build will fail without this diff --git a/libraries/AR_Motors/AP_MotorsUGV.cpp b/libraries/AR_Motors/AP_MotorsUGV.cpp index e6684df81c0a3..ba8a6c79f7935 100644 --- a/libraries/AR_Motors/AP_MotorsUGV.cpp +++ b/libraries/AR_Motors/AP_MotorsUGV.cpp @@ -136,7 +136,7 @@ const AP_Param::GroupInfo AP_MotorsUGV::var_info[] = { // @Range: 0 10 // @Units: s // @User: Advanced - AP_GROUPINFO("BAT_WATT_TC", 16, AP_MotorsUGV, _batt_power_time_constant, 5.0f), + AP_GROUPINFO("BAT_WATT_TC", 16, AP_MotorsUGV, _batt_power_time_constant, 2.0f), #endif AP_GROUPEND @@ -1024,8 +1024,8 @@ float AP_MotorsUGV::get_power_limit_max_throttle(float dt) _throttle_limit += (dt / (dt + _batt_power_time_constant)) * (1.0f - power_ratio); - // throttle limit drops to 5% minimum when over power limit - _throttle_limit = constrain_float(_throttle_limit, _throttle_min, _throttle_max); + // ensure throttle limit is within min and max throttle limits + _throttle_limit = constrain_float(_throttle_limit, _throttle_min * 0.01f, _throttle_max * 0.01f); return _throttle_limit; } diff --git a/libraries/RC_Channel/RC_Channels_VarInfo.h b/libraries/RC_Channel/RC_Channels_VarInfo.h index 14390535bf9bf..2345c820fd258 100644 --- a/libraries/RC_Channel/RC_Channels_VarInfo.h +++ b/libraries/RC_Channel/RC_Channels_VarInfo.h @@ -101,7 +101,7 @@ const AP_Param::GroupInfo RC_Channels::var_info[] = { // @DisplayName: RC protocols enabled // @Description: Bitmask of enabled RC protocols. Allows narrowing the protocol detection to only specific types of RC receivers which can avoid issues with incorrect detection. Set to 1 to enable all protocols. // @User: Advanced - // @Bitmask: 0:All,1:PPM,2:IBUS,3:SBUS,4:SBUS_NI,5:DSM,6:SUMD,7:SRXL,8:SRXL2,9:CRSF,10:ST24,11:FPORT,12:FPORT2,13:FastSBUS,14:DroneCAN,15:Ghost,16:MAVRadio + // @Bitmask: 0:All,1:PPM,2:IBUS,3:SBUS,4:SBUS_NI,5:DSM,6:SUMD,7:SRXL,8:SRXL2,9:CRSF,10:ST24,11:FPORT,12:FPORT2,13:FastSBUS,14:DroneCAN,15:Ghost,16:MAVRadio,18:SITL UDP AP_GROUPINFO("_PROTOCOLS", 34, RC_CHANNELS_SUBCLASS, _protocols, 1), // @Param: _FS_TIMEOUT