diff --git a/README.md b/README.md index 9b729bbe624bed01f84023bfe0a1b3bc5018eade..57fc2babcc92737c07a4d3ff30e645f6dccf083d 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,16 @@ -*This repository is part of the outcomes of the Specialist Task Force 620 focusing on the authoring of a World Representation as part of the ETSI ISG Augmented Reality Framework architecture (https://www.etsi.org/deliver/etsi_gs/ARF/001_099/003/01.01.01_60/gs_ARF003v010101p.pdf).* -*The set of the World Representation authoring components includes:* - -*• The C++ and C# source code for servers and clients generated from OpenAPI available here (https://forge.etsi.org/rep/arf/arf005)* - -*• A Unity plugin and a Unity editor for authoring and accessing a World Representation hosted on a World Storage server.* - -*All these components are available under the ETSI Labs group “World Storage API Helpers”: https://labs.etsi.org/rep/arf/world-storage-api-helpers* - -*If you wish to contribute to this project or any other projects in the context of the [ETSI ISG Augmented Reality Framework architecture](https://www.etsi.org/committee/1420-arf), please refer to the ["How to get involved in an ISG" section on the ETSI website](https://www.etsi.org/how-to-get-involved-in-an-isg)* +*This repository is part of the outcomes of the Specialist Task Force 620 and 669 focusing on the authoring and use of a World Representation as part of the ETSI ISG Augmented Reality Framework architecture (https://www.etsi.org/deliver/etsi_gs/ARF/001_099/003/01.01.01_60/gs_ARF003v010101p.pdf).* --- - # SolARWorldStorage -## Server implementation using the SolAR world storage module +## SolAR module wrapping the C++ RestBed World Storage server and the C libcurl World Storage client [![License](https://img.shields.io/github/license/SolARFramework/SolARModuleOpencv?style=flat-square&label=License)](https://www.apache.org/licenses/LICENSE-2.0) -The goal of the world storage server is to be able to store and fetch online all the elements needed to design and execute AR apps. -This server implements a [server partially generated by OpenAPI generator](https://labs.etsi.org/rep/arf/world-storage-api-helpers/world-storage-cpp-server.git), based on the ETSI specification and handles REST requests designed in the same ETSI specification file, [available on the ETSI forge](https://forge.etsi.org/rep/arf/arf005/-/blob/develop/API/openapi.yaml). -It uses the ETSIWorldStorage component of the Solar world storage module ([SolARModuleWorldStorage]((https://github.com/SolarFramework/SolARModuleWorldStorage/tree/develop))) as an implementation for SolAR framework's [IWorldGraphManager](https://github.com/SolarFramework/SolARFramework/blob/feature/WorldGraph/interfaces/api/storage/IWorldGraphManager.h). +The SolARModuleWorldGraph includes : +- The SolAR framework wrapping from the World Storage Server based on a C++ RestBed implementation [available on the ETSI labs](https://labs.etsi.org/rep/arf/world-storage-api-helpers/world-storage-cpp-server); +- The SolAR framework wrapping from the World Storage Client based on the C libcurl implementation [available on the ETSI labs](https://labs.etsi.org/rep/arf/world-storage-api-helpers/world-storage-c-client) +Both server and client are generated with OpenAPI generator from the World Graph OpenAPI specification verison 2.0.0 [available on the ETSI forge](https://forge.etsi.org/rep/arf/openapi) ![All the project's architecture](images/SchemaWrapper.png) @@ -31,12 +22,31 @@ All the classes in this project (except for the main and UnitSysConversion) are Except for the `DefaultSolARImpl` class, that only has usages for when you want to check if the server is up and check the version, all of the request handling classes have the world storage singleton as an attribute. On which they will be able to call methods in response to requests. The module is passsed down through the constructor to ensure the uniqueness of it. +## Server implementation using the SolAR world storage module + +[![License](https://img.shields.io/github/license/SolARFramework/SolARModuleOpencv?style=flat-square&label=License)](https://www.apache.org/licenses/LICENSE-2.0) + +The server is available in the *Service-WorldStorage* folder. It consists of a executable which is able to load and instantiate at runtime the World Storage Server component available in the SolAR World Graph Module, to start the server waiting for client requests, and answering these requests. + +## Client implementation using the SolAR world storage module + +[![License](https://img.shields.io/github/license/SolARFramework/SolARModuleOpencv?style=flat-square&label=License)](https://www.apache.org/licenses/LICENSE-2.0) + +The server is available in the *Service-WorldStorage/tests* folder. It consists of a executable which is able to load and instantiate at runtime the World Storage Client component available in the SolAR World Graph Module, to to send requests to a World Storage server, and to display the result message. + ## How to To be able to compile and run this server, you need to: -- clone [the OpenAPI world storage](https://labs.etsi.org/rep/arf/world-storage-api-helpers/world-storage-cpp-server.git) project and then generate the code and export it as a library (follow the git's instructions) - have [remaken](https://github.com/b-com-software-basis/remaken) installed -- clone [SolAR framework](https://github.com/SolarFramework/SolARFramework) (for now, as the work is not released yet, you will have to clone the [feature/WorldGraph](https://github.com/SolarFramework/SolARFramework/tree/feature/WorldGraph) branch), perform a `remaken install` in the source directory and finally build the project -- clone [the world storage module](https://github.com/SolarFramework/SolARModuleWorldStorage) (for now, as the work is not released yet, you will have to clone the [develop](https://github.com/SolarFramework/SolARModuleWorldStorage/tree/develop) branch) and build it - -Once all those requirements are met, you should be able to compile your server and run it, you can try and send requests to http://localhost:8080 to try and see if it's working (e.g. POST request to see if the server is up : http://localhost:8080/ping) +- build the world storage module using qtCreator. Before opening the projet, run the following commands to install dependencies: +``` +Remaken install +``` +and +``` +Remaken install -c debug +``` +- then build the World Storage server as well as the client test. +- FInally, launch the server and the client binaries available in the folder *Service-WorldStorage\deploy\bin\x86_64\static\release* + +You can also test the server by sending requests to http://localhost:8080. diff --git a/Service-WorldStorage/.gitignore b/Service-WorldStorage/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8097bd2224131adc8a3e12e096bb3a83e3667e64 --- /dev/null +++ b/Service-WorldStorage/.gitignore @@ -0,0 +1,92 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj +build/ +.build-rules/ + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Visual Studio files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.vcxproj* +*.user +*.user.* +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* +x64/ +.vs/ +*.bat +*remakeninfo.txt +Debug/ +Release/ +*-packagedependencies.* +*-packagedependencies-win.* +*-packagedependencies-linux.* +*-packagedependencies-unix.* +*-packagedependencies-android.* +*.pc +*-Debug +*-Release + +# Executables +deploy/ +*.exe +*.out +*.app + +# Generated documentation +doc/ +doxygen/ + +# Tests builds +tests/bin + +# Others +*.*pre1 +*.rej +*.stash +*.rc +*.res +*.exp +*.ilk +*.pdb +*.autosave +*.project +*.props +*.log +*.tlog +*.TMP +*.tmp +.git Merge \ No newline at end of file diff --git a/Service-WorldStorage/LICENSE b/Service-WorldStorage/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64 --- /dev/null +++ b/Service-WorldStorage/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Service-WorldStorage/SolARService_WorldStorage.pro b/Service-WorldStorage/SolARService_WorldStorage.pro new file mode 100644 index 0000000000000000000000000000000000000000..2ae2965bf39a05f22c3c38d009fc4a8cb5edd671 --- /dev/null +++ b/Service-WorldStorage/SolARService_WorldStorage.pro @@ -0,0 +1,75 @@ +############################################################################### +# SolAR ARCloud +# (C) Copyright 2024 b<>com. All rights reserved. +# +# IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX +# This software is the confidential intellectual property of b<>com. +# You shall not disclose it and shall use it only in accordance with +# the terms of the license agreement you entered into with b<>com. +# +################################################################################ + +## remove Qt dependencies +QT -= core gui +CONFIG -= qt + +QMAKE_PROJECT_DEPTH = 0 + +## global defintions : target lib name, version +TARGET = SolARService_WorldStorage +VERSION = 1.2.0 +PROJECTDEPLOYDIR = $${PWD}/deploy + +CONFIG += c++1z +CONFIG += console + +DEFINES += MYVERSION=\"\\\"$${VERSION}\\\"\" + +include(findremakenrules.pri) + +win32:CONFIG -= static +win32:CONFIG += shared + +QMAKE_TARGET.arch = x86_64 #must be defined prior to include + +# Default rules for deployment. +#qnx: target.path = $${PWD}/bin/Debug# /tmp/$${TARGET}/bin +#else: unix:!android: target.path = /opt/$${TARGET}/bin +#!isEmpty(target.path): INSTALLS += target + +DEPENDENCIESCONFIG = shared install_recurse + +## Configuration for Visual Studio to install binaries and dependencies. Work also for QT Creator by replacing QMAKE_INSTALL +PROJECTCONFIG = QTVS + +#NOTE : CONFIG as staticlib or sharedlib, DEPENDENCIESCONFIG as staticlib or sharedlib, QMAKE_TARGET.arch and PROJECTDEPLOYDIR MUST BE DEFINED BEFORE templatelibconfig.pri inclusion +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/templateappconfig.pri))) # Shell_quote & shell_path required for visual on windows + +SOURCES += main.cpp + +unix { + LIBS += -ldl + # Avoids adding install steps manually. To be commented to have a better control over them. + QMAKE_POST_LINK += "make install install_deps" +} + +win32 { + QMAKE_LFLAGS += /MACHINE:X64 + DEFINES += WIN64 UNICODE _UNICODE + QMAKE_COMPILER_DEFINES += _WIN64 + QMAKE_CXXFLAGS += -wd4250 -wd4251 -wd4244 -wd4275 + + # Windows Kit (msvc2013 64) + LIBS += -L$$(WINDOWSSDKDIR)lib/winv6.3/um/x64 -lshell32 -lgdi32 -lComdlg32 + INCLUDEPATH += $$(WINDOWSSDKDIR)lib/winv6.3/um/x64 +} + +config_files.path = $${TARGETDEPLOYDIR} +config_files.files= $$files($${PWD}/SolARService_World_Storage_conf.xml) +INSTALLS += config_files + +DISTFILES += \ + packagedependencies.txt + +#NOTE : Must be placed at the end of the .pro +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/remaken_install_target.pri)))) # Shell_quote & shell_path required for visual on windows diff --git a/Service-WorldStorage/SolARService_World_Storage_conf.xml b/Service-WorldStorage/SolARService_World_Storage_conf.xml new file mode 100644 index 0000000000000000000000000000000000000000..06d08c00d95eb5c4c0a147a47be7af59e2fa6dd9 --- /dev/null +++ b/Service-WorldStorage/SolARService_World_Storage_conf.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/findremakenrules.pri b/Service-WorldStorage/findremakenrules.pri similarity index 100% rename from findremakenrules.pri rename to Service-WorldStorage/findremakenrules.pri diff --git a/Service-WorldStorage/images/AnchorMethods.png b/Service-WorldStorage/images/AnchorMethods.png new file mode 100644 index 0000000000000000000000000000000000000000..14c16be461e2daeb321fc8ad972c34c54d98a62d Binary files /dev/null and b/Service-WorldStorage/images/AnchorMethods.png differ diff --git a/Service-WorldStorage/images/DefaultMethods.png b/Service-WorldStorage/images/DefaultMethods.png new file mode 100644 index 0000000000000000000000000000000000000000..97316f382bd351bbe197de2bec56bc9c13ce06f1 Binary files /dev/null and b/Service-WorldStorage/images/DefaultMethods.png differ diff --git a/Service-WorldStorage/images/HandleSetUp.png b/Service-WorldStorage/images/HandleSetUp.png new file mode 100644 index 0000000000000000000000000000000000000000..e431f5d8642543baa6fa499c27bb8f92cb649ad4 Binary files /dev/null and b/Service-WorldStorage/images/HandleSetUp.png differ diff --git a/Service-WorldStorage/images/LinkMethods.png b/Service-WorldStorage/images/LinkMethods.png new file mode 100644 index 0000000000000000000000000000000000000000..1d064d7b0ac55ff760ef0a7eb71dc6a5228fab0d Binary files /dev/null and b/Service-WorldStorage/images/LinkMethods.png differ diff --git a/Service-WorldStorage/images/SchemaWrapper.png b/Service-WorldStorage/images/SchemaWrapper.png new file mode 100644 index 0000000000000000000000000000000000000000..b562c46c54fbb09ffa22f4eb334c9290f6b918f4 Binary files /dev/null and b/Service-WorldStorage/images/SchemaWrapper.png differ diff --git a/Service-WorldStorage/images/ToUUID.png b/Service-WorldStorage/images/ToUUID.png new file mode 100644 index 0000000000000000000000000000000000000000..b4bd982790dc02e075e479f7ea368d769b36d947 Binary files /dev/null and b/Service-WorldStorage/images/ToUUID.png differ diff --git a/Service-WorldStorage/images/TrackableMethods.png b/Service-WorldStorage/images/TrackableMethods.png new file mode 100644 index 0000000000000000000000000000000000000000..1ad5285add7dab5018dd6872933587f32a280c18 Binary files /dev/null and b/Service-WorldStorage/images/TrackableMethods.png differ diff --git a/Service-WorldStorage/images/WorldStorageServer.png b/Service-WorldStorage/images/WorldStorageServer.png new file mode 100644 index 0000000000000000000000000000000000000000..904b8767ee6e29fdc7c3274f6edd5f7046936b1b Binary files /dev/null and b/Service-WorldStorage/images/WorldStorageServer.png differ diff --git a/Service-WorldStorage/images/XPCFComponentManager.png b/Service-WorldStorage/images/XPCFComponentManager.png new file mode 100644 index 0000000000000000000000000000000000000000..b290307312a1c9db1e56370184e5f6613881ac90 Binary files /dev/null and b/Service-WorldStorage/images/XPCFComponentManager.png differ diff --git a/Service-WorldStorage/images/serverClasses.png b/Service-WorldStorage/images/serverClasses.png new file mode 100644 index 0000000000000000000000000000000000000000..73c0e3c45134f46052f41d78921f7d3eb6df2586 Binary files /dev/null and b/Service-WorldStorage/images/serverClasses.png differ diff --git a/Service-WorldStorage/main.cpp b/Service-WorldStorage/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..902881688cfbdfd6a78f89b7725b212e79085139 --- /dev/null +++ b/Service-WorldStorage/main.cpp @@ -0,0 +1,101 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** +* World Storage API +* API ensuring interoperability between an authoring tool and a World Storage service +* +* The version of the OpenAPI document: 0.0.1 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ + +#include +#include +#include +#include +#include + +namespace xpcf = org::bcom::xpcf; + +using namespace SolAR; +using namespace SolAR::api; + +// Global service instance +SRef worldGraphService = 0; + +// Function called when interruption signal is triggered to close the service. +static void SigInt(int /* signo */) { + + LOG_INFO("\n\n===> Program interruption\n"); + + LOG_INFO("Stop World Graph Service"); + + if (worldGraphService != 0) { + worldGraphService->stop(); + } + + LOG_INFO("World Graph Service stopped"); + + exit(0); +} + +int main() { + + try { + +#if NDEBUG + boost::log::core::get()->set_logging_enabled(false); +#endif + + //init the logger + LOG_ADD_LOG_TO_CONSOLE(); + LOG_INFO("program is running"); + + // Signal interruption function (Ctrl + C) + signal(SIGINT, SigInt); + + /* instantiate component manager*/ + /* this is needed in dynamic mode */ + SRef xpcfComponentManager = xpcf::getComponentManagerInstance(); + + if(xpcfComponentManager->load("SolARService_World_Storage_conf.xml")!=org::bcom::xpcf::_SUCCESS) + { + LOG_ERROR("Failed to load the configuration file SolARService_World_Storage_conf.xml"); + return -1; + } + worldGraphService = xpcfComponentManager->resolve(); + + // init and start the World Graph Service + worldGraphService->init(); + worldGraphService->start(); + + return EXIT_SUCCESS; + } + + catch (xpcf::Exception e) + { + LOG_ERROR("Exception raised : \n {}", e.what()) + return -1; + } + return 0; + +} + + diff --git a/Service-WorldStorage/packagedependencies.txt b/Service-WorldStorage/packagedependencies.txt new file mode 100644 index 0000000000000000000000000000000000000000..40098e7c69177479e806f98c9e7b80908acf461c --- /dev/null +++ b/Service-WorldStorage/packagedependencies.txt @@ -0,0 +1 @@ +SolARFramework|1.3.0|SolARFramework|SolARBuild@github|https://github.com/SolarFramework/SolarFramework/releases/download diff --git a/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/.gitignore b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..fab7372d796ea95c80d02df6caa7eb2b411a7ac1 --- /dev/null +++ b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage.pro b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage.pro new file mode 100644 index 0000000000000000000000000000000000000000..0aaa8dce2c5daaf9f7278ed39b0f2e49f44fd6d4 --- /dev/null +++ b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage.pro @@ -0,0 +1,91 @@ +############################################################################### +# SolAR ARCloud +# (C) Copyright 2024 b<>com. All rights reserved. +# +# IDDN: FR.001.020021.000.S.C.2024.000.00000 +# This software is the confidential intellectual property of b<>com. +# You shall not disclose it and shall use it only in accordance with +# the terms of the license agreement you entered into with b<>com. +# +################################################################################ + +## remove Qt dependencies +QT -= core gui +CONFIG -= qt + +QMAKE_PROJECT_DEPTH = 0 + +## global defintions : target lib name, version +TARGET = SolARServiceTest_WorldStorage +VERSION=1.2.0 +PROJECTDEPLOYDIR = $${PWD}/../../deploy + +DEFINES += MYVERSION=$${VERSION} +CONFIG += c++1z +CONFIG += console + +CONFIG += externaldeps + +include(findremakenrules.pri) + +CONFIG(debug,debug|release) { + DEFINES += _DEBUG=1 + DEFINES += DEBUG=1 +} + +CONFIG(release,debug|release) { + DEFINES += _NDEBUG=1 + DEFINES += NDEBUG=1 +} + +win32:CONFIG -= static +win32:CONFIG += shared + +QMAKE_TARGET.arch = x86_64 #must be defined prior to include + +DEPENDENCIESCONFIG = sharedlib install_recurse + +PROJECTCONFIG = QTVS + +#NOTE : CONFIG as staticlib or sharedlib, DEPENDENCIESCONFIG as staticlib or sharedlib, QMAKE_TARGET.arch and PROJECTDEPLOYDIR MUST BE DEFINED BEFORE templatelibconfig.pri inclusion +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/templateappconfig.pri))) # Shell_quote & shell_path required for visual on windows + +HEADERS += \ + +SOURCES += \ + SolARServiceTest_WorldStorage_main.cpp + +unix { + LIBS += -ldl + QMAKE_CXXFLAGS += -Wno-attributes + + # Avoids adding install steps manually. To be commented to have a better control over them. + QMAKE_POST_LINK += "$(MAKE) install install_deps" +} + +linux { + QMAKE_LFLAGS += -ldl +# LIBS += -L/home/linuxbrew/.linuxbrew/lib # temporary fix caused by grpc with -lre2 ... without -L in grpc.pc +} + +win32 { + + DEFINES += WIN64 UNICODE _UNICODE + QMAKE_COMPILER_DEFINES += _WIN64 + QMAKE_CXXFLAGS += -wd4250 -wd4251 -wd4244 -wd4275 +} + +config_files.path = $${TARGETDEPLOYDIR} +config_files.files= $$files($${PWD}/SolARServiceTest_WorldStorage_conf.xml) +INSTALLS += config_files + +OTHER_FILES += \ + packagedependencies.txt + +DISTFILES += \ + .gitignore \ + SolARServiceTest_WorldStorage_conf.xml + +#NOTE : Must be placed at the end of the .pro +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/remaken_install_target.pri)))) # Shell_quote & shell_path required for visual on windows + diff --git a/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage_conf.xml b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage_conf.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce3e5c24c96c2034c453b4ef65b47eab0a3c8658 --- /dev/null +++ b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage_conf.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + diff --git a/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage_main.cpp b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc72a0d1059310f6fbc15e1e06a2d9b37eba24fe --- /dev/null +++ b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/SolARServiceTest_WorldStorage_main.cpp @@ -0,0 +1,329 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2022 b<>com. All rights reserved. + * + * IDDN: FR.001.020021.000.S.C.2024.000.00000 + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + +#include +#include +#include + +#include "core/Log.h" +#include "api/storage/IWorldGraphManager.h" + +using namespace std; +using namespace SolAR; +using namespace SolAR::datastructure; +using namespace SolAR::api::storage; + +namespace xpcf=org::bcom::xpcf; + +/// +/// \brief Test application for SolARService_WorldStroage +/// + +int main(int argc, char ** argv) +{ +#if NDEBUG + boost::log::core::get()->set_logging_enabled(false); +#endif + + LOG_ADD_LOG_TO_CONSOLE(); + +// LOG_SET_DEBUG_LEVEL(); + + // XPCF Component Manager + SRef xpcfComponentManager = 0; + + // Components used for the test + SRef worldGraphClient = 0; + + // Default configuration file + char * config_file = (char *)"SolARServiceTest_WorldStorage_conf.xml"; + + if (argc > 1) { + // Get service configuration file path and name from main args + config_file = argv[1]; + } + + try { + LOG_INFO("Get Component Manager instance"); + + xpcfComponentManager = xpcf::getComponentManagerInstance(); + + LOG_INFO("Load Service impl configuration file"); + + if (xpcfComponentManager->load(config_file) == org::bcom::xpcf::_SUCCESS) + { + // Create service impl component + worldGraphClient = xpcfComponentManager->resolve(); + + LOG_INFO("Service Manager impl component created"); + } + else { + LOG_ERROR("Failed to load the configuration file {}", config_file); + return -1; + } + + org::bcom::xpcf::uuids::random_generator generator; + org::bcom::xpcf::uuids::uuid creatorUuid = generator(); + EncodingInfo encodingInfo("OTHER","1.2.0"); + UnitSystem unitSystem = UnitSystem::M; + + org::bcom::xpcf::uuids::uuid uuidWA; + org::bcom::xpcf::uuids::uuid uuidWA2; + org::bcom::xpcf::uuids::uuid uuidFiducial1; + org::bcom::xpcf::uuids::uuid uuidFiducial2; + org::bcom::xpcf::uuids::uuid uuidFiducial3; + org::bcom::xpcf::uuids::uuid uuidLinkWAtoF1; + org::bcom::xpcf::uuids::uuid uuidLinkWAtoWA2; + org::bcom::xpcf::uuids::uuid uuidLinkWA2toF2; + org::bcom::xpcf::uuids::uuid uuidLinkWA2toF3; + + + + + + + + SRef fiducial1 = xpcf::utils::make_shared + (creatorUuid, + Transform3Df::Identity(), + unitSystem, + datastructure::Vector3d{1.0f, 1.0f, 1.0f}, + std::multimap {{"place","bcom4A"}}, + StorageTrackableType::FIDUCIAL_MARKER, + encodingInfo, + std::vector{std::byte{0x01}, std::byte{0x01}, std::byte{0x00}}, + "FIDUCIAL MARKER door"); + + SRef fiducial2 = xpcf::utils::make_shared + (creatorUuid, + Transform3Df::Identity(), + unitSystem, + datastructure::Vector3d{1.0f, 1.0f, 1.0f}, + std::multimap {{"place","bcom4A"}}, + StorageTrackableType::MAP, + encodingInfo, + std::vector{std::byte{0x01}, std::byte{0x01}, std::byte{0x00}}, + "MAP room"); + + SRef fiducial3 = xpcf::utils::make_shared + (creatorUuid, + Transform3Df::Identity(), + unitSystem, + datastructure::Vector3d{1.0f, 1.0f, 1.0f}, + std::multimap {{"place","bcom4A"}}, + StorageTrackableType::FIDUCIAL_MARKER, + encodingInfo, + std::vector{std::byte{0x01}, std::byte{0x01}, std::byte{0x00}}, + "FIDUCIAL MARKER room"); + + SRef wa1 = xpcf::utils::make_shared + (creatorUuid, + Transform3Df::Identity(), + unitSystem, + datastructure::Vector3d{1.0f, 1.0f, 1.0f}, + std::multimap {{"place","bcom4A"},{"room","2a"}}, + "WORLD ANCHOR door" + ); + + + SRef wa2 = xpcf::utils::make_shared + (creatorUuid, + Transform3Df::Identity(), + unitSystem, + datastructure::Vector3d{1.0f, 1.0f, 1.0f}, + std::multimap {{"place","bcom4A"},{"room","2a"}}, + "WORLD ANCHOR room" + ); + + + //WA1 POST + if (worldGraphClient->addWorldAnchor(uuidWA, wa1) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("World Anchor has been added. uuid returned: {}\n", uuidWA); + } + else + { + LOG_ERROR("World Anchor has not been added.\n"); + } + + + //WA2 POST + if (worldGraphClient->addWorldAnchor(uuidWA2, wa2) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("World Anchor has been added. uuid returned: {}\n", uuidWA2); + } + else + { + LOG_ERROR("World Anchor has not been added.\n"); + } + + + + //TRACKABLE1 + if (worldGraphClient->addTrackable(uuidFiducial1, fiducial1) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("Trackable has been added. uuid returned: {}\n", uuidFiducial1); + } + else + { + LOG_ERROR("Trackable has not been added.\n"); + } + + + + //TRACKABLE2 + if (worldGraphClient->addTrackable(uuidFiducial2, fiducial2) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("Trackable has been added. uuid returned: {}\n", uuidFiducial2); + } + else + { + LOG_ERROR("Trackable has not been added.\n"); + } + + + + + //TRACKABLE3 + if (worldGraphClient->addTrackable(uuidFiducial3, fiducial3) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("Trackable has been added. uuid returned: {}\n", uuidFiducial3); + } + else + { + LOG_ERROR("Trackable has not been added.\n"); + } + + + + Eigen::Vector3f translate(0.0f, 2.0f, 0.0f); + Transform3Df t = Transform3Df::Identity(); + + + SRef linkWatoF1 = xpcf::utils::make_shared(creatorUuid, + uuidWA, + uuidFiducial1, + ElementKind::ANCHOR, + ElementKind::TRACKABLE, + t.translate(translate), + unitSystem, + std::multimap {{"place","bcom4A"},{"room","2a"}} + ); + SRef linkWAtoWA2 = xpcf::utils::make_shared(creatorUuid, + uuidWA, + uuidWA2, + ElementKind::ANCHOR, + ElementKind::ANCHOR, + t.translate(translate), + unitSystem, + std::multimap {{"place","bcom4A"},{"room","2a"}} + ); + SRef linkWA2toF2 = xpcf::utils::make_shared(creatorUuid, + uuidWA2, + uuidFiducial2, + ElementKind::ANCHOR, + ElementKind::TRACKABLE, + t.translate(translate), + unitSystem, + std::multimap {{"place","bcom4A"},{"room","2a"}} + ); + SRef linkWA2toF3 = xpcf::utils::make_shared(creatorUuid, + uuidWA2, + uuidFiducial3, + ElementKind::ANCHOR, + ElementKind::TRACKABLE, + t.translate(translate), + unitSystem, + std::multimap {{"place","bcom4A"},{"room","2a"}} + ); + + + //LINK1 + if (worldGraphClient->addWorldLink(uuidLinkWAtoF1, linkWatoF1) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("Link has been added. uuid returned: {}\n", uuidLinkWAtoF1); + } + else + { + LOG_ERROR("Link has not been added.\n"); + } + + + + + if (worldGraphClient->addWorldLink(uuidLinkWAtoWA2, linkWAtoWA2) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("Link has been added. uuid returned: {}\n", uuidLinkWAtoWA2); + } + else + { + LOG_ERROR("Link has not been added.\n"); + } + + + + if (worldGraphClient->addWorldLink(uuidLinkWA2toF2, linkWA2toF2) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("Link has been added. uuid returned: {}\n", uuidLinkWA2toF2); + } + else + { + LOG_ERROR("Link has not been added.\n"); + } + + + + if (worldGraphClient->addWorldLink(uuidLinkWA2toF3, linkWA2toF3) == FrameworkReturnCode::_SUCCESS) + { + LOG_INFO("Link has been added. uuid returned: {}\n", uuidLinkWA2toF2); + } + else + { + LOG_ERROR("Link has not been added.\n"); + } + + + + + + + + + std::vector capabilities; + datastructure::StorageCapabilities capabilityMarker(StorageTrackableType::FIDUCIAL_MARKER,encodingInfo); + datastructure::StorageCapabilities capabilityMap(StorageTrackableType::MAP,encodingInfo); + capabilities.push_back(capabilityMarker); + capabilities.push_back(capabilityMap); + std::vector> uuids; + std::tuple element1 = std::make_tuple(uuidWA,true); + uuids.push_back(element1); + std::vector relocalizationInformation; + if (worldGraphClient->getRelocalizationInformation(uuids,"NULL",capabilities,relocalizationInformation) == FrameworkReturnCode::_SUCCESS) + { + + for(datastructure::RelocalizationInformation relocObj : relocalizationInformation){ + LOG_INFO("Reloc has been effectued. returned: {}", relocObj.getRootUUID()); + } + } + else + { + LOG_ERROR("Reloc has failed."); + } + + LOG_INFO("End of test"); + } + catch (xpcf::Exception & e) { + LOG_ERROR("The following exception has been caught {}", e.what()); + return -1; + } + + return 0; +} diff --git a/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/findremakenrules.pri b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/findremakenrules.pri new file mode 100644 index 0000000000000000000000000000000000000000..044728821fd63680bb80383c30f834d3b46dd9cf --- /dev/null +++ b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/findremakenrules.pri @@ -0,0 +1,43 @@ +# Author(s) : Loic Touraine, Stephane Leduc + +android { + # unix path + USERHOMEFOLDER = $$clean_path($$(HOME)) + isEmpty(USERHOMEFOLDER) { + # windows path + USERHOMEFOLDER = $$clean_path($$(USERPROFILE)) + isEmpty(USERHOMEFOLDER) { + USERHOMEFOLDER = $$clean_path($$(HOMEDRIVE)$$(HOMEPATH)) + } + } +} + +unix:!android { + USERHOMEFOLDER = $$clean_path($$(HOME)) +} + +win32 { + USERHOMEFOLDER = $$clean_path($$(USERPROFILE)) + isEmpty(USERHOMEFOLDER) { + USERHOMEFOLDER = $$clean_path($$(HOMEDRIVE)$$(HOMEPATH)) + } +} + +exists(builddefs/qmake) { + QMAKE_REMAKEN_RULES_ROOT=builddefs/qmake +} +else { + QMAKE_REMAKEN_RULES_ROOT = $$clean_path($$(REMAKEN_RULES_ROOT)) + !isEmpty(QMAKE_REMAKEN_RULES_ROOT) { + QMAKE_REMAKEN_RULES_ROOT = $$clean_path($$(REMAKEN_RULES_ROOT)/qmake) + } + else { + QMAKE_REMAKEN_RULES_ROOT = $${USERHOMEFOLDER}/.remaken/rules/qmake + } +} + +!exists($${QMAKE_REMAKEN_RULES_ROOT}) { + error("Unable to locate remaken rules in " $${QMAKE_REMAKEN_RULES_ROOT} ". Either check your remaken installation, or provide the path to your remaken qmake root folder rules in REMAKEN_RULES_ROOT environment variable.") +} + +message("Remaken qmake build rules used : " $$QMAKE_REMAKEN_RULES_ROOT) \ No newline at end of file diff --git a/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/packagedependencies.txt b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/packagedependencies.txt new file mode 100644 index 0000000000000000000000000000000000000000..40098e7c69177479e806f98c9e7b80908acf461c --- /dev/null +++ b/Service-WorldStorage/tests/SolARServiceTest_WorldStorage/packagedependencies.txt @@ -0,0 +1 @@ +SolARFramework|1.3.0|SolARFramework|SolARBuild@github|https://github.com/SolarFramework/SolarFramework/releases/download diff --git a/SolARModuleWorldGraph/.gitignore b/SolARModuleWorldGraph/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..19abf714c09ec19c4ce39ed8cea9b31dc400ed06 --- /dev/null +++ b/SolARModuleWorldGraph/.gitignore @@ -0,0 +1,91 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj +build/ +.build-rules/ + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Visual Studio files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.vcxproj* +*.user +*.user.* +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* +x64/ +.vs/ +*.bat +*remakeninfo.txt +Debug/ +Release/ +*-packagedependencies.* +*-packagedependencies-win.* +*-packagedependencies-linux.* +*-packagedependencies-unix.* +*-packagedependencies-android.* +*.pc +*-Debug +*-Release + +# Executables +*.exe +*.out +*.app + +# Generated documentation +doc/ +doxygen/ + +# Tests builds +tests/bin + +# Others +*.*pre1 +*.rej +*.stash +*.rc +*.res +*.exp +*.ilk +*.pdb +*.autosave +*.project +*.props +*.log +*.tlog +*.TMP +*.tmp +.git Merge \ No newline at end of file diff --git a/SolARModuleWorldGraph/LICENSE b/SolARModuleWorldGraph/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..89032c6df05d7377965b4586a708eca664611b9a --- /dev/null +++ b/SolARModuleWorldGraph/LICENSE @@ -0,0 +1,4 @@ +(C) Copyright b<>com. All rights reserved. +IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + +This software is the confidential intellectual property of b<>com. You shall not disclose it and shall use it only in accordance with the terms of the license agreement you entered into with b<>com. diff --git a/SolARModuleWorldGraph/README.md b/SolARModuleWorldGraph/README.md new file mode 100644 index 0000000000000000000000000000000000000000..06a1f20c4be87c81a7409874e7f7012313d7314f --- /dev/null +++ b/SolARModuleWorldGraph/README.md @@ -0,0 +1,117 @@ +# SolARModuleWorldStorage + +**SolARModuleWorldStorage** is a module used to store the elements needed to represent the world in an Augmented Reality application. These elements are called world elements and are represented by the abstract class ``StorageWorldElement``. + +To handle the elements, the module will deal with two of its attributes : +- ``m_id`` : An ID, it is a UUID randomly generated when the instance of the element is created +- ``m_tags`` : a ``MultiMap`` of `Pair`, which stores text attributes that we want to add by name ( e.g. : `"Floor":"4", "Aisle":"A"`) + +They are currently two types of WorldElements and both of them inherit from the class ``StorageWorldElement`` : + - ``StorageTrackable`` + - ``StorageWorldAnchor`` + +Each of those have corresponding attributes that are useful if you want to develop an Augmented Reality application. + +Furthermore, to be compliant with the latest ETSI API Specification, the module also handle ``StorageWorldLink``, a SolAR datastructure that holds the information of the relationship between two elements (i.e. the id of both elements and the transfrom between them). + +--- + +## Module + +The module has itself three attributes to store the information: + +- **m_nodes** : `map>` + - The map that holds all of the elements in the world storage, it stores their id as keys for performance purposes. +- **m_links** : `map>` + - The map that holds all of the information regarding relations between each element. +- **m_tags** : `multimap, shared_ptr>` + - A multimap that allows for research by the `tag`. + +All the methods implemented in the module return a `FRAMEWORK_RETURN_CODE`, a SolAR enum to standardize and store responses from methods. most of them will return +- `FRAMEWORK_RETURN_CODE::_SUCCESS` when the method executes succesfuly +- `FRAMEWORK_RETURN_CODE::_ERROR__` when an error is raised +- `FRAMEWORK_RETURN_CODE::_NOT_FOUND_` when ressources that need to be fetched are not available. + +--- + +## World Elements nodes + +The world storage module has a map that stores the world elements and offer several methods you can use to perform operations on it : + +#### *getting a single element* + +> `getWorldElement`( in UUID id, out StorageWorldElement worldElement) +> - Gets any element given its ID + +> `getTrackable`( in UUID id, out StorageTrackable trackable) +> - Gets a trackable given its ID + +> `getWorldAnchor`( in UUID id, out StorageWorldAnchor worldAnchor) +> - Gets an anchor given its ID + +#### *getting all elements of a given type* + +> `getWorldElements`( out vector vector) +> - Gets all the elements of the world storage + +> `getTrackables`( out vector vector) +> - Gets all the trackables of the world storage + +> `getWorldAnchors`( out vector vector) +> - Gets all the anchors of the world storage + +#### *adding elements to the world storage* + +> `addTrackable`( out UUID id, in StorageTrackable trackable) +> - Adds a trackable to the world storage + +> `addWorldAnchor`( out UUID id, in StorageWorldAnchor worldAnchor) +> - Adds an anchor to the world storage + +#### *removing elements from the world storage* + +> `removeTrackable`( in UUID id) +> - Removes a Trackable from the world storage given its id + +> `removeWorldAnchor`( in UUID id) +> - Removes an anchor from the world storage given its id + +--- + +## Links nodes + +Furthermore the world storage also needs to store the edges between two worldElements, for this purpose it also manipulates a data structure called StorageWorldLink. It stores the information ceoncerning the two world elements that it links and the 3D transform between them. Like the world elements it needs to be stored in a map with its UUID as a key. + +#### *getting a single link* + +> `getWorldLink`( in UUID id, out StorageWorldLink worldLink) +> - Gets any link given its ID + +> `getWorldLink`( in UUID parentId, in UUID childId, out StorageWorldLink worldLink) +> - Gets any link given the ids of the two elements it links + +#### *getting all links* + +> `getWorldLinks`( out vector vector) +> - Gets all the links connecting the world elements + +#### *adding links* + +> `addWorldLink`( in StorageWorldLink worldLink, out UUID id) +> - Adds a new link + +#### *removing links* + +> `removeWorldLink`( in UUID id) +> - Removes a link given its id + +> `removeWorldLink`( in UUID parentId, in UUID childId) +> - Removes a link given the ids of the two elements it links + +--- + +## Tags +As mentioned earlier, all of our dataStructures hold a multi map attribute m_tags that holds pairs of String attributes and values. + +We store all of these pairs in a multimap as a key to which are mapped as values, the elements that are holding them. This way we can perform operations on Elements given a pair of String key/value (e.g. : We want to delete all the elements that have the attribute `"shape":"triangle"`). +However those operations have yet to be implemented diff --git a/SolARModuleWorldGraph/SolARModuleWorldStorage.pri b/SolARModuleWorldGraph/SolARModuleWorldStorage.pri new file mode 100644 index 0000000000000000000000000000000000000000..08b6571badf3a58bae6883c667f5e8e31d45d951 --- /dev/null +++ b/SolARModuleWorldGraph/SolARModuleWorldStorage.pri @@ -0,0 +1,23 @@ +HEADERS += \ + interfaces/SolARWorldStorageAPI.h \ + interfaces/ETSIWorldGraphClient.h \ + interfaces/ETSIWorldGraphManager.h \ + interfaces/ETSIWorldGraphService.h \ + interfaces/RestBedImpl/DefaultSolARImpl.h \ + interfaces/RestBedImpl/RelocalizationInformationSolARImpl.h \ + interfaces/RestBedImpl/TrackablesSolARImpl.h \ + interfaces/RestBedImpl/UnitSysConversion.h \ + interfaces/RestBedImpl/WorldAnchorsSolARImpl.h \ + interfaces/RestBedImpl/WorldLinksSolARImpl.h + +SOURCES += \ + src/ETSIWorldGraphClient.cpp \ + src/ETSIWorldGraphManager.cpp \ + src/ETSIWorldGraphService.cpp \ + src/SolARModuleWorldStorage_main.cpp \ + src/RestBedImpl/DefaultSolARImpl.cpp \ + src/RestBedImpl/RelocalizationInformationSolARImpl.cpp \ + src/RestBedImpl/TrackablesSolARImpl.cpp \ + src/RestBedImpl/WorldAnchorsSolARImpl.cpp \ + src/RestBedImpl/WorldLinksSolARImpl.cpp + diff --git a/SolARModuleWorldGraph/SolARModuleWorldStorage.pro b/SolARModuleWorldGraph/SolARModuleWorldStorage.pro new file mode 100644 index 0000000000000000000000000000000000000000..05fedaaf8306d450f2643c0727badd8b0971bb7a --- /dev/null +++ b/SolARModuleWorldGraph/SolARModuleWorldStorage.pro @@ -0,0 +1,107 @@ +############################################################################### +# SolAR ARCloud +# (C) Copyright 2024 b<>com. All rights reserved. +# +# IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX +# This software is the confidential intellectual property of b<>com. +# You shall not disclose it and shall use it only in accordance with +# the terms of the license agreement you entered into with b<>com. +# +################################################################################ + +## remove Qt dependencies +QT -= core gui +CONFIG -= qt + +QMAKE_PROJECT_DEPTH = 0 + +## global defintions : target lib name, version +INSTALLSUBDIR = SolARBuild +TARGET = SolARModuleWorldStorage +FRAMEWORK = $$TARGET +VERSION=1.3.0 + +DEFINES += MYVERSION=$${VERSION} +DEFINES += TEMPLATE_LIBRARY +CONFIG += c++1z + +include(findremakenrules.pri) + +CONFIG(debug,debug|release) { + DEFINES += _DEBUG=1 + DEFINES += DEBUG=1 +} + +CONFIG(release,debug|release) { + DEFINES += _NDEBUG=1 + DEFINES += NDEBUG=1 +} + +DEPENDENCIESCONFIG = shared install_recurse + +## Configuration for Visual Studio to install binaries and dependencies. Work also for QT Creator by replacing QMAKE_INSTALL +PROJECTCONFIG = QTVS + +#NOTE : CONFIG as staticlib or sharedlib, DEPENDENCIESCONFIG as staticlib or sharedlib and PROJECTDEPLOYDIR MUST BE DEFINED BEFORE templatelibbundle.pri inclusion +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/templatelibconfig.pri))) + +## DEFINES FOR MSVC/INTEL C++ compilers +msvc { +DEFINES += "_BCOM_SHARED=__declspec(dllexport)" +} + +INCLUDEPATH += interfaces/ + +include (SolARModuleWorldStorage.pri) + + +unix { + # Avoids adding install steps manually. To be commented to have a better control over them. + QMAKE_POST_LINK += "make install install_deps" + QMAKE_CXXFLAGS += -Wignored-qualifiers -DCURL_STATICLIB +} + +linux { + QMAKE_LFLAGS += -ldl +} + +macx { + DEFINES += _MACOS_TARGET_ + QMAKE_MAC_SDK= macosx + QMAKE_CFLAGS += -mmacosx-version-min=10.7 #-x objective-c++ + QMAKE_CXXFLAGS += -mmacosx-version-min=10.7 -std=c++17 -fPIC#-x objective-c++ + QMAKE_LFLAGS += -mmacosx-version-min=10.7 -v -lstdc++ + LIBS += -lstdc++ -lc -lpthread +} + +win32 { + DEFINES += _X86_VC12_TARGET_ + QMAKE_CXXFLAGS += -wd4250 -wd4251 -wd4244 -wd4275 -wd5030 + QMAKE_CXXFLAGS_DEBUG += /Od + QMAKE_CXXFLAGS_RELEASE += /O2 + DEFINES += MBCS _MBCS + } + +INCLUDEPATH += $${PWD} + +header_files.path = $${PROJECTDEPLOYDIR}/interfaces/ +header_files.files = $$files($${PWD}/interfaces/*.h*) + +headerRestBed_files.path = $${PROJECTDEPLOYDIR}/interfaces/RestBedImpl +headerRestBed_files.files = $$files($${PWD}/interfaces/RestBedImpl/*.h*) + +xpcf_xml_files.path = $${USERHOMEFOLDER}/.xpcf/SolAR +xpcf_xml_files.files=$$files($${PWD}/xpcf*.xml) + +INSTALLS += header_files +INSTALLS += headerRestBed_files +INSTALLS += xpcf_xml_files + +DISTFILES += Makefile \ + xpcf_SolARModuleWorldStorage_registry.xml + +OTHER_FILES += packagedependencies.txt \ + packageignoreinstall.txt + +#NOTE : Must be placed at the end of the .pro +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/remaken_install_target.pri)))) # Shell_quote & shell_path required for visual on windows diff --git a/SolARModuleWorldGraph/bcom-SolARModuleWorldStorage.pc.in b/SolARModuleWorldGraph/bcom-SolARModuleWorldStorage.pc.in new file mode 100644 index 0000000000000000000000000000000000000000..fb83394020ceff918888697865e718ebcb151949 --- /dev/null +++ b/SolARModuleWorldGraph/bcom-SolARModuleWorldStorage.pc.in @@ -0,0 +1,9 @@ +libname=@TARGET@ +prefix=/usr/local +includedir=${prefix}/interfaces + +Name: @TARGET@ +Description: +Version: @VERSION@ +Requires: +Cflags: -I${includedir} diff --git a/SolARModuleWorldGraph/findremakenrules.pri b/SolARModuleWorldGraph/findremakenrules.pri new file mode 100644 index 0000000000000000000000000000000000000000..413e33a16e9703c012ffe3cf9c4afc294c3dd6e7 --- /dev/null +++ b/SolARModuleWorldGraph/findremakenrules.pri @@ -0,0 +1,43 @@ +# Author(s) : Loic Touraine, Stephane Leduc + +android { + # unix path + USERHOMEFOLDER = $$clean_path($$(HOME)) + isEmpty(USERHOMEFOLDER) { + # windows path + USERHOMEFOLDER = $$clean_path($$(USERPROFILE)) + isEmpty(USERHOMEFOLDER) { + USERHOMEFOLDER = $$clean_path($$(HOMEDRIVE)$$(HOMEPATH)) + } + } +} + +unix:!android { + USERHOMEFOLDER = $$clean_path($$(HOME)) +} + +win32 { + USERHOMEFOLDER = $$clean_path($$(USERPROFILE)) + isEmpty(USERHOMEFOLDER) { + USERHOMEFOLDER = $$clean_path($$(HOMEDRIVE)$$(HOMEPATH)) + } +} + +exists(builddefs/qmake) { + QMAKE_REMAKEN_RULES_ROOT=builddefs/qmake +} +else { + QMAKE_REMAKEN_RULES_ROOT = $$clean_path($$(REMAKEN_RULES_ROOT)) + !isEmpty(QMAKE_REMAKEN_RULES_ROOT) { + QMAKE_REMAKEN_RULES_ROOT = $$clean_path($$(REMAKEN_RULES_ROOT)/qmake) + } + else { + QMAKE_REMAKEN_RULES_ROOT=$${USERHOMEFOLDER}/.remaken/rules/qmake + } +} + +!exists($${QMAKE_REMAKEN_RULES_ROOT}) { + error("Unable to locate remaken rules in " $${QMAKE_REMAKEN_RULES_ROOT} ". Either check your remaken installation, or provide the path to your remaken qmake root folder rules in REMAKEN_RULES_ROOT environment variable.") +} + +message("Remaken qmake build rules used : " $$QMAKE_REMAKEN_RULES_ROOT) \ No newline at end of file diff --git a/SolARModuleWorldGraph/interfaces/ETSIWorldGraphClient.h b/SolARModuleWorldGraph/interfaces/ETSIWorldGraphClient.h new file mode 100644 index 0000000000000000000000000000000000000000..7d5fa15f62408d4ed058131dfc863a2be23c12c2 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/ETSIWorldGraphClient.h @@ -0,0 +1,154 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2021-2022 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + +#ifndef ETSIWORLDGRAPHCLIENT_H +#define ETSIWORLDGRAPHCLIENT_H + + +#include + +#include +#include + +#include +#include +#include +#include + +extern "C"{ + #include +} + +#include + + +namespace SolAR { +namespace MODULES { +namespace SolARModuleWorldStorage { + +/** + * @class ETSIWorldGraphClient + * @brief Implements a client to connect to a server managing a world graph. The client is based on cppRestSDK + * UUID: 89f083a4-75c8-4c44-928f-ae183d8e877b + * + */ + +class SOLARWORLDSTORAGE_EXPORT_API ETSIWorldGraphClient : public org::bcom::xpcf::ConfigurableBase, + public SolAR::api::storage::IWorldGraphManager +{ + public: + + ETSIWorldGraphClient(); + + ~ETSIWorldGraphClient() override; + + void unloadComponent () override final; + + org::bcom::xpcf::XPCFErrorCode onConfigured() override final; + + ///////////////////////////////// + /// GRAPH INFORMATION METHODS /// + ///////////////////////////////// + + virtual FrameworkReturnCode getRelocalizationInformation(const std::vector> &uuids, const std::string &token,const std::vector &capabilities,std::vector &relocalizationInformation ) override; + + //////////////////////////// + /// WORLDELEMENT METHODS /// + //////////////////////////// + + virtual FrameworkReturnCode getWorldElement(const org::bcom::xpcf::uuids::uuid& worldElementId, SRef& worldElement) override; + + virtual FrameworkReturnCode getWorldElements(std::vector> &vector) override; + + virtual FrameworkReturnCode getWorldElementByKeyValue(const std::string &key, const std::string &value, std::vector> &vector) override; + + virtual FrameworkReturnCode getWorldElementByKey(const std::string &key, std::vector> &vector) override; + + ///////////////////////// + /// TRACKABLE METHODS /// + ///////////////////////// + + virtual FrameworkReturnCode addTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable) override; + + virtual FrameworkReturnCode getTrackable(const org::bcom::xpcf::uuids::uuid &trackableId, SRef &trackable) override; + + virtual FrameworkReturnCode removeTrackable(const org::bcom::xpcf::uuids::uuid &trackableId) override; + + virtual FrameworkReturnCode getTrackables(std::vector> &vector) override; + + virtual FrameworkReturnCode modifyTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable) override; + + /////////////////////////// + /// WORLDANCHOR METHODS /// + /////////////////////////// + + virtual FrameworkReturnCode addWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor) override; + + virtual FrameworkReturnCode getWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId, SRef& worldAnchor) override; + + virtual FrameworkReturnCode removeWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId) override; + + virtual FrameworkReturnCode getWorldAnchors(std::vector>& vector) override; + + virtual FrameworkReturnCode modifyWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor) override; + + ///////////////////////// + /// WORLDLINK METHODS /// + ///////////////////////// + + virtual FrameworkReturnCode addWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink) override; + + virtual FrameworkReturnCode getWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId, SRef &worldLink) override; + + virtual FrameworkReturnCode getWorldLink(const org::bcom::xpcf::uuids::uuid &linkId, SRef &worldLink) override; + + virtual FrameworkReturnCode removeWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId) override; + + virtual FrameworkReturnCode removeWorldLink(const org::bcom::xpcf::uuids::uuid &linkId) override; + + virtual FrameworkReturnCode getWorldLinks(std::vector> &vector) override; + + virtual FrameworkReturnCode modifyWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink) override; + + ///////////////////////////////////////// + /// WORLD GRAPH SAVE AND LOAD METHODS /// + ///////////////////////////////////////// + + /// @brief load a world graph + /// @param[in] path: Path of the file where from which to load the World Graph + /// @return a FrameworkReturnCode succesfull if the world graph has been loaded + virtual FrameworkReturnCode load(std::string path) override; + + /// @brief save the world graph + /// @param[in] path: Path of the file where to save the World Graph + /// @return a FrameworkReturnCode succesfull if the world graph has been saved + virtual FrameworkReturnCode save(std::string path) override; + + private: + + apiClient_t* m_apiClient = NULL; + std::string m_url = "http://127.0.0.1:8080"; + +}; + +} // namespace SolARModuleWorldStorage +} // namespace MODULES +} // namespace SolAR + + +template <> struct org::bcom::xpcf::ComponentTraits +{ + static constexpr const char * UUID = "89f083a4-75c8-4c44-928f-ae183d8e877b"; + static constexpr const char * NAME = "ETSIWorldGraphClient"; + static constexpr const char * DESCRIPTION = "ETSIWorldGraphClient implements SolAR::api::storage::IWorldGraphManager interface"; +}; + +#endif // ETSIWORLDGRAPHCLIENT_H diff --git a/SolARModuleWorldGraph/interfaces/ETSIWorldGraphManager.h b/SolARModuleWorldGraph/interfaces/ETSIWorldGraphManager.h new file mode 100644 index 0000000000000000000000000000000000000000..62972a4a15d60193424dbea381e10f6d8b3f1513 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/ETSIWorldGraphManager.h @@ -0,0 +1,167 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2021-2022 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + +#ifndef ETSIWORLDGRAPHMANAGER_H +#define ETSIWORLDGRAPHMANAGER_H + + +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + + +namespace SolAR { +namespace MODULES { +namespace SolARModuleWorldStorage { + + + +/** + * @class ETSIWorldGraphManager + * @brief manages a world graph represented by trackables and world anchors. + * UUID: 58826213-806b-4569-9996-f18552acc2d7 + * + */ + +class SOLARWORLDSTORAGE_EXPORT_API ETSIWorldGraphManager : public org::bcom::xpcf::ConfigurableBase, + public SolAR::api::storage::IWorldGraphManager +{ + public: + + ETSIWorldGraphManager(); + + ~ETSIWorldGraphManager() = default; + + org::bcom::xpcf::XPCFErrorCode onConfigured() override final; + + void unloadComponent() override final; + + ///////////////////////////////// + /// GRAPH INFORMATION METHODS /// + ///////////////////////////////// + + virtual FrameworkReturnCode getRelocalizationInformation(const std::vector> &uuids, const std::string &token,const std::vector &capabilities,std::vector &relocalizationInformation ) override; + + //////////////////////////// + /// WORLDELEMENT METHODS /// + //////////////////////////// + + virtual FrameworkReturnCode getWorldElement(const org::bcom::xpcf::uuids::uuid& worldElementId, SRef& worldElement) override; + + virtual FrameworkReturnCode getWorldElements(std::vector> &vector) override; + + virtual FrameworkReturnCode getWorldElementByKeyValue(const std::string &key, const std::string &value, std::vector> &vector) override; + + virtual FrameworkReturnCode getWorldElementByKey(const std::string &key, std::vector> &vector) override; + + ///////////////////////// + /// TRACKABLE METHODS /// + ///////////////////////// + + virtual FrameworkReturnCode addTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable) override; + + virtual FrameworkReturnCode getTrackable(const org::bcom::xpcf::uuids::uuid &trackableId, SRef &trackable) override; + + virtual FrameworkReturnCode removeTrackable(const org::bcom::xpcf::uuids::uuid &trackableId) override; + + virtual FrameworkReturnCode getTrackables(std::vector> &vector) override; + + virtual FrameworkReturnCode modifyTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable) override; + + /////////////////////////// + /// WORLDANCHOR METHODS /// + /////////////////////////// + + virtual FrameworkReturnCode addWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor) override; + + virtual FrameworkReturnCode getWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId, SRef& worldAnchor) override; + + virtual FrameworkReturnCode removeWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId) override; + + virtual FrameworkReturnCode getWorldAnchors(std::vector>& vector) override; + + virtual FrameworkReturnCode modifyWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor) override; + + ///////////////////////// + /// WORLDLINK METHODS /// + ///////////////////////// + + virtual FrameworkReturnCode addWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink) override; + + virtual FrameworkReturnCode getWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId, SRef &worldLink) override; + + virtual FrameworkReturnCode getWorldLink(const org::bcom::xpcf::uuids::uuid &linkId, SRef &worldLink) override; + + virtual FrameworkReturnCode removeWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId) override; + + virtual FrameworkReturnCode removeWorldLink(const org::bcom::xpcf::uuids::uuid &linkId) override; + + virtual FrameworkReturnCode getWorldLinks(std::vector> &vector) override; + + virtual FrameworkReturnCode modifyWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink) override; + + ///////////////////////////////////////// + /// WORLD GRAPH SAVE AND LOAD METHODS /// + ///////////////////////////////////////// + + /// @brief load a world graph + /// @param[in] path: Path of the file where from which to load the World Graph + /// @return a FrameworkReturnCode succesfull if the world graph has been loaded + virtual FrameworkReturnCode load(std::string path) override; + + /// @brief save the world graph + /// @param[in] path: Path of the file where to save the World Graph + /// @return a FrameworkReturnCode succesfull if the world graph has been saved + virtual FrameworkReturnCode save(std::string path) override; + + private: + + virtual void getAllTrackableChild(const org::bcom::xpcf::uuids::uuid root,std::vector& obj,const org::bcom::xpcf::uuids::uuid OriginalRootUUID,const std::vector capabilities,bool isDeviceToWorldAnchor); + + virtual std::vector> getChildren(const org::bcom::xpcf::uuids::uuid root); + + virtual SRef getParent(const org::bcom::xpcf::uuids::uuid root); + + virtual datastructure::Transform3Df getTransformToRoot(const SRef firstLink,const org::bcom::xpcf::uuids::uuid root,datastructure::Transform3Df& res,bool isDeviceToWorldAnchor); + + virtual bool isSupported(const std::vector capabilities,const datastructure::StorageTrackable track); + + boost::adjacency_list,SRef> graph; + + std::multimap, SRef> m_tags; + + std::string m_worldGraphPath = ""; + int m_automaticSave = 1; // 0 automatic save disable, else enable +}; + +} // namespace SolARModuleWorldStorage +} // namespace MODULES +} // namespace SolAR + + +template <> struct org::bcom::xpcf::ComponentTraits +{ + static constexpr const char * UUID = "58826213-806b-4569-9996-f18552acc2d7"; + static constexpr const char * NAME = "ETSIWorldGraphManager"; + static constexpr const char * DESCRIPTION = "ETSIWorldGraphManager implements SolAR::api::storage::IWorldGraphManager interface"; +}; + +#endif // ETSIWORLDGRAPHMANAGER_H diff --git a/SolARModuleWorldGraph/interfaces/ETSIWorldGraphService.h b/SolARModuleWorldGraph/interfaces/ETSIWorldGraphService.h new file mode 100644 index 0000000000000000000000000000000000000000..097a4cd4cd6b67ae3963b0e0a53626f737eed282 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/ETSIWorldGraphService.h @@ -0,0 +1,108 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2021-2022 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + +#ifndef ETSIWorldGraphService_H +#define ETSIWorldGraphService_H + + +#include + +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace SolAR { +namespace MODULES { +namespace SolARModuleWorldStorage { + +using namespace org::openapitools::server::implem; + +/** + * @class ETSIWorldGraphService + * @brief Service for managing a world graph based on ETSI specification with a RestBed server. + * UUID: b603990c-6596-4225-a5df-c0ac68ff8d16 + * + */ + +class SOLARWORLDSTORAGE_EXPORT_API ETSIWorldGraphService : public org::bcom::xpcf::ConfigurableBase, public SolAR::api::service::IServiceWorldGraph +{ + public: + + ETSIWorldGraphService(); + + ~ETSIWorldGraphService() override; + + void unloadComponent () override final; + + org::bcom::xpcf::XPCFErrorCode onConfigured() override; + + + /// @brief Initialization of the service + /// @return FrameworkReturnCode::_SUCCESS if the init succeed, else FrameworkReturnCode::_ERROR_ + FrameworkReturnCode init() override; + + /// @brief start the Service managing a world graph + /// @return FrameworkReturnCode::_SUCCESS if the service is started, else FrameworkReturnCode::_ERROR_ + FrameworkReturnCode start() override; + + /// @brief stop the Service managing a world graph + /// @return FrameworkReturnCode::_SUCCESS if the service is stopped, else FrameworkReturnCode::_ERROR_ + FrameworkReturnCode stop() override; + + private: + + SRef m_worldGraphManager; + + uint32_t m_serverNbThread = 2; + uint32_t m_maxRequestSize = 32768; + uint32_t m_maxResponseSize = 32768; + uint32_t m_port = 8080; + + SRef m_solarImpl; + SRef m_relocImpl; + SRef m_trackablesImpl; + SRef m_worldAnchorImpl; + SRef m_worldLinkImpl; + + std::shared_ptr m_restbedService; + std::shared_ptr m_restbedSettings; + + +}; + +} // namespace SolARModuleWorldStorage +} // namespace MODULES +} // namespace SolAR + + +template <> struct org::bcom::xpcf::ComponentTraits +{ + static constexpr const char * UUID = "b603990c-6596-4225-a5df-c0ac68ff8d16"; + static constexpr const char * NAME = "ETSIWorldGraphService"; + static constexpr const char * DESCRIPTION = "ETSIWorldGraphService implements SolAR::api::storage::IWorldGraphManager interface"; +}; + +#endif // ETSIWorldGraphService_H diff --git a/SolARModuleWorldGraph/interfaces/RestBedImpl/DefaultSolARImpl.h b/SolARModuleWorldGraph/interfaces/RestBedImpl/DefaultSolARImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..36fa22a202e10c7b4c537d12d9677597f04f8935 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/RestBedImpl/DefaultSolARImpl.h @@ -0,0 +1,81 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEFAULTSOLARIMPL_H +#define DEFAULTSOLARIMPL_H + +#include +#include +#include + +#include +#include + +namespace org::openapitools::server::implem +{ + + using namespace org::openapitools::server::model; + using namespace org::openapitools::server::api; + + class SolARPingResource : public DefaultApiResources::PingResource { + public: + SolARPingResource(const std::string& context = ""); + + std::pair handler_GET() override; + }; + + class SolARVersionResource : public DefaultApiResources::VersionResource { + public: + SolARVersionResource(const std::string& context = ""); + + std::pair handler_GET() override; + }; + + class SolARAdminResource : public DefaultApiResources::AdminResource { + public: + SolARAdminResource(const std::string& context = ""); + + std::pair handler_GET() override; + }; + /** + * @class + * @brief implementation of (class generated by OpenAPI-Generator), implements all the method defined with no tags in the API specification + * + */ + + class DefaultSolARImpl : public org::openapitools::server::api::DefaultApi { + + public: + explicit DefaultSolARImpl(std::shared_ptrconst& restbedService); + ~DefaultSolARImpl() override = default; + + + + + virtual void publishDefaultResources() override; + + // DefaultApi interface + private: + std::shared_ptr m_SolARPingResource; + std::shared_ptr m_SolARVersionResource; + std::shared_ptr m_SolARAdminResource; + std::shared_ptr m_service; + + }; + +} + +#endif // DEFAULTSOLARIMPL_H diff --git a/SolARModuleWorldGraph/interfaces/RestBedImpl/RelocalizationInformationSolARImpl.h b/SolARModuleWorldGraph/interfaces/RestBedImpl/RelocalizationInformationSolARImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..b402669f7d8d14e1311e99500ab7e14a77a454b7 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/RestBedImpl/RelocalizationInformationSolARImpl.h @@ -0,0 +1,93 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RELOCALIZATIONINFORMATIONSOLARIMPL_H +#define RELOCALIZATIONINFORMATIONSOLARIMPL_H + +#include +#include + +#include +#include +#include + +#include +#include + +namespace org::openapitools::server::implem +{ + using namespace org::openapitools::server::api; + + + + class SolARRelocalizationInformationResource: public RelocalizationInformationApiResources::RelocalizationInformationResource + { + public: + SolARRelocalizationInformationResource(const std::string& context = "",const SRef worldStorage = NULL); + + std::pair handler_GET( + std::vector & uuids, std::vector & capabilities, std::string & token) override; + + + + private: + SRef m_worldStorage; + }; + + + +/** + * @class RelocalizationInformationSolARImpl + * @brief implementation of RelocalizationInformationApi (class generated by OpenAPI-Generator), implements all the methods defined with the tag 'RelocalizationInformationApi' in the API specification + * + */ + +class RelocalizationInformationSolARImpl : public org::openapitools::server::api::RelocalizationInformationApi { + + public: + explicit RelocalizationInformationSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage); + ~RelocalizationInformationSolARImpl() override = default; + + virtual void publishDefaultResources() override; + + /// @brief static method to convert RelocalizationInformation defined by the SolAR framework to a RelocalizationInformation defined by OpenAPI generator + /// @param relocObject: the RelocalizationInformation to be converted + /// @return the converted RelocalizationInformationObject + static org::openapitools::server::model::RelocalizationInformation from_storage(const SolAR::datastructure::RelocalizationInformation &relocObject); + + /// @brief static method to convert RelocalizationObject (defined by the SolAR framework) to a RelocalizationObject (defined by OpenAPI generator) + /// @param relocObject: the RelocalizationInformation to be converted + /// @return the converted RelocalizationInformationObject + static org::openapitools::server::model::RelocObject from_storage(const SolAR::datastructure::RelocObject Obj); + + + /// @brief initialize the API handler, creates the singleton m_worldStorage if it is not already done + void init(); + + private: + /// @brief the instance of the world storage manager that will be used to handle the queries + SRef m_worldStorage; + + std::shared_ptr m_spRelocalizationInformationResource; + + std::shared_ptr m_service; + +}; + +} // namespace org::openapitools::server::api + + +#endif // RELOCALIZATIONINFORMATIONSOLARIMPL_H diff --git a/SolARModuleWorldGraph/interfaces/RestBedImpl/TrackablesSolARImpl.h b/SolARModuleWorldGraph/interfaces/RestBedImpl/TrackablesSolARImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..49661f1922eb0b909f165bf63d5e74ec7f579ea9 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/RestBedImpl/TrackablesSolARImpl.h @@ -0,0 +1,134 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACKABLES_SOLAR_IMPL_H_ +#define TRACKABLES_SOLAR_IMPL_H_ + +#include +#include + +#include +#include + +#include +#include +#include + + +namespace org::openapitools::server::implem +{ +using namespace org::openapitools::server::api; + +class SolARTrackablesResourceUUID: public TrackablesApiResources::TrackablesTrackableUUIDResource +{ +public: + SolARTrackablesResourceUUID(const std::string& context = "",const SRef worldStorage = NULL); + + std::pair handler_GET(std::string & trackableUUID, std::string & token) override; + + std::pair handler_DELETE(std::string & trackableUUID, std::string & token) override; + +private: + SRef m_worldStorage; +}; + +class SolARTrackablesResource: public TrackablesApiResources::TrackablesResource +{ +public: + SolARTrackablesResource(const std::string& context = "",const SRef worldStorage = NULL); + + std::pair handler_GET(std::string & token) override; + + std::pair handler_PUT(Trackable & trackable,std::string & token) override; + + std::pairhandler_POST(Trackable & trackable,std::string & token) override; + + + + +private: + SRef m_worldStorage; +}; +/** + * @class TrackablesSolARImpl + * @brief implementation of TrackableAPI (class generated by OpenAPI-Generator), implements all the methods defined with the tag 'trackable' in the API specification + * + */ + +class TrackablesSolARImpl : public org::openapitools::server::api::TrackablesApi { + +public: + explicit TrackablesSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage); + ~TrackablesSolARImpl() override = default; + + virtual void publishDefaultResources() override; + /// @brief static method to convert StorageTrackable (defined by the SolAR framework) to a Trackable (defined by OpenAPI generator) + /// @param trackable: the StorageTrackable to be converted + /// @return the converted trackable + static org::openapitools::server::model::Trackable from_storage(const SolAR::datastructure::StorageTrackable &trackable); + + + /// @brief static method to transform a string into a vector of bytes. Used to transform a Trackable into a StorageTrackable (attribute payload) + /// @return a vector of byte + static std::vector to_bytes(const std::string &s); + + // /// @brief API method to add a trackable to the world storage. It converts the Trackable into a StorageTrackable and stores it in the worldGraph manager + // /// @param trackable: trackable to be added + // /// @param response: the response to be sent: if it succeeds, the UUID of the newly created StorageTrackable + // void add_trackable(const org::openapitools::server::model::Trackable &trackable, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + + // /// @brief API method to delete a trackable, it fetches the StorageTrackable in the world storage Manager and removes it + // /// @param trackableUUID: the ID of the StorageTrackable to be removed + // /// @param response: the response to be sent: if it succeeds, a confirmation of the deletion of the StorageTrackable + // void delete_trackable(const std::string &trackableUUID,const std::optional &token, Pistache::Http::ResponseWriter &response) override; + + // /// @brief API method to get a single StorageTrackable from the world storage + // /// @param trackableUUID: the ID of the trackable to be fetched + // /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from the StorageTrackable + // void get_trackable_by_id(const std::string &trackableUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + + // /// @brief API method to get all the trackables currently stored in the world storage + // /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from all the StorageTrackables + // void get_trackables(const std::optional &token, Pistache::Http::ResponseWriter &response) override; + + // /// @brief API method to modify an existing trackable in the world storage. + // /// @param trackable: trackable to be modified + // /// @param response: the response to be sent: if it succeeds, the UUID of the modified StorageTrackable + // void modify_trackable(const org::openapitools::server::model::Trackable &trackable, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + + + /// @brief initialize the API handler, creates the singleton m_worldStorage if it is not already done + void init(); + +private: + /// @brief the instance of the world storage manager that will be used to handle the queries + SRef m_worldStorage; + + std::shared_ptr m_spTrackablesResource; + //std::shared_ptr m_TrackablesResource; + + std::shared_ptr m_spTrackablesResourceUUID; + + std::shared_ptr m_restbedService; + + +}; + +} // namespace org::openapitools::server::api + + + +#endif diff --git a/SolARModuleWorldGraph/interfaces/RestBedImpl/UnitSysConversion.h b/SolARModuleWorldGraph/interfaces/RestBedImpl/UnitSysConversion.h new file mode 100644 index 0000000000000000000000000000000000000000..75c19ebb2b2898a37eb0bb740d4cf23d3ddb780c --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/RestBedImpl/UnitSysConversion.h @@ -0,0 +1,148 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UNITSYSCONVERSION_H +#define UNITSYSCONVERSION_H + +#include + +#include + +#include +#include + +namespace xpcf = org::bcom::xpcf; +namespace org::openapitools::server::implem +{ + + /// @brief method to swap between UnitSystem enums (SolAR & OPenAPI) + /// @param the UnitSystem in openAPI format + /// @return the UnitSystem in SolAR format + static SolAR::datastructure::UnitSystem resolve_unitSystem(org::openapitools::server::model::UnitSystem input){ + SolAR::datastructure::UnitSystem ret; + std::string enumValue = input.getEnumValue(); + + if (enumValue == "MM") { + ret = SolAR::datastructure::UnitSystem::MM; + } + else if (enumValue == "CM") { + ret = SolAR::datastructure::UnitSystem::CM; + } + else if (enumValue == "DM") { + ret = SolAR::datastructure::UnitSystem::DM; + } + else if (enumValue == "M") { + ret = SolAR::datastructure::UnitSystem::M; + } + else if (enumValue == "DAM") { + ret = SolAR::datastructure::UnitSystem::DAM; + } + else if (enumValue == "HM") { + ret = SolAR::datastructure::UnitSystem::HM; + } + else if (enumValue == "KM") { + return SolAR::datastructure::UnitSystem::KM; + } + else if (enumValue == "INCH") { + ret = SolAR::datastructure::UnitSystem::INCH; + } + else if (enumValue == "FOOT") { + ret = SolAR::datastructure::UnitSystem::FOOT; + } + else if (enumValue == "YARD") { + ret = SolAR::datastructure::UnitSystem::YARD; + } + else if (enumValue == "MILE") { + ret = SolAR::datastructure::UnitSystem::MILE; + } + else { + ret = SolAR::datastructure::UnitSystem::INVALID; + } + return ret; + } + + /// @brief method to swap between UnitSystem enums (OPenAPI & SolAR) + /// @param the UnitSystem in SolAR format + /// @return the UnitSystem in openAPI format + static org::openapitools::server::model::UnitSystem resolve_unitSystem(SolAR::datastructure::UnitSystem input){ + + org::openapitools::server::model::UnitSystem ret; + switch(input){ + case SolAR::datastructure::UnitSystem::MM: + { + ret.setEnumValue("MM"); + break; + } + case SolAR::datastructure::UnitSystem::CM: + { + ret.setEnumValue("CM"); + break; + } + case SolAR::datastructure::UnitSystem::DM: + { + ret.setEnumValue("DM"); + break; + } + case SolAR::datastructure::UnitSystem::M: + { + ret.setEnumValue("M"); + break; + } + case SolAR::datastructure::UnitSystem::DAM: + { + ret.setEnumValue("DAM"); + break; + } + case SolAR::datastructure::UnitSystem::HM: + { + ret.setEnumValue("HM"); + break; + } + case SolAR::datastructure::UnitSystem::KM: + { + ret.setEnumValue("KM"); + break; + } + case SolAR::datastructure::UnitSystem::INCH: + { + ret.setEnumValue("INCH"); + break; + } + case SolAR::datastructure::UnitSystem::FOOT: + { + ret.setEnumValue("FOOT"); + break; + } + case SolAR::datastructure::UnitSystem::YARD: + { + ret.setEnumValue("YARD"); + break; + } + case SolAR::datastructure::UnitSystem::MILE: + { + ret.setEnumValue("MILE"); + break; + } + default: + { + ret.setEnumValue("INVALID_VALUE_OPENAPI_GENERATED"); + } + } + return ret; + } + +} +#endif // UNITSYSCONVERSION_H diff --git a/SolARModuleWorldGraph/interfaces/RestBedImpl/WorldAnchorsSolARImpl.h b/SolARModuleWorldGraph/interfaces/RestBedImpl/WorldAnchorsSolARImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..4082349b6cf051f34005f8449046bc29d8d83888 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/RestBedImpl/WorldAnchorsSolARImpl.h @@ -0,0 +1,123 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WORLDANCHORSSOLARIMPL_H +#define WORLDANCHORSSOLARIMPL_H + +#include +#include +#include +#include +#include +#include + +namespace org::openapitools::server::implem +{ + +using namespace org::openapitools::server::api; + + class SolARWorldAnchorsResource: public WorldAnchorsApiResources::WorldAnchorsResource + { + public: + SolARWorldAnchorsResource(const std::string& context = "",const SRef worldStorage = NULL); + + std::pair handler_GET(std::string & token) override; + + std::pair handler_PUT(WorldAnchor & worldAnchor,std::string & token) override; + + std::pair handler_POST(WorldAnchor & worldAnchor,std::string & token) override; + + + + private: + SRef m_worldStorage; + }; + + + class SolARWorldAnchorsResourceUUID: public WorldAnchorsApiResources::WorldAnchorsWorldAnchorUUIDResource + { + public: + SolARWorldAnchorsResourceUUID(const std::string& context = "",const SRef worldStorage = NULL); + + std::pair handler_GET(std::string & worldAnchorUUID, std::string & token) override; + + std::pair handler_DELETE(std::string & worldAnchorUUID, std::string & token) override; + + private: + SRef m_worldStorage; + }; + +/** + * @class WorldAnchorsSolARImpl + * @brief implementation of WorldAnchorsAPI (class generated by OpenAPI-Generator), implements all the method defined with the tag 'world anchors' in the API specification + * + */ + +class WorldAnchorsSolARImpl : public org::openapitools::server::api::WorldAnchorsApi { + public: + explicit WorldAnchorsSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage); + ~WorldAnchorsSolARImpl() override = default; + + virtual void publishDefaultResources() override; +// /// @brief API method to add a world anchor to the world storage. It converts the World anchor into a StorageWorldAnchor and stores it in the worldGraph manager +// /// @param worldAnchor: worldAnchor to be added +// /// @param response: the response to be sent: if it succeeds, the UUID of the newly created StorageWorldAnchor +// void add_world_anchor(const org::openapitools::server::model::WorldAnchor &worldAnchor, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// /// @brief API method to delete a world anchor, it fetches the StorageWorldAnchor in the world storage Manager and removes it +// /// @param worldAnchorUUID: the ID of the StorageWorldAnchor to be removed +// /// @param response: the response to be sent: if it succeeds, a confirmation of the deletion of the StorageWorldAnchor +// void delete_world_anchor(const std::string &worldAnchorUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// /// @brief API method to get a single StorageWorldAnchor from the world storage +// /// @param worldAnchorUUID: the ID of the world anchor to be fetched +// /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from the StorageWorldAnchor +// void get_world_anchor_by_id(const std::string &worldAnchorUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// /// @brief API method to get all the world anchors currently stored in the world storage +// /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from all the StorageWorldAnchor +// void get_world_anchors(const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// /// @brief API method to modify an existing world anchor in the world storage. +// /// @param worldAnchor: worldAnchor to be modified +// /// @param response: the response to be sent: if it succeeds, the UUID of the modified worldAnchor +// void modify_world_anchor(const org::openapitools::server::model::WorldAnchor &worldAnchor, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + + /// @brief static method to convert StorageWorldAnchor (defined by the SolAR framework) to a world anchors (defined by OpenAPI generator) + /// @param worldAnchor: the StorageWorldAnchor to be converted + /// @return the converted world anchor + static org::openapitools::server::model::WorldAnchor from_storage(const SolAR::datastructure::StorageWorldAnchor &worldAnchor); + + /// @brief initialize the API handler, creates the singleton m_worldStorage if it is not already done + void init(); + + private: + /// @brief the instance of the world storage manager that will be used to handle the queries + SRef m_worldStorage; + + std::shared_ptr m_spWorldAnchorsResource; + + std::shared_ptr m_spWorldAnchorsResourceUUID; + + std::shared_ptr m_restbedService; + + +}; + +} // namespace org::openapitools::server::api + + +#endif // WORLDANCHORSSOLARIMPL_H diff --git a/SolARModuleWorldGraph/interfaces/RestBedImpl/WorldLinksSolARImpl.h b/SolARModuleWorldGraph/interfaces/RestBedImpl/WorldLinksSolARImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..00c04375ed67e8dffafffea65d01d821c849b510 --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/RestBedImpl/WorldLinksSolARImpl.h @@ -0,0 +1,127 @@ +#ifndef WORLDLINKSSOLARIMPL_H +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define WORLDLINKSSOLARIMPL_H + +#include +#include +#include +#include +#include +#include + +namespace org::openapitools::server::implem +{ + +using namespace org::openapitools::server::api; + + + class SolARWorldLinksResource: public WorldLinksApiResources::WorldLinksResource + { + public: + SolARWorldLinksResource(const std::string& context = "",const SRef worldStorage = NULL); + + std::pair handler_GET(std::string & token) override; + + std::pair handler_PUT(WorldLink & worldLink,std::string & token) override; + + std::pairhandler_POST(WorldLink & worldLink,std::string & token) override; + + private: + SRef m_worldStorage; + }; + + class SolARWorldLinksResourceUUID: public WorldLinksApiResources::WorldLinksWorldLinkUUIDResource + { + public: + SolARWorldLinksResourceUUID(const std::string& context = "",const SRef worldStorage = NULL); + + std::pair handler_GET(std::string & worldLinkUUID, std::string & token) override; + + std::pair handler_DELETE(std::string & worldLinkUUID, std::string & token) override; + + private: + SRef m_worldStorage; + }; + + +/** + * @class WorldLinksSolARImpl + * @brief implementation of WorldLinksAPI (class generated by OpenAPI-Generator), implements all the method defined with the tag 'world links' in the API specification + * + */ + +class WorldLinksSolARImpl : public org::openapitools::server::api::WorldLinksApi { + public: + explicit WorldLinksSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage); + ~WorldLinksSolARImpl() override = default; + + virtual void publishDefaultResources() override; + +// /// @brief API method to add a world link to the world storage. It converts the World link into a StorageWorldLink and stores it in the worldGraph manager +// /// @param worldLink: worldLink to be added +// /// @param response: the response to be sent: if it succeeds, the UUID of the newly created StorageWorldLink +// void add_world_link(const org::openapitools::server::model::WorldLink &worldLink, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// /// @brief API method to delete a world link, it fetches the StorageWorldLink in the world storage Manager and removes it +// /// @param worldLinkUUID: the ID of the StorageWorldLink to be removed +// /// @param response: the response to be sent: if it succeeds, a confirmation of the deletion of the StorageWorldLink +// void delete_world_link(const std::string &worldLinkUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// /// @brief API method to get a single StorageWorldLink from the world storage +// /// @param worldLinkUUID: the ID of the world link to be fetched +// /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from the StorageWorldLink +// void get_world_link_by_id(const std::string &worldLinkUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// /// @brief API method to get all the world links currently stored in the world storage +// /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from all the StorageWorldLink +// void get_world_links(const std::optional &token, Pistache::Http::ResponseWriter &response) override; + +// virtual void modify_world_link(const org::openapitools::server::model::WorldLink &worldLink, const std::optional &token, Pistache::Http::ResponseWriter &response) override; + + /// @brief static method that returns a worldlink Json object from the informations contaiend in the worldStorage (before implementing a solution taht complies with the world link api description) + /// @param worldLink: the StorageWorldLink to be converted + /// @return A Json containing the id of the link, the id of both attached elements and the transform between them + static org::openapitools::server::model::WorldLink from_storage(SolAR::datastructure::StorageWorldLink worldLink); + + /// @brief method to get the world elements currently linked to the given world link + /// @param response: A pair containing shared pointers of the two elements connected to by the link + std::pair,SRef> get_attached_objects_from_uuid(const std::string &worldLinkUUID); + + /// @brief initialize the API handler, creates the singleton m_worldStorage if it is not already done + void init(); + + /// @brief method to convert ElementKind(SolAR) to ObjectType(OpenAPI spec) + static model::TypeWorldStorage resolve_element_kind(SolAR::datastructure::ElementKind kind); + + /// @brief method to convert ObjectType(OpenAPI spec) to ElementKind(SolAR) + static SolAR::datastructure::ElementKind resolve_element_kind(model::TypeWorldStorage kind); + + private: + /// @brief the instance of the world storage manager that will be used to handle the queries + SRef m_worldStorage; + + std::shared_ptr m_spSolARWorldLinksResource; + + std::shared_ptr m_spSolARWorldLinksResourceUUID; + + std::shared_ptr m_restbedService; +}; + +} // namespace org::openapitools::server::api + +#endif // WORLDLINKSSOLARIMPL_H diff --git a/SolARModuleWorldGraph/interfaces/SolARWorldStorageAPI.h b/SolARModuleWorldGraph/interfaces/SolARWorldStorageAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..25bd3dcdfbbd6b206040fdec6d992b0b4d588b2d --- /dev/null +++ b/SolARModuleWorldGraph/interfaces/SolARWorldStorageAPI.h @@ -0,0 +1,24 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2017 b<>com. All rights reserved. + * + * IDDN: FR.001.020021.000.S.C.2024.000.00000 + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + +#ifndef SOLAR_WORLDSTORAGE_API_H +#define SOLAR_WORLDSTORAGE_API_H + +#if _WIN32 +#ifdef SolARModuleWorldStorage_API_DLLEXPORT +#define SOLARWORLDSTORAGE_EXPORT_API __declspec(dllexport) +#else //SOLARWORLDSTORAGE_API_DLLEXPORT +#define SOLARWORLDSTORAGE_EXPORT_API __declspec(dllimport) +#endif //SOLARWORLDSTORAGE_API_DLLEXPORT +#else //_WIN32 +#define SOLARWORLDSTORAGE_EXPORT_API +#endif //_WIN32 +#endif //SOLAR_WORLDSTORAGE_API_H diff --git a/SolARModuleWorldGraph/packagedependencies-linux.txt b/SolARModuleWorldGraph/packagedependencies-linux.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/SolARModuleWorldGraph/packagedependencies.txt b/SolARModuleWorldGraph/packagedependencies.txt new file mode 100644 index 0000000000000000000000000000000000000000..51cd4271bacaece78fcc464b9809a3a78058c772 --- /dev/null +++ b/SolARModuleWorldGraph/packagedependencies.txt @@ -0,0 +1,7 @@ +SolARFramework|1.3.0|SolARFramework|SolARBuild@github|https://github.com/SolarFramework/SolarFramework/releases/download +worldStorageRestBedServer|2.0.0|worldStorageRestBedServer|thirdParties@github|https://github.com/SolarFramework/binaries/releases/download|static +worldStorageCClient|2.0.0|worldStorageCClient|thirdParties@github|https://github.com/SolarFramework/binaries/releases/download|static +boost#stable|1.84.0|boost|conan|conan-center|static| +restbed|4.8|restbed|conan|conan-center|static +openssl|3.2.1|openssl|conan|conan-center|static +libcurl|8.6.0|libcurl|conan|conan-center|static diff --git a/SolARModuleWorldGraph/packageignoreinstall.txt b/SolARModuleWorldGraph/packageignoreinstall.txt new file mode 100644 index 0000000000000000000000000000000000000000..362dc34bfe2eb79ac8f00a1a02407db90126923b --- /dev/null +++ b/SolARModuleWorldGraph/packageignoreinstall.txt @@ -0,0 +1,4 @@ +SolARFramework +xpcf +boost +grpc \ No newline at end of file diff --git a/SolARModuleWorldGraph/src/ETSIWorldGraphClient.cpp b/SolARModuleWorldGraph/src/ETSIWorldGraphClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d5d02f8a40c2b50b877e844184c56d8a997c562 --- /dev/null +++ b/SolARModuleWorldGraph/src/ETSIWorldGraphClient.cpp @@ -0,0 +1,947 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2021-2022 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "worldStorageRestBedcppServer/RelocalizationInformations.h" +#include +#include +#include //.h> +#include +#include +#include "ETSIWorldGraphClient.h" + +extern "C"{ + #include + #include + #include + #include +} + +namespace xpcf = org::bcom::xpcf; + +XPCF_DEFINE_FACTORY_CREATE_INSTANCE(SolAR::MODULES::SolARModuleWorldStorage::ETSIWorldGraphClient) + +namespace SolAR { +namespace MODULES { +namespace SolARModuleWorldStorage { + +static std::map solarStorageDataFormatToETSI = + {{"hololens", "HOLOLENS"}, + {"arkit", "ARKIT"}, + {"arcore", "ARCORE"}, + {"vuforia", "VUFORIA"}, + {"aruco", "ARUCO"}, + {"other", "OTHER"}, + {"HOLOLENS", "HOLOLENS"}, + {"ARKIT", "ARKIT"}, + {"ARCORE", "ARCORE"}, + {"VUFORIA", "VUFORIA"}, + {"ARUCO", "ARUCO"}, + {"OTHER", "OTHER"}, +}; + +static std::map ETSIDataFormatToSolarStorage = + {{"HOLOLENS", "hololens"}, + {"ARKIT", "arkit"}, + {"ARCORE", "arcore"}, + {"VUFORIA", "vuforia"}, + {"ARUCO", "aruco"}, + {"OTHER", "other"}, + }; + +static std::map solarStorageTrackableTypeToETSI = + {{datastructure::StorageTrackableType::FIDUCIAL_MARKER, "FIDUCIAL_MARKER"}, + {datastructure::StorageTrackableType::IMAGE_MARKER, "IMAGE_MARKER"}, + {datastructure::StorageTrackableType::MESH, "MESH"}, + {datastructure::StorageTrackableType::MAP, "MAP"}, + {datastructure::StorageTrackableType::GEOPOSE, "GEOPOSE"}, + {datastructure::StorageTrackableType::OTHER, "OTHER"}}; + +static std::map ETSITrackableTypeToSolARStorage = + {{"FIDUCIAL_MARKER", datastructure::StorageTrackableType::FIDUCIAL_MARKER}, + {"IMAGE_MARKER", datastructure::StorageTrackableType::IMAGE_MARKER}, + {"MESH", datastructure::StorageTrackableType::MESH}, + {"MAP", datastructure::StorageTrackableType::MAP}, + {"GEOPOSE", datastructure::StorageTrackableType::GEOPOSE}, + {"OTHER", datastructure::StorageTrackableType::OTHER}}; + +static std::map solarUnitSystemToETSI = + {{datastructure::UnitSystem::MM, "MM"}, + {datastructure::UnitSystem::CM, "CM"}, + {datastructure::UnitSystem::DM, "DM"}, + {datastructure::UnitSystem::M, "M"}, + {datastructure::UnitSystem::DAM, "DAM"}, + {datastructure::UnitSystem::HM, "HM"}, + {datastructure::UnitSystem::KM, "KM"}, + {datastructure::UnitSystem::INCH, "INCH"}, + {datastructure::UnitSystem::FOOT, "FOOT"}, + {datastructure::UnitSystem::YARD, "YARD"}, + {datastructure::UnitSystem::MILE, "MILE"}}; + +static std::map ETSIUnitSystemToSolAR = + {{"MM", datastructure::UnitSystem::MM}, + {"CM", datastructure::UnitSystem::CM}, + {"DM", datastructure::UnitSystem::DM}, + {"M", datastructure::UnitSystem::M}, + {"DAM", datastructure::UnitSystem::DAM}, + {"HM", datastructure::UnitSystem::HM}, + {"KM", datastructure::UnitSystem::KM}, + {"INCH", datastructure::UnitSystem::INCH}, + {"FOOT", datastructure::UnitSystem::FOOT}, + {"YARD", datastructure::UnitSystem::YARD}, + {"MILE", datastructure::UnitSystem::MILE}}; + +datastructure::StorageTrackableType ETSITrackableType2SolARStorage (const std::string trackableType) +{ + std::map::const_iterator it = ETSITrackableTypeToSolARStorage.find(trackableType); + if (it == ETSITrackableTypeToSolARStorage.end()) + return datastructure::StorageTrackableType::OTHER; + else + return it->second; +} + +std::string SolARStoragetrackableType2ETSI (const datastructure::StorageTrackableType trackableType) +{ + std::map::const_iterator it = solarStorageTrackableTypeToETSI.find(trackableType); + if (it == solarStorageTrackableTypeToETSI.end()) + return "OTHER"; + else + return it->second; +} + +datastructure::UnitSystem ETSIUnitSystem2SolARStorage (const std::string unitySystem) +{ + std::map::const_iterator it = ETSIUnitSystemToSolAR.find(unitySystem); + if (it == ETSIUnitSystemToSolAR.end()) + return datastructure::UnitSystem::M; + else + return it->second; +} + +std::string SolARUnitSystem2ETSI (const datastructure::UnitSystem unitySystem) +{ + std::map::const_iterator it = solarUnitSystemToETSI.find(unitySystem); + if (it == solarUnitSystemToETSI.end()) + return "M"; + else + return it->second; +} + +std::string ETSIDataFormat2SolARStorage (const std::string unitySystem) +{ + std::map::const_iterator it = solarStorageDataFormatToETSI.find(unitySystem); + if (it == solarStorageDataFormatToETSI.end()) + return "other"; + else + return it->second; +} + +std::string SolARDataFormat2ETSI (const std::string unitySystem) +{ + std::map::const_iterator it = solarStorageDataFormatToETSI.find(unitySystem); + if (it == solarStorageDataFormatToETSI.end()) + return "OTHER"; + else + return it->second; +} + +/** + * @brief convert pointer datastructure::StorageTrackable to a pointer of trackable_t* + * @param trackable + * @return trackable in trackable_t* structure + */ +trackable_t* SolARToETSITrackable(SRef trackable) +{ + //Use the fonction of server model trackable and transform it to char* JSON + org::openapitools::server::model::Trackable t = org::openapitools::server::implem::TrackablesSolARImpl::from_storage(*trackable); + std::string jsonString = t.toJsonString(); + char* CharTrackableJson = new char[jsonString.size()+1]; + strcpy(CharTrackableJson, jsonString.data()); + + //parse json of the trackable + cJSON* a = cJSON_Parse(CharTrackableJson); + + //use trackable_t parsing json fonction to obtain the result + trackable_t* etsiTrackable =trackable_parseFromJSON(a); + + return etsiTrackable; +} + +/** + * @brief convert json char* of a trackable in SRef + * @param trackable a char* json of a trackable + * @return trackable in a pointer of SolAR StorageTrackabe + */ +SRef JSONTrackableToSolAR(char* trackable) { + + + //convert the json in a server model Trackable to make easier the conversion + org::openapitools::server::model::Trackable t; + t.fromJsonString(trackable); + //UUID + xpcf::uuids::uuid trackableUUID = xpcf::toUUID(t.getUUID()); + //creator uuid + xpcf::uuids::uuid creatorId = xpcf::toUUID(t.getCreatorUUID()); + + //localCRS + std::vector vector = t.getLocalCRS(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df localCRS(matrix); + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = ETSIUnitSystem2SolARStorage(t.getUnit().getEnumValue()); + + //dimension + Eigen::Vector3d dimension = Eigen::Vector3d(t.getTrackableSize().data()); + + //taglist + std::multimap keyvalueTagList; + for (const auto &tag : t.getKeyvalueTags()){ + for(const auto &value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //trackable type + SolAR::datastructure::StorageTrackableType type = ETSITrackableType2SolARStorage(t.getTrackableType().getEnumValue()); + + //encoding info + SolAR::datastructure::EncodingInfo encodingInfo(t.getTrackableEncodingInformation().getDataFormat(), t.getTrackableEncodingInformation().getVersion()); + + //payload + std::vector payload = org::openapitools::server::implem::TrackablesSolARImpl::to_bytes(t.getTrackablePayload()); + + //name + std::string name = t.getName(); + + //create the trackable + SRef storageTrackable = xpcf::utils::make_shared(trackableUUID, creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); + + return storageTrackable; +} + +/** + * @brief convert json char* of a worldAnchor in SRef + * @param worldAnchor a char* json of a worldAnchor + * @return worldAnchor in a pointer of SolAR StorageWorldAnchor + */ +SRef JSONWorldAnchorToSolAR(char* worldAnchor) { + + //convert the json in a server model WorldAnchor to make easier the conversion + org::openapitools::server::model::WorldAnchor w; + w.fromJsonString(worldAnchor); + + //creatorUUID + xpcf::uuids::uuid creatorId = xpcf::toUUID(w.getCreatorUUID()); + + //localCRS + std::vector vector = w.getLocalCRS(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df localCRS(matrix); + + //size + Eigen::Vector3d size = Eigen::Vector3d(w.getWorldAnchorSize().data()); + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = org::openapitools::server::implem::resolve_unitSystem(w.getUnit()); + + //taglist + std::multimap keyvalueTagList; + for (const auto &tag : w.getKeyvalueTags()){ + for(const auto &value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //name + std::string name = w.getName(); + + //create a world anchor + SRef storageWorldAnchor = xpcf::utils::make_shared(creatorId, localCRS, unitSystem, size, keyvalueTagList, name); + return storageWorldAnchor; + +} + +list_t* SolARToETSILocalCRS(const datastructure::Transform3Df transform3D) +{ + list_t* localCRS= new list_t(); + return localCRS; + +} + +list_t* SolARToETSISize(const datastructure::Vector3d size) +{ + list_t* etsiSize= new list_t(); + return etsiSize; + +} + +list_t* SolARToETSIKeyvalueTags(const std::multimap tags) +{ + list_t* etsiTags= new list_t(); + return etsiTags; + +} + +/** + * @brief convert pointer datastructure::StorageWorldAnchor to a pointer of world_anchor_t* + * @param worldAnchor + * @return worldAnchor in world_anchor_t* structure + */ +world_anchor_t* SolARToETSIWorldAnchor(SRef worldAnchor) +{ +/* + char* name = new char[worldAnchor->getName().size() + 1]; + strcpy(name, worldAnchor->getName().c_str()); + world_anchor_t* worldAnchorEtsi = world_anchor_create( + xpcf::uuids::to_string(worldAnchor->getID()).data(), + name, + xpcf::uuids::to_string(worldAnchor->getCreatorID()).data(), + SolARToETSILocalCRS(worldAnchor->getLocalCrs()), + unit_system_unit_system_FromString(SolARUnitSystem2ETSI(worldAnchor->getUnitSystem()).data()), + SolARToETSISize(worldAnchor->getSize()), + SolARToETSIKeyvalueTags(worldAnchor->getTags())); +*/ + //Use the fonction of server model WorldAnchor and transform it to char* JSON + org::openapitools::server::model::WorldAnchor w = org::openapitools::server::implem::WorldAnchorsSolARImpl::from_storage(*worldAnchor); + + std::string strWorldAnchorJson = w.toJsonString(); + char* CharWorldAnchorJson = new char[strWorldAnchorJson.size()+1]; + strcpy(CharWorldAnchorJson, strWorldAnchorJson.data()); + + //parse json of the worldAnchor + world_anchor_t* etsiWorldAnchor = world_anchor_parseFromJSON(cJSON_Parse(CharWorldAnchorJson)); + + return etsiWorldAnchor; +} + +/** + * @brief convert pointer datastructure::StorageWorldLink to a pointer of world_link_t* + * @param worldLink + * @return worldLink in world_link_t* structure + */ +world_link_t* SolARToETSIWorldLink(SRef worldLink){ + + //Use the fonction of server model worldLink and transform it to char* JSON + org::openapitools::server::model::WorldLink l = org::openapitools::server::implem::WorldLinksSolARImpl::from_storage(*worldLink); + + char* CharWorldLinkJson = new char[l.toJsonString().size()+1]; + strcpy(CharWorldLinkJson, l.toJsonString().c_str()); + + //parse json of the worldLink + world_link_t* etsiWorldLink = world_link_parseFromJSON(cJSON_Parse(CharWorldLinkJson)); + return etsiWorldLink; +} + +/** + * @brief convert json char* of a worldLink in SRef + * @param worldLink a char* json of a worldLink + * @return worldLink in a pointer of SolAR StorageWorldLink + */ +SRef JSONWorldLinkToSolAR(char* worldLink){ + + //convert the json in a server model worldLink to make easier the conversion + org::openapitools::server::model::WorldLink l; + l.fromJsonString(worldLink); + + //authorId + xpcf::uuids::uuid authorId = xpcf::toUUID(l.getCreatorUUID()); + + //transform 3d + std::vector vector = l.getTransform(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df transfo(matrix); + + //world element from ID + xpcf::uuids::uuid fromElementId = xpcf::toUUID(l.getUUIDFrom()); + + //world element to ID + xpcf::uuids::uuid toElementId = xpcf::toUUID(l.getUUIDTo()); + + + //world element from type + SolAR::datastructure::ElementKind fromElementType = org::openapitools::server::implem::WorldLinksSolARImpl::resolve_element_kind(l.getTypeFrom()); + + //world element to type + SolAR::datastructure::ElementKind toElementType = org::openapitools::server::implem::WorldLinksSolARImpl::resolve_element_kind(l.getTypeTo()); + + //adding the link to the storage by calling the world storage method + xpcf::uuids::uuid linkId; + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = org::openapitools::server::implem::resolve_unitSystem(l.getUnit()); + + //keytags + std::multimap keyvalueTagList; + for (const auto &tag : l.getKeyvalueTags()){ + for(const auto &value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + xpcf::utils::shared_ptr storageWorldLink = xpcf::utils::make_shared(authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); + + return storageWorldLink; +} + +ETSIWorldGraphClient::ETSIWorldGraphClient():xpcf::ConfigurableBase(xpcf::toUUID()) +{ + declareInterface(this); + declareProperty("url", m_url); +} + +ETSIWorldGraphClient::~ETSIWorldGraphClient() +{ + +} + +xpcf::XPCFErrorCode ETSIWorldGraphClient::onConfigured() +{ + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return xpcf::XPCFErrorCode::_FAIL; + } + + // Add custom onConfigured code + m_apiClient = apiClient_create_with_base_path(m_url.c_str(), NULL); + return xpcf::XPCFErrorCode::_SUCCESS; +} + +///////////////////////////////// +/// GRAPH INFORMATION METHODS /// +///////////////////////////////// +FrameworkReturnCode ETSIWorldGraphClient::getRelocalizationInformation (const std::vector> &uuids, const std::string &token,const std::vector &capabilities,std::vector &relocalizationInformation ) +{ + LOG_DEBUG("Request Relocalization Information : \n "); + + //list to pass in param of request + list_t *uuidToSend = list_createList(); + + //string value for one element of uuidToSend + std::string uuidStr = ""; + + //construct each element of the request for each pair of (uuid,mode) + for (size_t i = 0; i < uuids.size(); ++i) { + + //get the pair + const auto& uuid = uuids[i]; + + //form the encode Json of the element for the request + uuidStr += "%7B%22uuid%22%3A%22" + xpcf::uuids::to_string(std::get<0>(uuid)) + "%22%2C%22mode%22%3A%22"; + if (std::get<1>(uuid)) { + uuidStr += "TRACKABLES_TO_REQUEST%22%7D"; + } else { + uuidStr += "REQUEST_TO_TRACKABLES%22%7D"; + } + LOG_DEBUG("uuidStr: {}", uuidStr); + + //convert element into a char* + char* EncodeJson = new char[uuidStr.size()+1]; + strcpy(EncodeJson,uuidStr.c_str()); + + //add element to the list + list_addElement(uuidToSend,EncodeJson); + uuidStr = ""; + } + + + //list of capabilities + list_t *capabilitiesToSend = list_createList(); + std::string capabilityStr = ""; + for (size_t i = 0; i < capabilities.size(); ++i) { + //get the capability element + const auto& capability = capabilities[i]; + + //form the encode json element with the info of capabilty + datastructure::EncodingInfo encodInfo = capability.getEncodingInformation(); + capabilityStr += "%7B%22trackableType%22%3A%22" + datastructure::resolveTrackableType(capability.getTrackableType()) + + "%22%2C%22encodingInformation%22%3A%7B%22dataFormat%22%3A%20%22" + encodInfo.getDataFormat() + + "%22%2C%22version%22%3A%20%22" + encodInfo.getVersion()+ "%22%7D%7D"; + + + //convert the string element in char* + char* EncodeCapabilityJson = new char[capabilityStr.size()+1]; + strcpy(EncodeCapabilityJson,capabilityStr.c_str()); + + //add element to the list + list_addElement(capabilitiesToSend,EncodeCapabilityJson); + capabilityStr = ""; + } + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + //send the request and get the relocalization information object + relocalization_informations_t* resultObject = RelocalizationInformationAPI_getRelocalizationInformation(m_apiClient,uuidToSend,capabilitiesToSend,NULL); + if(!resultObject){ + LOG_DEBUG("RelocalizationInformationAPI_getRelocalizationInformation error"); + return FrameworkReturnCode::_ERROR_; + } + + //convert reloc object list in a server model RelocalizationInformation object list + std::vector r ; + org::openapitools::server::model::RelocalizationInformations response; + response.fromJsonString(cJSON_Print(relocalization_informations_convertToJSON(resultObject))); + LOG_DEBUG("JSON response: {}", cJSON_Print(relocalization_informations_convertToJSON(resultObject))); + r = response.getRelocInfo(); + + //iterate through the list for each requestUUID and fill all the information needeed in relocalizationInformation parameter + for( org::openapitools::server::model::RelocalizationInformation relocItem : r){ + + //element to add to relocalizationInformation parameter + datastructure::RelocalizationInformation relocToadd; + + //setRequestUUID + std::string rootUUID(relocItem.getRequestUUID()); + LOG_DEBUG("rootUUID: {}", rootUUID); + relocToadd.setRootUUID(boost::lexical_cast(rootUUID.c_str())); + + //set RelocObject + std::vector relocObjToadd; + for (org::openapitools::server::api::RelocObject relocObj : relocItem.getRelocObjects()){ + //convert relocObject client model into a SolAR relocObject + datastructure::RelocObject SolARrelocObj; + + //get the trackable JSON + char * jsonTrack =new char[ relocObj.getTrackable().toJsonString().size()+1]; + strcpy(jsonTrack, relocObj.getTrackable().toJsonString().c_str()); + LOG_DEBUG("JSON trackable; {}", jsonTrack); + + //set Trackable + SolARrelocObj.setTrackable(*JSONTrackableToSolAR( jsonTrack)); + + //define the matrix of the Transform 3D + Eigen::Matrix4f mat; + for (size_t i = 0; i < 4; ++i) { + for (size_t j = 0; j < 4; ++j) { + mat(i, j) = relocObj.getTransform3D()[i * 4 + j]; + } + } + + //set the transform3D + SolARrelocObj.setTransform3D(SolAR::datastructure::Transform3Df(mat)); + + //Push the element to the list of relocObject + relocObjToadd.push_back(SolARrelocObj); + } + relocToadd.setRelocObjects(relocObjToadd); + //push the relocalizationInformation object + relocalizationInformation.push_back(relocToadd); + } + + return FrameworkReturnCode::_SUCCESS; + + +} + +//////////////////////////// +/// WORLDELEMENT METHODS /// +//////////////////////////// + +FrameworkReturnCode ETSIWorldGraphClient::getWorldElement(const org::bcom::xpcf::uuids::uuid& worldElementId, SRef& worldElement) +{ + + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldElements(std::vector> &vector) +{ + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldElementByKeyValue(const std::string &key, const std::string &value,std::vector> &vector) +{ + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldElementByKey(const std::string &key, std::vector> &vector) +{ + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +///////////////////////// +/// TRACKABLE METHODS /// +///////////////////////// + + + +FrameworkReturnCode ETSIWorldGraphClient::addTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable) +{ + //convert the trackable to send request + trackable_t* etsiTrackable = SolARToETSITrackable(trackable); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + //send request and receive the uuid of the trackable posted + success_t* returnedMessage = TrackablesAPI_addTrackable(m_apiClient, etsiTrackable, NULL); + try { + //fill the result uuid + id = boost::lexical_cast(returnedMessage->message); + } catch (const boost::bad_lexical_cast& e) { + LOG_ERROR("Failed to convert UUID: {}. Error: {}", returnedMessage->message, e.what()); + return FrameworkReturnCode::_ERROR_; + } + + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::getTrackable(const org::bcom::xpcf::uuids::uuid &trackableId, SRef &trackable) +{ + char* id = new char[xpcf::uuids::to_string(trackableId).size()+1]; + strcpy(id, xpcf::uuids::to_string(trackableId).c_str()); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + trackable_t* t = TrackablesAPI_getTrackableById(m_apiClient, id, NULL); + if(t == nullptr){ + return FrameworkReturnCode::_NOT_FOUND; + } + trackable =JSONTrackableToSolAR(cJSON_Print(trackable_convertToJSON(t))); + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::removeTrackable(const org::bcom::xpcf::uuids::uuid &trackableId) +{ + char* id = new char[xpcf::uuids::to_string(trackableId).size()+1]; + strcpy(id, xpcf::uuids::to_string(trackableId).c_str()); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + TrackablesAPI_deleteTrackable(m_apiClient,id,NULL); + return FrameworkReturnCode::_SUCCESS; +} + + +FrameworkReturnCode ETSIWorldGraphClient::getTrackables(std::vector>& vector) +{ + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + trackables_response_t* trackables = TrackablesAPI_getTrackables(m_apiClient, NULL); + if (trackables == nullptr) { + return FrameworkReturnCode::_ERROR_; + } + for(int i =0 ; i< trackables->trackables->count ; i++ ){ + trackable_t* t = (trackable_t*) list_getElementAt(trackables->trackables,i); + + vector.push_back(JSONTrackableToSolAR((t->creator_uuid))); + } + return FrameworkReturnCode::_SUCCESS; + + +} + +FrameworkReturnCode ETSIWorldGraphClient::modifyTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable){ + trackable_t* etsiTrackable = SolARToETSITrackable(trackable); + + + char* idToSend = new char[xpcf::uuids::to_string(id).size()+1]; + strcpy(idToSend, xpcf::uuids::to_string(id).c_str()); + etsiTrackable->uuid = idToSend; + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + success_t* returnedMessage = TrackablesAPI_modifyTrackable(m_apiClient, etsiTrackable, NULL); + + if (returnedMessage != nullptr) { + try { + id = boost::lexical_cast(returnedMessage->message); + } catch (const boost::bad_lexical_cast& e) { + LOG_ERROR("Failed to convert UUID: {}. Error: {}", returnedMessage->message, e.what()); + return FrameworkReturnCode::_ERROR_; + } + } else { + LOG_ERROR("UUID is null"); + return FrameworkReturnCode::_ERROR_; + } + return FrameworkReturnCode::_SUCCESS; +} + + +/////////////////////////// +/// WORLDANCHOR METHODS /// +/////////////////////////// + +FrameworkReturnCode ETSIWorldGraphClient::addWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor) +{ + //convert the worldAnchor to send request + world_anchor_t* etsiWorldAnchor = SolARToETSIWorldAnchor(worldAnchor); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + LOG_INFO("URL : {}",m_url); + success_t* returnedMessage = WorldAnchorsAPI_addWorldAnchor(m_apiClient, etsiWorldAnchor, NULL); + + try { + id = boost::lexical_cast(returnedMessage->message); + } catch (const boost::bad_lexical_cast& e) { + LOG_ERROR("Failed to convert UUID: {}. Error: {}", returnedMessage->message, e.what()); + return FrameworkReturnCode::_ERROR_; + } + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId, SRef& worldAnchor) +{ + char* id = new char[xpcf::uuids::to_string(worldAnchorId).size()+1]; + strcpy(id, xpcf::uuids::to_string(worldAnchorId).c_str()); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + world_anchor_t* w = WorldAnchorsAPI_getWorldAnchorById(m_apiClient,id,NULL); + if(w == nullptr){ + return FrameworkReturnCode::_NOT_FOUND; + } + worldAnchor =JSONWorldAnchorToSolAR(cJSON_Print(world_anchor_convertToJSON(w))); + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::removeWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId) +{ + char* id = new char[xpcf::uuids::to_string(worldAnchorId).size()+1]; + strcpy(id, xpcf::uuids::to_string(worldAnchorId).c_str()); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + WorldAnchorsAPI_deleteWorldAnchor(m_apiClient,id,NULL); + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldAnchors(std::vector>& vector) +{ + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + world_anchors_response_t* worldAnchor = WorldAnchorsAPI_getWorldAnchors(m_apiClient, NULL); + if (worldAnchor == nullptr) { + return FrameworkReturnCode::_ERROR_; + } + for(int i =0 ; i< worldAnchor->world_anchors->count ; i++ ){ + world_anchor_t* w = (world_anchor_t*) list_getElementAt(worldAnchor->world_anchors,i); + + vector.push_back(JSONWorldAnchorToSolAR((w->creator_uuid))); + } + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::modifyWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor){ + world_anchor_t* etsiWorldAnchor = SolARToETSIWorldAnchor(worldAnchor); + + + char* idToSend = new char[xpcf::uuids::to_string(id).size()+1]; + strcpy(idToSend, xpcf::uuids::to_string(id).c_str()); + etsiWorldAnchor->uuid = idToSend; + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + success_t* uuid = WorldAnchorsAPI_modifyWorldAnchor(m_apiClient, etsiWorldAnchor, NULL); + + if (uuid != nullptr) { + try { + id = boost::lexical_cast(uuid->message); + } catch (const boost::bad_lexical_cast& e) { + LOG_ERROR("Failed to convert UUID: {}. Error: {}", uuid->message, e.what()); + return FrameworkReturnCode::_ERROR_; + } + } else { + LOG_ERROR("UUID is null"); + return FrameworkReturnCode::_ERROR_; + } + return FrameworkReturnCode::_SUCCESS; +} + +///////////////////////// +/// WORLDLINK METHODS /// +///////////////////////// + +FrameworkReturnCode ETSIWorldGraphClient::addWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink) +{ + world_link_t* etsiWorldLink = SolARToETSIWorldLink(worldLink); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + success_t* uuid = WorldLinksAPI_addWorldLink(m_apiClient, etsiWorldLink, NULL); + + try { + id = boost::lexical_cast(uuid->message); + } catch (const boost::bad_lexical_cast& e) { + LOG_ERROR("Failed to convert UUID: {}. Error: {}", uuid->message, e.what()); + return FrameworkReturnCode::_ERROR_; + } + + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId, SRef &worldLink) +{ + + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldLink(const org::bcom::xpcf::uuids::uuid &linkId, SRef &worldLink) +{ + char* id = new char[xpcf::uuids::to_string(linkId).size()+1]; + strcpy(id, xpcf::uuids::to_string(linkId).c_str()); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + world_link_t* w = WorldLinksAPI_getWorldLinkById(m_apiClient,id,NULL); + if(w == nullptr){ + return FrameworkReturnCode::_NOT_FOUND; + } + worldLink =JSONWorldLinkToSolAR(cJSON_Print(world_link_convertToJSON(w))); + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::removeWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId) +{ + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +FrameworkReturnCode ETSIWorldGraphClient::removeWorldLink(const org::bcom::xpcf::uuids::uuid &linkId) +{ + char* id = new char[xpcf::uuids::to_string(linkId).size()+1]; + strcpy(id, xpcf::uuids::to_string(linkId).c_str()); + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + WorldLinksAPI_deleteWorldLink(m_apiClient,id,NULL); + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::getWorldLinks(std::vector>& vector){ + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + LOG_INFO("URL : {}",m_url); + world_links_response_t* worldLinks = WorldLinksAPI_getWorldLinks(m_apiClient, NULL); + if (worldLinks == nullptr) { + return FrameworkReturnCode::_NOT_FOUND; + } + + listEntry_t *entry; + list_ForEach(entry, worldLinks->world_links) { + vector.push_back(JSONWorldLinkToSolAR(((char*)entry->data))); + } + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::modifyWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink){ + world_link_t* etsiWorldLink = SolARToETSIWorldLink(worldLink); + + + char* idToSend = new char[xpcf::uuids::to_string(id).size()+1]; + strcpy(idToSend, xpcf::uuids::to_string(id).c_str()); + etsiWorldLink->uuid = idToSend; + + //check if URL is empty + if(m_url.empty()){ + LOG_ERROR("Please precise an URL"); + return FrameworkReturnCode::_ERROR_; + } + + success_t* uuid = WorldLinksAPI_modifyWorldLink(m_apiClient, etsiWorldLink, NULL); + + if (uuid != nullptr) { + try { + id = boost::lexical_cast(uuid->message); + } catch (const boost::bad_lexical_cast& e) { + LOG_ERROR("Failed to convert UUID: {}. Error: {}", uuid->message, e.what()); + return FrameworkReturnCode::_ERROR_; + } + } else { + LOG_ERROR("UUID is null"); + return FrameworkReturnCode::_ERROR_; + } + return FrameworkReturnCode::_SUCCESS; +} + +FrameworkReturnCode ETSIWorldGraphClient::load(std::string path) +{ + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +FrameworkReturnCode ETSIWorldGraphClient::save(std::string path) +{ + return FrameworkReturnCode::_NOT_IMPLEMENTED; +} + +} // namespace SolARModuleWorldStorage +} // namespace MODULES +} // namespace SolAR diff --git a/SolARModuleWorldGraph/src/ETSIWorldGraphManager.cpp b/SolARModuleWorldGraph/src/ETSIWorldGraphManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0cd83b35193c1a2136b7f3f92baae254a70db76 --- /dev/null +++ b/SolARModuleWorldGraph/src/ETSIWorldGraphManager.cpp @@ -0,0 +1,951 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2021-2022 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ETSIWorldGraphManager.h" + + +namespace xpcf = org::bcom::xpcf; + +XPCF_DEFINE_FACTORY_CREATE_INSTANCE(SolAR::MODULES::SolARModuleWorldStorage::ETSIWorldGraphManager) + +namespace SolAR { +namespace MODULES { +namespace SolARModuleWorldStorage { + + using Graph = boost::adjacency_list, SRef>; + using Vertex = boost::graph_traits::vertex_descriptor; + using VertexIt = boost::graph_traits::vertex_iterator; + using Edge = boost::graph_traits::edge_descriptor; + using EdgeIt = boost::graph_traits::edge_iterator; + + + ETSIWorldGraphManager::ETSIWorldGraphManager():ConfigurableBase(xpcf::toUUID()) + { + declareInterface(this); + + declareProperty("worldGraphPath",m_worldGraphPath); + declareProperty("automaticSave",m_automaticSave); + LOG_DEBUG("ETSIWorldGraphManager constructor"); + } + + xpcf::XPCFErrorCode ETSIWorldGraphManager::onConfigured() + { + LOG_DEBUG("ETSIWorldGraphManager onConfigured"); + + if ( load(m_worldGraphPath) != FrameworkReturnCode::_SUCCESS) + { + LOG_WARNING("Unable to load world graph with path: {}", m_worldGraphPath); + } + return xpcf::XPCFErrorCode::_SUCCESS; + } + + ///////////////////////////////// + /// GRAPH INFORMATION METHODS /// + ///////////////////////////////// + FrameworkReturnCode ETSIWorldGraphManager::getRelocalizationInformation (const std::vector> &uuids, const std::string &token,const std::vector &capabilities,std::vector &relocalizationInformation ) + { + LOG_INFO("Fetching Relocalization Information : \n "); + try{ + + //Iterate on all pairs of uuids and boolean + for( const std::tuple &pair : uuids ){ + + + //search for all trackable and their transform under the root UUID + + //the root uuid : parent of all relocObjects to search + org::bcom::xpcf::uuids::uuid rootUUID = std::get<0>(pair); + + bool isDeviceToWorldAnchor = std::get<1>(pair); + + //the list of relocObjects children of rootUUID + std::vector obj; + + //Get all info on roottUUID's children : trackable and their transform + ETSIWorldGraphManager::getAllTrackableChild(rootUUID,obj,rootUUID,capabilities,isDeviceToWorldAnchor); + if(!obj.empty()){ + //Save into the good RelocalizationInformation format and add it to the list + datastructure::RelocalizationInformation result(std::get<0>(pair),obj,std::get<1>(pair)); + + relocalizationInformation.push_back(result); + } + } + if(relocalizationInformation.empty()){ + return FrameworkReturnCode::_NOT_FOUND; + } + return FrameworkReturnCode::_SUCCESS; + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + + /** + * @brief ETSIWorldGraphManager::getAllTrackableChild the recursive function for retrieve child's information of a WorldElement in the graph + * @param rootUUID The current uuid in the recursive method + * @param obj the return object which contains informations and transforms of all trackable + * @param OriginalRootUUID the original UUID requested + * @param capabilities the list of informations needeed to decide if a trackable is supported by the user or not + * @param isDeviceToWorldAnchor a boolean defining the context of the transform between originalRootUUID and the trackable + */ + void ETSIWorldGraphManager::getAllTrackableChild(const org::bcom::xpcf::uuids::uuid rootUUID, std::vector& obj,const org::bcom::xpcf::uuids::uuid OriginalRootUUID,const std::vector capabilities,bool isDeviceToWorldAnchor){ + + + SRef RootUUID; + SRef trackableRoot; + + //check if the UUID exist + FrameworkReturnCode c = ETSIWorldGraphManager::getWorldElement(rootUUID,RootUUID); + if(c == FrameworkReturnCode::_NOT_FOUND){ + LOG_ERROR("UUID not found"); + + } + else{ + //Check if the original rootUUID is a trackable : if yes just return information of this trackable + ETSIWorldGraphManager::getTrackable(rootUUID,trackableRoot); + if (trackableRoot) { + if(trackableRoot->getKind() == datastructure::ElementKind::TRACKABLE){ + + datastructure::EncodingInfo track = trackableRoot->getEncodingInfo(); + if(isSupported(capabilities,*trackableRoot)){ + //the child to construct and to add to the list + datastructure::RelocObject childObj; + + //construct the object with the right informations + childObj.setTrackable(*trackableRoot); + //the request is asked for one trackable so the transform is the identity matrix + datastructure::Transform3Df identity; + identity.setIdentity(); + childObj.setTransform3D(identity); + //give the trackable info + obj.push_back(childObj); + } + else{ + LOG_INFO("this trackable is not supported by the user"); + } + } + } + //if the root uuid is not a trackable, we search for his childs + else { + //the list of links wich are coming from rootUUID + std::vector> children = getChildren(rootUUID); + + //Iterate on all children of rootUUID + for(SRef& childLink : children ){ + //the child to construct and to add to the list + datastructure::RelocObject childObj; + + //the pointer to the trackable + SRef childObjTrack; + FrameworkReturnCode code; + + //check the type of the child + switch(childLink->getTypeTo()){ + + case datastructure::ElementKind::TRACKABLE : + + //get the reference to the trackable + + code = ETSIWorldGraphManager::getTrackable(childLink->getUuidTo(),childObjTrack); + if ( code == FrameworkReturnCode::_SUCCESS) { + + //get the value of the reference + const datastructure::StorageTrackable& trackableRef = *childObjTrack.get(); + + if(isSupported(capabilities,trackableRef)){ + //add it to the list of child to return + childObj.setTrackable(trackableRef); + + //check if the parent is the original root UUID so we just send the transform of ChildLink + if(childLink->getUuidFrom() == OriginalRootUUID){ + childObj.setTransform3D(childLink->getTransform() * trackableRef.getLocalCrs()); + } + //else we need to comput the transform from the trackable to the original root UUID + else{ + datastructure::Transform3Df TransformToRoot; + TransformToRoot = childLink->getTransform(); + childObj.setTransform3D(getTransformToRoot(childLink,OriginalRootUUID,TransformToRoot,isDeviceToWorldAnchor) * trackableRef.getLocalCrs()); + } + + obj.push_back(childObj); + } + else{ + LOG_INFO("this trackable is not supported by the user"); + } + } + else if(code == FrameworkReturnCode::_NOT_FOUND){ + LOG_ERROR("Exception raised : Child Trackable not found"); + } + else{ + LOG_ERROR("Exception raised : failed to retrieve child trackable"); + } + break; + case datastructure::ElementKind::ANCHOR : + //if the child is an anchor we do the same operation on this anchor + ETSIWorldGraphManager::getAllTrackableChild(childLink->getUuidTo(),obj,OriginalRootUUID,capabilities,isDeviceToWorldAnchor); + break; + case datastructure::ElementKind::INVALID : + //empty case : we do nothing + break; + } + } + } + } + } + + + /** + * @brief ETSIWorldGraphManager::getChildren private function for getRelocalizationInformation : get all descendant link from the root UUID ( can be empty if no child ) + * @param root the parent uuid + * @return a list of links which are the children of root + */ + std::vector> ETSIWorldGraphManager::getChildren(const org::bcom::xpcf::uuids::uuid root){ + + //The list to return + std::vector> result; + + //Iterate on all links + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + //Check if the link come from the root, if yes we add it to the result + if(graph[*ei]->getUuidFrom() == root){ + result.push_back(graph[*ei]); + } + + + } + + return result; + } + + + /** + * @brief ETSIWorldGraphManager::getParent private function for getRelocalizationInformation : get ascendent link from the root UUID ( can be empty if no parent ) + * @param root the child uuid + * @return a links which are the parent of root + */ + SRef ETSIWorldGraphManager::getParent(const org::bcom::xpcf::uuids::uuid root){ + + //The link to return + SRef result; + + //Iterate on all links + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + //Check if the link point on the root, if yes we return it + if(graph[*ei]->getUuidTo() == root){ + + result = graph[*ei]; + return result; + } + } + return result; + } + + /** + * @brief ETSIWorldGraphManager::getTransformToRoot private function for getRelocalizationInformation : compute the transform3D wich link the trackable to the original WorldElement asked + * @param firstLink the link whicjh link the trackable uuid to his parent + * @param root the uuid of the worldElement which is the stop condition of the function + * @param res the transform to return which contains the current transform linked to the trackable + * @param isDeviceToWorldAnchor a boolean defining the context of the transform between originalRootUUID and the trackable + * @return + */ + datastructure::Transform3Df ETSIWorldGraphManager::getTransformToRoot(const SRef firstLink,const org::bcom::xpcf::uuids::uuid root,datastructure::Transform3Df& res,bool isDeviceToWorldAnchor){ + + //get the parent from the first link + org::bcom::xpcf::uuids::uuid up = firstLink->getUuidFrom(); + + //stop condition : if the parent of the link is the root, we return res + if(up == root){ + return res; + } + //compute the produce of the transform with the transform of the parent's link + else{ + //check if the parent exist + SRef next = getParent(up); + if(next){ + + //compute in the right order + if(isDeviceToWorldAnchor){ + res = res * next->getTransform(); + } + else{ + res = next->getTransform() * res ; + } + //do the same until we found the root + res = getTransformToRoot(next,root,res,isDeviceToWorldAnchor); + } + return res; + } + } + + + /** + * @brief ETSIWorldGraphManager::isSupported private function which returns a boolean which indicate if the trackable in parameters is supported by the user + * @param capabilities a list of object containing information of wich data is supported by the user + * @param track the trackable to test if it is supported + * @return a boolean which indicate if the trackable track is supported + */ + bool ETSIWorldGraphManager::isSupported(const std::vector capabilities,const datastructure::StorageTrackable track){ + + datastructure::StorageCapabilities trackableInfos; + trackableInfos.setTrackableType(track.getType()); + trackableInfos.setEncodingInformation(track.getEncodingInfo()); + datastructure::EncodingInfo encodingInfoCopy = track.getEncodingInfo(); + + for(datastructure::StorageCapabilities capability : capabilities){ + if(capability.equals( trackableInfos)){ + return true; + } + } + return false; + + }; + + //////////////////////////// + /// WORLDELEMENT METHODS /// + //////////////////////////// + + FrameworkReturnCode ETSIWorldGraphManager::getWorldElement(const org::bcom::xpcf::uuids::uuid& worldElementId, SRef& worldElement) + { + LOG_INFO("Fetching world element"); + try + { + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getID() == worldElementId) + { + worldElement = graph[*vi]; + return FrameworkReturnCode::_SUCCESS; + } + } + + //WorldElement not found + worldElement = SRef(); + return FrameworkReturnCode::_NOT_FOUND; + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldElements(std::vector> &vector) + { + LOG_INFO("Fetching all world elements"); + try + { + SRef worldElement; + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + switch(graph[*vi]->getKind()){ + case datastructure::ElementKind::TRACKABLE : + worldElement = xpcf::utils::dynamic_pointer_cast(graph[*vi]); + vector.push_back(worldElement); + break; + case datastructure::ElementKind::ANCHOR : + worldElement = xpcf::utils::dynamic_pointer_cast(graph[*vi]); + vector.push_back(worldElement); + break; + case SolAR::datastructure::ElementKind::INVALID : + LOG_ERROR("Element unidentified"); + break; + default : + LOG_ERROR("Element unidentified"); + break; + } + } + return FrameworkReturnCode::_SUCCESS; + } + catch ( std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldElementByKeyValue(const std::string &key, const std::string &value,std::vector> &vector) + { + return FrameworkReturnCode::_NOT_IMPLEMENTED; + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldElementByKey(const std::string &key, std::vector> &vector) + { + return FrameworkReturnCode::_NOT_IMPLEMENTED; + } + + ///////////////////////// + /// TRACKABLE METHODS /// + ///////////////////////// + + FrameworkReturnCode ETSIWorldGraphManager::addTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable) + { + LOG_INFO("Adding trackable"); + try + { + Vertex vertex = boost::add_vertex(graph); + graph[vertex] = trackable; + + //The param that is to be changed + id = trackable->getID(); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getTrackable(const org::bcom::xpcf::uuids::uuid &trackableId, SRef &trackable) + { + LOG_INFO("Fetching trackable"); + try + { + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getID() == trackableId && graph[*vi]->getKind() == datastructure::ElementKind::TRACKABLE) + { + trackable = xpcf::utils::dynamic_pointer_cast(graph[*vi]); + return FrameworkReturnCode::_SUCCESS; + } + } + //trackable not found + trackable = SRef(); + return FrameworkReturnCode::_NOT_FOUND; + + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::removeTrackable(const org::bcom::xpcf::uuids::uuid &trackableId) + { + LOG_INFO("Removing trackable"); + try { + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getID() == trackableId && graph[*vi]->getKind() == datastructure::ElementKind::TRACKABLE) + { + boost::clear_vertex(*vi, graph); + boost::remove_vertex(*vi, graph); + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + } + return FrameworkReturnCode::_NOT_FOUND; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getTrackables(std::vector>& vector) + { + LOG_INFO("Fetching all trackables"); + try + { + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getKind() == datastructure::ElementKind::TRACKABLE){ + SRef trackable = xpcf::utils::dynamic_pointer_cast(graph[*vi]); + vector.push_back(trackable); + } + } + return FrameworkReturnCode::_SUCCESS; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::modifyTrackable(org::bcom::xpcf::uuids::uuid& id, SRef trackable){ + LOG_INFO("Modifying Trackable"); + try + { + boost::uuids::uuid trackableId = trackable->getID(); + + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getID() == trackableId && graph[*vi]->getKind() == datastructure::ElementKind::TRACKABLE) + { + //modify the trackable + graph[*vi] = trackable; + + //The param that is to be changed + id = graph[*vi]->getID(); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + } + //trackable not found + return FrameworkReturnCode::_NOT_FOUND; + + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + /////////////////////////// + /// WORLDANCHOR METHODS /// + /////////////////////////// + + FrameworkReturnCode ETSIWorldGraphManager::addWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor) + { + LOG_INFO("Adding anchor"); + try + { + Vertex vertex = boost::add_vertex(graph); + graph[vertex] = worldAnchor; + + id = worldAnchor->getID(); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId, SRef& worldAnchor) + { + LOG_INFO("Fetching anchor"); + try + { + + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getID() == worldAnchorId && graph[*vi]->getKind() == datastructure::ElementKind::ANCHOR) + { + worldAnchor = xpcf::utils::dynamic_pointer_cast(graph[*vi]); + return FrameworkReturnCode::_SUCCESS; + } + } + graph.vertex_by_property(worldAnchor); + + //anchor not found + worldAnchor = SRef(); + return FrameworkReturnCode::_NOT_FOUND; + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::removeWorldAnchor(const org::bcom::xpcf::uuids::uuid &worldAnchorId) + { + LOG_INFO("Removing anchor"); + try + { + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getID() == worldAnchorId && graph[*vi]->getKind() == datastructure::ElementKind::ANCHOR) + { + boost::clear_vertex(*vi, graph); + boost::remove_vertex(*vi, graph); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + } + return FrameworkReturnCode::_NOT_FOUND; + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldAnchors(std::vector>& vector) + { + LOG_INFO("Fetching anchor"); + try + { + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getKind() == datastructure::ElementKind::ANCHOR){ + SRef worldAnchor = xpcf::utils::dynamic_pointer_cast(graph[*vi]); + vector.push_back(worldAnchor); + } + } + return FrameworkReturnCode::_SUCCESS; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::modifyWorldAnchor(org::bcom::xpcf::uuids::uuid& id, SRef worldAnchor){ + LOG_INFO("Modifying anchor"); + try + { + boost::uuids::uuid worldAnchorId = worldAnchor->getID(); + + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); vi != viEnd; vi++) + { + if(graph[*vi]->getID() == worldAnchorId && graph[*vi]->getKind() == datastructure::ElementKind::ANCHOR) + { + //modify the worldAnchor + graph[*vi] = worldAnchor; + + //The param that is to be changed + id = graph[*vi]->getID(); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + } + //worldAnchor not found + return FrameworkReturnCode::_NOT_FOUND; + + } + catch(std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + ///////////////////////// + /// WORLDLINK METHODS /// + ///////////////////////// + + FrameworkReturnCode ETSIWorldGraphManager::addWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink) + { + LOG_INFO("Adding link"); + try + { + //we get the ids of the two connected elements + boost::uuids::uuid fromId = worldLink->getUuidFrom(); + boost::uuids::uuid toId = worldLink->getUuidTo(); + VertexIt vertexFrom = boost::vertices(graph).first; + VertexIt vertexTo = boost::vertices(graph).second; + + //we look for them in the world storage + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); ((vi != viEnd) && ((vertexFrom == viEnd) || (vertexTo == viEnd))); vi++) + { + if(graph[*vi]->getID() == fromId) + { + vertexFrom = vi; + } + if(graph[*vi]->getID() == toId) + { + vertexTo = vi; + } + } + if((vertexFrom != viEnd) && (vertexTo != viEnd)){ + auto pair = boost::add_edge(*vertexFrom, *vertexTo, worldLink, graph); + if(pair.second){ + id = graph[pair.first]->getId(); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + return FrameworkReturnCode::_ERROR_; + } + //The elements that are linked were not found + return FrameworkReturnCode::_NOT_FOUND; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId, SRef &worldLink) + { + LOG_INFO("Fetching link"); + try + { + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + if((graph[*ei]->getUuidFrom() == parentId) && (graph[*ei]->getUuidTo() == childId)) + { + worldLink = xpcf::utils::dynamic_pointer_cast(graph[*ei]); + return FrameworkReturnCode::_SUCCESS; + } + } + + //worldLink not found + worldLink = SRef(); + return FrameworkReturnCode::_NOT_FOUND; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldLink(const org::bcom::xpcf::uuids::uuid &linkId, SRef &worldLink) + { + LOG_INFO("Fetching link"); + try + { + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + if(graph[*ei]->getId() == linkId) + { + worldLink = xpcf::utils::dynamic_pointer_cast(graph[*ei]); + return FrameworkReturnCode::_SUCCESS; + } + } + + //worldLink not found + worldLink = SRef(); + return FrameworkReturnCode::_NOT_FOUND; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::removeWorldLink(const org::bcom::xpcf::uuids::uuid &parentId, const org::bcom::xpcf::uuids::uuid &childId) + { + LOG_INFO("Removing link"); + try + { + + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + if((graph[*ei]->getUuidFrom() == parentId) && (graph[*ei]->getUuidTo() == childId)) + { + boost::remove_edge(*ei, graph); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + } + + //worldLink not found + return FrameworkReturnCode::_NOT_FOUND; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::removeWorldLink(const org::bcom::xpcf::uuids::uuid &linkId) + { + LOG_INFO("Removing link"); + try + { + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + if((graph[*ei]->getId() == linkId)) + { + boost::remove_edge(*ei, graph); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + } + + //worldLink not found + return FrameworkReturnCode::_NOT_FOUND; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::getWorldLinks(std::vector>& vector){ + try + { + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + vector.push_back(graph[*ei]); + } + + return FrameworkReturnCode::_SUCCESS; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::modifyWorldLink(org::bcom::xpcf::uuids::uuid& id, SRef worldLink){ + LOG_INFO("Modifying link"); + try + { + boost::uuids::uuid worldLinkId = worldLink->getId(); + + EdgeIt ei, eiEnd; + for(boost::tie(ei,eiEnd) = edges(graph); ei != eiEnd; ei++) + { + if(graph[*ei]->getId() == worldLinkId) + { + //we verify that the elements it connects are present in the worldStorage + + //we get the ids of the two connected elements + boost::uuids::uuid fromId = worldLink->getUuidFrom(); + boost::uuids::uuid toId = worldLink->getUuidTo(); + + //we look for them in the world storage + bool foundFrom = false; + bool foundTo = false; + VertexIt vi, viEnd; + for(boost::tie(vi,viEnd) = vertices(graph); ((vi != viEnd) && !(foundFrom && foundTo)); vi++) + { + if(graph[*vi]->getID() == fromId) + { + foundFrom = true; + } + if(graph[*vi]->getID() == toId) + { + foundTo = true; + } + } + if(!(foundFrom && foundTo)){ + return FrameworkReturnCode::_NOT_FOUND; + } + + //the elements have been found + + //modify the worldAnchor + graph[*ei] = worldLink; + + //The param that is to be changed + id = graph[*ei]->getId(); + + // Save world graph if automatic saving + if (m_automaticSave) + save(m_worldGraphPath); + return FrameworkReturnCode::_SUCCESS; + } + } + + //worldLink not found + return FrameworkReturnCode::_NOT_FOUND; + } + catch (std::exception e) + { + //Exception raised + LOG_ERROR("Exception raised : \n {}", e.what()); + return FrameworkReturnCode::_ERROR_; + } + } + + FrameworkReturnCode ETSIWorldGraphManager::load(std::string path) + { + return FrameworkReturnCode::_SUCCESS; + } + + FrameworkReturnCode ETSIWorldGraphManager::save(std::string path) + { + return FrameworkReturnCode::_SUCCESS; + } + + +} // namespace SolARModuleWorldStorage +} // namespace MODULES +} // namespace SolAR diff --git a/SolARModuleWorldGraph/src/ETSIWorldGraphService.cpp b/SolARModuleWorldGraph/src/ETSIWorldGraphService.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79689c8df34ffab5f6f3d2437729cbcd8ae3c5bc --- /dev/null +++ b/SolARModuleWorldGraph/src/ETSIWorldGraphService.cpp @@ -0,0 +1,94 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2021-2022 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace xpcf = org::bcom::xpcf; + +XPCF_DEFINE_FACTORY_CREATE_INSTANCE(SolAR::MODULES::SolARModuleWorldStorage::ETSIWorldGraphService) + +namespace SolAR { +namespace MODULES { +namespace SolARModuleWorldStorage { + + ETSIWorldGraphService::ETSIWorldGraphService():xpcf::ConfigurableBase(xpcf::toUUID()) + { + declareInterface(this); + declareInjectable(m_worldGraphManager); + declareProperty("port", m_port); + declareProperty("serverNbThread", m_serverNbThread); + declareProperty("maxRequestSize", m_maxRequestSize); + declareProperty("maxResponseSize", m_maxResponseSize); + } + + ETSIWorldGraphService::~ETSIWorldGraphService() + { + + } + + xpcf::XPCFErrorCode ETSIWorldGraphService::onConfigured() + { + // Add custom onConfigured code + return xpcf::XPCFErrorCode::_SUCCESS; + } + + FrameworkReturnCode ETSIWorldGraphService::init() + { + m_restbedService = std::make_shared(); + m_restbedSettings = std::make_shared(); + + m_solarImpl = xpcf::utils::make_shared(m_restbedService); + m_relocImpl = xpcf::utils::make_shared(m_restbedService,m_worldGraphManager); + m_trackablesImpl = xpcf::utils::make_shared(m_restbedService,m_worldGraphManager); + m_worldAnchorImpl = xpcf::utils::make_shared(m_restbedService,m_worldGraphManager); + m_worldLinkImpl = xpcf::utils::make_shared(m_restbedService,m_worldGraphManager); + + m_restbedSettings->set_port( m_port ); + m_restbedSettings->set_worker_limit(m_serverNbThread); + + //publication des api + m_solarImpl->publishDefaultResources(); + m_relocImpl->publishDefaultResources(); + m_trackablesImpl->publishDefaultResources(); + m_worldAnchorImpl->publishDefaultResources(); + m_worldLinkImpl->publishDefaultResources(); + + return FrameworkReturnCode::_SUCCESS; + } + + FrameworkReturnCode ETSIWorldGraphService::start() + { + m_restbedService->start( m_restbedSettings ); + return FrameworkReturnCode::_SUCCESS; + } + + FrameworkReturnCode ETSIWorldGraphService::stop() + { + m_restbedService->stop( ); + return FrameworkReturnCode::_SUCCESS; + } + + +} // namespace SolARModuleWorldStorage +} // namespace MODULES +} // namespace SolAR diff --git a/SolARModuleWorldGraph/src/RestBedImpl/DefaultSolARImpl.cpp b/SolARModuleWorldGraph/src/RestBedImpl/DefaultSolARImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc24994fbce7d38588165d666bb9472fbe5c32e3 --- /dev/null +++ b/SolARModuleWorldGraph/src/RestBedImpl/DefaultSolARImpl.cpp @@ -0,0 +1,84 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include + +#include +#include +#include + +namespace org::openapitools::server::implem +{ +using namespace std; +using namespace restbed; + + + SolARPingResource::SolARPingResource(const std::string& context) : DefaultApiResources::PingResource(context) {} + + std::pair SolARPingResource::handler_GET() { + // Implémentez votre logique personnalisée ici + return make_pair(200,"pong"); + } + + + + SolARVersionResource::SolARVersionResource(const std::string& context) : DefaultApiResources::VersionResource(context) {} + + std::pair SolARVersionResource::handler_GET() { + // Implémentez votre logique personnalisée ici + return std::make_pair(200, "1.3.0"); + } + + + + SolARAdminResource::SolARAdminResource(const std::string& context) : DefaultApiResources::AdminResource(context) {} + + std::pair SolARAdminResource::handler_GET() { + // Implémentez votre logique personnalisée ici + + return std::make_pair(200, "Server running and ready !"); + } + + + + + DefaultSolARImpl::DefaultSolARImpl(std::shared_ptrconst& restbedService) + : DefaultApi(restbedService) + { + m_SolARPingResource = make_shared< SolARPingResource>( ); + m_SolARPingResource->set_path("/ping"); + m_SolARVersionResource = make_shared< SolARVersionResource>( ); + m_SolARVersionResource->set_path("/version"); + m_SolARAdminResource = make_shared< SolARAdminResource>( ); + m_SolARAdminResource->set_path("/admin"); + m_service = restbedService; + } + + + + void DefaultSolARImpl::publishDefaultResources() { + + m_service->publish(m_SolARAdminResource); + + m_service->publish(m_SolARPingResource); + + + m_service->publish(m_SolARVersionResource); + + } + +} diff --git a/SolARModuleWorldGraph/src/RestBedImpl/RelocalizationInformationSolARImpl.cpp b/SolARModuleWorldGraph/src/RestBedImpl/RelocalizationInformationSolARImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..baf3b0b8aba2f242ffb4366423514c2c001fc8ad --- /dev/null +++ b/SolARModuleWorldGraph/src/RestBedImpl/RelocalizationInformationSolARImpl.cpp @@ -0,0 +1,198 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "boost/lexical_cast.hpp" +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +namespace org::openapitools::server::implem +{ + +using namespace std; +using namespace restbed; + + + SolARRelocalizationInformationResource::SolARRelocalizationInformationResource(const std::string& context, const SRef worldStorage) : RelocalizationInformationResource::RelocalizationInformationResource(context) { + m_worldStorage = worldStorage; + } + + std::pair SolARRelocalizationInformationResource::handler_GET( + std::vector & uuids, std::vector & capabilities, std::string & token) { + nlohmann::json toAdd; + std::vector result; + + std::vector> tuplesReloc; + for ( const UuidAndMode& PairUUID : uuids){ + Mode_WorldStorage mode = PairUUID.getMode(); + bool boolToAdd; + if(mode.toString() == "TRACKABLES_TO_REQUEST"){ + boolToAdd = true; + } + else { + boolToAdd = false; + } + std::tuple PairToAdd(xpcf::toUUID(PairUUID.getUuid()),boolToAdd); + tuplesReloc.push_back(PairToAdd); + } + + std::vector capabilitiesReloc; + for ( const Capability& capability : capabilities){ + SolAR::datastructure::StorageCapabilities capToAdd; + capToAdd.setTrackableType(SolAR::datastructure::resolveTrackableType(capability.getTrackableType().toString())); + SolAR::datastructure::EncodingInfo encodingInfo(capability.getEncodingInformation().getDataFormat(), capability.getEncodingInformation().getVersion()); + capToAdd.setEncodingInformation(encodingInfo); + capabilitiesReloc.push_back(capToAdd); + } + std::vector relocInfoList; + RelocalizationInformation relocInfo; + RelocalizationInformations relocInfos; + switch(m_worldStorage->getRelocalizationInformation(tuplesReloc,token,capabilitiesReloc,result)){ + case SolAR::FrameworkReturnCode::_SUCCESS : + { + + for(SolAR::datastructure::RelocalizationInformation &solarRelocInfo : result){ + if (solarRelocInfo.getRelocObjects().empty()){ + toAdd = "Something went wrong : check server's log for more information"; + } + else{ + relocInfo = RelocalizationInformationSolARImpl::from_storage(solarRelocInfo); + SRef Element; + m_worldStorage->getWorldElement(solarRelocInfo.getRootUUID(),Element); + TypeWorldStorage requestType; + switch(Element->getKind()){ + case SolAR::datastructure::ElementKind::ANCHOR : { + requestType.setEnumValue("ANCHOR"); + break; + } + case SolAR::datastructure::ElementKind::TRACKABLE : { + requestType.setEnumValue("TRACKABLE"); + break; + + } + case SolAR::datastructure::ElementKind::INVALID : { + requestType.setEnumValue("UNKNOWN"); + break; + + } + + } + relocInfo.setRequestType(requestType); + + } + relocInfoList.push_back(relocInfo); + + } + relocInfos.setRelocInfo(relocInfoList); + return std::make_pair(restbed::OK, relocInfos); + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + return std::make_pair(restbed::NOT_FOUND,relocInfos); + } + default : + { + return std::make_pair(restbed::BAD_REQUEST, relocInfos); + } + } + } + + + + + + + + + RelocalizationInformationSolARImpl::RelocalizationInformationSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage) + : RelocalizationInformationApi(restbedService) + { + m_spRelocalizationInformationResource = std::make_shared< SolARRelocalizationInformationResource>("",worldStorage ); + m_spRelocalizationInformationResource->set_path("/relocalizationInformation"); + m_service = restbedService; + m_worldStorage = worldStorage; + } + + void RelocalizationInformationSolARImpl::publishDefaultResources() { + + m_service->publish(m_spRelocalizationInformationResource); + } + + + org::openapitools::server::model::RelocalizationInformation RelocalizationInformationSolARImpl::from_storage(const SolAR::datastructure::RelocalizationInformation &relocObj){ + + //the object to be returned + org::openapitools::server::model::RelocalizationInformation ret; + + //convert all the RelocalizationInformation's attributes into the attributes of the model of the server attibutes + + + //RootUUID + std::string rootUUID = xpcf::uuids::to_string(relocObj.getRootUUID()); + ret.setRequestUUID(rootUUID); //to adapat with a regenration of openAPI + + + //RelocObjects list + std::vector listToAdd; + for(const SolAR::datastructure::RelocObject &objToConvert : relocObj.getRelocObjects()){ + org::openapitools::server::model::RelocObject AddObj = from_storage(objToConvert); + listToAdd.push_back(AddObj); + } + ret.setRelocObjects(listToAdd); + + + return ret; + } + + org::openapitools::server::model::RelocObject RelocalizationInformationSolARImpl::from_storage(const SolAR::datastructure::RelocObject Obj){ + //convert all the RelocObject's attributes into the attributes of the model of the RelocObject's server attibutes + org::openapitools::server::model::RelocObject ret; + + //Trackable + org::openapitools::server::model::Trackable track = TrackablesSolARImpl::from_storage(Obj.getTrackable()); + ret.setTrackable(track); + + //3DTransform + //Transform3Df (localCRS) + SolAR::datastructure::Transform3Df transform3d = Obj.getTransform3D(); + Eigen::Matrix4f matrix = transform3d.matrix(); + std::vector localCRS; + for (size_t i = 0; i < (size_t) matrix.rows(); i++) + { + for (size_t j = 0; j < (size_t) matrix.cols(); j++) + { + localCRS.push_back(matrix(i, j)); + } + } + ret.setTransform3D(localCRS); + + return ret; + } + + +} diff --git a/SolARModuleWorldGraph/src/RestBedImpl/TrackablesSolARImpl.cpp b/SolARModuleWorldGraph/src/RestBedImpl/TrackablesSolARImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89f5de9caad03fa2b62947f516c13fbbc2ae2ee3 --- /dev/null +++ b/SolARModuleWorldGraph/src/RestBedImpl/TrackablesSolARImpl.cpp @@ -0,0 +1,677 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace xpcf = org::bcom::xpcf; + +namespace org::openapitools::server::implem +{ + +using namespace org::openapitools::server::api; +using namespace std; +using namespace restbed; + +SolARTrackablesResource::SolARTrackablesResource(const std::string& context, const SRef worldStorage) :TrackablesResource::TrackablesResource(context) { + m_worldStorage = worldStorage; +} + + +std::pair SolARTrackablesResource::handler_GET(std::string & token){ + //initialize the json object that we will send back to the client + TrackablesResponse trackableResponse; + std::vector trackablesToReturn; + org::openapitools::server::model::Trackable track; + + if (!m_worldStorage) { + // World storage is not valid, return internal server error + return std::make_pair(restbed::INTERNAL_SERVER_ERROR, trackableResponse); + } + std::vector> vector; + SolAR::FrameworkReturnCode code = m_worldStorage->getTrackables(vector); + if(code != SolAR::FrameworkReturnCode::_SUCCESS) + { + //Exception raised in getTrackables + return make_pair(restbed::INTERNAL_SERVER_ERROR,trackableResponse); + } + else + { + //iteration over the content of the world storage + for (const SRef &t : vector){ + + //add the current trackable to the JSON object + auto trackable = TrackablesSolARImpl::from_storage(*t); + trackablesToReturn.push_back(trackable); + } + trackableResponse.setTrackables(trackablesToReturn); + return std::make_pair(OK,trackableResponse); + } +} + +std::pair SolARTrackablesResource::handler_PUT(Trackable & trackable,std::string & token){ + + //convert all the Trackable attributes into StorageTrackable attributes to create one and store it in the world storage + + //creator uuid + xpcf::uuids::uuid creatorId = xpcf::toUUID(trackable.getCreatorUUID()); + + //localCRS + std::vector vector = trackable.getLocalCRS(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df localCRS(matrix); + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(trackable.getUnit()); + + //dimension + Eigen::Vector3d dimension = Eigen::Vector3d(trackable.getTrackableSize().data()); + + //taglist + std::multimap keyvalueTagList; + for (const auto &tag : trackable.getKeyvalueTags()){ + for(const auto &value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //trackable type + SolAR::datastructure::StorageTrackableType type = SolAR::datastructure::resolveTrackableType(trackable.getTrackableType().toString()); + + //encoding info + SolAR::datastructure::EncodingInfo encodingInfo(trackable.getTrackableEncodingInformation().getDataFormat(), trackable.getTrackableEncodingInformation().getVersion()); + + //payload + std::vector payload = TrackablesSolARImpl::to_bytes(trackable.getTrackablePayload()); + + //name + std::string name = trackable.getName(); + + //id + boost::uuids::uuid id = xpcf::toUUID(trackable.getUUID()); + + //create the trackable + SRef storageTrackable = xpcf::utils::make_shared(id, creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); + + //adding the newly created StorageTrackable to the worldgraph + xpcf::uuids::uuid trackableId; + Success returnedMessage; + switch(m_worldStorage->modifyTrackable(trackableId, storageTrackable)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + std::string trackableIdString = xpcf::uuids::to_string(trackableId); + returnedMessage.setMessage(trackableIdString); + return make_pair(OK,returnedMessage); + + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + returnedMessage.setMessage("Trackable not found"); + return make_pair(NOT_FOUND,returnedMessage); + + break; + } + + default : + { + //if something went wrong + returnedMessage.setMessage("Something went wrong when modifying the trackable to the world storage"); + return make_pair(INTERNAL_SERVER_ERROR,returnedMessage); + } + + + + } +} + +std::pair SolARTrackablesResource::handler_POST(Trackable & trackable,std::string & token) { + //convert all the Trackable attributes into StorageTrackable attributes to create one and store it in the world storage + + //creator uuid + xpcf::uuids::uuid creatorId = xpcf::toUUID(trackable.getCreatorUUID()); + //localCRS + std::vector vector = trackable.getLocalCRS(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df localCRS(matrix); + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(trackable.getUnit()); + + //dimension + Eigen::Vector3d dimension = Eigen::Vector3d(trackable.getTrackableSize().data()); + + //taglist + std::multimap keyvalueTagList; + for (const auto &tag : trackable.getKeyvalueTags()){ + for(const auto &value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //trackable type + SolAR::datastructure::StorageTrackableType type = SolAR::datastructure::resolveTrackableType(trackable.getTrackableType().toString()); + + //encoding info + SolAR::datastructure::EncodingInfo encodingInfo(trackable.getTrackableEncodingInformation().getDataFormat(), trackable.getTrackableEncodingInformation().getVersion()); + + //payload + std::vector payload = TrackablesSolARImpl::to_bytes(trackable.getTrackablePayload()); + + //name + std::string name = trackable.getName(); + SRef storageTrackable; + //create the trackable + if(trackable.getUUID().empty()){ + storageTrackable = xpcf::utils::make_shared(creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); + } + else { + //uuid + xpcf::uuids::uuid id = xpcf::toUUID(trackable.getUUID()); + storageTrackable = xpcf::utils::make_shared(id,creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); + } + + //adding the newly created StorageTrackable to the worldgraph + xpcf::uuids::uuid trackableId; + Success returnedMessage; + if(m_worldStorage->addTrackable(trackableId, storageTrackable) != SolAR::FrameworkReturnCode::_SUCCESS) + { + //if something went wrong + returnedMessage.setMessage("Something went wrong when adding the trackable to the world storage"); + return make_pair(INTERNAL_SERVER_ERROR,returnedMessage); + } + + //test for passing post method + //initialize the json object that we will send back to the client (the trackable's id) + std::string trackableIdString = xpcf::uuids::to_string(trackableId); + + //send the ID to the client + returnedMessage.setMessage(trackableIdString); + return make_pair(200,returnedMessage); +} + + + + + +SolARTrackablesResourceUUID::SolARTrackablesResourceUUID(const std::string& context,const SRef worldStorage):TrackablesTrackableUUIDResource(context){ + m_worldStorage = worldStorage; +} + +std::pair SolARTrackablesResourceUUID::handler_GET(std::string & trackableUUID, std::string & token){ + + + //look for the trackable with given id + xpcf::uuids::uuid id = xpcf::toUUID(trackableUUID); + SRef storageTrackable; + org::openapitools::server::model::Trackable trackable; + + switch(m_worldStorage->getTrackable(id, storageTrackable)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + //StorageTrackable found, we convert it into a Trackable + trackable = TrackablesSolARImpl::from_storage(*storageTrackable); + + //add the Trackable to our JSON object + return make_pair(OK,trackable); + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + return make_pair(NOT_FOUND,trackable); + + break; + } + + default : + { + return make_pair(INTERNAL_SERVER_ERROR,trackable); + } + } +} + +std::pair SolARTrackablesResourceUUID::handler_DELETE(std::string & trackableUUID, std::string & token) { + //trackable uuid + xpcf::uuids::uuid id = xpcf::toUUID(trackableUUID); + Success message; + switch(m_worldStorage->removeTrackable(id)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + message.setMessage("Trackable removed\n"); + return make_pair(OK,message); + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + message.setMessage("Trackable not found"); + return std::make_pair(OK,message); + break; + } + + default : + { + message.setMessage("Something went wrong"); + return make_pair(INTERNAL_SERVER_ERROR,message); + break; + } + } +} + + + +std::vector TrackablesSolARImpl::to_bytes(const std::string &s) +{ + std::vector bytes; + bytes.reserve(std::size(s)); + std::transform(std::begin(s), std::end(s), std::back_inserter(bytes), [](char c){ + return std::byte(c); + }); + + return bytes; +} + +std::string bytesToString(const std::vector& vec) { + std::string binaryString; + for (const auto& byte : vec) { + std::bitset<1> bits(static_cast(byte)); + binaryString += bits.to_string(); + } + return binaryString; +} + +TrackablesSolARImpl::TrackablesSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage) + : TrackablesApi(restbedService) +{ + m_restbedService = restbedService; + m_worldStorage = worldStorage; + + m_spTrackablesResource = std::make_shared("", worldStorage); + m_spTrackablesResourceUUID = std::make_shared("", worldStorage); + m_spTrackablesResourceUUID->set_path("/trackables/{trackableUUID: .*}"); + m_spTrackablesResource->set_path("/trackables"); + + +} +void TrackablesSolARImpl::publishDefaultResources(){ + m_restbedService->publish(m_spTrackablesResource); + m_restbedService->publish(m_spTrackablesResourceUUID); + +} + + +org::openapitools::server::model::Trackable TrackablesSolARImpl::from_storage(const SolAR::datastructure::StorageTrackable &trackable){ + //the object to be returned + org::openapitools::server::model::Trackable ret; + + //convert all the StorageTrackable attributes into Trackable attibutes + +// trackable UUID + std::string id = xpcf::uuids::to_string(trackable.getID()); + ret.setUUID(id); + + //creator UUID + std::string creatorUid = xpcf::uuids::to_string(trackable.getCreatorID()); + ret.setCreatorUUID(creatorUid); + + //name + ret.setName(trackable.getName()); + + //Trackable type + std::string type = resolveTrackableType(trackable.getType()); + org::openapitools::server::model::TrackableType trackableType; + trackableType.fromString(type); + ret.setTrackableType(trackableType); + + //EncodingInfo struct + + org::openapitools::server::model::EncodingInformationStructure encodingInfo; + SolAR::datastructure::EncodingInfo storageEncodingInfo(trackable.getEncodingInfo()); + encodingInfo.setDataFormat(storageEncodingInfo.getDataFormat()); + encodingInfo.setVersion(storageEncodingInfo.getVersion()); + ret.setTrackableEncodingInformation(encodingInfo); + + //Payload + + std::vector storagePayload = trackable.getPayload(); + + std::string payload = bytesToString(storagePayload); + ret.setTrackablePayload(payload); + + //Transform3Df (localCRS) + SolAR::datastructure::Transform3Df transform3d = trackable.getLocalCrs(); + Eigen::Matrix4f matrix = transform3d.matrix(); + std::vector localCRS; + for (size_t i = 0; i < (size_t) matrix.rows(); i++) + { + for (size_t j = 0; j < (size_t) matrix.cols(); j++) + { + localCRS.push_back(matrix(i, j)); + } + } + ret.setLocalCRS(localCRS); + + //Unit system + org::openapitools::server::model::UnitSystem unit = resolve_unitSystem(trackable.getUnitSystem()); + ret.setUnit(unit); + + //Dimension (scale) + Eigen::Vector3d dimension = trackable.getSize(); + std::vector vector(3); + for(int i = 0; i < 3; i++) + { + vector[i] = dimension[0,i]; + } + ret.setTrackableSize(vector); + + //keyvalue taglist (multimap to map>) + std::map> tagList; + auto storageMap = trackable.getTags(); + for (const auto &tag : storageMap) + { + if (tagList.count(tag.first) != 0){ + std::vector& vector = tagList.at(tag.first); + vector.push_back(tag.second); + }else { + std::vector vector; + vector.push_back(tag.second); + tagList.insert(std::pair>(tag.first, vector)); + } + } + ret.setKeyvalueTags(tagList); + + ret.setConfidence(0.0);// TO DEFINE + return ret; +} +// void TrackablesSolARImpl::add_trackable(const org::openapitools::server::model::Trackable &trackable, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //convert all the Trackable attributes into StorageTrackable attributes to create one and store it in the world storage + +// //creator uuid +// xpcf::uuids::uuid creatorId = xpcf::toUUID(trackable.getCreatorUUID()); + +// //localCRS +// std::vector vector = trackable.getLocalCRS(); +// Eigen::Matrix matrix = Eigen::Map>(vector.data()); +// SolAR::datastructure::Transform3Df localCRS(matrix); + +// //unitsystem +// SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(trackable.getUnit()); + +// //dimension +// Eigen::Vector3d dimension = Eigen::Vector3d(trackable.getTrackableSize().data()); + +// //taglist +// std::multimap keyvalueTagList; +// for (const auto &tag : trackable.getKeyvalueTags()){ +// for(const auto &value : tag.second){ +// keyvalueTagList.insert({tag.first,value}); +// } +// } + +// //trackable type +// SolAR::datastructure::StorageTrackableType type = SolAR::datastructure::resolveTrackableType(trackable.getTrackableType()); + +// //encoding info +// SolAR::datastructure::EncodingInfo encodingInfo(trackable.getTrackableEncodingInformation().getDataFormat(), trackable.getTrackableEncodingInformation().getVersion()); + +// //payload +// std::vector payload = TrackablesSolARImpl::to_bytes(trackable.getTrackablePayload()); + +// //name +// std::string name = trackable.getName(); + +// //create the trackable +// SRef storageTrackable = xpcf::utils::make_shared(creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); + +// //adding the newly created StorageTrackable to the worldgraph +// xpcf::uuids::uuid trackableId; +// if(m_worldStorage->addTrackable(trackableId, storageTrackable) != SolAR::FrameworkReturnCode::_SUCCESS) +// { +// //if something went wrong +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "something went wrong when adding the trackable to the world storage"); +// return; +// } + +// //initialize the json object that we will send back to the client (the trackable's id) +// std::string trackableIdString = xpcf::uuids::to_string(trackableId); +// auto jsonObjects = nlohmann::json::array(); +// nlohmann::to_json(jsonObjects, trackableIdString); + +// //send the ID to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// } + +// void TrackablesSolARImpl::delete_trackable(const std::string &trackableUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //trackable uuid +// xpcf::uuids::uuid id = xpcf::toUUID(trackableUUID); +// switch(m_worldStorage->removeTrackable(id)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Ok, "Trackable removed\n"); +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "Trackable not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// } + +// void TrackablesSolARImpl::get_trackable_by_id(const std::string &trackableUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //initialize the json object that we will send back to the client +// auto jsonObjects = nlohmann::json::array(); + +// //look for the trackable with given id +// xpcf::uuids::uuid id = xpcf::toUUID(trackableUUID); +// SRef storageTrackable; + +// switch(m_worldStorage->getTrackable(id, storageTrackable)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// //StorageTrackable found, we convert it into a Trackable +// org::openapitools::server::model::Trackable trackable = from_storage(*storageTrackable); + +// //add the Trackable to our JSON object +// to_json(jsonObjects, trackable); + +// //send the Trackable to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); + +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "Trackable not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } + + +// } + +// void TrackablesSolARImpl::get_trackables(const std::optional &token, Pistache::Http::ResponseWriter &response) +// { + +// //initialize the json object that we will send back to the client +// auto jsonObjects = nlohmann::json::array(); + +// //declaration of all the objects that will be changed at each iteration of the loop +// nlohmann::json toAdd; +// org::openapitools::server::model::Trackable track; + +// std::vector> vector; +// if(m_worldStorage->getTrackables(vector) != SolAR::FrameworkReturnCode::_SUCCESS) +// { +// //Exception raised in getTrackables +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong when fetching the trackables from the world storage"); +// } +// else +// { +// //iteration over the content of the world storage +// for (const SRef &t : vector){ +// //add the current trackable to the JSON object +// track = from_storage(*t); +// to_json(toAdd, track); +// jsonObjects.push_back(toAdd); +// } + +// //send the JSON object to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// } +// } + +// void TrackablesSolARImpl::modify_trackable(const model::Trackable &trackable, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //convert all the Trackable attributes into StorageTrackable attributes to create one and store it in the world storage + +// //creator uuid +// xpcf::uuids::uuid creatorId = xpcf::toUUID(trackable.getCreatorUUID()); + +// //localCRS +// std::vector vector = trackable.getLocalCRS(); +// Eigen::Matrix matrix = Eigen::Map>(vector.data()); +// SolAR::datastructure::Transform3Df localCRS(matrix); + +// //unitsystem +// SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(trackable.getUnit()); + +// //dimension +// Eigen::Vector3d dimension = Eigen::Vector3d(trackable.getTrackableSize().data()); + +// //taglist +// std::multimap keyvalueTagList; +// for (const auto &tag : trackable.getKeyvalueTags()){ +// for(const auto &value : tag.second){ +// keyvalueTagList.insert({tag.first,value}); +// } +// } + +// //trackable type +// SolAR::datastructure::StorageTrackableType type = SolAR::datastructure::resolveTrackableType(trackable.getTrackableType()); + +// //encoding info +// SolAR::datastructure::EncodingInfo encodingInfo(trackable.getTrackableEncodingInformation().getDataFormat(), trackable.getTrackableEncodingInformation().getVersion()); + +// //payload +// std::vector payload = TrackablesSolARImpl::to_bytes(trackable.getTrackablePayload()); + +// //name +// std::string name = trackable.getName(); + +// //id +// boost::uuids::uuid id = xpcf::toUUID(trackable.getUUID()); + +// //create the trackable +// SRef storageTrackable = xpcf::utils::make_shared(id, creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); + +// //adding the newly created StorageTrackable to the worldgraph +// xpcf::uuids::uuid trackableId; +// switch(m_worldStorage->modifyTrackable(trackableId, storageTrackable)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// //initialize the json object that we will send back to the client (the trackable's id) +// std::string trackableIdString = xpcf::uuids::to_string(trackableId); +// auto jsonObjects = nlohmann::json::array(); +// nlohmann::to_json(jsonObjects, trackableIdString); + +// //send the ID to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); + +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "Trackable not found\n"); + +// break; +// } + +// default : +// { +// //if something went wrong +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "something went wrong when modifying the trackable to the world storage\n"); + +// } +// } + +// return; +// } + + + + + + + +// void TrackablesSolARImpl::init(){ +// try { +// TrackablesApi::init(); +// } +// catch (xpcf::Exception e) +// { +// std::cout << e.what() << std::endl; +// } +// } + +} + diff --git a/SolARModuleWorldGraph/src/RestBedImpl/WorldAnchorsSolARImpl.cpp b/SolARModuleWorldGraph/src/RestBedImpl/WorldAnchorsSolARImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e93d75047d991bb241f5f99ec7f0a76bed9bce5b --- /dev/null +++ b/SolARModuleWorldGraph/src/RestBedImpl/WorldAnchorsSolARImpl.cpp @@ -0,0 +1,579 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include +#include + +#include + +namespace org::openapitools::server::implem +{ + +using namespace std; +using namespace restbed; + +SolARWorldAnchorsResource::SolARWorldAnchorsResource(const std::string& context,const SRef worldStorage):WorldAnchorsResource::WorldAnchorsResource(context){ + m_worldStorage= worldStorage; +} + +std::pair SolARWorldAnchorsResource::handler_GET(std::string & token){ + //initialize the json object that we will send back to the client + auto jsonObjects = nlohmann::json::array(); + WorldAnchorsResponse worldAnchorsResponse; + std::vector anchorList; + //declaration of all the objects that will be changed at each iteration of the loop + nlohmann::json toAdd; + org::openapitools::server::model::WorldAnchor worldAnchor; + + std::vector> vector; + if(m_worldStorage->getWorldAnchors(vector) != SolAR::FrameworkReturnCode::_SUCCESS) + { + //Exception raised in getWorldAnchor + return make_pair(INTERNAL_SERVER_ERROR, worldAnchorsResponse); + } + else + { + //iteration over the content of the world storage + for (const SRef &w : vector){ + //add the current worldAnchor to the JSON object + worldAnchor = WorldAnchorsSolARImpl::from_storage(*w); + + anchorList.push_back(worldAnchor); + } + + //send the JSON object to the client + worldAnchorsResponse.setWorldAnchors(anchorList); + return make_pair(OK, worldAnchorsResponse); + } +} + +std::pair SolARWorldAnchorsResource::handler_PUT(WorldAnchor & worldAnchor,std::string & token){ + //convert all the WorldAnchor attributes into StorageWorldAnchor attributes to create one and store it in the world storage + + //creator uuid + xpcf::uuids::uuid creatorId = xpcf::toUUID(worldAnchor.getCreatorUUID()); + + //localCRS + std::vector vector = worldAnchor.getLocalCRS(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df localCRS(matrix); + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldAnchor.getUnit()); + + //size + Eigen::Vector3d size = Eigen::Vector3d(worldAnchor.getWorldAnchorSize().data()); + + //taglist + std::multimap keyvalueTagList; + for (std::pair> tag : worldAnchor.getKeyvalueTags()){ + for(std::string value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //name + std::string name = worldAnchor.getName(); + + //id + xpcf::uuids::uuid id = xpcf::toUUID(worldAnchor.getUUID()); + + //create a world anchor + SRef storageWorldAnchor = xpcf::utils::make_shared(id, creatorId, localCRS, unitSystem, size, keyvalueTagList, name); + + //adding the newly created StorageWorldAnchor to the worldgraph + xpcf::uuids::uuid worldAnchorId; + Success returnedMessage; + switch(m_worldStorage->modifyWorldAnchor(worldAnchorId, storageWorldAnchor)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + //initialize the json object that we will send back to the client (the WorldAnchor's id) + std::string worldAnchorIdString = xpcf::uuids::to_string(worldAnchorId); + + returnedMessage.setMessage(worldAnchorIdString); + return make_pair(OK,returnedMessage); + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + returnedMessage.setMessage("WorldAnchor not found"); + return make_pair(NOT_FOUND, returnedMessage); + break; + } + + default : + { + returnedMessage.setMessage("Something went wrong"); + return make_pair(INTERNAL_SERVER_ERROR, returnedMessage); + + } + } +} + +std::pair SolARWorldAnchorsResource::handler_POST(WorldAnchor & worldAnchor,std::string & token){ + //convert all the WorldAnchor attributes into StorageWorldAnchor attributes to create one and store it in the world storage + + //creator uuid + xpcf::uuids::uuid creatorId = xpcf::toUUID(worldAnchor.getCreatorUUID()); + + //localCRS + std::vector vector = worldAnchor.getLocalCRS(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df localCRS(matrix); + + //size + Eigen::Vector3d size = Eigen::Vector3d(worldAnchor.getWorldAnchorSize().data()); + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldAnchor.getUnit()); + + //taglist + std::multimap keyvalueTagList; + for (std::pair> tag : worldAnchor.getKeyvalueTags()){ + for(std::string value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //name + std::string name = worldAnchor.getName(); + SRef storageWorldAnchor; + //create a world anchor + if(!worldAnchor.getUUID().empty()){ + xpcf::uuids::uuid id = xpcf::toUUID(worldAnchor.getUUID()); + + storageWorldAnchor = xpcf::utils::make_shared(id,creatorId, localCRS, unitSystem, size, keyvalueTagList, name); + } + else{ + storageWorldAnchor = xpcf::utils::make_shared(creatorId, localCRS, unitSystem, size, keyvalueTagList, name); + } + //adding the newly created StorageWorldAnchor to the worldgraph + xpcf::uuids::uuid worldAnchorId; + Success returnedMessage; + if(m_worldStorage->addWorldAnchor(worldAnchorId, storageWorldAnchor) != SolAR::FrameworkReturnCode::_SUCCESS) + { + //if something went wrong + returnedMessage.setMessage("something went wrong when adding the anchor to the world storage"); + return make_pair(INTERNAL_SERVER_ERROR,returnedMessage); + } + + //initialize the json object that we will send back to the client (the WorldAnchor's id) + returnedMessage.setMessage(xpcf::uuids::to_string(worldAnchorId)); + return make_pair(OK,returnedMessage); + +} + + + + +SolARWorldAnchorsResourceUUID::SolARWorldAnchorsResourceUUID(const std::string& context,const SRef worldStorage):WorldAnchorsWorldAnchorUUIDResource::WorldAnchorsWorldAnchorUUIDResource(context){ + m_worldStorage = worldStorage; +} + +std::pair SolARWorldAnchorsResourceUUID::handler_GET(std::string & worldAnchorUUID, std::string & token){ + //initialize the json object that we will send back to the client + auto jsonObjects = nlohmann::json::array(); + + //look for the world anchor with given id + xpcf::uuids::uuid id = xpcf::toUUID(worldAnchorUUID); + SRef storageWorldAnchor; + org::openapitools::server::model::WorldAnchor worldAnchor; + switch(m_worldStorage->getWorldAnchor(id, storageWorldAnchor)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + //StorageWorldAnchor found, we convert it into a WorldAnchor + worldAnchor = WorldAnchorsSolARImpl::from_storage(*storageWorldAnchor); + + //add the WorldAnchor to our JSON object + + return make_pair(OK,worldAnchor); + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + return make_pair(NOT_FOUND,worldAnchor); + break; + } + + default : + { + return make_pair(INTERNAL_SERVER_ERROR,worldAnchor); + } + } +} + +std::pair SolARWorldAnchorsResourceUUID::handler_DELETE(std::string & worldAnchorUUID, std::string & token){ + //world anchor uuid + xpcf::uuids::uuid id = xpcf::toUUID(worldAnchorUUID); + Success returnedMessage; + switch(m_worldStorage->removeWorldAnchor(id)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + returnedMessage.setMessage("WorldAnchor removed"); + return make_pair(OK,returnedMessage); + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + returnedMessage.setMessage("WorldAnchor not found"); + return make_pair(NOT_FOUND,returnedMessage); + break; + } + + default : + { + returnedMessage.setMessage("something went wrong"); + return make_pair(INTERNAL_SERVER_ERROR,returnedMessage); + + } + } +} + + + + + + + + + + + + +WorldAnchorsSolARImpl::WorldAnchorsSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage) + : WorldAnchorsApi(restbedService) +{ + m_spWorldAnchorsResource = std::make_shared< SolARWorldAnchorsResource >("",worldStorage); + m_spWorldAnchorsResource->set_path("/worldAnchors"); + m_spWorldAnchorsResourceUUID = std::make_shared< SolARWorldAnchorsResourceUUID >("",worldStorage); + m_spWorldAnchorsResourceUUID->set_path("/worldAnchors/{worldAnchorUUID: .*}"); + m_restbedService = restbedService; + m_worldStorage = worldStorage; +} + +void WorldAnchorsSolARImpl::publishDefaultResources(){ + m_restbedService->publish(m_spWorldAnchorsResource); + m_restbedService->publish(m_spWorldAnchorsResourceUUID); +} + + +org::openapitools::server::model::WorldAnchor WorldAnchorsSolARImpl::from_storage(const SolAR::datastructure::StorageWorldAnchor &worldAnchor) +{ + //the object to be returned + org::openapitools::server::model::WorldAnchor ret; + + //convert all the StorageWorldAnchor attributes into WorldAnchor attibutes + + //world anchor UUID + std::string id = xpcf::uuids::to_string(worldAnchor.getID()); + ret.setUUID(id); + + //name + ret.setName(worldAnchor.getName()); + + //creator UUID + std::string creatorUid = xpcf::uuids::to_string(worldAnchor.getCreatorID()); + ret.setCreatorUUID(creatorUid); + + //Transform3Df (localCRS) + SolAR::datastructure::Transform3Df transform3d = worldAnchor.getLocalCrs(); + Eigen::Matrix matrix = transform3d.matrix(); + std::vector localCRS; + for (size_t i = 0; i < (size_t) matrix.rows(); i++) + { + for (size_t j = 0; j < (size_t) matrix.cols(); j++) + { + localCRS.push_back(matrix(i, j)); + } + } + ret.setLocalCRS(localCRS); + +// Unit system + org::openapitools::server::model::UnitSystem unit = resolve_unitSystem(worldAnchor.getUnitSystem()); + ret.setUnit(unit); + + //Dimension (scale) + Eigen::Vector3d dimension = worldAnchor.getSize(); + std::vector vector(3); + for(int i = 0; i < 3; i++){ + vector[i] = dimension[0,i]; + } + ret.setWorldAnchorSize(vector); + + //keyvalue taglist (multimap to map>) + std::map> tagList; + auto storageMap = worldAnchor.getTags(); + for (const auto &tag : storageMap){ + if (tagList.count(tag.first) != 0){ + std::vector& vector = tagList.at(tag.first); + vector.push_back(tag.second); + }else { + std::vector vector; + vector.push_back(tag.second); + tagList.insert(std::pair>(tag.first, vector)); + } + } + ret.setKeyvalueTags(tagList); + + return ret; +} + +// void WorldAnchorsSolARImpl::add_world_anchor(const org::openapitools::server::model::WorldAnchor &worldAnchor, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //convert all the WorldAnchor attributes into StorageWorldAnchor attributes to create one and store it in the world storage + +// //creator uuid +// xpcf::uuids::uuid creatorId = xpcf::toUUID(worldAnchor.getCreatorUUID()); + +// //localCRS +// std::vector vector = worldAnchor.getLocalCRS(); +// Eigen::Matrix matrix = Eigen::Map>(vector.data()); +// SolAR::datastructure::Transform3Df localCRS(matrix); + +// //size +// Eigen::Vector3d size = Eigen::Vector3d(worldAnchor.getWorldAnchorSize().data()); + +// //unitsystem +// SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldAnchor.getUnit()); + +// //taglist +// std::multimap keyvalueTagList; +// for (std::pair> tag : worldAnchor.getKeyvalueTags()){ +// for(std::string value : tag.second){ +// keyvalueTagList.insert({tag.first,value}); +// } +// } + +// //name +// std::string name = worldAnchor.getName(); + +// //create a world anchor +// SRef storageWorldAnchor = xpcf::utils::make_shared(creatorId, localCRS, unitSystem, size, keyvalueTagList, name); + +// //adding the newly created StorageWorldAnchor to the worldgraph +// xpcf::uuids::uuid worldAnchorId; +// if(m_worldStorage->addWorldAnchor(worldAnchorId, storageWorldAnchor) != SolAR::FrameworkReturnCode::_SUCCESS) +// { +// //if something went wrong +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "something went wrong when adding the anchor to the world storage"); +// return; +// } + +// //initialize the json object that we will send back to the client (the WorldAnchor's id) +// std::string worldAnchorIdString = xpcf::uuids::to_string(worldAnchorId); +// auto jsonObjects = nlohmann::json::array(); +// nlohmann::to_json(jsonObjects, worldAnchorIdString); + +// //send the ID to the client +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// } + +// void WorldAnchorsSolARImpl::delete_world_anchor(const std::string &worldAnchorUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //world anchor uuid +// xpcf::uuids::uuid id = xpcf::toUUID(worldAnchorUUID); +// switch(m_worldStorage->removeWorldAnchor(id)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Ok, "WorldAnchor removed\n"); +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "WorldAnchor not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// } + +// void WorldAnchorsSolARImpl::get_world_anchor_by_id(const std::string &worldAnchorUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //initialize the json object that we will send back to the client +// auto jsonObjects = nlohmann::json::array(); + +// //look for the world anchor with given id +// xpcf::uuids::uuid id = xpcf::toUUID(worldAnchorUUID); +// SRef storageWorldAnchor; + +// switch(m_worldStorage->getWorldAnchor(id, storageWorldAnchor)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// //StorageWorldAnchor found, we convert it into a WorldAnchor +// org::openapitools::server::model::WorldAnchor worldAnchor = from_storage(*storageWorldAnchor); + +// //add the WorldAnchor to our JSON object +// to_json(jsonObjects, worldAnchor); + +// //send the WorldAnchor to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); + +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "WorldAnchor not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// } + +// void WorldAnchorsSolARImpl::get_world_anchors(const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //initialize the json object that we will send back to the client +// auto jsonObjects = nlohmann::json::array(); + +// //declaration of all the objects that will be changed at each iteration of the loop +// nlohmann::json toAdd; +// org::openapitools::server::model::WorldAnchor worldAnchor; + +// std::vector> vector; +// if(m_worldStorage->getWorldAnchors(vector) != SolAR::FrameworkReturnCode::_SUCCESS) +// { +// //Exception raised in getWorldAnchor +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong when fetching the world storage"); +// } +// else +// { +// //iteration over the content of the world storage +// for (const SRef &w : vector){ +// //add the current worldAnchor to the JSON object +// worldAnchor = from_storage(*w); +// to_json(toAdd, worldAnchor); +// jsonObjects.push_back(toAdd); +// } + +// //send the JSON object to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// } +// } + +// void WorldAnchorsSolARImpl::modify_world_anchor(const model::WorldAnchor &worldAnchor, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //convert all the WorldAnchor attributes into StorageWorldAnchor attributes to create one and store it in the world storage + +// //creator uuid +// xpcf::uuids::uuid creatorId = xpcf::toUUID(worldAnchor.getCreatorUUID()); + +// //localCRS +// std::vector vector = worldAnchor.getLocalCRS(); +// Eigen::Matrix matrix = Eigen::Map>(vector.data()); +// SolAR::datastructure::Transform3Df localCRS(matrix); + +// //unitsystem +// SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldAnchor.getUnit()); + +// //size +// Eigen::Vector3d size = Eigen::Vector3d(worldAnchor.getWorldAnchorSize().data()); + +// //taglist +// std::multimap keyvalueTagList; +// for (std::pair> tag : worldAnchor.getKeyvalueTags()){ +// for(std::string value : tag.second){ +// keyvalueTagList.insert({tag.first,value}); +// } +// } + +// //name +// std::string name = worldAnchor.getName(); + +// //id +// xpcf::uuids::uuid id = xpcf::toUUID(worldAnchor.getUUID()); + +// //create a world anchor +// SRef storageWorldAnchor = xpcf::utils::make_shared(id, creatorId, localCRS, unitSystem, size, keyvalueTagList, name); + +// //adding the newly created StorageWorldAnchor to the worldgraph +// xpcf::uuids::uuid worldAnchorId; +// switch(m_worldStorage->modifyWorldAnchor(worldAnchorId, storageWorldAnchor)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// //initialize the json object that we will send back to the client (the WorldAnchor's id) +// std::string worldAnchorIdString = xpcf::uuids::to_string(worldAnchorId); +// auto jsonObjects = nlohmann::json::array(); +// nlohmann::to_json(jsonObjects, worldAnchorIdString); + +// //send the ID to the client +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "WorldAnchor not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// return; +// } + +// void WorldAnchorsSolARImpl::init() +// { +// try +// { +// WorldAnchorsApi::init(); +// } +// catch (xpcf::Exception e) +// { +// std::cout << e.what() << std::endl; +// } +// } + + +} diff --git a/SolARModuleWorldGraph/src/RestBedImpl/WorldLinksSolARImpl.cpp b/SolARModuleWorldGraph/src/RestBedImpl/WorldLinksSolARImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6127ebf5774992f447638385e4e18adb06e926b --- /dev/null +++ b/SolARModuleWorldGraph/src/RestBedImpl/WorldLinksSolARImpl.cpp @@ -0,0 +1,699 @@ +/** + * @copyright Copyright (c) 2021-2022 B-com http://www.b-com.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +namespace xpcf = org::bcom::xpcf; + +namespace org::openapitools::server::implem { + +using namespace std; +using namespace restbed; + +SolARWorldLinksResource::SolARWorldLinksResource(const std::string& context,const SRef worldStorage):WorldLinksResource::WorldLinksResource(context){ + m_worldStorage = worldStorage; +} + +std::pair SolARWorldLinksResource::handler_GET(std::string & token){ + //initialize the json object that we will send back to the client + auto jsonObjects = nlohmann::json::array(); + WorldLinksResponse worldLinksResponse; + std::vector worldLinkList; + //declaration of all the objects that will be changed at each iteration of the loop + nlohmann::json toAdd; + org::openapitools::server::model::WorldLink worldLink; + + std::vector> vector; + if(m_worldStorage->getWorldLinks(vector) != SolAR::FrameworkReturnCode::_SUCCESS) + { + //Exception raised in getWorldLinks + return make_pair(INTERNAL_SERVER_ERROR,worldLinksResponse); + } + else + { + //for all the worldLinks in the worldStorage + for(const SRef &l : vector){ + //add the current world link to the JSON object + worldLink = WorldLinksSolARImpl::from_storage(*l); + worldLinkList.push_back(worldLink); + } + + //send the JSON object to the client + worldLinksResponse.setWorldLinks(worldLinkList); + return make_pair(OK,worldLinksResponse); + } +} + +std::pair SolARWorldLinksResource::handler_PUT(WorldLink & worldLink,std::string & token){ + //convert all the WorldLink attributes into StorageWorldLink attributes to create one and store it in the world storage + + //authorId + xpcf::uuids::uuid authorId = xpcf::toUUID(worldLink.getCreatorUUID()); + + //transform 3d + std::vector vector = worldLink.getTransform(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df transfo(matrix); + + //world element from ID + xpcf::uuids::uuid fromElementId = xpcf::toUUID(worldLink.getUUIDFrom()); + + //world element to ID + xpcf::uuids::uuid toElementId = xpcf::toUUID(worldLink.getUUIDTo()); + + Success returnedMessage; + //check if the link connects a single element + if(fromElementId == toElementId) + { + returnedMessage.setMessage("An element can not be connected to itself"); + return make_pair(BAD_REQUEST,returnedMessage); + } + + //world element from type + SolAR::datastructure::ElementKind fromElementType = WorldLinksSolARImpl::resolve_element_kind(worldLink.getTypeFrom()); + + //world element to type + SolAR::datastructure::ElementKind toElementType = WorldLinksSolARImpl::resolve_element_kind(worldLink.getTypeTo()); + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldLink.getUnit()); + + //taglist + std::multimap keyvalueTagList; + for (std::pair> tag : worldLink.getKeyvalueTags()){ + for(std::string value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //id + xpcf::uuids::uuid id = xpcf::toUUID(worldLink.getUUID()); + + + //build the worldLink + xpcf::utils::shared_ptr storageWorldLink = xpcf::utils::make_shared(id, authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); + + + //adding the link to the storage by calling the world storage method + xpcf::uuids::uuid linkId; + switch(m_worldStorage->modifyWorldLink(linkId, storageWorldLink)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + //initialize the json object that we will send back to the client (the WorldAnchor's id) + //std::string worldLinkIdString = xpcf::uuids::to_string(linkId); + //auto jsonObjects = nlohmann::json::array(); + //nlohmann::to_json(jsonObjects, worldLinkIdString); + + //send the ID to the client + returnedMessage.setMessage(xpcf::uuids::to_string(linkId)); + return make_pair(OK,returnedMessage); + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + returnedMessage.setMessage("Either the WorldLink was not found, or the elements it should connect were not found"); + return make_pair(NOT_FOUND,returnedMessage); + + break; + } + + default : + { + returnedMessage.setMessage("Something went wrong"); + return make_pair(INTERNAL_SERVER_ERROR,returnedMessage); + } + } +}; + +std::pair SolARWorldLinksResource::handler_POST(WorldLink & worldLink,std::string & token){ + //convert all the WorldLink attributes into StorageWorldLink attributes to create one and store it in the world storage + + //authorId + xpcf::uuids::uuid authorId = xpcf::toUUID(worldLink.getCreatorUUID()); + + //transform 3d + std::vector vector = worldLink.getTransform(); + Eigen::Matrix matrix = Eigen::Map>(vector.data()); + SolAR::datastructure::Transform3Df transfo(matrix); + + //world element from ID + xpcf::uuids::uuid fromElementId = xpcf::toUUID(worldLink.getUUIDFrom()); + + //world element to ID + xpcf::uuids::uuid toElementId = xpcf::toUUID(worldLink.getUUIDTo()); + + Success returnedMessage; + //check if the link connects a single element + if(fromElementId == toElementId) + { + returnedMessage.setMessage("An element can not be connected to itself"); + return make_pair(BAD_REQUEST,returnedMessage); + } + + //world element from type + SolAR::datastructure::ElementKind fromElementType = WorldLinksSolARImpl::resolve_element_kind(worldLink.getTypeFrom()); + + //world element to type + SolAR::datastructure::ElementKind toElementType = WorldLinksSolARImpl::resolve_element_kind(worldLink.getTypeTo()); + + //adding the link to the storage by calling the world storage method + xpcf::uuids::uuid linkId; + + //unitsystem + SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldLink.getUnit()); + + //taglist + std::multimap keyvalueTagList; + for (std::pair> tag : worldLink.getKeyvalueTags()){ + for(std::string value : tag.second){ + keyvalueTagList.insert({tag.first,value}); + } + } + + //build the worldLink + xpcf::utils::shared_ptr storageWorldLink; + if(!worldLink.getUUID().empty()){ + xpcf::uuids::uuid id = xpcf::toUUID(worldLink.getUUID()); + storageWorldLink = xpcf::utils::make_shared(id,authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); + + } + else{ + storageWorldLink = xpcf::utils::make_shared(authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); + + } + switch(m_worldStorage->addWorldLink(linkId, storageWorldLink)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + //initialize the json object that we will send back to the client (the WorldAnchor's id) + std::string worldLinkIdString = xpcf::uuids::to_string(linkId); + returnedMessage.setMessage(xpcf::uuids::to_string(linkId)); + return make_pair(OK,returnedMessage); + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + returnedMessage.setMessage("The connected elements were not found in the world storage"); + return make_pair(NOT_FOUND,returnedMessage); + break; + } + + default : + { + returnedMessage.setMessage("Something went wrong"); + return make_pair(INTERNAL_SERVER_ERROR,returnedMessage); + } + } +} + +SolARWorldLinksResourceUUID::SolARWorldLinksResourceUUID(const std::string& context,const SRef worldStorage):WorldLinksWorldLinkUUIDResource::WorldLinksWorldLinkUUIDResource(context){ + m_worldStorage = worldStorage; +} + +std::pair SolARWorldLinksResourceUUID::handler_GET(std::string & worldLinkUUID, std::string & token){ + //initialize the json object that we will send back to the client + auto jsonObjects = nlohmann::json::array(); + + //look for the world anchor with given id + xpcf::uuids::uuid id = xpcf::toUUID(worldLinkUUID); + SRef storageWorldLink; + org::openapitools::server::model::WorldLink worldLink; + switch(m_worldStorage->getWorldLink(id, storageWorldLink)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + //StorageWorldLink found, we convert it into a WorldLink + worldLink = WorldLinksSolARImpl::from_storage(*storageWorldLink); + + return make_pair(OK,worldLink); + + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + return make_pair(NOT_FOUND,worldLink); + + break; + } + + default : + { + return make_pair(INTERNAL_SERVER_ERROR,worldLink); + } + } +} + +std::pair SolARWorldLinksResourceUUID::handler_DELETE(std::string & worldLinkUUID, std::string & token){ + auto linkId = xpcf::toUUID(worldLinkUUID); + Success returnedMessage; + switch(m_worldStorage->removeWorldLink(linkId)) + { + case SolAR::FrameworkReturnCode::_SUCCESS : + { + returnedMessage.setMessage("WorldLink removed"); + return make_pair(OK,returnedMessage); + break; + } + + case SolAR::FrameworkReturnCode::_NOT_FOUND : + { + returnedMessage.setMessage("WorldLink not found"); + return make_pair(NOT_FOUND,returnedMessage); + break; + } + + default : + { + returnedMessage.setMessage("Something went wrong"); + return make_pair(INTERNAL_SERVER_ERROR,returnedMessage); + + } + } +} + + + +WorldLinksSolARImpl::WorldLinksSolARImpl(std::shared_ptr const& restbedService, SRef worldStorage) + : WorldLinksApi(restbedService) +{ + m_spSolARWorldLinksResource = std::make_shared< SolARWorldLinksResource >("",worldStorage); + m_spSolARWorldLinksResource->set_path("/worldLinks"); + m_spSolARWorldLinksResourceUUID = std::make_shared< SolARWorldLinksResourceUUID >("",worldStorage); + m_spSolARWorldLinksResourceUUID->set_path("/worldLinks/{worldLinkUUID: .*}"); + + m_restbedService = restbedService; + m_worldStorage = worldStorage; +} + + +void WorldLinksSolARImpl::publishDefaultResources(){ + m_restbedService->publish(m_spSolARWorldLinksResource); + m_restbedService->publish(m_spSolARWorldLinksResourceUUID); + +} + +org::openapitools::server::model::WorldLink WorldLinksSolARImpl::from_storage(SolAR::datastructure::StorageWorldLink worldLink) +{ + //the object to be returned + org::openapitools::server::model::WorldLink ret; + + //convert all the StorageWorldLink attributes into WorldLink attibutes + + //world link UUID + std::string id = xpcf::uuids::to_string(worldLink.getId()); + ret.setUUID(id); + + //creator UUID + std::string creatorUid = xpcf::uuids::to_string(worldLink.getAuthor()); + ret.setCreatorUUID(creatorUid); + + //element from UUID + std::string elementTo = xpcf::uuids::to_string(worldLink.getUuidFrom()); + ret.setUUIDFrom(elementTo); + + //element to UUID + std::string elementFrom = xpcf::uuids::to_string(worldLink.getUuidTo()); + ret.setUUIDTo(elementFrom); + + //element from Type + model::TypeWorldStorage typeFrom = resolve_element_kind(worldLink.getTypeFrom()); + ret.setTypeFrom(typeFrom); + + //element to Type + model::TypeWorldStorage typeTo = resolve_element_kind(worldLink.getTypeTo()); + ret.setTypeTo(typeTo); + + //transform + SolAR::datastructure::Transform3Df transform3d = worldLink.getTransform(); + Eigen::Matrix matrix = transform3d.matrix(); + std::vector localCRS; + for (size_t i = 0; i < (size_t) matrix.rows(); i++) + { + for (size_t j = 0; j < (size_t) matrix.cols(); j++) + { + localCRS.push_back(matrix(i, j)); + } + } + ret.setTransform(localCRS); + + //Unit system + org::openapitools::server::model::UnitSystem unit = resolve_unitSystem(worldLink.getUnitSystem()); + ret.setUnit(unit); + + //keyvalue taglist (multimap to map>) + std::map> tagList; + auto storageMap = worldLink.getTags(); + for (const auto &tag : storageMap){ + if (tagList.count(tag.first) != 0){ + std::vector& vector = tagList.at(tag.first); + vector.push_back(tag.second); + }else { + std::vector vector; + vector.push_back(tag.second); + tagList.insert(std::pair>(tag.first, vector)); + } + } + ret.setKeyvalueTags(tagList); + + return ret; +} + +model::TypeWorldStorage WorldLinksSolARImpl::resolve_element_kind(SolAR::datastructure::ElementKind kind) +{ + model::TypeWorldStorage ret; + switch(kind) + { + case SolAR::datastructure::ElementKind::ANCHOR : + ret.setEnumValue("ANCHOR"); + return ret; + break; + case SolAR::datastructure::ElementKind::TRACKABLE : + ret.setEnumValue("TRACKABLE"); + return ret; + break; + default : + ret.setEnumValue("NOTIDENTIFIED"); + return ret; + } +} + +SolAR::datastructure::ElementKind WorldLinksSolARImpl::resolve_element_kind(model::TypeWorldStorage kind) +{ + std::string enumValue = kind.getEnumValue(); + + if (enumValue == "ANCHOR") + { + return SolAR::datastructure::ElementKind::ANCHOR; + } + else if (enumValue == "TRACKABLE") + { + return SolAR::datastructure::ElementKind::TRACKABLE; + } + else + { + return SolAR::datastructure::ElementKind::INVALID; + } +} +// void WorldLinksSolARImpl::add_world_link(const org::openapitools::server::model::WorldLink &worldLink, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //convert all the WorldLink attributes into StorageWorldLink attributes to create one and store it in the world storage + +// //authorId +// xpcf::uuids::uuid authorId = xpcf::toUUID(worldLink.getCreatorUUID()); + +// //transform 3d +// std::vector vector = worldLink.getTransform(); +// Eigen::Matrix matrix = Eigen::Map>(vector.data()); +// SolAR::datastructure::Transform3Df transfo(matrix); + +// //world element from ID +// xpcf::uuids::uuid fromElementId = xpcf::toUUID(worldLink.getUUIDFrom()); + +// //world element to ID +// xpcf::uuids::uuid toElementId = xpcf::toUUID(worldLink.getUUIDTo()); + +// //check if the link connects a single element +// if(fromElementId == toElementId) +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Bad_Request, "An element can not be connected to himself\n"); +// return; +// } + +// //world element from type +// SolAR::datastructure::ElementKind fromElementType = resolve_element_kind(worldLink.getTypeFrom()); + +// //world element to type +// SolAR::datastructure::ElementKind toElementType = resolve_element_kind(worldLink.getTypeTo()); + +// //adding the link to the storage by calling the world storage method +// xpcf::uuids::uuid linkId; + +// //unitsystem +// SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldLink.getUnit()); + +// //taglist +// std::multimap keyvalueTagList; +// for (std::pair> tag : worldLink.getKeyvalueTags()){ +// for(std::string value : tag.second){ +// keyvalueTagList.insert({tag.first,value}); +// } +// } + +// //build the worldLink +// xpcf::utils::shared_ptr storageWorldLink = xpcf::utils::make_shared(authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); +// switch(m_worldStorage->addWorldLink(linkId, storageWorldLink)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// //initialize the json object that we will send back to the client (the WorldAnchor's id) +// std::string worldLinkIdString = xpcf::uuids::to_string(linkId); +// auto jsonObjects = nlohmann::json::array(); +// nlohmann::to_json(jsonObjects, worldLinkIdString); + +// //send the ID to the client +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "The connected elements were not found in the world storage\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// } + +// void WorldLinksSolARImpl::delete_world_link(const std::string &worldLinkUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// auto linkId = xpcf::toUUID(worldLinkUUID); +// switch(m_worldStorage->removeWorldLink(linkId)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Ok, "WorldLink removed\n"); +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "WorldLink not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// } + +// void WorldLinksSolARImpl::get_world_link_by_id(const std::string &worldLinkUUID, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //initialize the json object that we will send back to the client +// auto jsonObjects = nlohmann::json::array(); + +// //look for the world anchor with given id +// xpcf::uuids::uuid id = xpcf::toUUID(worldLinkUUID); +// SRef storageWorldLink; + +// switch(m_worldStorage->getWorldLink(id, storageWorldLink)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// //StorageWorldLink found, we convert it into a WorldLink +// org::openapitools::server::model::WorldLink worldLink = from_storage(*storageWorldLink); + +// //add the WorldLink to our JSON object +// to_json(jsonObjects, worldLink); + +// //send the link to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); + +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "WorldLink not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// } + +// void WorldLinksSolARImpl::get_world_links(const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //initialize the json object that we will send back to the client +// auto jsonObjects = nlohmann::json::array(); + +// //declaration of all the objects that will be changed at each iteration of the loop +// nlohmann::json toAdd; +// org::openapitools::server::model::WorldLink worldLink; + +// std::vector> vector; +// if(m_worldStorage->getWorldLinks(vector) != SolAR::FrameworkReturnCode::_SUCCESS) +// { +// //Exception raised in getWorldLinks +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong when fetching the world storage"); +// } +// else +// { +// //for all the worldLinks in the worldStorage +// for(const SRef &l : vector){ +// //add the current world link to the JSON object +// worldLink = from_storage(*l); +// to_json(toAdd, worldLink); +// jsonObjects.push_back(toAdd); +// } + +// //send the JSON object to the client +// response.headers().add(MIME(Application, Json)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// } +// } + +// void WorldLinksSolARImpl::modify_world_link(const model::WorldLink &worldLink, const std::optional &token, Pistache::Http::ResponseWriter &response) +// { +// //convert all the WorldLink attributes into StorageWorldLink attributes to create one and store it in the world storage + +// //authorId +// xpcf::uuids::uuid authorId = xpcf::toUUID(worldLink.getCreatorUUID()); + +// //transform 3d +// std::vector vector = worldLink.getTransform(); +// Eigen::Matrix matrix = Eigen::Map>(vector.data()); +// SolAR::datastructure::Transform3Df transfo(matrix); + +// //world element from ID +// xpcf::uuids::uuid fromElementId = xpcf::toUUID(worldLink.getUUIDFrom()); + +// //world element to ID +// xpcf::uuids::uuid toElementId = xpcf::toUUID(worldLink.getUUIDTo()); + +// //check if the link connects a single element +// if(fromElementId == toElementId) +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Bad_Request, "An element can not be connected to himself\n"); +// } + +// //world element from type +// SolAR::datastructure::ElementKind fromElementType = resolve_element_kind(worldLink.getTypeFrom()); + +// //world element to type +// SolAR::datastructure::ElementKind toElementType = resolve_element_kind(worldLink.getTypeTo()); + +// //unitsystem +// SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldLink.getUnit()); + +// //taglist +// std::multimap keyvalueTagList; +// for (std::pair> tag : worldLink.getKeyvalueTags()){ +// for(std::string value : tag.second){ +// keyvalueTagList.insert({tag.first,value}); +// } +// } + +// //id +// xpcf::uuids::uuid id = xpcf::toUUID(worldLink.getUUID()); + + +// //build the worldLink +// xpcf::utils::shared_ptr storageWorldLink = xpcf::utils::make_shared(id, authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); + + +// //adding the link to the storage by calling the world storage method +// xpcf::uuids::uuid linkId; +// switch(m_worldStorage->modifyWorldLink(linkId, storageWorldLink)) +// { +// case SolAR::FrameworkReturnCode::_SUCCESS : +// { +// //initialize the json object that we will send back to the client (the WorldAnchor's id) +// std::string worldLinkIdString = xpcf::uuids::to_string(linkId); +// auto jsonObjects = nlohmann::json::array(); +// nlohmann::to_json(jsonObjects, worldLinkIdString); + +// //send the ID to the client +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); +// break; +// } + +// case SolAR::FrameworkReturnCode::_NOT_FOUND : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Not_Found, "Either the WorldLink was not found, or the elements it should connect were not found\n"); +// break; +// } + +// default : +// { +// response.headers().add(MIME(Text, Plain)); +// response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); +// } +// } +// } + +// void WorldLinksSolARImpl::init() +// { +// try +// { +// WorldLinksApi::init(); +// } +// catch (xpcf::Exception e) +// { +// std::cout << e.what() << std::endl; +// } +// } + + +} diff --git a/SolARModuleWorldGraph/src/SolARModuleWorldStorage_main.cpp b/SolARModuleWorldGraph/src/SolARModuleWorldStorage_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31efc5e820fa9157a25f6810b27a4588fcfcfecc --- /dev/null +++ b/SolARModuleWorldGraph/src/SolARModuleWorldStorage_main.cpp @@ -0,0 +1,59 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2017 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + +#include + +#include +#include +#include +#include + +namespace xpcf=org::bcom::xpcf; + +/** + * @ingroup xpcfmodule + */ +/** + * Declare module. + */ +XPCF_DECLARE_MODULE("{be14ee99-b47b-46c4-92c8-8ec9f15e5ddd}","SolARModuleWorldStorage","SolARModuleWorldStorage module description"); + +/** + * This method is the module entry point. + * XPCF uses this method to create components available in the module. + * + * Each component exposed must be declared inside a xpcf::tryCreateComponent() call. + */ +extern "C" XPCF_MODULEHOOKS_API xpcf::XPCFErrorCode XPCF_getComponent(const xpcf::uuids::uuid& componentUUID,SRef& interfaceRef) +{ + xpcf::XPCFErrorCode errCode = xpcf::XPCFErrorCode::_FAIL; + errCode = xpcf::tryCreateComponent(componentUUID,interfaceRef); + if (errCode != xpcf::XPCFErrorCode::_SUCCESS) + { + errCode = xpcf::tryCreateComponent(componentUUID,interfaceRef); + } + if (errCode != xpcf::XPCFErrorCode::_SUCCESS) + { + errCode = xpcf::tryCreateComponent(componentUUID,interfaceRef); + } + + return errCode; +} + +/** + * The declarations below populate list of the components available in the module (it represents the module index). + * XPCF uses this index to introspect the components available in a module, providing the ability to generate the configuration file skeleton from the code. + */ +XPCF_BEGIN_COMPONENTS_DECLARATION +XPCF_ADD_COMPONENT(SolAR::MODULES::SolARModuleWorldStorage::ETSIWorldGraphManager) +XPCF_ADD_COMPONENT(SolAR::MODULES::SolARModuleWorldStorage::ETSIWorldGraphService) +XPCF_ADD_COMPONENT(SolAR::MODULES::SolARModuleWorldStorage::ETSIWorldGraphClient) +XPCF_END_COMPONENTS_DECLARATION diff --git a/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/SolARTest_ModuleWorldStorage_ETSIWorldStorage.pro b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/SolARTest_ModuleWorldStorage_ETSIWorldStorage.pro new file mode 100644 index 0000000000000000000000000000000000000000..8d02ee911cf14430c305ee8702f32b41e3ea2c15 --- /dev/null +++ b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/SolARTest_ModuleWorldStorage_ETSIWorldStorage.pro @@ -0,0 +1,90 @@ +############################################################################### +# SolAR ARCloud +# (C) Copyright 2024 b<>com. All rights reserved. +# +# IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX +# This software is the confidential intellectual property of b<>com. +# You shall not disclose it and shall use it only in accordance with +# the terms of the license agreement you entered into with b<>com. +# +################################################################################ + +## remove Qt dependencies +QT -= core gui +CONFIG -= qt + +QMAKE_PROJECT_DEPTH = 0 + +## global defintions : target lib name, version +TARGET = SolARTest_ModuleWorldStorage_ETSIWorldStorage +VERSION=1.3.0 +PROJECTDEPLOYDIR = $${PWD}/../../deploy + +CONFIG += c++1z +CONFIG += console + +DEFINES += MYVERSION=\"\\\"$${VERSION}\\\"\" + +include(findremakenrules.pri) + +CONFIG(debug,debug|release) { + DEFINES += _DEBUG=1 + DEFINES += DEBUG=1 +} + +CONFIG(release,debug|release) { + DEFINES += _NDEBUG=1 + DEFINES += NDEBUG=1 +} + +win32:CONFIG -= static +win32:CONFIG += shared + + +QMAKE_TARGET.arch = x86_64 #must be defined prior to include + +DEPENDENCIESCONFIG = shared install_recurse + +## Configuration for Visual Studio to install binaries and dependencies. Work also for QT Creator by replacing QMAKE_INSTALL +PROJECTCONFIG = QTVS + +#NOTE : CONFIG as staticlib or sharedlib, DEPENDENCIESCONFIG as staticlib or sharedlib, QMAKE_TARGET.arch and PROJECTDEPLOYDIR MUST BE DEFINED BEFORE templatelibconfig.pri inclusion +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/templateappconfig.pri))) # Shell_quote & shell_path required for visual on windows + +HEADERS += \ + +SOURCES += \ + main.cpp + +unix { + LIBS += -ldl + QMAKE_CXXFLAGS += -Wno-attributes + + # Avoids adding install steps manually. To be commented to have a better control over them. + QMAKE_POST_LINK += "$(MAKE) install install_deps" +} + +macx { + QMAKE_MAC_SDK= macosx + QMAKE_CXXFLAGS += -fasm-blocks -x objective-c++ +} + +win32 { + QMAKE_LFLAGS += /MACHINE:X64 + DEFINES += WIN64 UNICODE _UNICODE + QMAKE_COMPILER_DEFINES += _WIN64 + + # Windows Kit (msvc2013 64) + LIBS += -L$$(WINDOWSSDKDIR)lib/winv6.3/um/x64 -lshell32 -lgdi32 -lComdlg32 + INCLUDEPATH += $$(WINDOWSSDKDIR)lib/winv6.3/um/x64 +} + +configfile.path = $${TARGETDEPLOYDIR}/ +configfile.files = $${PWD}/SolARTest_ModuleWorldStorage_ETSIWorldStorage_conf.xml +INSTALLS += configfile + +DISTFILES += \ + packagedependencies.txt + +#NOTE : Must be placed at the end of the .pro +include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/remaken_install_target.pri)))) # Shell_quote & shell_path required for visual on windows diff --git a/SolARSample_World_Storage_conf.xml b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/SolARTest_ModuleWorldStorage_ETSIWorldStorage_conf.xml similarity index 58% rename from SolARSample_World_Storage_conf.xml rename to SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/SolARTest_ModuleWorldStorage_ETSIWorldStorage_conf.xml index 802e84a6e8220023824cc361ad018d6ecd2d1005..da2daccf105ef8ef1a5a1b042c8b6ca892e8ecbe 100644 --- a/SolARSample_World_Storage_conf.xml +++ b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/SolARTest_ModuleWorldStorage_ETSIWorldStorage_conf.xml @@ -1,14 +1,20 @@ - - - + + + + + + - - - - - diff --git a/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/findremakenrules.pri b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/findremakenrules.pri new file mode 100644 index 0000000000000000000000000000000000000000..413e33a16e9703c012ffe3cf9c4afc294c3dd6e7 --- /dev/null +++ b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/findremakenrules.pri @@ -0,0 +1,43 @@ +# Author(s) : Loic Touraine, Stephane Leduc + +android { + # unix path + USERHOMEFOLDER = $$clean_path($$(HOME)) + isEmpty(USERHOMEFOLDER) { + # windows path + USERHOMEFOLDER = $$clean_path($$(USERPROFILE)) + isEmpty(USERHOMEFOLDER) { + USERHOMEFOLDER = $$clean_path($$(HOMEDRIVE)$$(HOMEPATH)) + } + } +} + +unix:!android { + USERHOMEFOLDER = $$clean_path($$(HOME)) +} + +win32 { + USERHOMEFOLDER = $$clean_path($$(USERPROFILE)) + isEmpty(USERHOMEFOLDER) { + USERHOMEFOLDER = $$clean_path($$(HOMEDRIVE)$$(HOMEPATH)) + } +} + +exists(builddefs/qmake) { + QMAKE_REMAKEN_RULES_ROOT=builddefs/qmake +} +else { + QMAKE_REMAKEN_RULES_ROOT = $$clean_path($$(REMAKEN_RULES_ROOT)) + !isEmpty(QMAKE_REMAKEN_RULES_ROOT) { + QMAKE_REMAKEN_RULES_ROOT = $$clean_path($$(REMAKEN_RULES_ROOT)/qmake) + } + else { + QMAKE_REMAKEN_RULES_ROOT=$${USERHOMEFOLDER}/.remaken/rules/qmake + } +} + +!exists($${QMAKE_REMAKEN_RULES_ROOT}) { + error("Unable to locate remaken rules in " $${QMAKE_REMAKEN_RULES_ROOT} ". Either check your remaken installation, or provide the path to your remaken qmake root folder rules in REMAKEN_RULES_ROOT environment variable.") +} + +message("Remaken qmake build rules used : " $$QMAKE_REMAKEN_RULES_ROOT) \ No newline at end of file diff --git a/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/main.cpp b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f11406cf1d4e15528ab3007c18b889874dd1a35 --- /dev/null +++ b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/main.cpp @@ -0,0 +1,70 @@ +/******************************************************************************* + * SolAR ARCloud + * (C) Copyright 2017 b<>com. All rights reserved. + * + * IDDN: FR.XXX.XXXXXX.XXX.X.X.XXXX.XXX.XXXXX + * This software is the confidential intellectual property of b<>com. + * You shall not disclose it and shall use it only in accordance with + * the terms of the license agreement you entered into with b<>com. + * + ********************************************************************************/ + +#include +#include +#include + +#include + +// ADD MODULES TRAITS HEADERS HERE + +// ADD XPCF HEADERS HERE +#include "xpcf/xpcf.h" + +// ADD COMPONENTS HEADERS HERE + +#include "api/storage/IWorldGraphManager.h" +#include "core/Log.h" + + +using namespace SolAR; +using namespace SolAR::datastructure; +using namespace SolAR::api; + +namespace xpcf = org::bcom::xpcf; + +int main(int argc, char *argv[]) +{ + + + LOG_ADD_LOG_TO_CONSOLE(); + try { + /* instantiate component manager*/ + /* this is needed in dynamic mode */ + SRef xpcfComponentManager = xpcf::getComponentManagerInstance(); + + if(xpcfComponentManager->load("SolARTest_ModuleWorldStorage_ETSIWorldStorage_conf.xml")!=org::bcom::xpcf::_SUCCESS) + { + LOG_ERROR("SolARTest_ModuleWorldStorage_ETSIWorldStorage_conf.xml"); + return -1; + } + + // declare and create components + LOG_INFO("Start creating components"); + + SRef worldGraphManager = xpcfComponentManager->resolve(); + + if (!worldGraphManager) + { + LOG_ERROR("One or more component creations have failed"); + return -1; + } + + LOG_INFO("coucou"); + } + catch (xpcf::Exception e) + { + LOG_ERROR ("The following exception has been catch : {}", e.what()); + return -1; + } + return 0; +} diff --git a/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/packagedependencies.txt b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/packagedependencies.txt new file mode 100644 index 0000000000000000000000000000000000000000..905063cc0275ab660360dc1ac091ddc9212f9db9 --- /dev/null +++ b/SolARModuleWorldGraph/tests/SolARTest_ModuleWorldStorage_ETSIWorldStorage/packagedependencies.txt @@ -0,0 +1 @@ +SolARFramework|1.3.0|SolARFramework|SolARBuild@github|https://github.com/SolarFramework/SolarFramework/releases/download diff --git a/SolARModuleWorldGraph/xpcf_SolARModuleWorldStorage_registry.xml b/SolARModuleWorldGraph/xpcf_SolARModuleWorldStorage_registry.xml new file mode 100644 index 0000000000000000000000000000000000000000..f28192aa58f77a4ecb22935407e28d458a079d56 --- /dev/null +++ b/SolARModuleWorldGraph/xpcf_SolARModuleWorldStorage_registry.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Solar-Wrapper/README.md b/Solar-Wrapper/README.md deleted file mode 100644 index dcfe53c34d5d95f4112f14d25bd01b8da8bc2aab..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/README.md +++ /dev/null @@ -1,139 +0,0 @@ -# SolARWorldStorage -## Server implementation using the SolAR world storage module - -[![License](https://img.shields.io/github/license/SolARFramework/SolARModuleOpencv?style=flat-square&label=License)](https://www.apache.org/licenses/LICENSE-2.0) - -This server handles REST requests designed in the ETSI specification file, [available on the ETSI forge](https://forge.etsi.org/rep/arf/arf005/-/blob/develop/API/openapi.yaml). - -It relies on two libraries: -- The library generated by the OpenAPI generator project. ([git repository](https://labs.etsi.org/rep/arf/world-storage-api-helpers/world-storage-cpp-server.git)) -- The world storage, a SolAR module used to store the different items needed to create an AR app ([git repository](https://github.com/SolarFramework/SolARModuleWorldStorage/tree/develop)) - - - -## I - OpenAPI project - -This project is the direct implementation of the server classes generated by the [OpenAPI generator ETSI project](https://labs.etsi.org/rep/arf/world-storage-api-helpers/world-storage-cpp-server.git) from the [API specification file](https://forge.etsi.org/rep/arf/arf005/-/blob/develop/API/openapi.yaml). -For each tag attribute that we defined in our specification (i.e "default", "trackable", "world anchor" and "world link"), OpenAPI generates classes handling the requests specific to that tag (one method generated per request specified). - -![OpenAPI generated classes](images/serverClasses.png) - -The OpenAPI project also generates model classes for our specified objects (e.g Trackables, WorldAnchors...). - -All of this project is exported as a library for us to use and augment in our wrapper. More info can be found in the project's git. - -Although we won't be using them, OpenAPI also generates basic implementation of the API endpoints classes and a main class to run your server instantly. - -## II - SolAR module - -**SolAR architecture** - -By SolAR standards, a module is a collection of components. Components are implementations of SolAR interfaces. -Our wrapper uses the world storage module, a singleton instantiated by the XPCF component manager, a SolAR tool. - -![XPCF component manager instantiation](images/XPCFComponentManager.png) - -It has a component that dynamically stores `Trackables`, `Anchors` and `Links` and implements the methods of the world graph manager, a SolAR interface. These methods allow for interaction with the stored elements. These elements are specified in the SolAR framework itself in the datastrucutre folder. -| **datastructure** | **description** | -|:-------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------:| -| `StorageWorldLink` | A Link between two `StorageWorldElement`, it holds the information of both elements and the transform between them | -| `StorageWorldElement` | The abstract type used to describe the elements that we want to store in our world storage. It holds all the common attributes to those elements. | -| `StorageTrackable` | (inherits `StorageWorldELement`) A trackable that will be stored in the world storage | -| `StorageWorldAnchor` | (inherits `StorageWorldELement`) A world anchor that will be stored in the world storage | - -Each datastructure is described in detail in the [SolAR git repository](https://github.com/SolarFramework/SolARFramework). - -**Module world storage** - -The module in itself has three attributes used to store information: - -- **m_nodes** : `map>` - - The map that holds all of the elements in the world storage, it stores their id as keys for performance purposes. -- **m_tags** : `multimap, shared_ptr>` - - A multimap that allows for research by the `tag`, a `StorageWorldElement` attribute that widens the capacity of customisation. It consists of a pair of string {key;value}. -- **m_links** : `map>` - - The map that holds all of the information regarding relations between each element. - -Each datastructure is stored dynamically with the usage of `shared_ptr`. - -**Method calls** - -All the methods of the world storage return a `FRAMEWORK_RETURN_CODE`, a SolAR enum to standardize and store responses from methods. most of them will return -- `FRAMEWORK_RETURN_CODE::_SUCCESS` when the method executes succesfuly -- `FRAMEWORK_RETURN_CODE::_ERROR__` when an error is raised -- `FRAMEWORK_RETURN_CODE::_NOT_FOUND_` when ressources that need to be fetched are not available. - -Most of the methods implemented by the module are described in the [project README](https://github.com/SolarFramework/SolARModuleWorldStorage/tree/develop#readme) - -## III - Wrapper architecture - -**OpenAPI inheritance** - -For the endpoints, we have to make new classes that inherit those generated by OpenAPI and override their handle methods in order to be able to correcly answer REST requests. -For now we have four child classes : -- `DefaultSolARImpl` -- `TrackablesSolARImpl` -- `WolrdAnchorsSolARImpl` -- `WorldLinksSolARImpl` - -Here are the methods associated to each endpoint : - -| Class | Methods | -|:------------:|:--------------------------------------------------:| -| `DefaultApi.h` | ![Default methods](images/DefaultMethods.png) | -| `TrackableApi.h` | ![Trackable methods](images/TrackableMethods.png) | -| `WorldAnchorApi.h` | ![Anchor methods](images/AnchorMethods.png) | -| `WorldLinkApi.h` | ![Link methods](images/LinkMethods.png) | - - -For all those methods, the `Pistache::Http::ResponseWriter` is a [out] param that allows the user to give the response back to the REST request. - - -Except for the `DefaultSolARImpl` class, that only has usages for when you want to check if the server is up and check the version, all of those classes have the world storage singleton as an attribute. On which they will be able to call methods in response to requests. -The module is passsed down through the constructor to ensure the uniqueness of it. - -**Default methods** - **`get_ping` | `get_version`** -These two methods are associated to the "Default" endpoint and serve the purpose of indicating the server's state. - -**add_X** - **`add_trackable` | `add_world_anchor` | `add_world_link`** -These methods are used for all the models that we want to preserve in our storage. As an argument, you receive the object you want to add. Its type is of the model type defined in the API specification. The verification of the object's integrity is already done in the OpenAPI generated library. -In our SolAR wrapper we perform a conversion between the two types that we use (OpenAPI model and SolAR datastructure) and then call the module's add method corresponding to the element in question to add it to the world storage. -For the `add_world_link`, we also added a verification that the two elements it connects are present in the world storage prior to the request reception. -When the user performs a REST request to add an element, he gets as a response the ID of the newly added element. - -**delete_X** - **`delete_trackable` | `delete_world_anchor` | `delete_world_link`** -Those are the methods you call when you want to delete an element from the world storage. The methods receive a UUID (unique identifier) as a `String` argument, convert it to the `UUID` type (from the boost library) and pass it to the module's delete method. -When the user performs a REST request to remove an element, he gets as a response a confirmation that the element is deleted (or not). - -**get_X_by_id** - **`get_trackable_by_id` | `get_world_anchor_by_id` | `get_world_link_by_id`** -The logic is the same as the delete methods: we get a `String` UUID, convert it to `UUID` type and pass it to the module's get method. -The module's method returns a SolAR datastructure on which we call the `from_storage` method to convert it to the OpenAPI model. Then we can translate it into a JSON thanks to the `to_json` method generated by OpenAPI. We return this JSON to the user who sent the request. - - -**get_Xs** - **`get_trackables` | `get_world_anchors` | `get_world_links`** -These methods return all the elements (of a given type) present in the world storage. We call the module's get_Xs method that returns a vector. For each element of this vector we add it to a JSON array that will be sent back to the user. - - -**get_attached_objects_from_uuid** - **`get_attached_objects_from_uuid`** -This method receives as an argument a link Id, fetches it from the world storage via the module's `getWorldLink` method. Then we look at the two elements it connects and put their info into a JSON that we send back to the user. - -**Utility methods** - **`from_storage` | `to_bytes`** -These methods do not override methods from the OpenAPI generated library, they are here to help handle models/datastructures. `from_storage` converts a SolAR datastructure into an OpenAPI model, `to_bytes` is only used to convert the `Trackable`'s payload attribute from a `String` into a vector of bytes. - -## Main - -The main.cpp class being already generated by OpenAPI, we just have to modify it to match what we want for our server. After setting up the world storage module, we need to set up our endpoints classes. - -![XPCF component manager instantiation](images/HandleSetUp.png) - -Once it's done, the rest of the generated code sets up everything up and waits for REST requests on http://localhost:8080. - - - diff --git a/Solar-Wrapper/interfaces/DefaultSolARImpl.h b/Solar-Wrapper/interfaces/DefaultSolARImpl.h deleted file mode 100644 index a65921aa387feccde3b6311fb7e0cf2f5fb87abe..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/interfaces/DefaultSolARImpl.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DEFAULTSOLARIMPL_H -#define DEFAULTSOLARIMPL_H - -#include -#include -#include -#include -#include -#include -#include -#include - - - -namespace org::openapitools::server::implem -{ - - using namespace org::openapitools::server::model; - - /** - * @class - * @brief implementation of (class generated by OpenAPI-Generator), implements all the method defined with no tags in the API specification - * - */ - - class DefaultSolARImpl : public org::openapitools::server::api::DefaultApi { - - public: - explicit DefaultSolARImpl(const std::shared_ptr& rtr); - ~DefaultSolARImpl() override = default; - - void get_version(Pistache::Http::ResponseWriter &response) override; - void get_ping(Pistache::Http::ResponseWriter &response) override; - void get_admin(Pistache::Http::ResponseWriter &response) override; - - // DefaultApi interface - private: - }; - -} - -#endif // DEFAULTSOLARIMPL_H diff --git a/Solar-Wrapper/interfaces/TrackablesSolARImpl.h b/Solar-Wrapper/interfaces/TrackablesSolARImpl.h deleted file mode 100644 index 986c0c95fdc267fe89d2b3e4f5ff74799c4238c0..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/interfaces/TrackablesSolARImpl.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TRACKABLES_SOLAR_IMPL_H_ -#define TRACKABLES_SOLAR_IMPL_H_ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -namespace org::openapitools::server::implem -{ - -/** - * @class TrackablesSolARImpl - * @brief implementation of TrackableAPI (class generated by OpenAPI-Generator), implements all the methods defined with the tag 'trackable' in the API specification - * - */ - -class TrackablesSolARImpl : public org::openapitools::server::api::TrackablesApi { - public: - explicit TrackablesSolARImpl(const std::shared_ptr& rtr, SRef worldStorage); - ~TrackablesSolARImpl() override = default; - - - /// @brief API method to add a trackable to the world storage. It converts the Trackable into a StorageTrackable and stores it in the worldGraph manager - /// @param trackable: trackable to be added - /// @param response: the response to be sent: if it succeeds, the UUID of the newly created StorageTrackable - void add_trackable(const org::openapitools::server::model::Trackable &trackable, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to delete a trackable, it fetches the StorageTrackable in the world storage Manager and removes it - /// @param trackableUUID: the ID of the StorageTrackable to be removed - /// @param response: the response to be sent: if it succeeds, a confirmation of the deletion of the StorageTrackable - void delete_trackable(const std::string &trackableUUID, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to get a single StorageTrackable from the world storage - /// @param trackableUUID: the ID of the trackable to be fetched - /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from the StorageTrackable - void get_trackable_by_id(const std::string &trackableUUID, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to get all the trackables currently stored in the world storage - /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from all the StorageTrackables - void get_trackables(Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to modify an existing trackable in the world storage. - /// @param trackable: trackable to be modified - /// @param response: the response to be sent: if it succeeds, the UUID of the modified StorageTrackable - void modify_trackable(const org::openapitools::server::model::Trackable &trackable, Pistache::Http::ResponseWriter &response) override; - - /// @brief static method to convert StorageTrackable (defined by the SolAR framework) to a Trackable (defined by OpenAPI generator) - /// @param trackable: the StorageTrackable to be converted - /// @return the converted trackable - static org::openapitools::server::model::Trackable from_storage(const SolAR::datastructure::StorageTrackable &trackable); - - /// @brief static method to transform a string into a vector of bytes. Used to transform a Trackable into a StorageTrackable (attribute payload) - /// @return a vector of byte - static std::vector to_bytes(const std::string &s); - - /// @brief initialize the API handler, creates the singleton m_worldStorage if it is not already done - void init(); - - private: - /// @brief the instance of the world storage manager that will be used to handle the queries - SRef m_worldStorage; -}; - -} // namespace org::openapitools::server::api - - - -#endif diff --git a/Solar-Wrapper/interfaces/UnitSysConversion.h b/Solar-Wrapper/interfaces/UnitSysConversion.h deleted file mode 100644 index 3f9baeddf9275dc1f1bda7c097f07a7dfbbadc9b..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/interfaces/UnitSysConversion.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef UNITSYSCONVERSION_H -#define UNITSYSCONVERSION_H - - -#include -#include -#include -#include -#include - -#include "TrackablesSolARImpl.h" - -namespace xpcf = org::bcom::xpcf; -namespace org::openapitools::server::implem -{ - - /// @brief method to swap between UnitSystem enums (SolAR & OPenAPI) - /// @param the UnitSystem in openAPI format - /// @return the UnitSystem in SolAR format - static SolAR::datastructure::UnitSystem resolve_unitSystem(org::openapitools::server::model::UnitSystem input){ - switch(input.getValue()){ - case org::openapitools::server::model::UnitSystem::eUnitSystem::MM: - { - return SolAR::datastructure::UnitSystem::MM; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::CM: - { - return SolAR::datastructure::UnitSystem::CM; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::DM: - { - return SolAR::datastructure::UnitSystem::DM; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::M: - { - return SolAR::datastructure::UnitSystem::M; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::DAM: - { - return SolAR::datastructure::UnitSystem::DAM; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::HM: - { - return SolAR::datastructure::UnitSystem::HM; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::KM: - { - return SolAR::datastructure::UnitSystem::KM; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::INCH: - { - return SolAR::datastructure::UnitSystem::INCH; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::FOOT: - { - return SolAR::datastructure::UnitSystem::FOOT; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::YARD: - { - return SolAR::datastructure::UnitSystem::YARD; - break; - } - case org::openapitools::server::model::UnitSystem::eUnitSystem::MILE: - { - return SolAR::datastructure::UnitSystem::MILE; - break; - } - default: - { - return SolAR::datastructure::UnitSystem::INVALID; - } - } - } - - /// @brief method to swap between UnitSystem enums (OPenAPI & SolAR) - /// @param the UnitSystem in SolAR format - /// @return the UnitSystem in openAPI format - static org::openapitools::server::model::UnitSystem resolve_unitSystem(SolAR::datastructure::UnitSystem input){ - - org::openapitools::server::model::UnitSystem ret; - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::INVALID_VALUE_OPENAPI_GENERATED); - switch(input){ - case SolAR::datastructure::UnitSystem::MM: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::MM); - break; - } - case SolAR::datastructure::UnitSystem::CM: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::CM); - break; - } - case SolAR::datastructure::UnitSystem::DM: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::DM); - break; - } - case SolAR::datastructure::UnitSystem::M: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::M); - break; - } - case SolAR::datastructure::UnitSystem::DAM: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::DAM); - break; - } - case SolAR::datastructure::UnitSystem::HM: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::HM); - break; - } - case SolAR::datastructure::UnitSystem::KM: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::KM); - break; - } - case SolAR::datastructure::UnitSystem::INCH: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::INCH); - break; - } - case SolAR::datastructure::UnitSystem::FOOT: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::FOOT); - break; - } - case SolAR::datastructure::UnitSystem::YARD: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::YARD); - break; - } - case SolAR::datastructure::UnitSystem::MILE: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::MILE); - break; - } - default: - { - ret.setValue(org::openapitools::server::model::UnitSystem::eUnitSystem::INVALID_VALUE_OPENAPI_GENERATED); - } - } - return ret; - } - -} -#endif // UNITSYSCONVERSION_H diff --git a/Solar-Wrapper/interfaces/WorldAnchorsSolARImpl.h b/Solar-Wrapper/interfaces/WorldAnchorsSolARImpl.h deleted file mode 100644 index bc8fb74ca89f4ef03a123d6c1124f03f8440260d..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/interfaces/WorldAnchorsSolARImpl.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WORLDANCHORSSOLARIMPL_H -#define WORLDANCHORSSOLARIMPL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace org::openapitools::server::implem -{ - - -/** - * @class WorldAnchorsSolARImpl - * @brief implementation of WorldAnchorsAPI (class generated by OpenAPI-Generator), implements all the method defined with the tag 'world anchors' in the API specification - * - */ - -class WorldAnchorsSolARImpl : public org::openapitools::server::api::WorldAnchorsApi { - public: - explicit WorldAnchorsSolARImpl(const std::shared_ptr& rtr, SRef worldStorage); - ~WorldAnchorsSolARImpl() override = default; - - - /// @brief API method to add a world anchor to the world storage. It converts the World anchor into a StorageWorldAnchor and stores it in the worldGraph manager - /// @param worldAnchor: worldAnchor to be added - /// @param response: the response to be sent: if it succeeds, the UUID of the newly created StorageWorldAnchor - void add_world_anchor(const org::openapitools::server::model::WorldAnchor &worldAnchor, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to delete a world anchor, it fetches the StorageWorldAnchor in the world storage Manager and removes it - /// @param worldAnchorUUID: the ID of the StorageWorldAnchor to be removed - /// @param response: the response to be sent: if it succeeds, a confirmation of the deletion of the StorageWorldAnchor - void delete_world_anchor(const std::string &worldAnchorUUID, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to get a single StorageWorldAnchor from the world storage - /// @param worldAnchorUUID: the ID of the world anchor to be fetched - /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from the StorageWorldAnchor - void get_world_anchor_by_id(const std::string &worldAnchorUUID, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to get all the world anchors currently stored in the world storage - /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from all the StorageWorldAnchor - void get_world_anchors(Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to modify an existing world anchor in the world storage. - /// @param worldAnchor: worldAnchor to be modified - /// @param response: the response to be sent: if it succeeds, the UUID of the modified worldAnchor - void modify_world_anchor(const org::openapitools::server::model::WorldAnchor &worldAnchor, Pistache::Http::ResponseWriter &response) override; - - /// @brief static method to convert StorageWorldAnchor (defined by the SolAR framework) to a world anchors (defined by OpenAPI generator) - /// @param worldAnchor: the StorageWorldAnchor to be converted - /// @return the converted world anchor - static org::openapitools::server::model::WorldAnchor from_storage(const SolAR::datastructure::StorageWorldAnchor &worldAnchor); - - /// @brief initialize the API handler, creates the singleton m_worldStorage if it is not already done - void init(); - - private: - /// @brief the instance of the world storage manager that will be used to handle the queries - SRef m_worldStorage; - -}; - -} // namespace org::openapitools::server::api - - -#endif // WORLDANCHORSSOLARIMPL_H diff --git a/Solar-Wrapper/interfaces/WorldLinksSolARImpl.h b/Solar-Wrapper/interfaces/WorldLinksSolARImpl.h deleted file mode 100644 index 583e56be476974dde21e66f189cf84b5c1ecc51e..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/interfaces/WorldLinksSolARImpl.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifndef WORLDLINKSSOLARIMPL_H - -#define WORLDLINKSSOLARIMPL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace org::openapitools::server::implem -{ - -/** - * @class WorldLinksSolARImpl - * @brief implementation of WorldLinksAPI (class generated by OpenAPI-Generator), implements all the method defined with the tag 'world links' in the API specification - * - */ - -class WorldLinksSolARImpl : public org::openapitools::server::api::WorldLinksApi { - public: - explicit WorldLinksSolARImpl(const std::shared_ptr& rtr, SRef worldStorage); - ~WorldLinksSolARImpl() override = default; - - - /// @brief API method to add a world link to the world storage. It converts the World link into a StorageWorldLink and stores it in the worldGraph manager - /// @param worldLink: worldLink to be added - /// @param response: the response to be sent: if it succeeds, the UUID of the newly created StorageWorldLink - void add_world_link(const org::openapitools::server::model::WorldLink &worldLink, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to delete a world link, it fetches the StorageWorldLink in the world storage Manager and removes it - /// @param worldLinkUUID: the ID of the StorageWorldLink to be removed - /// @param response: the response to be sent: if it succeeds, a confirmation of the deletion of the StorageWorldLink - void delete_world_link(const std::string &worldLinkUUID, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to get a single StorageWorldLink from the world storage - /// @param worldLinkUUID: the ID of the world link to be fetched - /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from the StorageWorldLink - void get_world_link_by_id(const std::string &worldLinkUUID, Pistache::Http::ResponseWriter &response) override; - - /// @brief API method to get all the world links currently stored in the world storage - /// @param response: the response to be sent: if it succeeds, a JSON containing all the informations from all the StorageWorldLink - void get_world_links(Pistache::Http::ResponseWriter &response) override; - - virtual void modify_world_link(const org::openapitools::server::model::WorldLink &worldLink, Pistache::Http::ResponseWriter &response) override; - - /// @brief static method that returns a worldlink Json object from the informations contaiend in the worldStorage (before implementing a solution taht complies with the world link api description) - /// @param worldLink: the StorageWorldLink to be converted - /// @return A Json containing the id of the link, the id of both attached elements and the transform between them - static org::openapitools::server::model::WorldLink from_storage(SolAR::datastructure::StorageWorldLink worldLink); - - /// @brief method to get the world elements currently linked to the given world link - /// @param response: A pair containing shared pointers of the two elements connected to by the link - std::pair,SRef> get_attached_objects_from_uuid(const std::string &worldLinkUUID); - - /// @brief initialize the API handler, creates the singleton m_worldStorage if it is not already done - void init(); - - /// @brief method to convert ElementKind(SolAR) to ObjectType(OpenAPI spec) - static model::ObjectType resolve_element_kind(SolAR::datastructure::ElementKind kind); - - /// @brief method to convert ObjectType(OpenAPI spec) to ElementKind(SolAR) - static SolAR::datastructure::ElementKind resolve_element_kind(model::ObjectType kind); - - private: - /// @brief the instance of the world storage manager that will be used to handle the queries - SRef m_worldStorage; - -}; - -} // namespace org::openapitools::server::api - -#endif // WORLDLINKSSOLARIMPL_H diff --git a/Solar-Wrapper/openapitools.json b/Solar-Wrapper/openapitools.json deleted file mode 100644 index 2774f4541b6dc8afc9786080258ce73cf28cb845..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/openapitools.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json", - "spaces": 2, - "generator-cli": { - "version": "5.3.1" - } -} diff --git a/Solar-Wrapper/src/DefaultSolARImpl.cpp b/Solar-Wrapper/src/DefaultSolARImpl.cpp deleted file mode 100644 index f64144aa4851b9bd4312c82969791887a79265c2..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/src/DefaultSolARImpl.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "DefaultSolARImpl.h" - -namespace org::openapitools::server::implem -{ - - DefaultSolARImpl::DefaultSolARImpl(const std::shared_ptr& rtr) - : DefaultApi(rtr) - { - } - - void DefaultSolARImpl::get_version(Pistache::Http::ResponseWriter &response){ - response.headers().add(MIME(Text, Plain)); - //TODO put it in a variable - response.send(Pistache::Http::Code::Ok, "Version 1.0.0"); - } - - void DefaultSolARImpl::get_ping(Pistache::Http::ResponseWriter &response) { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, "Pong"); - } - - void DefaultSolARImpl::get_admin(Pistache::Http::ResponseWriter &response) { - response.headers().add(MIME(Text, Plain)); - //TODO add verif on the module side - response.send(Pistache::Http::Code::Ok, "Server running and ready!"); - } - -} diff --git a/Solar-Wrapper/src/TrackablesSolARImpl.cpp b/Solar-Wrapper/src/TrackablesSolARImpl.cpp deleted file mode 100644 index 0ab6a5899ede6bdc75855b6ed14390795331cb9e..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/src/TrackablesSolARImpl.cpp +++ /dev/null @@ -1,389 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace xpcf = org::bcom::xpcf; - -namespace org::openapitools::server::implem -{ - - - TrackablesSolARImpl::TrackablesSolARImpl(const std::shared_ptr& rtr, SRef worldStorage) - : TrackablesApi(rtr) - { - m_worldStorage = worldStorage; - } - - void TrackablesSolARImpl::add_trackable(const org::openapitools::server::model::Trackable &trackable, Pistache::Http::ResponseWriter &response) - { - //convert all the Trackable attributes into StorageTrackable attributes to create one and store it in the world storage - - //creator uuid - xpcf::uuids::uuid creatorId = xpcf::toUUID(trackable.getCreatorUUID()); - - //localCRS - for (float i: trackable.getLocalCRS()){ - std::cout << std::to_string(i) << std::endl; - } - std::vector vector = trackable.getLocalCRS(); - float* data = vector.data(); - Eigen::Matrix matrix = Eigen::Map>(data); - SolAR::datastructure::Transform3Df localCRS(matrix); - - //unitsystem - SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(trackable.getUnit()); - - //dimension - Eigen::Vector3d dimension = Eigen::Vector3d(trackable.getTrackableSize().data()); - - //taglist - std::multimap keyvalueTagList; - for (const auto &tag : trackable.getKeyvalueTags()){ - for(const auto &value : tag.second){ - keyvalueTagList.insert({tag.first,value}); - } - } - - //trackable type - SolAR::datastructure::StorageTrackableType type = SolAR::datastructure::resolveTrackableType(trackable.getTrackableType()); - - //encoding info - SolAR::datastructure::EncodingInfo encodingInfo(trackable.getTrackableEncodingInformation().getDataFormat(), trackable.getTrackableEncodingInformation().getVersion()); - - //payload - std::vector payload = TrackablesSolARImpl::to_bytes(trackable.getTrackablePayload()); - - //name - std::string name = trackable.getName(); - - //create the trackable - SRef storageTrackable = xpcf::utils::make_shared(creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); - - //adding the newly created StorageTrackable to the worldgraph - xpcf::uuids::uuid trackableId; - if(m_worldStorage->addTrackable(trackableId, storageTrackable) != SolAR::FrameworkReturnCode::_SUCCESS) - { - //if something went wrong - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "something went wrong when adding the trackable to the world storage"); - return; - } - - //initialize the json object that we will send back to the client (the trackable's id) - std::string trackableIdString = xpcf::uuids::to_string(trackableId); - auto jsonObjects = nlohmann::json::array(); - nlohmann::to_json(jsonObjects, trackableIdString); - - //send the ID to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - } - - void TrackablesSolARImpl::delete_trackable(const std::string &trackableUUID, Pistache::Http::ResponseWriter &response) - { - //trackable uuid - xpcf::uuids::uuid id = xpcf::toUUID(trackableUUID); - switch(m_worldStorage->removeTrackable(id)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, "Trackable removed\n"); - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "Trackable not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - } - - void TrackablesSolARImpl::get_trackable_by_id(const std::string &trackableUUID, Pistache::Http::ResponseWriter &response) - { - //initialize the json object that we will send back to the client - auto jsonObjects = nlohmann::json::array(); - - //look for the trackable with given id - xpcf::uuids::uuid id = xpcf::toUUID(trackableUUID); - SRef storageTrackable; - - switch(m_worldStorage->getTrackable(id, storageTrackable)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - //StorageTrackable found, we convert it into a Trackable - org::openapitools::server::model::Trackable trackable = from_storage(*storageTrackable); - - //add the Trackable to our JSON object - to_json(jsonObjects, trackable); - - //send the Trackable to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "Trackable not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - - - } - - void TrackablesSolARImpl::get_trackables(Pistache::Http::ResponseWriter &response) - { - - //initialize the json object that we will send back to the client - auto jsonObjects = nlohmann::json::array(); - - //declaration of all the objects that will be changed at each iteration of the loop - nlohmann::json toAdd; - org::openapitools::server::model::Trackable track; - - std::vector> vector; - if(m_worldStorage->getTrackables(vector) != SolAR::FrameworkReturnCode::_SUCCESS) - { - //Exception raised in getTrackables - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong when fetching the trackables from the world storage"); - } - else - { - //iteration over the content of the world storage - for (const SRef &t : vector){ - //add the current trackable to the JSON object - track = from_storage(*t); - to_json(toAdd, track); - jsonObjects.push_back(toAdd); - } - - //send the JSON object to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - } - } - - void TrackablesSolARImpl::modify_trackable(const model::Trackable &trackable, Pistache::Http::ResponseWriter &response) - { - //convert all the Trackable attributes into StorageTrackable attributes to create one and store it in the world storage - - //creator uuid - xpcf::uuids::uuid creatorId = xpcf::toUUID(trackable.getCreatorUUID()); - - //localCRS - std::vector vector = trackable.getLocalCRS(); - Eigen::Matrix matrix = Eigen::Map>(vector.data()); - SolAR::datastructure::Transform3Df localCRS(matrix); - - //unitsystem - SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(trackable.getUnit()); - - //dimension - Eigen::Vector3d dimension = Eigen::Vector3d(trackable.getTrackableSize().data()); - - //taglist - std::multimap keyvalueTagList; - for (const auto &tag : trackable.getKeyvalueTags()){ - for(const auto &value : tag.second){ - keyvalueTagList.insert({tag.first,value}); - } - } - - //trackable type - SolAR::datastructure::StorageTrackableType type = SolAR::datastructure::resolveTrackableType(trackable.getTrackableType()); - - //encoding info - SolAR::datastructure::EncodingInfo encodingInfo(trackable.getTrackableEncodingInformation().getDataFormat(), trackable.getTrackableEncodingInformation().getVersion()); - - //payload - std::vector payload = TrackablesSolARImpl::to_bytes(trackable.getTrackablePayload()); - - //name - std::string name = trackable.getName(); - - //id - boost::uuids::uuid id = xpcf::toUUID(trackable.getUUID()); - - //create the trackable - SRef storageTrackable = xpcf::utils::make_shared(id, creatorId, localCRS, unitSystem, dimension, keyvalueTagList, type, encodingInfo, payload, name); - - //adding the newly created StorageTrackable to the worldgraph - xpcf::uuids::uuid trackableId; - switch(m_worldStorage->modifyTrackable(trackableId, storageTrackable)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - //initialize the json object that we will send back to the client (the trackable's id) - std::string trackableIdString = xpcf::uuids::to_string(trackableId); - auto jsonObjects = nlohmann::json::array(); - nlohmann::to_json(jsonObjects, trackableIdString); - - //send the ID to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "Trackable not found\n"); - - break; - } - - default : - { - //if something went wrong - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "something went wrong when modifying the trackable to the world storage\n"); - - } - } - - return; - } - - org::openapitools::server::model::Trackable TrackablesSolARImpl::from_storage(const SolAR::datastructure::StorageTrackable &trackable){ - //the object to be returned - org::openapitools::server::model::Trackable ret; - - //convert all the StorageTrackable attributes into Trackable attibutes - - //trackable UUID - std::string id = xpcf::uuids::to_string(trackable.getID()); - ret.setUUID(id); - - //creator UUID - std::string creatorUid = xpcf::uuids::to_string(trackable.getCreatorID()); - ret.setCreatorUUID(creatorUid); - - //name - ret.setName(trackable.getName()); - - //Trackable type - std::string type = resolveTrackableType(trackable.getType()); - ret.setTrackableType(type); - - //EncodingInfo struct - org::openapitools::server::model::EncodingInformationStructure encodingInfo; - SolAR::datastructure::EncodingInfo storageEncodingInfo(trackable.getEncodingInfo()); - encodingInfo.setDataFormat(storageEncodingInfo.getDataFormat()); - encodingInfo.setVersion(storageEncodingInfo.getVersion()); - ret.setTrackableEncodingInformation(encodingInfo); - - //Payload - std::vector storagePayload = trackable.getPayload(); - std::string payload(reinterpret_cast(&storagePayload[0]), storagePayload.size()); - ret.setTrackablePayload(payload); - - //Transform3Df (localCRS) - SolAR::datastructure::Transform3Df transform3d = trackable.getLocalCrs(); - Eigen::Matrix4f matrix = transform3d.matrix(); - std::vector localCRS; - for (size_t i = 0; i < (size_t) matrix.rows(); i++) - { - for (size_t j = 0; j < (size_t) matrix.cols(); j++) - { - localCRS.push_back(matrix(i, j)); - } - } - ret.setLocalCRS(localCRS); - - //Unit system - org::openapitools::server::model::UnitSystem unit = resolve_unitSystem(trackable.getUnitSystem()); - ret.setUnit(unit); - - //Dimension (scale) - Eigen::Vector3d dimension = trackable.getSize(); - std::vector vector(3); - for(int i = 0; i < 3; i++) - { - vector[i] = dimension[0,i]; - } - ret.setTrackableSize(vector); - - //keyvalue taglist (multimap to map>) - std::map> tagList; - auto storageMap = trackable.getTags(); - for (const auto &tag : storageMap) - { - if (tagList.count(tag.first) != 0){ - std::vector& vector = tagList.at(tag.first); - vector.push_back(tag.second); - }else { - std::vector vector; - vector.push_back(tag.second); - tagList.insert(std::pair>(tag.first, vector)); - } - } - ret.setKeyvalueTags(tagList); - - return ret; - } - - std::vector TrackablesSolARImpl::to_bytes(const std::string &s) - { - std::vector bytes; - bytes.reserve(std::size(s)); - std::transform(std::begin(s), std::end(s), std::back_inserter(bytes), [](char c){ - return std::byte(c); - }); - - return bytes; - } - - void TrackablesSolARImpl::init(){ - try { - TrackablesApi::init(); - } - catch (xpcf::Exception e) - { - std::cout << e.what() << std::endl; - } - } - -} - diff --git a/Solar-Wrapper/src/WorldAnchorsSolARImpl.cpp b/Solar-Wrapper/src/WorldAnchorsSolARImpl.cpp deleted file mode 100644 index 58ecba2b16b3924122396481a0437489bd796741..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/src/WorldAnchorsSolARImpl.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include -#include -#include -#include -#include - -namespace org::openapitools::server::implem -{ - - - WorldAnchorsSolARImpl::WorldAnchorsSolARImpl(const std::shared_ptr& rtr, SRef worldStorage) - : WorldAnchorsApi(rtr) - { - m_worldStorage = worldStorage; - } - - void WorldAnchorsSolARImpl::add_world_anchor(const org::openapitools::server::model::WorldAnchor &worldAnchor, Pistache::Http::ResponseWriter &response) - { - //convert all the WorldAnchor attributes into StorageWorldAnchor attributes to create one and store it in the world storage - - //creator uuid - xpcf::uuids::uuid creatorId = xpcf::toUUID(worldAnchor.getCreatorUUID()); - - //localCRS - std::vector vector = worldAnchor.getLocalCRS(); - Eigen::Matrix matrix = Eigen::Map>(vector.data()); - SolAR::datastructure::Transform3Df localCRS(matrix); - - //size - Eigen::Vector3d size = Eigen::Vector3d(worldAnchor.getWorldAnchorSize().data()); - - //unitsystem - SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldAnchor.getUnit()); - - //taglist - std::multimap keyvalueTagList; - for (std::pair> tag : worldAnchor.getKeyvalueTags()){ - for(std::string value : tag.second){ - keyvalueTagList.insert({tag.first,value}); - } - } - - //name - std::string name = worldAnchor.getName(); - - //create a world anchor - SRef storageWorldAnchor = xpcf::utils::make_shared(creatorId, localCRS, unitSystem, size, keyvalueTagList, name); - - //adding the newly created StorageWorldAnchor to the worldgraph - xpcf::uuids::uuid worldAnchorId; - if(m_worldStorage->addWorldAnchor(worldAnchorId, storageWorldAnchor) != SolAR::FrameworkReturnCode::_SUCCESS) - { - //if something went wrong - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "something went wrong when adding the anchor to the world storage"); - return; - } - - //initialize the json object that we will send back to the client (the WorldAnchor's id) - std::string worldAnchorIdString = xpcf::uuids::to_string(worldAnchorId); - auto jsonObjects = nlohmann::json::array(); - nlohmann::to_json(jsonObjects, worldAnchorIdString); - - //send the ID to the client - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - } - - void WorldAnchorsSolARImpl::delete_world_anchor(const std::string &worldAnchorUUID, Pistache::Http::ResponseWriter &response) - { - //world anchor uuid - xpcf::uuids::uuid id = xpcf::toUUID(worldAnchorUUID); - switch(m_worldStorage->removeWorldAnchor(id)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, "WorldAnchor removed\n"); - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "WorldAnchor not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - } - - void WorldAnchorsSolARImpl::get_world_anchor_by_id(const std::string &worldAnchorUUID, Pistache::Http::ResponseWriter &response) - { - //initialize the json object that we will send back to the client - auto jsonObjects = nlohmann::json::array(); - - //look for the world anchor with given id - xpcf::uuids::uuid id = xpcf::toUUID(worldAnchorUUID); - SRef storageWorldAnchor; - - switch(m_worldStorage->getWorldAnchor(id, storageWorldAnchor)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - //StorageWorldAnchor found, we convert it into a WorldAnchor - org::openapitools::server::model::WorldAnchor worldAnchor = from_storage(*storageWorldAnchor); - - //add the WorldAnchor to our JSON object - to_json(jsonObjects, worldAnchor); - - //send the WorldAnchor to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "WorldAnchor not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - } - - void WorldAnchorsSolARImpl::get_world_anchors(Pistache::Http::ResponseWriter &response) - { - //initialize the json object that we will send back to the client - auto jsonObjects = nlohmann::json::array(); - - //declaration of all the objects that will be changed at each iteration of the loop - nlohmann::json toAdd; - org::openapitools::server::model::WorldAnchor worldAnchor; - - std::vector> vector; - if(m_worldStorage->getWorldAnchors(vector) != SolAR::FrameworkReturnCode::_SUCCESS) - { - //Exception raised in getWorldAnchor - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong when fetching the world storage"); - } - else - { - //iteration over the content of the world storage - for (const SRef &w : vector){ - //add the current worldAnchor to the JSON object - worldAnchor = from_storage(*w); - to_json(toAdd, worldAnchor); - jsonObjects.push_back(toAdd); - } - - //send the JSON object to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - } - } - - void WorldAnchorsSolARImpl::modify_world_anchor(const model::WorldAnchor &worldAnchor, Pistache::Http::ResponseWriter &response) - { - //convert all the WorldAnchor attributes into StorageWorldAnchor attributes to create one and store it in the world storage - - //creator uuid - xpcf::uuids::uuid creatorId = xpcf::toUUID(worldAnchor.getCreatorUUID()); - - //localCRS - std::vector vector = worldAnchor.getLocalCRS(); - Eigen::Matrix matrix = Eigen::Map>(vector.data()); - SolAR::datastructure::Transform3Df localCRS(matrix); - - //unitsystem - SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldAnchor.getUnit()); - - //size - Eigen::Vector3d size = Eigen::Vector3d(worldAnchor.getWorldAnchorSize().data()); - - //taglist - std::multimap keyvalueTagList; - for (std::pair> tag : worldAnchor.getKeyvalueTags()){ - for(std::string value : tag.second){ - keyvalueTagList.insert({tag.first,value}); - } - } - - //name - std::string name = worldAnchor.getName(); - - //id - xpcf::uuids::uuid id = xpcf::toUUID(worldAnchor.getUUID()); - - //create a world anchor - SRef storageWorldAnchor = xpcf::utils::make_shared(id, creatorId, localCRS, unitSystem, size, keyvalueTagList, name); - - //adding the newly created StorageWorldAnchor to the worldgraph - xpcf::uuids::uuid worldAnchorId; - switch(m_worldStorage->modifyWorldAnchor(worldAnchorId, storageWorldAnchor)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - //initialize the json object that we will send back to the client (the WorldAnchor's id) - std::string worldAnchorIdString = xpcf::uuids::to_string(worldAnchorId); - auto jsonObjects = nlohmann::json::array(); - nlohmann::to_json(jsonObjects, worldAnchorIdString); - - //send the ID to the client - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "WorldAnchor not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - return; - } - - void WorldAnchorsSolARImpl::init() - { - try - { - WorldAnchorsApi::init(); - } - catch (xpcf::Exception e) - { - std::cout << e.what() << std::endl; - } - } - - org::openapitools::server::model::WorldAnchor WorldAnchorsSolARImpl::from_storage(const SolAR::datastructure::StorageWorldAnchor &worldAnchor) - { - //the object to be returned - org::openapitools::server::model::WorldAnchor ret; - - //convert all the StorageWorldAnchor attributes into WorldAnchor attibutes - - //world anchor UUID - std::string id = xpcf::uuids::to_string(worldAnchor.getID()); - ret.setUUID(id); - - //name - ret.setName(worldAnchor.getName()); - - //creator UUID - std::string creatorUid = xpcf::uuids::to_string(worldAnchor.getCreatorID()); - ret.setCreatorUUID(creatorUid); - - //Transform3Df (localCRS) - SolAR::datastructure::Transform3Df transform3d = worldAnchor.getLocalCrs(); - Eigen::Matrix matrix = transform3d.matrix(); - std::vector localCRS; - for (size_t i = 0; i < (size_t) matrix.rows(); i++) - { - for (size_t j = 0; j < (size_t) matrix.cols(); j++) - { - localCRS.push_back(matrix(i, j)); - } - } - ret.setLocalCRS(localCRS); - - //Unit system - org::openapitools::server::model::UnitSystem unit = resolve_unitSystem(worldAnchor.getUnitSystem()); - ret.setUnit(unit); - - //Dimension (scale) - Eigen::Vector3d dimension = worldAnchor.getSize(); - std::vector vector(3); - for(int i = 0; i < 3; i++){ - vector[i] = dimension[0,i]; - } - ret.setWorldAnchorSize(vector); - - //keyvalue taglist (multimap to map>) - std::map> tagList; - auto storageMap = worldAnchor.getTags(); - for (const auto &tag : storageMap){ - if (tagList.count(tag.first) != 0){ - std::vector& vector = tagList.at(tag.first); - vector.push_back(tag.second); - }else { - std::vector vector; - vector.push_back(tag.second); - tagList.insert(std::pair>(tag.first, vector)); - } - } - ret.setKeyvalueTags(tagList); - - return ret; - } -} diff --git a/Solar-Wrapper/src/WorldLinksSolARImpl.cpp b/Solar-Wrapper/src/WorldLinksSolARImpl.cpp deleted file mode 100644 index 5e045bfd013d610ed894f2d679016169cdb2a8b1..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/src/WorldLinksSolARImpl.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "TrackablesSolARImpl.h" -#include "UnitSysConversion.h" -#include "WorldAnchorsSolARImpl.h" -#include "WorldLinksSolARImpl.h" - -namespace xpcf = org::bcom::xpcf; - -namespace org::openapitools::server::implem { - - - WorldLinksSolARImpl::WorldLinksSolARImpl(const std::shared_ptr& rtr, SRef worldStorage) - : WorldLinksApi(rtr) - { - m_worldStorage = worldStorage; - } - - void WorldLinksSolARImpl::add_world_link(const org::openapitools::server::model::WorldLink &worldLink, Pistache::Http::ResponseWriter &response) - { - //convert all the WorldLink attributes into StorageWorldLink attributes to create one and store it in the world storage - - //authorId - xpcf::uuids::uuid authorId = xpcf::toUUID(worldLink.getCreatorUUID()); - - //transform 3d - std::vector vector = worldLink.getTransform(); - Eigen::Matrix matrix = Eigen::Map>(vector.data()); - SolAR::datastructure::Transform3Df transfo(matrix); - - //world element from ID - xpcf::uuids::uuid fromElementId = xpcf::toUUID(worldLink.getUUIDFrom()); - - //world element to ID - xpcf::uuids::uuid toElementId = xpcf::toUUID(worldLink.getUUIDTo()); - - //check if the link connects a single element - if(fromElementId == toElementId) - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Bad_Request, "An element can not be connected to himself\n"); - return; - } - - //world element from type - SolAR::datastructure::ElementKind fromElementType = resolve_element_kind(worldLink.getTypeFrom()); - - //world element to type - SolAR::datastructure::ElementKind toElementType = resolve_element_kind(worldLink.getTypeTo()); - - //adding the link to the storage by calling the world storage method - xpcf::uuids::uuid linkId; - - //unitsystem - SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldLink.getUnit()); - - //taglist - std::multimap keyvalueTagList; - for (std::pair> tag : worldLink.getKeyvalueTags()){ - for(std::string value : tag.second){ - keyvalueTagList.insert({tag.first,value}); - } - } - - //build the worldLink - xpcf::utils::shared_ptr storageWorldLink = xpcf::utils::make_shared(authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); - switch(m_worldStorage->addWorldLink(linkId, storageWorldLink)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - //initialize the json object that we will send back to the client (the WorldAnchor's id) - std::string worldLinkIdString = xpcf::uuids::to_string(linkId); - auto jsonObjects = nlohmann::json::array(); - nlohmann::to_json(jsonObjects, worldLinkIdString); - - //send the ID to the client - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "The connected elements were not found in the world storage\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - } - - void WorldLinksSolARImpl::delete_world_link(const std::string &worldLinkUUID, Pistache::Http::ResponseWriter &response) - { - auto linkId = xpcf::toUUID(worldLinkUUID); - switch(m_worldStorage->removeWorldLink(linkId)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, "WorldLink removed\n"); - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "WorldLink not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - } - - void WorldLinksSolARImpl::get_world_link_by_id(const std::string &worldLinkUUID, Pistache::Http::ResponseWriter &response) - { - //initialize the json object that we will send back to the client - auto jsonObjects = nlohmann::json::array(); - - //look for the world anchor with given id - xpcf::uuids::uuid id = xpcf::toUUID(worldLinkUUID); - SRef storageWorldLink; - - switch(m_worldStorage->getWorldLink(id, storageWorldLink)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - //StorageWorldLink found, we convert it into a WorldLink - org::openapitools::server::model::WorldLink worldLink = from_storage(*storageWorldLink); - - //add the WorldLink to our JSON object - to_json(jsonObjects, worldLink); - - //send the link to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "WorldLink not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - } - - void WorldLinksSolARImpl::get_world_links(Pistache::Http::ResponseWriter &response) - { - //initialize the json object that we will send back to the client - auto jsonObjects = nlohmann::json::array(); - - //declaration of all the objects that will be changed at each iteration of the loop - nlohmann::json toAdd; - org::openapitools::server::model::WorldLink worldLink; - - std::vector> vector; - if(m_worldStorage->getWorldLinks(vector) != SolAR::FrameworkReturnCode::_SUCCESS) - { - //Exception raised in getWorldLinks - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong when fetching the world storage"); - } - else - { - //for all the worldLinks in the worldStorage - for(const SRef &l : vector){ - //add the current world link to the JSON object - worldLink = from_storage(*l); - to_json(toAdd, worldLink); - jsonObjects.push_back(toAdd); - } - - //send the JSON object to the client - response.headers().add(MIME(Application, Json)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - } - } - - void WorldLinksSolARImpl::modify_world_link(const model::WorldLink &worldLink, Pistache::Http::ResponseWriter &response) - { - //convert all the WorldLink attributes into StorageWorldLink attributes to create one and store it in the world storage - - //authorId - xpcf::uuids::uuid authorId = xpcf::toUUID(worldLink.getCreatorUUID()); - - //transform 3d - std::vector vector = worldLink.getTransform(); - Eigen::Matrix matrix = Eigen::Map>(vector.data()); - SolAR::datastructure::Transform3Df transfo(matrix); - - //world element from ID - xpcf::uuids::uuid fromElementId = xpcf::toUUID(worldLink.getUUIDFrom()); - - //world element to ID - xpcf::uuids::uuid toElementId = xpcf::toUUID(worldLink.getUUIDTo()); - - //check if the link connects a single element - if(fromElementId == toElementId) - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Bad_Request, "An element can not be connected to himself\n"); - } - - //world element from type - SolAR::datastructure::ElementKind fromElementType = resolve_element_kind(worldLink.getTypeFrom()); - - //world element to type - SolAR::datastructure::ElementKind toElementType = resolve_element_kind(worldLink.getTypeTo()); - - //unitsystem - SolAR::datastructure::UnitSystem unitSystem = resolve_unitSystem(worldLink.getUnit()); - - //taglist - std::multimap keyvalueTagList; - for (std::pair> tag : worldLink.getKeyvalueTags()){ - for(std::string value : tag.second){ - keyvalueTagList.insert({tag.first,value}); - } - } - - //id - xpcf::uuids::uuid id = xpcf::toUUID(worldLink.getUUID()); - - - //build the worldLink - xpcf::utils::shared_ptr storageWorldLink = xpcf::utils::make_shared(id, authorId, fromElementId, toElementId, fromElementType, toElementType, transfo, unitSystem, keyvalueTagList); - - - //adding the link to the storage by calling the world storage method - xpcf::uuids::uuid linkId; - switch(m_worldStorage->modifyWorldLink(linkId, storageWorldLink)) - { - case SolAR::FrameworkReturnCode::_SUCCESS : - { - //initialize the json object that we will send back to the client (the WorldAnchor's id) - std::string worldLinkIdString = xpcf::uuids::to_string(linkId); - auto jsonObjects = nlohmann::json::array(); - nlohmann::to_json(jsonObjects, worldLinkIdString); - - //send the ID to the client - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Ok, jsonObjects.dump()); - break; - } - - case SolAR::FrameworkReturnCode::_NOT_FOUND : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Not_Found, "Either the WorldLink was not found, or the elements it should connect were not found\n"); - break; - } - - default : - { - response.headers().add(MIME(Text, Plain)); - response.send(Pistache::Http::Code::Internal_Server_Error, "Something went wrong\n"); - } - } - } - - void WorldLinksSolARImpl::init() - { - try - { - WorldLinksApi::init(); - } - catch (xpcf::Exception e) - { - std::cout << e.what() << std::endl; - } - } - - org::openapitools::server::model::WorldLink WorldLinksSolARImpl::from_storage(SolAR::datastructure::StorageWorldLink worldLink) - { - //the object to be returned - org::openapitools::server::model::WorldLink ret; - - //convert all the StorageWorldLink attributes into WorldLink attibutes - - //world link UUID - std::string id = xpcf::uuids::to_string(worldLink.getId()); - ret.setUUID(id); - - //creator UUID - std::string creatorUid = xpcf::uuids::to_string(worldLink.getAuthor()); - ret.setCreatorUUID(creatorUid); - - //element from UUID - std::string elementTo = xpcf::uuids::to_string(worldLink.getUuidFrom()); - ret.setUUIDFrom(elementTo); - - //element to UUID - std::string elementFrom = xpcf::uuids::to_string(worldLink.getUuidTo()); - ret.setUUIDTo(elementFrom); - - //element from Type - model::ObjectType typeFrom = resolve_element_kind(worldLink.getTypeFrom()); - ret.setTypeFrom(typeFrom); - - //element to Type - model::ObjectType typeTo = resolve_element_kind(worldLink.getTypeTo()); - ret.setTypeTo(typeTo); - - //transform - SolAR::datastructure::Transform3Df transform3d = worldLink.getTransform(); - Eigen::Matrix matrix = transform3d.matrix(); - std::vector localCRS; - for (size_t i = 0; i < (size_t) matrix.rows(); i++) - { - for (size_t j = 0; j < (size_t) matrix.cols(); j++) - { - localCRS.push_back(matrix(i, j)); - } - } - ret.setTransform(localCRS); - - //Unit system - org::openapitools::server::model::UnitSystem unit = resolve_unitSystem(worldLink.getUnitSystem()); - ret.setUnit(unit); - - //keyvalue taglist (multimap to map>) - std::map> tagList; - auto storageMap = worldLink.getTags(); - for (const auto &tag : storageMap){ - if (tagList.count(tag.first) != 0){ - std::vector& vector = tagList.at(tag.first); - vector.push_back(tag.second); - }else { - std::vector vector; - vector.push_back(tag.second); - tagList.insert(std::pair>(tag.first, vector)); - } - } - ret.setKeyvalueTags(tagList); - - return ret; - } - - model::ObjectType WorldLinksSolARImpl::resolve_element_kind(SolAR::datastructure::ElementKind kind) - { - model::ObjectType ret; - switch(kind) - { - case SolAR::datastructure::ElementKind::ANCHOR : - ret.setValue(model::ObjectType::eObjectType::WORLDANCHOR); - return ret; - break; - case SolAR::datastructure::ElementKind::TRACKABLE : - ret.setValue(model::ObjectType::eObjectType::TRACKABLE); - return ret; - break; - default : - ret.setValue(model::ObjectType::eObjectType::NOTIDENTIFIED); - return ret; - } - } - - SolAR::datastructure::ElementKind WorldLinksSolARImpl::resolve_element_kind(model::ObjectType kind) - { - switch(kind.getValue()) - { - case model::ObjectType::eObjectType::WORLDANCHOR : - return SolAR::datastructure::ElementKind::ANCHOR; - break; - case model::ObjectType::eObjectType::TRACKABLE : - return SolAR::datastructure::ElementKind::TRACKABLE; - break; - default : - return SolAR::datastructure::ElementKind::INVALID; - } - } -} diff --git a/Solar-Wrapper/src/main.cpp b/Solar-Wrapper/src/main.cpp deleted file mode 100644 index 3abce4cd6293bdf2eccbfc15df50f42f4a24ca51..0000000000000000000000000000000000000000 --- a/Solar-Wrapper/src/main.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright 2022 ETSI - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** -* World Storage API -* API ensuring interoperability between an authoring tool and a World Storage service -* -* The version of the OpenAPI document: 0.0.1 -* -* -* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). -* https://openapi-generator.tech -* Do not edit the class manually. -*/ - -#ifdef __linux__ -#include -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include "TrackablesSolARImpl.h" -#include "WorldAnchorsSolARImpl.h" -#include "WorldLinksSolARImpl.h" -#include "DefaultSolARImpl.h" - -#define PISTACHE_SERVER_THREADS 2 -#define PISTACHE_SERVER_MAX_REQUEST_SIZE 32768 -#define PISTACHE_SERVER_MAX_RESPONSE_SIZE 32768 - - -namespace xpcf = org::bcom::xpcf; - -static Pistache::Http::Endpoint *httpEndpoint; -#ifdef __linux__ -static void sigHandler [[noreturn]] (int sig){ - switch(sig){ - case SIGINT: - case SIGQUIT: - case SIGTERM: - case SIGHUP: - default: - httpEndpoint->shutdown(); - break; - } - exit(0); -} - -static void setUpUnixSignals(std::vector quitSignals) { - sigset_t blocking_mask; - sigemptyset(&blocking_mask); - for (auto sig : quitSignals) - sigaddset(&blocking_mask, sig); - - struct sigaction sa; - sa.sa_handler = sigHandler; - sa.sa_mask = blocking_mask; - sa.sa_flags = 0; - - for (auto sig : quitSignals) - sigaction(sig, &sa, nullptr); -} -#endif - -using namespace org::openapitools::server::implem; -using namespace SolAR; - -int main() { - - #ifdef __linux__ - std::vector sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP}; - setUpUnixSignals(sigs); - #endif - - try { - - #if NDEBUG - boost::log::core::get()->set_logging_enabled(false); - #endif - - //init the logger - LOG_ADD_LOG_TO_CONSOLE(); - LOG_INFO("program is running"); - - /* instantiate component manager*/ - /* this is needed in dynamic mode */ - SRef xpcfComponentManager = xpcf::getComponentManagerInstance(); - - if(xpcfComponentManager->load("SolARSample_World_Storage_conf.xml")!=org::bcom::xpcf::_SUCCESS) - { - LOG_ERROR("Failed to load the configuration file SolARSample_World_Storage_conf.xml"); - return -1; - } - auto worldStorage = xpcfComponentManager->resolve(); - - Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(8080)); - - httpEndpoint = new Pistache::Http::Endpoint((addr)); - auto router = std::make_shared(); - - auto opts = Pistache::Http::Endpoint::options().threads(PISTACHE_SERVER_THREADS); - opts.flags(Pistache::Tcp::Options::ReuseAddr); - opts.maxRequestSize(PISTACHE_SERVER_MAX_REQUEST_SIZE); - opts.maxResponseSize(PISTACHE_SERVER_MAX_RESPONSE_SIZE); - httpEndpoint->init(opts); - - - DefaultSolARImpl DefaultApiserver(router); - DefaultApiserver.init(); - TrackablesSolARImpl TrackablesApiserver(router, worldStorage); - TrackablesApiserver.init(); - WorldAnchorsSolARImpl WorldAnchorsApiserver(router, worldStorage); - WorldAnchorsApiserver.init(); - WorldLinksSolARImpl WorldLinksApiserver(router, worldStorage); - WorldLinksApiserver.init(); - - httpEndpoint->setHandler(router->handler()); - httpEndpoint->serve(); - - httpEndpoint->shutdown(); - - } - - catch (xpcf::Exception e) - { - LOG_ERROR("Exception raised : \n {}", e.what()) - return -1; - } - return 0; - -} diff --git a/Solar-pistache-server-localbuild.pro b/Solar-pistache-server-localbuild.pro deleted file mode 100644 index fb39657d5f66ba08741a56a23d7f886e04c6105e..0000000000000000000000000000000000000000 --- a/Solar-pistache-server-localbuild.pro +++ /dev/null @@ -1,62 +0,0 @@ -## global defintions : target lib name, version -TARGET = SolARService_WorldStorage -VERSION = 0.11.0 - -QMAKE_PROJECT_DEPTH = 0 - -## remove Qt dependencies -QT -= core gui -CONFIG -= qt -CONFIG += c++1z -CONFIG += console -CONFIG += verbose - -DEFINES += MYVERSION=$${VERSION} - -include(findremakenrules.pri) - -LIBS += -L"/usr/local" -l"PistacheGen" - -# Default rules for deployment. -qnx: target.path = $${PWD}/bin/Debug# /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - - -unix: CONFIG += link_pkgconfig -unix: PKGCONFIG += libpistache - -DEPENDENCIESCONFIG = sharedlib install_recurse - -#NOTE : CONFIG as staticlib or sharedlib, DEPENDENCIESCONFIG as staticlib or sharedlib, QMAKE_TARGET.arch and PROJECTDEPLOYDIR MUST BE DEFINED BEFORE templatelibconfig.pri inclusion -include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/templateappconfig.pri))) # Shell_quote & shell_path required for visual on windows - -INCLUDEPATH += \ - Solar-Wrapper/ \ - Solar-Wrapper/interfaces/ - -HEADERS += \ - Solar-Wrapper/interfaces/DefaultSolARImpl.h \ - Solar-Wrapper/interfaces/TrackablesSolARImpl.h \ - Solar-Wrapper/interfaces/UnitSysConversion.h \ - Solar-Wrapper/interfaces/WorldAnchorsSolARImpl.h \ - Solar-Wrapper/interfaces/WorldLinksSolARImpl.h - -SOURCES += \ - Solar-Wrapper/src/DefaultSolARImpl.cpp \ - Solar-Wrapper/src/TrackablesSolARImpl.cpp \ - Solar-Wrapper/src/WorldAnchorsSolARImpl.cpp \ - Solar-Wrapper/src/WorldLinksSolARImpl.cpp \ - Solar-Wrapper/src/main.cpp - -DISTFILES += \ - build/SolARSample_World_Storage_conf.xml \ - packagedependencies.txt - -config_files.path = target.path -config_files.files= $$files($${PWD}/SolARSample_World_Storage_conf.xml) -INSTALLS += config_files - - -#NOTE : Must be placed at the end of the .pro -include ($$shell_quote($$shell_path($${QMAKE_REMAKEN_RULES_ROOT}/remaken_install_target.pri)))) # Shell_quote & shell_path required for visual on windows diff --git a/bundle_system_install.sh b/bundle_system_install.sh deleted file mode 100755 index a9bf588e2f88457fdf73ac7361ef1d596fb81453..0000000000000000000000000000000000000000 --- a/bundle_system_install.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e77ee76ca26a16736757c4cfc9dcf74ec0614ad6..0000000000000000000000000000000000000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Solar-pistache-server-localbuild", - "lockfileVersion": 2, - "requires": true, - "packages": {} -} diff --git a/packagedependencies.txt b/packagedependencies.txt deleted file mode 100644 index 62ba3137b51b9fc75d74c0ddfe51a48d5080a31b..0000000000000000000000000000000000000000 --- a/packagedependencies.txt +++ /dev/null @@ -1,2 +0,0 @@ -SolARFramework|0.11.0|SolARFramework|SolARBuild@github|https://github.com/SolarFramework/SolarFramework/releases/download -xpcf|2.5.0|xpcf|github|https://github.com/ diff --git a/target.path/SolARSample_World_Storage_conf.xml b/target.path/SolARSample_World_Storage_conf.xml deleted file mode 100644 index 802e84a6e8220023824cc361ad018d6ecd2d1005..0000000000000000000000000000000000000000 --- a/target.path/SolARSample_World_Storage_conf.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - -