From 57b3e0965b08e6ac2290cac7ce3edec1b32435fa Mon Sep 17 00:00:00 2001
From: Sylvain Calinon <sylvain.calinon@idiap.ch>
Date: Fri, 7 Jul 2017 11:51:05 +0200
Subject: [PATCH] List of examples added

---
 CMakeLists.txt       |  18 +-
 README.md            | 167 +++++++++++++--
 src/demo_proMP01.cpp | 468 -------------------------------------------
 3 files changed, 147 insertions(+), 506 deletions(-)
 delete mode 100644 src/demo_proMP01.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f305553..b995ef4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -172,22 +172,6 @@ target_link_libraries(demo_LQR_infHor
 	${PBD_LIB}
 )
 
-add_executable(demo_proMP01
-	${PROJECT_SOURCE_DIR}/src/imgui_impl_glfw_gl3.cpp
-	${PROJECT_SOURCE_DIR}/src/gfx_ui.cpp
-	${PROJECT_SOURCE_DIR}/src/gfx3.cpp
-	${PROJECT_SOURCE_DIR}/src/imgui.cpp
-	${PROJECT_SOURCE_DIR}/src/imgui_draw.cpp
-	${PROJECT_SOURCE_DIR}/src/demo_proMP01.cpp
-)
-target_link_libraries(demo_proMP01
-	${OPENGL_LIBRARIES}
-	${GLEW_LIBRARIES}
-	${GLFW_LIB}
-	${ARMADILLO_LIBRARIES}
-	${PBD_LIB}
-)
-
 add_executable(demo_Riemannian_cov_interp02
 	${PROJECT_SOURCE_DIR}/src/imgui.cpp
 	${PROJECT_SOURCE_DIR}/src/imgui_impl_glfw.cpp
@@ -342,4 +326,4 @@ target_link_libraries(demo_teleop
 	${ARMADILLO_LIBRARIES}
 	${GLFW_LIB}
 	${PBD_LIB}
-)
\ No newline at end of file
+)
diff --git a/README.md b/README.md
index 9af449a..e3c4ade 100644
--- a/README.md
+++ b/README.md
@@ -51,36 +51,161 @@ make
 **Note:** The `-DBUILD_SHARED_LIBS` is necessary otherwise cmake will create a
 static library.
 
-### Execution
 
-This project will build a number of executables, as listed below:
+### References
 
-- *demo_dptpgmm*: online tp-gmm learning and lqr-based trajectory generation. 
+Did you find PbDLib useful for your research? Please acknowledge the authors in any academic publications that used parts of these codes.
+<br><br>
 
-- *demo_glsl*: Minimalist example with glsl display
+[1] Tutorial (GMM, TP-GMM, MFA, MPPCA, GMR, LWR, GPR, MPC, LQR, trajGMM):
+```
+@article{Calinon16JIST,
+	author="Calinon, S.",
+	title="A Tutorial on Task-Parameterized Movement Learning and Retrieval",
+	journal="Intelligent Service Robotics",
+	publisher="Springer Berlin Heidelberg",
+	year="2016",
+	volume="9",
+	number="1",
+	pages="1--29",
+	doi="10.1007/s11370-015-0187-9",
+}
+```
 
-- *demo_LQR_infHor*: Minimalist example of discrete infinite horizon linear
-                     quadratic regulation.
+[2] HMM, HSMM:
+```
+@article{Rozo16Frontiers,
+	author="Rozo, L. and Silv\'erio, J. and Calinon, S. and Caldwell, D. G.",
+	title="Learning Controllers for Reactive and Proactive Behaviors in Human-Robot Collaboration",
+	journal="Frontiers in Robotics and {AI}",
+	year="2016",
+	month="June",
+	volume="3",
+	number="30",
+	pages="1--11",
+	doi="10.3389/frobt.2016.00030"
+}
+```
 
