Migration Guide#
TudatPy v1.0#
This section provides a guide for users migrating from TudatPy v0.9 and older to v1.0.
Have questions or feedback? As always, let us know in our Github Discussion forum!
Installation#
How to obtain the new version: the installation of tudatpy for users has not changed, you can simply use our installation using the conda packages
as described on our installation guide. The only difference is that installing tudatpy will now no longer result in a separate tudat and tudatpy conda packages being installed, since the two have been merged into a single tudatpy package.
New module structure#
As of v1.0, we have thoroughly re-organized the module structure of tudatpy. We have implemented this such that old import statements will still work (so v1.0 is backwards compatible with code written for older version), but will phase out this support in later versions. A comprehensive overview of the changes to the module structure is given below.
Why was this needed?#
There are two driving reasons behind our reorganization of the module structure. The primary reason is the poor organization of functionality in the numerical_simulation.estimation and numerical_simulation.estimation_setup modules, which led to a large amount of functionality being combined into a small number of modules
(such as numerical_simulation.estimation_setup.observation), making tudatpy functionality poorly findable, and hampering transparent further developments. An additional reason was that the bulk of the functionality was in the numerical_simulation module. It was decided to split this into two top-level modules dynamics and estimation, where the former contains functionality for propagation of dynamics, and the latter contains all functionality required for estimation of states and parameters from (tracking) data.
In addition to these two drivers, we also took the opportunity to re-organize some other minor aspects of the modules, moving some classes and functions into a more suitable module.
How does it effect users?#
The impact on existing scripts should be none, since all reorganization has been done in a backwards compatible manner. If you find any functionality fot which this does not seem to be the case, let us know in our Github Discussion forum.
Using the pre-v1.0 imports will result in a deprecation warning being printed. We expect to drop support for the older imports after two years, in the course of 2027.
All newly developed functionality will only be provided in the new module structure. In addition, all updates to documentation will only be available in the new module setup, so we recommend all users to update their code to the new import statements.
How to migrate?#
Migrating to the new module setup can be done by modifying top-level import statements of modules, and module specifications in the code when using a specific piece of functionality. Most of the propagation-related functionality in the environment, environment_setup, propagation and propagation_setup submodules is simply moved from the old numerical_simulation module to the new dynamics module. Estimation-related functionality in the estimation and estimation_setup submodules has been refactored in multiple submodules, which requires more detailed treatment. Below we provide an overview of all changes that have been made. Implementing these modifications in your code should fully migrate you to v1.0!
Old module |
New module |
|---|---|
|
|
Top-level |
Split in |
|
|
|
|
|
|
|
|
|
Distributed in |
|
Distributed in |
|
Split in |
|
Split in |
New Time type#
Up until v0.9, tudatpy used float variables to denote both epochs and durations of time. As of v1.0, we have moved to a new setup where time is represented by a dedicated Time class. Also in v0.9 and earlier, it was possible to use the Time type internally, but this required manual recompilation with specific settings to trigger this behaviour. As of v1.0, we have chosen to make this the default behaviour in our packages.
Why was this needed?#
A float variable has a numerical resolution of about \(2\cdot 10^{-16}\), meaning that a relative change below this level cannot be represented. In Tudat, we use seconds since epoch J2000 as time representation. Using a float for this means that for epochs durther away from J2000, the resolution to which time can be represented degrades. For either 1950 or 2050 (about \(1.6\cdot 10^{9}\) seconds from J2000) this imposes a hard limit of 0.35 microseconds in resolution of time.
There are several concrete examples of cases where this poor timing resolution limits the performance of analyses. For numerical integration with small time steps, rounding errors in the representation of time have been known to lead to confusing results in (for instance) benchmarking. As an additional example, in Doppler data analysis of planetary missions, the observable is computed by the difference of two light times. Due to the limited resolution in representing epochs, using Time is required to get state-of-the-art performance. This required Tudat to be manually compiled to use this functionality. With the data analysis framework of Tudat taking an ever more prominent place, it has become important to provide this functionality in the ânormalâ package.
How does it affect users?#
The modifications we have made to change to a different time representation have all been made in a backwards compatible manner. An implicit conversion between Time and float has been implemented, so that any function that requires a Time object as input can also take a float as input. In doing so, the value is âupconverted` to the higher resolution representation, allowing all later computations to be done at the high resolution.
Various output structures in tudat are provided as dictionaries with time as the independent variable (key). By default, the output a user extracts, for instance from the state_history attribute for the state history from a numerical propagation will (as in v0.9 and earlier) provide this state history with float as independent variable, since for most post-processing purposes this is both sufficient and more convenient. However, we now also provide the option to retrieve the state history with time at the native resolution in which the propagation was performed by using the state_history_time_object attribute. A similar setup has been introduced in various other tudat output options, facilitating backwards compatibility, permitting use of the more typical float for post-processing, and providing access to the native resolution when required. Some more information on Tudat time representations can be found on our page for Using time representations.
How to migrate?#
No action is required to migrate for this modification. All v0.9 interfaces remain valid and are not deprecated. For various applications, it will not be relevant whether the float or Time representation is used internally, and inputs and outputs using float continue to be valid as they were before. Even for applications where the use of the high-accuracy internal time representation improves numerical results, it will often still be sufficient to provide the input and output at the original float representation.
Merging of tudatpy repositories and conda packages#
The previous structure of the project, with separate conda packages and code repositories for tudat (underlying C++ models) and tudatpy (Python exposure), as well as a tudat-bundle repositories for developers to compile both tudat and tudatpy concurrently, has been a source of various complications and inconsistencies. The codebase from the original tudat repository is now included as a subdirectory within the tudatpy repository (with some reorganization), which contains both the C++ source code and the Python bindings. The tudatpy-examples repository still exists, now as a submodule within tudatpy. The tudat-bundle repository has been deprecated, developers now compile the tudatpy repository directly.
The CMake configuration from tudat has been merged into the main CMakeLists.txt of tudatpy, resulting in a unified build system. The tudatpy repository now follows a mirrored structure: each component has its own tudat (for C++) and tudatpy (for Python) subdirectories. In general, the core logic is located in the tudat folders, while Python bindings and Python-only functionality are placed under the tudatpy folders. The build logic is now largely identical for developing, testing and deploying.
Where some files were previously duplicated or mirrored between tudat and tudatpy, they have now been consolidatedâtypically by keeping the version from tudatpy when the content was identical.
The tudat conda package and tudat-feedstock repository are now longer used with this change. The tudatpy conda package now contains both the underlying C++ models and the Python exposure.
Why was this needed?#
The decision to merge the tudat and tudatpy repositories was driven by the need to simplify development, testing, and packaging workflows. Maintaining them separately had become increasingly cumbersome, and the original motivation for the split no longer reflects how the project is used today.
Here are the main reasons behind the merge:
Simpler build process: Previously, the tudat and tudatpy conda packages had to be built in sequence, which made the setup more fragile and added unnecessary overheadâespecially for contributors and automated packaging.
More effective testing: With separate repositories, the continuous integration pipelines were also split. This made it difficult to test changes to tudatpy until corresponding changes in tudat were merged, since the PRs werenât linked. A single repo ensures all components can be tested together.
Reduced complexity: Developers were expected to build from the tudat-bundle repository, even though the actual source code lived in tudat and tudatpy. This indirection often caused confusion, particularly for new contributors. The merge removes this extra layer.
Consistent configuration: Maintaining separate build systems (CMake and conda feedstock) for two repositories sometimes led to inconsistencies or duplication of effort. A unified repo makes it easier to keep things aligned.
Changing usage patterns: The repositories were originally split to support C++-only users. However, most users now rely on the Python interface. With the merged setup, C++-only workflows are still fully supported, but thereâs no longer a strong reason to keep the two codebases apart.
In short, the merge makes Tudat easier to work with, more robust to maintain, and better aligned with how itâs actually used by the community.
How does it effect users?#
The repository restructuring introduces a cleaner and more unified layout, but all core functionalities remain unchanged. Most users will continue working with tudatpy as before.
However, developers who were actively working on branches in the old tudat repository will need to migrate their work to the new combined repository. This typically involves rebasing or transplanting their changes into the appropriate location within the new structure (e.g. moving C++ code to the tudat/ subdirectory within tudatpy).
To preserve commit history and ensure smooth integration, we recommend carefully following the steps outlined in the âHow to Migrate?â section below. If you encounter any issues or are unsure how to proceed, feel free to reach out to the core development team on our discussion forum
How to migrate?#
For users, simply creating a new conda environment for tudatpy (as per out Installation) will migrate to the new setup, without any changes on the user side.
Developers without any active development branches on either tudat or tudatpy (pre-v1.0) should clone the new (v1.0) tudatpy develop branch, and work with this in the exact same manner as they interacted with the old tudat-bundle repository.
Developers with active development branches on either tudat or tudatpy that have diverged from the develop branch should contact the tudatpy development team. We can assist in migrating your code to the new repository setup.