thrustlab 0.6.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {thrustlab-0.6.0 → thrustlab-0.7.0}/CHANGELOG.md +86 -1
- {thrustlab-0.6.0 → thrustlab-0.7.0}/PKG-INFO +21 -1
- {thrustlab-0.6.0 → thrustlab-0.7.0}/README.md +20 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/pyproject.toml +7 -0
- thrustlab-0.7.0/tests/estimate/test_equation.py +234 -0
- thrustlab-0.7.0/tests/estimate/test_grid.py +663 -0
- thrustlab-0.7.0/tests/test_resources/__init__.py +0 -0
- thrustlab-0.7.0/tests/test_spec_coverage.py +217 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/__init__.py +74 -6
- thrustlab-0.7.0/thrustlab/_models/compare_entry.py +74 -0
- thrustlab-0.7.0/thrustlab/_models/compare_entry_in.py +89 -0
- thrustlab-0.7.0/thrustlab/_models/compare_lists_body.py +67 -0
- thrustlab-0.7.0/thrustlab/_models/compare_lists_in.py +177 -0
- thrustlab-0.7.0/thrustlab/_models/compare_lists_out.py +108 -0
- thrustlab-0.7.0/thrustlab/_models/compare_lists_resource.py +78 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_create_body.py +40 -8
- thrustlab-0.7.0/thrustlab/_models/dynamic_create_body_propeller_model.py +9 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_patch.py +21 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource.py +2 -2
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in.py +66 -9
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in.py +66 -9
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/entitlements_resource.py +28 -4
- thrustlab-0.7.0/thrustlab/_models/propeller_label.py +167 -0
- thrustlab-0.7.0/thrustlab/_models/propeller_label_family.py +12 -0
- thrustlab-0.7.0/thrustlab/_models/public_catalog_redirect.py +79 -0
- thrustlab-0.7.0/thrustlab/_models/public_component.py +137 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_facets.py +120 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_facets_discrete.py +68 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_facets_ranges.py +60 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_facets_type.py +10 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_list.py +128 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_resource.py +145 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_resource_spec_json.py +50 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_resource_type.py +10 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_spec_json.py +50 -0
- thrustlab-0.7.0/thrustlab/_models/public_component_type.py +10 -0
- thrustlab-0.7.0/thrustlab/_models/public_facet_range.py +97 -0
- thrustlab-0.7.0/thrustlab/_models/public_facet_value.py +70 -0
- thrustlab-0.7.0/thrustlab/_models/public_run_claim.py +93 -0
- thrustlab-0.7.0/thrustlab/_models/public_run_claim_kind.py +9 -0
- thrustlab-0.7.0/thrustlab/_models/public_run_view.py +88 -0
- thrustlab-0.7.0/thrustlab/_models/public_simulate_body.py +467 -0
- thrustlab-0.7.0/thrustlab/_models/public_simulate_body_cooling_source_type_0.py +11 -0
- thrustlab-0.7.0/thrustlab/_models/public_simulate_body_flight_regime.py +11 -0
- thrustlab-0.7.0/thrustlab/_models/public_simulate_body_inflow_mode.py +9 -0
- thrustlab-0.7.0/thrustlab/_models/public_simulate_body_propeller_model.py +9 -0
- thrustlab-0.7.0/thrustlab/_models/public_simulate_response.py +102 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in.py +59 -10
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_resource.py +61 -9
- thrustlab-0.7.0/thrustlab/_models/rotor_group_resource_propeller_label_type_0.py +47 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in.py +59 -10
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body.py +41 -8
- thrustlab-0.7.0/thrustlab/_models/simulation_create_body_propeller_model.py +9 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_patch.py +21 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource.py +11 -2
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_config_in.py +111 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_create_body.py +88 -21
- thrustlab-0.6.0/thrustlab/_models/sweep_create_body_cooling_source.py → thrustlab-0.7.0/thrustlab/_models/sweep_create_body_cooling_source_type_0.py +1 -1
- thrustlab-0.7.0/thrustlab/_models/sweep_create_body_flight_regime.py +11 -0
- thrustlab-0.7.0/thrustlab/_models/sweep_create_body_propeller_model.py +9 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_patch.py +21 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_inputs.py +69 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_resource.py +5 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource.py +11 -2
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in.py +59 -10
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in.py +59 -10
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/user_resource.py +31 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_version.py +1 -1
- thrustlab-0.7.0/thrustlab/estimate/__init__.py +368 -0
- thrustlab-0.7.0/thrustlab/estimate/__main__.py +3 -0
- thrustlab-0.7.0/thrustlab/estimate/_fixture/worked-examples.json +22823 -0
- thrustlab-0.7.0/thrustlab/estimate/cli.py +202 -0
- thrustlab-0.7.0/thrustlab/estimate/fixture.py +437 -0
- thrustlab-0.7.0/thrustlab/estimate/grid.py +1250 -0
- thrustlab-0.6.0/tests/test_spec_coverage.py +0 -117
- thrustlab-0.6.0/thrustlab/_models/list_public_propellers_v1_public_propellers_get_response_list_public_propellers_v1_public_propellers_get.py +0 -47
- {thrustlab-0.6.0 → thrustlab-0.7.0}/.gitignore +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/LICENSE +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/NOTICE +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/components/create_component.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/dynamic/run_and_poll.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/dynamic/watch_and_cancel.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/fly_mission.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/fmu.parm +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/plot_mission.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/quad_x.yaml +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/render_mission_video.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/fly_transition.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/tilttri.parm +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/tilttri.yaml +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/plot_coax_split.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/y6.parm +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/y6.yaml +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/betaflight_config.txt +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/betaflight_quad_x.yaml +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/fly_hover.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/endurance/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/endurance/hover_endurance.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/export_and_download.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/gazebo/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/gazebo/quad_fmu.sdf +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/quad_5inch_x.yaml +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/simulink/.gitignore +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/simulink/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/simulink/fmu_cosim.png +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/fmu/simulink/run_fmu_simulink.m +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/outputs/read_dynamic.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/outputs/read_steady_state.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/projects/create.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/projects/list.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/projects/retrieve.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/quickstart.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/simulations/run_sync.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/simulations/wait.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/sweeps/component_axis_grid.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/sweeps/run_and_poll.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/examples/webhooks/verify_handler.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/__init__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/conftest.py +0 -0
- {thrustlab-0.6.0/tests/test_resources → thrustlab-0.7.0/tests/estimate}/__init__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/__init__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/ardupilot_parser.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/betaflight_fc.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/conftest.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/mock_fmu.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_betaflight_bridge.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_betaflight_protocol.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_kinematics.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_protocol.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_rigidbody.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_state_machine.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_step_path.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_tilt_wing.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/sitl/test_vehicle.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_async_polling.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_client.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_components_create.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_components_find.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_dynamic_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_exceptions.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_http.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_pagination.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_components.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_compute_units.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_fmu.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_projects.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_simulations.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_simulations_cancel_batch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_simulations_run_batch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_starred_components.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_submissions.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_sweeps.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_users.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_resources/test_webhook_endpoints.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/tests/test_webhooks.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/__init__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_async_polling.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_http.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/airfoil_breakpoint.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/airfoil_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/airfoil_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_request.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_request_mode.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_request_target_type_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_response_envelope_limiting_factor_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_response_envelope_status_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_station_row.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/body_import_airfoil_v1_airfoils_import_post.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/calibrate_accepted_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/cancel_batch_result.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/cancel_selected_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/cancel_skipped.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/cancel_skipped_reason.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_brand.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_brands_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_create_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_create_body_spec_json.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_filter_bounds.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_ids_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_ids_response_filters.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_list_response_filters.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_patch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_patch_spec_json_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_resource_spec_json.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_specs_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_specs_response_spec_json.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_sweep_axis_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_sweep_axis_in_axis.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_write_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_write_response_spec_json.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/component_write_warning.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/concurrency_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/create_webhook_endpoint_v1_webhook_endpoints_post_response_create_webhook_endpoint_v1_webhook_endpoints_post.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_balance_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_bucket_breakdown.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_bucket_breakdown_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_event_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_event_resource_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_event_resource_unit_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_related_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_related_resource_object.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_summary_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_summary_resource_window.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/design_request.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/design_request_target_mode.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_estimate_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_estimate_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_battery_topology_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_display_labels_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_error_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_input_snapshot_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_progress_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_result_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_status.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in_esc_timing.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in_esc_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in_motor_cooling_source.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_esc_timing.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_esc_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_motor_cooling_source.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_rotation_sense.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/export_geometry_request.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/export_geometry_request_format.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/export_geometry_request_rotation_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/fire_test_event_v1_webhook_endpoints_public_id_test_post_response_fire_test_event_v1_webhook_endpoints_public_id_test_post.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/fmu_export_accepted_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/fmu_export_job_error.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/fmu_export_status_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/generate_geometry_request.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/geometry_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/geometry_style_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/geometry_styles_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/get_delivery_v1_webhook_endpoints_public_id_deliveries_delivery_public_id_get_response_get_delivery_v1_webhook_endpoints_public_id_deliveries_delivery_public_id_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/get_event_v1_events_event_id_get_response_get_event_v1_events_event_id_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/get_public_result_v1_public_results_slug_get_response_get_public_result_v1_public_results_slug_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/get_shared_result_v1_public_share_share_token_get_response_get_shared_result_v1_public_share_share_token_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/get_webhook_endpoint_v1_webhook_endpoints_public_id_get_response_get_webhook_endpoint_v1_webhook_endpoints_public_id_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/http_validation_error.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/list_deliveries_v1_webhook_endpoints_public_id_deliveries_get_response_list_deliveries_v1_webhook_endpoints_public_id_deliveries_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/list_events_v1_events_get_response_list_events_v1_events_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/list_webhook_endpoints_v1_webhook_endpoints_get_response_list_webhook_endpoints_v1_webhook_endpoints_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/pack_leaf_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/pack_parallel_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/pack_series_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/pack_topology_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/patch_webhook_endpoint_v1_webhook_endpoints_public_id_patch_response_patch_webhook_endpoint_v1_webhook_endpoints_public_id_patch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/project_create_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/project_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/project_patch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/project_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/retry_delivery_v1_webhook_endpoints_public_id_deliveries_delivery_public_id_retry_post_response_retry_delivery_v1_webhook_endpoints_public_id_deliveries_delivery_public_id_retry_post.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotate_webhook_secret_v1_webhook_endpoints_public_id_rotate_secret_post_response_rotate_webhook_secret_v1_webhook_endpoints_public_id_rotate_secret_post.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in_esc_timing.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in_esc_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in_motor_cooling_source.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_esc_timing.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_esc_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_motor_cooling_source.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_rotation_sense.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/run_queued_v1v1_simulations_run_queued_post_response_run_queued_v1v1_simulations_run_queued_post.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/run_selected_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/run_selected_v1v1_simulations_run_selected_post_response_run_selected_v1v1_simulations_run_selected_post.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/schedule_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/schedule_in_interpolation_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/schedule_in_mode.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_group_command_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_group_command_in_throttle_ramp_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_group_command_in_tilt_ramp_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_airspeed_ramp.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_per_group.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_throttle_ramp.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_vertical_speed_ramp.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/share_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_cancel_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_cooling_source_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_flight_regime.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_inflow_mode.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_launch_intent.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_inputs.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_patch_plot_config_json_type_0_item.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_battery_topology_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_display_labels_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_error_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_input_snapshot_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_plot_config_json_type_0_item.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_result_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_result_type_0_additional_property.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_status.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/spline_data.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/starred_component_create_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/starred_component_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/starred_component_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/submission_create_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/submission_create_body_data_json.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/submission_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/submission_patch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/submission_patch_data_json_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/submission_resource.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/submission_resource_data_json.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_cancel_body.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_config_in_esc_timing_values_type_0_item.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_create_body_inflow_mode.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_create_body_launch_intent.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_credits_breakdown.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_inputs.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_param_range_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_param_range_in_mode.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_patch_plot_config_json_type_0_item.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_component_selection.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_list_response.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_list_response_display_labels_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_patch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_resource_rotors_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_resource_rotors_type_0_additional_property.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_error_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_input_snapshot_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_plot_config_json_type_0_item.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_status.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_summary_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_sweep_config_type_0.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in_esc_timing.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in_esc_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in_motor_cooling_source.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_esc_timing.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_esc_type.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_motor_cooling_source.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_rotation_sense.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/termination_in.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/termination_in_mode.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/types.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/user_resource_gate_required_tiers.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/user_resource_unit_system.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/v1_custom_component_override.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/v1_custom_component_override_spec_json.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/v1_health_v1_health_get_response_v1_health_v1_health_get.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/validation_error.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/webhook_endpoint_create.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_models/webhook_endpoint_patch.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/_pagination.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/client.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/exceptions.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/__init__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/_base.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/components.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/compute_units.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/dynamic_simulations.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/fmu.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/projects.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/simulations.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/starred_components.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/submissions.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/sweeps.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/users.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/resources/webhook_endpoints.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/README.md +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/__init__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/__main__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/bridge.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/cli.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/fmu.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/kinematics.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/model.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/protocol.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/rigidbody.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/rpmlog.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/__init__.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/ardupilot.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/base.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/betaflight.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/sitl/vehicle.py +0 -0
- {thrustlab-0.6.0 → thrustlab-0.7.0}/thrustlab/webhooks.py +0 -0
|
@@ -6,7 +6,92 @@ ThrustLab API version (which is permanently `/v1/`).
|
|
|
6
6
|
|
|
7
7
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
8
8
|
|
|
9
|
-
## [
|
|
9
|
+
## [0.7.0] - 2026-10-02
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `thrustlab.estimate`: the ThrustLab propeller equation, offline. Thrust, torque,
|
|
14
|
+
shaft power and the coefficients from a propeller's printed size, blade count,
|
|
15
|
+
rpm and airspeed, with an ISA atmosphere and a zero-thrust airspeed search. No API
|
|
16
|
+
key, no network, no dependencies. `thrustlab-estimate --diameter 10 --pitch 5
|
|
17
|
+
--rpm 8000` on the command line (`--airspeed 0:30:5` for a table, `--json`).
|
|
18
|
+
This is the closed form of the Fast propeller model in the simulator; the
|
|
19
|
+
simulator adds the motor, ESC, battery and thermal coupling.
|
|
20
|
+
- The **Fast propeller model**. `propeller_model="fast"` on a single-point,
|
|
21
|
+
sweep or batch submission runs from a propeller's printed label rather than
|
|
22
|
+
its measured blade geometry: `PropellerLabel` carries `diameter_m`,
|
|
23
|
+
`pitch_m`, `num_blades`, a planform `family` (and `chord_ratio` for
|
|
24
|
+
`custom`) and `camber_pct`. Send it on a rotor whose propeller you typed;
|
|
25
|
+
send `propeller_component_id` alone for a catalog pick and the server derives
|
|
26
|
+
the label from that row. `propeller_model="full"` (the measured blade) is
|
|
27
|
+
still the default, so an existing call is byte-for-byte unchanged.
|
|
28
|
+
- **Anonymous runs.** `POST /v1/public/simulate` needs no credentials at all —
|
|
29
|
+
it answers synchronously on the Fast model with a `run_…` token, a `/s/<token>`
|
|
30
|
+
link and the result — and `POST /v1/runs/{token}/claim` imports one into your
|
|
31
|
+
account's default project. Generated models for both, plus the public read
|
|
32
|
+
`GET /v1/public/runs/{token}`.
|
|
33
|
+
- **The open catalog**, unauthenticated: `GET /v1/public/motors`,
|
|
34
|
+
`/v1/public/batteries` and the per-component `…/{id}` reads. Each list is
|
|
35
|
+
paged with a `starting_after` cursor and states the data licence in a
|
|
36
|
+
`license` field. There is no bulk export.
|
|
37
|
+
- The five public routes now declare real response models, so
|
|
38
|
+
`PublicComponentList`, `PublicComponentResource`, `PublicSimulateResponse`,
|
|
39
|
+
`PublicRunView` and `PublicRunClaim` are generated types rather than untyped
|
|
40
|
+
objects. `PublicRunView` is deliberately open: its body is the same
|
|
41
|
+
projection the share route returns and it grows with the result shape.
|
|
42
|
+
- `default_project_id`, `full_model_daily` and `full_model_used_today` on
|
|
43
|
+
`client.users.me()`.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- **Every datasheet value is now public on every tier.** Motor `n`,
|
|
48
|
+
`iq_nominal`, `R`, `L` and `inertia` and battery `pack_resistance_mOhm` and
|
|
49
|
+
`internal_resistance_mOhm` come back from the component list, the detail read
|
|
50
|
+
and `/specs` alike. `/specs` no longer requires a paid plan, a Turnstile
|
|
51
|
+
challenge or a per-account budget, and filter bounds are arbitrary rather than
|
|
52
|
+
snapped to preset edges. A propeller's station arrays are still never served.
|
|
53
|
+
- **`project_id` is optional** on the single-point, sweep and dynamic create
|
|
54
|
+
bodies. Omit it and the run lands in your account's default project ("My
|
|
55
|
+
simulations"), which is created on first use. `PATCH` accepts `project_id` on
|
|
56
|
+
all three resources, so a run can be moved after the fact.
|
|
57
|
+
- The free tier's limit is no longer a daily simulation cap. Fast-model runs are
|
|
58
|
+
unlimited; `full_model_daily` counts Full-model JOBS per rolling 24 h, one per
|
|
59
|
+
run whether it is a single point or a bounded sweep.
|
|
60
|
+
|
|
61
|
+
### Breaking (import names only)
|
|
62
|
+
|
|
63
|
+
The wire contract is unchanged — every request and response body is the same
|
|
64
|
+
shape 0.6.0 sent and received. What moved is the NAME of some generated model
|
|
65
|
+
classes, because the OpenAPI schemas they are derived from changed. Only code
|
|
66
|
+
that imports these by name from `thrustlab` breaks, and only at import time.
|
|
67
|
+
|
|
68
|
+
- `SweepCreateBodyCoolingSource` → `SweepCreateBodyCoolingSourceType0`.
|
|
69
|
+
`cooling_source` on a sweep is nullable now (null means "resolve from the
|
|
70
|
+
deprecated `flight_regime`", matching the single-point body), and the
|
|
71
|
+
generator names the enum arm of a nullable union `…Type0`. The accepted
|
|
72
|
+
values are identical.
|
|
73
|
+
- `PublicSimulateBodyInputSnapshotType0` is **gone**. `input_snapshot` is a
|
|
74
|
+
first-party field and is no longer published in the contract, so no model is
|
|
75
|
+
generated for it. The endpoint still accepts it.
|
|
76
|
+
- Four inline response models are **gone**, replaced by the named models listed
|
|
77
|
+
under Added above:
|
|
78
|
+
`CreatePublicSimulationV1PublicSimulatePostResponseCreatePublicSimulationV1PublicSimulatePost`
|
|
79
|
+
→ `PublicSimulateResponse`;
|
|
80
|
+
`ReadPublicRunV1PublicRunsTokenGetResponseReadPublicRunV1PublicRunsTokenGet`
|
|
81
|
+
→ `PublicRunView`;
|
|
82
|
+
`ClaimPublicRunV1RunsTokenClaimPostResponseClaimPublicRunV1RunsTokenClaimPost`
|
|
83
|
+
→ `PublicRunClaim`;
|
|
84
|
+
`ListPublicMotorsV1PublicMotorsGetResponseListPublicMotorsV1PublicMotorsGet`
|
|
85
|
+
and its batteries twin → `PublicComponentList`.
|
|
86
|
+
These existed for one unreleased day and named nothing a caller would have
|
|
87
|
+
typed on purpose, but they were importable, so they are listed.
|
|
88
|
+
|
|
89
|
+
### Deprecated
|
|
90
|
+
|
|
91
|
+
- `entitlements.db_access` and `entitlements.component_specs` on
|
|
92
|
+
`client.users.me()` are frozen at `"full"` and `True`, and `daily_cap` at
|
|
93
|
+
`null`. They are kept for one major so a pinned 0.6.x client keeps validating;
|
|
94
|
+
read `full_model_daily` instead of `daily_cap`.
|
|
10
95
|
|
|
11
96
|
## [0.6.0] - 2026-09-09
|
|
12
97
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thrustlab
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Official Python SDK for the ThrustLab API
|
|
5
5
|
Project-URL: Homepage, https://thrustlab.com
|
|
6
6
|
Project-URL: Documentation, https://thrustlab.com/docs
|
|
@@ -120,6 +120,26 @@ See [`examples/fmu/`](./examples/fmu/) for bundled ready-to-fly FMUs with
|
|
|
120
120
|
quadcopter, Y6 coax, and tilt-tricopter missions, an endurance study, and
|
|
121
121
|
replay rendering.
|
|
122
122
|
|
|
123
|
+
## Offline propeller estimate
|
|
124
|
+
|
|
125
|
+
`thrustlab.estimate` is the ThrustLab propeller equation: thrust, torque and
|
|
126
|
+
power from the printed size, with no account and no network.
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from thrustlab.estimate import from_label
|
|
130
|
+
|
|
131
|
+
point = from_label(diameter_in=10, pitch_in=5, rpm=8000, airspeed_mps=12.0)
|
|
132
|
+
print(point.T, point.Q, point.P_shaft) # N, N m, W
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
```shell
|
|
136
|
+
thrustlab-estimate --diameter 10 --pitch 5 --rpm 8000 --airspeed 0:30:5
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
It is the closed form of the simulator's Fast propeller model. The simulator adds
|
|
140
|
+
the motor, ESC, battery and thermal coupling; the Full model adds the measured
|
|
141
|
+
blade geometry.
|
|
142
|
+
|
|
123
143
|
## Why the SDK (and not `urllib` / `wget`)?
|
|
124
144
|
|
|
125
145
|
The SDK gives you automatic retries with backoff, idempotency keys, cursor
|
|
@@ -84,6 +84,26 @@ See [`examples/fmu/`](./examples/fmu/) for bundled ready-to-fly FMUs with
|
|
|
84
84
|
quadcopter, Y6 coax, and tilt-tricopter missions, an endurance study, and
|
|
85
85
|
replay rendering.
|
|
86
86
|
|
|
87
|
+
## Offline propeller estimate
|
|
88
|
+
|
|
89
|
+
`thrustlab.estimate` is the ThrustLab propeller equation: thrust, torque and
|
|
90
|
+
power from the printed size, with no account and no network.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from thrustlab.estimate import from_label
|
|
94
|
+
|
|
95
|
+
point = from_label(diameter_in=10, pitch_in=5, rpm=8000, airspeed_mps=12.0)
|
|
96
|
+
print(point.T, point.Q, point.P_shaft) # N, N m, W
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```shell
|
|
100
|
+
thrustlab-estimate --diameter 10 --pitch 5 --rpm 8000 --airspeed 0:30:5
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
It is the closed form of the simulator's Fast propeller model. The simulator adds
|
|
104
|
+
the motor, ESC, battery and thermal coupling; the Full model adds the measured
|
|
105
|
+
blade geometry.
|
|
106
|
+
|
|
87
107
|
## Why the SDK (and not `urllib` / `wget`)?
|
|
88
108
|
|
|
89
109
|
The SDK gives you automatic retries with backoff, idempotency keys, cursor
|
|
@@ -49,6 +49,7 @@ sitl = []
|
|
|
49
49
|
|
|
50
50
|
[project.scripts]
|
|
51
51
|
thrustlab-sitl = "thrustlab.sitl.cli:main"
|
|
52
|
+
thrustlab-estimate = "thrustlab.estimate.cli:main"
|
|
52
53
|
|
|
53
54
|
[project.urls]
|
|
54
55
|
Homepage = "https://thrustlab.com"
|
|
@@ -61,11 +62,17 @@ path = "thrustlab/_version.py"
|
|
|
61
62
|
|
|
62
63
|
[tool.hatch.build.targets.wheel]
|
|
63
64
|
packages = ["thrustlab"]
|
|
65
|
+
# The committed worked-example fixture is data, not code. `artifacts` names it
|
|
66
|
+
# explicitly so neither a VCS-ignore rule nor a future `exclude` can drop it from the
|
|
67
|
+
# wheel: `thrustlab.estimate` reads it at runtime and the Rust Fast-model port is gated
|
|
68
|
+
# against it.
|
|
69
|
+
artifacts = ["thrustlab/estimate/_fixture/*.json"]
|
|
64
70
|
|
|
65
71
|
[tool.hatch.build.targets.sdist]
|
|
66
72
|
# The bundled example FMUs live in the repo for out-of-the-box examples; the
|
|
67
73
|
# sdist stays source-only (each is 4-10 MB of binary).
|
|
68
74
|
exclude = ["*.fmu"]
|
|
75
|
+
artifacts = ["thrustlab/estimate/_fixture/*.json"]
|
|
69
76
|
include = [
|
|
70
77
|
"/thrustlab",
|
|
71
78
|
"/tests",
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""Regression and invariant tests for ``thrustlab.estimate`` (the label-only propeller
|
|
2
|
+
thrust and torque equation). Pure Python plus numpy for the quadrature oracle."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import math
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from thrustlab import estimate as te
|
|
12
|
+
from thrustlab.estimate import cli
|
|
13
|
+
|
|
14
|
+
IN = 0.0254
|
|
15
|
+
PI = math.pi
|
|
16
|
+
APC_10x5 = dict(D=10 * IN, P=5 * IN, B=2, c=0.064 * 10 * IN, n=8000 / 60)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ----------------------------------------------------------------------------- pinned values
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_worked_examples_pinned():
|
|
23
|
+
"""The four worked examples in the design spec, thrust in N and shaft power in W."""
|
|
24
|
+
cases = [
|
|
25
|
+
(dict(diameter_in=10, pitch_in=5, rpm=8000, chord_ratio=0.064), 8.10, 95.5),
|
|
26
|
+
(dict(diameter_in=10, pitch_in=5, rpm=8000, chord_ratio=0.064, airspeed_mps=15.0), 2.69, 59.4),
|
|
27
|
+
(dict(diameter_in=5, pitch_in=4.5, rpm=20000, blades=3, chord_ratio=0.11), 8.92, 245.4),
|
|
28
|
+
(dict(diameter_in=20, pitch_in=10, rpm=4000, chord_ratio=0.064), 32.87, 373.4),
|
|
29
|
+
]
|
|
30
|
+
for kw, T, P in cases:
|
|
31
|
+
r = te.from_label(**kw, camber_pct=3.5 / 1.1)
|
|
32
|
+
assert r.converged
|
|
33
|
+
assert r.T == pytest.approx(T, rel=2e-3)
|
|
34
|
+
assert r.P_shaft == pytest.approx(P, rel=2e-3)
|
|
35
|
+
labels = [label for label, _, _ in te.worked_examples()]
|
|
36
|
+
assert labels[0].startswith("APC 10x5E static")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ----------------------------------------------------------------------------- the equation itself
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _oracle(r, D, P, B, c, kw):
|
|
43
|
+
"""Integrate the section law numerically at the returned state; return (ct_r, profile cq_r)."""
|
|
44
|
+
sec = kw.get("section", te.DEFAULT_SECTION)
|
|
45
|
+
xh = min(max(kw.get("x_hub", 0.15), 0.0), 0.5)
|
|
46
|
+
sigma, theta = B * c / (PI * D / 2), P / (PI * D)
|
|
47
|
+
a_eff = sec.a / math.sqrt(1 - min(r.mach, te.MACH_CORR_CAP) ** 2)
|
|
48
|
+
g = theta - r.lam
|
|
49
|
+
clmax, cd0 = r.CLmax, sec.cd0(r.Re)
|
|
50
|
+
alpha_stall = sec.alpha0 + clmax / a_eff
|
|
51
|
+
x = np.linspace(max(xh, 1e-6), 1.0, 400_001)
|
|
52
|
+
cl = np.minimum(a_eff * (g / x - sec.alpha0), clmax)
|
|
53
|
+
cd = cd0 + sec.k * (cl - sec.cl_d) ** 2 + sec.cd_stall * np.maximum(g / x - alpha_stall, 0.0)
|
|
54
|
+
lift = np.where(x <= r.Bt, cl * x ** 2, 0.0)
|
|
55
|
+
ct_r = 0.5 * sigma * np.trapezoid(lift, x)
|
|
56
|
+
prof = 0.5 * sigma * np.trapezoid(cd * x ** 3, x)
|
|
57
|
+
return ct_r, prof
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@pytest.mark.parametrize("case", [
|
|
61
|
+
dict(APC_10x5), # ordinary static, partial stall
|
|
62
|
+
dict(APC_10x5, V=15.0), # cruise, nearly attached
|
|
63
|
+
dict(APC_10x5, V=19.0), # close to zero thrust
|
|
64
|
+
dict(D=10 * IN, P=10 * IN, B=1, c=0.064 * 10 * IN, n=8000 / 60), # single blade, fully stalled past B_t
|
|
65
|
+
dict(D=5 * IN, P=4.5 * IN, B=4, c=0.11 * 5 * IN, n=20000 / 60), # high solidity
|
|
66
|
+
dict(APC_10x5, x_hub=0.0), # no hub cut-out
|
|
67
|
+
dict(APC_10x5, section=te.Section.from_camber(5.0)), # more camber
|
|
68
|
+
])
|
|
69
|
+
def test_closed_form_matches_quadrature_and_momentum(case):
|
|
70
|
+
r = te.propeller_performance(**case)
|
|
71
|
+
assert r.converged and abs(r.residual) < 1e-9
|
|
72
|
+
f = (1 - r.a_prime) ** 2
|
|
73
|
+
ct_r = r.CT / f / (PI ** 3 / 4)
|
|
74
|
+
cq_r = r.CP / f / (PI ** 4 / 4)
|
|
75
|
+
lam_c = r.lam - r.lam_i
|
|
76
|
+
assert 2 * r.lam_i * (lam_c + r.lam_i) == pytest.approx(ct_r, rel=1e-7)
|
|
77
|
+
ct_oracle, prof_oracle = _oracle(r, case["D"], case["P"], case["B"], case["c"], case)
|
|
78
|
+
assert ct_r == pytest.approx(ct_oracle, rel=1e-5)
|
|
79
|
+
prof_code = cq_r - lam_c * ct_r - 1.10 * r.lam_i * ct_r
|
|
80
|
+
assert prof_code == pytest.approx(prof_oracle, rel=1e-5)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_thrust_falls_with_airspeed_and_crosses_zero_above_pitch_speed():
|
|
84
|
+
pts = te.airspeed_sweep(**APC_10x5, speeds=[0, 5, 10, 15, 20])
|
|
85
|
+
thrusts = [p.T for p in pts]
|
|
86
|
+
assert thrusts == sorted(thrusts, reverse=True)
|
|
87
|
+
V0 = te.zero_thrust_speed(**APC_10x5)
|
|
88
|
+
pitch_speed = APC_10x5["n"] * APC_10x5["P"]
|
|
89
|
+
assert 1.05 * pitch_speed < V0 < 1.35 * pitch_speed
|
|
90
|
+
assert abs(te.propeller_performance(**APC_10x5, V=V0).T) < 1e-3
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_zero_thrust_speed_low_pitch_is_bracketed():
|
|
94
|
+
"""Camber adds an aerodynamic pitch offset, so a near-zero label pitch still has a
|
|
95
|
+
zero-thrust speed well above 2 n P; the search must expand until it brackets it."""
|
|
96
|
+
kw = dict(D=10 * IN, P=0.01, B=2, c=0.064 * 10 * IN, n=8000 / 60)
|
|
97
|
+
V0 = te.zero_thrust_speed(**kw)
|
|
98
|
+
assert V0 > 2 * kw["n"] * kw["P"] + 1
|
|
99
|
+
assert abs(te.propeller_performance(**kw, V=V0).T) < 1e-3
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_brake_regime_is_flagged_not_faked():
|
|
103
|
+
r = te.propeller_performance(**APC_10x5, V=30.0)
|
|
104
|
+
assert r.T < 0 and r.regime == "brake"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_more_blades_more_thrust_sublinear():
|
|
108
|
+
t2 = te.propeller_performance(**APC_10x5).T
|
|
109
|
+
t3 = te.propeller_performance(**{**APC_10x5, "B": 3}).T
|
|
110
|
+
t4 = te.propeller_performance(**{**APC_10x5, "B": 4}).T
|
|
111
|
+
assert 1.2 < t3 / t2 < 1.6
|
|
112
|
+
assert 1.4 < t4 / t2 < 2.0
|
|
113
|
+
assert t4 / t3 < t3 / t2
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_density_scaling_exact_and_torque_identities():
|
|
117
|
+
r1 = te.propeller_performance(**APC_10x5)
|
|
118
|
+
r2 = te.propeller_performance(**APC_10x5, rho=0.9 * 1.225)
|
|
119
|
+
assert r2.T == pytest.approx(0.9 * r1.T, rel=1e-9)
|
|
120
|
+
assert r2.CT == pytest.approx(r1.CT, rel=1e-9)
|
|
121
|
+
assert r1.Q == pytest.approx(r1.P_shaft / (2 * PI * APC_10x5["n"]), rel=1e-12)
|
|
122
|
+
assert r1.CQ == pytest.approx(r1.CP / (2 * PI), rel=1e-12)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_similarity_scaling_with_matched_reynolds_and_mach():
|
|
126
|
+
"""Double D, P, c, halve n, double nu: same Re and Mach, so CT and CP are unchanged,
|
|
127
|
+
thrust scales by 4 and torque by 8."""
|
|
128
|
+
r1 = te.propeller_performance(**APC_10x5)
|
|
129
|
+
r2 = te.propeller_performance(D=2 * APC_10x5["D"], P=2 * APC_10x5["P"], B=2, c=2 * APC_10x5["c"],
|
|
130
|
+
n=APC_10x5["n"] / 2, nu=2 * 1.46e-5)
|
|
131
|
+
assert r2.Re == pytest.approx(r1.Re, rel=1e-9) and r2.mach == pytest.approx(r1.mach, rel=1e-9)
|
|
132
|
+
assert r2.CT == pytest.approx(r1.CT, rel=1e-8) and r2.CP == pytest.approx(r1.CP, rel=1e-8)
|
|
133
|
+
assert r2.T == pytest.approx(4 * r1.T, rel=1e-8) and r2.Q == pytest.approx(8 * r1.Q, rel=1e-8)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_swirl_converges_and_state_is_consistent_at_high_solidity():
|
|
137
|
+
"""Six wide blades (solidity 0.5) at high pitch and airspeed: the swirl fixed point
|
|
138
|
+
must converge and the returned inflow must be consistent with the returned swirl."""
|
|
139
|
+
r = te.propeller_performance(D=10 * IN, P=20 * IN, B=6, c=1.3 * IN, n=8000 / 60, V=60.0)
|
|
140
|
+
assert r.converged and r.swirl_passes < 30
|
|
141
|
+
lam_c_from_swirl = 60.0 / (2 * PI * (8000 / 60) * (1 - r.a_prime) * 5 * IN)
|
|
142
|
+
assert r.lam - r.lam_i == pytest.approx(lam_c_from_swirl, rel=1e-5)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def test_absurd_solidity_is_rejected_not_solved():
|
|
146
|
+
with pytest.raises(ValueError):
|
|
147
|
+
te.propeller_performance(D=0.254, P=2.0, B=100, c=1.0, n=8000 / 60)
|
|
148
|
+
with pytest.raises(ValueError):
|
|
149
|
+
te.propeller_performance(D=0.254, P=0.508, B=8, c=0.127, n=8000 / 60, V=67.7)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_camber_raises_thrust_and_moves_zero_thrust_speed():
|
|
153
|
+
lo = te.propeller_performance(**APC_10x5, section=te.Section.from_camber(2.0))
|
|
154
|
+
hi = te.propeller_performance(**APC_10x5, section=te.Section.from_camber(5.0))
|
|
155
|
+
assert hi.T > lo.T
|
|
156
|
+
assert te.zero_thrust_speed(**APC_10x5, section=te.Section.from_camber(5.0)) > te.zero_thrust_speed(
|
|
157
|
+
**APC_10x5, section=te.Section.from_camber(2.0))
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_section_law_and_guards():
|
|
161
|
+
s = te.Section()
|
|
162
|
+
assert s.clmax(1e5) == pytest.approx(1.30)
|
|
163
|
+
assert s.clmax(5e4) == pytest.approx(1.30 * 0.5 ** 0.15)
|
|
164
|
+
assert s.clmax(1e7) == 1.45 and s.clmax(100) == 0.6
|
|
165
|
+
assert s.cd0(1e5) == pytest.approx(0.019)
|
|
166
|
+
with pytest.raises(ValueError): # CL_max below the zero-angle lift is not a section
|
|
167
|
+
te.propeller_performance(**APC_10x5, section=te.Section(clmax_ref=0.3, clmax_cap=0.3, clmax_re_exp=0.0))
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_mach_is_reported_unclipped():
|
|
171
|
+
r = te.from_label(10, 5, 40000)
|
|
172
|
+
assert r.mach > 1.0
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ----------------------------------------------------------------------------- helpers and API
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def test_air_density_isa_layers():
|
|
179
|
+
rho0, nu0 = te.air_density(0.0)
|
|
180
|
+
rho3, nu3 = te.air_density(3000.0)
|
|
181
|
+
assert rho0 == pytest.approx(1.225, rel=2e-3)
|
|
182
|
+
assert nu0 == pytest.approx(1.46e-5, rel=3e-2)
|
|
183
|
+
assert rho3 / rho0 == pytest.approx(0.742, rel=5e-3) and nu3 > nu0
|
|
184
|
+
lo, hi = te.air_density(10999.0)[0], te.air_density(11001.0)[0]
|
|
185
|
+
assert lo == pytest.approx(hi, rel=2e-3)
|
|
186
|
+
assert te.air_density(15000.0)[0] == pytest.approx(0.1937, rel=2e-3)
|
|
187
|
+
assert te.air_density(0.0, temperature_c=35.0)[0] < rho0
|
|
188
|
+
for bad in ((25000.0, None), (0.0, -300.0)):
|
|
189
|
+
with pytest.raises(ValueError):
|
|
190
|
+
te.air_density(*bad)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def test_from_label_matches_si_api_and_forwards_section_and_atmosphere():
|
|
194
|
+
sec = te.Section.from_camber(4.0)
|
|
195
|
+
a = te.from_label(10, 5, 8000, chord_in=0.64, section=sec, rho=1.1, nu=1.5e-5, airspeed_mps=3.0)
|
|
196
|
+
b = te.propeller_performance(10 * IN, 5 * IN, 2, 0.64 * IN, 8000 / 60, 3.0, rho=1.1, nu=1.5e-5, section=sec)
|
|
197
|
+
assert a == b
|
|
198
|
+
with pytest.raises(ValueError):
|
|
199
|
+
te.from_label(10, 5, 8000, chord_in=0.0)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def test_bad_inputs_raise():
|
|
203
|
+
bad = [
|
|
204
|
+
dict(D=0.0), dict(P=-1.0), dict(c=float("nan")), dict(n=float("inf")), dict(B=0), dict(B=2.5),
|
|
205
|
+
dict(V=-1.0), dict(V=float("nan")), dict(rho=0.0), dict(rho=-1.0), dict(nu=0.0), dict(nu=-1e-5),
|
|
206
|
+
]
|
|
207
|
+
for kw in bad:
|
|
208
|
+
with pytest.raises(ValueError):
|
|
209
|
+
te.propeller_performance(**{**APC_10x5, **kw})
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# ----------------------------------------------------------------------------- command line
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_cli_table_and_json(capsys):
|
|
216
|
+
assert cli.main(["--diameter", "10", "--pitch", "5", "--rpm", "8000", "--chord-ratio", "0.064",
|
|
217
|
+
"--camber", str(3.5 / 1.1)]) == 0
|
|
218
|
+
out = capsys.readouterr().out
|
|
219
|
+
assert "8.10" in out and "zero thrust at" in out
|
|
220
|
+
|
|
221
|
+
assert cli.main(["--diameter", "10", "--pitch", "5", "--rpm", "8000", "--airspeed", "0:10:5", "--json"]) == 0
|
|
222
|
+
payload = json.loads(capsys.readouterr().out)
|
|
223
|
+
assert [p["airspeed_mps"] for p in payload["points"]] == [0.0, 5.0, 10.0]
|
|
224
|
+
assert payload["points"][0]["T"] > payload["points"][2]["T"]
|
|
225
|
+
assert payload["zero_thrust_airspeed_mps"] > 10.0
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def test_cli_examples_and_errors(capsys):
|
|
229
|
+
assert cli.main(["--examples", "--json"]) == 0
|
|
230
|
+
rows = json.loads(capsys.readouterr().out)
|
|
231
|
+
assert len(rows) == 4 and rows[0]["T"] == pytest.approx(8.10, rel=2e-3)
|
|
232
|
+
assert cli.main(["--diameter", "10", "--pitch", "5", "--rpm", "8000", "--chord-in", "0"]) == 2
|
|
233
|
+
with pytest.raises(SystemExit):
|
|
234
|
+
cli.main(["--diameter", "10"])
|