Install SolAR before creating your app

Refer to Install section.

Install the XPCF Wizards.

Create an application project

QT Creator

  • Open QTCreator and create a new project (in File menu).

App wizard QT
  • Then, set the name of your application (e.g. MySolARApp) that will use a SolAR pipeline, and its location.

App wizard QT
  • The next step let you configure project details relative to build options. Select Use QTVS if you intend to use Visual Studio Qt extension.

App wizard QT
  • Give the location of the installed version of XPCF to use for this application

App wizard QT
  • Next, define your build system with qmake. For the next step, choose your development kits. We recommend to use MSVC 2017 64bit on Windows or Clang on Linux.

App wizard QT
  • Finally, click on Finish on the summary panel to generate the files and complete the project setup.

App wizard QT

Your project is now created and the result is a .pro file like following:

MySolARApp.pro
## remove Qt dependencies
QT -= core gui
TARGET = MySolARApp  (1)
VERSION=x.x.x (2)

CONFIG += c++1z
CONFIG -= qt
CONFIG += console

DEFINES += MYVERSION=$${VERSION}

QMAKE_PROJECT_DEPTH = 0

include(findremakenrules.pri)

CONFIG(debug,debug|release) {
    DEFINES += _DEBUG=1
    DEFINES += DEBUG=1
}

CONFIG(release,debug|release) {
    DEFINES += _NDEBUG=1
    DEFINES += NDEBUG=1
}

DEPENDENCIESCONFIG = sharedlib install_recurse

win32:CONFIG -= static
win32:CONFIG += shared

## 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
  (3)

DEFINES += BOOST_ALL_DYN_LINK
DEFINES += BOOST_AUTO_LINK_NOMANGLE
DEFINES += BOOST_LOG_DYN_LINK

SOURCES += \
    main.cpp

unix {
    LIBS += -ldl
    QMAKE_CXXFLAGS += -DBOOST_LOG_DYN_LINK
}

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
    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

}

android {
    ANDROID_ABIS="arm64-v8a"
}

DISTFILES += \
    MySolARApp_conf.xml \
    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

Now, just update the .pro file:

1 set the TARGET with the name of your application,
2 set the version number of your application,
3 check if the builddefs folder used to define the building pipeline is well referenced

Finally, click on Projects in the left menu of QTcreator, click on Run, set your working directory to the root directory of your project, and check _Add build library search path to PATH if not already done.

Visual Studio

You can also simply create your application with Visual Studio by using the .pro file (see above for more details how to configure the .pro file).

Microsoft Visual Studio provides a Qt Visual Studio Tools. This enables developers to import QT project files (.pro) into Visual Studio.

Install QT Visual Studio Tools:

  • In Visual Studio, select Tools > Extensions and Updates > Online to install and update QT Visual Studio Tools.

Import the .pro. file into Visual Studio:

  • Select Qt VS Tools > Open Qt Project File (.pro) and choose your .pro file.

Right now, your project is configured.

Select your dependencies

Copy in your project folder the packagedependencies.txt file of the pipeline you want to use, and add a dependency to the pipeline:

packagedependencies.txt
SolARFramework|0.10.0|SolARFramework|SolARBuild@github|https://github.com/SolarFramework/SolarFramework/releases/download
(1)
OtherDependency|version x.x.x|OtherDependency|LocalFolder@WhereDistant|urlToIt
1 Add the dependency to the pipeline you want to use, with its version number.

More documentation here : Remaken is a dependencies manager. https://github.com/b-com-software-basis/remaken It manages your third parties and it creates a QMAKE_REMAKEN_RULES_ROOT env. variable.

Configure your pipeline

Copy the configuration file provided with your pipeline in your project folder:

MySolARApp_conf.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<xpcf-registry autoAlias="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<module uuid="94b21be9-703b-4a00-86a9-0db1bf70ef89" name="MyPipelineModule" path="$XPCF_MODULE_ROOT/SolARBuild/MyPipeline/x.x.x/lib/x86_64/shared" description="MyPipelineModule">
  <component uuid="855c83b7-f4ec-48ab-8e89-56018ea9e169" name="MyPipeline" description="MyPipeline">
    <interface uuid="125f2007-1bf9-421d-9367-fbdc1210d006" name="IComponentIntrospect" description="IComponentIntrospect"/>
    <interface uuid="b5a6225e-6a91-4050-b298-886f4c17d9d2" name="IPoseEstimationPipeline" description="The interface to define a video see-throuh pipeline" />
  </component>
</module>
<module uuid="15e1990b-86b2-445c-8194-0cbe80ede970" name="SolARModuleOpenCV" description="SolARModuleOpenCV" path="$XPCF_MODULE_ROOT/SolARBuild/SolARModuleOpenCV/0.10.0/lib/x86_64/shared">
  <component uuid="5B7396F4-A804-4F3C-A0EB-FB1D56042BB4" name="SolARCameraOpencv" description="SolARCameraOpencv">
    <interface uuid="125f2007-1bf9-421d-9367-fbdc1210d006" name="IComponentIntrospect" description="IComponentIntrospect"/>
    <interface uuid="5DDC7DF0-8377-437F-9C81-3643F7676A5B" name="ICamera" description="ICamera"/>
  </component>