-- *demo_online_gmm*: online gmm learning and lqr-based trajectory generation.
+[3] Riemannian manifolds (S2,S3):
+```
+@article{Zeestraten17RAL,
+	author="Zeestraten, M. J. A. and Havoutis, I. and Silv\'erio, J. and Calinon, S. and Caldwell, D. G.",
+	title="An Approach for Imitation Learning on {R}iemannian Manifolds",
+	journal="{IEEE} Robotics and Automation Letters ({RA-L})",
+	year="2017",
+	month="June",
+	volume="2",
+	number="3",
+	pages="1240--1247"
+	doi="10.1109/LRA.2017.2657001",
+}
+```
 
-- *demo_online_hsmm*: online hsmm learning and sampling with lqr-based trajectory
-                      generation.
+[4] Riemannian manifolds (S+):
+```
+@inproceedings{Jaquier17IROS,
+	author="Jaquier, N. and Calinon, S.", 
+	title="Gaussian Mixture Regression on Symmetric Positive Definite Matrices Manifolds: Application to Wrist Motion Estimation with {sEMG}",
+	booktitle="Proc. {IEEE/RSJ} Intl Conf. on Intelligent Robots and Systems ({IROS})",
+	year="2017",
+	month="September",
+	address="Vancouver, Canada",
+	pages=""
+}
+```
 
-- *demo_proMP01*: Conditioning on trajectory distributions with ProMP
+[5] Semi-tied GMM:
+```
+@article{Tanwani16RAL,
+	author="Tanwani, A. K. and Calinon, S.",
+	title="Learning Robot Manipulation Tasks with Task-Parameterized Semi-Tied Hidden Semi-{M}arkov Model",
+	journal="{IEEE} Robotics and Automation Letters ({RA-L})",
+	year="2016",
+	month="January",
+	volume="1",
+	number="1",
+	pages="235--242",
+	doi="10.1109/LRA.2016.2517825"
+}
+```
 
-- *demo_Riemannian_cov_interp02*: Covariance interpolation on Riemannian manifold
-                                  from a GMM with augmented covariances.
+[6] DP-means:
+```
+@article{Bruno17AURO,
+	author="Bruno, D. and Calinon, S. and Caldwell, D. G.",
+	title="Learning Autonomous Behaviours for the Body of a Flexible Surgical Robot",
+	journal="Autonomous Robots",
+	year="2017",
+	month="February",
+	volume="41",
+	number="2",
+	pages="333--347",
+	doi="10.1007/s10514-016-9544-6"
+}
+```
 
-- *demo_Riemannian_sphere_infHorLQR*: Linear quadratic regulation on a sphere by
-                                      relying on Riemannian manifold and
-                                      infinite-horizon LQR.
+[7] Shared control, adaptive teleoperation:
+```
+@inproceedings{Havoutis17ICRA,
+	author="Havoutis, I. and Calinon, S.",
+	title="Supervisory teleoperation with online learning and optimal control",
+	booktitle=ICRA,
+	year="2017",
+	month="May-June",
+	address="Singapore",
+	pages="1534--1540"
+}
+```
 
-- *demo_teleop*: Example of online learning of tp-hsmm model and teleoperator-like
-                 usage example.
+[8] Calligraphy, graffiti, handwriting movement generation:
+```
+@inproceedings{Berio17GI,
+	author="Berio, D. and Calinon, S. and Fol Leymarie, F.",
+	title="Generating Calligraphic Trajectories with Model Predictive Control",
+	booktitle="Proc. 43rd Conf. on Graphics Interface",
+	year="2017",
+	month="May",
+	address="Edmonton, AL, Canada",
+	pages=""
+}
+```
+
+[9] Adaptive assistance:
+```
+@article{Pignat17RAS,
+	author="Pignat, E. and Calinon, S.",
+	title="Learning adaptive dressing assistance from human demonstration",
+	journal="Robotics and Autonomous Systems",
+	year="2017",
+	month="July",
+	volume="93",
+	number="",
+	pages="61--75",
+	doi="10.1016/j.robot.2017.03.017",
+}
+```
 
