thrustlab 0.5.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.
Files changed (384) hide show
  1. {thrustlab-0.5.0 → thrustlab-0.7.0}/CHANGELOG.md +122 -1
  2. {thrustlab-0.5.0 → thrustlab-0.7.0}/PKG-INFO +49 -1
  3. {thrustlab-0.5.0 → thrustlab-0.7.0}/README.md +48 -0
  4. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/components/create_component.py +2 -2
  5. thrustlab-0.7.0/examples/dynamic/watch_and_cancel.py +132 -0
  6. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/README.md +10 -1
  7. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/README.md +10 -1
  8. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/README.md +21 -8
  9. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/README.md +10 -1
  10. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/endurance/README.md +10 -1
  11. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/gazebo/README.md +10 -1
  12. thrustlab-0.7.0/examples/fmu/simulink/.gitignore +2 -0
  13. thrustlab-0.7.0/examples/fmu/simulink/README.md +53 -0
  14. thrustlab-0.7.0/examples/fmu/simulink/fmu_cosim.png +0 -0
  15. thrustlab-0.7.0/examples/fmu/simulink/run_fmu_simulink.m +93 -0
  16. thrustlab-0.7.0/examples/sweeps/component_axis_grid.py +85 -0
  17. {thrustlab-0.5.0 → thrustlab-0.7.0}/pyproject.toml +10 -0
  18. thrustlab-0.7.0/tests/estimate/test_equation.py +234 -0
  19. thrustlab-0.7.0/tests/estimate/test_grid.py +663 -0
  20. thrustlab-0.7.0/tests/test_resources/__init__.py +0 -0
  21. thrustlab-0.7.0/tests/test_resources/test_simulations_cancel_batch.py +62 -0
  22. thrustlab-0.7.0/tests/test_resources/test_simulations_run_batch.py +80 -0
  23. thrustlab-0.7.0/tests/test_spec_coverage.py +217 -0
  24. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/__init__.py +94 -6
  25. thrustlab-0.7.0/thrustlab/_models/cancel_batch_result.py +97 -0
  26. thrustlab-0.7.0/thrustlab/_models/cancel_selected_body.py +42 -0
  27. thrustlab-0.7.0/thrustlab/_models/cancel_skipped.py +71 -0
  28. thrustlab-0.7.0/thrustlab/_models/cancel_skipped_reason.py +10 -0
  29. thrustlab-0.7.0/thrustlab/_models/compare_entry.py +74 -0
  30. thrustlab-0.7.0/thrustlab/_models/compare_entry_in.py +89 -0
  31. thrustlab-0.7.0/thrustlab/_models/compare_lists_body.py +67 -0
  32. thrustlab-0.7.0/thrustlab/_models/compare_lists_in.py +177 -0
  33. thrustlab-0.7.0/thrustlab/_models/compare_lists_out.py +108 -0
  34. thrustlab-0.7.0/thrustlab/_models/compare_lists_resource.py +78 -0
  35. thrustlab-0.7.0/thrustlab/_models/component_filter_bounds.py +97 -0
  36. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_ids_response.py +27 -3
  37. thrustlab-0.7.0/thrustlab/_models/component_ids_response_filters.py +63 -0
  38. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_list_response.py +19 -0
  39. thrustlab-0.7.0/thrustlab/_models/component_list_response_filters.py +63 -0
  40. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_sweep_axis_in.py +1 -1
  41. thrustlab-0.7.0/thrustlab/_models/concurrency_resource.py +108 -0
  42. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_balance_resource.py +1 -1
  43. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_event_resource.py +1 -1
  44. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_summary_resource.py +1 -1
  45. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_create_body.py +40 -8
  46. thrustlab-0.7.0/thrustlab/_models/dynamic_create_body_propeller_model.py +9 -0
  47. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_patch.py +21 -0
  48. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource.py +87 -4
  49. thrustlab-0.7.0/thrustlab/_models/dynamic_resource_progress_type_0.py +47 -0
  50. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in.py +66 -9
  51. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in.py +66 -9
  52. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/entitlements_resource.py +28 -4
  53. thrustlab-0.7.0/thrustlab/_models/propeller_label.py +167 -0
  54. thrustlab-0.7.0/thrustlab/_models/propeller_label_family.py +12 -0
  55. thrustlab-0.7.0/thrustlab/_models/public_catalog_redirect.py +79 -0
  56. thrustlab-0.7.0/thrustlab/_models/public_component.py +137 -0
  57. thrustlab-0.7.0/thrustlab/_models/public_component_facets.py +120 -0
  58. thrustlab-0.7.0/thrustlab/_models/public_component_facets_discrete.py +68 -0
  59. thrustlab-0.7.0/thrustlab/_models/public_component_facets_ranges.py +60 -0
  60. thrustlab-0.7.0/thrustlab/_models/public_component_facets_type.py +10 -0
  61. thrustlab-0.7.0/thrustlab/_models/public_component_list.py +128 -0
  62. thrustlab-0.7.0/thrustlab/_models/public_component_resource.py +145 -0
  63. thrustlab-0.7.0/thrustlab/_models/public_component_resource_spec_json.py +50 -0
  64. thrustlab-0.7.0/thrustlab/_models/public_component_resource_type.py +10 -0
  65. thrustlab-0.7.0/thrustlab/_models/public_component_spec_json.py +50 -0
  66. thrustlab-0.7.0/thrustlab/_models/public_component_type.py +10 -0
  67. thrustlab-0.7.0/thrustlab/_models/public_facet_range.py +97 -0
  68. thrustlab-0.7.0/thrustlab/_models/public_facet_value.py +70 -0
  69. thrustlab-0.7.0/thrustlab/_models/public_run_claim.py +93 -0
  70. thrustlab-0.7.0/thrustlab/_models/public_run_claim_kind.py +9 -0
  71. thrustlab-0.7.0/thrustlab/_models/public_run_view.py +88 -0
  72. thrustlab-0.7.0/thrustlab/_models/public_simulate_body.py +467 -0
  73. thrustlab-0.7.0/thrustlab/_models/public_simulate_body_cooling_source_type_0.py +11 -0
  74. thrustlab-0.7.0/thrustlab/_models/public_simulate_body_flight_regime.py +11 -0
  75. thrustlab-0.7.0/thrustlab/_models/public_simulate_body_inflow_mode.py +9 -0
  76. thrustlab-0.7.0/thrustlab/_models/public_simulate_body_propeller_model.py +9 -0
  77. thrustlab-0.7.0/thrustlab/_models/public_simulate_response.py +102 -0
  78. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in.py +59 -10
  79. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_resource.py +61 -9
  80. thrustlab-0.7.0/thrustlab/_models/rotor_group_resource_propeller_label_type_0.py +47 -0
  81. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in.py +59 -10
  82. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body.py +41 -8
  83. thrustlab-0.7.0/thrustlab/_models/simulation_create_body_propeller_model.py +9 -0
  84. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_patch.py +21 -0
  85. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource.py +76 -31
  86. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_config_in.py +111 -0
  87. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_create_body.py +94 -24
  88. thrustlab-0.5.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
  89. thrustlab-0.7.0/thrustlab/_models/sweep_create_body_flight_regime.py +11 -0
  90. thrustlab-0.7.0/thrustlab/_models/sweep_create_body_propeller_model.py +9 -0
  91. thrustlab-0.7.0/thrustlab/_models/sweep_credits_breakdown.py +73 -0
  92. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_param_range_in.py +12 -6
  93. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_patch.py +21 -0
  94. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_inputs.py +69 -0
  95. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_resource.py +5 -0
  96. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource.py +131 -31
  97. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in.py +59 -10
  98. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in.py +59 -10
  99. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/user_resource.py +60 -0
  100. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_version.py +1 -1
  101. thrustlab-0.7.0/thrustlab/estimate/__init__.py +368 -0
  102. thrustlab-0.7.0/thrustlab/estimate/__main__.py +3 -0
  103. thrustlab-0.7.0/thrustlab/estimate/_fixture/worked-examples.json +22823 -0
  104. thrustlab-0.7.0/thrustlab/estimate/cli.py +202 -0
  105. thrustlab-0.7.0/thrustlab/estimate/fixture.py +437 -0
  106. thrustlab-0.7.0/thrustlab/estimate/grid.py +1250 -0
  107. thrustlab-0.7.0/thrustlab/resources/simulations.py +186 -0
  108. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/sweeps.py +1 -1
  109. thrustlab-0.5.0/tests/test_spec_coverage.py +0 -117
  110. thrustlab-0.5.0/thrustlab/_models/list_public_propellers_v1_public_propellers_get_response_list_public_propellers_v1_public_propellers_get.py +0 -47
  111. thrustlab-0.5.0/thrustlab/resources/simulations.py +0 -87
  112. {thrustlab-0.5.0 → thrustlab-0.7.0}/.gitignore +0 -0
  113. {thrustlab-0.5.0 → thrustlab-0.7.0}/LICENSE +0 -0
  114. {thrustlab-0.5.0 → thrustlab-0.7.0}/NOTICE +0 -0
  115. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/dynamic/run_and_poll.py +0 -0
  116. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/fly_mission.py +0 -0
  117. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/fmu.parm +0 -0
  118. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/plot_mission.py +0 -0
  119. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/quad_x.yaml +0 -0
  120. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl/render_mission_video.py +0 -0
  121. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/fly_transition.py +0 -0
  122. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/tilttri.parm +0 -0
  123. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_tilttri/tilttri.yaml +0 -0
  124. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/plot_coax_split.py +0 -0
  125. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/y6.parm +0 -0
  126. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/ardupilot_sitl_y6/y6.yaml +0 -0
  127. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/betaflight_config.txt +0 -0
  128. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/betaflight_quad_x.yaml +0 -0
  129. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/betaflight_sitl/fly_hover.py +0 -0
  130. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/endurance/hover_endurance.py +0 -0
  131. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/export_and_download.py +0 -0
  132. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/gazebo/quad_fmu.sdf +0 -0
  133. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/fmu/quad_5inch_x.yaml +0 -0
  134. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/outputs/read_dynamic.py +0 -0
  135. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/outputs/read_steady_state.py +0 -0
  136. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/projects/create.py +0 -0
  137. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/projects/list.py +0 -0
  138. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/projects/retrieve.py +0 -0
  139. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/quickstart.py +0 -0
  140. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/simulations/run_sync.py +0 -0
  141. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/simulations/wait.py +0 -0
  142. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/sweeps/run_and_poll.py +0 -0
  143. {thrustlab-0.5.0 → thrustlab-0.7.0}/examples/webhooks/verify_handler.py +0 -0
  144. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/__init__.py +0 -0
  145. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/conftest.py +0 -0
  146. {thrustlab-0.5.0/tests/test_resources → thrustlab-0.7.0/tests/estimate}/__init__.py +0 -0
  147. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/__init__.py +0 -0
  148. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/ardupilot_parser.py +0 -0
  149. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/betaflight_fc.py +0 -0
  150. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/conftest.py +0 -0
  151. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/mock_fmu.py +0 -0
  152. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_betaflight_bridge.py +0 -0
  153. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_betaflight_protocol.py +0 -0
  154. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_kinematics.py +0 -0
  155. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_protocol.py +0 -0
  156. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_rigidbody.py +0 -0
  157. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_state_machine.py +0 -0
  158. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_step_path.py +0 -0
  159. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_tilt_wing.py +0 -0
  160. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/sitl/test_vehicle.py +0 -0
  161. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_async_polling.py +0 -0
  162. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_client.py +0 -0
  163. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_components_create.py +0 -0
  164. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_components_find.py +0 -0
  165. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_dynamic_resource.py +0 -0
  166. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_exceptions.py +0 -0
  167. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_http.py +0 -0
  168. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_pagination.py +0 -0
  169. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_components.py +0 -0
  170. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_compute_units.py +0 -0
  171. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_fmu.py +0 -0
  172. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_projects.py +0 -0
  173. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_simulations.py +0 -0
  174. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_starred_components.py +0 -0
  175. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_submissions.py +0 -0
  176. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_sweeps.py +0 -0
  177. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_users.py +0 -0
  178. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_resources/test_webhook_endpoints.py +0 -0
  179. {thrustlab-0.5.0 → thrustlab-0.7.0}/tests/test_webhooks.py +0 -0
  180. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/__init__.py +0 -0
  181. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_async_polling.py +0 -0
  182. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_http.py +0 -0
  183. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/airfoil_breakpoint.py +0 -0
  184. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/airfoil_list_response.py +0 -0
  185. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/airfoil_resource.py +0 -0
  186. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_request.py +0 -0
  187. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_request_mode.py +0 -0
  188. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_request_target_type_type_0.py +0 -0
  189. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_response.py +0 -0
  190. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_response_envelope_limiting_factor_type_0.py +0 -0
  191. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_geometry_response_envelope_status_type_0.py +0 -0
  192. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/analyze_station_row.py +0 -0
  193. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/body_import_airfoil_v1_airfoils_import_post.py +0 -0
  194. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/calibrate_accepted_response.py +0 -0
  195. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_brand.py +0 -0
  196. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_brands_response.py +0 -0
  197. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_create_body.py +0 -0
  198. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_create_body_spec_json.py +0 -0
  199. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_patch.py +0 -0
  200. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_patch_spec_json_type_0.py +0 -0
  201. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_resource.py +0 -0
  202. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_resource_spec_json.py +0 -0
  203. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_specs_response.py +0 -0
  204. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_specs_response_spec_json.py +0 -0
  205. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_sweep_axis_in_axis.py +0 -0
  206. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_write_response.py +0 -0
  207. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_write_response_spec_json.py +0 -0
  208. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/component_write_warning.py +0 -0
  209. {thrustlab-0.5.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
  210. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_bucket_breakdown.py +0 -0
  211. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_bucket_breakdown_type.py +0 -0
  212. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_event_resource_type.py +0 -0
  213. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_event_resource_unit_type.py +0 -0
  214. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_list_response.py +0 -0
  215. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_related_resource.py +0 -0
  216. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_related_resource_object.py +0 -0
  217. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/credit_usage_summary_resource_window.py +0 -0
  218. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/design_request.py +0 -0
  219. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/design_request_target_mode.py +0 -0
  220. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_estimate_body.py +0 -0
  221. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_estimate_resource.py +0 -0
  222. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_list_response.py +0 -0
  223. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_battery_topology_type_0.py +0 -0
  224. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_display_labels_type_0.py +0 -0
  225. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_error_type_0.py +0 -0
  226. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_input_snapshot_type_0.py +0 -0
  227. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_result_type_0.py +0 -0
  228. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_resource_status.py +0 -0
  229. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in_esc_timing.py +0 -0
  230. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in_esc_type.py +0 -0
  231. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_group_in_motor_cooling_source.py +0 -0
  232. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_esc_timing.py +0 -0
  233. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_esc_type.py +0 -0
  234. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_motor_cooling_source.py +0 -0
  235. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/dynamic_rotor_in_rotation_sense.py +0 -0
  236. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/export_geometry_request.py +0 -0
  237. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/export_geometry_request_format.py +0 -0
  238. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/export_geometry_request_rotation_type_0.py +0 -0
  239. {thrustlab-0.5.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
  240. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/fmu_export_accepted_response.py +0 -0
  241. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/fmu_export_job_error.py +0 -0
  242. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/fmu_export_status_response.py +0 -0
  243. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/generate_geometry_request.py +0 -0
  244. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/geometry_response.py +0 -0
  245. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/geometry_style_resource.py +0 -0
  246. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/geometry_styles_list_response.py +0 -0
  247. {thrustlab-0.5.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
  248. {thrustlab-0.5.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
  249. {thrustlab-0.5.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
  250. {thrustlab-0.5.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
  251. {thrustlab-0.5.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
  252. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/http_validation_error.py +0 -0
  253. {thrustlab-0.5.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
  254. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/list_events_v1_events_get_response_list_events_v1_events_get.py +0 -0
  255. {thrustlab-0.5.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
  256. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/pack_leaf_in.py +0 -0
  257. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/pack_parallel_in.py +0 -0
  258. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/pack_series_in.py +0 -0
  259. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/pack_topology_in.py +0 -0
  260. {thrustlab-0.5.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
  261. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/project_create_body.py +0 -0
  262. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/project_list_response.py +0 -0
  263. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/project_patch.py +0 -0
  264. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/project_resource.py +0 -0
  265. {thrustlab-0.5.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
  266. {thrustlab-0.5.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
  267. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in_esc_timing.py +0 -0
  268. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in_esc_type.py +0 -0
  269. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_group_in_motor_cooling_source.py +0 -0
  270. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_esc_timing.py +0 -0
  271. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_esc_type.py +0 -0
  272. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_motor_cooling_source.py +0 -0
  273. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/rotor_in_rotation_sense.py +0 -0
  274. {thrustlab-0.5.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
  275. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/run_selected_body.py +0 -0
  276. {thrustlab-0.5.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
  277. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/schedule_in.py +0 -0
  278. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/schedule_in_interpolation_type_0.py +0 -0
  279. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/schedule_in_mode.py +0 -0
  280. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_group_command_in.py +0 -0
  281. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_group_command_in_throttle_ramp_type_0.py +0 -0
  282. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_group_command_in_tilt_ramp_type_0.py +0 -0
  283. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in.py +0 -0
  284. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_airspeed_ramp.py +0 -0
  285. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_per_group.py +0 -0
  286. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_throttle_ramp.py +0 -0
  287. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/segment_in_vertical_speed_ramp.py +0 -0
  288. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/share_resource.py +0 -0
  289. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_cancel_body.py +0 -0
  290. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_cooling_source_type_0.py +0 -0
  291. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_flight_regime.py +0 -0
  292. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_inflow_mode.py +0 -0
  293. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_create_body_launch_intent.py +0 -0
  294. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_inputs.py +0 -0
  295. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_list_response.py +0 -0
  296. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_patch_plot_config_json_type_0_item.py +0 -0
  297. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_battery_topology_type_0.py +0 -0
  298. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_display_labels_type_0.py +0 -0
  299. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_error_type_0.py +0 -0
  300. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_input_snapshot_type_0.py +0 -0
  301. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_plot_config_json_type_0_item.py +0 -0
  302. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_result_type_0.py +0 -0
  303. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_result_type_0_additional_property.py +0 -0
  304. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/simulation_resource_status.py +0 -0
  305. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/spline_data.py +0 -0
  306. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/starred_component_create_body.py +0 -0
  307. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/starred_component_list_response.py +0 -0
  308. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/starred_component_resource.py +0 -0
  309. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/submission_create_body.py +0 -0
  310. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/submission_create_body_data_json.py +0 -0
  311. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/submission_list_response.py +0 -0
  312. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/submission_patch.py +0 -0
  313. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/submission_patch_data_json_type_0.py +0 -0
  314. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/submission_resource.py +0 -0
  315. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/submission_resource_data_json.py +0 -0
  316. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_cancel_body.py +0 -0
  317. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_config_in_esc_timing_values_type_0_item.py +0 -0
  318. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_create_body_inflow_mode.py +0 -0
  319. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_create_body_launch_intent.py +0 -0
  320. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_inputs.py +0 -0
  321. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_list_response.py +0 -0
  322. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_param_range_in_mode.py +0 -0
  323. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_patch_plot_config_json_type_0_item.py +0 -0
  324. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_component_selection.py +0 -0
  325. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_list_response.py +0 -0
  326. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_list_response_display_labels_type_0.py +0 -0
  327. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_patch.py +0 -0
  328. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_resource_rotors_type_0.py +0 -0
  329. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_point_resource_rotors_type_0_additional_property.py +0 -0
  330. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_error_type_0.py +0 -0
  331. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_input_snapshot_type_0.py +0 -0
  332. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_plot_config_json_type_0_item.py +0 -0
  333. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_status.py +0 -0
  334. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_summary_type_0.py +0 -0
  335. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_resource_sweep_config_type_0.py +0 -0
  336. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in_esc_timing.py +0 -0
  337. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in_esc_type.py +0 -0
  338. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_group_in_motor_cooling_source.py +0 -0
  339. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_esc_timing.py +0 -0
  340. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_esc_type.py +0 -0
  341. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_motor_cooling_source.py +0 -0
  342. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/sweep_rotor_in_rotation_sense.py +0 -0
  343. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/termination_in.py +0 -0
  344. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/termination_in_mode.py +0 -0
  345. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/types.py +0 -0
  346. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/user_resource_gate_required_tiers.py +0 -0
  347. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/user_resource_unit_system.py +0 -0
  348. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/v1_custom_component_override.py +0 -0
  349. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/v1_custom_component_override_spec_json.py +0 -0
  350. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/v1_health_v1_health_get_response_v1_health_v1_health_get.py +0 -0
  351. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/validation_error.py +0 -0
  352. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/webhook_endpoint_create.py +0 -0
  353. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_models/webhook_endpoint_patch.py +0 -0
  354. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/_pagination.py +0 -0
  355. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/client.py +0 -0
  356. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/exceptions.py +0 -0
  357. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/__init__.py +0 -0
  358. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/_base.py +0 -0
  359. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/components.py +0 -0
  360. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/compute_units.py +0 -0
  361. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/dynamic_simulations.py +0 -0
  362. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/fmu.py +0 -0
  363. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/projects.py +0 -0
  364. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/starred_components.py +0 -0
  365. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/submissions.py +0 -0
  366. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/users.py +0 -0
  367. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/resources/webhook_endpoints.py +0 -0
  368. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/README.md +0 -0
  369. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/__init__.py +0 -0
  370. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/__main__.py +0 -0
  371. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/bridge.py +0 -0
  372. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/cli.py +0 -0
  373. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/fmu.py +0 -0
  374. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/kinematics.py +0 -0
  375. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/model.py +0 -0
  376. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/protocol.py +0 -0
  377. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/rigidbody.py +0 -0
  378. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/rpmlog.py +0 -0
  379. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/__init__.py +0 -0
  380. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/ardupilot.py +0 -0
  381. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/base.py +0 -0
  382. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/targets/betaflight.py +0 -0
  383. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/sitl/vehicle.py +0 -0
  384. {thrustlab-0.5.0 → thrustlab-0.7.0}/thrustlab/webhooks.py +0 -0
@@ -6,7 +6,128 @@ 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
- ## [Unreleased]
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`.
95
+
96
+ ## [0.6.0] - 2026-09-09
97
+
98
+ ### Added
99
+
100
+ - `client.simulations.cancel_selected(run_ids)` cancels up to 1000 runs of any
101
+ kind (`sim_`, `sweep_`, `dyn_`) in one call and reports which were canceled,
102
+ which were asked to stop, and which were skipped and why.
103
+ `client.simulations.cancel_queued(project_id=...)` cancels every queued run
104
+ you own, optionally within one project.
105
+ - `client.simulations.run_queued()` and
106
+ `client.simulations.run_selected(simulation_ids)` dispatch runs parked with
107
+ `launch_intent="queue"` — all of them, or a named subset. Both accept sweep
108
+ ids as well as single-point ids.
109
+ - Generated models for the batch cancel response (`CancelBatchResult`,
110
+ `CancelSkipped`) and request body (`CancelSelectedBody`).
111
+ - Two runnable examples. `examples/sweeps/component_axis_grid.py` crosses a
112
+ propeller component axis with a throttle range in one submission and reads
113
+ the propeller name back off each point.
114
+ `examples/dynamic/watch_and_cancel.py` watches a mission's `progress` and
115
+ cancels it part-way through.
116
+
117
+ ### Changed
118
+
119
+ - Cancelling a running sweep is now a durable request: the server records it
120
+ and the worker stops after the point it is computing, even if the stop takes
121
+ longer than a minute to reach.
122
+ - Cancelling a RUNNING dynamic mission now reports under `requested` rather
123
+ than `canceled`. The mission keeps its partial result (`run_meta.partial`,
124
+ `run_meta.canceled_at_t_s`), the credits are refunded, and the execution slot
125
+ frees when the worker stops at its next integration window.
126
+ - Run resources carry `started_at`, the instant the solver began, alongside
127
+ `created_at`, `dispatched_at` and `completed_at`. Queue wait is
128
+ `started_at - dispatched_at`.
129
+ - Dynamic run resources carry `progress` and `cancel_requested_at`. Sweep
130
+ resources carry `cancel_requested_at` and `credits_breakdown`.
10
131
 
11
132
  ## [0.5.0] - 2026-08-31
12
133
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thrustlab
3
- Version: 0.5.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
@@ -93,6 +93,53 @@ Runnable end-to-end examples for every simulation type live in
93
93
  [`sweeps/run_and_poll.py`](./examples/sweeps/run_and_poll.py), and
94
94
  [`dynamic/run_and_poll.py`](./examples/dynamic/run_and_poll.py).
95
95
 
96
+ ## FMU export and SITL
97
+
98
+ Export a completed simulation as an FMI 3.0 co-simulation FMU:
99
+
100
+ ```python
101
+ job_id = client.fmu.export(sim_id)["id"]
102
+ client.fmu.wait(job_id)
103
+ client.fmu.download(job_id, "powertrain.fmu")
104
+ ```
105
+
106
+ The FMU exposes per-rotor inputs and outputs, battery and thermal state, and a
107
+ validity envelope; it runs in any FMI 3.0 co-simulation host and is verified
108
+ in Simulink.
109
+
110
+ `thrustlab-sitl`, installed with the SDK, flies the FMU in ArduPilot SITL or
111
+ Betaflight SITL (`--target betaflight`). See
112
+ [`thrustlab/sitl/README.md`](./thrustlab/sitl/README.md) for the full
113
+ documentation.
114
+
115
+ ```shell
116
+ thrustlab-sitl --fmu powertrain.fmu --vehicle quad_x.yaml --target betaflight
117
+ ```
118
+
119
+ See [`examples/fmu/`](./examples/fmu/) for bundled ready-to-fly FMUs with
120
+ quadcopter, Y6 coax, and tilt-tricopter missions, an endurance study, and
121
+ replay rendering.
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
+
96
143
  ## Why the SDK (and not `urllib` / `wget`)?
97
144
 
98
145
  The SDK gives you automatic retries with backoff, idempotency keys, cursor
@@ -131,6 +178,7 @@ client.submissions
131
178
  client.starred_components
132
179
  client.compute_units
133
180
  client.webhook_endpoints
181
+ client.fmu
134
182
  ```
135
183
 
136
184
  ## Error handling
@@ -57,6 +57,53 @@ Runnable end-to-end examples for every simulation type live in
57
57
  [`sweeps/run_and_poll.py`](./examples/sweeps/run_and_poll.py), and
58
58
  [`dynamic/run_and_poll.py`](./examples/dynamic/run_and_poll.py).
59
59
 
60
+ ## FMU export and SITL
61
+
62
+ Export a completed simulation as an FMI 3.0 co-simulation FMU:
63
+
64
+ ```python
65
+ job_id = client.fmu.export(sim_id)["id"]
66
+ client.fmu.wait(job_id)
67
+ client.fmu.download(job_id, "powertrain.fmu")
68
+ ```
69
+
70
+ The FMU exposes per-rotor inputs and outputs, battery and thermal state, and a
71
+ validity envelope; it runs in any FMI 3.0 co-simulation host and is verified
72
+ in Simulink.
73
+
74
+ `thrustlab-sitl`, installed with the SDK, flies the FMU in ArduPilot SITL or
75
+ Betaflight SITL (`--target betaflight`). See
76
+ [`thrustlab/sitl/README.md`](./thrustlab/sitl/README.md) for the full
77
+ documentation.
78
+
79
+ ```shell
80
+ thrustlab-sitl --fmu powertrain.fmu --vehicle quad_x.yaml --target betaflight
81
+ ```
82
+
83
+ See [`examples/fmu/`](./examples/fmu/) for bundled ready-to-fly FMUs with
84
+ quadcopter, Y6 coax, and tilt-tricopter missions, an endurance study, and
85
+ replay rendering.
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
+
60
107
  ## Why the SDK (and not `urllib` / `wget`)?
61
108
 
62
109
  The SDK gives you automatic retries with backoff, idempotency keys, cursor
@@ -95,6 +142,7 @@ client.submissions
95
142
  client.starred_components
96
143
  client.compute_units
97
144
  client.webhook_endpoints
145
+ client.fmu
98
146
  ```
99
147
 
100
148
  ## Error handling
@@ -18,8 +18,8 @@ Notes on validation:
18
18
  one resistance figure (c_rating or pack_resistance_mOhm), and bounding-box
19
19
  dims; form_factor is derived from chemistry when omitted.
20
20
  * Propeller: per-station radius/chord/twist and rotation are required, and
21
- persisting a propeller needs the hobbyist tier or higher — the create below
22
- reports the tier gate cleanly on a free account.
21
+ persisting a propeller needs the Pro plan — the create below reports the
22
+ tier gate cleanly on a free account.
23
23
  """
24
24
 
25
25
  from thrustlab import Client
@@ -0,0 +1,132 @@
1
+ """Dynamic progress + cancel: submit -> watch `progress` -> cancel -> read the partial.
2
+
3
+ Run it:
4
+ export THRUSTLAB_API_KEY=key_... # never hard-code the key
5
+ python examples/dynamic/watch_and_cancel.py
6
+
7
+ Submits a mission that flies until the pack is empty, watches `progress` while
8
+ it runs, cancels it part-way through, and reads the partial result.
9
+
10
+ `progress` is {fraction, sim_time_s, sim_time_total_s, wall_s, updated_at}, and
11
+ is None until the worker picks the run up.
12
+
13
+ Cancelling a RUNNING dynamic mission does not stop it instantly. The response
14
+ keeps status "running" and sets `cancel_requested_at`; the worker stops at its
15
+ next integration window, at most 20 seconds of mission time. What comes back is
16
+ a real partial result: `run_meta.partial` is true, `run_meta.canceled_at_t_s`
17
+ gives the mission time it stopped at, and the credits are refunded.
18
+
19
+ This mission runs to depletion, so `fraction` is an estimate rather than an
20
+ exact ratio.
21
+ """
22
+
23
+ import time
24
+
25
+ from thrustlab import Client
26
+
27
+ client = Client() # reads $THRUSTLAB_API_KEY from the environment
28
+
29
+ project = client.projects.create(name="sdk dynamic progress example")
30
+
31
+ motor = client.components.find(name="BadAss 2826-820Kv")
32
+ prop = client.components.find(name="10.5x4.5")
33
+ battery = client.components.find(
34
+ name="Liperior 5000mAh 4S 35C 14.8V Lipo Battery With XT90 Plug"
35
+ )
36
+
37
+ # A hover flown until the pack is empty.
38
+ #
39
+ # The schedule steps to 15% before it ramps, rather than ramping up from rest.
40
+ # One external study observed ramps starting at near-zero duty producing a
41
+ # handful of non-converged rows in their first milliseconds; as a fraction of a
42
+ # short flight's rows that was enough to get a run rejected with
43
+ # `solver_no_convergence`. Stepping to a working throttle first avoided it.
44
+ dyn = client.dynamic_simulations.create(
45
+ project_id=project["id"],
46
+ battery_component_id=battery["id"],
47
+ density_kg_m3=1.225,
48
+ battery_charge_pct=100,
49
+ ambient_temp_c=25,
50
+ rotor_groups=[
51
+ {
52
+ "label": "main",
53
+ "count": 4,
54
+ "motor_component_id": motor["id"],
55
+ "propeller_component_id": prop["id"],
56
+ }
57
+ ],
58
+ schedule={
59
+ "mode": "segments",
60
+ "segments": [
61
+ # Step to the ESC's working range first.
62
+ {
63
+ "duration_s": 0.2,
64
+ "airspeed_target": 0.0,
65
+ "per_group": {"main": {"throttle_target": 15, "throttle_ramp": "step"}},
66
+ },
67
+ # Then ramp from there to the hover setting.
68
+ {
69
+ "duration_s": 2.0,
70
+ "airspeed_target": 0.0,
71
+ "per_group": {"main": {"throttle_target": 65, "throttle_ramp": "linear"}},
72
+ },
73
+ # Hold until the pack is empty. `until_depleted` takes no duration.
74
+ {
75
+ "until_depleted": True,
76
+ "airspeed_target": 0.0,
77
+ "per_group": {"main": {"throttle_target": 65}},
78
+ },
79
+ ],
80
+ },
81
+ # The total mission time is not known in advance, so progress["fraction"]
82
+ # is an estimate rather than an exact ratio.
83
+ termination={"mode": "until_depleted", "soc_cutoff_pct": 20.0},
84
+ )
85
+ print(f"created {dyn['id']}, status={dyn['status']}")
86
+
87
+ # Watch progress. 2-5 s is the right cadence; anything faster spends requests
88
+ # on a value the worker only rewrites once per integration window.
89
+ CANCEL_AFTER_S = 45.0
90
+ deadline = time.monotonic() + CANCEL_AFTER_S
91
+
92
+ while time.monotonic() < deadline:
93
+ time.sleep(3.0)
94
+ run = client.dynamic_simulations.retrieve(dyn["id"])
95
+ if run["status"] not in ("queued", "running"):
96
+ break
97
+ # `progress` is None until the worker picks the run up.
98
+ p = run.get("progress")
99
+ if p is None:
100
+ print(f" {run['status']}, no progress yet")
101
+ continue
102
+ frac = p.get("fraction")
103
+ pct = f"{frac * 100:5.1f}%" if frac is not None else " ? %"
104
+ print(f" {pct} sim {p['sim_time_s']:.1f} s wall {p['wall_s']:.1f} s")
105
+
106
+ run = client.dynamic_simulations.retrieve(dyn["id"])
107
+ if run["status"] in ("queued", "running"):
108
+ # Cancel whatever state the deadline caught it in. A queued run comes back
109
+ # `canceled` immediately, with the compute units refunded and no result. A
110
+ # running one comes back still `running` with cancel_requested_at set, and
111
+ # the worker stops at its next integration window.
112
+ #
113
+ # Cancelling both matters here: with every execution slot busy this run can
114
+ # still be queued at the deadline, and skipping it would leave it to
115
+ # execute later against a script that has already exited.
116
+ accepted = client.dynamic_simulations.cancel(dyn["id"])
117
+ print(f"\ncancel accepted: status={accepted['status']}, "
118
+ f"cancel_requested_at={accepted.get('cancel_requested_at')}")
119
+ run = client.dynamic_simulations.wait(dyn["id"], timeout=300)
120
+
121
+ print(f"final status: {run['status']}")
122
+
123
+ blob = run.get("result")
124
+ if blob:
125
+ meta = blob["run_meta"]
126
+ if meta.get("partial"):
127
+ print(f"partial result, stopped at t = {meta['canceled_at_t_s']:.1f} s of mission time")
128
+ sc = blob["scorecard"]
129
+ print(f"flight time: {sc['flight_time_s']:.1f} s")
130
+ print(f"energy: {sc['energy_wh']:.1f} Wh")
131
+ print(f"peak winding: {sc['peak_winding_temp_c']:.1f} C")
132
+ print(f"samples returned: {len(blob['samples'])}")
@@ -22,7 +22,7 @@ state of charge — all from the `.fmu` you exported.
22
22
  ```sh
23
23
  mkdir -p mission_out
24
24
  python -m thrustlab.sitl \
25
- --fmu my-powertrain.fmu --vehicle quad_x.yaml \
25
+ --fmu ../validation-quad.fmu --vehicle quad_x.yaml \
26
26
  --rpm-log mission_out/mission_rpm_log.csv
27
27
  ```
28
28
 
@@ -78,3 +78,12 @@ RPM lane — so the bridge logs it to `mission_out/mission_rpm_log.csv` for
78
78
  reconciliation against flight logs. If you changed the vehicle mass in
79
79
  `quad_x.yaml`, set `WEIGHT_N` at the top of `plot_mission.py` to match — it
80
80
  aligns the two recordings' clocks on the takeoff event.
81
+
82
+ ## The bundled FMU
83
+
84
+ This example ships with a ready-to-fly FMU exported from ThrustLab
85
+ (`../validation-quad.fmu`). The exact powertrain it reproduces is documented
86
+ in the archive's own `resources/README.md`; unzip the FMU to read it. To
87
+ recreate the FMU, build the same powertrain in ThrustLab or through the
88
+ API/SDK, then export it with **Export → FMU** or `client.fmu`; your export
89
+ will fly these examples identically.
@@ -31,7 +31,7 @@ Everything the quad example needs (`../ardupilot_sitl/README.md`), plus:
31
31
  ```sh
32
32
  mkdir -p mission_out
33
33
  python -m thrustlab.sitl \
34
- --fmu my-tri-powertrain.fmu --vehicle tilttri.yaml \
34
+ --fmu example-tri.fmu --vehicle tilttri.yaml \
35
35
  --rpm-log mission_out/mission_rpm_log.csv
36
36
  ```
37
37
 
@@ -74,3 +74,12 @@ physics. And a stopped rotor's flag means nothing: the rear rotor is
74
74
  deliberately stopped for most of the circuit while the wing carries the
75
75
  weight, so judge the envelope over spinning rotors only — the replay video
76
76
  does exactly that.
77
+
78
+ ## The bundled FMU
79
+
80
+ This example ships with a ready-to-fly FMU exported from ThrustLab
81
+ (`example-tri.fmu`). The exact powertrain it reproduces is documented in the
82
+ archive's own `resources/README.md`; unzip the FMU to read it. To recreate
83
+ the FMU, build the same powertrain in ThrustLab or through the API/SDK, then
84
+ export it with **Export → FMU** or `client.fmu`; your export will fly these
85
+ examples identically.
@@ -22,7 +22,7 @@ Same three terminals as the quad example, swapping in this directory's files:
22
22
  ```sh
23
23
  mkdir -p mission_out
24
24
  python -m thrustlab.sitl \
25
- --fmu my-y6-powertrain.fmu --vehicle y6.yaml \
25
+ --fmu example-y6.fmu --vehicle y6.yaml \
26
26
  --rpm-log mission_out/mission_rpm_log.csv
27
27
  ```
28
28
 
@@ -32,15 +32,19 @@ python -m thrustlab.sitl \
32
32
  ```
33
33
 
34
34
  ```sh
35
- python ../ardupilot_sitl/fly_mission.py --out-dir ./mission_out --speed-scale 0.3
35
+ python ../ardupilot_sitl/fly_mission.py --out-dir ./mission_out --speed-scale 0.42
36
36
  ```
37
37
 
38
- `--speed-scale 0.3` matters here: a coax lane's sampled envelope is tighter
39
- than a solo rotor's map — edgewise speed caps near 5 m/s at this scale and
40
- descent states are not sampled at all — so the full-speed mission spends
41
- most of its time flagged `all_in_envelope=false` (outputs clamp to the
42
- envelope edge instead of being measured). Scaled down, the flight stays on
43
- sampled physics except for brief descents.
38
+ `--speed-scale 0.42` uses the bundled FMU's wider sampled coax envelope: at
39
+ hover rotor speed, it covers level edgewise flight to about 7 m/s, descent to
40
+ 3 m/s, and gentle approach legs (about 1.5 m/s down) to about 4.5 m/s
41
+ edgewise. The entire 397-second demo mission stays on measured physics, with
42
+ 99.2% of armed frames `all_in_envelope`; the remainder are brief arm/disarm
43
+ spool transients. The binding limit is the slowest rotor because the edgewise
44
+ axis scales with rotor speed, advance-ratio style: in forward flight the
45
+ unloaded rear-lower rotor reaches the envelope edge near 6.3 m/s, while
46
+ loaded rotors remain covered to about 7.3 m/s. Beyond the envelope, outputs
47
+ clamp to its edge and set `all_in_envelope=false` rather than extrapolating.
44
48
 
45
49
  ## The plots
46
50
 
@@ -60,3 +64,12 @@ python plot_coax_split.py ./mission_out ./mission_out/plots
60
64
  Its bottom panel is the point of the whole example: the lower rotor's share
61
65
  of each stack's thrust sits below 50% for the entire flight — the wake
62
66
  coupling, resolved per rotor, in a model the autopilot drives at 400 Hz.
67
+
68
+ ## The bundled FMU
69
+
70
+ This example ships with a ready-to-fly FMU exported from ThrustLab
71
+ (`example-y6.fmu`). The exact powertrain it reproduces is documented in the
72
+ archive's own `resources/README.md`; unzip the FMU to read it. To recreate
73
+ the FMU, build the same powertrain in ThrustLab or through the API/SDK, then
74
+ export it with **Export → FMU** or `client.fmu`; your export will fly these
75
+ examples identically.
@@ -81,7 +81,7 @@ ls eeprom.bin
81
81
  ```bash
82
82
  python -m thrustlab.sitl \
83
83
  --target betaflight \
84
- --fmu ~/validation-quad.fmu \
84
+ --fmu ../validation-quad.fmu \
85
85
  --vehicle betaflight_quad_x.yaml \
86
86
  --rpm-log mission_rpm_log.csv \
87
87
  --truth-port 9005 \
@@ -240,3 +240,12 @@ servo channels at all. The error reports the received size.
240
240
  - Betaflight master provides waypoint navigation through `BOX_AUTOPILOT` and
241
241
  `waypoint insert` in the CLI. The bridge supplies the required data, but this
242
242
  example does not test it.
243
+
244
+ ## The bundled FMU
245
+
246
+ This example ships with a ready-to-fly FMU exported from ThrustLab
247
+ (`../validation-quad.fmu`). The exact powertrain it reproduces is documented
248
+ in the archive's own `resources/README.md`; unzip the FMU to read it. To
249
+ recreate the FMU, build the same powertrain in ThrustLab or through the
250
+ API/SDK, then export it with **Export → FMU** or `client.fmu`; your export
251
+ will fly these examples identically.
@@ -16,7 +16,7 @@ of extrapolated.
16
16
 
17
17
  ```sh
18
18
  pip install fmpy numpy matplotlib
19
- python hover_endurance.py my-powertrain.fmu --mass-kg 1.20
19
+ python hover_endurance.py ../validation-quad.fmu --mass-kg 1.20
20
20
  ```
21
21
 
22
22
  `--mass-kg` is the all-up mass WITHOUT payload (airframe + battery).
@@ -29,3 +29,12 @@ each flight — the spread between the two is the battery sag made visible.
29
29
 
30
30
  Export an FMU with `examples/fmu/export_and_download.py` or the dashboard's
31
31
  Share menu.
32
+
33
+ ## The bundled FMU
34
+
35
+ This example ships with a ready-to-fly FMU exported from ThrustLab
36
+ (`../validation-quad.fmu`). The exact powertrain it reproduces is documented
37
+ in the archive's own `resources/README.md`; unzip the FMU to read it. To
38
+ recreate the FMU, build the same powertrain in ThrustLab or through the
39
+ API/SDK, then export it with **Export → FMU** or `client.fmu`; your export
40
+ will fly these examples identically.
@@ -7,7 +7,7 @@ links — spin-up dynamics, battery state and envelope flags included.
7
7
 
8
8
  ## What you need
9
9
 
10
- - An exported FMU, **unzipped** (`unzip my-powertrain.fmu -d my-powertrain/`).
10
+ - An exported FMU, **unzipped** (`unzip ../validation-quad.fmu -d validation-quad/`).
11
11
  - The `fmu-gz-plugin` ThrustlabFmuSystem plugin, built against gz-sim ≥ 9
12
12
  (see its README for the CMake build; it dlopens the FMU's own
13
13
  `binaries/x86_64-linux/*.so`).
@@ -61,3 +61,12 @@ For an ArduPilot- or PX4-controlled Gazebo vehicle, keep their standard
61
61
  Gazebo integration for control surfaces and use this plugin as the
62
62
  propulsion + battery physics; the ArduPilot JSON bridge
63
63
  (`thrustlab.sitl`) is the lighter path when you don't need a 3D world.
64
+
65
+ ## The bundled FMU
66
+
67
+ This example ships with a ready-to-fly FMU exported from ThrustLab
68
+ (`../validation-quad.fmu`). The exact powertrain it reproduces is documented
69
+ in the archive's own `resources/README.md`; unzip the FMU to read it. To
70
+ recreate the FMU, build the same powertrain in ThrustLab or through the
71
+ API/SDK, then export it with **Export → FMU** or `client.fmu`; your export
72
+ will fly these examples identically.
@@ -0,0 +1,2 @@
1
+ slprj/
2
+ *.slxc
@@ -0,0 +1,53 @@
1
+ # Simulink co-simulation
2
+
3
+ `run_fmu_simulink.m` builds a Simulink model programmatically, imports the
4
+ bundled quadcopter FMU, commands a fixed throttle on every rotor, and runs
5
+ FMI 3.0 Co-Simulation. It plots thrust, bus voltage, and battery state of
6
+ charge to `fmu_cosim.png`.
7
+
8
+ ![Thrust, bus voltage, and battery state of charge](fmu_cosim.png)
9
+
10
+ ## Requirements
11
+
12
+ MATLAB + Simulink, verified on R2025a. No toolboxes beyond Simulink are
13
+ required.
14
+
15
+ ## Run it
16
+
17
+ From this folder:
18
+
19
+ ```sh
20
+ matlab -batch "run('run_fmu_simulink.m')"
21
+ ```
22
+
23
+ Or open `run_fmu_simulink.m` in MATLAB and run it interactively.
24
+
25
+ ## FMU import gotchas
26
+
27
+ Three things that will silently ruin the model if changed:
28
+
29
+ - The FMU Import block lives in the Simulink Extras library
30
+ (`'simulink_extras/FMU Import/FMU'`), NOT in User-Defined Functions.
31
+ - The block wants a BARE file name with the FMU's folder on the MATLAB
32
+ path — a full path in `FMUName` is not accepted.
33
+ - Every FMU output you care about must be wired to a root Outport;
34
+ unconnected outputs are removed by block reduction and the simulation
35
+ proves nothing about them.
36
+
37
+ Port order follows the FMU's `modelDescription.xml` declaration order and is
38
+ the same for every ThrustLab export regardless of rotor count. The full
39
+ input and output list is in the script header.
40
+
41
+ ## Use your own FMU
42
+
43
+ Export an FMU from a completed simulation through **Share → Export FMU** or
44
+ `client.fmu`. Put its folder on the MATLAB path, then set `FMU_FILE` to the
45
+ bare archive name and `N_ROTORS` to its rotor count in
46
+ `run_fmu_simulink.m`.
47
+
48
+ ## The bundled FMU
49
+
50
+ This example ships with a quadcopter FMU exported from ThrustLab
51
+ (`../validation-quad.fmu`). The exact powertrain it reproduces is documented
52
+ in the archive's own `resources/README.md`; unzip the FMU to read it. An
53
+ equivalent export will fly this example identically.