</module>
<module uuid="28b89d39-41bd-451d-b19e-d25a3d7c5797" name="SolARModuleTools"  description="SolARModuleTools"  path="$XPCF_MODULE_ROOT/SolARBuild/SolARModuleTools/0.10.0/lib/x86_64/shared">
  <component uuid="85db2f25-4f1c-4e06-9011-e020284bfc4f" name="SolARBasicSink" description="A Sink component for a synchronized pose and image pair">
    <interface uuid="125f2007-1bf9-421d-9367-fbdc1210d006" name="IComponentIntrospect" description="IComponentIntrospect" />
    <interface uuid="c0d9fee4-d7d7-4866-a6cd-3bacac23316a" name="ISinkPoseImage" description="An interface allowing to store a synchronized pose and image from the pipeline to make it available to a third party application" />
  </component>
  <component uuid="1e43cda9-7850-4a8a-a32b-f3f31ea94902" name="SolARBasicSource" description="A source component for feeding the pipeline with external images">
    <interface uuid="125f2007-1bf9-421d-9367-fbdc1210d006" name="IComponentIntrospect" description="IComponentIntrospect" />
    <interface uuid="06e2fc5d-39da-4486-b2a6-1d8bd788fa13" name="ISourceImage" description="An interface allowing to store an image from extern source to make it available to the pipeline" />
  </component>
</module>

<properties>
  <configuration component="SolARCameraOpencv">
    <property name="calibrationFile" type="string" value="camera_calibration.yml"/>
    <property name="deviceID" type="uint" value="0"/>
  </configuration>
</properties>

</xpcf-registry>

main.cpp

Copy the following code in your main.cpp file for testing your SolAR pipeline:

main.cpp
/**
 * information concerning the copyright and license of your SolAR application
 */

#include <boost/log/core.hpp>
#include "core/Log.h"
#include "xpcf/xpcf.h"


// ADD COMPONENTS HEADERS HERE, e.g #include "SolarComponent.h"
#include "api/pipeline/IPoseEstimationPipeline.h"
#include "api/display/IImageViewer.h"
#include "api/display/I3DOverlay.h"
#include "datastructure/CameraDefinitions.h"

namespace xpcf  = org::bcom::xpcf;

using namespace SolAR;
using namespace SolAR::datastructure;
using namespace SolAR::api;

int main(){

#if NDEBUG
    boost::log::core::get()->set_logging_enabled(false);
#endif

    try {
        LOG_ADD_LOG_TO_CONSOLE();
        SRef<xpcf::IComponentManager> componentMgr = xpcf::getComponentManagerInstance();
        componentMgr->load("MySolARApp_conf.xml");
        auto pipeline = componentMgr->resolve<pipeline::IPoseEstimationPipeline>();

        (1)
        if (pipeline->init() == FrameworkReturnCode::_SUCCESS)
        {
            auto imageViewerResult = componentMgr->resolve<display::IImageViewer>();
            auto overlay3DComponent = componentMgr->resolve<display::I3DOverlay>();

            // Set camera parameters
            CameraParameters camParam = pipeline->getCameraParameters();
            overlay3DComponent->setCameraParameters(camParam.intrinsic, camParam.distortion);

            unsigned char* r_imageData=new unsigned char[camParam.resolution.width * camParam.resolution.height * 3];
            SRef<Image> camImage=xpcf::utils::make_shared<Image>(r_imageData,camParam.resolution.width,camParam.resolution.height, Image::LAYOUT_BGR, Image::INTERLEAVED, Image::TYPE_8U);

            Transform3Df s_pose;

            if (pipeline->start(camImage->data()) == FrameworkReturnCode::_SUCCESS)
            {
                while (true)
                {
                    Transform3Df pose;

                    sink::SinkReturnCode returnCode = pipeline->update(pose);

                    if (returnCode == sink::SinkReturnCode::_NOTHING)
                        continue;

                    if ((returnCode == sink::SinkReturnCode::_NEW_POSE) || (returnCode == sink::SinkReturnCode::_NEW_POSE_AND_IMAGE))
                    {
                        for(int i=0;i<3;i++)
                            for(int j=0;j<3;j++)
                                s_pose(i,j)=pose(i,j);
                        for(int i=0;i<3;i++)
                                s_pose(i,3)=pose(i,3);
                        for(int j=0;j<3;j++)
                            s_pose(3,j)=0;
                        s_pose(3,3)=1;
                        overlay3DComponent->draw(s_pose, camImage);
                    }

                    if (imageViewerResult->display(camImage) == SolAR::FrameworkReturnCode::_STOP){
                        pipeline->stop();
                        break;
                    }
                }
            }
            delete[] r_imageData;
        }
    }
    catch (xpcf::Exception e)
    {
        LOG_ERROR ("The following exception has been caught : {}", e.what());
        return -1;
    }
}
1 when you will load your pipeline, fill in the path to its configuration file and its UUID (the UUID of the component representing the pipeline available in the configuration file).
Don’t forget to re-run qmake before building your application for QT Creator and re-import .pro file for Visual Studio.

Build and run your application.