-- *demo_tp_multiLqr*: online tp-hsmm and tp-gmm with lqr-based trajectory generation
-                      and multiframe-lqr trajectory generation.
+### List of examples
+
+This project will build a number of executables, as listed in the table below.
+
+| Filename | ref. | Description |
+|----------|------|-------------|
+| demo_dptpgmm | [9] | Online tp-gmm learning and lqr-based trajectory generation |
+| demo_glsl | [8] | Rendering example with glsl display |
+| demo_glsl_gfx | [8] | Rendering example with glsl display (using glfx) |
+| demo_LQR_infHor | [1] | Discrete infinite horizon linear quadratic regulation |
+| demo_MPC_batch_01 | [1,8] | Model predictive control (MPC) with batch linear quadratic tracking (LQT) formulation |
+| demo_MPC_iterative_01 | [1,8] | Model predictive control (MPC) with iterative linear quadratic tracking (LQT) formulation |
+| demo_MPC_semitied_01 | [5,8] | MPC with semi-tied covariances |
+| demo_MPC_velocity_01 | [1,8] | MPC with an objective including velocity tracking |
+| demo_online_gmm | [6] | Online GMM learning and LQR-based trajectory generation |
+| demo_online_hsmm | [2,7] | Online HSMM learning and sampling with LQR-based trajectory generation |
+| demo_Riemannian_cov_interp02 | [4] | Covariance interpolation on Riemannian manifold from a GMM with augmented covariances |
+| demo_Riemannian_quat_infHorLQR | [3] | Linear quadratic regulation on hypersphere (orientation as unit quaternions) by relying on Riemannian manifold and infinite-horizon LQR |
+| demo_Riemannian_sphere_infHorLQR | [3] | Linear quadratic regulation on a sphere by relying on Riemannian manifold and infinite-horizon LQR |
+| demo_teleop | [7] | Online learning of tp-hsmm model and teleoperator-like usage example |
+| demo_tp_multiLqr | [7] | Online tp-hsmm and tp-gmm with lqr-based trajectory generation and multiframe-lqr trajectory generation |
+| demo_tp_trajMpc | [7] | Online tp-hsmm learning and trajMPC-based trajectory generation when communication is cut |
 
