├── .antora ├── antora.yml └── modules │ └── sensor-model │ ├── nav.adoc │ └── pages ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md ├── pull_request_template.md └── workflows │ ├── antora-generator.yml │ ├── protobuf.yml │ └── remote_release.yml ├── .gitignore ├── .gitmodules ├── .markdownlint.json ├── LICENSE ├── README.md ├── VERSION ├── doc ├── _config.adoc ├── misc │ ├── example.adoc │ └── introduction.adoc ├── osi-sensor-model-packaging_spec.adoc ├── setup │ └── build_install_example.adoc └── spec │ ├── basic_conventions.adoc │ ├── binary_variables.adoc │ ├── ground_truth_init_parameters.adoc │ ├── model_types.adoc │ ├── sensor_data_inputs.adoc │ ├── sensor_data_outputs.adoc │ ├── sensor_view_input_configuration.adoc │ ├── sensor_view_inputs.adoc │ ├── sensor_view_outputs.adoc │ ├── streaming_update_inputs.adoc │ ├── traffic_command_inputs.adoc │ ├── traffic_command_update_outputs.adoc │ └── traffic_update_outputs.adoc ├── examples ├── CMakeLists.txt ├── Modules │ └── FindZeroMQ.cmake ├── OSMPCNetworkProxy │ ├── CMakeLists.txt │ ├── OSMPCNetworkProxy.c │ ├── OSMPCNetworkProxy.h │ ├── OSMPCNetworkProxyConfig.in.h │ └── modelDescription.in.xml ├── OSMPDummySensor │ ├── CMakeLists.txt │ ├── OSMPDummySensor.cpp │ ├── OSMPDummySensor.h │ ├── OSMPDummySensorConfig.in.h │ └── modelDescription.in.xml ├── OSMPDummySource │ ├── CMakeLists.txt │ ├── OSMPDummySource.cpp │ ├── OSMPDummySource.h │ ├── OSMPDummySourceConfig.in.h │ └── modelDescription.in.xml ├── README.md └── includes │ ├── fmi2FunctionTypes.h │ ├── fmi2Functions.h │ ├── fmi2TypesPlatform.h │ ├── fmiFunctions.h │ └── fmiPlatformTypes.h ├── local_build_tools ├── asciidoctor.bat ├── compose.yml └── windows_convert_symlinks(ADMIN).bat └── osmp.xsd /.antora/antora.yml: -------------------------------------------------------------------------------- 1 | # Component name (without spaces!). All content repositories with the same component name are merged in Antora. 2 | name: asamosi 3 | version: 4 | # Update version number accordingly. This is the version for the main branch 5 | main: 'current' 6 | master: 'current' 7 | v(*)-antora: V$1 8 | x-antora-v(*): V$1 9 | v(*): V$1 10 | V(*): V$1 11 | # Update version number accordingly. This is the version for any other activated branch (branch must be added in the generator site.yml!). Schema = 0.0.x- (only works for branches starting with "feature/") 12 | (*): 'V3.6.0-$1' 13 | -------------------------------------------------------------------------------- /.antora/modules/sensor-model/nav.adoc: -------------------------------------------------------------------------------- 1 | [preface] 2 | * xref:00_preface/00_foreword.adoc[] 3 | [preface] 4 | * xref:00_preface/01_introduction.adoc[] 5 | * xref:01_scope/01_scope.adoc[] 6 | * xref:02_normative_references/01_normative_references.adoc[] 7 | * xref:03_terms_and_definitions/01_terms_and_definitions.adoc[] 8 | * xref:04_abbreviations/01_abbreviations.adoc[] 9 | * xref:05_backward_compatibility/01_backward_compatibility.adoc[] 10 | 11 | [appendix] 12 | * xref:xx_annexes/REPLACE_ME.adoc[] 13 | [bibliography] 14 | * xref:bibliography.adoc[] 15 | 16 | :sectnums!: 17 | * xref:list_of_figures.adoc[] 18 | 19 | :sectnums!: 20 | * xref:list_of_tables.adoc[] 21 | 22 | // TODO Replace with generator -------------------------------------------------------------------------------- /.antora/modules/sensor-model/pages: -------------------------------------------------------------------------------- 1 | ../../../doc -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | #### Describe the bug 11 | A clear and concise description of what the bug is. 12 | 13 | #### Describe how to reproduce the bug 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | #### Describe the expected behavior 21 | A clear and concise description of what you expected to happen. 22 | 23 | #### Show some screenshots 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | #### Describe the OS you are using 27 | - OS: [e.g. iOS, Ubuntu 18.04, Windows 10, ...] 28 | - Language: [e.g. C++, Python, ...] 29 | - Version [e.g. 3.6.8] 30 | 31 | #### Additional context 32 | Add any other context about the bug here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature request 6 | assignees: '' 7 | 8 | --- 9 | 10 | #### Describe the feature 11 | Is your feature request related to a problem? 12 | A clear and concise description of what the problem is. 13 | Example: I am always frustrated when [...]. 14 | 15 | #### Describe the solution you would like 16 | A clear and concise description of what you want to happen. 17 | 18 | #### Describe alternatives you have considered 19 | A clear and concise description of any alternative solutions or features you have considered. 20 | 21 | #### Describe the backwards compatibility 22 | How does the feature impact the backwards compatibility of the current major version of OSI Sensor Model Packaging? 23 | If the suggested feature would be implemented would there be an issue with the previous versions of OSI Sensor Model Packaging? What part of OSI Sensor Model Packaging would break or improve by this feature? 24 | 25 | #### Additional context 26 | Add any other context or screenshots about the feature request here. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question if you do not understand something or just want clarifications. 4 | title: '' 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | #### Describe the problem 11 | I want to do ... in my application, but what I am actually getting is.... 12 | Here is a screenshot that illustrates the problem: 13 | 14 | `image.png` 15 | 16 | #### Describe what you have already tried 17 | This is the most simplified version of my code that I have been able to get, which still produces the problem I described above. 18 | 19 | // my code 20 | ... 21 | 22 | Basically, what the code is doing is.... 23 | Changing ... does not work because it gives the following error: 24 | 25 | 26 | Some error 27 | 28 | 29 | #### Describe your research 30 | [The documentation here] mentioned ... but did not provide a clear example of how that is done. 31 | [This Stack Overflow question] describes a similar problem, but mine is different because.... 32 | 33 | #### Ask your question 34 | So my basic question is, how do I...? 35 | 36 | #### Additional context 37 | Add any other context or screenshots about the question here. 38 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | #### Reference to a related issue in the repository 2 | Add a reference to a related issue in the repository. 3 | 4 | #### Add a description 5 | Add a description of the changes proposed in the pull request. 6 | 7 | **Some questions to ask**: 8 | What is this change? 9 | What does it fix? 10 | Is this a bug fix or a feature? Does it break any existing functionality or force me to update to a new version? 11 | How has it been tested? 12 | 13 | #### Mention a member 14 | Add @mentions of the person or team responsible for reviewing proposed changes. 15 | 16 | #### Check the checklist 17 | 18 | - [ ] I have performed a self-review of my own code. 19 | - [ ] I have made corresponding changes to the [documentation](https://github.com/OpenSimulationInterface/osi-documentation) for osi-sensor-model-packaging. 20 | - [ ] My changes generate no new warnings. 21 | - [ ] I have added tests that prove my fix is effective or that my feature works. 22 | - [ ] New and existing unit tests / Github Actions pass locally with my changes. -------------------------------------------------------------------------------- /.github/workflows/antora-generator.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Antora build trigger 3 | 4 | on: 5 | push: 6 | branches: [ master ] 7 | paths-ignore: [ .gitlab/**, .gitmodules ] 8 | pull_request: 9 | branches: [ master ] 10 | 11 | jobs: 12 | trigger_antora: 13 | name: Trigger antora generator 14 | 15 | runs-on: Ubuntu-latest 16 | 17 | env: 18 | MUP_KEY: ${{ secrets.MACHINE_USER_PAT }} 19 | 20 | steps: 21 | - name: Trigger generator 22 | if: ${{ env.MUP_KEY != '' }} 23 | uses: peter-evans/repository-dispatch@v3 24 | with: 25 | token: ${{ secrets.MACHINE_USER_PAT }} 26 | event-type: antora-build-trigger 27 | repository: OpenSimulationInterface/osi-antora-generator 28 | client-payload: '{"src": "${{ github.repository }}", "ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "head_ref": "${{ github.head_ref }}"}' 29 | 30 | -------------------------------------------------------------------------------- /.github/workflows/protobuf.yml: -------------------------------------------------------------------------------- 1 | name: ProtoBuf CI Builds 2 | 3 | env: 4 | PROTOBUF_VERSION: 3.20.1 5 | PROTOBUF_VARIANT: '-all' # Use '-all' prior to 22.0, '' after 6 | ABSEIL_VERSION: 20230802.1 7 | 8 | on: 9 | push: 10 | branches: 11 | - '**' 12 | paths-ignore: [ .github/**, .gitmodules ] 13 | tags-ignore: 14 | - '**' 15 | pull_request: 16 | branches: [ master ] 17 | repository_dispatch: 18 | types: [examples-build] 19 | 20 | # this is a test 21 | 22 | jobs: 23 | build-osmp-examples: 24 | name: Build OSMP examples 25 | 26 | runs-on: ubuntu-22.04 27 | 28 | steps: 29 | - name: Checkout OSI 30 | uses: actions/checkout@v4 31 | with: 32 | submodules: true 33 | 34 | - name: Setup Python 35 | uses: actions/setup-python@v5 36 | with: 37 | python-version: '3.8' 38 | 39 | - name: Cache Dependencies 40 | id: cache-depends 41 | uses: actions/cache@v4 42 | with: 43 | path: protobuf-${{ env.PROTOBUF_VERSION }} 44 | key: ${{ runner.os }}-v2-depends 45 | 46 | - name: Download ProtoBuf ${{ env.PROTOBUF_VERSION }} 47 | if: steps.cache-depends.outputs.cache-hit != 'true' 48 | run: curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v${{env.PROTOBUF_VERSION}}/protobuf${{env.PROTOBUF_VARIANT}}-${{env.PROTOBUF_VERSION}}.tar.gz && tar xzvf protobuf${{env.PROTOBUF_VARIANT}}-${{env.PROTOBUF_VERSION}}.tar.gz 49 | 50 | - name: Download Abseil ${{ env.ABSEIL_VERSION }} 51 | if: steps.cache-depends.outputs.cache-hit != 'true' && env.PROTOBUF_VARIANT == '' 52 | run: curl -OL https://github.com/abseil/abseil-cpp/archive/refs/tags/${{env.ABSEIL_VERSION}}.tar.gz && tar xzvf ${{env.ABSEIL_VERSION}}.tar.gz && rm -rf protobuf-${{env.PROTOBUF_VERSION}}/third_party/abseil-cpp && mv abseil-cpp-${{env.ABSEIL_VERSION}} protobuf-${{env.PROTOBUF_VERSION}}/third_party/abseil-cpp 53 | 54 | - name: Build ProtoBuf ${{ env.PROTOBUF_VERSION }} via autotools 55 | if: steps.cache-depends.outputs.cache-hit != 'true' && env.PROTOBUF_VARIANT == '-all' 56 | working-directory: protobuf-${{ env.PROTOBUF_VERSION }} 57 | run: ./configure DIST_LANG=cpp --prefix=/usr && make 58 | 59 | - name: Build ProtoBuf ${{ env.PROTOBUF_VERSION }} via cmake 60 | if: steps.cache-depends.outputs.cache-hit != 'true' && env.PROTOBUF_VARIANT == '' 61 | working-directory: protobuf-${{ env.PROTOBUF_VERSION }} 62 | run: cmake -DCMAKE_CXX_STANDARD=17 -Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_BUILD_TESTS=OFF . && cmake --build . --config Release -j 4 63 | 64 | - name: Install ProtoBuf ${{ env.PROTOBUF_VERSION }} 65 | working-directory: protobuf-${{ env.PROTOBUF_VERSION }} 66 | run: sudo make install && sudo ldconfig 67 | 68 | - name: Prepare C++ Build 69 | working-directory: examples 70 | run: mkdir build 71 | 72 | - name: Configure C++ Build 73 | working-directory: examples/build 74 | run: cmake ${{ env.PROTOBUF_VARIANT =='' && '-DCMAKE_CXX_STANDARD=17' }} .. 75 | 76 | - name: Build C++ 77 | working-directory: examples/build 78 | run: cmake --build . --config Release -j 4 79 | 80 | - name: Upload build artifacts 81 | uses: actions/upload-artifact@v4 82 | with: 83 | name: Examples 84 | path: examples/build 85 | 86 | update_interface_release: 87 | name: Update OSI release 88 | runs-on: ubuntu-22.04 89 | needs: [build-osmp-examples] 90 | if: ${{ github.event.client_payload }} 91 | steps: 92 | - name: Collect previous artifacts 93 | uses: actions/download-artifact@v4 94 | with: 95 | name: Examples 96 | path: examples/build 97 | - name: Zip artifacts 98 | uses: TheDoctor0/zip-release@0.7.6 99 | with: 100 | filename: Examples.zip 101 | path: examples/build 102 | - name: Upload artifacts to release 103 | uses: svenstaro/upload-release-action@v2 104 | with: 105 | repo_token: ${{ secrets.MACHINE_USER_PAT }} 106 | file: Examples.zip 107 | tag: ${{ github.event.client_payload.tag }} 108 | repo_name: ${{ github.event.client_payload.source_repo }} 109 | -------------------------------------------------------------------------------- /.github/workflows/remote_release.yml: -------------------------------------------------------------------------------- 1 | name: Remote Tagging 2 | 3 | on: 4 | repository_dispatch: 5 | types: [update-tag] 6 | 7 | permissions: 8 | contents: write 9 | repository-projects: write 10 | 11 | jobs: 12 | submodule: 13 | name: Update submodule and create tag 14 | runs-on: Ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository. 20 | 21 | - name: Update submodule 22 | run: | 23 | git submodule init 24 | git submodule update --recursive --remote 25 | cd examples/open-simulation-interface 26 | git checkout ${{ github.event.client_payload.tag }} 27 | cd ../.. 28 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" 29 | git config --local user.name "github-actions[bot]" 30 | git add . 31 | git commit -m "git submodule updated" 32 | continue-on-error: true 33 | 34 | - name: Create Antora tag 35 | run: git tag x-antora-${{ github.event.client_payload.tag }} 36 | 37 | - name: Create release tag 38 | run: | 39 | REPO_TAG="v$(sed -rn 's/VERSION_MAJOR = (.+)/\1/p' VERSION).$(sed -rn 's/VERSION_MINOR = (.+)/\1/p' VERSION).$(sed -rn 's/VERSION_PATCH = (.+)/\1/p' VERSION)${{ github.event.client_payload.suffix }}" 40 | git tag ${REPO_TAG} 41 | 42 | - name: GitHub Push 43 | uses: CasperWA/push-protected@v2.15.0 44 | with: 45 | # Token for the repo. Can be passed in using $\{{ secrets.GITHUB_TOKEN }} 46 | token: ${{ secrets.MACHINE_USER_PAT }} 47 | branch: master 48 | # Determines if --tags is used 49 | tags: true 50 | force: true 51 | unprotect_reviews: true 52 | 53 | - name: Trigger examples creation 54 | uses: peter-evans/repository-dispatch@v2 55 | with: 56 | token: ${{ secrets.MACHINE_USER_PAT }} 57 | event-type: examples-build 58 | client-payload: '{"tag": "${{ github.event.client_payload.tag }}", "source_repo": "${{ github.event.client_payload.source_repo }}"}' 59 | 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | examples/build 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "examples/open-simulation-interface"] 2 | path = examples/open-simulation-interface 3 | url = https://github.com/OpenSimulationInterface/open-simulation-interface.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "MD003": { "style": "atx" }, 4 | "MD007": { "indent": 4 }, 5 | "MD013": false, 6 | "MD030": { "ol_multi": 3, "ul_multi": 3 } 7 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The source code and documentation in this repository is distributed 2 | under the terms of the Mozilla Public License, v. 2.0, attached below, 3 | unless stated otherwise. 4 | 5 | The files fmi2Functions.h, fmi2FunctionTypes.h and fmi2TypesPlatform.h 6 | are distributed under the terms indicated in their header comments. 7 | 8 | Mozilla Public License Version 2.0 9 | ================================== 10 | 11 | 1. Definitions 12 | -------------- 13 | 14 | 1.1. "Contributor" 15 | means each individual or legal entity that creates, contributes to 16 | the creation of, or owns Covered Software. 17 | 18 | 1.2. "Contributor Version" 19 | means the combination of the Contributions of others (if any) used 20 | by a Contributor and that particular Contributor's Contribution. 21 | 22 | 1.3. "Contribution" 23 | means Covered Software of a particular Contributor. 24 | 25 | 1.4. "Covered Software" 26 | means Source Code Form to which the initial Contributor has attached 27 | the notice in Exhibit A, the Executable Form of such Source Code 28 | Form, and Modifications of such Source Code Form, in each case 29 | including portions thereof. 30 | 31 | 1.5. "Incompatible With Secondary Licenses" 32 | means 33 | 34 | (a) that the initial Contributor has attached the notice described 35 | in Exhibit B to the Covered Software; or 36 | 37 | (b) that the Covered Software was made available under the terms of 38 | version 1.1 or earlier of the License, but not also under the 39 | terms of a Secondary License. 40 | 41 | 1.6. "Executable Form" 42 | means any form of the work other than Source Code Form. 43 | 44 | 1.7. "Larger Work" 45 | means a work that combines Covered Software with other material, in 46 | a separate file or files, that is not Covered Software. 47 | 48 | 1.8. "License" 49 | means this document. 50 | 51 | 1.9. "Licensable" 52 | means having the right to grant, to the maximum extent possible, 53 | whether at the time of the initial grant or subsequently, any and 54 | all of the rights conveyed by this License. 55 | 56 | 1.10. "Modifications" 57 | means any of the following: 58 | 59 | (a) any file in Source Code Form that results from an addition to, 60 | deletion from, or modification of the contents of Covered 61 | Software; or 62 | 63 | (b) any new file in Source Code Form that contains any Covered 64 | Software. 65 | 66 | 1.11. "Patent Claims" of a Contributor 67 | means any patent claim(s), including without limitation, method, 68 | process, and apparatus claims, in any patent Licensable by such 69 | Contributor that would be infringed, but for the grant of the 70 | License, by the making, using, selling, offering for sale, having 71 | made, import, or transfer of either its Contributions or its 72 | Contributor Version. 73 | 74 | 1.12. "Secondary License" 75 | means either the GNU General Public License, Version 2.0, the GNU 76 | Lesser General Public License, Version 2.1, the GNU Affero General 77 | Public License, Version 3.0, or any later versions of those 78 | licenses. 79 | 80 | 1.13. "Source Code Form" 81 | means the form of the work preferred for making modifications. 82 | 83 | 1.14. "You" (or "Your") 84 | means an individual or a legal entity exercising rights under this 85 | License. For legal entities, "You" includes any entity that 86 | controls, is controlled by, or is under common control with You. For 87 | purposes of this definition, "control" means (a) the power, direct 88 | or indirect, to cause the direction or management of such entity, 89 | whether by contract or otherwise, or (b) ownership of more than 90 | fifty percent (50%) of the outstanding shares or beneficial 91 | ownership of such entity. 92 | 93 | 2. License Grants and Conditions 94 | -------------------------------- 95 | 96 | 2.1. Grants 97 | 98 | Each Contributor hereby grants You a world-wide, royalty-free, 99 | non-exclusive license: 100 | 101 | (a) under intellectual property rights (other than patent or trademark) 102 | Licensable by such Contributor to use, reproduce, make available, 103 | modify, display, perform, distribute, and otherwise exploit its 104 | Contributions, either on an unmodified basis, with Modifications, or 105 | as part of a Larger Work; and 106 | 107 | (b) under Patent Claims of such Contributor to make, use, sell, offer 108 | for sale, have made, import, and otherwise transfer either its 109 | Contributions or its Contributor Version. 110 | 111 | 2.2. Effective Date 112 | 113 | The licenses granted in Section 2.1 with respect to any Contribution 114 | become effective for each Contribution on the date the Contributor first 115 | distributes such Contribution. 116 | 117 | 2.3. Limitations on Grant Scope 118 | 119 | The licenses granted in this Section 2 are the only rights granted under 120 | this License. No additional rights or licenses will be implied from the 121 | distribution or licensing of Covered Software under this License. 122 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 123 | Contributor: 124 | 125 | (a) for any code that a Contributor has removed from Covered Software; 126 | or 127 | 128 | (b) for infringements caused by: (i) Your and any other third party's 129 | modifications of Covered Software, or (ii) the combination of its 130 | Contributions with other software (except as part of its Contributor 131 | Version); or 132 | 133 | (c) under Patent Claims infringed by Covered Software in the absence of 134 | its Contributions. 135 | 136 | This License does not grant any rights in the trademarks, service marks, 137 | or logos of any Contributor (except as may be necessary to comply with 138 | the notice requirements in Section 3.4). 139 | 140 | 2.4. Subsequent Licenses 141 | 142 | No Contributor makes additional grants as a result of Your choice to 143 | distribute the Covered Software under a subsequent version of this 144 | License (see Section 10.2) or under the terms of a Secondary License (if 145 | permitted under the terms of Section 3.3). 146 | 147 | 2.5. Representation 148 | 149 | Each Contributor represents that the Contributor believes its 150 | Contributions are its original creation(s) or it has sufficient rights 151 | to grant the rights to its Contributions conveyed by this License. 152 | 153 | 2.6. Fair Use 154 | 155 | This License is not intended to limit any rights You have under 156 | applicable copyright doctrines of fair use, fair dealing, or other 157 | equivalents. 158 | 159 | 2.7. Conditions 160 | 161 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 162 | in Section 2.1. 163 | 164 | 3. Responsibilities 165 | ------------------- 166 | 167 | 3.1. Distribution of Source Form 168 | 169 | All distribution of Covered Software in Source Code Form, including any 170 | Modifications that You create or to which You contribute, must be under 171 | the terms of this License. You must inform recipients that the Source 172 | Code Form of the Covered Software is governed by the terms of this 173 | License, and how they can obtain a copy of this License. You may not 174 | attempt to alter or restrict the recipients' rights in the Source Code 175 | Form. 176 | 177 | 3.2. Distribution of Executable Form 178 | 179 | If You distribute Covered Software in Executable Form then: 180 | 181 | (a) such Covered Software must also be made available in Source Code 182 | Form, as described in Section 3.1, and You must inform recipients of 183 | the Executable Form how they can obtain a copy of such Source Code 184 | Form by reasonable means in a timely manner, at a charge no more 185 | than the cost of distribution to the recipient; and 186 | 187 | (b) You may distribute such Executable Form under the terms of this 188 | License, or sublicense it under different terms, provided that the 189 | license for the Executable Form does not attempt to limit or alter 190 | the recipients' rights in the Source Code Form under this License. 191 | 192 | 3.3. Distribution of a Larger Work 193 | 194 | You may create and distribute a Larger Work under terms of Your choice, 195 | provided that You also comply with the requirements of this License for 196 | the Covered Software. If the Larger Work is a combination of Covered 197 | Software with a work governed by one or more Secondary Licenses, and the 198 | Covered Software is not Incompatible With Secondary Licenses, this 199 | License permits You to additionally distribute such Covered Software 200 | under the terms of such Secondary License(s), so that the recipient of 201 | the Larger Work may, at their option, further distribute the Covered 202 | Software under the terms of either this License or such Secondary 203 | License(s). 204 | 205 | 3.4. Notices 206 | 207 | You may not remove or alter the substance of any license notices 208 | (including copyright notices, patent notices, disclaimers of warranty, 209 | or limitations of liability) contained within the Source Code Form of 210 | the Covered Software, except that You may alter any license notices to 211 | the extent required to remedy known factual inaccuracies. 212 | 213 | 3.5. Application of Additional Terms 214 | 215 | You may choose to offer, and to charge a fee for, warranty, support, 216 | indemnity or liability obligations to one or more recipients of Covered 217 | Software. However, You may do so only on Your own behalf, and not on 218 | behalf of any Contributor. You must make it absolutely clear that any 219 | such warranty, support, indemnity, or liability obligation is offered by 220 | You alone, and You hereby agree to indemnify every Contributor for any 221 | liability incurred by such Contributor as a result of warranty, support, 222 | indemnity or liability terms You offer. You may include additional 223 | disclaimers of warranty and limitations of liability specific to any 224 | jurisdiction. 225 | 226 | 4. Inability to Comply Due to Statute or Regulation 227 | --------------------------------------------------- 228 | 229 | If it is impossible for You to comply with any of the terms of this 230 | License with respect to some or all of the Covered Software due to 231 | statute, judicial order, or regulation then You must: (a) comply with 232 | the terms of this License to the maximum extent possible; and (b) 233 | describe the limitations and the code they affect. Such description must 234 | be placed in a text file included with all distributions of the Covered 235 | Software under this License. Except to the extent prohibited by statute 236 | or regulation, such description must be sufficiently detailed for a 237 | recipient of ordinary skill to be able to understand it. 238 | 239 | 5. Termination 240 | -------------- 241 | 242 | 5.1. The rights granted under this License will terminate automatically 243 | if You fail to comply with any of its terms. However, if You become 244 | compliant, then the rights granted under this License from a particular 245 | Contributor are reinstated (a) provisionally, unless and until such 246 | Contributor explicitly and finally terminates Your grants, and (b) on an 247 | ongoing basis, if such Contributor fails to notify You of the 248 | non-compliance by some reasonable means prior to 60 days after You have 249 | come back into compliance. Moreover, Your grants from a particular 250 | Contributor are reinstated on an ongoing basis if such Contributor 251 | notifies You of the non-compliance by some reasonable means, this is the 252 | first time You have received notice of non-compliance with this License 253 | from such Contributor, and You become compliant prior to 30 days after 254 | Your receipt of the notice. 255 | 256 | 5.2. If You initiate litigation against any entity by asserting a patent 257 | infringement claim (excluding declaratory judgment actions, 258 | counter-claims, and cross-claims) alleging that a Contributor Version 259 | directly or indirectly infringes any patent, then the rights granted to 260 | You by any and all Contributors for the Covered Software under Section 261 | 2.1 of this License shall terminate. 262 | 263 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 264 | end user license agreements (excluding distributors and resellers) which 265 | have been validly granted by You or Your distributors under this License 266 | prior to termination shall survive termination. 267 | 268 | ************************************************************************ 269 | * * 270 | * 6. Disclaimer of Warranty * 271 | * ------------------------- * 272 | * * 273 | * Covered Software is provided under this License on an "as is" * 274 | * basis, without warranty of any kind, either expressed, implied, or * 275 | * statutory, including, without limitation, warranties that the * 276 | * Covered Software is free of defects, merchantable, fit for a * 277 | * particular purpose or non-infringing. The entire risk as to the * 278 | * quality and performance of the Covered Software is with You. * 279 | * Should any Covered Software prove defective in any respect, You * 280 | * (not any Contributor) assume the cost of any necessary servicing, * 281 | * repair, or correction. This disclaimer of warranty constitutes an * 282 | * essential part of this License. No use of any Covered Software is * 283 | * authorized under this License except under this disclaimer. * 284 | * * 285 | ************************************************************************ 286 | 287 | ************************************************************************ 288 | * * 289 | * 7. Limitation of Liability * 290 | * -------------------------- * 291 | * * 292 | * Under no circumstances and under no legal theory, whether tort * 293 | * (including negligence), contract, or otherwise, shall any * 294 | * Contributor, or anyone who distributes Covered Software as * 295 | * permitted above, be liable to You for any direct, indirect, * 296 | * special, incidental, or consequential damages of any character * 297 | * including, without limitation, damages for lost profits, loss of * 298 | * goodwill, work stoppage, computer failure or malfunction, or any * 299 | * and all other commercial damages or losses, even if such party * 300 | * shall have been informed of the possibility of such damages. This * 301 | * limitation of liability shall not apply to liability for death or * 302 | * personal injury resulting from such party's negligence to the * 303 | * extent applicable law prohibits such limitation. Some * 304 | * jurisdictions do not allow the exclusion or limitation of * 305 | * incidental or consequential damages, so this exclusion and * 306 | * limitation may not apply to You. * 307 | * * 308 | ************************************************************************ 309 | 310 | 8. Litigation 311 | ------------- 312 | 313 | Any litigation relating to this License may be brought only in the 314 | courts of a jurisdiction where the defendant maintains its principal 315 | place of business and such litigation shall be governed by laws of that 316 | jurisdiction, without reference to its conflict-of-law provisions. 317 | Nothing in this Section shall prevent a party's ability to bring 318 | cross-claims or counter-claims. 319 | 320 | 9. Miscellaneous 321 | ---------------- 322 | 323 | This License represents the complete agreement concerning the subject 324 | matter hereof. If any provision of this License is held to be 325 | unenforceable, such provision shall be reformed only to the extent 326 | necessary to make it enforceable. Any law or regulation which provides 327 | that the language of a contract shall be construed against the drafter 328 | shall not be used to construe this License against a Contributor. 329 | 330 | 10. Versions of the License 331 | --------------------------- 332 | 333 | 10.1. New Versions 334 | 335 | Mozilla Foundation is the license steward. Except as provided in Section 336 | 10.3, no one other than the license steward has the right to modify or 337 | publish new versions of this License. Each version will be given a 338 | distinguishing version number. 339 | 340 | 10.2. Effect of New Versions 341 | 342 | You may distribute the Covered Software under the terms of the version 343 | of the License under which You originally received the Covered Software, 344 | or under the terms of any subsequent version published by the license 345 | steward. 346 | 347 | 10.3. Modified Versions 348 | 349 | If you create software not governed by this License, and you want to 350 | create a new license for such software, you may create and use a 351 | modified version of this License if you rename the license and remove 352 | any references to the name of the license steward (except to note that 353 | such modified license differs from this License). 354 | 355 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 356 | Licenses 357 | 358 | If You choose to distribute Source Code Form that is Incompatible With 359 | Secondary Licenses under the terms of this version of the License, the 360 | notice described in Exhibit B of this License must be attached. 361 | 362 | Exhibit A - Source Code Form License Notice 363 | ------------------------------------------- 364 | 365 | This Source Code Form is subject to the terms of the Mozilla Public 366 | License, v. 2.0. If a copy of the MPL was not distributed with this 367 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 368 | 369 | If it is not possible or desirable to put the notice in a particular 370 | file, then You may include the notice in a location (such as a LICENSE 371 | file in a relevant directory) where a recipient would be likely to look 372 | for such a notice. 373 | 374 | You may add additional accurate notices of copyright ownership. 375 | 376 | Exhibit B - "Incompatible With Secondary Licenses" Notice 377 | --------------------------------------------------------- 378 | 379 | This Source Code Form is "Incompatible With Secondary Licenses", as 380 | defined by the Mozilla Public License, v. 2.0. 381 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSI Sensor Model Packaging 2 | 3 | [![ProtoBuf CI Builds](https://github.com/OpenSimulationInterface/osi-sensor-model-packaging/actions/workflows/protobuf.yml/badge.svg)](https://github.com/OpenSimulationInterface/osi-sensor-model-packaging/actions/workflows/protobuf.yml) 4 | 5 | OSI Sensor Model Packaging specifies ways in which models (like e.g. environmental effect models, sensor models and logical models) using the [Open Simulation Interface (OSI)][] are to be packaged for their use in simulation environments using FMI 2.0. 6 | The specification can be found in the [doc/osi-sensor-model-packaging_spec.adoc](doc/osi-sensor-model-packaging_spec.adoc) document in this repository. 7 | 8 | For more detailed information see the [official documentation](https://opensimulationinterface.github.io/osi-antora-generator/asamosi/latest/sensor-model/misc/introduction.html). 9 | 10 | [Open Simulation Interface (OSI)]: https://github.com/OpenSimulationInterface/open-simulation-interface 11 | 12 | ## Usage 13 | The examples in the directory [`examples`](https://github.com/OpenSimulationInterface/osi-sensor-model-packaging/tree/master/examples) of this repository can be built using CMake. They require that the open-simulation-interface submodule of the repository is populated. 14 | 15 | The [`OSMPDummySource`](https://github.com/OpenSimulationInterface/osi-sensor-model-packaging/tree/master/examples/OSMPDummySource) example can be used as a simplistic source of SensorView (including GroundTruth) data, that can be connected to the input of an OSMPDummySensor model, for simple testing and demonstration purposes. 16 | 17 | The [`OSMPCNetworkProxy`](https://github.com/OpenSimulationInterface/osi-sensor-model-packaging/tree/master/examples/OSMPCNetworkProxy) example demonstrates a simple C network proxy that can send and receive OSI data via TCP sockets. 18 | 19 | The [`OSMPDummySensor`](https://github.com/OpenSimulationInterface/osi-sensor-model-packaging/tree/master/examples/OSMPDummySensor) example can be used as a simple dummy sensor model, demonstrating the use of OSI for sensor models consuming SensorView data and generating SensorData output. 20 | 21 | ## Installation 22 | ##### Dependencies 23 | 24 | Install `cmake` 3.10.2: 25 | ```bash 26 | $ sudo apt-get install cmake 27 | ``` 28 | Install `protobuf` 3.0.0: 29 | ```bash 30 | $ sudo apt-get install libprotobuf-dev protobuf-compiler 31 | ``` 32 | 33 | ##### Build examples 34 | ```bash 35 | $ git clone https://github.com/OpenSimulationInterface/osi-sensor-model-packaging.git 36 | $ cd osi-sensor-model-packaging 37 | $ git submodule update --init 38 | $ cd examples 39 | $ mkdir -p build 40 | $ cd build 41 | $ cmake .. 42 | $ cmake --build . 43 | ``` 44 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | VERSION_MAJOR = 1 2 | VERSION_MINOR = 5 3 | VERSION_PATCH = 0 4 | -------------------------------------------------------------------------------- /doc/_config.adoc: -------------------------------------------------------------------------------- 1 | 2 | // This file contains AsciiDoc attributes that shall be used in every AsciiDoc file. 3 | // NOTE: Its content is only applied for Asciidoctor! 4 | // If the same attribute is defined in the antora.yml (without @), the antora.yml definition takes precedence for Antora. 5 | 6 | ifndef::root-path[:root-path: ./] 7 | 8 | :partials-path: {root-path}../_additional_content 9 | :appendix-caption: Annex 10 | 11 | // ifndef::use-antora-rules,include-only-once[] 12 | ifndef::include-only-once[] 13 | :GLO_VAR_STA_ASAM_OpenCRG: ASAM OpenCRG 14 | :glo_var_sta_asam_opencrg: {GLO_VAR_STA_ASAM_OpenCRG} 15 | :GLO_VAR_STA_ASAM_OpenDRIVE: ASAM OpenDRIVE 16 | :GLO_VAR_STA_ASAM_OpenLABEL: ASAM OpenLABEL 17 | :GLO_VAR_STA_ASAM_OpenODD: ASAM OpenODD 18 | :GLO_VAR_STA_ASAM_OSI: ASAM OSI® 19 | :GLO_VAR_STA_ASAM_OpenSCENARIO: ASAM OpenSCENARIO 20 | :GLO_VAR_STA_ASAM_OpenXOntology: ASAM OpenXOntology 21 | :GLO_VAR_STA_BSI_PAS_1883: BSI PAS 1883 22 | :revnumber: --localbuild-- 23 | :revdate: {docdate} 24 | :bibtex-file: ./content/general_docs/bibliography.bib 25 | // Replace PLACEHOLDER with the name of your standard, e.g. OpenDRIVE 26 | :THIS_STANDARD: {GLO_VAR_STA_ASAM_OSI} 27 | :asam-terminology: https://code.asam.net/common/asam-terminology/-/raw/main/terms_and_definitions_opendrive.adoc 28 | :imagesdir: {root-path}/images 29 | :include-only-once: true 30 | :topicdir: topics 31 | :reusedir: reuse 32 | :toclevels: 3 33 | :xrefstyle: full 34 | :images_open_simulation_interface: ./open-simulation-interface/doc/images 35 | // :images_osi-sensor-model-packaging: ./osi-sensor-model-packaging/doc/images 36 | :doc_open_simulation_interface: ../../open-simulation-interface/doc/ 37 | :doc_osi-sensor-model-packaging: ../../osi-sensor-model-packaging/doc/ 38 | // Since a document spanning multiple repos is rendered here, the pathing regarding images is a bit involved. 39 | // We create a variable for every repo that is included. It point to the repo in question. 40 | // If the subrepo is rendered seperatly, then the variable is set to just "./images" with ifdef. 41 | // Please note that this variable has to used in all image includes. Includes here have to use "image::./images..." 42 | // :images_osi_sensor_model_packaging: ./osi-sensor-model-packaging/doc/images // example 43 | :imagesoutdir: ./images/generated_images 44 | :page-feedbackurl: https://github.com/OpenSimulationInterface/osi-sensor-model-packaging/issues/new 45 | 46 | 47 | endif::[] 48 | 49 | 50 | ifdef::env-gitlab[] 51 | :relfilesuffix: .adoc 52 | endif::[] 53 | -------------------------------------------------------------------------------- /doc/misc/example.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Example: Simple sensor model FMU 6 | 7 | The following example shows the content of a `modelDescription.xml` file that satisfies OSMP requirements. 8 | The example describes a sensor model FMU with one input, one output, and no additional features: 9 | 10 | [source,xml,linenums] 11 | ---- 12 | 13 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ---- 72 | -------------------------------------------------------------------------------- /doc/misc/introduction.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Introduction 6 | 7 | _OSI Sensor Model Packaging_ (OSMP) is a package layer specification for the _Open Simulation Interface_ (OSI). 8 | It specifies how models that use OSI are packaged as _Functional Mock-up Units_ (FMUs) in accordance with the _Functional Mock-up Interface 2.0_ (FMI 2.0). 9 | 10 | This is version 1.5.0 of this specification. The version number is to be 11 | interpreted according to the https://semver.org/spec/v2.0.0.html[_Semantic Versioning Specification 2.0.0_]. 12 | -------------------------------------------------------------------------------- /doc/osi-sensor-model-packaging_spec.adoc: -------------------------------------------------------------------------------- 1 | :root-path: ./ 2 | include::{root-path}_config.adoc[] 3 | = OSI Sensor Model Packaging 4 | 5 | :antora_mapping: title;numbered 6 | ifndef::use-antora-rules[] 7 | include::./misc/introduction.adoc[leveloffset=+1] 8 | 9 | == OSMP specification 10 | 11 | include::./spec/model_types.adoc[leveloffset=+2] 12 | 13 | include::./spec/basic_conventions.adoc[leveloffset=+2] 14 | 15 | include::./spec/binary_variables.adoc[leveloffset=+2] 16 | 17 | include::./spec/sensor_view_inputs.adoc[leveloffset=+2] 18 | 19 | include::./spec/sensor_view_input_configuration.adoc[leveloffset=+2] 20 | 21 | include::./spec/sensor_view_outputs.adoc[leveloffset=+2] 22 | 23 | include::./spec/sensor_data_inputs.adoc[leveloffset=+2] 24 | 25 | include::./spec/sensor_data_outputs.adoc[leveloffset=+2] 26 | 27 | include::./spec/ground_truth_init_parameters.adoc[leveloffset=+2] 28 | 29 | include::./spec/traffic_command_inputs.adoc[leveloffset=+2] 30 | 31 | include::./spec/traffic_command_update_outputs.adoc[leveloffset=+2] 32 | 33 | include::./spec/traffic_update_outputs.adoc[leveloffset=+2] 34 | 35 | include::./spec/streaming_update_inputs.adoc[leveloffset=+2] 36 | 37 | == Examples 38 | 39 | include::./setup/build_install_example.adoc[leveloffset=+2] 40 | 41 | include::./misc/example.adoc[leveloffset=+2] 42 | 43 | endif::[] 44 | :!antora-mapping: 45 | -------------------------------------------------------------------------------- /doc/setup/build_install_example.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Building and installing examples 6 | 7 | OSMP includes three examples located in `_osmp_/examples`: 8 | 9 | `OSMPDummySensor/`:: 10 | Can be used as a simple dummy sensor model, demonstrating the use of OSI for sensor models consuming sensor view data and generating sensor data output. 11 | 12 | `OSMPDummySource/`:: 13 | Can be used as a simple source of sensor view data and ground-truth data. 14 | It can be connected to the input of an `OSMPDummySensor` model, for simple testing and demonstration purposes. 15 | 16 | `OSMPCNetworkProxy/`:: 17 | Demonstrates a simple C network proxy that can send and receive OSI data via TCP sockets. 18 | 19 | **Prerequisites** 20 | 21 | * You have installed all prerequisites according to the way of linking of your choice, as described in <>. 22 | 23 | **Steps** 24 | 25 | . Clone the OSMP repository. 26 | + 27 | ---- 28 | git clone https://github.com/OpenSimulationInterface/osi-sensor-model-packaging.git 29 | ---- 30 | + 31 | . Switch to the OSMP repository. 32 | + 33 | ---- 34 | cd osi-sensor-model-packaging 35 | ---- 36 | + 37 | . Update and initialize the OSI submodule. 38 | + 39 | ---- 40 | git submodule update --init 41 | ---- 42 | + 43 | . Run cmake and build 44 | .. If you followed the protobuf installation instructions for Windows using vcpkg, you can use the built protobuf libraries to automatically build the examples by specifying the triplet and toolchain file from VCPKG on the cmake configuration command-line: 45 | + 46 | ---- 47 | cd examples 48 | mkdir build 49 | cd build 50 | cmake .. -DVCPKG_TARGET_TRIPLET=x64-windows-static-md -DCMAKE_TOOLCHAIN_FILE=../../../vcpkg/scripts/buildsystems/vcpkg.cmake 51 | cmake –-build . 52 | ---- 53 | + 54 | 55 | The CMAKE_TOOLCHAIN_FILE must point to your vcpkg directory, which in this example was parallel to the osi-sensor-model-packaging directory. 56 | 57 | .. If you did not install and build protobuf using vcpkg, use: 58 | + 59 | ---- 60 | cd examples 61 | mkdir build 62 | cd build 63 | cmake .. 64 | cmake --build . 65 | ---- 66 | + -------------------------------------------------------------------------------- /doc/spec/basic_conventions.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Basic conventions 6 | 7 | The model shall be packaged as a valid FMU for co-simulation, as specified in the FMI 2.0 standard cite:[fmi2.0]. 8 | Unless otherwise noted, all specifications in the FMI 2.0 cite:[fmi2.0] standard apply as-is. 9 | 10 | The following annotation shall be placed into the `` element of the `modelDescription.xml` to mark the FMU as being conformant to this version of the specification: 11 | 12 | [source,xml] 13 | ---- 14 | 15 | ---- 16 | 17 | The `@osi-version` attribute should contain the major, minor, and patch version number of the OSI specification that this model was compiled against. 18 | Indicating the OSI version ensures that the importing environment can determine which OSI version to use prior to communicating with the FMU. 19 | 20 | If OSMP is used without OSI data being transported across binary variables, `@osi-version` should not be specified. 21 | 22 | The variable naming convention of the FMU shall be structured. 23 | 24 | The default experiment step size should be defined. 25 | It should indicate the actual model refresh rate for the input side. 26 | A simulator can call the FMU `fmi2DoStep` routine at this implied rate. 27 | If the step size is not supplied, the model communication rate is determined from any input configuration data the model provides, or it must be configured manually. 28 | 29 | The model may have inputs, outputs, and parameters that are not specified by OSMP if the model can be run correctly with all of those variables left unconnected and at their default values. 30 | 31 | == FMI 3.0 32 | 33 | Alternatively a model can be packaged as a valid FMU for co-simulation as specified in the FMI 3.0 standard cite:[fmi3.0]. 34 | In this case, unless otherwise noted, all specifications in the FMI 3.0 cite:[fmi3.0] standard apply as-is. 35 | 36 | The rules above for FMI 2.0 apply, with the provision that the annotation shall be placed as an `` element into the `` element of the `modelDescription.xml`: 37 | 38 | [source,xml] 39 | ---- 40 | 41 | ---- 42 | -------------------------------------------------------------------------------- /doc/spec/binary_variables.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Binary variables 6 | 7 | FMI 2.0 cite:[fmi2.0] does not directly support the efficient exchange of arbitrary binary data between FMUs. 8 | OSMP therefore introduces the concept of notional binary variables that are mapped to actual integer variables for use with FMI 2.0 cite:[fmi2.0]. 9 | 10 | For FMI 3.0 cite:[fmi3.0] and above these notional binary variables can be directly mapped into actual binary variables as specified below. 11 | 12 | A notional binary variable named `` is defined using the following conventions: 13 | 14 | The name of the notional binary variable given by `` shall be a valid structured name according to FMI 2.0 cite:[fmi2.0] (or FMI 3.0 cite:[fmi3.0] for 3.0 FMUs). 15 | 16 | The FMU shall not contain any other variable that is named ``. 17 | This restriction ensures that there is no conflict between notional binary variables and actual variables. 18 | 19 | For FMI 2.0, for each notional binary variable, three actual FMU integer variables shall be defined: 20 | 21 | `.base.lo`:: 22 | Lower, meaning the least significant, 32-bit address part of the binary data buffer to be passed into or out of the model, cast into a signed 32-bit integer without changing the bit values. 23 | `.base.hi`:: 24 | Higher, meaning the most significant, 32-bit address part of the binary data buffer to be passed into or out of the model, cast into a signed 32-bit integer without changing the bit values. 25 | Note that this variable is only used for 64-bit platforms. 26 | For 32-bit platforms, it shall still be present but will always be 0 to support FMUs with 32-bit and 64-bit implementations. 27 | `.size`:: 28 | Size of the binary data buffer to be passed into or out of the model as a signed 32-bit integer. 29 | This restricts the maximum size of binary data buffers being passed around to a size less than 2 GB. 30 | 31 | The three actual variables shall have matching causality and variability, which will be the causality and variability of the notional binary variable. 32 | 33 | The variables shall have a start value of 0, indicating that no valid binary data buffer is available. 34 | The variables may have a different or no start value if the combination of causality and variability precludes this, for example, for `@variability = fixed` or `@variability = tunable` and `@causality = calculatedParameter`. 35 | 36 | Model FMUs shall interpret values of 0 for the merged base address or the size to indicate that no valid binary data buffer is available. 37 | Models FMUs shall handle this case safely. 38 | 39 | The three actual variables shall contain an annotation of the following form in the `` child element of their `` element of the `modelDescription.xml`: 40 | 41 | [source,xml] 42 | ---- 43 | 44 | ---- 45 | 46 | `` is the prefix as defined above, and `@role` is either `base.lo`, `base.hi`, or `size`, depending on the variable. 47 | 48 | It is an error if there is not exactly one variable of each role for the same name. 49 | 50 | The MIME type given in `@mime-type` shall be a valid MIME type specification. 51 | 52 | It is an error if the MIME types specified in the annotations for one notional binary variable differ. 53 | 54 | In the case of OSI-specified data, the MIME type shall have the following form to indicate that the binary content is conformant to the given OSI version and contains a message of the given type: 55 | 56 | [source,xml] 57 | ---- 58 | application/x-open-simulation-interface; type=; version=x.y.z 59 | ---- 60 | 61 | `` shall be the name of an OSI top-level message, excluding the `osi3::` prefix. 62 | 63 | The version parameter of the MIME type `application/x-open-simulation-interface` will default to the version specified in the `@osi-version` attribute as part of the top-level `` annotation. 64 | It is an error if a version number is specified neither as part of the MIME type nor using the `@osi-version` attribute. 65 | 66 | The guaranteed lifetime of the binary data buffer pointer transported through the actual variables is defined for each kind of variable, as specified in the following sections. 67 | 68 | Generally the lifetime for inputs is from the time they are set to the time the corresponding co-simulation step calculation finishes. 69 | For outputs the lifetime is extended from the point the output is provided at the end of a co-simulation step until the end of the next co-simulation step. 70 | 71 | This convention allows the use of FMUs in simulation engines that have no special support for the protocol buffer pointers: 72 | The simulation engine can rely on the provided buffer to remain valid from the moment it is passed out of a model until the end of the next co-simulation calculation cycle. 73 | Thus, the simulation engine does not need to copy the contents in that case, corresponding to zero-copy output for the simulation engine at the cost of double buffering for the model providing the output data. 74 | It is possible to daisy-chain FMUs with protocol buffer inputs and outputs in a normal simulation engine supporting FMI, and get valid results. 75 | 76 | == FMI 3.0 77 | 78 | For FMI 3.0, each notional binary variable is mapped to an actual binary variable with the name `` and the causality and variability of the notional binary variable. 79 | 80 | The variable shall have a start value of length 0 (i.e. the empty binary), indicating that no valid binary data is available. 81 | The variable may have a different or no start value if the combination of causality and variability precludes this, for example, for `@variability = fixed` or `@variability = tunable` and `@causality = calculatedParameter`. 82 | 83 | Model FMUs shall interpret empty binary values to indicate that no valid binary data is available. 84 | Model FMUs shall handle this case safely. 85 | 86 | The actual binary variable shall contain an annotation of the following form in the `` child element of their `` element of the `modelDescription.xml`: 87 | 88 | [source,xml] 89 | ---- 90 | 91 | ---- 92 | 93 | `` is the prefix as defined above. 94 | 95 | It is an error if there is not exactly one variable for the same name. 96 | 97 | The MIME type given in `@mime-type` shall be a valid MIME type specification. 98 | It shall be identical to the MIME type specification given in the `@mimeType` attribute of the binary variable element. 99 | 100 | In the case of OSI-specified data, the MIME type shall have the following form to indicate that the binary content is conformant to the given OSI version and contains a message of the given type: 101 | 102 | [source,xml] 103 | ---- 104 | application/x-open-simulation-interface; type=; version=x.y.z 105 | ---- 106 | 107 | `` shall be the name of an OSI top-level message, excluding the `osi3::` prefix. 108 | 109 | The version parameter of the MIME type `application/x-open-simulation-interface` will default to the version specified in the `@osi-version` attribute as part of the top-level `` annotation. 110 | It is an error if a version number is specified neither as part of the MIME type nor using the `@osi-version` attribute. 111 | 112 | The guaranteed lifetime of the binary data transported through the actual variable is defined in the FMI 3.0 standard, **regardless** of any specifications in the following sections. 113 | 114 | Alternatively, for specific compatibility or other reasons, it is permissible, though not recommended, for an FMI 3.0 FMU to follow the FMI 2.0 approach as specified above. 115 | -------------------------------------------------------------------------------- /doc/spec/ground_truth_init_parameters.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Ground truth initialization parameters 6 | 7 | All models can optionally consume `osi3::GroundTruth` via an initialization parameter called `OSMPGroundTruthInit`. 8 | Its purpose is to provide the model with information in OSI format that does not change throughout the simulation, i.e. is considered static. 9 | This can encompass, for example, the road network or referenced 3D models. 10 | 11 | `OSMPGroundTruthInit` contains only data encountered by the model that does not change during a simulation run. 12 | All data provided in this message can be assumed by the receiver to be static during the simulation run. 13 | 14 | If the model is instantiated multiple times, all instantiations should receive the exact same content. 15 | This allows a model to do expensive map calculations or loading 3D assets only once during initialization, and to share the calculated data between multiple instantiations. 16 | 17 | **Prefix** 18 | 19 | Ground truth initialization parameters shall be named with the following prefix: 20 | 21 | [source,protobuf] 22 | ---- 23 | OSMPGroundTruthInit 24 | ---- 25 | 26 | **Rules** 27 | 28 | * If a model needs ground truth during initialization, it shall have a parameter named `OSMPGroundTruthInit`. 29 | * `OSMPGroundTruthInit` shall be defined as a notional discrete binary input parameter variable, with `@causality="parameter"`, `@variability="fixed"` and `@initial="exact"`. 30 | * The MIME type of the variable shall specify the `type=GroundTruth` as part of the MIME type parameters. 31 | * `OSMPGroundTruthInit` shall be encoded as `osi3::GroundTruth`. 32 | * `OSMPGroundTruthInit` shall contain only data encountered by the model that does not change during a simulation run. 33 | * The IDs of objects in `OSMPGroundTruthInit` shall be identical to the IDs of the same objects contained in later `OSMPSensorViewIn` or other input data. 34 | * If the model is instantiated multiple times, then all instantiations should receive the exact same content stored in the `OSMPGroundTruthInit` parameter. 35 | * The guaranteed lifetime of the ground-truth protocol-buffer pointer provided as input to the FMU shall be from the time of the call to `fmi2SetInteger` that provides those values until the end of the following `fmi2ExitInitializationMode` call. 36 | -------------------------------------------------------------------------------- /doc/spec/model_types.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Model types 6 | 7 | The current specification supports packaging the following model types as _Functional Mock-up Units_ (FMUs). 8 | 9 | Environmental effect model:: 10 | This model type can be used to model environmental effects or the physical parts of sensors. 11 | It consumes `osi3::SensorView` as input and produces `osi3::SensorView` as output. 12 | 13 | Sensor models:: 14 | This model type is used to model the perception function of sensors. 15 | It consumes `osi3::SensorView` as input and produces `osi3::SensorData` as output. 16 | 17 | Logical models:: 18 | This model type is used to model the further processing of sensor output, for example, sensor fusion. 19 | It consumes `osi3::SensorData` as input and produces `osi3::SensorData` as output. 20 | 21 | Traffic participant models:: 22 | This model type is used to model whole traffic participants, such as vehicles or pedestrians. 23 | Traffic participant models may internally use environmental effect models, sensor models, or logical models as part of a modeled autonomous vehicle. 24 | They may also be used to implement surrounding traffic in simplified ways. 25 | Traffic participant models consume `osi3::SensorView` as input and produce `osi3::TrafficUpdate` as output. 26 | They may additionally consume `osi3::TrafficCommand` as input to allow control by a scenario engine or other coordinating function. 27 | They may additionally produce `osi3::TrafficCommandUpdate` as output to allow status responses to such control messages. 28 | 29 | Streaming update consumer models:: 30 | This model type receives a streaming update input for further processing. 31 | Examples of this model type can be visualization, evaluation, or logging modules. 32 | Streaming update consumer models consume `osi3::StreamingUpdate` as input; if they produce any output, it is currently not specified as part of this standard. 33 | 34 | All models may also consume a global `osi3::GroundTruth` parameter during initialization. 35 | 36 | Complex models may combine various aspects of the above model types. 37 | Manual intervention is needed to configure and set up these FMUs. 38 | 39 | In implementations that support the use of the _System Structure and Parameterization_ (SSP) standard cite:[ssp1.0], a model can alternatively be packaged as a system consisting of multiple FMUs, if it presents the same interface at system level as this specification mandates for the overall model of the given type. 40 | -------------------------------------------------------------------------------- /doc/spec/sensor_data_inputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Sensor data inputs 6 | 7 | **Prefix** 8 | 9 | Sensor data inputs shall be named with the following prefix: 10 | 11 | [source,protobuf] 12 | ---- 13 | OSMPSensorDataIn 14 | ---- 15 | 16 | **Rules** 17 | 18 | * If only one sensor data input is configured, the prefix shall only be `OSMPSensorDataIn`. 19 | * If more than one sensor data input is configured, the prefix shall be extended by an array index, for example, `OSMPSensorDataIn[1]` and `OSMPSensorDataIn[2]`. 20 | * Array indices shall start at 1 and shall be consecutive. 21 | * Each sensor data input shall be defined as a notional discrete binary input variable with `@causality="input"` and `@variability="discrete"`. 22 | * The MIME type of the variable shall specify the `type="SensorData"` as part of the MIME type parameters. 23 | * Sensor data shall be encoded as `osi3::SensorData`. 24 | * The guaranteed lifetime of the sensor data protocol-buffer pointer provided as input to the FMU shall be from the time of the call to `fmi2SetInteger` that provides those values until the end of the following `fmi2DoStep` call. -------------------------------------------------------------------------------- /doc/spec/sensor_data_outputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Sensor data outputs 6 | 7 | **Prefix** 8 | 9 | Sensor data outputs shall be named with the following prefix: 10 | 11 | [source,protobuf] 12 | ---- 13 | OSMPSensorDataOut 14 | ---- 15 | 16 | **Rules** 17 | 18 | * If only one sensor data output is configured, the prefix shall only be `OSMPSensorDataOut`. 19 | * If more than one sensor data output is configured, the prefix shall be extended by an array index, for example, `OSMPSensorDataOut[1]` and `OSMPSensorDataOut[2]`. 20 | * Array indices shall start at 1 and shall be consecutive. 21 | * Each sensor data output shall be defined as a notional discrete binary output variable with `@causality="output"` and `@variability="discrete"`. 22 | * The MIME type of the variable shall specify `type="SensorData"` as part of the MIME type parameters. 23 | * Sensor data shall be encoded as `osi3::SensorData`. 24 | * The guaranteed lifetime of the sensor data protocol-buffer pointer provided as output by the FMU shall be from the end of the call to `fmi2DoStep` that calculated this buffer until the beginning of the second `fmi2DoStep` call after that. -------------------------------------------------------------------------------- /doc/spec/sensor_view_input_configuration.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Sensor view input configuration 6 | 7 | For each notional sensor view input variable with the base prefix `OSMPSensorViewIn`, a corresponding calculated parameter with the base prefix `OSMPSensorViewInConfigRequest` and a parameter with the base prefix `OSMPSensorViewInConfig` can exist. 8 | 9 | During FMI initialization mode, the simulation environment queries the value of `OSMPSensorViewInConfigRequest`. 10 | Taking this value into account, a suitable and supported sensor view input configuration is determined. 11 | Before exiting initialization mode, the simulation environment then sets this configuration using the corresponding `OSMPSensorViewInConfig` parameter. 12 | 13 | **Prefix** 14 | 15 | Sensor view input configurations shall be named with the following prefix: 16 | 17 | [source,protobuf] 18 | ---- 19 | OSMPSensorViewInConfig 20 | ---- 21 | 22 | Sensor view input configuration requests shall be named with the following prefix: 23 | 24 | [source,protobuf] 25 | ---- 26 | OSMPSensorViewInConfigRequest 27 | ---- 28 | 29 | **Rules** 30 | 31 | * If more than one sensor view input is to be configured, the prefix shall be extended by an array index, for example, `OSMPSensorViewInConfigRequest[1]`, `OSMPSensorViewInConfig[1]`, `OSMPSensorViewInConfigRequest[2]`, and `OSMPSensorViewInConfig[2]`. 32 | * Array indices shall start at 1, shall be consecutive, and shall correspond between sensor view inputs and sensor view configuration parameters. 33 | * If the calculated parameter `OSMPSensorViewInConfigRequest` exists, then the corresponding parameter `OSMPSensorViewInConfig` shall exist. 34 | * `OSMPSensorViewInConfigRequest` shall have a `@causality = "calculatedParameter"` and a `@variability = "fixed"` or `@variability = "tunable"`. 35 | * `OSMPSensorViewInConfig` shall have a `@causality = "parameter"` and a `@variability = "fixed"` or `@variability = "tunable"`. 36 | * The `@variability` values of `OSMPSensorViewInConfigRequest` and `OSMPSensorViewInConfig` shall match. 37 | * The MIME type of both variables shall specify `type="SensorViewConfiguration"` as part of the MIME type parameters. 38 | * The variable values shall be encoded as `osi3::SensorViewConfiguration`. 39 | * As long as no non-zero value has been assigned to `OSMPSensorViewInConfig`, the value of the corresponding `OSMPSensorViewInConfigRequest` shall be the desired sensor view configuration for the corresponding variable `OSMPSensorViewIn`. 40 | This configuration is based on model-internal requirements or any other parameters on which this calculated parameter depends. 41 | * Once a non-zero value has been assigned to `OSMPSensorViewInConfig`, the value of the corresponding `OSMPSensorViewInConfigRequest` shall be an encoded OSI protocol buffer containing the same data as the `OSMPSensorViewInConfig`. 42 | * During FMI initialization mode, the simulation environment should query the value of `OSMPSensorViewInConfigRequest` and determine a suitable sensor view input configuration. 43 | * Before exiting initialization mode, the simulation environment shall set the sensor view input configuration using the corresponding `OSMPSensorViewInConfig` parameter. 44 | * The guaranteed lifetime of the sensor view configuration protocol-buffer pointers shall be from the time of the call to `fmi2SetInteger` that provides those values until the end of the FMI initialization mode, indicating by the return of the `fmi2ExitInitializationMode` call. -------------------------------------------------------------------------------- /doc/spec/sensor_view_inputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Sensor view inputs 6 | 7 | **Prefix** 8 | 9 | Sensor view inputs shall be named with the following prefix: 10 | 11 | [source,protobuf] 12 | ---- 13 | OSMPSensorViewIn 14 | ---- 15 | 16 | **Rules** 17 | 18 | * If only one sensor view input is configured, the prefix shall only be `OSMPSensorViewIn`. 19 | * If more than one sensor view input is configured, the prefix shall be extended by an array index, for example, `OSMPSensorViewIn[1]` and `OSMPSensorViewIn[2]`. 20 | * Array indices shall start at 1 and shall be consecutive. 21 | * Each sensor view input shall be defined as a notional discrete binary input variable with `@causality="input"` and `@variability="discrete"`. 22 | * The MIME type of the variable shall specify the `type=SensorView` as part of the MIME type parameters. 23 | * Sensor view data shall be encoded as `osi3::SensorView`. 24 | * The sensor view passed to the model shall contain data as specified by the parameter `OSMPSensorViewInConfiguration`. 25 | * The guaranteed lifetime of the sensor view protocol-buffer pointer provided as input to the FMU shall be from the time of the call to `fmi2SetInteger` that provides those values until the end of the following `fmi2DoStep` call. 26 | -------------------------------------------------------------------------------- /doc/spec/sensor_view_outputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Sensor view outputs 6 | 7 | **Prefix** 8 | 9 | Sensor view outputs shall be named with the following prefix: 10 | 11 | [source,protobuf] 12 | ---- 13 | OSMPSensorViewOut 14 | ---- 15 | 16 | **Rules** 17 | 18 | * If only one sensor view output is configured, the prefix shall only be `OSMPSensorViewOut`. 19 | * If more than one sensor view output is configured, the prefix shall be extended by an array index, for example, `OSMPSensorViewOut[1]` and `OSMPSensorViewOut[2]`. 20 | * Array indices shall start at 1 and shall be consecutive. 21 | * Each sensor view output shall be defined as a notional discrete binary output variable with `@causality="output"` and `@variability="discrete"`. 22 | * The MIME type of the variable shall specify the `type="SensorView"` as part of the MIME type parameters. 23 | * Sensor view data shall be encoded as `osi3::SensorView`. 24 | * The guaranteed lifetime of the sensor view protocol-buffer pointer provided as output by the FMU shall be from the end of the call to `fmi2DoStep` that calculated this buffer until the beginning of the second `fmi2DoStep` call after that. -------------------------------------------------------------------------------- /doc/spec/streaming_update_inputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Streaming update inputs 6 | 7 | Streaming update inputs are present in streaming update consumer models. 8 | They provide incremental updates of environmental simulation state in a way that is suitable for low latency applications. 9 | 10 | **Prefix** 11 | 12 | Streaming update inputs shall be named with the following prefix: 13 | 14 | [source,protobuf] 15 | ---- 16 | OSMPStreamingUpdateIn 17 | ---- 18 | 19 | **Rules** 20 | 21 | * If only one streaming update input is configured, the prefix shall only be `OSMPStreamingUpdateIn`. 22 | * If more than one streaming update input is configured, the prefix shall be extended by an array index designator, for example `OSMPStreamingUpdateIn[1]` and `OSMPStreamingUpdateIn[2]`. 23 | * Array indices shall start at 1 and shall be consecutive. 24 | * Each streaming update input shall be defined as a notional discrete binary input variable with `@causality="input"` and `@variability="discrete"`. 25 | * The MIME type of the variable shall specify the `type="StreamingUpdate"` as part of the MIME type parameters. 26 | * Streaming updates shall be encoded as `osi3::StreamingUpdate`. 27 | * The guaranteed lifetime of the traffic command protocol-buffer pointer provided as input to the FMU shall be from the time of the call to `fmi2SetInteger` that provides those values until the end of the following `fmi2DoStep` call. 28 | -------------------------------------------------------------------------------- /doc/spec/traffic_command_inputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Traffic command inputs 6 | 7 | Traffic command inputs are present in traffic participant models. 8 | This makes it possible to control the traffic participant behavior using scenario engines. 9 | 10 | **Prefix** 11 | 12 | Traffic command inputs shall be named with the following prefix: 13 | 14 | [source,protobuf] 15 | ---- 16 | OSMPTrafficCommandIn 17 | ---- 18 | 19 | **Rules** 20 | 21 | * If only one traffic command input is configured, the prefix shall only be `OSMPTrafficCommandIn`. 22 | * If more than one traffic command input is configured, the prefix shall be extended by an array index designator, for example `OSMPTrafficCommandIn[1]` and `OSMPTrafficCommandIn[2]`. 23 | * Array indices shall start at 1 and shall be consecutive. 24 | * Each traffic command input shall be defined as a notional discrete binary input variable with `@causality="input"` and `@variability="discrete"`. 25 | * The MIME type of the variable shall specify the `type="TrafficCommand"` as part of the MIME type parameters. 26 | * Traffic commands shall be encoded as `osi3::TrafficCommand`. 27 | * The guaranteed lifetime of the traffic command protocol-buffer pointer provided as input to the FMU shall be from the time of the call to `fmi2SetInteger` that provides those values until the end of the following `fmi2DoStep` call. 28 | -------------------------------------------------------------------------------- /doc/spec/traffic_command_update_outputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Traffic command update outputs 6 | 7 | Traffic command update outputs are present in traffic participant models. 8 | 9 | **Prefix** 10 | 11 | Traffic command update outputs shall be named with the following prefix: 12 | 13 | [source,protobuf] 14 | ---- 15 | OSMPTrafficCommandUpdateOut 16 | ---- 17 | 18 | **Rules** 19 | 20 | * If only one traffic command update output is configured, the prefix shall only be `OSMPTrafficCommandUpdateOut`. 21 | * If more than one traffic command update output is configured, the prefix shall be extended by an array index, for example `OSMPTrafficCommandUpdateOut[1]` and `OSMPTrafficCommandUpdateOut[2]`. 22 | * Array indices shall start at 1 and shall be consecutive. 23 | * Each traffic command update output shall be defined as a notional discrete binary output variable with a `@causality="output"` and a `@variability="discrete"`. 24 | * The MIME type of the variable shall specify the `type=TrafficCommandUpdate` as part of the MIME type parameters. 25 | * Traffic command updates shall be encoded as `osi3::TrafficCommandUpdate`. 26 | * The guaranteed lifetime of the traffic command update protocol-buffer pointer provided as output by the FMU shall be from the end of the call to `fmi2DoStep` that calculated this buffer until the beginning of the second `fmi2DoStep` call after that. -------------------------------------------------------------------------------- /doc/spec/traffic_update_outputs.adoc: -------------------------------------------------------------------------------- 1 | ifndef::include-only-once[] 2 | :root-path: ../ 3 | include::{root-path}_config.adoc[] 4 | endif::[] 5 | = Traffic update outputs 6 | 7 | Traffic update outputs are present in traffic participant models. 8 | 9 | **Prefix** 10 | 11 | Traffic update outputs shall be named with the following prefix: 12 | 13 | [source,protobuf] 14 | ---- 15 | OSMPTrafficUpdateOut 16 | ---- 17 | 18 | **Rules** 19 | 20 | * If only one traffic update output is configured, the prefix shall only be `OSMPTrafficUpdateOut`. 21 | * If more than one traffic update output is configured, the prefix shall be extended by an array index, for example `OSMPTrafficUpdateOut[1]` and `OSMPTrafficUpdateOut[2]`. 22 | * Array indices shall start at 1 and shall be consecutive. 23 | * Each traffic update output shall be defined as a notional discrete binary output variable with a `@causality="output"` and a `@variability="discrete"`. 24 | * The MIME type of the variable shall specify the `type=TrafficUpdate` as part of the MIME type parameters. 25 | * Traffic updates shall be encoded as `osi3::TrafficUpdate`. 26 | * The guaranteed lifetime of the traffic update protocol-buffer pointer provided as output by the FMU shall be from the end of the call to `fmi2DoStep` that calculated this buffer until the beginning of the second `fmi2DoStep` call after that. -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/Modules/") 3 | 4 | # Set a default build type if none was specified 5 | set(default_build_type "Release") 6 | if(EXISTS "${CMAKE_SOURCE_DIR}/../.git") 7 | set(default_build_type "Debug") 8 | endif() 9 | 10 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 11 | message(STATUS "Setting build type to '${default_build_type}' as none was specified.") 12 | set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE 13 | STRING "Choose the type of build." FORCE) 14 | # Set the possible values of build type for cmake-gui 15 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 16 | "Debug" "Release" "MinSizeRel" "RelWithDebInfo") 17 | endif() 18 | 19 | file(READ "../VERSION" ver) 20 | 21 | string(REGEX MATCH "VERSION_MAJOR ([0-9]*)" _ ${ver}) 22 | set(OSMP_VERSION_MAJOR ${CMAKE_MATCH_1}) 23 | 24 | string(REGEX MATCH "VERSION_MINOR ([0-9]*)" _ ${ver}) 25 | set(OSMP_VERSION_MINOR ${CMAKE_MATCH_1}) 26 | 27 | string(REGEX MATCH "VERSION_PATCH ([0-9]*)" _ ${ver}) 28 | set(OSMP_VERSION_PATCH ${CMAKE_MATCH_1}) 29 | 30 | set(OSMPVERSION "${OSMP_VERSION_MAJOR}.${OSMP_VERSION_MINOR}.${OSMP_VERSION_PATCH}" CACHE STRING "OSMP Version String") 31 | 32 | add_subdirectory( open-simulation-interface ) 33 | 34 | get_directory_property(OSI_VERSION_MAJOR DIRECTORY open-simulation-interface DEFINITION VERSION_MAJOR) 35 | get_directory_property(OSI_VERSION_MINOR DIRECTORY open-simulation-interface DEFINITION VERSION_MINOR) 36 | get_directory_property(OSI_VERSION_PATCH DIRECTORY open-simulation-interface DEFINITION VERSION_PATCH) 37 | set(OSIVERSION "${OSI_VERSION_MAJOR}.${OSI_VERSION_MINOR}.${OSI_VERSION_PATCH}") 38 | 39 | include_directories( includes ) 40 | add_subdirectory( OSMPDummySensor ) 41 | add_subdirectory( OSMPDummySource ) 42 | add_subdirectory( OSMPCNetworkProxy ) 43 | -------------------------------------------------------------------------------- /examples/Modules/FindZeroMQ.cmake: -------------------------------------------------------------------------------- 1 | # Try to find ZeroMQ Library 2 | 3 | find_package(PkgConfig) 4 | pkg_check_modules(PC_ZeroMQ QUIET zmq) 5 | 6 | find_path(ZeroMQ_INCLUDE_DIR 7 | NAMES zmq.hpp 8 | PATHS ${PC_ZeroMQ_INCLUDE_DIRS}) 9 | 10 | find_library(ZeroMQ_LIBRARY 11 | NAMES libzmq${CMAKE_SHARED_LIBRARY_SUFFIX} 12 | PATHS ${PC_ZeroMQ_LIBRARY_DIRS}) 13 | 14 | find_library(ZeroMQ_LIBRARY_STATIC 15 | NAMES libzmq${CMAKE_STATIC_LIBRARY_SUFFIX} 16 | PATHS ${PC_ZeroMQ_LIBRARY_DIRS}) 17 | 18 | include(FindPackageHandleStandardArgs) 19 | find_package_handle_standard_args(ZeroMQ DEFAULT_MSG ZeroMQ_LIBRARY ZeroMQ_LIBRARY_STATIC ZeroMQ_INCLUDE_DIR) 20 | mark_as_advanced(ZeroMQ_INCLUDE_DIR ZeroMQ_LIBRARY ZeroMQ_LIBRARY_STATIC) 21 | -------------------------------------------------------------------------------- /examples/OSMPCNetworkProxy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(OSMPCNetworkProxy) 3 | 4 | set(PUBLIC_LOGGING OFF CACHE BOOL "Enable logging via FMI logger") 5 | set(PRIVATE_LOGGING OFF CACHE BOOL "Enable private logging to file") 6 | if(WIN32) 7 | set(PRIVATE_LOG_PATH_CPROXY "C:/TEMP/OSMPCNetworkProxyLog.log" CACHE FILEPATH "Path to write private log file to") 8 | else() 9 | set(PRIVATE_LOG_PATH_CPROXY "/tmp/OSMPCNetworkProxyLog.log" CACHE FILEPATH "Path to write private log file to") 10 | endif() 11 | if(PRIVATE_LOGGING) 12 | file(TO_NATIVE_PATH ${PRIVATE_LOG_PATH_CPROXY} PRIVATE_LOG_PATH_CPROXY_NATIVE) 13 | string(REPLACE "\\" "\\\\" PRIVATE_LOG_PATH ${PRIVATE_LOG_PATH_CPROXY_NATIVE}) 14 | endif() 15 | set(VERBOSE_FMI_LOGGING OFF CACHE BOOL "Enable detailed FMI function logging") 16 | set(DEBUG_BREAKS OFF CACHE BOOL "Enable debugger traps for debug builds of FMU") 17 | set(FMU_DEFAULT_ADDRESS "127.0.0.1" CACHE STRING "Default address for connections") 18 | set(FMU_DEFAULT_PORT "3456" CACHE STRING "Default port for connections") 19 | set(FMU_LISTEN OFF CACHE BOOL "Create FMU that passively listens (server mode)") 20 | 21 | string(TIMESTAMP FMUTIMESTAMP UTC) 22 | string(MD5 FMUGUID modelDescription.in.xml) 23 | configure_file(modelDescription.in.xml modelDescription.xml @ONLY) 24 | configure_file(OSMPCNetworkProxyConfig.in.h OSMPCNetworkProxyConfig.h) 25 | 26 | add_library(OSMPCNetworkProxy SHARED OSMPCNetworkProxy.c) 27 | set_target_properties(OSMPCNetworkProxy PROPERTIES PREFIX "") 28 | target_compile_definitions(OSMPCNetworkProxy PRIVATE "FMU_SHARED_OBJECT") 29 | if(WIN32) 30 | target_link_libraries(OSMPCNetworkProxy wsock32 ws2_32) 31 | endif() 32 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 33 | 34 | if(WIN32) 35 | if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) 36 | set(FMI_BINARIES_PLATFORM "win64") 37 | else() 38 | set(FMI_BINARIES_PLATFORM "win32") 39 | endif() 40 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") 41 | if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) 42 | set(FMI_BINARIES_PLATFORM "linux64") 43 | else() 44 | set(FMI_BINARIES_PLATFORM "linux32") 45 | endif() 46 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 47 | if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) 48 | set(FMI_BINARIES_PLATFORM "darwin64") 49 | else() 50 | set(FMI_BINARIES_PLATFORM "darwin32") 51 | endif() 52 | endif() 53 | 54 | add_custom_command(TARGET OSMPCNetworkProxy 55 | POST_BUILD 56 | COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" 57 | COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/sources" 58 | COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}" 59 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/modelDescription.xml" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/modelDescription.xml" 60 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/OSMPCNetworkProxy.c" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/OSMPCNetworkProxy.c" 61 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/OSMPCNetworkProxy.h" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/OSMPCNetworkProxy.h" 62 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/OSMPCNetworkProxyConfig.h" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/OSMPCNetworkProxyConfig.h" 63 | COMMAND ${CMAKE_COMMAND} -E copy $ "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}" 64 | COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" ${CMAKE_COMMAND} -E tar "cfv" "../OSMPCNetworkProxy.fmu" --format=zip "modelDescription.xml" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}") 65 | -------------------------------------------------------------------------------- /examples/OSMPCNetworkProxy/OSMPCNetworkProxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #include "OSMPCNetworkProxy.h" 12 | 13 | /* 14 | * Debug Breaks 15 | * 16 | * If you define DEBUG_BREAKS the FMU will automatically break 17 | * into an attached Debugger on all major computation functions. 18 | * Note that the FMU is likely to break all environments if no 19 | * Debugger is actually attached when the breaks are triggered. 20 | */ 21 | #if defined(DEBUG_BREAKS) && !defined(NDEBUG) 22 | #if defined(__has_builtin) && !defined(__ibmxl__) 23 | #if __has_builtin(__builtin_debugtrap) 24 | #define DEBUGBREAK() __builtin_debugtrap() 25 | #elif __has_builtin(__debugbreak) 26 | #define DEBUGBREAK() __debugbreak() 27 | #endif 28 | #endif 29 | #if !defined(DEBUGBREAK) 30 | #if defined(_MSC_VER) || defined(__INTEL_COMPILER) 31 | #include 32 | #define DEBUGBREAK() __debugbreak() 33 | #else 34 | #include 35 | #if defined(SIGTRAP) 36 | #define DEBUGBREAK() raise(SIGTRAP) 37 | #else 38 | #define DEBUGBREAK() raise(SIGABRT) 39 | #endif 40 | #endif 41 | #endif 42 | #else 43 | #define DEBUGBREAK() 44 | #endif 45 | 46 | #include 47 | 48 | #ifdef PRIVATE_LOG_PATH 49 | FILE* OSMPCNetworkProxy_private_log_file; 50 | #endif 51 | 52 | /* 53 | * Binary Data Accessors 54 | */ 55 | 56 | void* decode_integer_to_pointer(fmi2Integer hi,fmi2Integer lo) 57 | { 58 | #if PTRDIFF_MAX == INT64_MAX 59 | union addrconv { 60 | struct { 61 | int lo; 62 | int hi; 63 | } base; 64 | unsigned long long address; 65 | } myaddr; 66 | myaddr.base.lo=lo; 67 | myaddr.base.hi=hi; 68 | return (void*)(myaddr.address); 69 | #elif PTRDIFF_MAX == INT32_MAX 70 | return (void*)(lo); 71 | #else 72 | #error "Cannot determine 32bit or 64bit environment!" 73 | #endif 74 | } 75 | 76 | void encode_pointer_to_integer(const void* ptr,fmi2Integer* hi,fmi2Integer* lo) 77 | { 78 | #if PTRDIFF_MAX == INT64_MAX 79 | union addrconv { 80 | struct { 81 | int lo; 82 | int hi; 83 | } base; 84 | unsigned long long address; 85 | } myaddr; 86 | myaddr.address=(unsigned long long)(ptr); 87 | *hi=myaddr.base.hi; 88 | *lo=myaddr.base.lo; 89 | #elif PTRDIFF_MAX == INT32_MAX 90 | *hi=0; 91 | *lo=(int)(ptr); 92 | #else 93 | #error "Cannot determine 32bit or 64bit environment!" 94 | #endif 95 | } 96 | 97 | 98 | /* 99 | * TCP Proxy Communication 100 | */ 101 | 102 | #ifdef FMU_LISTEN 103 | int ensure_tcp_proxy_listen(OSMPCNetworkProxy component) 104 | { 105 | struct addrinfo hints; 106 | struct addrinfo *result; 107 | int rc; 108 | 109 | if (component->tcp_proxy_listen_socket != INVALID_SOCKET) 110 | return 1; 111 | 112 | memset(&hints,0,sizeof(hints)); 113 | hints.ai_family = AF_UNSPEC; 114 | hints.ai_socktype = SOCK_STREAM; 115 | hints.ai_protocol = IPPROTO_TCP; 116 | hints.ai_flags = AI_NUMERICHOST|AI_PASSIVE; 117 | hints.ai_addrlen=0; 118 | hints.ai_canonname=0; 119 | hints.ai_addr=0; 120 | hints.ai_next=0; 121 | 122 | normal_log(component,"NET","Listening on %s:%s",component->string_vars[FMI_STRING_ADDRESS_IDX],component->string_vars[FMI_STRING_PORT_IDX]); 123 | rc=getaddrinfo(component->string_vars[FMI_STRING_ADDRESS_IDX],component->string_vars[FMI_STRING_PORT_IDX],&hints,&result); 124 | if (rc!=0 || !result) { 125 | #ifdef _WIN32 126 | normal_log(component,"NET","Error getting listening address: %d",WSAGetLastError()); 127 | #else 128 | normal_log(component,"NET","Error getting listening address: %d (%s)",rc,gai_strerror(rc)); 129 | #endif 130 | return 0; 131 | } 132 | 133 | component->tcp_proxy_listen_socket = socket(result->ai_family,SOCK_STREAM,IPPROTO_TCP); 134 | if (component->tcp_proxy_listen_socket == INVALID_SOCKET) { 135 | #ifdef _WIN32 136 | normal_log(component,"NET","Error setting up Socket: %d",WSAGetLastError()); 137 | #else 138 | normal_log(component,"NET","Error setting up Socket: %d (%s)",errno,strerror(errno)); 139 | #endif 140 | freeaddrinfo(result); 141 | return 0; 142 | } 143 | 144 | rc = bind(component->tcp_proxy_listen_socket,result->ai_addr,result->ai_addrlen); 145 | 146 | if (rc != 0) { 147 | #ifdef _WIN32 148 | normal_log(component,"NET","Error setting up Socket Bind: %d",WSAGetLastError()); 149 | #else 150 | normal_log(component,"NET","Error setting up Socket Bind: %d (%s)",errno,strerror(errno)); 151 | #endif 152 | #ifdef _WIN32 153 | closesocket(component->tcp_proxy_listen_socket); 154 | #else 155 | close(component->tcp_proxy_listen_socket); 156 | #endif 157 | component->tcp_proxy_listen_socket=INVALID_SOCKET; 158 | freeaddrinfo(result); 159 | return 0; 160 | } 161 | 162 | freeaddrinfo(result); 163 | return 1; 164 | } 165 | 166 | int ensure_tcp_proxy_connection(OSMPCNetworkProxy component) 167 | { 168 | int rc; 169 | 170 | if (component->tcp_proxy_socket != INVALID_SOCKET) 171 | return 1; 172 | 173 | if (!ensure_tcp_proxy_listen(component)) 174 | return 0; 175 | 176 | normal_log(component,"NET","Listening on %s:%s",component->string_vars[FMI_STRING_ADDRESS_IDX],component->string_vars[FMI_STRING_PORT_IDX]); 177 | rc=listen(component->tcp_proxy_listen_socket,SOMAXCONN); 178 | if (rc!=0) { 179 | #ifdef _WIN32 180 | normal_log(component,"NET","Error listening on socket: %d",WSAGetLastError()); 181 | closesocket(component->tcp_proxy_listen_socket); 182 | #else 183 | normal_log(component,"NET","Error listening on socket: %d (%s)",rc,gai_strerror(rc)); 184 | close(component->tcp_proxy_listen_socket); 185 | #endif 186 | component->tcp_proxy_listen_socket=INVALID_SOCKET; 187 | return 0; 188 | } 189 | 190 | component->tcp_proxy_socket = accept(component->tcp_proxy_listen_socket,NULL,NULL); 191 | if (component->tcp_proxy_socket == INVALID_SOCKET) { 192 | #ifdef _WIN32 193 | normal_log(component,"NET","Error accepting on Socket: %d",WSAGetLastError()); 194 | closesocket(component->tcp_proxy_listen_socket); 195 | #else 196 | normal_log(component,"NET","Error accpeting on Socket: %d (%s)",errno,strerror(errno)); 197 | close(component->tcp_proxy_listen_socket); 198 | #endif 199 | component->tcp_proxy_listen_socket=INVALID_SOCKET; 200 | return 0; 201 | } 202 | 203 | return 1; 204 | } 205 | 206 | void close_tcp_proxy_connection(OSMPCNetworkProxy component) 207 | { 208 | if (component->tcp_proxy_socket!=INVALID_SOCKET) { 209 | #ifdef _WIN32 210 | closesocket(component->tcp_proxy_socket); 211 | #else 212 | close(component->tcp_proxy_socket); 213 | #endif 214 | component->tcp_proxy_socket=INVALID_SOCKET; 215 | } 216 | } 217 | 218 | void close_tcp_proxy_listen(OSMPCNetworkProxy component) 219 | { 220 | if (component->tcp_proxy_listen_socket!=INVALID_SOCKET) { 221 | #ifdef _WIN32 222 | closesocket(component->tcp_proxy_listen_socket); 223 | #else 224 | close(component->tcp_proxy_listen_socket); 225 | #endif 226 | component->tcp_proxy_listen_socket=INVALID_SOCKET; 227 | } 228 | } 229 | 230 | #else 231 | 232 | int ensure_tcp_proxy_connection(OSMPCNetworkProxy component) 233 | { 234 | struct addrinfo hints; 235 | struct addrinfo *result; 236 | int rc; 237 | 238 | if (component->tcp_proxy_socket != INVALID_SOCKET) 239 | return 1; 240 | 241 | memset(&hints,0,sizeof(hints)); 242 | hints.ai_family = AF_UNSPEC; 243 | hints.ai_socktype = SOCK_STREAM; 244 | hints.ai_protocol = IPPROTO_TCP; 245 | hints.ai_flags = AI_NUMERICHOST; 246 | hints.ai_addrlen=0; 247 | hints.ai_canonname=0; 248 | hints.ai_addr=0; 249 | hints.ai_next=0; 250 | 251 | normal_log(component,"NET","Connecting to %s:%s",component->string_vars[FMI_STRING_ADDRESS_IDX],component->string_vars[FMI_STRING_PORT_IDX]); 252 | rc=getaddrinfo(component->string_vars[FMI_STRING_ADDRESS_IDX],component->string_vars[FMI_STRING_PORT_IDX],&hints,&result); 253 | if (rc!=0 || !result) { 254 | #ifdef _WIN32 255 | normal_log(component,"NET","Error getting destination address: %d",WSAGetLastError()); 256 | #else 257 | normal_log(component,"NET","Error getting destination address: %d (%s)",rc,gai_strerror(rc)); 258 | #endif 259 | return 0; 260 | } 261 | 262 | component->tcp_proxy_socket = socket(result->ai_family,SOCK_STREAM,IPPROTO_TCP); 263 | if (component->tcp_proxy_socket == INVALID_SOCKET) { 264 | #ifdef _WIN32 265 | normal_log(component,"NET","Error setting up Socket: %d",WSAGetLastError()); 266 | #else 267 | normal_log(component,"NET","Error setting up Socket: %d (%s)",errno,strerror(errno)); 268 | #endif 269 | freeaddrinfo(result); 270 | return 0; 271 | } 272 | 273 | rc = connect(component->tcp_proxy_socket,result->ai_addr,result->ai_addrlen); 274 | 275 | if (rc != 0) { 276 | #ifdef _WIN32 277 | normal_log(component,"NET","Error setting up Socket Connection: %d",WSAGetLastError()); 278 | #else 279 | normal_log(component,"NET","Error setting up Socket Connection: %d (%s)",errno,strerror(errno)); 280 | #endif 281 | #ifdef _WIN32 282 | closesocket(component->tcp_proxy_socket); 283 | #else 284 | close(component->tcp_proxy_socket); 285 | #endif 286 | component->tcp_proxy_socket=INVALID_SOCKET; 287 | freeaddrinfo(result); 288 | return 0; 289 | } 290 | 291 | freeaddrinfo(result); 292 | return 1; 293 | } 294 | 295 | void close_tcp_proxy_connection(OSMPCNetworkProxy component) 296 | { 297 | if (component->tcp_proxy_socket!=INVALID_SOCKET) { 298 | #ifdef _WIN32 299 | closesocket(component->tcp_proxy_socket); 300 | #else 301 | close(component->tcp_proxy_socket); 302 | #endif 303 | component->tcp_proxy_socket=INVALID_SOCKET; 304 | } 305 | } 306 | 307 | #endif 308 | /* 309 | * Actual Core Content 310 | */ 311 | 312 | fmi2Status doInit(OSMPCNetworkProxy component) 313 | { 314 | int i; 315 | 316 | DEBUGBREAK(); 317 | 318 | /* Booleans */ 319 | for (i = 0; iboolean_vars[i] = fmi2False; 321 | 322 | component->boolean_vars[FMI_BOOLEAN_SENDER_IDX] = fmi2True; 323 | component->boolean_vars[FMI_BOOLEAN_RECEIVER_IDX] = fmi2True; 324 | 325 | /* Integers */ 326 | for (i = 0; iinteger_vars[i] = 0; 328 | 329 | /* Reals */ 330 | for (i = 0; ireal_vars[i] = 0.0; 332 | 333 | /* Strings */ 334 | component->string_vars[FMI_STRING_ADDRESS_IDX]=strdup(FMU_DEFAULT_ADDRESS); 335 | component->string_vars[FMI_STRING_PORT_IDX]=strdup(FMU_DEFAULT_PORT); 336 | 337 | return fmi2OK; 338 | } 339 | 340 | fmi2Status doStart(OSMPCNetworkProxy component,fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) 341 | { 342 | DEBUGBREAK(); 343 | component->last_time = startTime; 344 | return fmi2OK; 345 | } 346 | 347 | fmi2Status doEnterInitializationMode(OSMPCNetworkProxy component) 348 | { 349 | return fmi2OK; 350 | } 351 | 352 | fmi2Status doExitInitializationMode(OSMPCNetworkProxy component) 353 | { 354 | #ifdef FMU_LISTEN 355 | if (!ensure_tcp_proxy_listen(component)) 356 | return fmi2Error; 357 | else 358 | #endif 359 | return fmi2OK; 360 | } 361 | 362 | fmi2Status doCalc(OSMPCNetworkProxy component, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) 363 | { 364 | void* buffer=NULL; 365 | int buffersize=0; 366 | 367 | DEBUGBREAK(); 368 | 369 | component->boolean_vars[FMI_BOOLEAN_INPUT_VALID_IDX]=fmi2False; 370 | component->boolean_vars[FMI_BOOLEAN_INPUT_SENT_IDX]=fmi2False; 371 | 372 | buffer = decode_integer_to_pointer(component->integer_vars[FMI_INTEGER_SENSORDATA_IN_BASEHI_IDX],component->integer_vars[FMI_INTEGER_SENSORDATA_IN_BASELO_IDX]); 373 | buffersize = component->integer_vars[FMI_INTEGER_SENSORDATA_IN_SIZE_IDX]; 374 | 375 | if (component->integer_vars[FMI_INTEGER_SENSORDATA_IN_SIZE_IDX] > 0) { 376 | normal_log(component,"OSMP","Got %08X %08X LEN %08X, reading from %p (length %i)...",component->integer_vars[FMI_INTEGER_SENSORDATA_IN_BASEHI_IDX],component->integer_vars[FMI_INTEGER_SENSORDATA_IN_BASELO_IDX],buffersize,buffer,buffersize); 377 | if (component->boolean_vars[FMI_BOOLEAN_LOG_DATA_IDX]) { 378 | int i=0; 379 | for (i=0;i>4]; 388 | *ptr++=hexmap[byte&0xF]; 389 | } 390 | *ptr='\0'; 391 | normal_log(component,"OSMP"," %s",hexline); 392 | } 393 | } 394 | component->boolean_vars[FMI_BOOLEAN_INPUT_VALID_IDX]=fmi2True; 395 | } 396 | 397 | if (!component->boolean_vars[FMI_BOOLEAN_DUMMY_IDX] && component->boolean_vars[FMI_BOOLEAN_SENDER_IDX]) { 398 | if (ensure_tcp_proxy_connection(component)) { 399 | int sendval=send(component->tcp_proxy_socket,(char*)&buffersize,sizeof(buffersize),0); 400 | if (sendval!=sizeof(buffersize)) { 401 | #ifdef _WIN32 402 | normal_log(component,"NET","Failed to send message size (%d): %d",buffersize,WSAGetLastError()); 403 | #else 404 | normal_log(component,"NET","Failed to send message size (%d): %d (%s)",buffersize,errno,strerror(errno)); 405 | #endif 406 | close_tcp_proxy_connection(component); 407 | } else { 408 | if (buffersize > 0) { 409 | sendval=send(component->tcp_proxy_socket,(char*)buffer,buffersize,0); 410 | if (sendval!=buffersize) { 411 | #ifdef _WIN32 412 | normal_log(component,"NET","Failed to send message itself with size %d: %d",buffersize,WSAGetLastError()); 413 | #else 414 | normal_log(component,"NET","Failed to send message itself with size %d: %d (%s)",buffersize,errno,strerror(errno)); 415 | #endif 416 | close_tcp_proxy_connection(component); 417 | } else { 418 | normal_log(component,"NET","Successfully sent tcp message with size %d.",buffersize); 419 | component->boolean_vars[FMI_BOOLEAN_INPUT_SENT_IDX]=fmi2True; 420 | } 421 | } else { 422 | normal_log(component,"NET","Successfully sent empty tcp message with size %d.",buffersize); 423 | component->boolean_vars[FMI_BOOLEAN_INPUT_SENT_IDX]=fmi2True; 424 | } 425 | } 426 | } 427 | } 428 | 429 | if (!component->boolean_vars[FMI_BOOLEAN_DUMMY_IDX] && component->boolean_vars[FMI_BOOLEAN_RECEIVER_IDX]) { 430 | /* Switch Buffers */ 431 | if (component->prev_output_buffer_ptr != NULL) { 432 | free(component->prev_output_buffer_ptr); 433 | component->prev_output_buffer_ptr=NULL; 434 | component->prev_output_buffer_size=0; 435 | } 436 | component->prev_output_buffer_ptr = component->output_buffer_ptr; 437 | component->prev_output_buffer_size = component->output_buffer_size; 438 | component->output_buffer_ptr = NULL; 439 | component->output_buffer_size = 0; 440 | component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX] = 0; 441 | component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX] = 0; 442 | component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX] = 0; 443 | 444 | if (ensure_tcp_proxy_connection(component)) { 445 | int recv_buffer_size=0; 446 | char* recv_buffer_ptr=NULL; 447 | int recvval=0; 448 | recvval=recv(component->tcp_proxy_socket,(char*)&(recv_buffer_size),sizeof(recv_buffer_size),MSG_WAITALL); 449 | if (recvval!=sizeof(recv_buffer_size)) { 450 | #ifdef _WIN32 451 | normal_log(component,"NET","Failed to recv message size (%d): %d",sizeof(recv_buffer_size),WSAGetLastError()); 452 | #else 453 | normal_log(component,"NET","Failed to recv message size (%d): %d (%s)",sizeof(recv_buffer_size),errno,strerror(errno)); 454 | #endif 455 | close_tcp_proxy_connection(component); 456 | } else if (recv_buffer_size == 0) { 457 | normal_log(component,"NET","Successfully recv empty tcp message with size %d.",recv_buffer_size); 458 | component->boolean_vars[FMI_BOOLEAN_OUTPUT_RECEIVED_IDX] = fmi2True; 459 | component->output_buffer_ptr = NULL; 460 | component->output_buffer_size = recv_buffer_size; 461 | component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX] = 0; 462 | component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX] = 0; 463 | component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX] = recv_buffer_size; 464 | component->boolean_vars[FMI_BOOLEAN_OUTPUT_VALID_IDX] = fmi2False; 465 | } else { 466 | recv_buffer_ptr = calloc(recv_buffer_size,1); 467 | if (recv_buffer_ptr == NULL) { 468 | normal_log(component,"NET","Failed to allocated recv message buffer of size (%d)",recv_buffer_size); 469 | close_tcp_proxy_connection(component); 470 | } else { 471 | recvval=recv(component->tcp_proxy_socket,recv_buffer_ptr,recv_buffer_size,MSG_WAITALL); 472 | if (recvval!=recv_buffer_size) { 473 | #ifdef _WIN32 474 | normal_log(component,"NET","Failed to recv message itself with size %d: %d",recv_buffer_size,WSAGetLastError()); 475 | #else 476 | normal_log(component,"NET","Failed to recv message itself with size %d: %d (%s)",recv_buffer_size,errno,strerror(errno)); 477 | #endif 478 | close_tcp_proxy_connection(component); 479 | } else { 480 | normal_log(component,"NET","Successfully recv tcp message with size %d.",recv_buffer_size); 481 | component->boolean_vars[FMI_BOOLEAN_OUTPUT_RECEIVED_IDX] = fmi2True; 482 | component->output_buffer_ptr = recv_buffer_ptr; 483 | component->output_buffer_size = recv_buffer_size; 484 | encode_pointer_to_integer(recv_buffer_ptr,&(component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX]),&(component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX])); 485 | component->integer_vars[FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX] = recv_buffer_size; 486 | component->boolean_vars[FMI_BOOLEAN_OUTPUT_VALID_IDX] = fmi2True; 487 | } 488 | } 489 | } 490 | } 491 | } 492 | 493 | component->last_time=currentCommunicationPoint+communicationStepSize; 494 | return fmi2OK; 495 | } 496 | 497 | fmi2Status doTerm(OSMPCNetworkProxy component) 498 | { 499 | DEBUGBREAK(); 500 | #ifdef FMU_LISTEN 501 | close_tcp_proxy_listen(component); 502 | #endif 503 | close_tcp_proxy_connection(component); 504 | return fmi2OK; 505 | } 506 | 507 | void doFree(OSMPCNetworkProxy component) 508 | { 509 | DEBUGBREAK(); 510 | if (component->prev_output_buffer_ptr!=NULL) { 511 | free(component->prev_output_buffer_ptr); 512 | component->prev_output_buffer_ptr=NULL; 513 | component->prev_output_buffer_size=0; 514 | } 515 | if (component->output_buffer_ptr!=NULL) { 516 | free(component->output_buffer_ptr); 517 | component->output_buffer_ptr=NULL; 518 | component->output_buffer_size=0; 519 | } 520 | } 521 | 522 | /* 523 | * FMI 2.0 Co-Simulation Interface API 524 | */ 525 | 526 | FMI2_Export const char* fmi2GetTypesPlatform() 527 | { 528 | return fmi2TypesPlatform; 529 | } 530 | 531 | FMI2_Export const char* fmi2GetVersion() 532 | { 533 | return fmi2Version; 534 | } 535 | 536 | FMI2_Export fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) 537 | { 538 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 539 | fmi_verbose_log(myc,"fmi2SetDebugLogging(%s)", loggingOn ? "true" : "false"); 540 | myc->loggingOn = loggingOn ? 1 : 0; 541 | 542 | for (;myc->loggingCategories!=NULL && myc->nCategories>0;) free(myc->loggingCategories[--(myc->nCategories)]); 543 | free(myc->loggingCategories); 544 | myc->loggingCategories = NULL; 545 | myc->nCategories = 0; 546 | 547 | if (categories && (nCategories > 0)) { 548 | myc->loggingCategories = calloc(nCategories,sizeof(char*)); 549 | if (myc->loggingCategories != NULL) { 550 | size_t i; 551 | myc->nCategories = nCategories; 552 | for (i=0;iloggingCategories[i]=strdup(categories[i]); 553 | } 554 | } else { 555 | myc->loggingCategories = calloc(3,sizeof(char*)); 556 | if (myc->loggingCategories != NULL) { 557 | myc->nCategories = 3; 558 | myc->loggingCategories[0] = strdup("FMI"); 559 | myc->loggingCategories[1] = strdup("OSMP"); 560 | myc->loggingCategories[2] = strdup("NET"); 561 | } 562 | } 563 | 564 | return fmi2OK; 565 | } 566 | 567 | /* 568 | * Functions for Co-Simulation 569 | */ 570 | FMI2_Export fmi2Component fmi2Instantiate(fmi2String instanceName, 571 | fmi2Type fmuType, 572 | fmi2String fmuGUID, 573 | fmi2String fmuResourceLocation, 574 | const fmi2CallbackFunctions* functions, 575 | fmi2Boolean visible, 576 | fmi2Boolean loggingOn) 577 | { 578 | #ifdef _WIN32 579 | long rc; 580 | WSADATA WsaDat; 581 | #endif 582 | OSMPCNetworkProxy myc = NULL; 583 | 584 | #ifdef FMU_GUID 585 | if (fmuGUID!=NULL && 0!=strcmp(fmuGUID,FMU_GUID)) { 586 | fmi_verbose_log_global("fmi2Instantiate(\"%s\",%d,\"%s\",\"%s\",\"%s\",%d,%d) = NULL (GUID mismatch, expected %s)", 587 | instanceName, fmuType, fmuGUID, 588 | (fmuResourceLocation != NULL) ? fmuResourceLocation : "", 589 | "FUNCTIONS", visible, loggingOn, FMU_GUID); 590 | return NULL; 591 | } 592 | #endif 593 | 594 | myc = calloc(1,sizeof(struct OSMPCNetworkProxy)); 595 | 596 | if (myc == NULL) { 597 | fmi_verbose_log_global("fmi2Instantiate(\"%s\",%d,\"%s\",\"%s\",\"%s\",%d,%d) = NULL (alloc failure)", 598 | instanceName, fmuType, fmuGUID, 599 | (fmuResourceLocation != NULL) ? fmuResourceLocation : "", 600 | "FUNCTIONS", visible, loggingOn); 601 | return NULL; 602 | } 603 | 604 | myc->instanceName=strdup(instanceName); 605 | myc->fmuType=fmuType; 606 | myc->fmuGUID=strdup(fmuGUID); 607 | myc->fmuResourceLocation=strdup(fmuResourceLocation); 608 | myc->functions.logger=functions->logger; 609 | myc->functions.allocateMemory=functions->allocateMemory; 610 | myc->functions.freeMemory=functions->freeMemory; 611 | myc->functions.stepFinished=functions->stepFinished; 612 | myc->functions.componentEnvironment=functions->componentEnvironment; 613 | myc->visible=visible; 614 | myc->loggingOn=loggingOn; 615 | myc->last_time=0.0; 616 | #ifdef FMU_LISTEN 617 | myc->tcp_proxy_listen_socket=INVALID_SOCKET; 618 | #endif 619 | myc->tcp_proxy_socket=INVALID_SOCKET; 620 | myc->output_buffer_ptr=NULL; 621 | myc->output_buffer_size=0; 622 | myc->prev_output_buffer_ptr=NULL; 623 | myc->prev_output_buffer_size=0; 624 | 625 | myc->loggingCategories = calloc(3,sizeof(char*)); 626 | if (myc->loggingCategories != NULL) { 627 | myc->nCategories = 3; 628 | myc->loggingCategories[0] = strdup("FMI"); 629 | myc->loggingCategories[1] = strdup("OSMP"); 630 | myc->loggingCategories[2] = strdup("NET"); 631 | } 632 | 633 | #ifdef _WIN32 634 | if ((rc=WSAStartup(MAKEWORD(2,2),&WsaDat)) != 0) { 635 | normal_log(myc,"NET","Error %d setting up Windows Socket Communications.",rc); 636 | WSACleanup(); 637 | } 638 | #endif 639 | 640 | if (doInit(myc) != fmi2OK) { 641 | fmi_verbose_log_global("fmi2Instantiate(\"%s\",%d,\"%s\",\"%s\",\"%s\",%d,%d) = NULL (doInit failure)", 642 | instanceName, fmuType, fmuGUID, 643 | (fmuResourceLocation != NULL) ? fmuResourceLocation : "", 644 | "FUNCTIONS", visible, loggingOn); 645 | free(myc->fmuResourceLocation); 646 | free(myc->fmuGUID); 647 | free(myc->instanceName); 648 | for (;myc->loggingCategories!=NULL && myc->nCategories>0;) free(myc->loggingCategories[--(myc->nCategories)]); 649 | free(myc->loggingCategories); 650 | free(myc); 651 | return NULL; 652 | } 653 | fmi_verbose_log_global("fmi2Instantiate(\"%s\",%d,\"%s\",\"%s\",\"%s\",%d,%d) = %p", 654 | instanceName, fmuType, fmuGUID, 655 | (fmuResourceLocation != NULL) ? fmuResourceLocation : "", 656 | "FUNCTIONS", visible, loggingOn, myc); 657 | return (fmi2Component)myc; 658 | } 659 | 660 | FMI2_Export fmi2Status fmi2SetupExperiment(fmi2Component c, 661 | fmi2Boolean toleranceDefined, 662 | fmi2Real tolerance, 663 | fmi2Real startTime, 664 | fmi2Boolean stopTimeDefined, 665 | fmi2Real stopTime) 666 | { 667 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 668 | fmi_verbose_log(myc,"fmi2SetupExperiment(%d,%g,%g,%d,%g)", toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); 669 | return doStart(myc,toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); 670 | } 671 | 672 | FMI2_Export fmi2Status fmi2EnterInitializationMode(fmi2Component c) 673 | { 674 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 675 | fmi_verbose_log(myc,"fmi2EnterInitializationMode()"); 676 | return doEnterInitializationMode(myc); 677 | } 678 | 679 | FMI2_Export fmi2Status fmi2ExitInitializationMode(fmi2Component c) 680 | { 681 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 682 | fmi_verbose_log(myc,"fmi2ExitInitializationMode()"); 683 | return doExitInitializationMode(myc); 684 | } 685 | 686 | FMI2_Export fmi2Status fmi2DoStep(fmi2Component c, 687 | fmi2Real currentCommunicationPoint, 688 | fmi2Real communicationStepSize, 689 | fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component) 690 | { 691 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 692 | fmi_verbose_log(myc,"fmi2DoStep(%g,%g,%d)", currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPointfmi2Component); 693 | return doCalc(myc,currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPointfmi2Component); 694 | } 695 | 696 | FMI2_Export fmi2Status fmi2Terminate(fmi2Component c) 697 | { 698 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 699 | fmi_verbose_log(myc,"fmi2Terminate()"); 700 | return doTerm(myc); 701 | } 702 | 703 | FMI2_Export fmi2Status fmi2Reset(fmi2Component c) 704 | { 705 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 706 | fmi_verbose_log(myc,"fmi2Reset()"); 707 | doFree(myc); 708 | return doInit(myc); 709 | } 710 | 711 | FMI2_Export void fmi2FreeInstance(fmi2Component c) 712 | { 713 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 714 | fmi_verbose_log(myc,"fmi2FreeInstance()"); 715 | doFree(myc); 716 | 717 | #ifdef FMU_LISTEN 718 | close_tcp_proxy_listen(myc); 719 | #endif 720 | close_tcp_proxy_connection(myc); 721 | #ifdef _WIN32 722 | WSACleanup(); 723 | #endif 724 | 725 | free(myc->fmuResourceLocation); 726 | free(myc->fmuGUID); 727 | free(myc->instanceName); 728 | for (;myc->loggingCategories!=NULL && myc->nCategories>0;) free(myc->loggingCategories[--(myc->nCategories)]); 729 | free(myc->loggingCategories); 730 | free(myc); 731 | } 732 | 733 | /* 734 | * Data Exchange Functions 735 | */ 736 | FMI2_Export fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) 737 | { 738 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 739 | size_t i; 740 | fmi_verbose_log(myc,"fmi2GetReal(...)"); 741 | for (i = 0; ireal_vars[vr[i]]; 744 | else 745 | return fmi2Error; 746 | } 747 | return fmi2OK; 748 | } 749 | 750 | FMI2_Export fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) 751 | { 752 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 753 | size_t i; 754 | fmi_verbose_log(myc,"fmi2GetInteger(...)"); 755 | for (i = 0; iinteger_vars[vr[i]]; 758 | else 759 | return fmi2Error; 760 | } 761 | return fmi2OK; 762 | } 763 | 764 | FMI2_Export fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) 765 | { 766 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 767 | size_t i; 768 | fmi_verbose_log(myc,"fmi2GetBoolean(...)"); 769 | for (i = 0; iboolean_vars[vr[i]]; 772 | else 773 | return fmi2Error; 774 | } 775 | return fmi2OK; 776 | } 777 | 778 | FMI2_Export fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) 779 | { 780 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 781 | size_t i; 782 | fmi_verbose_log(myc,"fmi2GetString(...)"); 783 | for (i = 0; istring_vars[vr[i]]; 786 | else 787 | return fmi2Error; 788 | } 789 | return fmi2OK; 790 | } 791 | 792 | FMI2_Export fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) 793 | { 794 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 795 | size_t i; 796 | fmi_verbose_log(myc,"fmi2SetReal(...)"); 797 | for (i = 0; ireal_vars[vr[i]] = value[i]; 800 | else 801 | return fmi2Error; 802 | } 803 | return fmi2OK; 804 | } 805 | 806 | FMI2_Export fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) 807 | { 808 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 809 | size_t i; 810 | fmi_verbose_log(myc,"fmi2SetInteger(...)"); 811 | for (i = 0; iinteger_vars[vr[i]] = value[i]; 814 | else 815 | return fmi2Error; 816 | } 817 | return fmi2OK; 818 | } 819 | 820 | FMI2_Export fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) 821 | { 822 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 823 | size_t i; 824 | fmi_verbose_log(myc,"fmi2SetBoolean(...)"); 825 | for (i = 0; iboolean_vars[vr[i]] = value[i]; 828 | else 829 | return fmi2Error; 830 | } 831 | return fmi2OK; 832 | } 833 | 834 | FMI2_Export fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) 835 | { 836 | OSMPCNetworkProxy myc = (OSMPCNetworkProxy)c; 837 | size_t i; 838 | fmi_verbose_log(myc,"fmi2SetString(...)"); 839 | for (i = 0; istring_vars[vr[i]]) 842 | free(myc->string_vars[vr[i]]); 843 | myc->string_vars[vr[i]] = strdup(value[i]); 844 | } else 845 | return fmi2Error; 846 | } 847 | return fmi2OK; 848 | } 849 | 850 | /* 851 | * Unsupported Features (FMUState, Derivatives, Async DoStep, Status Enquiries) 852 | */ 853 | FMI2_Export fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) 854 | { 855 | return fmi2Error; 856 | } 857 | 858 | FMI2_Export fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) 859 | { 860 | return fmi2Error; 861 | } 862 | 863 | FMI2_Export fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) 864 | { 865 | return fmi2Error; 866 | } 867 | 868 | FMI2_Export fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) 869 | { 870 | return fmi2Error; 871 | } 872 | 873 | FMI2_Export fmi2Status fmi2SerializeFMUstate (fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) 874 | { 875 | return fmi2Error; 876 | } 877 | 878 | FMI2_Export fmi2Status fmi2DeSerializeFMUstate (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) 879 | { 880 | return fmi2Error; 881 | } 882 | 883 | FMI2_Export fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, 884 | const fmi2ValueReference vUnknown_ref[], size_t nUnknown, 885 | const fmi2ValueReference vKnown_ref[] , size_t nKnown, 886 | const fmi2Real dvKnown[], 887 | fmi2Real dvUnknown[]) 888 | { 889 | return fmi2Error; 890 | } 891 | 892 | FMI2_Export fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, 893 | const fmi2ValueReference vr[], 894 | size_t nvr, 895 | const fmi2Integer order[], 896 | const fmi2Real value[]) 897 | { 898 | return fmi2Error; 899 | } 900 | 901 | FMI2_Export fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, 902 | const fmi2ValueReference vr[], 903 | size_t nvr, 904 | const fmi2Integer order[], 905 | fmi2Real value[]) 906 | { 907 | return fmi2Error; 908 | } 909 | 910 | FMI2_Export fmi2Status fmi2CancelStep(fmi2Component c) 911 | { 912 | return fmi2OK; 913 | } 914 | 915 | FMI2_Export fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status* value) 916 | { 917 | return fmi2Discard; 918 | } 919 | 920 | FMI2_Export fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real* value) 921 | { 922 | return fmi2Discard; 923 | } 924 | 925 | FMI2_Export fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value) 926 | { 927 | return fmi2Discard; 928 | } 929 | 930 | FMI2_Export fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value) 931 | { 932 | return fmi2Discard; 933 | } 934 | 935 | FMI2_Export fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String* value) 936 | { 937 | return fmi2Discard; 938 | } 939 | -------------------------------------------------------------------------------- /examples/OSMPCNetworkProxy/OSMPCNetworkProxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #include "OSMPCNetworkProxyConfig.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING) 18 | #include 19 | #endif 20 | 21 | #ifdef _WIN32 22 | #include 23 | #include 24 | #else 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | typedef int SOCKET; 31 | #endif 32 | #ifndef INVALID_SOCKET 33 | #define INVALID_SOCKET -1 34 | #endif 35 | 36 | #ifndef FMU_SHARED_OBJECT 37 | #define FMI2_FUNCTION_PREFIX OSMPCNetworkProxy_ 38 | #endif 39 | #include "fmi2Functions.h" 40 | 41 | /* 42 | * Logging Control 43 | * 44 | * Logging is controlled via three definitions: 45 | * 46 | * - If PRIVATE_LOG_PATH is defined it gives the name of a file 47 | * that is to be used as a private log file. 48 | * - If PUBLIC_LOGGING is defined then we will (also) log to 49 | * the FMI logging facility where appropriate. 50 | * - If VERBOSE_FMI_LOGGING is defined then logging of basic 51 | * FMI calls is enabled, which can get very verbose. 52 | */ 53 | 54 | /* 55 | * Variable Definitions 56 | * 57 | * Define FMI_*_LAST_IDX to the zero-based index of the last variable 58 | * of the given type (0 if no variables of the type exist). This 59 | * ensures proper space allocation, initialisation and handling of 60 | * the given variables in the template code. Optionally you can 61 | * define FMI_TYPENAME_VARNAME_IDX definitions (e.g. FMI_REAL_MYVAR_IDX) 62 | * to refer to individual variables inside your code, or for example 63 | * FMI_REAL_MYARRAY_OFFSET and FMI_REAL_MYARRAY_SIZE definitions for 64 | * array variables. 65 | */ 66 | 67 | /* Boolean Variables */ 68 | #define FMI_BOOLEAN_DUMMY_IDX 0 69 | #define FMI_BOOLEAN_SENDER_IDX 1 70 | #define FMI_BOOLEAN_RECEIVER_IDX 2 71 | #define FMI_BOOLEAN_ZMQ_IDX 3 72 | #define FMI_BOOLEAN_PUBSUB_IDX 4 73 | #define FMI_BOOLEAN_LOG_DATA_IDX 5 74 | #define FMI_BOOLEAN_INPUT_VALID_IDX 6 75 | #define FMI_BOOLEAN_INPUT_SENT_IDX 7 76 | #define FMI_BOOLEAN_OUTPUT_RECEIVED_IDX 8 77 | #define FMI_BOOLEAN_OUTPUT_VALID_IDX 9 78 | #define FMI_BOOLEAN_LAST_IDX FMI_BOOLEAN_OUTPUT_VALID_IDX 79 | #define FMI_BOOLEAN_VARS (FMI_BOOLEAN_LAST_IDX+1) 80 | 81 | /* Integer Variables */ 82 | #define FMI_INTEGER_SENSORDATA_IN_BASELO_IDX 0 83 | #define FMI_INTEGER_SENSORDATA_IN_BASEHI_IDX 1 84 | #define FMI_INTEGER_SENSORDATA_IN_SIZE_IDX 2 85 | #define FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX 3 86 | #define FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX 4 87 | #define FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX 5 88 | #define FMI_INTEGER_LAST_IDX FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX 89 | #define FMI_INTEGER_VARS (FMI_INTEGER_LAST_IDX+1) 90 | 91 | /* Real Variables */ 92 | #define FMI_REAL_LAST_IDX 0 93 | #define FMI_REAL_VARS (FMI_REAL_LAST_IDX+1) 94 | 95 | /* String Variables */ 96 | #define FMI_STRING_ADDRESS_IDX 0 97 | #define FMI_STRING_PORT_IDX 1 98 | #define FMI_STRING_LAST_IDX FMI_STRING_PORT_IDX 99 | #define FMI_STRING_VARS (FMI_STRING_LAST_IDX+1) 100 | 101 | /* Callbacks without const */ 102 | typedef struct { 103 | fmi2CallbackLogger logger; 104 | fmi2CallbackAllocateMemory allocateMemory; 105 | fmi2CallbackFreeMemory freeMemory; 106 | fmi2StepFinished stepFinished; 107 | fmi2ComponentEnvironment componentEnvironment; 108 | } fmi2CallbackFunctionsVar; 109 | 110 | /* FMU Instance */ 111 | typedef struct OSMPCNetworkProxy { 112 | /* Members */ 113 | char* instanceName; 114 | fmi2Type fmuType; 115 | char* fmuGUID; 116 | char* fmuResourceLocation; 117 | int visible; 118 | int loggingOn; 119 | size_t nCategories; 120 | char** loggingCategories; 121 | fmi2CallbackFunctionsVar functions; 122 | fmi2Boolean boolean_vars[FMI_BOOLEAN_VARS]; 123 | fmi2Integer integer_vars[FMI_INTEGER_VARS]; 124 | fmi2Real real_vars[FMI_REAL_VARS]; 125 | char* string_vars[FMI_STRING_VARS]; 126 | double last_time; 127 | 128 | /* Proxy Connections */ 129 | #ifdef FMU_LISTEN 130 | SOCKET tcp_proxy_listen_socket; 131 | #endif 132 | SOCKET tcp_proxy_socket; 133 | 134 | /* Buffering */ 135 | size_t output_buffer_size, prev_output_buffer_size; 136 | char *output_buffer_ptr, *prev_output_buffer_ptr; 137 | } *OSMPCNetworkProxy; 138 | 139 | /* Private File-based Logging just for Debugging */ 140 | #ifdef PRIVATE_LOG_PATH 141 | static FILE* private_log_file = NULL; 142 | #endif 143 | 144 | void fmi_verbose_log_global(const char* format, ...) 145 | { 146 | #ifdef VERBOSE_FMI_LOGGING 147 | #ifdef PRIVATE_LOG_PATH 148 | va_list ap; 149 | va_start(ap, format); 150 | if (private_log_file == NULL) 151 | private_log_file = fopen(PRIVATE_LOG_PATH,"a"); 152 | if (private_log_file != NULL) { 153 | fprintf(private_log_file,"OSMPCNetworkProxy::Global: "); 154 | vfprintf(private_log_file, format, ap); 155 | fputc('\n',private_log_file); 156 | fflush(private_log_file); 157 | } 158 | #endif 159 | #endif 160 | } 161 | 162 | void internal_log(OSMPCNetworkProxy component,const char* category, const char* format, va_list arg) 163 | { 164 | #if defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING) 165 | char buffer[1024]; 166 | #ifdef _WIN32 167 | vsnprintf_s(buffer, 1024, _TRUNCATE, format, arg); 168 | #else 169 | vsnprintf(buffer, 1024, format, arg); 170 | buffer[1023]='\0'; 171 | #endif 172 | #ifdef PRIVATE_LOG_PATH 173 | if (private_log_file == NULL) 174 | private_log_file = fopen(PRIVATE_LOG_PATH,"a"); 175 | if (private_log_file != NULL) { 176 | fprintf(private_log_file,"OSMPCNetworkProxy::%s<%p>: %s\n",component->instanceName,component,buffer); 177 | fflush(private_log_file); 178 | } 179 | #endif 180 | #ifdef PUBLIC_LOGGING 181 | if (component->loggingOn) { 182 | size_t i; 183 | int active = component->nCategories == 0; 184 | for (i=0;inCategories;i++) { 185 | if (0==strcmp(category,component->loggingCategories[i])) { 186 | active = 1; 187 | break; 188 | } 189 | } 190 | if (active) 191 | component->functions.logger(component->functions.componentEnvironment,component->instanceName,fmi2OK,category,buffer); 192 | } 193 | #endif 194 | #endif 195 | } 196 | 197 | void fmi_verbose_log(OSMPCNetworkProxy component,const char* format, ...) 198 | { 199 | #if defined(VERBOSE_FMI_LOGGING) && (defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING)) 200 | va_list ap; 201 | va_start(ap, format); 202 | internal_log(component,"FMI",format,ap); 203 | va_end(ap); 204 | #endif 205 | } 206 | 207 | /* Normal Logging */ 208 | void normal_log(OSMPCNetworkProxy component, const char* category, const char* format, ...) { 209 | #if defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING) 210 | va_list ap; 211 | va_start(ap, format); 212 | internal_log(component,category,format,ap); 213 | va_end(ap); 214 | #endif 215 | } 216 | -------------------------------------------------------------------------------- /examples/OSMPCNetworkProxy/OSMPCNetworkProxyConfig.in.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #cmakedefine PUBLIC_LOGGING 12 | #cmakedefine PRIVATE_LOG_PATH "@PRIVATE_LOG_PATH@" 13 | #cmakedefine VERBOSE_FMI_LOGGING 14 | #cmakedefine DEBUG_BREAKS 15 | #define FMU_GUID "@FMUGUID@" 16 | 17 | #cmakedefine FMU_LISTEN 18 | #define FMU_DEFAULT_ADDRESS "@FMU_DEFAULT_ADDRESS@" 19 | #define FMU_DEFAULT_PORT "@FMU_DEFAULT_PORT@" 20 | -------------------------------------------------------------------------------- /examples/OSMPCNetworkProxy/modelDescription.in.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /examples/OSMPDummySensor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(OSMPDummySensor) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(LINK_WITH_SHARED_OSI OFF CACHE BOOL "Link FMU with shared OSI library instead of statically linking") 7 | set(PUBLIC_LOGGING OFF CACHE BOOL "Enable logging via FMI logger") 8 | set(PRIVATE_LOGGING OFF CACHE BOOL "Enable private logging to file") 9 | if(WIN32) 10 | set(PRIVATE_LOG_PATH "C:/TEMP/OSMPDummySensorLog.log" CACHE FILEPATH "Path to write private log file to") 11 | else() 12 | set(PRIVATE_LOG_PATH "/tmp/OSMPDummySensorLog.log" CACHE FILEPATH "Path to write private log file to") 13 | endif() 14 | if(PRIVATE_LOGGING) 15 | file(TO_NATIVE_PATH ${PRIVATE_LOG_PATH} PRIVATE_LOG_PATH_NATIVE) 16 | string(REPLACE "\\" "\\\\" PRIVATE_LOG_PATH ${PRIVATE_LOG_PATH_NATIVE}) 17 | endif() 18 | set(VERBOSE_FMI_LOGGING OFF CACHE BOOL "Enable detailed FMI function logging") 19 | set(DEBUG_BREAKS OFF CACHE BOOL "Enable debugger traps for debug builds of FMU") 20 | 21 | string(TIMESTAMP FMUTIMESTAMP UTC) 22 | string(MD5 FMUGUID modelDescription.in.xml) 23 | configure_file(modelDescription.in.xml modelDescription.xml @ONLY) 24 | configure_file(OSMPDummySensorConfig.in.h OSMPDummySensorConfig.h) 25 | 26 | find_package(Protobuf 2.6.1 REQUIRED) 27 | add_library(OSMPDummySensor SHARED OSMPDummySensor.cpp) 28 | set_target_properties(OSMPDummySensor PROPERTIES PREFIX "") 29 | target_compile_definitions(OSMPDummySensor PRIVATE "FMU_SHARED_OBJECT") 30 | if(LINK_WITH_SHARED_OSI) 31 | target_link_libraries(OSMPDummySensor open_simulation_interface) 32 | else() 33 | target_link_libraries(OSMPDummySensor open_simulation_interface_pic) 34 | endif() 35 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 36 | 37 | if(WIN32) 38 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 39 | set(FMI_BINARIES_PLATFORM "win64") 40 | else() 41 | set(FMI_BINARIES_PLATFORM "win32") 42 | endif() 43 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") 44 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 45 | set(FMI_BINARIES_PLATFORM "linux64") 46 | else() 47 | set(FMI_BINARIES_PLATFORM "linux32") 48 | endif() 49 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 50 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 51 | set(FMI_BINARIES_PLATFORM "darwin64") 52 | else() 53 | set(FMI_BINARIES_PLATFORM "darwin32") 54 | endif() 55 | endif() 56 | 57 | add_custom_command(TARGET OSMPDummySensor 58 | POST_BUILD 59 | COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" 60 | COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources" 61 | COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}" 62 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/modelDescription.xml" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" 63 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/OSMPDummySensor.cpp" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/" 64 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/OSMPDummySensor.h" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/" 65 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/OSMPDummySensorConfig.h" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/OSMPDummySensorConfig.h" 66 | COMMAND ${CMAKE_COMMAND} -E copy $ $<$:$<$:$>> "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}" 67 | COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" ${CMAKE_COMMAND} -E tar "cfv" "../OSMPDummySensor.fmu" --format=zip "modelDescription.xml" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}") 68 | -------------------------------------------------------------------------------- /examples/OSMPDummySensor/OSMPDummySensor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #include "OSMPDummySensorConfig.h" 12 | 13 | using namespace std; 14 | 15 | #ifndef FMU_SHARED_OBJECT 16 | #define FMI2_FUNCTION_PREFIX OSMPDummySensor_ 17 | #endif 18 | #include "fmi2Functions.h" 19 | 20 | /* 21 | * Logging Control 22 | * 23 | * Logging is controlled via three definitions: 24 | * 25 | * - If PRIVATE_LOG_PATH is defined it gives the name of a file 26 | * that is to be used as a private log file. 27 | * - If PUBLIC_LOGGING is defined then we will (also) log to 28 | * the FMI logging facility where appropriate. 29 | * - If VERBOSE_FMI_LOGGING is defined then logging of basic 30 | * FMI calls is enabled, which can get very verbose. 31 | */ 32 | 33 | /* 34 | * Variable Definitions 35 | * 36 | * Define FMI_*_LAST_IDX to the zero-based index of the last variable 37 | * of the given type (0 if no variables of the type exist). This 38 | * ensures proper space allocation, initialisation and handling of 39 | * the given variables in the template code. Optionally you can 40 | * define FMI_TYPENAME_VARNAME_IDX definitions (e.g. FMI_REAL_MYVAR_IDX) 41 | * to refer to individual variables inside your code, or for example 42 | * FMI_REAL_MYARRAY_OFFSET and FMI_REAL_MYARRAY_SIZE definitions for 43 | * array variables. 44 | */ 45 | 46 | /* Boolean Variables */ 47 | #define FMI_BOOLEAN_VALID_IDX 0 48 | #define FMI_BOOLEAN_LAST_IDX FMI_BOOLEAN_VALID_IDX 49 | #define FMI_BOOLEAN_VARS (FMI_BOOLEAN_LAST_IDX+1) 50 | 51 | /* Integer Variables */ 52 | #define FMI_INTEGER_SENSORVIEW_IN_BASELO_IDX 0 53 | #define FMI_INTEGER_SENSORVIEW_IN_BASEHI_IDX 1 54 | #define FMI_INTEGER_SENSORVIEW_IN_SIZE_IDX 2 55 | #define FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX 3 56 | #define FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX 4 57 | #define FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX 5 58 | #define FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASELO_IDX 6 59 | #define FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASEHI_IDX 7 60 | #define FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_SIZE_IDX 8 61 | #define FMI_INTEGER_SENSORVIEW_CONFIG_BASELO_IDX 9 62 | #define FMI_INTEGER_SENSORVIEW_CONFIG_BASEHI_IDX 10 63 | #define FMI_INTEGER_SENSORVIEW_CONFIG_SIZE_IDX 11 64 | #define FMI_INTEGER_COUNT_IDX 12 65 | #define FMI_INTEGER_LAST_IDX FMI_INTEGER_COUNT_IDX 66 | #define FMI_INTEGER_VARS (FMI_INTEGER_LAST_IDX+1) 67 | 68 | /* Real Variables */ 69 | #define FMI_REAL_NOMINAL_RANGE_IDX 0 70 | #define FMI_REAL_LAST_IDX FMI_REAL_NOMINAL_RANGE_IDX 71 | #define FMI_REAL_VARS (FMI_REAL_LAST_IDX+1) 72 | 73 | /* String Variables */ 74 | #define FMI_STRING_LAST_IDX 0 75 | #define FMI_STRING_VARS (FMI_STRING_LAST_IDX+1) 76 | 77 | #include 78 | #include 79 | #include 80 | #include 81 | #include 82 | 83 | #undef min 84 | #undef max 85 | #include "osi_sensorview.pb.h" 86 | #include "osi_sensordata.pb.h" 87 | 88 | /* FMU Class */ 89 | class COSMPDummySensor { 90 | public: 91 | /* FMI2 Interface mapped to C++ */ 92 | COSMPDummySensor(fmi2String theinstanceName, fmi2Type thefmuType, fmi2String thefmuGUID, fmi2String thefmuResourceLocation, const fmi2CallbackFunctions* thefunctions, fmi2Boolean thevisible, fmi2Boolean theloggingOn); 93 | ~COSMPDummySensor(); 94 | fmi2Status SetDebugLogging(fmi2Boolean theloggingOn,size_t nCategories, const fmi2String categories[]); 95 | static fmi2Component Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, fmi2String fmuResourceLocation, const fmi2CallbackFunctions* functions, fmi2Boolean visible, fmi2Boolean loggingOn); 96 | fmi2Status SetupExperiment(fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime); 97 | fmi2Status EnterInitializationMode(); 98 | fmi2Status ExitInitializationMode(); 99 | fmi2Status DoStep(fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component); 100 | fmi2Status Terminate(); 101 | fmi2Status Reset(); 102 | void FreeInstance(); 103 | fmi2Status GetReal(const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); 104 | fmi2Status GetInteger(const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); 105 | fmi2Status GetBoolean(const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); 106 | fmi2Status GetString(const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); 107 | fmi2Status SetReal(const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); 108 | fmi2Status SetInteger(const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); 109 | fmi2Status SetBoolean(const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); 110 | fmi2Status SetString(const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); 111 | 112 | protected: 113 | /* Internal Implementation */ 114 | fmi2Status doInit(); 115 | fmi2Status doStart(fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime); 116 | fmi2Status doEnterInitializationMode(); 117 | fmi2Status doExitInitializationMode(); 118 | fmi2Status doCalc(fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component); 119 | fmi2Status doTerm(); 120 | void doFree(); 121 | 122 | protected: 123 | /* Private File-based Logging just for Debugging */ 124 | #ifdef PRIVATE_LOG_PATH 125 | static ofstream private_log_file; 126 | #endif 127 | 128 | static void fmi_verbose_log_global(const char* format, ...) { 129 | #ifdef VERBOSE_FMI_LOGGING 130 | #ifdef PRIVATE_LOG_PATH 131 | va_list ap; 132 | va_start(ap, format); 133 | char buffer[1024]; 134 | if (!private_log_file.is_open()) 135 | private_log_file.open(PRIVATE_LOG_PATH, ios::out | ios::app); 136 | if (private_log_file.is_open()) { 137 | #ifdef _WIN32 138 | vsnprintf_s(buffer, 1024, format, ap); 139 | #else 140 | vsnprintf(buffer, 1024, format, ap); 141 | #endif 142 | private_log_file << "OSMPDummySensor" << "::Global:FMI: " << buffer << endl; 143 | private_log_file.flush(); 144 | } 145 | #endif 146 | #endif 147 | } 148 | 149 | void internal_log(const char* category, const char* format, va_list arg) 150 | { 151 | #if defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING) 152 | char buffer[1024]; 153 | #ifdef _WIN32 154 | vsnprintf_s(buffer, 1024, format, arg); 155 | #else 156 | vsnprintf(buffer, 1024, format, arg); 157 | #endif 158 | #ifdef PRIVATE_LOG_PATH 159 | if (!private_log_file.is_open()) 160 | private_log_file.open(PRIVATE_LOG_PATH, ios::out | ios::app); 161 | if (private_log_file.is_open()) { 162 | private_log_file << "OSMPDummySensor" << "::" << instanceName << "<" << ((void*)this) << ">:" << category << ": " << buffer << endl; 163 | private_log_file.flush(); 164 | } 165 | #endif 166 | #ifdef PUBLIC_LOGGING 167 | if (loggingOn && loggingCategories.count(category)) 168 | functions.logger(functions.componentEnvironment,instanceName.c_str(),fmi2OK,category,buffer); 169 | #endif 170 | #endif 171 | } 172 | 173 | void fmi_verbose_log(const char* format, ...) { 174 | #if defined(VERBOSE_FMI_LOGGING) && (defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING)) 175 | va_list ap; 176 | va_start(ap, format); 177 | internal_log("FMI",format,ap); 178 | va_end(ap); 179 | #endif 180 | } 181 | 182 | /* Normal Logging */ 183 | void normal_log(const char* category, const char* format, ...) { 184 | #if defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING) 185 | va_list ap; 186 | va_start(ap, format); 187 | internal_log(category,format,ap); 188 | va_end(ap); 189 | #endif 190 | } 191 | 192 | protected: 193 | /* Members */ 194 | string instanceName; 195 | fmi2Type fmuType; 196 | string fmuGUID; 197 | string fmuResourceLocation; 198 | bool visible; 199 | bool loggingOn; 200 | set loggingCategories; 201 | fmi2CallbackFunctions functions; 202 | fmi2Boolean boolean_vars[FMI_BOOLEAN_VARS]; 203 | fmi2Integer integer_vars[FMI_INTEGER_VARS]; 204 | fmi2Real real_vars[FMI_REAL_VARS]; 205 | string string_vars[FMI_STRING_VARS]; 206 | bool simulation_started; 207 | string* currentOutputBuffer; 208 | string* lastOutputBuffer; 209 | string* currentConfigRequestBuffer; 210 | string* lastConfigRequestBuffer; 211 | 212 | /* Simple Accessors */ 213 | fmi2Boolean fmi_valid() { return boolean_vars[FMI_BOOLEAN_VALID_IDX]; } 214 | void set_fmi_valid(fmi2Boolean value) { boolean_vars[FMI_BOOLEAN_VALID_IDX]=value; } 215 | fmi2Integer fmi_count() { return integer_vars[FMI_INTEGER_COUNT_IDX]; } 216 | void set_fmi_count(fmi2Integer value) { integer_vars[FMI_INTEGER_COUNT_IDX]=value; } 217 | fmi2Real fmi_nominal_range() { return real_vars[FMI_REAL_NOMINAL_RANGE_IDX]; } 218 | void set_fmi_nominal_range(fmi2Real value) { real_vars[FMI_REAL_NOMINAL_RANGE_IDX]=value; } 219 | 220 | 221 | /* Protocol Buffer Accessors */ 222 | bool get_fmi_sensor_view_config(osi3::SensorViewConfiguration& data); 223 | void set_fmi_sensor_view_config_request(const osi3::SensorViewConfiguration& data); 224 | void reset_fmi_sensor_view_config_request(); 225 | bool get_fmi_sensor_view_in(osi3::SensorView& data); 226 | void set_fmi_sensor_data_out(const osi3::SensorData& data); 227 | void reset_fmi_sensor_data_out(); 228 | 229 | /* Refreshing of Calculated Parameters */ 230 | void refresh_fmi_sensor_view_config_request(); 231 | }; 232 | -------------------------------------------------------------------------------- /examples/OSMPDummySensor/OSMPDummySensorConfig.in.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #cmakedefine PUBLIC_LOGGING 12 | #cmakedefine PRIVATE_LOG_PATH "@PRIVATE_LOG_PATH@" 13 | #cmakedefine VERBOSE_FMI_LOGGING 14 | #cmakedefine DEBUG_BREAKS 15 | #define FMU_GUID "@FMUGUID@" 16 | -------------------------------------------------------------------------------- /examples/OSMPDummySensor/modelDescription.in.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /examples/OSMPDummySource/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(OSMPDummySource) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(LINK_WITH_SHARED_OSI OFF CACHE BOOL "Link FMU with shared OSI library instead of statically linking") 7 | set(PUBLIC_LOGGING OFF CACHE BOOL "Enable logging via FMI logger") 8 | set(PRIVATE_LOGGING OFF CACHE BOOL "Enable private logging to file") 9 | if(WIN32) 10 | set(PRIVATE_LOG_PATH_SOURCE "C:/TEMP/OSMPDummySourceLog.log" CACHE FILEPATH "Path to write private log file to") 11 | else() 12 | set(PRIVATE_LOG_PATH_SOURCE "/tmp/OSMPDummySourceLog.log" CACHE FILEPATH "Path to write private log file to") 13 | endif() 14 | if(PRIVATE_LOGGING) 15 | file(TO_NATIVE_PATH ${PRIVATE_LOG_PATH_SOURCE} PRIVATE_LOG_PATH_SOURCE_NATIVE) 16 | string(REPLACE "\\" "\\\\" PRIVATE_LOG_PATH ${PRIVATE_LOG_PATH_SOURCE_NATIVE}) 17 | endif() 18 | set(VERBOSE_FMI_LOGGING OFF CACHE BOOL "Enable detailed FMI function logging") 19 | set(DEBUG_BREAKS OFF CACHE BOOL "Enable debugger traps for debug builds of FMU") 20 | 21 | string(TIMESTAMP FMUTIMESTAMP UTC) 22 | string(MD5 FMUGUID modelDescription.in.xml) 23 | configure_file(modelDescription.in.xml modelDescription.xml @ONLY) 24 | configure_file(OSMPDummySourceConfig.in.h OSMPDummySourceConfig.h) 25 | 26 | find_package(Protobuf 2.6.1 REQUIRED) 27 | add_library(OSMPDummySource SHARED OSMPDummySource.cpp) 28 | set_target_properties(OSMPDummySource PROPERTIES PREFIX "") 29 | target_compile_definitions(OSMPDummySource PRIVATE "FMU_SHARED_OBJECT") 30 | if(LINK_WITH_SHARED_OSI) 31 | target_link_libraries(OSMPDummySource open_simulation_interface) 32 | else() 33 | target_link_libraries(OSMPDummySource open_simulation_interface_pic) 34 | endif() 35 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 36 | 37 | if(WIN32) 38 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 39 | set(FMI_BINARIES_PLATFORM "win64") 40 | else() 41 | set(FMI_BINARIES_PLATFORM "win32") 42 | endif() 43 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") 44 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 45 | set(FMI_BINARIES_PLATFORM "linux64") 46 | else() 47 | set(FMI_BINARIES_PLATFORM "linux32") 48 | endif() 49 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 50 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 51 | set(FMI_BINARIES_PLATFORM "darwin64") 52 | else() 53 | set(FMI_BINARIES_PLATFORM "darwin32") 54 | endif() 55 | endif() 56 | 57 | add_custom_command(TARGET OSMPDummySource 58 | POST_BUILD 59 | COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" 60 | COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources" 61 | COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}" 62 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/modelDescription.xml" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" 63 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/OSMPDummySource.cpp" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/" 64 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/OSMPDummySource.h" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/" 65 | COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/OSMPDummySourceConfig.h" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources/OSMPDummySourceConfig.h" 66 | COMMAND ${CMAKE_COMMAND} -E copy $ $<$:$<$:$>> "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}" 67 | COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/buildfmu" ${CMAKE_COMMAND} -E tar "cfv" "../OSMPDummySource.fmu" --format=zip "modelDescription.xml" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/sources" "${CMAKE_CURRENT_BINARY_DIR}/buildfmu/binaries/${FMI_BINARIES_PLATFORM}") 68 | -------------------------------------------------------------------------------- /examples/OSMPDummySource/OSMPDummySource.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #include "OSMPDummySource.h" 12 | 13 | /* 14 | * Debug Breaks 15 | * 16 | * If you define DEBUG_BREAKS the FMU will automatically break 17 | * into an attached Debugger on all major computation functions. 18 | * Note that the FMU is likely to break all environments if no 19 | * Debugger is actually attached when the breaks are triggered. 20 | */ 21 | #if defined(DEBUG_BREAKS) && !defined(NDEBUG) 22 | #if defined(__has_builtin) && !defined(__ibmxl__) 23 | #if __has_builtin(__builtin_debugtrap) 24 | #define DEBUGBREAK() __builtin_debugtrap() 25 | #elif __has_builtin(__debugbreak) 26 | #define DEBUGBREAK() __debugbreak() 27 | #endif 28 | #endif 29 | #if !defined(DEBUGBREAK) 30 | #if defined(_MSC_VER) || defined(__INTEL_COMPILER) 31 | #include 32 | #define DEBUGBREAK() __debugbreak() 33 | #else 34 | #include 35 | #if defined(SIGTRAP) 36 | #define DEBUGBREAK() raise(SIGTRAP) 37 | #else 38 | #define DEBUGBREAK() raise(SIGABRT) 39 | #endif 40 | #endif 41 | #endif 42 | #else 43 | #define DEBUGBREAK() 44 | #endif 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | using namespace std; 53 | 54 | #ifdef PRIVATE_LOG_PATH 55 | ofstream COSMPDummySource::private_log_file; 56 | #endif 57 | 58 | /* 59 | * ProtocolBuffer Accessors 60 | */ 61 | 62 | void* decode_integer_to_pointer(fmi2Integer hi,fmi2Integer lo) 63 | { 64 | #if PTRDIFF_MAX == INT64_MAX 65 | union addrconv { 66 | struct { 67 | int lo; 68 | int hi; 69 | } base; 70 | unsigned long long address; 71 | } myaddr; 72 | myaddr.base.lo=lo; 73 | myaddr.base.hi=hi; 74 | return reinterpret_cast(myaddr.address); 75 | #elif PTRDIFF_MAX == INT32_MAX 76 | return reinterpret_cast(lo); 77 | #else 78 | #error "Cannot determine 32bit or 64bit environment!" 79 | #endif 80 | } 81 | 82 | void encode_pointer_to_integer(const void* ptr,fmi2Integer& hi,fmi2Integer& lo) 83 | { 84 | #if PTRDIFF_MAX == INT64_MAX 85 | union addrconv { 86 | struct { 87 | int lo; 88 | int hi; 89 | } base; 90 | unsigned long long address; 91 | } myaddr; 92 | myaddr.address=reinterpret_cast(ptr); 93 | hi=myaddr.base.hi; 94 | lo=myaddr.base.lo; 95 | #elif PTRDIFF_MAX == INT32_MAX 96 | hi=0; 97 | lo=reinterpret_cast(ptr); 98 | #else 99 | #error "Cannot determine 32bit or 64bit environment!" 100 | #endif 101 | } 102 | 103 | void COSMPDummySource::set_fmi_sensor_view_out(const osi3::SensorView& data) 104 | { 105 | data.SerializeToString(currentBuffer); 106 | encode_pointer_to_integer(currentBuffer->data(),integer_vars[FMI_INTEGER_SENSORVIEW_OUT_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORVIEW_OUT_BASELO_IDX]); 107 | integer_vars[FMI_INTEGER_SENSORVIEW_OUT_SIZE_IDX]=(fmi2Integer)currentBuffer->length(); 108 | normal_log("OSMP","Providing %08X %08X, writing from %p ...",integer_vars[FMI_INTEGER_SENSORVIEW_OUT_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORVIEW_OUT_BASELO_IDX],currentBuffer->data()); 109 | swap(currentBuffer,lastBuffer); 110 | } 111 | 112 | void COSMPDummySource::reset_fmi_sensor_view_out() 113 | { 114 | integer_vars[FMI_INTEGER_SENSORVIEW_OUT_SIZE_IDX]=0; 115 | integer_vars[FMI_INTEGER_SENSORVIEW_OUT_BASEHI_IDX]=0; 116 | integer_vars[FMI_INTEGER_SENSORVIEW_OUT_BASELO_IDX]=0; 117 | } 118 | 119 | /* 120 | * Actual Core Content 121 | */ 122 | 123 | fmi2Status COSMPDummySource::doInit() 124 | { 125 | DEBUGBREAK(); 126 | 127 | /* Booleans */ 128 | for (int i = 0; iCopyFrom(osi3::InterfaceVersion::descriptor()->file()->options().GetExtension(osi3::current_interface_version)); 194 | currentOut.mutable_sensor_id()->set_value(10000); 195 | currentOut.mutable_host_vehicle_id()->set_value(14); 196 | osi3::GroundTruth *currentGT = currentOut.mutable_global_ground_truth(); 197 | currentOut.mutable_timestamp()->set_seconds((long long int)floor(time)); 198 | currentOut.mutable_timestamp()->set_nanos((int)((time - floor(time))*1000000000.0)); 199 | currentGT->mutable_timestamp()->set_seconds((long long int)floor(time)); 200 | currentGT->mutable_timestamp()->set_nanos((int)((time - floor(time))*1000000000.0)); 201 | currentGT->mutable_host_vehicle_id()->set_value(14); 202 | 203 | // Vehicles 204 | for (unsigned int i=0;i<10;i++) { 205 | osi3::MovingObject *veh = currentGT->add_moving_object(); 206 | veh->mutable_id()->set_value(10+i); 207 | veh->set_type(osi3::MovingObject_Type_TYPE_VEHICLE); 208 | auto vehclass = veh->mutable_vehicle_classification(); 209 | vehclass->set_type(source_veh_types[i]); 210 | auto vehlights = vehclass->mutable_light_state(); 211 | vehlights->set_indicator_state(osi3::MovingObject_VehicleClassification_LightState_IndicatorState_INDICATOR_STATE_OFF); 212 | vehlights->set_brake_light_state(osi3::MovingObject_VehicleClassification_LightState_BrakeLightState_BRAKE_LIGHT_STATE_OFF); 213 | veh->mutable_base()->mutable_dimension()->set_height(1.5); 214 | veh->mutable_base()->mutable_dimension()->set_width(2.0); 215 | veh->mutable_base()->mutable_dimension()->set_length(5.0); 216 | veh->mutable_base()->mutable_position()->set_x(source_x_offsets[i]+time*source_x_speeds[i]); 217 | veh->mutable_base()->mutable_position()->set_y(source_y_offsets[i]+sin(time/source_x_speeds[i])*0.25); 218 | veh->mutable_base()->mutable_position()->set_z(0.0); 219 | veh->mutable_base()->mutable_velocity()->set_x(source_x_speeds[i]); 220 | veh->mutable_base()->mutable_velocity()->set_y(cos(time/source_x_speeds[i])*0.25/source_x_speeds[i]); 221 | veh->mutable_base()->mutable_velocity()->set_z(0.0); 222 | veh->mutable_base()->mutable_acceleration()->set_x(0.0); 223 | veh->mutable_base()->mutable_acceleration()->set_y(-sin(time/source_x_speeds[i])*0.25/(source_x_speeds[i]*source_x_speeds[i])); 224 | veh->mutable_base()->mutable_acceleration()->set_z(0.0); 225 | veh->mutable_base()->mutable_orientation()->set_pitch(0.0); 226 | veh->mutable_base()->mutable_orientation()->set_roll(0.0); 227 | veh->mutable_base()->mutable_orientation()->set_yaw(0.0); 228 | veh->mutable_base()->mutable_orientation_rate()->set_pitch(0.0); 229 | veh->mutable_base()->mutable_orientation_rate()->set_roll(0.0); 230 | veh->mutable_base()->mutable_orientation_rate()->set_yaw(0.0); 231 | normal_log("OSI","GT: Adding Vehicle %d[%llu] Absolute Position: %f,%f,%f Velocity (%f,%f,%f)",i,veh->id().value(),veh->base().position().x(),veh->base().position().y(),veh->base().position().z(),veh->base().velocity().x(),veh->base().velocity().y(),veh->base().velocity().z()); 232 | } 233 | 234 | set_fmi_sensor_view_out(currentOut); 235 | set_fmi_valid(true); 236 | set_fmi_count(currentGT->moving_object_size()); 237 | return fmi2OK; 238 | } 239 | 240 | fmi2Status COSMPDummySource::doTerm() 241 | { 242 | DEBUGBREAK(); 243 | return fmi2OK; 244 | } 245 | 246 | void COSMPDummySource::doFree() 247 | { 248 | DEBUGBREAK(); 249 | } 250 | 251 | /* 252 | * Generic C++ Wrapper Code 253 | */ 254 | 255 | COSMPDummySource::COSMPDummySource(fmi2String theinstanceName, fmi2Type thefmuType, fmi2String thefmuGUID, fmi2String thefmuResourceLocation, const fmi2CallbackFunctions* thefunctions, fmi2Boolean thevisible, fmi2Boolean theloggingOn) 256 | : instanceName(theinstanceName), 257 | fmuType(thefmuType), 258 | fmuGUID(thefmuGUID), 259 | fmuResourceLocation(thefmuResourceLocation), 260 | functions(*thefunctions), 261 | visible(!!thevisible), 262 | loggingOn(!!theloggingOn) 263 | { 264 | currentBuffer = new string(); 265 | lastBuffer = new string(); 266 | loggingCategories.clear(); 267 | loggingCategories.insert("FMI"); 268 | loggingCategories.insert("OSMP"); 269 | loggingCategories.insert("OSI"); 270 | } 271 | 272 | COSMPDummySource::~COSMPDummySource() 273 | { 274 | delete currentBuffer; 275 | delete lastBuffer; 276 | } 277 | 278 | fmi2Status COSMPDummySource::SetDebugLogging(fmi2Boolean theloggingOn, size_t nCategories, const fmi2String categories[]) 279 | { 280 | fmi_verbose_log("fmi2SetDebugLogging(%s)", theloggingOn ? "true" : "false"); 281 | loggingOn = theloggingOn ? true : false; 282 | if (categories && (nCategories > 0)) { 283 | loggingCategories.clear(); 284 | for (size_t i=0;i", 309 | "FUNCTIONS", visible, loggingOn); 310 | return NULL; 311 | } 312 | 313 | if (myc->doInit() != fmi2OK) { 314 | fmi_verbose_log_global("fmi2Instantiate(\"%s\",%d,\"%s\",\"%s\",\"%s\",%d,%d) = NULL (doInit failure)", 315 | instanceName, fmuType, fmuGUID, 316 | (fmuResourceLocation != NULL) ? fmuResourceLocation : "", 317 | "FUNCTIONS", visible, loggingOn); 318 | delete myc; 319 | return NULL; 320 | } 321 | else { 322 | fmi_verbose_log_global("fmi2Instantiate(\"%s\",%d,\"%s\",\"%s\",\"%s\",%d,%d) = %p", 323 | instanceName, fmuType, fmuGUID, 324 | (fmuResourceLocation != NULL) ? fmuResourceLocation : "", 325 | "FUNCTIONS", visible, loggingOn, myc); 326 | return (fmi2Component)myc; 327 | } 328 | } 329 | 330 | fmi2Status COSMPDummySource::SetupExperiment(fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) 331 | { 332 | fmi_verbose_log("fmi2SetupExperiment(%d,%g,%g,%d,%g)", toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); 333 | return doStart(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); 334 | } 335 | 336 | fmi2Status COSMPDummySource::EnterInitializationMode() 337 | { 338 | fmi_verbose_log("fmi2EnterInitializationMode()"); 339 | return doEnterInitializationMode(); 340 | } 341 | 342 | fmi2Status COSMPDummySource::ExitInitializationMode() 343 | { 344 | fmi_verbose_log("fmi2ExitInitializationMode()"); 345 | return doExitInitializationMode(); 346 | } 347 | 348 | fmi2Status COSMPDummySource::DoStep(fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component) 349 | { 350 | fmi_verbose_log("fmi2DoStep(%g,%g,%d)", currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPointfmi2Component); 351 | return doCalc(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPointfmi2Component); 352 | } 353 | 354 | fmi2Status COSMPDummySource::Terminate() 355 | { 356 | fmi_verbose_log("fmi2Terminate()"); 357 | return doTerm(); 358 | } 359 | 360 | fmi2Status COSMPDummySource::Reset() 361 | { 362 | fmi_verbose_log("fmi2Reset()"); 363 | 364 | doFree(); 365 | return doInit(); 366 | } 367 | 368 | void COSMPDummySource::FreeInstance() 369 | { 370 | fmi_verbose_log("fmi2FreeInstance()"); 371 | doFree(); 372 | } 373 | 374 | fmi2Status COSMPDummySource::GetReal(const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) 375 | { 376 | fmi_verbose_log("fmi2GetReal(...)"); 377 | for (size_t i = 0; iSetDebugLogging(loggingOn, nCategories, categories); 490 | } 491 | 492 | /* 493 | * Functions for Co-Simulation 494 | */ 495 | FMI2_Export fmi2Component fmi2Instantiate(fmi2String instanceName, 496 | fmi2Type fmuType, 497 | fmi2String fmuGUID, 498 | fmi2String fmuResourceLocation, 499 | const fmi2CallbackFunctions* functions, 500 | fmi2Boolean visible, 501 | fmi2Boolean loggingOn) 502 | { 503 | return COSMPDummySource::Instantiate(instanceName, fmuType, fmuGUID, fmuResourceLocation, functions, visible, loggingOn); 504 | } 505 | 506 | FMI2_Export fmi2Status fmi2SetupExperiment(fmi2Component c, 507 | fmi2Boolean toleranceDefined, 508 | fmi2Real tolerance, 509 | fmi2Real startTime, 510 | fmi2Boolean stopTimeDefined, 511 | fmi2Real stopTime) 512 | { 513 | COSMPDummySource* myc = (COSMPDummySource*)c; 514 | return myc->SetupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); 515 | } 516 | 517 | FMI2_Export fmi2Status fmi2EnterInitializationMode(fmi2Component c) 518 | { 519 | COSMPDummySource* myc = (COSMPDummySource*)c; 520 | return myc->EnterInitializationMode(); 521 | } 522 | 523 | FMI2_Export fmi2Status fmi2ExitInitializationMode(fmi2Component c) 524 | { 525 | COSMPDummySource* myc = (COSMPDummySource*)c; 526 | return myc->ExitInitializationMode(); 527 | } 528 | 529 | FMI2_Export fmi2Status fmi2DoStep(fmi2Component c, 530 | fmi2Real currentCommunicationPoint, 531 | fmi2Real communicationStepSize, 532 | fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component) 533 | { 534 | COSMPDummySource* myc = (COSMPDummySource*)c; 535 | return myc->DoStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPointfmi2Component); 536 | } 537 | 538 | FMI2_Export fmi2Status fmi2Terminate(fmi2Component c) 539 | { 540 | COSMPDummySource* myc = (COSMPDummySource*)c; 541 | return myc->Terminate(); 542 | } 543 | 544 | FMI2_Export fmi2Status fmi2Reset(fmi2Component c) 545 | { 546 | COSMPDummySource* myc = (COSMPDummySource*)c; 547 | return myc->Reset(); 548 | } 549 | 550 | FMI2_Export void fmi2FreeInstance(fmi2Component c) 551 | { 552 | COSMPDummySource* myc = (COSMPDummySource*)c; 553 | myc->FreeInstance(); 554 | delete myc; 555 | } 556 | 557 | /* 558 | * Data Exchange Functions 559 | */ 560 | FMI2_Export fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) 561 | { 562 | COSMPDummySource* myc = (COSMPDummySource*)c; 563 | return myc->GetReal(vr, nvr, value); 564 | } 565 | 566 | FMI2_Export fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) 567 | { 568 | COSMPDummySource* myc = (COSMPDummySource*)c; 569 | return myc->GetInteger(vr, nvr, value); 570 | } 571 | 572 | FMI2_Export fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) 573 | { 574 | COSMPDummySource* myc = (COSMPDummySource*)c; 575 | return myc->GetBoolean(vr, nvr, value); 576 | } 577 | 578 | FMI2_Export fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) 579 | { 580 | COSMPDummySource* myc = (COSMPDummySource*)c; 581 | return myc->GetString(vr, nvr, value); 582 | } 583 | 584 | FMI2_Export fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) 585 | { 586 | COSMPDummySource* myc = (COSMPDummySource*)c; 587 | return myc->SetReal(vr, nvr, value); 588 | } 589 | 590 | FMI2_Export fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) 591 | { 592 | COSMPDummySource* myc = (COSMPDummySource*)c; 593 | return myc->SetInteger(vr, nvr, value); 594 | } 595 | 596 | FMI2_Export fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) 597 | { 598 | COSMPDummySource* myc = (COSMPDummySource*)c; 599 | return myc->SetBoolean(vr, nvr, value); 600 | } 601 | 602 | FMI2_Export fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) 603 | { 604 | COSMPDummySource* myc = (COSMPDummySource*)c; 605 | return myc->SetString(vr, nvr, value); 606 | } 607 | 608 | /* 609 | * Unsupported Features (FMUState, Derivatives, Async DoStep, Status Enquiries) 610 | */ 611 | FMI2_Export fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) 612 | { 613 | return fmi2Error; 614 | } 615 | 616 | FMI2_Export fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) 617 | { 618 | return fmi2Error; 619 | } 620 | 621 | FMI2_Export fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) 622 | { 623 | return fmi2Error; 624 | } 625 | 626 | FMI2_Export fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) 627 | { 628 | return fmi2Error; 629 | } 630 | 631 | FMI2_Export fmi2Status fmi2SerializeFMUstate (fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) 632 | { 633 | return fmi2Error; 634 | } 635 | 636 | FMI2_Export fmi2Status fmi2DeSerializeFMUstate (fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) 637 | { 638 | return fmi2Error; 639 | } 640 | 641 | FMI2_Export fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, 642 | const fmi2ValueReference vUnknown_ref[], size_t nUnknown, 643 | const fmi2ValueReference vKnown_ref[] , size_t nKnown, 644 | const fmi2Real dvKnown[], 645 | fmi2Real dvUnknown[]) 646 | { 647 | return fmi2Error; 648 | } 649 | 650 | FMI2_Export fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, 651 | const fmi2ValueReference vr[], 652 | size_t nvr, 653 | const fmi2Integer order[], 654 | const fmi2Real value[]) 655 | { 656 | return fmi2Error; 657 | } 658 | 659 | FMI2_Export fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, 660 | const fmi2ValueReference vr[], 661 | size_t nvr, 662 | const fmi2Integer order[], 663 | fmi2Real value[]) 664 | { 665 | return fmi2Error; 666 | } 667 | 668 | FMI2_Export fmi2Status fmi2CancelStep(fmi2Component c) 669 | { 670 | return fmi2OK; 671 | } 672 | 673 | FMI2_Export fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status* value) 674 | { 675 | return fmi2Discard; 676 | } 677 | 678 | FMI2_Export fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real* value) 679 | { 680 | return fmi2Discard; 681 | } 682 | 683 | FMI2_Export fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value) 684 | { 685 | return fmi2Discard; 686 | } 687 | 688 | FMI2_Export fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value) 689 | { 690 | return fmi2Discard; 691 | } 692 | 693 | FMI2_Export fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String* value) 694 | { 695 | return fmi2Discard; 696 | } 697 | 698 | } 699 | -------------------------------------------------------------------------------- /examples/OSMPDummySource/OSMPDummySource.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #include "OSMPDummySourceConfig.h" 12 | 13 | using namespace std; 14 | 15 | #ifndef FMU_SHARED_OBJECT 16 | #define FMI2_FUNCTION_PREFIX OSMPDummySource_ 17 | #endif 18 | #include "fmi2Functions.h" 19 | 20 | /* 21 | * Logging Control 22 | * 23 | * Logging is controlled via three definitions: 24 | * 25 | * - If PRIVATE_LOG_PATH is defined it gives the name of a file 26 | * that is to be used as a private log file. 27 | * - If PUBLIC_LOGGING is defined then we will (also) log to 28 | * the FMI logging facility where appropriate. 29 | * - If VERBOSE_FMI_LOGGING is defined then logging of basic 30 | * FMI calls is enabled, which can get very verbose. 31 | */ 32 | 33 | /* 34 | * Variable Definitions 35 | * 36 | * Define FMI_*_LAST_IDX to the zero-based index of the last variable 37 | * of the given type (0 if no variables of the type exist). This 38 | * ensures proper space allocation, initialisation and handling of 39 | * the given variables in the template code. Optionally you can 40 | * define FMI_TYPENAME_VARNAME_IDX definitions (e.g. FMI_REAL_MYVAR_IDX) 41 | * to refer to individual variables inside your code, or for example 42 | * FMI_REAL_MYARRAY_OFFSET and FMI_REAL_MYARRAY_SIZE definitions for 43 | * array variables. 44 | */ 45 | 46 | /* Boolean Variables */ 47 | #define FMI_BOOLEAN_VALID_IDX 0 48 | #define FMI_BOOLEAN_LAST_IDX FMI_BOOLEAN_VALID_IDX 49 | #define FMI_BOOLEAN_VARS (FMI_BOOLEAN_LAST_IDX+1) 50 | 51 | /* Integer Variables */ 52 | #define FMI_INTEGER_SENSORVIEW_OUT_BASELO_IDX 0 53 | #define FMI_INTEGER_SENSORVIEW_OUT_BASEHI_IDX 1 54 | #define FMI_INTEGER_SENSORVIEW_OUT_SIZE_IDX 2 55 | #define FMI_INTEGER_COUNT_IDX 3 56 | #define FMI_INTEGER_LAST_IDX FMI_INTEGER_COUNT_IDX 57 | #define FMI_INTEGER_VARS (FMI_INTEGER_LAST_IDX+1) 58 | 59 | /* Real Variables */ 60 | #define FMI_REAL_LAST_IDX 0 61 | #define FMI_REAL_VARS (FMI_REAL_LAST_IDX+1) 62 | 63 | /* String Variables */ 64 | #define FMI_STRING_LAST_IDX 0 65 | #define FMI_STRING_VARS (FMI_STRING_LAST_IDX+1) 66 | 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | 73 | #undef min 74 | #undef max 75 | #include "osi_sensorview.pb.h" 76 | 77 | /* FMU Class */ 78 | class COSMPDummySource { 79 | public: 80 | /* FMI2 Interface mapped to C++ */ 81 | COSMPDummySource(fmi2String theinstanceName, fmi2Type thefmuType, fmi2String thefmuGUID, fmi2String thefmuResourceLocation, const fmi2CallbackFunctions* thefunctions, fmi2Boolean thevisible, fmi2Boolean theloggingOn); 82 | ~COSMPDummySource(); 83 | fmi2Status SetDebugLogging(fmi2Boolean theloggingOn,size_t nCategories, const fmi2String categories[]); 84 | static fmi2Component Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, fmi2String fmuResourceLocation, const fmi2CallbackFunctions* functions, fmi2Boolean visible, fmi2Boolean loggingOn); 85 | fmi2Status SetupExperiment(fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime); 86 | fmi2Status EnterInitializationMode(); 87 | fmi2Status ExitInitializationMode(); 88 | fmi2Status DoStep(fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component); 89 | fmi2Status Terminate(); 90 | fmi2Status Reset(); 91 | void FreeInstance(); 92 | fmi2Status GetReal(const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); 93 | fmi2Status GetInteger(const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); 94 | fmi2Status GetBoolean(const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); 95 | fmi2Status GetString(const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); 96 | fmi2Status SetReal(const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); 97 | fmi2Status SetInteger(const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); 98 | fmi2Status SetBoolean(const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); 99 | fmi2Status SetString(const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); 100 | 101 | protected: 102 | /* Internal Implementation */ 103 | fmi2Status doInit(); 104 | fmi2Status doStart(fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime); 105 | fmi2Status doEnterInitializationMode(); 106 | fmi2Status doExitInitializationMode(); 107 | fmi2Status doCalc(fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component); 108 | fmi2Status doTerm(); 109 | void doFree(); 110 | 111 | protected: 112 | /* Private File-based Logging just for Debugging */ 113 | #ifdef PRIVATE_LOG_PATH 114 | static ofstream private_log_file; 115 | #endif 116 | 117 | static void fmi_verbose_log_global(const char* format, ...) { 118 | #ifdef VERBOSE_FMI_LOGGING 119 | #ifdef PRIVATE_LOG_PATH 120 | va_list ap; 121 | va_start(ap, format); 122 | char buffer[1024]; 123 | if (!private_log_file.is_open()) 124 | private_log_file.open(PRIVATE_LOG_PATH, ios::out | ios::app); 125 | if (private_log_file.is_open()) { 126 | #ifdef _WIN32 127 | vsnprintf_s(buffer, 1024, format, ap); 128 | #else 129 | vsnprintf(buffer, 1024, format, ap); 130 | #endif 131 | private_log_file << "OSMPDummySource" << "::Global:FMI: " << buffer << endl; 132 | private_log_file.flush(); 133 | } 134 | #endif 135 | #endif 136 | } 137 | 138 | void internal_log(const char* category, const char* format, va_list arg) 139 | { 140 | #if defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING) 141 | char buffer[1024]; 142 | #ifdef _WIN32 143 | vsnprintf_s(buffer, 1024, format, arg); 144 | #else 145 | vsnprintf(buffer, 1024, format, arg); 146 | #endif 147 | #ifdef PRIVATE_LOG_PATH 148 | if (!private_log_file.is_open()) 149 | private_log_file.open(PRIVATE_LOG_PATH, ios::out | ios::app); 150 | if (private_log_file.is_open()) { 151 | private_log_file << "OSMPDummySource" << "::" << instanceName << "<" << ((void*)this) << ">:" << category << ": " << buffer << endl; 152 | private_log_file.flush(); 153 | } 154 | #endif 155 | #ifdef PUBLIC_LOGGING 156 | if (loggingOn && loggingCategories.count(category)) 157 | functions.logger(functions.componentEnvironment,instanceName.c_str(),fmi2OK,category,buffer); 158 | #endif 159 | #endif 160 | } 161 | 162 | void fmi_verbose_log(const char* format, ...) { 163 | #if defined(VERBOSE_FMI_LOGGING) && (defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING)) 164 | va_list ap; 165 | va_start(ap, format); 166 | internal_log("FMI",format,ap); 167 | va_end(ap); 168 | #endif 169 | } 170 | 171 | /* Normal Logging */ 172 | void normal_log(const char* category, const char* format, ...) { 173 | #if defined(PRIVATE_LOG_PATH) || defined(PUBLIC_LOGGING) 174 | va_list ap; 175 | va_start(ap, format); 176 | internal_log(category,format,ap); 177 | va_end(ap); 178 | #endif 179 | } 180 | 181 | protected: 182 | /* Members */ 183 | string instanceName; 184 | fmi2Type fmuType; 185 | string fmuGUID; 186 | string fmuResourceLocation; 187 | bool visible; 188 | bool loggingOn; 189 | set loggingCategories; 190 | fmi2CallbackFunctions functions; 191 | fmi2Boolean boolean_vars[FMI_BOOLEAN_VARS]; 192 | fmi2Integer integer_vars[FMI_INTEGER_VARS]; 193 | fmi2Real real_vars[FMI_REAL_VARS]; 194 | string string_vars[FMI_STRING_VARS]; 195 | string* currentBuffer; 196 | string* lastBuffer; 197 | 198 | /* Simple Accessors */ 199 | fmi2Boolean fmi_valid() { return boolean_vars[FMI_BOOLEAN_VALID_IDX]; } 200 | void set_fmi_valid(fmi2Boolean value) { boolean_vars[FMI_BOOLEAN_VALID_IDX]=value; } 201 | fmi2Integer fmi_count() { return integer_vars[FMI_INTEGER_COUNT_IDX]; } 202 | void set_fmi_count(fmi2Integer value) { integer_vars[FMI_INTEGER_COUNT_IDX]=value; } 203 | 204 | /* Protocol Buffer Accessors */ 205 | void set_fmi_sensor_view_out(const osi3::SensorView& data); 206 | void reset_fmi_sensor_view_out(); 207 | }; 208 | -------------------------------------------------------------------------------- /examples/OSMPDummySource/OSMPDummySourceConfig.in.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PMSF FMU Framework for FMI 2.0 Co-Simulation FMUs 3 | * 4 | * (C) 2016 -- 2018 PMSF IT Consulting Pierre R. Mai 5 | * 6 | * This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | */ 10 | 11 | #cmakedefine PUBLIC_LOGGING 12 | #cmakedefine PRIVATE_LOG_PATH "@PRIVATE_LOG_PATH@" 13 | #cmakedefine VERBOSE_FMI_LOGGING 14 | #cmakedefine DEBUG_BREAKS 15 | #define FMU_GUID "@FMUGUID@" 16 | -------------------------------------------------------------------------------- /examples/OSMPDummySource/modelDescription.in.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | OSI Sensor Model Packaging Examples 2 | =================================== 3 | 4 | The examples in this directory can be built using CMake. 5 | They require that the open-simulation-interface submodule 6 | of the repository is populated. 7 | 8 | The OSMPDummySensor example can be used as a simple dummy sensor 9 | model, demonstrating the use of OSI for sensor models consuming 10 | SensorView data and generating SensorData output. 11 | 12 | The OSMPDummySource example can be used as a simplistic source of 13 | SensorView (including GroundTruth) data, that can be connected to 14 | the input of an OSMPDummySensor model, for simple testing and 15 | demonstration purposes. 16 | 17 | The OSMPCNetworkProxy example demonstrates a simple C network proxy 18 | that can send and receive OSI data via TCP sockets. 19 | -------------------------------------------------------------------------------- /examples/includes/fmi2FunctionTypes.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenSimulationInterface/osi-sensor-model-packaging/961f01a352b8b7448bf198b659516bd623db3c4f/examples/includes/fmi2FunctionTypes.h -------------------------------------------------------------------------------- /examples/includes/fmi2Functions.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenSimulationInterface/osi-sensor-model-packaging/961f01a352b8b7448bf198b659516bd623db3c4f/examples/includes/fmi2Functions.h -------------------------------------------------------------------------------- /examples/includes/fmi2TypesPlatform.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenSimulationInterface/osi-sensor-model-packaging/961f01a352b8b7448bf198b659516bd623db3c4f/examples/includes/fmi2TypesPlatform.h -------------------------------------------------------------------------------- /examples/includes/fmiFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef fmiFunctions_h 2 | #define fmiFunctions_h 3 | 4 | /* This header file must be utilized when compiling a FMU. 5 | It defines all functions of Co-Simulation Interface. 6 | In order to have unique function names even if several FMUs 7 | are compiled together (e.g. for embedded systems), every "real" function name 8 | is constructed by prepending the function name by 9 | "MODEL_IDENTIFIER" + "_" where "MODEL_IDENTIFIER" is the short name 10 | of the model used as the name of the zip-file where the model is stored. 11 | Therefore, the typical usage is: 12 | 13 | #define MODEL_IDENTIFIER MyModel 14 | #include "fmiFunctions.h" 15 | 16 | As a result, a function that is defined as "fmiGetDerivatives" in this header file, 17 | is actually getting the name "MyModel_fmiGetDerivatives". 18 | 19 | Revisions: 20 | - November 4, 2010: Adapted to specification text: 21 | o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform 22 | o fmiInstantiateSlave: Argument GUID replaced by fmuGUID 23 | Argument mimetype replaced by mimeType 24 | o tabs replaced by spaces 25 | - October 16, 2010: First public Version 26 | 27 | 28 | Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. 29 | This file is licensed by the copyright holders under the BSD License 30 | (http://www.opensource.org/licenses/bsd-license.html): 31 | 32 | ---------------------------------------------------------------------------- 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | 36 | - Redistributions of source code must retain the above copyright notice, 37 | this list of conditions and the following disclaimer. 38 | - Redistributions in binary form must reproduce the above copyright notice, 39 | this list of conditions and the following disclaimer in the documentation 40 | and/or other materials provided with the distribution. 41 | - Neither the name of the copyright holders nor the names of its 42 | contributors may be used to endorse or promote products derived 43 | from this software without specific prior written permission. 44 | 45 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 46 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 49 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 50 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 | ---------------------------------------------------------------------------- 57 | */ 58 | 59 | #include "fmiPlatformTypes.h" 60 | #include 61 | 62 | /* Export fmi functions on Windows */ 63 | #ifdef _MSC_VER 64 | #define DllExport __declspec( dllexport ) 65 | #else 66 | #define DllExport 67 | #endif 68 | 69 | /* Macros to construct the real function name 70 | (prepend function name by MODEL_IDENTIFIER + "_") */ 71 | 72 | #define fmiPaste(a,b) a ## b 73 | #define fmiPasteB(a,b) fmiPaste(a,b) 74 | #define fmiFullName(name) fmiPasteB(MODEL_IDENTIFIER, name) 75 | 76 | /*************************************************** 77 | Common Functions 78 | ****************************************************/ 79 | #define fmiGetTypesPlatform fmiFullName(_fmiGetTypesPlatform) 80 | #define fmiGetVersion fmiFullName(_fmiGetVersion) 81 | #define fmiSetDebugLogging fmiFullName(_fmiSetDebugLogging) 82 | 83 | /*Data Exchange*/ 84 | #define fmiSetReal fmiFullName(_fmiSetReal) 85 | #define fmiSetInteger fmiFullName(_fmiSetInteger) 86 | #define fmiSetBoolean fmiFullName(_fmiSetBoolean) 87 | #define fmiSetString fmiFullName(_fmiSetString) 88 | 89 | #define fmiGetReal fmiFullName(_fmiGetReal) 90 | #define fmiGetInteger fmiFullName(_fmiGetInteger) 91 | #define fmiGetBoolean fmiFullName(_fmiGetBoolean) 92 | #define fmiGetString fmiFullName(_fmiGetString) 93 | 94 | /*************************************************** 95 | Functions for FMI for Co-Simulation 96 | ****************************************************/ 97 | #define fmiInstantiateSlave fmiFullName(_fmiInstantiateSlave) 98 | #define fmiInitializeSlave fmiFullName(_fmiInitializeSlave) 99 | #define fmiTerminateSlave fmiFullName(_fmiTerminateSlave) 100 | #define fmiResetSlave fmiFullName(_fmiResetSlave) 101 | #define fmiFreeSlaveInstance fmiFullName(_fmiFreeSlaveInstance) 102 | #define fmiSetRealInputDerivatives fmiFullName(_fmiSetRealInputDerivatives) 103 | #define fmiGetRealOutputDerivatives fmiFullName(_fmiGetRealOutputDerivatives) 104 | #define fmiDoStep fmiFullName(_fmiDoStep) 105 | #define fmiCancelStep fmiFullName(_fmiCancelStep) 106 | #define fmiGetStatus fmiFullName(_fmiGetStatus) 107 | #define fmiGetRealStatus fmiFullName(_fmiGetRealStatus) 108 | #define fmiGetIntegerStatus fmiFullName(_fmiGetIntegerStatus) 109 | #define fmiGetBooleanStatus fmiFullName(_fmiGetBooleanStatus) 110 | #define fmiGetStringStatus fmiFullName(_fmiGetStringStatus) 111 | 112 | /* Version number */ 113 | #define fmiVersion "1.0" 114 | 115 | /* make sure all compiler use the same alignment policies for structures */ 116 | #ifdef WIN32 117 | #pragma pack(push,8) 118 | #endif 119 | 120 | 121 | /* Type definitions */ 122 | typedef enum {fmiOK, 123 | fmiWarning, 124 | fmiDiscard, 125 | fmiError, 126 | fmiFatal, 127 | fmiPending} fmiStatus; 128 | 129 | typedef void (*fmiCallbackLogger) (fmiComponent c, fmiString instanceName, fmiStatus status, 130 | fmiString category, fmiString message, ...); 131 | typedef void* (*fmiCallbackAllocateMemory)(size_t nobj, size_t size); 132 | typedef void (*fmiCallbackFreeMemory) (void* obj); 133 | typedef void (*fmiStepFinished) (fmiComponent c, fmiStatus status); 134 | 135 | typedef struct { 136 | fmiCallbackLogger logger; 137 | fmiCallbackAllocateMemory allocateMemory; 138 | fmiCallbackFreeMemory freeMemory; 139 | fmiStepFinished stepFinished; 140 | } fmiCallbackFunctions; 141 | 142 | typedef struct { 143 | fmiBoolean iterationConverged; 144 | fmiBoolean stateValueReferencesChanged; 145 | fmiBoolean stateValuesChanged; 146 | fmiBoolean terminateSimulation; 147 | fmiBoolean upcomingTimeEvent; 148 | fmiReal nextEventTime; 149 | } fmiEventInfo; 150 | 151 | /* reset alignment policy to the one set before reading this file */ 152 | #ifdef WIN32 153 | #pragma pack(pop) 154 | #endif 155 | 156 | /*************************************************** 157 | Common Functions 158 | ****************************************************/ 159 | 160 | /* Inquire version numbers of header files */ 161 | DllExport const char* fmiGetTypesPlatform(); 162 | DllExport const char* fmiGetVersion(); 163 | 164 | DllExport fmiStatus fmiSetDebugLogging (fmiComponent c, fmiBoolean loggingOn); 165 | 166 | /* Data Exchange Functions*/ 167 | DllExport fmiStatus fmiGetReal (fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]); 168 | DllExport fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]); 169 | DllExport fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]); 170 | DllExport fmiStatus fmiGetString (fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]); 171 | 172 | DllExport fmiStatus fmiSetReal (fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]); 173 | DllExport fmiStatus fmiSetInteger (fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]); 174 | DllExport fmiStatus fmiSetBoolean (fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]); 175 | DllExport fmiStatus fmiSetString (fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]); 176 | 177 | /*************************************************** 178 | Functions for FMI for Co-Simulation 179 | ****************************************************/ 180 | 181 | /* Creation and destruction of slave instances and setting debug status */ 182 | DllExport fmiComponent fmiInstantiateSlave(fmiString instanceName, 183 | fmiString fmuGUID, 184 | fmiString fmuLocation, 185 | fmiString mimeType, 186 | fmiReal timeout, 187 | fmiBoolean visible, 188 | fmiBoolean interactive, 189 | fmiCallbackFunctions functions, 190 | fmiBoolean loggingOn); 191 | 192 | DllExport fmiStatus fmiInitializeSlave(fmiComponent c, 193 | fmiReal tStart, 194 | fmiBoolean StopTimeDefined, 195 | fmiReal tStop); 196 | 197 | DllExport fmiStatus fmiTerminateSlave (fmiComponent c); 198 | DllExport fmiStatus fmiResetSlave (fmiComponent c); 199 | DllExport void fmiFreeSlaveInstance(fmiComponent c); 200 | 201 | DllExport fmiStatus fmiSetRealInputDerivatives(fmiComponent c, 202 | const fmiValueReference vr[], 203 | size_t nvr, 204 | const fmiInteger order[], 205 | const fmiReal value[]); 206 | 207 | DllExport fmiStatus fmiGetRealOutputDerivatives(fmiComponent c, 208 | const fmiValueReference vr[], 209 | size_t nvr, 210 | const fmiInteger order[], 211 | fmiReal value[]); 212 | 213 | DllExport fmiStatus fmiCancelStep(fmiComponent c); 214 | DllExport fmiStatus fmiDoStep (fmiComponent c, 215 | fmiReal currentCommunicationPoint, 216 | fmiReal communicationStepSize, 217 | fmiBoolean newStep); 218 | 219 | 220 | typedef enum {fmiDoStepStatus, 221 | fmiPendingStatus, 222 | fmiLastSuccessfulTime} fmiStatusKind; 223 | 224 | DllExport fmiStatus fmiGetStatus (fmiComponent c, const fmiStatusKind s, fmiStatus* value); 225 | DllExport fmiStatus fmiGetRealStatus (fmiComponent c, const fmiStatusKind s, fmiReal* value); 226 | DllExport fmiStatus fmiGetIntegerStatus(fmiComponent c, const fmiStatusKind s, fmiInteger* value); 227 | DllExport fmiStatus fmiGetBooleanStatus(fmiComponent c, const fmiStatusKind s, fmiBoolean* value); 228 | DllExport fmiStatus fmiGetStringStatus (fmiComponent c, const fmiStatusKind s, fmiString* value); 229 | 230 | 231 | #endif // fmiFunctions_h 232 | -------------------------------------------------------------------------------- /examples/includes/fmiPlatformTypes.h: -------------------------------------------------------------------------------- 1 | #ifndef fmiPlatformTypes_h 2 | #define fmiPlatformTypes_h 3 | 4 | /* Standard header file to define the argument types of the 5 | functions of the Model Execution Interface. 6 | This header file must be utilized both by the model and 7 | by the simulation engine. 8 | 9 | Revisions: 10 | - October 2010: First public Version 11 | 12 | 13 | Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. 14 | This file is licensed by the copyright holders under the BSD License 15 | (http://www.opensource.org/licenses/bsd-license.html): 16 | 17 | 18 | ---------------------------------------------------------------------------- 19 | Redistribution and use in source and binary forms, with or without 20 | modification, are permitted provided that the following conditions are met: 21 | 22 | - Redistributions of source code must retain the above copyright notice, 23 | this list of conditions and the following disclaimer. 24 | - Redistributions in binary form must reproduce the above copyright notice, 25 | this list of conditions and the following disclaimer in the documentation 26 | and/or other materials provided with the distribution. 27 | - Neither the name of the copyright holders nor the names of its 28 | contributors may be used to endorse or promote products derived 29 | from this software without specific prior written permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 33 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 35 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 36 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 37 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 38 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 39 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 40 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | ---------------------------------------------------------------------------- 43 | */ 44 | 45 | /* Platform (combination of machine, compiler, operating system) */ 46 | #define fmiPlatform "standard32" 47 | 48 | /* Type definitions of variables passed as arguments 49 | Version "standard32" means: 50 | 51 | fmiComponent : 32 bit pointer 52 | fmiValueReference: 32 bit 53 | fmiReal : 64 bit 54 | fmiInteger : 32 bit 55 | fmiBoolean : 8 bit 56 | fmiString : 32 bit pointer 57 | 58 | */ 59 | typedef void* fmiComponent; 60 | typedef unsigned int fmiValueReference; 61 | typedef double fmiReal ; 62 | typedef int fmiInteger; 63 | typedef char fmiBoolean; 64 | typedef const char* fmiString ; 65 | 66 | /* Values for fmiBoolean */ 67 | #define fmiTrue 1 68 | #define fmiFalse 0 69 | 70 | /* Undefined value for fmiValueReference (largest unsigned int value) */ 71 | #define fmiUndefinedValueReference (fmiValueReference)(-1) 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /local_build_tools/asciidoctor.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | docker-compose up -d 3 | PAUSE 4 | 5 | -------------------------------------------------------------------------------- /local_build_tools/compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | services: 4 | asciidoctor: 5 | image: asciidoctor/docker-asciidoctor 6 | volumes: 7 | - ../:/documents 8 | entrypoint: asciidoctor --failure-level WARN -r asciidoctor-kroki -a mathjax -r asciidoctor-bibtex --trace content/index.adoc -o local_build_tools/HTML_content_local_build.html -------------------------------------------------------------------------------- /local_build_tools/windows_convert_symlinks(ADMIN).bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | SET Targetpath=..\.antora\modules\sensor-model 3 | SET Symlinkroot=..\..\.. 4 | 5 | @REM mklink /D %Targetpath%\images %Symlinkroot%\doc\images 6 | 7 | mklink /D %Targetpath%\pages %Symlinkroot%\doc 8 | 9 | @REM mklink /D %Targetpath%\partials %Symlinkroot%\_additional_content 10 | 11 | @REM mklink /D %Targetpath%\attachments %Symlinkroot%\_attachments 12 | 13 | PAUSE -------------------------------------------------------------------------------- /osmp.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | --------------------------------------------------------------------------------