-- *demo_tp_trajMpc*: online tp-hsmm learning and trajMPC-based trajectory generation
-                     when communication is cut.
diff --git a/src/demo_proMP01.cpp b/src/demo_proMP01.cpp
deleted file mode 100644
index 55c57a3..0000000
--- a/src/demo_proMP01.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * demo_proMP01.cpp
- *
- * Conditioning on trajectory distributions with ProMP
- *
- * @incollection{Paraschos13,
- *   title = {Probabilistic Movement Primitives},
- *   author = {Paraschos, A. and Daniel, C. and Peters, J. and Neumann, G.},
- *   booktitle = NIPS,
- *   pages = {2616--2624},
- *   year = {2013},
- *   publisher = {Curran Associates, Inc.}
- * }
- * @inproceedings{Rueckert15,
- *   author = "Rueckert, E. and  Mundo, J. and  Paraschos, A. and  Peters, J. and  Neumann, G.",
- *   title = "Extracting Low-Dimensional Control Variables for Movement Primitives",
- *   booktitle =	ICRA,
- *   year = "2015",
- *   pages = "1511--1518",
- *   address = "Seattle, WA, USA"
- * }
- *
- * Authors: Sylvain Calinon, Philip Abbet
- */
-
-
-#include <stdio.h>
-#include <armadillo>
-#include <pbdlib/demonstration.h>
-#include <pbdlib/mvn.h>
-
-#include <gfx3.h>
-#include <gfx_ui.h>
-#include <GLFW/glfw3.h>
-#include <imgui.h>
-#include <imgui_impl_glfw_gl3.h>
-
-
-using namespace pbdlib;
-
-
-/*********************************** TYPES ***********************************/
-
-struct parameters_t {
-    int   nb_states;    // Number of components in the GMM
-    int   nb_var;       // Dimension of position data (here: x1, x2)
-    int   nb_data;      // Number of datapoints in a trajectory
-    float dt;           // Time step (without rescaling, large values such
-                        // as 1 has the advantage of creating clusers based
-                        // on position information)
-};
-
-
-/******************************** CONSTANTS **********************************/
-
-const arma::mat COLORS({
-    { 0.00000, 0.00000, 1.00000},
-    { 0.00000, 0.50000, 0.00000},
-    { 1.00000, 0.00000, 0.00000},
-    { 0.00000, 0.75000, 0.75000},
-    { 0.75000, 0.00000, 0.75000},
-    { 0.75000, 0.75000, 0.00000},
-    { 0.25000, 0.25000, 0.25000},
-    { 0.00000, 0.00000, 1.00000},
-    { 0.00000, 0.50000, 0.00000},
-    { 1.00000, 0.00000, 0.00000},
-});
-
-
-/****************************** HELPER FUNCTIONS *****************************/
-
-static void error_callback(int error, const char* description) {
-    fprintf(stderr, "Error %d: %s\n", error, description);
-}
-
-//-----------------------------------------------
-
-// Create a demonstration (with a length of 'nb_samples') from a trajectory
-// (of any length)
-Demonstration sample_trajectory(const std::vector<arma::vec>& trajectory, int nb_samples) {
-
-    // Resampling of the trajectory
-    arma::vec x(trajectory.size());
-    arma::vec y(trajectory.size());
-    arma::vec x2(trajectory.size());
-    arma::vec y2(trajectory.size());
-
-    for (size_t i = 0; i < trajectory.size(); ++i) {
-        x(i) = trajectory[i](0);
-        y(i) = trajectory[i](1);
-    }
-
-    arma::vec from_indices = arma::linspace<arma::vec>(0, trajectory.size() - 1, trajectory.size());
-    arma::vec to_indices = arma::linspace<arma::vec>(0, trajectory.size() - 1, nb_samples);
-
-    interp1(from_indices, x, to_indices, x2, "*linear");
-    interp1(from_indices, y, to_indices, y2, "*linear");
-
-    // Create the demonstration
-    Demonstration demo = Demonstration(2, nb_samples);
-    mat& datapoints = demo.getDatapoints().getData();
-    for (int i = 0; i < nb_samples; ++i) {
-        datapoints(0, i) = x2[i];
-        datapoints(1, i) = y2[i];
-    }
-
-    return demo;
-}
-
-
-/********************************* FUNCTIONS *********************************/
-
-// The actual computation
-//
-// Inputs: demos, parameters
-// Outputs: mu_mat, mu2_mat, H
-void process(std::vector<Demonstration>& demos, const parameters_t& parameters,
-             arma::mat &mu_mat, arma::mat &mu2_mat, arma::mat &H) {
-
-    // Create basis functions (GMM with components equally split in time)
-    arma::vec timesteps = arma::linspace<arma::vec>(
-        0, parameters.nb_data - 1, parameters.nb_data
-    ) * parameters.dt;
-
-    arma::vec mu = arma::linspace<arma::vec>(
-        timesteps(0), timesteps(timesteps.n_rows - 1), parameters.nb_states
-    );
-
-    arma::vec sigma = arma::ones<arma::vec>(parameters.nb_states) * 0.01;
-
-    // Compute basis functions activation
-    H = arma::mat(parameters.nb_states, parameters.nb_data);
-
-    for (unsigned int i = 0; i < parameters.nb_states; ++i) {
-        arma::colvec mu_({ mu(i) });
-        arma::mat sigma_({ sigma(i) });
-
-        GaussianDistribution gauss(mu_, sigma_);
-
-        H.row(i) = gauss.getPDFValue(timesteps.t()).t();
-    }
-
-    H = H / repmat(sum(H, 0), parameters.nb_states, 1);
-
-
-    //_____ ProMP __________
-
-    arma::mat psi(parameters.nb_var * parameters.nb_data,
-                  parameters.nb_var * parameters.nb_states);
-
-    for (unsigned int i = 0; i < parameters.nb_data; ++i) {
-        psi.rows(i * parameters.nb_var, (i + 1) * parameters.nb_var - 1) =
-            arma::kron(H.col(i).t(), arma::eye(parameters.nb_var, parameters.nb_var));
-    }
-
-    arma::mat w(parameters.nb_var * parameters.nb_states, demos.size());
-    for (size_t i = 0; i < demos.size(); ++i) {
-        w.col(i) = pinv(psi) * (arma::mat) arma::vectorise(demos[i].getDatapoints().getData());
-    }
-
-    // Distribution in parameter space
-    arma::mat mu_w = arma::mean(w, 1);
-
-    //-- First regularization term
-    arma::mat sigma_w = arma::eye(parameters.nb_var * parameters.nb_states,
-                                  parameters.nb_var * parameters.nb_states);
-
-    if (w.n_cols == 1) {
-        sigma_w += arma::rowvec(arma::cov(w.t()))[0];
-    }
-    else {
-        sigma_w += arma::cov(w.t());
-    }
-
-    // Trajectory distribution
-    mu = psi * mu_w;
-
-    arma::mat sigma2 = psi * sigma_w * psi.t() +    // Second regularization term
-                       0.01 * arma::eye(parameters.nb_var * parameters.nb_data,
-                                        parameters.nb_var * parameters.nb_data);
-
-
-    //_____ Conditioning on trajectory distribution __________
-    // (reconstruction from partial data)
-
-    arma::uvec in_out = arma::linspace<arma::uvec>(
-        0, parameters.nb_data * parameters.nb_var - 1, parameters.nb_data * parameters.nb_var
-    );
-
-    arma::uvec in(2 * parameters.nb_var);
-
-    in.head(parameters.nb_var) = in_out.head(parameters.nb_var);
-    in.tail(parameters.nb_var) = in_out.tail(parameters.nb_var);
-
-    arma::uvec out = in_out.subvec(parameters.nb_var, in_out.n_elem - parameters.nb_var - 1);
-
-    // Input data
-    arma::vec mu_in = arma::reshape(
-        demos[0].getDatapoints().getData().cols(arma::uvec({0, (unsigned) parameters.nb_data - 1})) +
-        arma::repmat((arma::randu(parameters.nb_var, 1) - 0.5) * 10.0, 1, 2),
-        parameters.nb_var * 2, 1
-    );
-
-    // Gaussian conditioning with trajectory distribution
-    arma::vec mu2(in_out.n_elem, fill::zeros);
-
-    mu2.rows(in) = mu_in;
-
-    arma::mat A = sigma_w * psi.rows(in).t();                   // Used to simplify the
-    arma::mat B = psi.rows(in) * sigma_w * psi.rows(in).t();    // following operation
-
-    arma::mat mu_w_tmp = mu_w +
-                        (arma::inv(B.t()) * A.t()).t() *        // == A / B (not
-                        (mu2.rows(in) - psi.rows(in) * mu_w);   // supported by armadillo)
-
-    mu2.rows(out) = psi.rows(out) * mu_w_tmp;
-
-
-    //_____ Results __________
-
-    mu_mat = arma::conv_to<arma::mat>::from(mu);
-    mu_mat.reshape(parameters.nb_var, parameters.nb_data);
-
-    mu2_mat = arma::conv_to<arma::mat>::from(mu2);
-    mu2_mat.reshape(parameters.nb_var, parameters.nb_data);
-}
-
-//-----------------------------------------------
-
-int main(int argc, char **argv) {
-    arma::arma_rng::set_seed_random();
-
-    // Parameters
-    parameters_t parameters;
-    parameters.nb_states = 6;
-    parameters.nb_var    = 2;
-    parameters.dt        = 0.01;
-    parameters.nb_data   = 100;
-
-
-    // Initialise GLFW
-    glfwSetErrorCallback(error_callback);
-
-    if (!glfwInit())
-        return -1;
-
-    glfwWindowHint(GLFW_SAMPLES, 4);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
-    // Open a window and create its OpenGL context
-    GLFWwindow* window = glfwCreateWindow(
-        800, 800, "Demo Conditioning on trajectory distributions", NULL, NULL
-    );
-
-    glfwMakeContextCurrent(window);
-
-    // Take 4k screens into account (framebuffer size != window size)
-    int win_width = ImGui::GetIO().DisplaySize.x;
-    int win_height = ImGui::GetIO().DisplaySize.y;
-
-    int fb_width, fb_height;
-    glfwGetFramebufferSize(window, &fb_width, &fb_height);
-
-    // Setup GLSL
-    gfx3::init();
-    glEnable(GL_DEPTH_TEST);
-    glEnable(GL_CULL_FACE);
-    glEnable(GL_LINE_SMOOTH);
-    glDepthFunc(GL_LESS);
-
-    // Setup ImGui
-    ImGui_ImplGlfwGL3_Init(window, true);
-
-    // Creation of the Vertex Array Object (VAO)
-    GLuint vertexArrayID;
-    glGenVertexArrays(1, &vertexArrayID);
-    glBindVertexArray(vertexArrayID);
-
-
-    // Projection matrix
-    arma::fmat projection = gfx3::orthographic(
-        (float) fb_width, (float) fb_height, 0.1f, 10.0f);
-
-    // Camera matrix
-    arma::fmat view = gfx3::lookAt(
-        arma::fvec({0, 0, 3}),  // Position of the camera
-        arma::fvec({0, 0, 0}),  // Look at the origin
-        arma::fvec({0, 1, 0})   // Head is up
-    );
-
-
-    // Loading of the shaders
-    gfx3::shader_t colored_shader = gfx3::loadShader(gfx3::VERTEX_SHADER_COLORED,
-                                                     gfx3::FRAGMENT_SHADER_COLORED);
-
-
-    // Main loop
-    bool adding_line = false;
-    std::vector<arma::vec> current_trajectory;
-    std::vector< std::vector<arma::vec> > original_trajectories;
-    std::vector<Demonstration> demos;
-    arma::mat mu;
-    arma::mat mu2;
-    arma::mat H;
-    int current_nb_data = parameters.nb_data;
-    int current_nb_states = parameters.nb_states;
-
-    while (!glfwWindowShouldClose(window)) {
-        glfwPollEvents();
-
-        // Detect when the window was resized
-        if ((ImGui::GetIO().DisplaySize.x != win_width) ||
-            (ImGui::GetIO().DisplaySize.y != win_height)) {
-
-            win_width = ImGui::GetIO().DisplaySize.x;
-            win_height = ImGui::GetIO().DisplaySize.y;
-
-            glfwGetFramebufferSize(window, &fb_width, &fb_height);
-
-            // Update the projection matrix
-            projection = gfx3::orthographic(
-                (float) fb_width, (float) fb_height, 0.1f, 10.0f);
-        }
-
-
-        // If the parameters changed, recompute
-        if ((parameters.nb_data != current_nb_data) ||
-            (parameters.nb_states != current_nb_states)) {
-
-            demos.clear();
-
-            for (size_t i = 0; i < original_trajectories.size(); ++i)
-                demos.push_back(sample_trajectory(original_trajectories[i], parameters.nb_data));
-
-            process(demos, parameters, mu, mu2, H);
-
-            current_nb_data = parameters.nb_data;
-            current_nb_states = parameters.nb_states;
-        }
-
-
-        // Start the rendering
-        ImGui_ImplGlfwGL3_NewFrame();
-        glViewport(0, 0, fb_width, fb_height);
-        glClearColor(0.6f, 0.6f, 0.6f, 0.0f);
-        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-
-        // Draw the currently created demonstration (if any)
-        if (current_trajectory.size() > 1) {
-            gfx3::model_t line = gfx3::create_line(
-                colored_shader, arma::fvec({0.33f, 0.97f, 0.33f}), current_trajectory);
-
-            gfx3::draw(line, view, projection);
-
-            gfx3::destroy(line);
-        }
-
-
-        // Draw the demonstrations (if any)
-        for (auto iter = demos.begin(); iter != demos.end(); ++iter) {
-            Datapoints& datapoints = iter->getDatapoints();
-
-            for (uint i = 0; i < datapoints.getNumPOINTS(); ++i) {
-                arma::fvec color = arma::conv_to<arma::fvec>::from(H.col(i).t() * COLORS.rows(0, parameters.nb_states - 1));
-
-                gfx3::model_t point = gfx3::create_square(colored_shader, color, 10.0f);
-
-                point.transforms.position = arma::conv_to<arma::fvec>::from(datapoints.getData(i));
-                point.transforms.position.reshape(3, point.transforms.position.n_cols);
-
-                gfx3::draw(point, view, projection);
-
-                gfx3::destroy(point);
-            }
-        }
-
-
-        // Draw the computed trajectories
-        if (mu.n_elem > 0) {
-            gfx3::model_t line = gfx3::create_line(
-                colored_shader, arma::fvec({0.0f, 0.0f, 0.0f}), mu);
-
-            gfx3::draw(line, view, projection);
-
-            gfx3::destroy(line);
-
-            line = gfx3::create_line(
-                colored_shader, arma::fvec({0.8f, 0.0f, 0.0f}), mu2);
-
-            gfx3::draw(line, view, projection);
-
-            gfx3::destroy(line);
-        }
-
-
-        // Parameter window
-        ImGui::SetNextWindowSize(ImVec2(400, 110));
-        ImGui::Begin("Parameters", NULL,
-                     ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings |
-                     ImGuiWindowFlags_NoMove
-        );
-
-        ImGui::SliderInt("Nb states", &parameters.nb_states, 2, 10);
-        ImGui::SliderInt("Nb data", &parameters.nb_data, 20, 300);
-
-        if (ImGui::Button("Clear")){
-            demos.clear();
-            original_trajectories.clear();
-            mu = arma::mat();
-            mu2 = arma::mat();
-            H = arma::mat();
-        }
-
-        ImGui::Text("Draw several similar trajectories");
-        ImGui::End();
-
-
-        // GUI rendering
-        ImGui::Render();
-
-        // Swap buffers
-        glfwSwapBuffers(window);
-
-        // Keyboard input
-        if (ImGui::IsKeyPressed(GLFW_KEY_ESCAPE))
-            break;
-
-
-        // Left click: start a new demonstration
-        if (!adding_line && ImGui::IsMouseClicked(GLFW_MOUSE_BUTTON_1)) {
-            // Only if not on the UI
-            if (!ImGui::GetIO().WantCaptureMouse)
-                adding_line = true;
-        }
-
-        if (adding_line) {
-            double mouse_x, mouse_y;
-            glfwGetCursorPos(window, &mouse_x, &mouse_y);
-
-            current_trajectory.push_back(gfx3::ui2fb({ mouse_x, mouse_y },
-                                                     win_width, win_height,
-                                                     fb_width, fb_height));
-        }
-
-        // Left mouse button release: end the demonstration creation
-        if (adding_line && !ImGui::IsMouseDown(GLFW_MOUSE_BUTTON_1)) {
-            adding_line = false;
-
-            demos.push_back(sample_trajectory(current_trajectory, parameters.nb_data));
-
-            original_trajectories.push_back(current_trajectory);
-            current_trajectory.clear();
-
-            process(demos, parameters, mu, mu2, H);
-        }
-    }
-
-
-    // Cleanup
-    ImGui_ImplGlfwGL3_Shutdown();
-    glfwTerminate();
-
-    return 0;
-}
-- 
GitLab