diff --git a/README.md b/README.md index 36144ec853ab47a61448eaf4ee7c6e8337793d5c..4f8ba1dda6a9de6f1992bd4e1dd5b3b26d7f27c9 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # pbdlib-matlab -<p>PbDlib is a collection of source codes for robot programming by demonstration (learning from demonstration). It includes various functionalities at the crossroad of statistical learning, dynamical systems, optimal control and Riemannian geometry.</p> +<p>PbDlib is a collection of source codes for robot programming by demonstration (learning from demonstration). It includes various functionalities including statistical learning, dynamical systems, optimal control and Riemannian geometry.</p> <p>PbDlib can be used in applications requiring task adaptation, human-robot skill transfer, safe controllers based on minimal intervention principle, as well as for probabilistic motion analysis and synthesis in multiple coordinate systems.</p> -<p>The codes are compatible with both Matlab and GNU Octave. Other versions of the library in Python and C++ are also available at http://www.idiap.ch/software/pbdlib/ (currently, the Matlab version has the most functionalities).</p> +<p>The codes are compatible with both Matlab and GNU Octave. Other versions of the library in Python and C++ are also available at https://www.idiap.ch/software/pbdlib/ (currently, the Matlab version contains the most complete set of examples).</p> ### Usage @@ -14,14 +14,6 @@ All the examples are located in the `demos` folder, and the functions are locate | Filename | Ref. | Description | |----------|------|-------------| -| [benchmark/benchmark_DS_GP_GMM01.m](./demos/benchmark_DS_GP_GMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized model based on GPR, with trajectory model (GMM encoding) | -| [benchmark/benchmark_DS_GP_raw01.m](./demos/benchmark_DS_GP_raw01.m) | [[1]](#ref-1) | Benchmark of task-parameterized model based on GPR, with raw trajectory | -| [benchmark/benchmark_DS_PGMM01.m](./demos/benchmark_DS_PGMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized model based on parametric Gaussian mixture model | -| [benchmark/benchmark_DS_TP_GMM01.m](./demos/benchmark_DS_TP_GMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized Gaussian mixture model (TP-GMM) | -| [benchmark/benchmark_DS_TP_GP01.m](./demos/benchmark_DS_TP_GP01.m) | [[1]](#ref-1) | Benchmark of task-parameterized Gaussian process (nonparametric task-parameterized method) | -| [benchmark/benchmark_DS_TP_LWR01.m](./demos/benchmark_DS_TP_LWR01.m) | [[1]](#ref-1) | Benchmark of task-parameterized locally weighted regression (nonparametric task-parameterized method) | -| [benchmark/benchmark_DS_TP_MFA01.m](./demos/benchmark_DS_TP_MFA01.m) | [[1]](#ref-1) | Benchmark of task-parameterized mixture of factor analyzers (TP-MFA) | -| [benchmark/benchmark_DS_TP_trajGMM01.m](./demos/benchmark_DS_TP_trajGMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized Gaussian mixture model (TP-GMM) | | [demo_affineTransform01.m](./demos/demo_affineTransform01.m) | [[1]](#ref-1) | Miscellaneous affine transformations of raw data as pre-processing step to train a task-parameterized model | | [demo_AR01.m](./demos/demo_AR01.m) | [[2]](#ref-2) | Multivariate autoregressive (AR) model parameters estimation with least-squares | | [demo_AR_HSMM01.m](./demos/demo_AR_HSMM01.m) | [[2]](#ref-2) | Multivariate autoregressive (AR) model implemented as a hidden semi-Markov model with lognormal duration model | @@ -111,7 +103,7 @@ All the examples are located in the `demos` folder, and the functions are locate | [demo_HSMM_MPC01.m](./demos/demo_HSMM_MPC01.m) | [[2]](#ref-2) | Use of HSMM (with lognormal duration model) and batch LQR (with position only) for motion synthesis | | [demo_HSMM_online01.m](./demos/demo_HSMM_online01.m) | [[2]](#ref-2) | Online HSMM | | [demo_ID01.m](./demos/demo_ID01.m) | [[10]](#ref-10) | Inverse dynamics with dynamically consistent nullspace (requires the robotics toolbox) | -| [demo_IK01.m](./demos/demo_IK01.m) | [[10]](#ref-10) | Inverse kinematics with nullspace control (requires the robotics toolbox) | +| [demo_IK01.m](./demos/demo_IK01.m) | [[10]](#ref-10) | Basic forward and inverse kinematics for a planar robot, with numerical Jacobian computation | | [demo_IK02.m](./demos/demo_IK02.m) | [[10]](#ref-10) | Inverse kinematics with two arms and nullspace control (requires the robotics toolbox) | | [demo_IK_nullspaceAsProduct01.m](./demos/demo_IK_nullspaceAsProduct01.m) | [[1]](#ref-1) | 3-level nullspace control formulated as product of Gaussians | | [demo_IK_nullspace_TPGMM01.m](./demos/demo_IK_nullspace_TPGMM01.m) | [[1]](#ref-1) | IK with nullspace treated with task-parameterized GMM (bimanual tracking task, version with 4 frames) | @@ -138,43 +130,44 @@ All the examples are located in the `demos` folder, and the functions are locate | [demo_manipulabilityTransfer01.m](./demos/demo_manipulabilityTransfer01.m) | [[6]](#ref-6) | Use of robot redundancy to track desired manipulability ellipsoid | | [demo_manipulabilityTransfer02.m](./demos/demo_manipulabilityTransfer02.m) | [[6]](#ref-6) | Learning and reproduction of manipulability ellipsoid profiles | | [demo_manipulabilityTransfer03.m](./demos/demo_manipulabilityTransfer03.m) | [[6]](#ref-6) | Learning and reproduction of manipulability ellipsoid profiles (numerical version) | -| [demo_MPC01.m](./demos/demo_MPC01.m) | [[2]](#ref-2) | Batch LQR with viapoints and a double integrator system. | -| [demo_MPC02.m](./demos/demo_MPC02.m) | [[2]](#ref-2) | Same as demo_MPC01.m but with a GMM encoding of only position data | -| [demo_MPC03.m](./demos/demo_MPC03.m) | [[2]](#ref-2) | Control of a spring attached to a point with batch LQR | -| [demo_MPC04.m](./demos/demo_MPC04.m) | [[2]](#ref-2) | Control of a spring attached to a point with batch LQR (with augmented state space) | -| [demo_MPC_augmSigma01.m](./demos/demo_MPC_augmSigma01.m) | [[2]](#ref-2) | Batch LQR with augmented covariance to transform a tracking problem to a regulation problem | -| [demo_MPC_constrained01.m](./demos/demo_MPC_constrained01.m) | [[2]](#ref-2) | Constrained batch LQT by using quadratic programming solver, with an encoding of position and velocity data | -| [demo_MPC_fullQ01.m](./demos/demo_MPC_fullQ01.m) | [[2]](#ref-2) | Batch LQR exploiting full Q matrix by constraining the motion to pass through a common point at different time steps | -| [demo_MPC_fullQ02.m](./demos/demo_MPC_fullQ02.m) | [[2]](#ref-2) | Batch LQR exploiting full Q matrix by constraining the motion of two agents | -| [demo_MPC_fullQ03.m](./demos/demo_MPC_fullQ03.m) | [[2]](#ref-2) | Batch LQR exploiting full Q matrix by constraining the motion of two agents in a ballistic task | -| [demo_MPC_infHor01.m](./demos/demo_MPC_infHor01.m) | [[2]](#ref-2) | Discrete infinite horizon linear quadratic regulation (with precision matrix only on position) | -| [demo_MPC_infHor02.m](./demos/demo_MPC_infHor02.m) | [[2]](#ref-2) | Discrete infinite horizon linear quadratic regulation (with precision matrix on position and velocity) | -| [demo_MPC_infHor03.m](./demos/demo_MPC_infHor03.m) | [[2]](#ref-2) | Continuous infinite horizon linear quadratic tracking, by relying on a GMM encoding of position and velocity data | -| [demo_MPC_infHor04.m](./demos/demo_MPC_infHor04.m) | [[2]](#ref-2) | Discrete infinite horizon linear quadratic tracking, by relying on a GMM encoding of position and velocity data | -| [demo_MPC_infHor_bicopter01.m](./demos/demo_MPC_infHor_bicopter01.m) | [[2]](#ref-2) | Infinite horizon LQR applied on a planar UAV with an iterative linearization of the system plant | -| [demo_MPC_infHor_incremental01.m](./demos/demo_MPC_infHor_incremental01.m) | [[2]](ref-2) | Infinite horizon LQR with an iterative re-estimation of the system plant linear system (example with planar UAV) | -| [demo_MPC_infHor_incremental02.m](./demos/demo_MPC_infHor_incremental02.m) | [[2]](ref-2) | Same as demo_MPC_infHor_incremental01.m but with pendulum) | -| [demo_MPC_iterativeLQR01.m](./demos/demo_MPC_iterativeLQR01.m) | [[2]](#ref-2) | Iterative computation of linear quadratic tracking (with feedback and feedforward terms) | -| [demo_MPC_iterativeLQR02.m](./demos/demo_MPC_iterativeLQR02.m) | [[2]](#ref-2) | Same as demo_MPC_iterativeLQR01.m, by relying on a GMM encoding of position and velocity data | -| [demo_MPC_iterativeLQR03.m](./demos/demo_MPC_iterativeLQR03.m) | [[2]](#ref-2) | Same as demo_MPC_iterativeLQR01.m, by relying on a GMM encoding of only position data | -| [demo_MPC_iterativeLQR04.m](./demos/demo_MPC_iterativeLQR04.m) | [[2]](#ref-2) | Control of a spring attached to a point with iterative linear quadratic tracking (with feedback and feedforward terms) | -| [demo_MPC_iterativeLQR_augmSigma01.m](./demos/demo_MPC_iterativeLQR_augmSigma01.m) | [[2]](#ref-2) | Iterative LQR with augmented covariance to transform the tracking problem to a regulation problem | -| [demo_MPC_iterativeLQR_augmSigma_online01.m](./demos/demo_MPC_iterativeLQR_augmSigma_online01.m) | [[2]](#ref-2) | Same as demo_iterativeLQR_augmSigma01 but recomputed in an online manner | -| [demo_MPC_Lagrangian01.m](./demos/demo_MPC_Lagrangian01.m) | [[2]](#ref-2) | Batch LQR with Lagrangian in matrix form to force first and last point to coincide in order to form periodic motion | -| [demo_MPC_MP01.m](./demos/demo_MPC_MP01.m) | [[2]](#ref-2) | Batch LQR using sparse movement primitives with radial basis functions | -| [demo_MPC_MP02.m](./demos/demo_MPC_MP02.m) | [[2]](#ref-2) | Batch LQR using sparse movement primitives with Fourier basis functions | -| [demo_MPC_noInitialState01.m](./demos/demo_MPC_noInitialState01.m) | [[2]](#ref-2) | Batch LQR solution finding the optimal initial state together with the optimal control commands | -| [demo_MPC_nullspace01.m](./demos/demo_MPC_nullspace01.m) | [[2]](#ref-2) | Batch LQR with nullspace formulation | -| [demo_MPC_nullspace_online01.m](./demos/demo_MPC_nullspace_online01.m) | [[2]](#ref-2) | Online batch LQR with nullspace formulation | -| [demo_MPC_online01.m](./demos/demo_MPC_online01.m) | [[2]](#ref-2) | MPC recomputed in an online manner with a time horizon | -| [demo_MPC_online02.m](./demos/demo_MPC_online02.m) | [[2]](#ref-2) | MPC recomputed in an online manner with a time horizon, by relying on a GMM encoding of position and velocity data (with animation) | -| [demo_MPC_online03.m](./demos/demo_MPC_online03.m) | [[2]](#ref-2) | Obstacle avoidance with MPC recomputed in an online manner | -| [demo_MPC_robot01.m](./demos/demo_MPC_robot01.m) | [[2]](#ref-2) | Robot tracking task with online batch LQR, by linearization of the system plant at each time step | -| [demo_MPC_skillsRepr01.m](./demos/demo_MPC_skillsRepr01.m) | [[2]](#ref-2) | Representation of skills combined in parallel and in series through a batch LQT formulation | -| [demo_MPC_viapoints01.m](./demos/demo_MPC_viapoints01.m) | [[2]](#ref-2) | Keypoint-based motion through MPC, with a GMM encoding of position and velocity | -| [demo_MPC_viapoints02.m](./demos/demo_MPC_viapoints02.m) | [[2]](#ref-2) | Same as demo_MPC_viapoints01 with only position encoding | -| [demo_MPC_viapoints03.m](./demos/demo_MPC_viapoints03.m) | [[8]](#ref-8) | Equivalence between cubic Bezier curve and batch LQR with double integrator | -| [demo_MPC_viapoints_withProd01.m](./demos/demo_MPC_viapoints_withProd01.m) | [[2]](#ref-2) | Batch LQT with viapoints computed as a product of trajectory distributions in control space | +| [demo_OC_DDP_bicopter01.m](./demos/demo_OC_DDP_bicopter01.m) | [[2]](#ref-2) | iLQR applied to a bicopter problem | +| [demo_OC_DDP_car01.m](./demos/demo_OC_DDP_car01.m) | [[2]](#ref-2) | iLQR applied to a car parking problem | +| [demo_OC_DDP_cartpole01.m](./demos/demo_OC_DDP_cartpole01.m) | [[2]](#ref-2) | iLQR applied to a cartpole problem | +| [demo_OC_DDP_humanoid01.m](./demos/demo_OC_DDP_humanoid01.m) | [[2]](#ref-2) | iLQR applied to a planar 5-link humanoid problem with constraints between joints | +| [demo_OC_DDP_manipulator01.m](./demos/demo_OC_DDP_manipulator01.m) | [[2]](#ref-2) | iLQR applied to a 2D manipulator problem | +| [demo_OC_DDP_pendulum01.m](./demos/demo_OC_DDP_pendulum01.m) | [[2]](#ref-2) | iLQR applied to an actuated inverted pendulum problem | +| [demo_OC_LQT01.m](./demos/demo_OC_LQT01.m) | [[2]](#ref-2) | Batch solution of linear quadratic optimal control (unconstrained linear MPC), by relying on a Gaussian mixture model (GMM) encoding of position and velocity data (see also demo_OC_LQT_iterativeLQR01.m) | +| [demo_OC_LQT02.m](./demos/demo_OC_LQT02.m) | [[2]](#ref-2) | Same as demo_OC_LQT01.m but with a GMM encoding of only position data | +| [demo_OC_LQT03.m](./demos/demo_OC_LQT03.m) | [[2]](#ref-2) | Same as demo_OC_LQT01.m but by tracking only position references | +| [demo_OC_LQT04.m](./demos/demo_OC_LQT04.m) | [[2]](#ref-2) | Control of a spring attached to a point with batch LQR (with augmented state space) | +| [demo_OC_LQT_augmSigma01.m](./demos/demo_OC_LQT_augmSigma01.m) | [[2]](#ref-2) | Batch LQR with augmented covariance to transform a tracking problem to a regulation problem | +| [demo_OC_LQT_ballistic01.m](./demos/demo_OC_LQT_ballistic01.m) | [[2]](#ref-2) | Batch LQT with augmented state to solve simple ballistic problem | +| [demo_OC_LQT_constrained01.m](./demos/demo_OC_LQT_constrained01.m) | [[2]](#ref-2) | Constrained batch LQT by using quadratic programming solver, with an encoding of position and velocity data | +| [demo_OC_LQT_fullQ01.m](./demos/demo_OC_LQT_fullQ01.m) | [[2]](#ref-2) | Batch LQT problem exploiting full Q matrix by constraining the motion to pass through a common point at different time steps | +| [demo_OC_LQT_fullQ02.m](./demos/demo_OC_LQT_fullQ02.m) | [[2]](#ref-2) | Batch LQT problem exploiting full Q matrix by constraining the motion of two agents | +| [demo_OC_LQT_fullQ03.m](./demos/demo_OC_LQT_fullQ03.m) | [[2]](#ref-2) | Batch LQT problem exploiting full Q matrix by constraining the motion of two agents in a simple ballistic task | +| [demo_OC_LQT_fullQ04.m](./demos/demo_OC_LQT_fullQ04.m) | [[2]](#ref-2) | Batch LQT exploiting full Q matrix to constrain the motion of two agents in a ballistic task mimicking a bimanual tennis serve problem | +| [demo_OC_LQT_infHor01.m](./demos/demo_OC_LQT_infHor01.m) | [[2]](#ref-2) | Discrete infinite horizon linear quadratic regulation (with precision matrix only on position) | +| [demo_OC_LQT_infHor02.m](./demos/demo_OC_LQT_infHor02.m) | [[2]](#ref-2) | Discrete infinite horizon linear quadratic regulation (with precision matrix on position and velocity) | +| [demo_OC_LQT_infHor03.m](./demos/demo_OC_LQT_infHor03.m) | [[2]](#ref-2) | Continuous infinite horizon linear quadratic tracking, by relying on a GMM encoding of position and velocity data | +| [demo_OC_LQT_infHor04.m](./demos/demo_OC_LQT_infHor04.m) | [[2]](#ref-2) | Discrete infinite horizon linear quadratic tracking, by relying on a GMM encoding of position and velocity data | +| [demo_OC_LQT_recursive01.m](./demos/demo_OC_LQT_recursive01.m) | [[2]](#ref-2) | Recursive computation of linear quadratic tracking (with feedback and feedforward terms) | +| [demo_OC_LQT_recursive02.m](./demos/demo_OC_LQT_recursive02.m) | [[2]](#ref-2) | Same as demo_OC_LQT_recursive01.m, by relying on a GMM encoding of position and velocity data, including comparison with batch LQT | +| [demo_OC_LQT_recursive03.m](./demos/demo_OC_LQT_recursive03.m) | [[2]](#ref-2) | Same as demo_OC_LQT_recursive01.m, by relying on a GMM encoding of only position data | +| [demo_OC_LQT_recursive_augmSigma01.m](./demos/demo_OC_LQT_recursive_augmSigma01.m) | [[2]](#ref-2) | Recursive LQR with augmented covariance to transform the tracking problem to a regulation problem | +| [demo_OC_LQT_Lagrangian01.m](./demos/demo_OC_LQT_Lagrangian01.m) | [[2]](#ref-2) | Batch LQR with Lagrangian in matrix form to force first and last point to coincide in order to form periodic motion | +| [demo_OC_LQT_noInitialState01.m](./demos/demo_OC_LQT_noInitialState01.m) | [[2]](#ref-2) | Batch LQR solution finding the optimal initial state together with the optimal control commands | +| [demo_OC_LQT_nullspace01.m](./demos/demo_OC_LQT_nullspace01.m) | [[2]](#ref-2) | Batch LQR with nullspace formulation | +| [demo_OC_LQT_nullspace02.m](./demos/demo_OC_LQT_nullspace02.m) | [[2]](#ref-2) | Batch LQR with nullspace formulation - ballistic task with an augmented state space | +| [demo_OC_LQT_online01.m](./demos/demo_OC_LQT_online01.m) | [[2]](#ref-2) | MPC recomputed in an online manner with a time horizon | +| [demo_OC_LQT_online02.m](./demos/demo_OC_LQT_online02.m) | [[2]](#ref-2) | MPC recomputed in an online manner with a time horizon, by relying on a GMM encoding of position and velocity data (with animation) | +| [demo_OC_LQT_online03.m](./demos/demo_OC_LQT_online03.m) | [[2]](#ref-2) | Obstacle avoidance with MPC recomputed in an online manner | +| [demo_OC_LQT_online_minimal01.m](./demos/demo_OC_LQT_online_minimal01.m) | [[2]](#ref-2) | Minimal example of online batch LQT | +| [demo_OC_LQT_skillsRepr01.m](./demos/demo_OC_LQT_skillsRepr01.m) | [[2]](#ref-2) | Representation of skills combined in parallel and in series through a batch LQT formulation | +| [demo_OC_LQT_viapoints01.m](./demos/demo_OC_LQT_viapoints01.m) | [[2]](#ref-2) | Keypoint-based motion through MPC, with a GMM encoding of position and velocity | +| [demo_OC_LQT_viapoints02.m](./demos/demo_OC_LQT_viapoints02.m) | [[2]](#ref-2) | Same as demo_OC_LQT_viapoints01 with only position encoding | +| [demo_OC_LQT_viapoints03.m](./demos/demo_OC_LQT_viapoints03.m) | [[2]](#ref-2) | Equivalence between cubic Bezier curve and batch LQT with double integrator | +| [demo_OC_LQT_viapoints_withProd01.m](./demos/demo_OC_LQT_viapoints_withProd01.m) | [[2]](#ref-2) | Batch LQT with viapoints computed as a product of trajectory distributions in control space | | [demo_PCA01.m](./demos/demo_PCA01.m) | [[10]](#ref-10) | Principal component analysis (PCA) | | [demo_Procrustes01.m](./demos/demo_Procrustes01.m) | [[10]](#ref-10) | SVD solution of orthogonal Procrustes problem | | [demo_proMP01.m](./demos/demo_proMP01.m) | [[5]](#ref-5) | Conditioning on trajectory distributions with Probabilistic movement primitives to estimate trajectory distribution| @@ -254,6 +247,14 @@ All the examples are located in the `demos` folder, and the functions are locate | [demo_trajHSMM01.m](./demos/demo_trajHSMM01.m) | [[2]](#ref-2) | Trajectory synthesis with an HSMM with dynamic features (trajectory-HSMM) | | [demo_trajHSMM_adaptiveDuration01.m](./demos/demo_trajHSMM_adaptiveDuration01.m) | [[9]](#ref-9) | Hidden semi-Markov model with adaptive duration | | [demo_trajHSMM_adaptiveDuration_online01.m](./demos/demo_trajHSMM_adaptiveDuration_online01.m) | [[9]](#ref-9) | Online trajectory retrieval method built on an HSMM with adaptive duration and a trajectory-GMM representation | +| [benchmarks/benchmark_DS_GP_GMM01.m](./demos/benchmarks/benchmark_DS_GP_GMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized model based on GPR, with trajectory model (GMM encoding) | +| [benchmarks/benchmark_DS_GP_raw01.m](./demos/benchmarks/benchmark_DS_GP_raw01.m) | [[1]](#ref-1) | Benchmark of task-parameterized model based on GPR, with raw trajectory | +| [benchmarks/benchmark_DS_PGMM01.m](./demos/benchmarks/benchmark_DS_PGMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized model based on parametric Gaussian mixture model | +| [benchmarks/benchmark_DS_TP_GMM01.m](./demos/benchmarks/benchmark_DS_TP_GMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized Gaussian mixture model (TP-GMM) | +| [benchmarks/benchmark_DS_TP_GP01.m](./demos/benchmarks/benchmark_DS_TP_GP01.m) | [[1]](#ref-1) | Benchmark of task-parameterized Gaussian process (nonparametric task-parameterized method) | +| [benchmarks/benchmark_DS_TP_LWR01.m](./demos/benchmarks/benchmark_DS_TP_LWR01.m) | [[1]](#ref-1) | Benchmark of task-parameterized locally weighted regression (nonparametric task-parameterized method) | +| [benchmarks/benchmark_DS_TP_MFA01.m](./demos/benchmarks/benchmark_DS_TP_MFA01.m) | [[1]](#ref-1) | Benchmark of task-parameterized mixture of factor analyzers (TP-MFA) | +| [benchmarks/benchmark_DS_TP_trajGMM01.m](./demos/benchmarks/benchmark_DS_TP_trajGMM01.m) | [[1]](#ref-1) | Benchmark of task-parameterized Gaussian mixture model (TP-GMM) | ### References @@ -263,72 +264,72 @@ If you find PbDlib useful for your research, please cite the related publication <p><a name="ref-1"> [1] Calinon, S. (2016). <strong>A Tutorial on Task-Parameterized Movement Learning and Retrieval</strong>. Intelligent Service Robotics (Springer), 9:1, 1-29. </a><br> -[[pdf]](http://calinon.ch/papers/Calinon-JIST2015.pdf) -[[bib]](http://calinon.ch/papers/Calinon-JIST2015.bib) +[[pdf]](https://calinon.ch/papers/Calinon-JIST2015.pdf) +[[bib]](https://calinon.ch/papers/Calinon-JIST2015.bib) <br><strong>(Ref. for GMM, TP-GMM, MFA, MPPCA, GPR, trajGMM)</strong> </p> <p><a name="ref-2"> [2] Calinon, S. and Lee, D. (2019). <strong>Learning Control</strong>. Vadakkepat, P. and Goswami, A. (eds.). Humanoid Robotics: a Reference, pp. 1261-1312. Springer. </a><br> -[[pdf]](http://calinon.ch/papers/Calinon-Lee-learningControl.pdf) -[[bib]](http://calinon.ch/papers/Calinon-Lee-learningControl.bib) -<br><strong>(Ref. for MPC, LQR, HMM, HSMM)</strong> +[[pdf]](https://calinon.ch/papers/Calinon-Lee-learningControl.pdf) +[[bib]](https://calinon.ch/papers/Calinon-Lee-learningControl.bib) +<br><strong>(Ref. for LQR, MPC, HMM, HSMM)</strong> </p> <p><a name="ref-3"> -[3] Calinon, S. (2020). <strong>Gaussians on Riemannian Manifolds: Applications for Robot Learning and Adaptive Control</strong>. IEEE Robotics and Automation Magazine (RAM). +[3] Calinon, S. (2020). <strong>Gaussians on Riemannian Manifolds: Applications for Robot Learning and Adaptive Control</strong>. IEEE Robotics and Automation Magazine (RAM), 27:2, 33-45. </a><br> -[[pdf]](http://calinon.ch/papers/Calinon-RAM2020.pdf) -[[bib]](http://calinon.ch/papers/Calinon-RAM2020.bib) +[[pdf]](https://calinon.ch/papers/Calinon-RAM2020.pdf) +[[bib]](https://calinon.ch/papers/Calinon-RAM2020.bib) <br><strong>(Ref. for Riemannian manifolds)</strong> </p> <p><a name="ref-4"> [4] Jaquier, N. and Calinon, S. (2017). <strong>Gaussian Mixture Regression on Symmetric Positive Definite Matrices Manifolds: Application to Wrist Motion Estimation with sEMG</strong>. In Proc. of the IEEE/RSJ Intl Conf. on Intelligent Robots and Systems (IROS), pp. 59-64. </a><br> -[[pdf]](http://calinon.ch/papers/Jaquier-IROS2017.pdf) -[[bib]](http://calinon.ch/papers/Jaquier-IROS2017.bib) +[[pdf]](https://calinon.ch/papers/Jaquier-IROS2017.pdf) +[[bib]](https://calinon.ch/papers/Jaquier-IROS2017.bib) <br><strong>(Ref. for S^+ Riemannian manifolds)</strong> </p> <p><a name="ref-5"> [5] Calinon, S. (2019). <strong>Mixture Models for the Analysis, Edition, and Synthesis of Continuous Time Series</strong>. Bouguila, N. and Fan, W. (eds). Mixture Models and Applications, pp. 39-57. Springer. </a><br> -[[pdf]](http://calinon.ch/papers/Calinon_MMchapter2019.pdf) -[[bib]](http://calinon.ch/papers/Calinon_MMchapter2019.bib) +[[pdf]](https://calinon.ch/papers/Calinon_MMchapter2019.pdf) +[[bib]](https://calinon.ch/papers/Calinon_MMchapter2019.bib) <br><strong>(Ref. for ergodic control, Bezier curves, LWR, GMR, probabilistic movement primitives)</strong> </p> <p><a name="ref-6"> -[6] Jaquier, N., Rozo, L., Caldwell, D.G. and Calinon, S. (2019). <strong>Geometry-aware Manipulability Transfer</strong>. arXiv:1811.11050. +[6] Jaquier, N., Rozo, L., Caldwell, D.G. and Calinon, S. (2020). <strong>Geometry-aware Manipulability Learning, Tracking and Transfer</strong>. International Journal of Robotics Research (IJRR). </a><br> -[[pdf]](http://calinon.ch/papers/Jaquier-arXiv2018.pdf) -[[bib]](http://calinon.ch/papers/Jaquier-arXiv2018.bib) +[[pdf]](https://calinon.ch/papers/Jaquier-IJRR2020.pdf) +[[bib]](https://calinon.ch/papers/Jaquier-IJRR2020.bib) <br><strong>(Ref. for manipulability ellipsoids)</strong> </p> <p><a name="ref-7"> [7] Bruno, D., Calinon, S. and Caldwell, D.G. (2017). <strong>Learning Autonomous Behaviours for the Body of a Flexible Surgical Robot</strong>. Autonomous Robots, 41:2, 333-347. </a><br> -[[pdf]](http://calinon.ch/papers/Bruno-AURO2017.pdf) -[[bib]](http://calinon.ch/papers/Bruno-AURO2017.bib) +[[pdf]](https://calinon.ch/papers/Bruno-AURO2017.pdf) +[[bib]](https://calinon.ch/papers/Bruno-AURO2017.bib) <br><strong>(Ref. for DP-means)</strong> </p> <p><a name="ref-8"> [8] Berio, D., Calinon, S. and Fol Leymarie, F. (2017). <strong>Generating Calligraphic Trajectories with Model Predictive Control</strong>. In Proc. of the 43rd Conf. on Graphics Interface, pp. 132-139. </a><br> -[[pdf]](http://calinon.ch/papers/Berio-GI2017.pdf) -[[bib]](http://calinon.ch/papers/Berio-GI2017.bib) -<br><strong>(Ref. for Bezier curves as MPC with viapoints)</strong> +[[pdf]](https://calinon.ch/papers/Berio-GI2017.pdf) +[[bib]](https://calinon.ch/papers/Berio-GI2017.bib) +<br><strong>(Ref. for Bezier curves as batch LQT with viapoints)</strong> </p> <p><a name="ref-9"> [9] Rozo, L., Silvério, J., Calinon, S. and Caldwell, D.G. (2016). <strong>Learning Controllers for Reactive and Proactive Behaviors in Human-Robot Collaboration</strong>. Frontiers in Robotics and AI, 3:30, 1-11. </a><br> -[[pdf]](http://calinon.ch/papers/Rozo-Frontiers2016.pdf) -[[bib]](http://calinon.ch/papers/Rozo-Frontiers2016.bib) +[[pdf]](https://calinon.ch/papers/Rozo-Frontiers2016.pdf) +[[bib]](https://calinon.ch/papers/Rozo-Frontiers2016.bib) <br><strong>(Ref. for HSMM with adaptive time duration)</strong> </p> @@ -356,7 +357,7 @@ If you find PbDlib useful for your research, please cite the related publication The Matlab/GNU Octave version of PbDlib is maintained by Sylvain Calinon, Idiap Research Institute. -Copyright (c) 2015-2019 Idiap Research Institute, http://idiap.ch/ +Copyright (c) 2015-2021 Idiap Research Institute, https://idiap.ch/ PbDlib is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation. diff --git a/demos/demo_IK01.m b/demos/demo_IK01.m index 03a4d2aa379dd50381c8a68907473d56d644c9ec..0521ea1adfd8c36354a9d9682a40020274977c20 100644 --- a/demos/demo_IK01.m +++ b/demos/demo_IK01.m @@ -37,7 +37,7 @@ addpath('./m_fcts/'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dt = 1E-2; %Time step nbData = 100; - + use %% Robot parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/demos/demo_MPC_MP01.m b/demos/demo_MPC_MP01.m deleted file mode 100644 index 6451406c1f52a7a4e8d02699a9ae841121c91430..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_MP01.m +++ /dev/null @@ -1,191 +0,0 @@ -function demo_MPC_MP01 -% Batch LQR using sparse movement primitives with radial basis functions -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19MM, -% author="Calinon, S.", -% title="Mixture Models for the Analysis, Edition, and Synthesis of Continuous Time Series", -% booktitle="Mixture Models and Applications", -% publisher="Springer", -% editor="Bouguila, N. and Fan, W.", -% year="2019", -% pages="39--57", -% doi="10.1007/978-3-030-23876-6_3" -% } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon, http://calinon.ch/ -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbVarPos = 2; %Dimension of position data (here: x1,x2) -nbDeriv = 1; %Number of static & dynamic features (nbDeriv=2 for [x,dx]) -nbData = 200; %Number of datapoints in a trajectory - -dt = 0.01; %Time step duration -rfactor = 1E2; %Control cost in LQR -R = speye((nbData-1)*nbVarPos) * rfactor; - - -%% Dynamical System settings (discrete version) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -A1d = zeros(nbDeriv); -for i=0:nbDeriv-1 - A1d = A1d + diag(ones(nbDeriv-i,1),i) .* dt^i ./ factorial(i); %Discrete 1D -end -B1d = zeros(nbDeriv,1); -for i=1:nbDeriv - B1d(nbDeriv-i+1) = dt^i ./ factorial(i); %Discrete 1D -end -A = kron(A1d, eye(nbVarPos)); %Discrete nD -B = kron(B1d, eye(nbVarPos)); %Discrete nD -C = kron([1, zeros(1,nbDeriv-1)], eye(nbVarPos)); - -%Build CSx and CSu matrices for batch LQR -CSu = zeros(nbVarPos*nbData, nbVarPos*(nbData-1)); -CSx = kron(ones(nbData,1), [eye(nbVarPos) zeros(nbVarPos, nbVarPos*(nbDeriv-1))]); -M = B; -for n=2:nbData - id1 = (n-1)*nbVarPos+1:n*nbVarPos; - CSx(id1,:) = CSx(id1,:) * A; - id1 = (n-1)*nbVarPos+1:n*nbVarPos; - id2 = 1:(n-1)*nbVarPos; - CSu(id1,id2) = C * M; - M = [A*M(:,1:nbVarPos), M]; %Also M = [A^(n-1)*B, M] or M = [Sx(id1,:)*B, M] -end - - -%% Probabilistic movement primitives with radial basis functions -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Generate data -nbSamples = 4; %Number of demonstrations -for n=1:nbSamples - t = linspace(.2*n/3, 1.5*pi+.4*n/3, nbData); - xtmp = (1+n.*1E-2) .* [cos(t); sin(t)] + (.7+n.*1E-2) .* [zeros(1,nbData); cos(t*2-pi/3)] + randn(nbVarPos,nbData) .* 1E-2; - x(:,n) = xtmp(:); -end - -%Compute basis functions Psi and activation weights w -nbFct = 12; -t = linspace(0,1,nbData); -tMu = linspace(t(1), t(end), nbFct); -phi = zeros(nbData,nbFct); - -for i=1:nbFct - phi(:,i) = gaussPDF(t, tMu(i), 1E-2); -% phi(:,i) = mvnpdf(t', tMu(i), 1E-2); -end -% phi = phi ./ repmat(sum(phi,2),1,nbFct); %Optional rescaling - -% for i=0:nbFct-1 -% phi(:,i+1) = factorial(nbFct-1) ./ (factorial(i) .* factorial(nbFct-1-i)) .* (1-t).^(nbFct-1-i) .* t.^i; %Bernstein basis functions -% end - -Psi = kron(phi, eye(nbVarPos)); - -% w = (Psi' * Psi + eye(nbFct*nbVarPos).*1E-18) \ Psi' * x; -w = pinv(Psi) * x; - -%Distribution in parameter space -Mu_w = mean(w,2); %Mean -Sigma_w = cov(w') + eye(nbFct*nbVarPos) .* 1E-4; %Covariance - -%Distribution in trajectory space -MuQ = Psi * Mu_w; %Mean -Q = Psi / Sigma_w * Psi'; %Precision matrix -% rank(Q) %Q is sparse - - -%% Reproduction -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -x0 = [x(1:2,1)+.2; zeros(nbVarPos*(nbDeriv-1),1)]; - -% % u = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - Sx*x0)); -% % rx = reshape(Sx*x0+Su*u, nbVarPos, nbData); -% u = (CSu' * Q * CSu + R) \ (CSu' * Q * (MuQ - CSx*x0)); -% rx = reshape(CSx*x0+CSu*u, nbVarPos, nbData); - -%Alternative computation highlighting the linear relation to Mu_w and x0 in the solution -A0 = (CSu' * Q * CSu + R) \ CSu' * Q; -A1 = CSu * A0 * Psi; -A2 = CSx - CSu * A0 * CSx; -rx = reshape(A1 * Mu_w + A2 * x0, nbVarPos, nbData); - -%Comparison with Gaussian conditioning -in = 1:nbVarPos; -out = nbVarPos+1:nbVarPos*nbData; -Sigma = Psi * Sigma_w * Psi'; -rx_out = MuQ(out) + Sigma(out,in) / Sigma(in,in) * (x0(1:nbVarPos) - MuQ(in)); -% rx_out = MuQ(out) - Q(out,out) \ Q(out,in) * (x0(1:nbVarPos) - MuQ(in)); -rx2 = reshape([x0(1:nbVarPos); rx_out], nbVarPos, nbData); - -% %Computation of covariances -% uSigma = inv(Rq) .* 1E-1; -% xSigma = Su * uSigma * Su'; - - -%% 2D Plots -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10,10,2300,1200]); -subplot(3,2,[1,3,5]); hold on; axis off; -for n=1:nbSamples - plot(x(1:2:end,n), x(2:2:end,n), '-','linewidth',4,'color',[.7,.7,.7]); -end -plot(MuQ(1:2:end), MuQ(2:2:end), '-','linewidth',4,'color',[.8 0 0]); -plot(rx(1,1), rx(2,1), '.','markersize',28,'color',[0,0,0]); -plot(rx(1,:), rx(2,:), '-','linewidth',4,'color',[0,0,0]); -plot(rx2(1,:), rx2(2,:), '-','linewidth',4,'color',[0,0,.8]); -axis equal; - -%Timeline Plots -for j=1:2 - subplot(3,2,2*(j-1)+2); hold on; %axis off; - for n=1:nbSamples - plot(1:nbData, x(j:2:end,n), '-','linewidth',3,'color',[.7,.7,.7]); - end -% %Plot uncertainty -% id = j:nbVar:nbVar*nbData; -% S = diag(xSigma(id,id)); -% patch([1:nbData nbData:-1:1], [rx(j,:)-S(:)' fliplr(rx(j,:)+S(:)')], [.8 0 0],'edgecolor',[.6 0 0],'facealpha', .2, 'edgealpha', .2); - plot(1:nbData, MuQ(j:2:end), '-','linewidth',4,'color',[.8 0 0]); - plot(1:nbData, rx(j,:), '-','linewidth',4,'color',[0 0 0]); - set(gca,'xtick',[],'ytick',[]); - xlabel('$t$','interpreter','latex','fontsize',34); - ylabel(['$x_' num2str(j) '$'],'interpreter','latex','fontsize',34); -end - -%Basis functions plot -subplot(3,2,6); hold on; -clrmap = lines(nbFct); -for i=1:nbFct - plot(1:nbData, phi(:,i), '-','linewidth',3,'color',clrmap(i,:)); %axis tight; -end -set(gca,'xtick',[],'ytick',[]); -xlabel('$t$','interpreter','latex','fontsize',34); ylabel('$\phi_k$','interpreter','latex','fontsize',34); - -% %Psi*Psi' plot -% figure; hold on; axis off; title('\Psi\Psi^T','fontsize',16); -% colormap(flipud(gray)); -% imagesc(abs(Psi * Psi')); -% axis tight; axis square; axis ij; - -% print('-dpng','graphs/MPC_MP01.png'); -pause; -close all; \ No newline at end of file diff --git a/demos/demo_MPC_MP02.m b/demos/demo_MPC_MP02.m deleted file mode 100644 index 853c910a70f2ba0b8962170b1c95a30c8f383c8d..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_MP02.m +++ /dev/null @@ -1,195 +0,0 @@ -function demo_MPC_MP02 -% Batch LQR using sparse movement primitives with Fourier basis functions -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19MM, -% author="Calinon, S.", -% title="Mixture Models for the Analysis, Edition, and Synthesis of Continuous Time Series", -% booktitle="Mixture Models and Applications", -% publisher="Springer", -% editor="Bouguila, N. and Fan, W.", -% year="2019", -% pages="39--57", -% doi="10.1007/978-3-030-23876-6_3" -% } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon, http://calinon.ch/ -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbVarPos = 2; %Dimension of position data (here: x1,x2) -nbDeriv = 1; %Number of static & dynamic features (D=2 for [x,dx]) -nbVar = nbVarPos * nbDeriv; %Dimension of state vector -nbData = 500; %Number of datapoints in a trajectory - -dt = 0.01; %Time step duration -rfactor = 1E-8; %Control cost in LQR -R = speye((nbData-1)*nbVarPos) * rfactor; - - -%% Dynamical System settings (discrete version) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Integration with higher order Taylor series expansion -A1d = zeros(nbDeriv); -for i=0:nbDeriv-1 - A1d = A1d + diag(ones(nbDeriv-i,1),i) * dt^i * 1/factorial(i); %Discrete 1D -end -B1d = zeros(nbDeriv,1); -for i=1:nbDeriv - B1d(nbDeriv-i+1) = dt^i * 1/factorial(i); %Discrete 1D -end -A = kron(A1d, speye(nbVarPos)); %Discrete nD -B = kron(B1d, speye(nbVarPos)); %Discrete nD - -%Construct Su and Sx matrices (transfer matrices in batch LQR) -Su = zeros(nbVar*nbData, nbVarPos*(nbData-1)); -Sx = kron(ones(nbData,1),eye(nbVar)); -M = B; -for n=2:nbData - %Build Sx matrix - id1 = (n-1)*nbVar+1:nbData*nbVar; - Sx(id1,:) = Sx(id1,:) * A; - %Build Su matrix - id1 = (n-1)*nbVar+1:n*nbVar; - id2 = 1:(n-1)*nbVarPos; - Su(id1,id2) = M; - M = [A*M(:,1:nbVarPos), M]; -end - - -%% Probabilistic movement primitives with Fourier basis functions -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% t = linspace(0, 4*pi, nbData); -% MuTmp = [fft(cos(t) + .4 * cos(t*2+pi/3)); fft(sin(t))]; -% MuTmp = [ifft(MuTmp(1,:)); ifft(MuTmp(2,:))]; -% MuQ = MuTmp(:); -% Q = eye(nbVar*nbData); - -%Generate periodic data -nbSamples = 4; %Number of demonstrations -for n=1:nbSamples - t = linspace(2*n/3, 4*pi+2*n/3, nbData); - xtmp = (1+n.*1E-2) .* [cos(t); sin(t)] + (.7+n.*1E-2) .* [zeros(1,nbData); cos(t*2-pi/3)] + randn(nbVar,nbData) .* 1E-2; - x(:,n) = xtmp(:); -end - -%Compute basis functions Psi and activation weights w -k = -5:5; -% nbFct = length(k); -t = linspace(0, 1, nbData); -phi = exp(t' * k * 2 * pi * 1i) ./ nbData; -Psi = kron(phi, eye(nbVar)); - -% w = (Psi' * Psi + eye(nbFct).*1E-18) \ Psi' * x; -w = pinv(Psi) * x; - -%Distribution in parameter space -Mu_R = mean(abs(w), 2); %Magnitude average -Mu_theta = mean_angle(angle(w), 2); %Phase average -Mu_w = Mu_R .* exp(1i * Mu_theta); %Reconstruction - -Sigma_R = cov(abs(w')); %Magnitude spread -Sigma_theta = cov_angle(angle(w')); %Phase spread - -% %Remove correlations -% Sigma_R = diag(diag(Sigma_R)); -% Sigma_theta = diag(diag(Sigma_theta)); - -Sigma_w = Sigma_R .* exp(1i * Sigma_theta); %+ eye(size(Sigma_R)) * 1E-4; %Reconstruction - -% % [V_R, D_R] = eig(Sigma_R); -% % [V_theta, D_theta] = eig(Sigma_theta); -% % U_R = V_R * D_R.^.5; -% % U_theta = V_theta * D_theta.^.5; -% U_R = sqrtm(Sigma_R); -% U_theta = sqrtm(Sigma_theta); -% U_w = U_R .* exp(1i * U_theta) -% Sigma_w = U_w * U_w'; - - -MuQ = Psi * Mu_w; -Q = Psi / Sigma_w * Psi'; - - -%% Reproduction -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% x0 = zeros(nbVarPos,1); -x0 = x(11:12,1); %[10; 0]; -u = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - Sx*x0)); -rx = reshape(Sx*x0+Su*u, nbVar, nbData); - -% uSigma = inv(Rq) .* 1E-1; -% xSigma = Su * uSigma * Su'; - - -%% 2D Plots -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% rxi = imag(rx); -rx = real(rx); -figure('position',[10,10,2300,1200]); -subplot(2,2,[1,3]); hold on; axis off; -for n=1:nbSamples - plot(x(1:2:end,n), x(2:2:end,n), '-','linewidth',4,'color',[.7,.7,.7]); -end -plot(MuQ(1:2:end), MuQ(2:2:end), '-','linewidth',4,'color',[.8 0 0]); -plot(rx(1,:), rx(2,:), '-','linewidth',4,'color',[0,0,0]); -plot(rx(1,1), rx(2,1), '.','markersize',28,'color',[0,0,0]); -% plot(rxi(1,:), rxi(2,:), ':','linewidth',4,'color',[0,0,0]); -axis equal; - -%Timeline Plots -for j=1:2 - subplot(2,2,2*(j-1)+2); hold on; %axis off; - for n=1:nbSamples - plot(1:nbData, x(j:2:end,n), '-','linewidth',3,'color',[.7,.7,.7]); - end -% %Plot uncertainty -% id = j:nbVar:nbVar*nbData; -% S = diag(xSigma(id,id)); -% patch([1:nbData nbData:-1:1], [rx(j,:)-S(:)' fliplr(rx(j,:)+S(:)')], [.8 0 0],'edgecolor',[.6 0 0],'facealpha', .2, 'edgealpha', .2); -% plot(1:nbData, rxi(j,:), ':','linewidth',4,'color',[0 0 0]); - plot(1:nbData, rx(j,:), '-','linewidth',4,'color',[0 0 0]); - plot(1:nbData, MuQ(j:2:end), '-','linewidth',4,'color',[.8 0 0]); - - set(gca,'xtick',[],'ytick',[]); - xlabel('$t$','interpreter','latex','fontsize',34); - ylabel(['$x_' num2str(j) '$'],'interpreter','latex','fontsize',34); -end - -% print('-dpng','graphs/MPC_MP02.png'); -pause; -close all; -end - -%%%%%%%%%%%%%%%%%% -function Mu = mean_angle(phi, dim) - if nargin<2 - dim = 1; - end - Mu = angle(mean(exp(1i*phi), dim)); -end - -%%%%%%%%%%%%%%%%%% -function Sigma = cov_angle(phi) - Mu = mean_angle(phi); - e = phi - repmat(Mu, size(phi,1), 1); - Sigma = cov(angle(exp(1i*e))); -end \ No newline at end of file diff --git a/demos/demo_MPC_infHor_bicopter01.m b/demos/demo_MPC_infHor_bicopter01.m deleted file mode 100644 index 7ceee4c39b7e4c326997fcd3265d5a0c4ba8305c..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_infHor_bicopter01.m +++ /dev/null @@ -1,310 +0,0 @@ -function demo_MPC_infHor_bicopter01 -% Infinite horizon LQR applied on a planar UAV with an iterative linearization of the system plant. -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19chapter, -% author="Calinon, S. and Lee, D.", -% title="Learning Control", -% booktitle="Humanoid Robotics: a Reference", -% publisher="Springer", -% editor="Vadakkepat, P. and Goswami, A.", -% year="2019", -% pages="1261--1312", -% doi="10.1007/978-94-007-6046-2_68" -% } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Antonio Paolillo and Sylvain Calinon -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -close all; -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbData = 400; %Number of datapoints -nbIter = 1; %Number of reproductions - -model.nbVarPos = 3; %Dimension of position data (here: x1,x2) -model.nbDeriv = 2; %Number of static & dynamic features (D=2 for [x,dx]) -model.nbVarX = model.nbVarPos * model.nbDeriv; %Dimension of state vector in the tangent space -model.nbVarU = 2; -model.dt = 1E-2; %Time step duration -model.rfactor = 0.5; %Control cost in LQR - -% UAV parameters -robot.m = 2.5; % mass [kg] -robot.g = 9.81; % gravity acceleration [m/s^2] -robot.l = 0.5; % arms length [m] -robot.I = 1.2; % inertia [kg*m^2] - -% Control cost matrix -R = eye(model.nbVarU) * model.rfactor; - -%Task description -model.Mu = [2; 5; 0; zeros(model.nbVarPos,1)]; -model.Sigma = blkdiag(eye(model.nbVarPos-1).*1E-2, 1E-1,eye(model.nbVarPos).*1E1); - -% Control input at the reference point -u0 = 0.5 * robot.m * robot.g * ones(2,1); - -animation = true; - -% Waitbar -h_bar = waitbar(0, '0.00%','name','PROGRESS'); - - -%% iLQR reproduction -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -for n=1:nbIter - u = zeros(model.nbVarU, 1); - x = zeros(model.nbVarX, 1); - for t=1:nbData - - frac = t / nbData; - waitbar(frac, h_bar, sprintf ('Iteration n. %d of %d: %.2f%%', n, nbIter, 100*frac)); - - % Log data for plots - r(n).x(:,t) = x; - r(n).u(:,t) = u; - r(n).time(t) = t*model.dt; - - % Simulate UAV motion - % 1- Update the system (acceleration) - ddx = dynSys(x, u, robot); - - % 2- Update velocity (integration) - x(model.nbVarPos+1:end) = x(model.nbVarPos+1:end) + ddx .* model.dt; - % 3- Update position (integration) - x(1:model.nbVarPos) = x(1:model.nbVarPos) + x(model.nbVarPos+1:end) .* model.dt; - - % Linearization of the system plant around the reference point - [A, B] = computeTransferMatrices(model.Mu, u0, model, robot); - % Linearization of the system plant around the current point - %[A, B] = computeTransferMatrices(x, u, model, robot); - - % Iterative discrete LQR with infinite horizon - % 1- Compute precision matrix - Q = inv(model.Sigma); - % 2- Solve Riccati's equation - P = solveAlgebraicRiccati_eig_discrete(A, B*(R\B'), (Q+Q')/2); - % 3- Compute the gain - L = (B'*P*B + R) \ B'*P*A; - - % Control law (steering method) - u = u0 + L * (model.Mu-x); - end -end - -close(h_bar) - -%% Animation -if animation - figure('name', 'animation'); - - subplot(2,2,[1 3]) - hold on - h1 = plot(zeros(1,nbData),zeros(1,nbData),'k--'); - h2 = plot(0,0,'r.','markersize',10); - h3 = plot( zeros(3,1), zeros(3,1), 'b.-', 'linewidth',2,'markersize',10); - h4 = plot(0,0,'k.','markersize',10,'linewidth',1.5); - - margin = robot.l + 0.1; - var = [r(end).x(1,:), model.Mu(1)]; - x_min = min(var) - margin; - x_max = max(var) + margin; - var = [r(end).x(2,:), model.Mu(2,:)]; - y_min = min(var) - margin; - y_max = max(var) + margin; - - axis([x_min x_max y_min y_max]) - xlabel('x [m]') - ylabel('y [m]') - axis equal; grid on; axis on; box on; - - subplot(2,2,2) - hold on; - h5 = plot(0,0,'k.','markersize',5,'linewidth',2); - h6 = plot(zeros(1,nbData), zeros(1,nbData),'k'); - var = r(end).u(1,:); margin = 0.05; - x_min = min(r(end).time(:)); x_max = max(r(end).time(:)); - margin = 0.1*abs(max(var)-min(var)); - y_min = min(var) - margin; - y_max = max(var) + margin; - axis([x_min x_max y_min y_max]); - axis on; grid on; box on; - xlabel('time [s]') - ylabel('u_1 [kg m s^{-2}]') - - subplot(2,2,4) - hold on; - h7 = plot(0,0,'k.','markersize',5,'linewidth',2); - h8 = plot(zeros(1,nbData), zeros(1,nbData),'k'); - var = r(end).u(2,:); margin = 0.05; - margin = 0.1*abs(max(var)-min(var)); - y_min = min(var) - margin; - y_max = max(var) + margin; - axis([x_min x_max y_min y_max]); - axis on; grid on; box on; - xlabel('time [s]') - ylabel('u_2 [kg m s^{-2}]') - - for i=1:nbData - tic - x_left = [r(end).x(1,i)-robot.l*cos(r(end).x(3,i)); r(end).x(2,i)-robot.l*sin(r(end).x(3,i))]; - x_right= [r(end).x(1,i)+robot.l*cos(r(end).x(3,i)); r(end).x(2,i)+robot.l*sin(r(end).x(3,i))]; - set(h1, 'xdata', [zeros(1,nbData-i),r(end).x(1,1:i)], 'ydata', [zeros(1,nbData-i),r(end).x(2,1:i)]); - set(h2, 'xdata', model.Mu(1), 'ydata', model.Mu(2)); - set(h3, 'xdata', [x_left(1); r(end).x(1,i); x_right(1)],'ydata',[x_left(2); r(end).x(2,i); x_right(2)]) - set(h4, 'xdata', r(end).x(1,1),'ydata',r(end).x(2,1)); - set(h5, 'xdata', r(end).time(i), 'ydata', r(end).u(1,i)); - set(h6, 'xdata', [zeros(1,nbData-i),r(end).time(1:i)], 'ydata', [zeros(1,nbData-i),r(end).u(1,1:i)]); - set(h7, 'xdata', r(end).time(i), 'ydata', r(end).u(2,i)); - set(h8, 'xdata', [zeros(1,nbData-i),r(end).time(1:i)], 'ydata', [zeros(1,nbData-i),r(end).u(2,1:i)]); - drawnow() - pause(model.dt - 0.001*toc) - if i==1 || i==nbData - pause(2) - end - end -end - -%% Plot 2D -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%figure('position',[10 10 700 700],'color',[1 1 1],'name','x1-x2 plot'); -figure('name', 'trajectory') -hold on; axis on; grid on; box on; -plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [1 0 0], .5); -plot(model.Mu(1), model.Mu(2), 'r.','markersize',15); -%Plot reproduction samples -x_min = 0; -x_max = 0; -y_min = 0; -y_max = 0; -for n=1:nbIter - plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',2,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - plot(r(n).x(1,1), r(n).x(2,1), '.','markersize',15,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - var = [r(n).x(1,:), model.Mu(1)]; - margin = 0.1 * abs(min(var)-max(var)); - if min(var) - margin < x_min - x_min = min(var) - margin; - end - if max(var) + margin > x_max - x_max = max(var) + margin; - end - var = [r(n).x(2,:), model.Mu(2,:)]; - margin = 0.1 * abs(min(var)-max(var)); - if min(var) - margin < y_min - y_min = min(var) - margin; - end - if max(var) + margin > y_max - y_max = max(var) + margin; - end -end -axis([x_min x_max y_min y_max]) -xlabel('x [m]') -ylabel('y [m]') -axis equal; - - -%% Timeline plot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -labList = {'$x_1$','$x_2$','$x_3$','$\dot{x}_1$','$\dot{x}_2$','$\dot{x}_3$'}; -%figure('position',[720 10 1000 1300],'color',[1 1 1]); -figure('name', 'system state') -for j=1:model.nbVarX - subplot(model.nbVarX,1,j); - axis on; grid on; hold on; box on; - if j>model.nbVarPos - plot([1,nbData],[0,0],':','color',[.5 .5 .5]); - end - %Plot reproduction samples - for n=1:nbIter - plot(r(n).x(j,:), '-','linewidth',1,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - end - ylabel(labList{j},'fontsize',14,'interpreter','latex'); -end -xlabel('$t$','fontsize',14,'interpreter','latex'); -% control input -figure('name','system input') -for j=1:model.nbVarU - subplot(model.nbVarU,1,j); - axis on; grid on; hold on; box on; - %Plot reproduction samples - for n=1:nbIter - plot(r(n).u(j,:), '-','linewidth',1,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - end - ylabel(['$u_' num2str(j) '$'],'fontsize',14,'interpreter','latex'); -end -xlabel('$t$','fontsize',14,'interpreter','latex'); - -end - - -%%%%%%%%%%%%%%%%% -function f = dynSys(x,u,robot) - m = robot.m; - g = robot.g; - l = robot.l; - I = robot.I; - - f = zeros(3,1); - - f(1,1) = -m.^-1 .* (u(1) + u(2)) .* sin(x(3)); %ddx - f(2,1) = m.^-1 .* (u(1) + u(2)) .* cos(x(3)) - g; %ddy - f(3,1) = l/I .* (u(1) - u(2)); %ddt -end - -%%%%%%%%%%%%%%%%% -function [A, B] = computeTransferMatrices(x, u, model, robot) - m = robot.m; - l = robot.l; - I = robot.I; - - dfdx = zeros(3,1); - dfdy = zeros(3,1); - dfdt = zeros(3,1); - dfdu1 = zeros(3,1); - dfdu2 = zeros(3,1); - - dfdx(1) = 0; - dfdx(2) = 0; - dfdx(3) = 0; - - dfdy(1) = 0; - dfdy(2) = 0; - dfdy(3) = 0; - - dfdt(1) = -m.^-1 .* (u(1) + u(2)) .* cos(x(3)); %*dx? - dfdt(2) = -m.^-1 .* (u(1) + u(2)) .* sin(x(3)); %*dx? - dfdt(3) = 0; - - dfdu1(1) = -m.^-1 .* sin(x(3)); - dfdu1(2) = m.^-1 .* cos(x(3)); - dfdu1(3) = l/I; - - dfdu2(1) = -m.^-1 .* sin(x(3)); - dfdu2(2) = m.^-1 .* cos(x(3)); - dfdu2(3) = -l/I; - - Ac = [zeros(model.nbVarPos), eye(model.nbVarPos); [dfdx, dfdy, dfdt], zeros(model.nbVarPos)]; - Bc = [zeros(model.nbVarPos,model.nbVarU); [dfdu1, dfdu2]]; - - %Conversion to discrete linear system - A = eye(model.nbVarX) + Ac * model.dt; - B = Bc * model.dt; -end \ No newline at end of file diff --git a/demos/demo_MPC_infHor_incremental01.m b/demos/demo_MPC_infHor_incremental01.m deleted file mode 100644 index 409116ba4dcf05c360f4fac9cc7d3e3d7c20d422..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_infHor_incremental01.m +++ /dev/null @@ -1,183 +0,0 @@ -function demo_MPC_infHor_incremental01 -% Infinite horizon LQR with an iterative re-estimation of the system plant linear system (example with planar UAV). -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19chapter, -% author="Calinon, S. and Lee, D.", -% title="Learning Control", -% booktitle="Humanoid Robotics: a Reference", -% publisher="Springer", -% editor="Vadakkepat, P. and Goswami, A.", -% year="2019", -% pages="1261--1312", -% doi="10.1007/978-94-007-6046-2_68" -% } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon and Danilo Bruno -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbData = 300; %Number of datapoints -nbIter = 1; %Number of reproductions - -model.nbVarPos = 3; %Dimension of position data (here: x=x1,x2,theta) -model.nbDeriv = 2; %Number of derivatives for the state space -model.nbVarX = model.nbVarPos * model.nbDeriv; %Dimension of state space (here: [x,dx]) -model.nbVarU = 2; %Dimension of control command (here: force of two propellers) -model.dt = 1E-2; %Time step duration -model.rfactor = 1E-4; %Control cost in LQR - -%Control cost matrix -R = eye(model.nbVarU) * model.rfactor; - - -%% Task description -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -model.Mu = [1; 1; 0; zeros(model.nbVarPos,1)]; -model.Sigma = blkdiag(eye(model.nbVarPos).*1E-2, eye(model.nbVarPos).*1E-1); -Q = inv(model.Sigma); %Precision matrix -u00 = repmat(0.5 * 2.5 * 9.81, 2, 1); - - -%% iLQR reproduction -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -for n=1:nbIter - u = zeros(model.nbVarU, 1); - x = zeros(model.nbVarX, 1); - for t=1:nbData - %Log data - r(n).x(:,t) = x; - r(n).u(:,t) = u; - - %Simulation - ddx = dynSys(x, u); %Compute acceleration - x(model.nbVarPos+1:end) = x(model.nbVarPos+1:end) + ddx .* model.dt; %Update velocity - x(1:model.nbVarPos) = x(1:model.nbVarPos) + x(model.nbVarPos+1:end) .* model.dt; %Update position - - %Linearization of system plant - u1 = 0.5 * ( (2.5*(ddx(2)+9.81))/cos(x(3)) + (1.2*ddx(3))/0.5 ); - u2 = 0.5 * ( (2.5*(ddx(2)+9.81))/cos(x(3)) - (1.2*ddx(3))/0.5 ); - [A, B] = computeTransferMatrices(x, [u1; u2], model); - - %Iterative discrete LQR with infinite horizon - P = solveAlgebraicRiccati_eig_discrete(A, B*(R\B'), (Q+Q')/2); - L = (B'*P*B + R) \ B'*P*A; %Feedback gain (discrete version) - u = L * (model.Mu-x) + u00; %Compute acceleration (with only feedback terms) -% x = A*x + B*u; - end -end - - -%% Plot 2D -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 700 700],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; -plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [.8 0 0], .5); -plot(model.Mu(1,:), model.Mu(2,:), '.','markersize',20,'color',[.8 0 0]); -%Plot reproduction samples -for n=1:nbIter - plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',2,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - plot(r(n).x(1,1), r(n).x(2,1), '.','markersize',20,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); -end -axis equal; - - -%% Timeline plot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -labList = {'$x_1$','$x_2$','$x_3$','$\dot{x}_1$','$\dot{x}_2$','$\dot{x}_3$'}; -figure('position',[720 10 1000 1300],'color',[1 1 1]); -for j=1:model.nbVarX - subplot(model.nbVarX+model.nbVarU,1,j); hold on; - plot([1,nbData],[model.Mu(j) model.Mu(j)],':','color',[.5 .5 .5]); - %Plot reproduction samples - for n=1:nbIter - plot(r(n).x(j,:), '-','linewidth',1,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - end - ylabel(labList{j},'fontsize',14,'interpreter','latex'); -end -for j=1:model.nbVarU - subplot(model.nbVarX+model.nbVarU,1,model.nbVarX+j); hold on; - %Plot reproduction samples - for n=1:nbIter - plot(r(n).u(j,:), '-','linewidth',1,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - end - ylabel(['$u_' num2str(j) '$'],'fontsize',14,'interpreter','latex'); -end -xlabel('$t$','fontsize',14,'interpreter','latex'); - -pause; -close all; -end - -%%%%%%%%%%%%%%%%% -function f = dynSys(x,u) - m = 2.5; - g = 9.81; - l = 0.5; - I = 1.2; - f = zeros(3,1); - f(1,1) = -m.^-1 .* (u(1) + u(2)) .* sin(x(3)); %ddx - f(2,1) = m.^-1 .* (u(1) + u(2)) .* cos(x(3)) - g; %ddy - f(3,1) = l/I .* (u(1) - u(2)); %ddt -end - -%%%%%%%%%%%%%%%%% -function [A, B] = computeTransferMatrices(x, u, model) - m = 2.5; -% g = 9.81; - l = 0.5; - I = 1.2; - - %syms x; - dfdx = zeros(3,1); - dfdy = zeros(3,1); - dfdt = zeros(3,1); - dfdu1 = zeros(3,1); - dfdu2 = zeros(3,1); - -% f = dynSys(x(:,t), u(:,t)); - - dfdx(1) = 0; - dfdx(2) = 0; - dfdx(3) = 0; - - dfdy(1) = 0; - dfdy(2) = 0; - dfdy(3) = 0; - - dfdt(1) = -m.^-1 .* (u(1) + u(2)) .* cos(x(3)); %*dx? - dfdt(2) = -m.^-1 .* (u(1) + u(2)) .* sin(x(3)); %*dx? - dfdt(3) = 0; - - dfdu1(1) = -m.^-1 .* sin(x(3)); - dfdu1(2) = m.^-1 .* cos(x(3)); - dfdu1(3) = l/I; - - dfdu2(1) = -m.^-1 .* sin(x(3)); - dfdu2(2) = m.^-1 .* cos(x(3)); - dfdu2(3) = -l/I; - - Ac = [zeros(model.nbVarPos), eye(model.nbVarPos); [dfdx, dfdy, dfdt], zeros(model.nbVarPos)]; - Bc = [zeros(model.nbVarPos,model.nbVarU); [dfdu1, dfdu2]]; - - %Conversion to discrete linear system - A = eye(model.nbVarX) + Ac * model.dt; - B = Bc * model.dt; -end \ No newline at end of file diff --git a/demos/demo_MPC_infHor_incremental02.m b/demos/demo_MPC_infHor_incremental02.m deleted file mode 100644 index f76814f7db5b7a8d40126bee5578a7ad7f59eb82..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_infHor_incremental02.m +++ /dev/null @@ -1,166 +0,0 @@ -function demo_MPC_infHor_incremental02 -% Infinite horizon LQR with an iterative re-estimation of the system plant linear system (example with pendulum). -% (similar example as in "LQR-RRT∗: Optimal Sampling-Based Motion Planning with Automatically Derived Extension Heuristics") -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19chapter, -% author="Calinon, S. and Lee, D.", -% title="Learning Control", -% booktitle="Humanoid Robotics: a Reference", -% publisher="Springer", -% editor="Vadakkepat, P. and Goswami, A.", -% year="2019", -% pages="1261--1312", -% doi="10.1007/978-94-007-6046-2_68" -% } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon and Danilo Bruno -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbData = 200; %Number of datapoints -nbIter = 1; %Number of reproductions - -model.nbVarPos = 1; %Dimension of position data (here: q) -model.nbDeriv = 2; %Number of derivatives for the state space -model.nbVarX = model.nbVarPos * model.nbDeriv; %Dimension of state space (here: [q,dq]) -model.nbVarU = 1; %Dimension of control command (here: torque) -model.dt = 1E-2; %Time step duration -model.rfactor = 1E-4; %Control cost in LQR - -%Control cost matrix -R = eye(model.nbVarU) * model.rfactor; - - -%% Task description -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -model.Mu = [pi/2; 0]; %pi/2 -model.Sigma = diag([1E-2, 1E-1]); -Q = inv(model.Sigma); %Precision matrix - - -%% iLQR reproduction -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -for n=1:nbIter - u = 0; - x = [-pi/2; 0]; - - for t=1:nbData - %Log data - r(n).x(:,t) = x; - - %Simulation - ddx = dynSys(x, u); %Compute acceleration - x(2) = x(2) + ddx .* model.dt; %Update velocity - x(1) = x(1) + x(2) .* model.dt; %Update position - - %Linearization of system plant - [A, B] = computeTransferMatrices(x, model); - - %Iterative discrete LQR with infinite horizon - P = solveAlgebraicRiccati_eig_discrete(A, B*(R\B'), (Q+Q')/2); - K = (B'*P*B + R) \ B'*P*A; %Feedback gain (discrete version) - u = K * (model.Mu - x); %Compute acceleration (with only feedback terms) -% x = A*x + B*u; - - r(n).c(t) = (model.Mu-x)'*Q*(model.Mu-x) + u'*R*u; %Value of the cost function - r(n).u(:,t) = u; - end -end - - -%% Plot 2D -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 700 700],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; -plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [.8 0 0], .5); -plot(model.Mu(1,:), model.Mu(2,:), '.','markersize',20,'color',[.8 0 0]); -%Plot reproduction samples -for n=1:nbIter - plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',2,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - plot(r(n).x(1,1), r(n).x(2,1), '.','markersize',20,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); -end -axis equal; - - -%% Timeline plot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -labList = {'$x_1$','$x_2$','$x_3$','$\dot{x}_1$','$\dot{x}_2$','$\dot{x}_3$'}; -figure('position',[720 10 1000 1300],'color',[1 1 1]); -for j=1:model.nbVarX - subplot(model.nbVarX+model.nbVarU,1,j); hold on; - plot([1,nbData],[model.Mu(j) model.Mu(j)],':','color',[.5 .5 .5]); - %Plot reproduction samples - for n=1:nbIter - plot(r(n).x(j,:), '-','linewidth',1,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - end - ylabel(labList{j},'fontsize',14,'interpreter','latex'); -end -for j=1:model.nbVarU - subplot(model.nbVarX+model.nbVarU,1,model.nbVarX+j); hold on; - %Plot reproduction samples - for n=1:nbIter - plot(r(n).u(j,:), '-','linewidth',1,'color',ones(1,3)-ones(1,3).*.8.*n./nbIter); - end - ylabel(['$u_' num2str(j) '$'],'fontsize',14,'interpreter','latex'); -end -xlabel('$t$','fontsize',14,'interpreter','latex'); - - -%% Animated plot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('PaperPosition',[0 0 8 8],'position',[10,10,1000,1000],'color',[1 1 1]); hold on; axis off; -plotArm(model.Mu(1), 1, [0;0;0], .03, [.8 0 0]); -for t=round(linspace(1,nbData,20)) - colTmp = [.9,.9,.9] - [.7,.7,.7] * t/nbData; - plotArm(r(1).x(1,t), 1, [0;0;t*0.1], .02, colTmp); -end -axis equal; - -figure; hold on; -plot(r(1).c,'k-'); - -pause; -close all; -end - -%%%%%%%%%%%%%%%%% -function f = dynSys(x,u) - b = 0.1; - g = 9.81; - f = u - b .* x(2,:) - g .* cos(x(1,:)); -end - -%%%%%%%%%%%%%%%%% -function [A, B] = computeTransferMatrices(x, model) - b = 0.1; - g = 9.81; - - dfdx = g .* sin(x(1,:)); - dfddx = -b; - dfdu = 1; - - Ac = [0, 1; dfdx, dfddx]; - Bc = [0; dfdu]; - - %Conversion to discrete linear system - A = eye(model.nbVarX) + Ac * model.dt; - B = Bc * model.dt; -end \ No newline at end of file diff --git a/demos/demo_MPC_iterativeLQR04.m b/demos/demo_MPC_iterativeLQR04.m deleted file mode 100644 index 6f90751747d8093d6a2c7ec7e1e244593e7eb1ea..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_iterativeLQR04.m +++ /dev/null @@ -1,123 +0,0 @@ -function demo_MPC_iterativeLQR04 -% Control of a spring attached to a point with linear quadratic tracking (with feedback and feedforward terms using the recursive formulation). -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19chapter, -% author="Calinon, S. and Lee, D.", -% title="Learning Control", -% booktitle="Humanoid Robotics: a Reference", -% publisher="Springer", -% editor="Vadakkepat, P. and Goswami, A.", -% year="2019", -% pages="1261--1312", -% doi="10.1007/978-94-007-6046-2_68" -% } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon, http://calinon.ch/ -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbVarPos = 2; %Dimension of position data (here: x1,x2) -nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) -nbVar = nbVarPos * (nbDeriv+1); %Dimension of state vector -dt = 1E-2; %Time step duration -rfactor = 1E-4; %Control cost in LQR -kP = 0; %Stiffness gain (initial estimate) -kV = (2*kP)^.5; %Damping gain (with ideal underdamped damping ratio) -%kV = 2*kP^.5; %Damping (for critically damped system) - -nbRepros = 5; %Number of reproductions -nbData = 200; %Number of datapoints - - -%% Dynamical System settings (discrete version) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Dynamical System settings (discrete version) -Ac = kron([0, 1, 0; -kP, -kV, kP; 0, 0, 0], eye(nbVarPos)); -A = eye(nbVar) + Ac * dt; -B = kron([dt^2/2; dt; 0], eye(nbVarPos)); -%Control cost matrix -R = eye(nbVarPos) * rfactor; - - -%% Setting tracking task -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -xTar = [0; 3]; %Equilibrium point of the spring -Mu = [zeros(nbVarPos,1); zeros(nbVarPos,1); xTar]; -Gamma = blkdiag(eye(nbVarPos)*1E1, zeros(nbVarPos), zeros(nbVarPos)); - - -%% Iterative LQR reproduction (finite horizon, discrete version) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -P = zeros(nbVar,nbVar,nbData); -P(:,:,end) = Gamma; -d = zeros(nbVar, nbData); -Q = Gamma; - -%Backward computation -for t=nbData-1:-1:1 - P(:,:,t) = Q - A' * (P(:,:,t+1) * B / (B' * P(:,:,t+1) * B + R) * B' * P(:,:,t+1) - P(:,:,t+1)) * A; - d(:,t) = (A' - A' * P(:,:,t+1) * B / (R + B' * P(:,:,t+1) * B) * B' ) * (P(:,:,t+1) * (A * Mu - Mu) + d(:,t+1)); -end - -%Reproduction with feedback (FB) and feedforward (FF) terms -for n=1:nbRepros - X = [10; 10; zeros(2,1); xTar] + [randn(2,1)*3E0; zeros(4,1)]; - r(n).X0 = X; - for t=1:nbData - r(n).Data(:,t) = X; %Log data - K = (B' * P(:,:,t) * B + R) \ B' * P(:,:,t) * A; %FB gain - -% %Test ratio between kp and kv -% kp = eigs(K(:,1:2)); -% kv = eigs(K(:,3:4)); -% ratio = kv ./ (2.*kp).^.5 - -% figure; hold on; -% plotGMM(zeros(2,1), K(:,1:2), [.8 0 0],.3); -% plotGMM(zeros(2,1), K(:,3:4), [.8 0 0],.3); -% axis equal; -% pause; -% close all; - - M = -(B' * P(:,:,t) * B + R) \ B' * (P(:,:,t) * (A * Mu - Mu) + d(:,t)); %FF term - u = K * (Mu - X) + M; %Acceleration command with FB and FF terms - X = A * X + B * u; %Update of state vector - end -end - - -%% Plot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1200 1200],'color',[1 1 1]); hold on; axis off; -for n=1:nbRepros - plot(r(n).Data(1,:), r(n).Data(2,:), '-','linewidth',1,'color',[.8 0 0]); - plot(r(n).Data(1,:), r(n).Data(2,:), '.','markersize',6,'color',[.6 0 0]); -end -%plotGMM(Mu(1:2,:), Sigma(1:2,1:2,:), [0.5 0.5 0.5]); -h(1) = plot(Mu(1,:), Mu(2,:), 'k.','markersize',20, 'color', [0.5 0.5 0.5]); -h(2) = plot(xTar(1),xTar(2),'k+','markersize',20,'linewidth',2); -legend(h,{'Target to reach','Equilibrium point of the spring'}); -axis equal; - -%print('-dpng','graphs/demo_iterativeLQR04.png'); -pause; -close all; \ No newline at end of file diff --git a/demos/demo_MPC_iterativeLQR_augmSigma_online01.m b/demos/demo_MPC_iterativeLQR_augmSigma_online01.m deleted file mode 100644 index ffdb1e2489ba1f44609486cff42ae736418df72c..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_iterativeLQR_augmSigma_online01.m +++ /dev/null @@ -1,159 +0,0 @@ -function demo_MPC_iterativeLQR_augmSigma_online01 -% Recursive LQR with augmented covariance to transform the tracking problem to a regulation problem, recomputed in an online manner. -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19chapter, -% author="Calinon, S. and Lee, D.", -% title="Learning Control", -% booktitle="Humanoid Robotics: a Reference", -% publisher="Springer", -% editor="Vadakkepat, P. and Goswami, A.", -% year="2019", -% pages="1261--1312", -% doi="10.1007/978-94-007-6046-2_68" -% } -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon, http://calinon.ch/ -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbSamples = 5; %Number of demonstrations -nbRepros = 1; %Number of reproductions -nbData = 100; %Number of datapoints -nbD = 20; %Time window for LQR computation - -model.nbStates = 5; %Number of Gaussians in the GMM -model.nbVarPos = 2; %Dimension of position data (here: x1,x2) -model.nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) -model.nbVar = model.nbVarPos * model.nbDeriv; %Dimension of state vector -model.dt = 0.01; %Time step duration -model.rfactor = 1E-6; %Control cost in LQR - -%Control cost matrix -R = eye(model.nbVarPos) * model.rfactor; - - -%% Dynamical System settings (discrete version) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Integration with higher order Taylor series expansion -A1d = zeros(model.nbDeriv); -for i=0:model.nbDeriv-1 - A1d = A1d + diag(ones(model.nbDeriv-i,1),i) * model.dt^i * 1/factorial(i); %Discrete 1D -end -B1d = zeros(model.nbDeriv,1); -for i=1:model.nbDeriv - B1d(model.nbDeriv-i+1) = model.dt^i * 1/factorial(i); %Discrete 1D -end -A0 = kron(A1d, eye(model.nbVarPos)); %Discrete nD -B0 = kron(B1d, eye(model.nbVarPos)); %Discrete nD - -A = [A0, zeros(model.nbVar,1); zeros(1,model.nbVar), 1]; %Augmented A -B = [B0; zeros(1,model.nbVarPos)]; %Augmented B - - -%% Load handwriting data -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -load('data/2Dletters/A.mat'); -Data=[]; -for n=1:nbSamples - s(n).Data=[]; - for m=1:model.nbDeriv - if m==1 - dTmp = spline(1:size(demos{n}.pos,2), demos{n}.pos, linspace(1,size(demos{n}.pos,2),nbData)); %Resampling - else - dTmp = gradient(dTmp) / model.dt; %Compute derivatives - end - s(n).Data = [s(n).Data; dTmp]; - end - Data = [Data s(n).Data]; -end - - -%% Learning -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -model = init_GMM_kbins(Data,model,nbSamples); -[model, H] = EM_GMM(Data, model); - -%Transform model to the corresponding version with augmented covariance -model0 = model; -model.nbVar = model0.nbVar+1; -model.Mu = zeros(model.nbVar, model.nbStates); -model.Sigma = zeros(model.nbVar, model.nbVar, model.nbStates); -for i=1:model.nbStates - model.Sigma(:,:,i) = [model0.Sigma(:,:,i)+model0.Mu(:,i)*model0.Mu(:,i)', model0.Mu(:,i); model0.Mu(:,i)', 1]; -end - - -%% Iterative LQR with augmented state space, recomputed in an online manner -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -tic -for n=1:nbRepros - X = [Data(:,1); 1]; - for t=1:nbData - r(n).Data(:,t) = X; %Log data - %Set list of states according to first demonstration (alternatively, an HSMM can be used) - id = [t:min(t+nbD-1,nbData), repmat(nbData,1,t-nbData+nbD-1)]; - [~,q] = max(H(:,id),[],1); %works also for nbStates=1 - %Riccati equation - P = zeros(model.nbVar,model.nbVar,nbD); - P(:,:,end) = inv(model.Sigma(:,:,q(end))); - for s=nbD-1:-1:1 - Q = inv(model.Sigma(:,:,q(s))); - P(:,:,s) = Q - A' * (P(:,:,s+1) * B / (B' * P(:,:,s+1) * B + R) * B' * P(:,:,s+1) - P(:,:,s+1)) * A; - end - K = (B' * P(:,:,1) * B + R) \ B' * P(:,:,1) * A; %FB gain - u = -K * X; %Acceleration command with FB terms on augmented state (resulting in FB and FF terms) - X = A * X + B * u; %Update of state vector - end -end -toc - -%% Plot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Plot position -figure('position',[10 10 1000 1000],'color',[1 1 1]); hold on; -plotGMM(model0.Mu(1:2,:), model0.Sigma(1:2,1:2,:), [0.5 0.5 0.5], .3); -for n=1:nbSamples - plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]); -end -for n=1:nbRepros - h(1) = plot(r(n).Data(1,:), r(n).Data(2,:), '-','linewidth',2,'color',[.8 0 0]); -end -axis equal; -xlabel('x_1'); ylabel('x_2'); - -% %Plot velocity -% figure('position',[1020 10 1000 1000],'color',[1 1 1]); hold on; -% plotGMM(model0.Mu(3:4,:), model0.Sigma(3:4,3:4,:), [0.5 0.5 0.5], .3); -% for n=1:nbSamples -% plot(Data(3,(n-1)*nbData+1:n*nbData), Data(4,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]); -% end -% for n=1:nbRepros -% plot(r(n).Data(3,:), r(n).Data(4,:), '-','linewidth',2,'color',[.8 0 0]); -% plot(r(n).Data(3,1), r(n).Data(4,1), '.','markersize',18,'color',[.6 0 0]); -% end -% plot(0,0,'k+'); -% axis equal; -% xlabel('dx_1'); ylabel('dx_2'); - -%print('-dpng','graphs/demo_iterativeLQR_augmSigma_online01.png'); -pause; -close all; \ No newline at end of file diff --git a/demos/demo_MPC_robot01.m b/demos/demo_MPC_robot01.m deleted file mode 100644 index ba1b8c9a8403d84b6fb039699736eb12b7f7a325..0000000000000000000000000000000000000000 --- a/demos/demo_MPC_robot01.m +++ /dev/null @@ -1,198 +0,0 @@ -function demo_MPC_robot01 -% Robot manipulator tracking task with MPC, by relinearization of the system plant at each time step. -% -% If this code is useful for your research, please cite the related publication: -% @incollection{Calinon19chapter, -% author="Calinon, S. and Lee, D.", -% title="Learning Control", -% booktitle="Humanoid Robotics: a Reference", -% publisher="Springer", -% editor="Vadakkepat, P. and Goswami, A.", -% year="2019", -% pages="1261--1312", -% doi="10.1007/978-94-007-6046-2_68" -% } -% -% The commented parts of this demo require the robotics toolbox RTB10 (http://petercorke.com/wordpress/toolboxes/robotics-toolbox). -% First run 'startup_rvc' from the robotics toolbox if you uncomment these parts. -% -% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon, http://calinon.ch/ -% -% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ -% -% PbDlib is free software: you can redistribute it and/or modify -% it under the terms of the GNU General Public License version 3 as -% published by the Free Software Foundation. -% -% PbDlib is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. - -addpath('./m_fcts/'); - - -%% Parameters -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbData = 50; %Number of datapoints in a trajectory -nbD = 10; %Time horizon -nbDOFs = 3; %Number of articulations - -model.nbStates = 1; %Number of Gaussians in the GMM -model.nbVarPos = 2; %Dimension of position data -model.nbDeriv = 1; %Number of static & dynamic features (D=2 for [x,dx]) -model.nbVarX = model.nbVarPos * model.nbDeriv; %Dimension of state space -model.nbVarU = nbDOFs; %Dimension of control space - -model.dt = 1E-3; %Time step duration -model.rfactor = 1E-2; %Control cost in LQR - -%Control cost matrix -R = eye(model.nbVarU) * model.rfactor; -R = kron(eye(nbD-1),R); - -%Robot description -model.l = 0.6; - -% L1 = Link('d', 0, 'a', model.l, 'alpha', 0); -% robot = SerialLink(repmat(L1,nbDOFs,1)); - - -%% Task description -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -model.Mu = ones(model.nbVarPos,1) * .7; -model.Sigma = eye(model.nbVarPos) * 1E-3; -MuQ = kron(ones(nbD,1), model.Mu); -Q = kron(eye(nbD), inv(model.Sigma)); - - -%% Online batch LQR with relinearization of the system plant -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -q = ones(nbDOFs,1) * 0.1; -% Htmp = robot.fkine(q); -% x = Htmp.t(1:model.nbVarPos); -x = fkine(q, model); - -for t=1:nbData -% [Su, Sx] = computeTransferMatrices(q, model, robot, nbD); %Linearization of system plant - [Su, Sx] = computeTransferMatrices(q, model, nbD); %Linearization of system plant - u = (Su' * Q * Su + R) \ Su' * Q * (MuQ - Sx * x); %Control trajectory - %Log data - r(1).q(:,t) = q; - r(1).x(:,t) = x; - r(1).u(:,t) = u(1:model.nbVarU); - %Update state - q = q + u(1:model.nbVarU) * model.dt; -% Htmp = robot.fkine(q); %Forward kinematics -% x = Htmp.t(1:model.nbVarPos); - x = fkine(q, model); -end - - -%% Plot 2D -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; -for t=round(linspace(1,nbData,2)) - colTmp = [.9,.9,.9] - [.7,.7,.7] * t/nbData; - plotArm(r(1).q(:,t), ones(nbDOFs,1)*model.l, [0;0;-10+t*0.1], .06, colTmp); -end -% plotArm(model.Mu, ones(nbDOFs,1)*model.l, [0;0;10], .02, [.8 0 0]); - -plotGMM(model.Mu, model.Sigma, [.8 0 0], .5); -plot(model.Mu(1,:), model.Mu(2,:), '.','markersize',20,'color',[.8 0 0]); -for n=1:1 - plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',2,'color',[0 0 0]); - plot(r(n).x(1,:), r(n).x(2,:), '.','markersize',12,'color',[.2 .2 .2]); -end -axis equal; - - -%% Timeline plot -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -labList = {'$x_1$','$x_2$','$\dot{x}_1$','$\dot{x}_2$'}; -figure('position',[830 10 800 800],'color',[1 1 1]); -for j=1:model.nbVarX - subplot(model.nbVarX+model.nbVarU,1,j); hold on; - plot([1,nbData],[model.Mu(j) model.Mu(j)],':','color',[.5 .5 .5]); - %Plot reproduction samples - for n=1:1 - plot(r(n).x(j,:), '-','linewidth',1,'color',[0 0 0]); - end - errorbar(nbData, model.Mu(j), model.Sigma(j,j)^.5, 'color',[.8 0 0]); - plot(nbData, model.Mu(j), '.','markersize',15,'color',[.8 0 0]); - ylabel(labList{j},'fontsize',14,'interpreter','latex'); -end -for j=1:model.nbVarU - subplot(model.nbVarX+model.nbVarU,1,model.nbVarX+j); hold on; - %Plot reproduction samples - for n=1:1 - plot(r(n).u(j,:), '-','linewidth',1,'color',[0 0 0]); - end - ylabel(['$u_' num2str(j) '$'],'fontsize',14,'interpreter','latex'); -end -xlabel('$t$','fontsize',14,'interpreter','latex'); - -%print('-dpng','graphs/demo_MPC_robot01.png'); -pause; -close all; -end - -%%%%%%%%%%%%%%%%%%%%%% -function [Su, Sx] = transferMatrices(A, B, nbD) - [nbVarX, nbVarU] = size(B); - Su = zeros(nbVarX*nbD, nbVarU*(nbD-1)); - Sx = kron(ones(nbD,1), eye(nbVarX)); - M = B; - for t=2:nbD - id1 = (t-1)*nbVarX+1:nbD*nbVarX; - Sx(id1,:) = Sx(id1,:) * A; - id1 = (t-1)*nbVarX+1:t*nbVarX; - id2 = 1:(t-1)*nbVarU; - Su(id1,id2) = M; - M = [A*M(:,1:nbVarU), M]; %Also M = [A^(n-1)*B, M] or M = [Sx(id1,:)*B, M] - end -end - -%%%%%%%%%%%%%%%%%%%%%% -% function [Su, Sx, A, B] = computeTransferMatrices(q, model, robot, nbD) -function [Su, Sx, A, B] = computeTransferMatrices(q, model, nbD) -% J = robot.jacob0(q,'trans'); - J = jacob0(q, model); - %Discrete linear system x(t+1) = x(t) + J * dq - A = eye(model.nbVarX); - B = J * model.dt; - [Su, Sx] = transferMatrices(A, B, nbD); -end - -%%%%%%%%%%%%%%%%%%%%%% -%Forward kinematics -function [x, Tf] = fkine(q, model) - Tf = eye(4); - T = repmat(Tf, [1,1,size(q,1)]); - for n=1:size(q,1) - c = cos(q(n)); - s = sin(q(n)); - T(:,:,n) = [c, -s, 0, model.l * c; ... - s, c, 0, model.l * s; ... - 0, 0, 1, 0; - 0, 0, 0, 1]; %Homogeneous matrix - Tf = Tf * T(:,:,n); - end - x = Tf(1:2,end); -end - -%%%%%%%%%%%%%%%%%%%%%% -%Jacobian with numerical computation -function J = jacob0(q, model) - e = 1E-4; - J = zeros(2,size(q,1)); - for n=1:size(q,1) - qtmp = q; - qtmp(n) = qtmp(n) + e; - J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; - end -end \ No newline at end of file diff --git a/demos/demo_OC_DDP_bicopter01.m b/demos/demo_OC_DDP_bicopter01.m new file mode 100644 index 0000000000000000000000000000000000000000..ec201b75164f01d9c4c86e35814efe636f821616 --- /dev/null +++ b/demos/demo_OC_DDP_bicopter01.m @@ -0,0 +1,279 @@ +function demo_OC_DDP_bicopter01 +% iLQR applied to a bicopter problem +% +% Sylvain Calinon, 2020 +% +% Reference: +% W. Li and E. Todorov, "Iterative linear quadratic regulator design for nonlinear biological movement systems," +% in Intl Conf. on InfoRatics in Control, Automation and Robotics, 2004, pp. 222–229 + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +model.sim_time = 3; %Simulation time +model.dt = 1E-1; %Time step size +model.nbData = model.sim_time / model.dt; %Number of datapoints +model.nbIter = 20; %Number of iterations for iLQR + +model.nbVarPos = 3; %Dimension of position (x1,x2,theta) +model.nbDeriv = 2; %Number of derivatives (nbDeriv=2 for [x; dx] state) +model.nbVarX = model.nbVarPos * model.nbDeriv; %State space dimension +model.nbVarU = 2; %Control space dimension (u1,u2) + +model.rfactor = 1E-6; %Control weight teR +model.Mu = [4; 4; 0; zeros(model.nbVarPos,1)]; %Target + +model.m = 2.5; %Mass +model.l = 0.5; %Length +model.g = 9.81; %Acceleration due to gravity +model.I = 1.2; %Inertia + +R = speye((model.nbData-1)*model.nbVarU) * model.rfactor; %Control weight matrix (at trajectory level) +Rx = speye(model.nbData*model.nbVarX) * model.rfactor; + +Q = blkdiag(sparse((model.nbData-1)*model.nbVarX, (model.nbData-1)*model.nbVarX), diag([1E2, 1E2, 1E1, 1E0, 1E0, 1E0])); %Sparse precision matrix (at trajectory level) +MuQ = [sparse((model.nbData-1)*model.nbVarX,1); model.Mu]; %Sparse reference (at trajectory level) + + +%% Iterative LQR (iLQR) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% delta_x0 = zeros(model.nbVarX, 1); +% u = zeros(model.nbVarU, model.nbData-1); +u0 = 0.5 * model.m * model.g * ones(model.nbVarU,1); +u = repmat(u0, 1, model.nbData-1); +x0 = zeros(model.nbVarX,1); +% x0 = [-1; 1; -pi/8; .3; .1; .2]; + +% uSigma = zeros(model.nbVarU*(model.nbData-1)); +% xSigma = zeros(model.nbVarX*model.nbData); + +for n=1:model.nbIter + %System evolution + x = dynSysSimulation(x0, u, model); +% if n>1 +% x = reshape(Sx * x0 + Su * u(:), model.nbVarX, model.nbData); %Approximated dynamics +% end + + %Linearization + [A, B] = linSys(x, u, model); + [Su, Sx] = transferMatrices(A, B); + +% du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:) - Su' * Q * Sx * delta_x0); %Control trajectory + du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:)); %Control trajectory + delta_u = reshape(du_vec, model.nbVarU, model.nbData-1); +% delta_x = reshape(Sx * delta_x0 + Su * delta_u(:), model.nbVarX, model.nbData); %Forward recursion + + %Estimate step size with line search method + alpha = 1; + cost0 = (MuQ - x(:))' * Q * (MuQ - x(:)) + u(:)' * R * u(:); + while 1 + utmp = u + delta_u * alpha; + xtmp = dynSysSimulation(x0, utmp, model); +% xtmp = reshape(Sx * x0 + Su * utmp(:), model.nbVarX, model.nbData); %Approximated dynamics + + cost = (MuQ - xtmp(:))' * Q * (MuQ - xtmp(:)) + utmp(:)' * R * utmp(:); %Compute the cost + if cost < cost0 || alpha < 1E-4 + break; + end + alpha = alpha * 0.5; + end + disp(alpha); + u = u + delta_u * alpha; %Update control by following gradient + +% uSigmaTmp = inv(Su' * Q * Su + R); +% uSigma = uSigma + uSigmaTmp * alpha^2; +% xSigma = xSigma + Su * uSigmaTmp * Su' * alpha^2; + + %Log data + r(n).x = x; + r(n).u = u; +end + + +%% Stochastic sampling by exploiting the nullspace structure of the problem +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% %Standard stochastic sampling +% uSigma = inv(Su' * Q * Su + R); +% % xSigma = Su * uSigma * Su'; +% [V, D] = eig(full(uSigma)); +% U = real(V * D.^.5); +% nbSamples = 50; +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% for n=1:nbSamples +% utmp = u(:) + U * randn(model.nbVarU*(model.nbData-1), 1) * 1E-3; +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + +% %Generate structured stochastic u through Bezier curves +% nbSamples = 50; +% nbRBF = 18; +% H = zeros(nbRBF, model.nbData-1); +% tl = linspace(0, 1, model.nbData-1); +% nbDeg = nbRBF - 1; +% for i=0:nbDeg +% H(i+1,:) = factorial(nbDeg) / (factorial(i) * factorial(nbDeg-i)) * (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions +% end +% %Nullspace planning +% [V,D] = eig(full(Q)); +% U = V * D.^.5; +% N = eye((model.nbData-1)*model.nbVarU) - Su' * U / (U' * (Su * Su') * U + Rx) * U' * Su; %Nullspace projection matrix +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% for n=1:nbSamples +% w = randn(model.nbVarU, nbRBF) * 1E0; %Random weights +% un = w * H; %Reconstruction of signals by weighted superposition of basis functions +% utmp = u(:) + N * un(:); +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + + +%% Plot state space +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10,10,800,800]); hold on; axis off; grid on; box on; +% for t=1:model.nbData +% plotGMM(r(end).x(1:2,t), xSigma(model.nbVarX*(t-1)+[1,2],model.nbVarX*(t-1)+[1,2]).*1E-5, [.8 0 0], .1); +% end + +%iLQR refinement steps +for k=1:length(r) + plot(r(k).x(1,:), r(k).x(2,:), '-','linewidth',1,'color',[.7 .7 .7]-.7*k/length(r)); +end + +% %Stochastic samples +% for n=1:nbSamples +% plot(sx(1:model.nbVarX:end,n), sx(2:model.nbVarX:end,n), '-','linewidth',1,'color',(ones(1,3)-n/nbSamples)*.9); +% end + +% plot(r(end).x(1,:),r(end).x(2,:), '-','linewidth',2,'color',[.8 0 0]); +h(1) = plot(r(end).x(1,1),r(end).x(2,1), '.','markersize',40,'color',[0 0 0]); +%Animation +for t=floor(linspace(1,model.nbData,20)) + plot(r(end).x(1,t), r(end).x(2,t), '.','markersize',40,'color',[0 0 0]); + msh = [r(end).x(1:2,t), r(end).x(1:2,t)] + [cos(r(end).x(3,t)); sin(r(end).x(3,t))] * [-.4, .4]; + plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[0 0 0]); +end +msh = [model.Mu(1:2), model.Mu(1:2)] + [cos(model.Mu(3)); sin(model.Mu(3))] * [-.4, .4]; +plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[.8 0 0]); +h(2) = plot(model.Mu(1), model.Mu(2), '.','markersize',40,'color',[.8 0 0]); +legend(h,{'Starting point','Ending point'},'location','southeast','fontsize',40); +axis equal; axis([-.5 4.5 -.2 4.4]); +xlabel('x_1'); ylabel('x_2'); +print('-dpng','graphs/DDP_bicopter01.png'); + + +% %% Plot control space +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[1030,10,1000,1000]); +% t = model.dt:model.dt:model.dt*model.nbData; +% for kk=1:size(r(1).u,1) +% subplot(size(r(1).u,1), 1, kk); grid on; hold on; box on; box on; +% for k=1:length(r) +% plot(t(1:end-1), r(k).u(kk,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end +% plot(t(1:end-1), r(end).u(kk,:), '-','linewidth',2,'color',[0 0 0]); +% axis([min(t), max(t(1:end-1)), min(r(end).u(kk,:))-2, max(r(end).u(kk,:))+2]); +% xlabel('t'); ylabel(['u_' num2str(kk)]); +% end + + +% %% Plot animated robot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10,10,1000,1000]); hold on; axis off; +% plot(model.Mu(1), model.Mu(2), '.','markersize',40,'color',[.8 0 0]); +% msh = [model.Mu(1:2), model.Mu(1:2)] + [cos(model.Mu(3)); sin(model.Mu(3))] * [-.4, .4]; +% plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[.8 0 0]); +% axis equal; axis([-.5 4.5 -.2 4.2]); +% for t=1:model.nbData +% h(1) = plot(r(end).x(1,t), r(end).x(2,t), '.','markersize',40,'color',[0 0 0]); +% msh = [r(end).x(1:2,t), r(end).x(1:2,t)] + [cos(r(end).x(3,t)); sin(r(end).x(3,t))] * [-.4, .4]; +% h(2) = plot(msh(1,:), msh(2,:), '-','linewidth',5,'color',[0 0 0]); +% drawnow; +% % print('-dpng',['graphs/anim/DDP_bicopter_anim' num2str(t,'%.3d') '.png']); +% if t<model.nbData +% delete(h); +% end +% end +% % for t=model.nbData+1:model.nbData+10 +% % print('-dpng',['graphs/anim/DDP_bicopter_anim' num2str(t,'%.3d') '.png']); +% % end + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Given the control trajectory u and initial state x0, compute the whole state trajectory +function x = dynSysSimulation(x0, u, model) + m = model.m; + l = model.l; + I = model.I; + g = model.g; + x = zeros(model.nbVarX, model.nbData); + f = zeros(model.nbVarX, 1); + x(:,1) = x0; + for t=1:model.nbData-1 + f(1) = x(4,t); + f(2) = x(5,t); + f(3) = x(6,t); + f(4) = -m^-1 * (u(1,t) + u(2,t)) * sin(x(3,t)); + f(5) = m^-1 * (u(1,t) + u(2,t)) * cos(x(3,t)) - g; + f(6) = l/I * (u(1,t) - u(2,t)); + x(:,t+1) = x(:,t) + f * model.dt; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Linearize the system along the trajectory computing the matrices A and B +function [A, B] = linSys(x, u, model) + m = model.m; + l = model.l; + I = model.I; + A = zeros(model.nbVarX, model.nbVarX, model.nbData-1); + B = zeros(model.nbVarX, model.nbVarU, model.nbData-1); + Ac = zeros(model.nbVarX); + Ac(1:3,4:6) = eye(model.nbVarPos); + Bc = zeros(model.nbVarX, model.nbVarU); + for t=1:model.nbData-1 + %Linearize the system + Ac(4,3) = -m^-1 * (u(1) + u(2)) * cos(x(3)); + Ac(5,3) = -m^-1 * (u(1) + u(2)) * sin(x(3)); + Bc(4,1) = -m^-1 * sin(x(3)); Bc(4,2) = Bc(4,1); + Bc(5,1) = m^-1 * cos(x(3)); Bc(5,2) = Bc(5,1); + Bc(6,1) = l / I; Bc(6,2) = -Bc(6,1); + %Discretize the linear system + A(:,:,t) = eye(model.nbVarX) + Ac * model.dt; + B(:,:,t) = Bc * model.dt; + end + +% %Symbolic expressions to find linearized system +% syms m l g I +% x = sym('x',[6 1]); +% u = sym('u',[2 1]); +% f(1) = x(4); +% f(2) = x(5); +% f(3) = x(6); +% f(4) = -m^-1 * (u(1) + u(2)) * sin(x(3)); +% f(5) = m^-1 * (u(1) + u(2)) * cos(x(3)) - g; +% f(6) = l/I * (u(1) - u(2)); +% jacobian(f, x) +% jacobian(f, u) +end \ No newline at end of file diff --git a/demos/demo_OC_DDP_car01.m b/demos/demo_OC_DDP_car01.m new file mode 100644 index 0000000000000000000000000000000000000000..ba5dc0b671d3da6285efb5d111c01d6de064f70b --- /dev/null +++ b/demos/demo_OC_DDP_car01.m @@ -0,0 +1,279 @@ +function demo_OC_DDP_car01 +% iLQR applied to a car parking problem +% +% Sylvain Calinon, 2020 +% +% Reference: +% W. Li and E. Todorov, "Iterative linear quadratic regulator design for nonlinear biological movement systems," +% in Intl Conf. on InfoRatics in Control, Automation and Robotics, 2004, pp. 222–229 + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +model.sim_time = 3; %Simulation time +model.dt = 1E-1; %Time step size +model.nbData = model.sim_time / model.dt; %Number of datapoints +model.nbIter = 10; %Number of iterations for iLQR + +model.nbVarX = 4; %Dimension of state (x1,x2,theta,phi) +model.nbVarU = 2; %Control space dimension (v,dphi) + +model.rfactor = 1E-6; %Control weight teR +model.Mu = [4; 3; pi/2; 0]; %Target +% model.Mu = [.2; 2; pi/2; 0]; %Target + + +model.l = 0.5; %Length of car + +R = speye((model.nbData-1)*model.nbVarU) * model.rfactor; %Control weight matrix (at trajectory level) +Rx = speye(model.nbData*model.nbVarX) * model.rfactor; + +Q = blkdiag(sparse((model.nbData-1)*model.nbVarX, (model.nbData-1)*model.nbVarX), speye(model.nbVarX)*1E2); %Sparse precision matrix (at trajectory level) +MuQ = [sparse((model.nbData-1)*model.nbVarX,1); model.Mu]; %Sparse reference (at trajectory level) + + +%% Iterative LQR (iLQR) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% delta_x0 = zeros(model.nbVarX, 1); +u = zeros(model.nbVarU, model.nbData-1); +% u = repmat([2; 0], 1, model.nbData-1); +x0 = zeros(model.nbVarX,1); + +% uSigma = zeros(model.nbVarU*(model.nbData-1)); +% xSigma = zeros(model.nbVarX*model.nbData); + +for n=1:model.nbIter + %System evolution + x = dynSysSimulation(x0, u, model); +% if n>1 +% x = reshape(Sx * x0 + Su * u(:), model.nbVarX, model.nbData); %Approximated dynamics +% end + + %Linearization + [A, B] = linSys(x, u, model); + [Su, Sx] = transferMatrices(A, B); + +% du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:) - Su' * Q * Sx * delta_x0); %Control trajectory + du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:)); %Control trajectory + delta_u = reshape(du_vec, model.nbVarU, model.nbData-1); +% delta_x = reshape(Sx * delta_x0 + Su * delta_u(:), model.nbVarX, model.nbData); %Forward recursion + + %Estimate step size with line search method + alpha = 1; + cost0 = (MuQ - x(:))' * Q * (MuQ - x(:)) + u(:)' * R * u(:); + while 1 + utmp = u + delta_u * alpha; + xtmp = dynSysSimulation(x0, utmp, model); +% xtmp = reshape(Sx * x0 + Su * utmp(:), model.nbVarX, model.nbData); %Approximated dynamics + + cost = (MuQ - xtmp(:))' * Q * (MuQ - xtmp(:)) + utmp(:)' * R * utmp(:); %Compute the cost + if cost < cost0 || alpha < 1E-4 + break; + end + alpha = alpha * 0.5; + end +% disp(alpha); + u = u + delta_u * alpha; %Update control by following gradient + +% uSigmaTmp = inv(Su' * Q * Su + R); +% uSigma = uSigma + uSigmaTmp * alpha^2; +% xSigma = xSigma + Su * uSigmaTmp * Su' * alpha^2; + + %Log data + r(n).x = x; + r(n).u = u; +end + + +%% Stochastic sampling by exploiting the nullspace structure of the problem +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% %Standard stochastic sampling +% uSigma = inv(Su' * Q * Su + R); +% % xSigma = Su * uSigma * Su'; +% [V, D] = eig(full(uSigma)); +% U = real(V * D.^.5); +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% nbSamples = 50; +% for n=1:nbSamples +% utmp = u(:) + U * randn(model.nbVarU*(model.nbData-1), 1) * 1E-3; +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + +% %Generate structured stochastic u through Bezier curves +% nbSamples = 50; +% nbRBF = 18; +% H = zeros(nbRBF, model.nbData-1); +% tl = linspace(0, 1, model.nbData-1); +% nbDeg = nbRBF - 1; +% for i=0:nbDeg +% H(i+1,:) = factorial(nbDeg) / (factorial(i) * factorial(nbDeg-i)) * (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions +% end +% %Nullspace planning +% [V,D] = eig(full(Q)); +% U = V * D.^.5; +% N = eye((model.nbData-1)*model.nbVarU) - Su' * U / (U' * (Su * Su') * U + Rx) * U' * Su; %Nullspace projection matrix +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% for n=1:nbSamples +% w = randn(model.nbVarU, nbRBF) * 1E0; %Random weights +% un = w * H; %Reconstruction of signals by weighted superposition of basis functions +% utmp = u(:) + N * un(:); +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + + +%% Plot state space +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10,10,800,800]); hold on; axis off; +% for t=1:model.nbData +% plotGMM(r(end).x(1:2,t), xSigma(model.nbVarX*(t-1)+[1,2],model.nbVarX*(t-1)+[1,2]).*1E-6, [.8 0 0], .1); +% end +%Animation +for t=round(linspace(1,model.nbData,model.nbData)) + R = [cos(r(end).x(3,t)) -sin(r(end).x(3,t)); sin(r(end).x(3,t)) cos(r(end).x(3,t))]; + msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(r(end).x(1:2,t),1,5); + plot(msh(1,:), msh(2,:), '-','linewidth',2,'color',[.8 .8 .8]); +end + +% %iLQR refinement steps +% for k=1:length(r) +% plot(r(k).x(1,:), r(k).x(2,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end + +% %Stochastic samples +% for n=1:nbSamples +% plot(sx(1:model.nbVarX:end,n), sx(2:model.nbVarX:end,n), '-','linewidth',1,'color',(ones(1,3)-n/nbSamples)*.9); +% end + +plot(r(end).x(1,:),r(end).x(2,:), '-','linewidth',2,'color',[0 0 0]); +%Initial pose +R = [cos(r(end).x(3,1)) -sin(r(end).x(3,1)); sin(r(end).x(3,1)) cos(r(end).x(3,1))]; +msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(r(end).x(1:2,1),1,5); +plot(msh(1,:), msh(2,:), '-','linewidth',2,'color',[0 0 0]); +h(1) = plot(r(end).x(1,1),r(end).x(2,1), '.','markersize',20,'color',[0 0 0]); +%Final pose +R = [cos(r(end).x(3,end)) -sin(r(end).x(3,end)); sin(r(end).x(3,end)) cos(r(end).x(3,end))]; +msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(r(end).x(1:2,end),1,5); +plot(msh(1,:), msh(2,:), '-','linewidth',4,'color',[0 0 0]); +h(1) = plot(r(end).x(1,1),r(end).x(2,1), '.','markersize',20,'color',[0 0 0]); +%Target pose +R = [cos(model.Mu(3)) -sin(model.Mu(3)); sin(model.Mu(3)) cos(model.Mu(3))]; +msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(model.Mu(1:2),1,5); +plot(msh(1,:), msh(2,:), '-','linewidth',2,'color',[.8 0 0]); +h(2) = plot(model.Mu(1), model.Mu(2), '.','markersize',20,'color',[.8 0 0]); + +legend(h,{'Initial pose','Target pose'},'location','northwest','fontsize',20); +axis equal; axis([-1 5 -1 4]); +% print('-dpng','graphs/DDP_car01_Sigma.png'); + + +% %% Plot control space +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[1030,10,1000,1000]); +% t = model.dt:model.dt:model.dt*model.nbData; +% for kk=1:size(r(1).u,1) +% subplot(size(r(1).u,1), 1, kk); grid on; hold on; box on; box on; +% for k=1:length(r) +% plot(t(1:end-1), r(k).u(kk,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end +% plot(t(1:end-1), r(end).u(kk,:), '-','linewidth',2,'color',[0 0 0]); +% axis([min(t), max(t(1:end-1)), min(r(end).u(kk,:))-.2, max(r(end).u(kk,:))+.2]); +% xlabel('t'); ylabel(['u_' num2str(kk)]); +% end + + +% %% Plot animated robot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10,10,1000,1000]); hold on; axis off; +% %Target pose +% R = [cos(model.Mu(3)) -sin(model.Mu(3)); sin(model.Mu(3)) cos(model.Mu(3))]; +% msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(model.Mu(1:2),1,5); +% plot(msh(1,:), msh(2,:), '-','linewidth',4,'color',[.8 0 0]); +% plot(model.Mu(1), model.Mu(2), '.','markersize',40,'color',[.8 0 0]); +% axis equal; axis([-1 5 -1 4]); +% for t=1:model.nbData +% R = [cos(r(end).x(3,t)) -sin(r(end).x(3,t)); sin(r(end).x(3,t)) cos(r(end).x(3,t))]; +% msh = R * [-.6 -.6 .6 .6 -.6; -.4 .4 .4 -.4 -.4] + repmat(r(end).x(1:2,t),1,5); +% h(1) = plot(msh(1,:), msh(2,:), '-','linewidth',4,'color',[0 0 0]); +% h(2) = plot(r(end).x(1,t),r(end).x(2,t), '.','markersize',40,'color',[0 0 0]); +% % print('-dpng',['graphs/anim/DDP_car_anim' num2str(t,'%.3d') '.png']); +% if t<model.nbData +% delete(h); +% end +% end +% % for t=model.nbData+1:model.nbData+10 +% % print('-dpng',['graphs/anim/DDP_car_anim' num2str(t,'%.3d') '.png']); +% % end + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Given the control trajectory u and initial state x0, compute the whole state trajectory +function x = dynSysSimulation(x0, u, model) + l = model.l; + x = zeros(model.nbVarX, model.nbData); + f = zeros(model.nbVarX, 1); + x(:,1) = x0; + for t=1:model.nbData-1 + f(1) = cos(x(3,t)) * u(1,t); + f(2) = sin(x(3,t)) * u(1,t); + f(3) = tan(x(4,t)) * u(1,t) / l; + f(4) = u(2,t); + x(:,t+1) = x(:,t) + f * model.dt; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Linearize the system along the trajectory computing the matrices A and B +function [A, B] = linSys(x, u, model) + l = model.l; + A = zeros(model.nbVarX, model.nbVarX, model.nbData-1); + B = zeros(model.nbVarX, model.nbVarU, model.nbData-1); + Ac = zeros(model.nbVarX); + Bc = zeros(model.nbVarX, model.nbVarU); + for t=1:model.nbData-1 + %Linearize the system + Ac(1,3) = -u(1,t) * sin(x(3,t)); + Ac(2,3) = u(1,t) * cos(x(3,t)); + Ac(3,4) = u(1,t) * tan(x(4,t)^2 + 1) / l; + Bc(1,1) = cos(x(3,t)); + Bc(2,1) = sin(x(3,t)); + Bc(3,1) = tan(x(4,t)) / l; + Bc(4,2) = 1; + %Discretize the linear system + A(:,:,t) = eye(model.nbVarX) + Ac * model.dt; + B(:,:,t) = Bc * model.dt; + end + +% %Symbolic expressions to find linearized system +% syms l +% x = sym('x',[4 1]); +% u = sym('u',[2 1]); +% f(1) = cos(x(3)) * u(1); +% f(2) = sin(x(3)) * u(1); +% f(3) = tan(x(4)) * u(1) / l; +% f(4) = u(2); +% jacobian(f, x) +% jacobian(f, u) +end \ No newline at end of file diff --git a/demos/demo_OC_DDP_cartpole01.m b/demos/demo_OC_DDP_cartpole01.m new file mode 100644 index 0000000000000000000000000000000000000000..0c3be4c620ec3dcca956a635ea5185f0daaefa24 --- /dev/null +++ b/demos/demo_OC_DDP_cartpole01.m @@ -0,0 +1,269 @@ +function demo_OC_DDP_cartpole01 +% iLQR applied to a cartpole problem +% +% Sylvain Calinon, 2020 +% +% Reference for cartpole system: +% http://databookuw.com/databook.pdf, p. 372 + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +model.sim_time = 3; %Simulation time +model.dt = 2E-2; %Time step size +model.nbData = model.sim_time / model.dt; %Number of datapoints +model.nbIter = 30; %Number of iterations for iLQR + +model.nbVarPos = 2; %Dimension of position +model.nbDeriv = 2; %Number of derivatives (nbDeriv=2 for [x; dx] state) +model.nbVarX = model.nbVarPos * model.nbDeriv; %State space dimension +model.nbVarU = 1; %Control space dimension + +model.rfactor = 1E-5; %Control weight teR +model.Mu = [2; pi; 0; 0]; %Target + +model.m = 1; %Pendulum mass +model.M = 5; %Cart mass +model.L = 1; %Pendulum length +model.g = 9.81; %Acceleration due to gravity +model.d = 1; %Cart damping +% model.b = 0.01; %Friction + +R = speye((model.nbData-1)*model.nbVarU) * model.rfactor; %Control weight matrix (at trajectory level) +Rx = speye(model.nbData*model.nbVarX) * model.rfactor; + +Q = blkdiag(sparse((model.nbData-1)*model.nbVarX, (model.nbData-1)*model.nbVarX), diag([1E4, 1E4, 1E3, 1E3])); %Sparse precision matrix (at trajectory level) +MuQ = [sparse((model.nbData-1)*model.nbVarX,1); model.Mu]; %Sparse reference (at trajectory level) + + +%% Iterative LQR (iLQR) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% delta_x0 = zeros(model.nbVarX, 1); +u = zeros(model.nbVarU, model.nbData-1); +x0 = zeros(model.nbVarX,1); +% x0 = [0; pi/4; .4; 0]; + +% uSigma = zeros(model.nbVarU*(model.nbData-1)); +% xSigma = zeros(model.nbVarX*model.nbData); + +for n=1:model.nbIter + %sxstem evolution + x = dynSysSimulation(x0, u, model); + + %Linearization + [A, B] = linSys(x, u, model); + [Su, Sx] = transferMatrices(A, B); + +% du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:) - Su' * Q * Sx * delta_x0); %Control trajectory + du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:)); %Control trajectory + delta_u = reshape(du_vec, model.nbVarU, model.nbData-1); +% delta_x = reshape(Sx * delta_x0 + Su * delta_u(:), model.nbVarX, model.nbData); %Forward recursion + + %Estimate step size with line search method + alpha = 1; + cost0 = (MuQ - x(:))' * Q * (MuQ - x(:)) + u(:)' * R * u(:); + while 1 + utmp = u + delta_u * alpha; + xtmp = dynSysSimulation(x0, utmp, model); + cost = (MuQ - xtmp(:))' * Q * (MuQ - xtmp(:)) + utmp(:)' * R * utmp(:); %Compute the cost + if cost < cost0 || alpha < 1E-4 + break; + end + alpha = alpha * 0.5; + end +% disp(alpha); + u = u + delta_u * alpha; %Update control by following gradient + +% uSigmaTmp = inv(Su' * Q * Su + R); +% uSigma = uSigma + uSigmaTmp * alpha^2; +% xSigma = xSigma + Su * uSigmaTmp * Su' * alpha^2; + + %Log data + r(n).x = x; + r(n).u = u; +end + +%% Stochastic sampling by exploiting the nullspace structure of the problem +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% %Standard stochastic sampling +% uSigma = inv(Su' * Q * Su + R); +% % xSigma = Su * uSigma * Su'; +% [V, D] = eig(full(uSigma)); +% U = real(V * D.^.5); +% nbSamples = 50; +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% for n=1:nbSamples +% utmp = u(:) + U * randn(model.nbVarU*(model.nbData-1), 1) * 1E-1; +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + +% %Generate structured stochastic u through Bezier curves +% nbSamples = 50; +% nbRBF = 18; +% H = zeros(nbRBF, model.nbData-1); +% tl = linspace(0, 1, model.nbData-1); +% nbDeg = nbRBF - 1; +% for i=0:nbDeg +% H(i+1,:) = factorial(nbDeg) / (factorial(i) * factorial(nbDeg-i)) * (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions +% end +% %Nullspace planning +% [V,D] = eig(full(Q)); +% U = V * D.^.5; +% N = eye((model.nbData-1)*model.nbVarU) - Su' * U / (U' * (Su * Su') * U + Rx) * U' * Su; %Nullspace projection matrix +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% for n=1:nbSamples +% w = randn(model.nbVarU, nbRBF) * 1E1; %Random weights +% un = w * H; %Reconstruction of signals by weighted superposition of basis functions +% utmp = u(:) + N * un(:); +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + + +%% Plot state space +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10,10,800,800]); hold on; axis on; grid on; box on; +% for t=1:model.nbData +% plotGMM(r(end).x(1:2,t), xSigma(model.nbVarX*(t-1)+[1,2],model.nbVarX*(t-1)+[1,2]).*5E-2, [.8 0 0], .05); +% end + +% %iLQR refinement steps +% for k=1:length(r) +% plot(r(k).x(1,:), r(k).x(2,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end + +% %Stochastic samples +% for n=1:nbSamples +% plot(sx(1:model.nbVarX:end,n), sx(2:model.nbVarX:end,n), '-','linewidth',1,'color',(ones(1,3)-n/nbSamples)*.9); +% end + +plot(r(end).x(1,:),r(end).x(2,:), '-','linewidth',2,'color',[.8 0 0]); +h(1) = plot(r(end).x(1,1),r(end).x(2,1), '.','markersize',20,'color',[0 0 0]); +h(2) = plot(model.Mu(1), model.Mu(2), '.','markersize',20,'color',[.8 0 0]); +legend(h,{'Starting point','Ending point'},'location','southwest'); +axis equal; %axis([-5 5 -4 6]); +xlabel('x'); ylabel('\theta'); + + +% %% Plot control space +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[1020,10,1000,1000]); +% t = model.dt:model.dt:model.dt*model.nbData; +% for kk=1:size(r(1).u,1) +% subplot(size(r(1).u,1), 1, kk); grid on; hold on; box on; box on; +% for k=1:length(r) +% plot(t(1:end-1), r(k).u(kk,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end +% plot(t(1:end-1), r(end).u(kk,:), '-','linewidth',2,'color',[0 0 0]); +% axis([min(t), max(t(1:end-1)), min(r(end).u(kk,:))-2, max(r(end).u(kk,:))+2]); +% xlabel('t'); ylabel(['u_' num2str(kk)]); +% end + + +% %% Plot animated robot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 2200 700],'color',[1 1 1]); hold on; axis off; +% plotAR(model.Mu(2)-pi/2, model.L, [0;0;-1], .1, [.8 0 0]); +% axis equal; axis([-4.2 4.2 -1.2 1.2]*2); +% h=[]; +% for t=1:model.nbData +% delete(h); +% h = plotAR(r(end).x(2,t)-pi/2, model.L, [r(end).x(1,t);0;0], .1, [0 0 0]); +% drawnow; +% end + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Given the control trajectory u and initial state x0, compute the whole state trajectory +function x = dynSysSimulation(x0, u, model) + m = model.m; + M = model.M; + L = model.L; + g = model.g; + d = model.d; + x = zeros(model.nbVarX, model.nbData); + f = zeros(model.nbVarX, 1); + x(:,1) = x0; + for t=1:model.nbData-1 + sx = sin(x(2,t)); + cx = cos(x(2,t)); + D = m*L^2*(M+m*(1-cx^2)); + f(1) = x(3,t); + f(2) = x(4,t); +% f(3) = (1/D)*(-m^2*L^2*g*cx*sx + m*L^2*(m*L*x(4,t)^2*sx - d*x(3,t))) + m*L^2*(1/D) * u(1,t); +% f(4) = (1/D)*((m+M)*m*g*L*sx - m*L*cx*(m*L*x(4,t)^2*sx - d*x(3,t))) - m*L*cx*(1/D) * u(1,t); + f(3) = (u(1,t) + m*sx*(L*x(4,t)^2+g*cx)) / (M+m*sx^2); %From RLSC Homework (Part 2: Optimal Control) + f(4) = (-u(1,t) - m*L*x(4,t)*cx*sx - (M+m)*g*sx) / (L*(M+m*sx^2)); %From RLSC Homework (Part 2: Optimal Control) + x(:,t+1) = x(:,t) + f * model.dt; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Linearize the sxstem along the trajectory computing the matrices A and B +function [A, B] = linSys(x, u, model) + m = model.m; + M = model.M; + L = model.L; + g = model.g; + d = model.d; + + A = zeros(model.nbVarX, model.nbVarX, model.nbData-1); + B = zeros(model.nbVarX, model.nbVarU, model.nbData-1); + +% %Linearization at target (pendulum up corresponds to s=1) +% s = 1; +% Ac = [0 0 1 0; +% 0 0 0 1; +% 0 -m*g/M -d/M 0; +% 0 -s*(m+M)*g/(M*L) -s*d/(M*L) 0]; +% Bc = [0; 0; 1/M; s*1/(M*L)]; + + for t=1:model.nbData-1 + %Linearization + Ac = [0, 0, 1, 0; ... + 0, 0, 0, 1; ... + 0, ((m*cos(x(2,t))*(L*x(4,t)^2 + g*cos(x(2,t))) - g*m*sin(x(2,t))^2)/(m*sin(x(2,t))^2 + M) - (2*m*cos(x(2,t))*sin(x(2,t))*(u(1,t) + m*sin(x(2,t))*(L*x(4,t)^2 + g*cos(x(2,t)))))/(m*sin(x(2,t))^2 + M)^2), 0, ((2*L*m*x(4,t)*sin(x(2,t)))/(m*sin(x(2,t))^2 + M)); ... + 0, (2*m*cos(x(2,t))*sin(x(2,t))*(u(1,t) + g*sin(x(2,t))*(M + m) + L*m*x(4,t)*cos(x(2,t))*sin(x(2,t))))/(L*(m*sin(x(2,t))^2 + M)^2) - (g*cos(x(2,t))*(M + m) + L*m*x(4,t)*cos(x(2,t))^2 - L*m*x(4,t)*sin(x(2,t))^2)/(L*(m*sin(x(2,t))^2 + M)), 0, (-(m*cos(x(2,t))*sin(x(2,t)))/(m*sin(x(2,t))^2 + M))]; + Bc = [0; 0; 1/(m*sin(x(2,t))^2 + M); -1/(L*(m*sin(x(2,t))^2 + M))]; + %Discretize the linear sxstem + A(:,:,t) = eye(model.nbVarX) + Ac * model.dt; + B(:,:,t) = Bc * model.dt; + end + +% %Symbolic expressions to find linearized system +% syms m M L g d u +% x = sym('x',[4 1]); +% sx = sin(x(2)); +% cx = cos(x(2)); +% D = m*L^2*(M+m*(1-cx^2)); +% f(1) = x(3); +% f(2) = x(4); +% % f(3) = (1/D)*(-m^2*L^2*g*cx*sx + m*L^2*(m*L*x(4)^2*sx - d*x(3))) + m*L^2*(1/D) * u; +% % f(4) = (1/D)*((m+M)*m*g*L*sx - m*L*cx*(m*L*x(4)^2*sx - d*x(3))) - m*L*cx*(1/D) * u; +% f(3) = (u + m*sx*(L*x(4)^2+g*cx)) / (M+m*sx^2); +% f(4) = (-u - m*L*x(4)*cx*sx - (M+m)*g*sx) / (L*(M+m*sx^2)); +% jacobian(f, x) +% jacobian(f, u) +end \ No newline at end of file diff --git a/demos/demo_OC_DDP_humanoid01.m b/demos/demo_OC_DDP_humanoid01.m new file mode 100644 index 0000000000000000000000000000000000000000..419ea951abd72eb4ebdf6864709f377207c922d3 --- /dev/null +++ b/demos/demo_OC_DDP_humanoid01.m @@ -0,0 +1,259 @@ +function demo_OC_DDP_humanoid01 +% iLQR applied to a planar 5-link humanoid problem with constraints between joints +% +% Sylvain Calinon, 2020 + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +model.sim_time = 1; %Simulation time +model.dt = 1E-2; %Time step size +model.nbData = model.sim_time / model.dt; %Number of datapoints +model.nbPoints = 2; %Number of viapoints +model.nbIter = 20; %Number of iterations for iLQR +model.nbVarX = 5; %Dimension of state (x1,x2, q1,q2,q3) +model.nbVarU = 3; %Control space dimension (dq1,dq2,dq3) + +model.rfactor = 1E-2; %Control weight term +model.Mu(:,1) = [3; 1.5; zeros(model.nbVarU,1)]; %Target (x1h,x2h, q1h,q2h,q3h) +model.Mu(:,2) = [2; 5; zeros(model.nbVarU,1)]; %Target (x1h,x2h, q1h,q2h,q3h) + +model.l = 2; %Link length + +R = speye((model.nbData-1)*model.nbVarU) * model.rfactor; %Control weight matrix (at trajectory level) +Rx = speye(model.nbData*model.nbVarX) * model.rfactor; + +% Q = blkdiag(sparse((model.nbData-1)*model.nbVarX, (model.nbData-1)*model.nbVarX), diag([1E2, 1E2, zeros(1,model.nbVarU)])); %Sparse precision matrix (at trajectory level) +% MuQ = [sparse((model.nbData-1)*model.nbVarX,1); model.Mu]; %Sparse reference (at trajectory level) + +Q = blkdiag(sparse((model.nbData/2-1)*model.nbVarX, (model.nbData/2-1)*model.nbVarX), diag([1E2, 1E2, zeros(1,model.nbVarU)]), ... + sparse((model.nbData/2-1)*model.nbVarX, (model.nbData/2-1)*model.nbVarX), diag([1E2, 1E2, zeros(1,model.nbVarU)])); %Sparse precision matrix (at trajectory level) +MuQ = [sparse((model.nbData/2-1)*model.nbVarX,1); model.Mu(:,1); ... + sparse((model.nbData/2-1)*model.nbVarX,1); model.Mu(:,2)]; %Sparse reference (at trajectory level) + +% Q = blkdiag(zeros((model.nbData-2)*model.nbVarX), diag([1E2, 1E2, 0, 0, 0, 1E2, 1E2, 0, 0, 0])); %Sparse precision matrix (at trajectory level) +% MuQ = [zeros((model.nbData-2)*model.nbVarX,1); model.Mu; model.Mu]; %Sparse reference (at trajectory level) + +% Q = kron(eye(model.nbData), diag([1E0, 1E0, 0, 0, 0])); %Sparse precision matrix (at trajectory level) +% MuQ = kron(ones(model.nbData,1), model.Mu); %Sparse reference (at trajectory level) + +% Q = kron(eye(model.nbData), inv(model.Sigma)); %Sparse precision matrix (at trajectory level) +% MuQ = kron(ones(model.nbData,1), model.Mu); %Sparse reference (at trajectory level) + + +%% Iterative LQR (iLQR) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +u = zeros(model.nbVarU, model.nbData-1); +% u = repmat(linspace(0,1E-3,model.nbData-1), model.nbVarU, 1); +% u = ones(model.nbVarU, model.nbData-1) * 1E-1; + +% q0 = zeros(model.nbVarU,1); +% q0 = ones(model.nbVarU,1) * pi/20; +q0 = [.7; pi-.2; pi/2]; +x0 = [fkine(q0, model); q0]; + +for n=1:model.nbIter + %System evolution + x = dynSysSimulation(x0, u, model); + + %Linearization + [A, B] = linSys(x, u, model); + [Su, Sx] = transferMatrices(A, B); + +% du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:) - Su' * Q * Sx * delta_x0); %Control trajectory + du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:)); %Control trajectory + delta_u = reshape(du_vec, model.nbVarU, model.nbData-1); + + %Estimate step size with line search method + alpha = 1; + cost0 = (MuQ - x(:))' * Q * (MuQ - x(:)) + u(:)' * R * u(:); + while 1 + utmp = u + delta_u * alpha; + xtmp = dynSysSimulation(x0, utmp, model); + cost = (MuQ - xtmp(:))' * Q * (MuQ - xtmp(:)) + utmp(:)' * R * utmp(:); %Compute the cost + if cost < cost0 || alpha < 1E-3 + break; + end + alpha = alpha * 0.5; + end + u = u + delta_u * alpha; %Update control by following gradient + + %Log data + r(n).x = [x(1:2,:); pi/2-x(3,:); 2*x(3,:); -x(3,:); x(4:5,:)]; + r(n).u = u; +end + + +% %% Plot control space +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[1020,10,1000,1000]); +% t = model.dt:model.dt:model.dt*model.nbData; +% for kk=1:size(r(1).u,1) +% subplot(size(r(1).u,1), 1, kk); grid on; hold on; box on; box on; +% for k=1:length(r) +% plot(t(1:end-1), r(k).u(kk,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end +% plot(t(1:end-1), r(end).u(kk,:), '-','linewidth',2,'color',[0 0 0]); +% axis([min(t), max(t(1:end-1)), min(r(end).u(kk,:))-.1, max(r(end).u(kk,:))+.1]); +% xlabel('t'); ylabel(['u_' num2str(kk)]); +% end + + +%% Plot static robot +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10,10,1600,800]); hold on; axis off; +% for t=1:model.nbData +% plotGMM(r(end).x(1:2,t), xSigma(model.nbVarX*(t-1)+[1,2],model.nbVarX*(t-1)+[1,2]).*1E-2, [.8 0 0], .1); +% end +% plotArm(r(end).x(3:end,1), ones(5,1)*model.l, [0; 0; -3], .2, [.8 .8 .8]); +% plotArm(r(end).x(3:end,end/2), ones(5,1)*model.l, [ofxa; 0; -2], .2, [.6 .6 .6]); +% plotArm(r(end).x(3:end,end), ones(5,1)*model.l, [2*ofxa; 0; -1], .2, [.4 .4 .4]); + +% %iLQR refinement steps +% for k=1:length(r) +% plot(r(k).x(1,:), r(k).x(2,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end + +% %Stochastic samples +% for n=1:nbSamples +% plot(sx(1:model.nbVarX:end,n), sx(2:model.nbVarX:end,n), '-','linewidth',1,'color',(ones(1,3)-n/nbSamples)*.9); +% end + +colMat = lines(model.nbPoints); +tl = floor(linspace(1,model.nbData,3)); +msh = [-1 -1 1 1 -1; -1 1 1 -1 -1] * 6E-1; +ofxa = 6; +for i=1:3 + ofx = (i-1)*ofxa; + plotArm(r(end).x(3:end,tl(i)), ones(5,1)*model.l, [ofx; 0; -2], .2, [.8 .8 .8]-(i-1)*[.2 .2 .2]); + for j=1:model.nbPoints + plot2Dframe(eye(2)*4E-1, model.Mu(1:2,j)+[ofx;0], repmat(colMat(j,:),3,1), 6); + plot(msh(1,:)+model.Mu(1,j)+ofx, msh(2,:)+model.Mu(2,j), '-','linewidth',2,'color',colMat(j,:)); + end +% for t=floor(linspace(model.nbData/2,model.nbData,2)) +% msh = [-1 -1 1 1 -1; -1 1 1 -1 -1]*6E-1 + repmat(r(end).x(1:2,t), 1, 5); +% plot3(msh(1,:)+ofx, msh(2,:), ones(5,1)*-2, '-','linewidth',2,'color',[0 0 0]); +% end + plot(r(end).x(1,1:tl(i))+ofx, r(end).x(2,1:tl(i)), '-','linewidth',2,'color',[0 0 0]); + plot(r(end).x(1,1)+ofx, r(end).x(2,1), '.','markersize',40,'color',[0 0 0]); +end +% msh = [-1 -1 1 1 -1; -1 1 1 -1 -1]*6E-1 + repmat(model.Mu(1:2,1), 1, 5); +% plot3(msh(1,:), msh(2,:), ones(5,1)*-2, '-','linewidth',2,'color',[0 0 0]); + +axis equal; %axis([-3.5 6.5 -1 5.5]); +% print('-dpng','graphs/DDP_humanoid01.png'); + + +% %% Plot animated robot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 700 700],'color',[1 1 1]); hold on; axis off; +% plot3(model.Mu(1,:), model.Mu(2,:), [1,1], '.','markersize',40,'color',[.8 0 0]); +% +% msh = [-1 -1 1 1 -1; -1 1 1 -1 -1]*6E-1 + repmat(model.Mu(1:2,1), 1, 5); +% plot3(msh(1,:), msh(2,:), ones(5,1)*-2, ':','linewidth',2,'color',[.8 0 0]); +% hb = plot3(msh(1,:), msh(2,:), ones(5,1)*-2, '-','linewidth',2,'color',[0 0 0]); +% +% msh = [-1 -1 1 1 -1; -1 1 1 -1 -1]*6E-1 + repmat(model.Mu(1:2,2), 1, 5); +% plot3(msh(1,:), msh(2,:), ones(5,1)*-2, ':','linewidth',2,'color',[.8 0 0]); +% +% axis equal; axis([-1 3.7 -.6 5.6]); +% for t=1:model.nbData +% h = plotArm(r(end).x(3:end,t), ones(5,1)*model.l, zeros(3,1), .2, [0 0 0]); +% if t>model.nbData/2 +% msh = [-1 -1 1 1 -1; -1 1 1 -1 -1]*6E-1 + repmat(r(end).x(1:2,t), 1, 5); +% delete(hb); +% hb = plot3(msh(1,:), msh(2,:), ones(5,1)*-2, '-','linewidth',2,'color',[0 0 0]); +% end +% drawnow; +% % print('-dpng',['graphs/anim/DDP_humanoid_anim' num2str(t,'%.3d') '.png']); +% if t<model.nbData +% delete(h); +% end +% end +% % for t=model.nbData+1:model.nbData+10 +% % print('-dpng',['graphs/anim/DDP_humanoid_anim' num2str(t,'%.3d') '.png']); +% % end + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Given the control trajectory u and initial state x0, compute the whole state trajectory +function x = dynSysSimulation(x0, u, model) + x = zeros(model.nbVarX, model.nbData); + x(:,1) = x0; + for t=1:model.nbData-1 + x(3:end,t+1) = x(3:end,t) + u(:,t) * model.dt; +% Htmp = model.rob.fkine(x(3:end,t+1)); %Forward kinematics +% x(1:2,t+1) = Htmp.t(1:2); + x(1:2,t+1) = fkine(x(3:end,t+1), model); %Forward kinematics + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Linearize the system along the trajectory computing the matrices A and B +function [A, B] = linSys(x, u, model) + A = zeros(model.nbVarX, model.nbVarX, model.nbData-1); + B = zeros(model.nbVarX, model.nbVarU, model.nbData-1); + Ac = zeros(model.nbVarX); + Bc = zeros(model.nbVarX, model.nbVarU); + for t=1:model.nbData-1 + %Linearize the system +% J = model.rob.jacob0(x(3:end,t),'trans'); +% Bc(1:2,:) = J(1:2,:); + Bc(1:2,:) = jacob0(x(3:end,t), model); + Bc(3:end,:) = eye(model.nbVarU); + %Discretize the linear system + A(:,:,t) = eye(model.nbVarX) + Ac * model.dt; + B(:,:,t) = Bc * model.dt; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Forward kinematics +function [x, Tf] = fkine(q, model) + q = [pi/2-q(1); 2*q(1); -q(1); q(2); q(3)]; + Tf = eye(4); + T = repmat(Tf, [1,1,size(q,1)]); + for n=1:size(q,1) + c = cos(q(n)); + s = sin(q(n)); + T(:,:,n) = [c, -s, 0, model.l * c; ... + s, c, 0, model.l * s; ... + 0, 0, 1, 0; ... + 0, 0, 0, 1]; %Homogeneous matrix + Tf = Tf * T(:,:,n); + end + x = Tf(1:2,end); +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian with numerical computation +function J = jacob0(q, model) + e = 1E-6; + J = zeros(2,size(q,1)); + for n=1:size(q,1) + qtmp = q; + qtmp(n) = qtmp(n) + e; + J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; + end +end \ No newline at end of file diff --git a/demos/demo_OC_DDP_manipulator01.m b/demos/demo_OC_DDP_manipulator01.m new file mode 100644 index 0000000000000000000000000000000000000000..3331f67add369c42371919cce974566d2403c3cd --- /dev/null +++ b/demos/demo_OC_DDP_manipulator01.m @@ -0,0 +1,329 @@ +function demo_OC_DDP_manipulator01 +% iLQR applied to a 2D manipulator problem +% +% Sylvain Calinon, 2020 + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +model.dt = 1E-2; %Time step size +model.nbData = 100; %Number of datapoints +model.nbIter = 20; %Number of iterations for iLQR +model.nbPoints = 2; %Number of viapoints +model.nbVarX = 3; %State space dimension (q1,q2,q3) +model.nbVarU = 3; %Control space dimension (dq1,dq2,dq3) +model.nbVarF = 2; %Objective function dimension (x1,x2) + +model.rfactor = 1E-2; %Control weight term +% model.Mu = [2; 4]; %Target (x1h,x2h) +model.Mu = rand(model.nbVarF, model.nbPoints) * 5; %Viapoints + +model.l = [2,2,2]; %Link length + +R = speye((model.nbData-1)*model.nbVarU) * model.rfactor; %Control weight matrix (at trajectory level) +% Rx = speye(model.nbData*model.nbVarX) * model.rfactor; + +% Q = kron(eye(model.nbData), inv(model.Sigma)); %Sparse precision matrix (at trajectory level) +% MuQ = kron(ones(model.nbData,1), model.Mu); %Sparse reference (at trajectory level) + +% Q = blkdiag(sparse((model.nbData-1)*2,(model.nbData-1)*2), diag([1E1, 1E1])); %Sparse precision matrix (at trajectory level) +% MuQ = [sparse((model.nbData-1)*2,1); model.Mu]; %Sparse reference (at trajectory level) + +%Sparse reference with a set of via-points +tl = linspace(1, model.nbData, model.nbPoints+1); +tl = round(tl(2:end)); +MuQ = sparse(model.nbVarF * model.nbData, 1); +Q = sparse(model.nbVarF * model.nbData, model.nbVarF * model.nbData); +for t=1:length(tl) + id(:,t) = (tl(t) - 1) * model.nbVarF + [1:model.nbVarF]; + Q(id(:,t), id(:,t)) = eye(model.nbVarF) * 1E3; + MuQ(id(:,t)) = model.Mu(:,t); +end + + +%% Iterative LQR (iLQR) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% u = zeros(model.nbVarU, model.nbData-1); +% u = repmat(linspace(0,1E-3,model.nbData-1), model.nbVarU, 1); +u = ones(model.nbVarU, model.nbData-1) * pi/8; +x0 = zeros(model.nbVarX,1); + +% uSigma = zeros(model.nbVarU*(model.nbData-1)); +% xSigma = zeros(model.nbVarX*model.nbData); + +for n=1:model.nbIter + %System evolution + x = dynSysSimulation(x0, u, model); +% x = reshape(Su * u(:) + Sx * x0, model.nbVarX, model.nbData); + + %Linearization + if n==1 %Constant Su and Sx for the proposed system + [A, B] = linSys(x, u, model); + [Su, Sx] = transferMatrices(A, B); + end + +% f=[]; +% % J=[]; +% % JQJ0=[]; JQ0=[]; +% for t=1:model.nbData +% ftmp = fkine(x(:,t), model); +% f = [f; ftmp]; %Endeffector positions in lifted form +% +% % Jtmp = jacob0(x(:,t), model); +% % J = blkdiag(J, Jtmp); %Jacobians in lifted form +% +% % %Alternative computation (equivalent if no constraint between time steps) +% % Jtmp = jacob0(x(:,t), model); +% % id = (t-1) * model.nbVarF + [1:model.nbVarF]; +% % JQJ0 = blkdiag(JQJ0, Jtmp' * Q(id,id) * Jtmp); +% % JQ0 = blkdiag(JQ0, Jtmp' * Q(id,id)); +% end +% f = fkine(x, model); + + %Alternative computation (fast version exploiting sparsity of Q) + f = sparse(model.nbData*model.nbVarF, 1); + JQJ = sparse(model.nbData*model.nbVarX, model.nbData*model.nbVarX); + JQ = sparse(model.nbData*model.nbVarX, model.nbData*model.nbVarF); + for t=1:length(tl) + Jtmp = jacob0(x(:,tl(t)), model); + idu = (tl(t) - 1) * model.nbVarU + [1:model.nbVarU]; + idf = (tl(t) - 1) * model.nbVarF + [1:model.nbVarF]; + JQJ(idu,idu) = Jtmp' * Q(idf,idf) * Jtmp; + JQ(idu,idf) = Jtmp' * Q(idf,idf); + f(idf) = fkine(x(:,tl(t)), model); + end + +% du_vec = (Su' * J' * Q * J * Su + R) \ (Su' * J' * Q * (MuQ - f(:)) - R * u(:)); %Control trajectory + du_vec = (Su' * JQJ * Su + R) \ (Su' * JQ * (MuQ - f(:)) - R * u(:)); %Control trajectory (alternative computation) + + delta_u = reshape(du_vec, model.nbVarU, model.nbData-1); + + %Estimate step size with line search method + alpha = 1; + cost0 = (MuQ - f(:))' * Q * (MuQ - f(:)) + u(:)' * R * u(:); + while 1 + utmp = u + delta_u * alpha; +% xtmp = dynSysSimulation(x0, utmp, model); + xtmp = reshape(Su * utmp(:) + Sx * x0, model.nbVarX, model.nbData); +% ftmp = []; +% for t=1:model.nbData +% ftmp = [ftmp; fkine(xtmp(:,t), model)]; %Endeffector positions in lifted form +% end + ftmp = fkine(xtmp, model); + cost = (MuQ - ftmp(:))' * Q * (MuQ - ftmp(:)) + utmp(:)' * R * utmp(:); %Compute the cost + if cost < cost0 || alpha < 1E-3 + break; + end + alpha = alpha * 0.5; + end + u = u + delta_u * alpha; %Update control by following gradient + +% uSigmaTmp = inv(Su' * J' * Q * J * Su + R); +% uSigma = uSigma + uSigmaTmp * alpha^2; +% xSigma = xSigma + Su * uSigmaTmp * Su' * alpha^2; + +% %Log data +% r(n).x = x; +% r(n).f = f; %reshape(f, model.nbVarF, model.nbData); +% r(n).u = u; +end + +%Log data +r(1).x = x; +r(1).f = fkine(x, model); +r(1).u = u; + + +%% Stochastic sampling by exploiting the nullspace structure of the problem +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% %Standard stochastic sampling +% uSigma = inv(Su' * J' * Q * J * Su + R); +% % xSigma = Su * uSigma * Su'; +% [V, D] = eig(full(uSigma)); +% U = real(V * D.^.5); +% nbSamples = 50; +% for n=1:nbSamples +% utmp = u(:) + U * randn(model.nbVarU*(model.nbData-1), 1) * 5E-2; +% qtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% ftmp = []; +% for t=1:model.nbData +% % Htmp = model.rob.fkine(qtmp(:,t)); %Forward kinematics +% % ftmp = [ftmp; Htmp.t(1:2)]; %Endeffector positions in lifted form +% ftmp = [ftmp; fkine(qtmp(:,t), model)]; %Endeffector positions in lifted form +% end +% sx(:,n) = ftmp; +% end + +% %Generate structured stochastic u through Bezier curves +% nbSamples = 50; +% nbRBF = 18; +% H = zeros(nbRBF, model.nbData-1); +% tl = linspace(0, 1, model.nbData-1); +% nbDeg = nbRBF - 1; +% for i=0:nbDeg +% H(i+1,:) = factorial(nbDeg) / (factorial(i) * factorial(nbDeg-i)) * (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions +% end +% %Nullspace planning +% [V,D] = eig(full(J' * Q * J)); +% U = V * D.^.5; +% N = eye((model.nbData-1)*model.nbVarU) - Su' * U / (U' * (Su * Su') * U + Rx) * U' * Su; %Nullspace projection matrix +% sx = zeros(model.nbData*2, nbSamples); +% for n=1:nbSamples +% w = randn(model.nbVarU, nbRBF) * 5E-1; %Random weights +% un = w * H; %Reconstruction of signals by weighted superposition of basis functions +% utmp = u(:) + N * un(:); +% qtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% ftmp = []; +% for t=1:model.nbData +% % Htmp = model.rob.fkine(qtmp(:,t)); %Forward kinematics +% % f = [f; Htmp.t(1:2)]; %Endeffector positions in lifted form +% ftmp = [ftmp; fkine(qtmp(:,t), model)]; %Endeffector positions in lifted form +% end +% sx(:,n) = ftmp; +% end + + +%% Plot state space +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10,10,1000,800],'color',[1,1,1]); hold on; axis off; +plotArm(r(end).x(:,1), ones(model.nbVarU,1)*model.l, [0; 0; -3], .2, [.8 .8 .8]); +plotArm(r(end).x(:,model.nbData/2+1), ones(model.nbVarU,1)*model.l, [0; 0; -2], .2, [.6 .6 .6]); +plotArm(r(end).x(:,model.nbData), ones(model.nbVarU,1)*model.l, [0; 0; -1], .2, [.4 .4 .4]); + +% for k=1:length(r) +% plot(r(k).f(1,:), r(k).f(2,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end + +% %Stochastic samples +% for n=1:nbSamples +% plot(sx(1:2:end,n), sx(2:2:end,n), '-','linewidth',1,'color',(ones(1,3)-n/nbSamples)*.9); +% end + +colMat = lines(model.nbPoints); +for i=1:model.nbPoints + plot2Dframe(eye(2)*4E-1, model.Mu(:,i), repmat(colMat(i,:),3,1), 6); +end + +plot(r(end).f(1,:), r(end).f(2,:), '-','linewidth',2,'color',[0 0 0]); +h(1) = plot(r(end).f(1,1), r(end).f(2,1), '.','markersize',40,'color',[0 0 0]); +% h(2) = plot3(model.Mu(1,:), model.Mu(2,:), ones(1,size(model.Mu,2)), '.','markersize',40,'color',[.8 0 0]); +% legend(h,{'Initial endeffector position','Target endeffector viapoint position'},'location','northwest','fontsize',20); +axis equal; %axis([-3.5 6.5 -2 5.5]); +% print('-dpng','graphs/DDP_manipulator01.png'); + + +% %% Plot control space +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[1020,10,1000,1000]); +% t = model.dt:model.dt:model.dt*model.nbData; +% for kk=1:size(r(1).u,1) +% subplot(size(r(1).u,1), 1, kk); grid on; hold on; box on; box on; +% for k=1:length(r) +% plot(t(1:end-1), r(k).u(kk,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end +% plot(t(1:end-1), r(end).u(kk,:), '-','linewidth',2,'color',[0 0 0]); +% axis([min(t), max(t(1:end-1)), min(r(end).u(kk,:))-.1, max(r(end).u(kk,:))+.1]); +% xlabel('t'); ylabel(['u_' num2str(kk)]); +% end + + +% %% Plot animated robot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 700 700],'color',[1 1 1]); hold on; axis off; +% plot3(model.Mu(1), model.Mu(2), 1, '.','markersize',40,'color',[.8 0 0]); +% axis equal; axis([-3.5 6.5 -1 5.5]); +% for t=1:model.nbData +% h = plotArm(r(end).x(:,t), ones(model.nbVarU,1)*model.l, zeros(3,1), .2, [0 0 0]); +% drawnow; +% % print('-dpng',['graphs/anim/DDP_manipulator_anim' num2str(t,'%.3d') '.png']); +% if t<model.nbData +% delete(h); +% end +% end +% % for t=model.nbData+1:model.nbData+10 +% % print('-dpng',['graphs/anim/DDP_manipulator_anim' num2str(t,'%.3d') '.png']); +% % end + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Given the control trajectory u and initial state x0, compute the whole state trajectory +function x = dynSysSimulation(x0, u, model) + x = zeros(model.nbVarX, model.nbData); + x(:,1) = x0; + for t=1:model.nbData-1 + x(:,t+1) = x(:,t) + u(:,t) * model.dt; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Linearize the system along the trajectory computing the matrices A and B +function [A, B] = linSys(x, u, model) + A = zeros(model.nbVarX, model.nbVarX, model.nbData-1); + B = zeros(model.nbVarX, model.nbVarU, model.nbData-1); + Ac = zeros(model.nbVarX); + Bc = eye(model.nbVarX, model.nbVarU); + for t=1:model.nbData-1 + %Discretize the linear system + A(:,:,t) = eye(model.nbVarX) + Ac * model.dt; + B(:,:,t) = Bc * model.dt; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Forward kinematics +function [x, Tf] = fkine(q, model) +% Tf = eye(4); +% T = repmat(Tf, [1,1,size(q,1)]); +% for n=1:size(q,1) +% c = cos(q(n)); +% s = sin(q(n)); +% T(:,:,n) = [c, -s, 0, model.l(n) * c; ... +% s, c, 0, model.l(n) * s; ... +% 0, 0, 1, 0; ... +% 0, 0, 0, 1]; %Homogeneous matrix +% Tf = Tf * T(:,:,n); +% end +% x = Tf(1:2,end); + +% x = [model.l * cos(tril(ones(model.nbVarU)) * q); model.l * sin(tril(ones(model.nbVarU)) * q)]; + + x = model.l * exp(1i * tril(ones(model.nbVarU)) * q); %Computation in matrix form + x = [real(x); imag(x)]; +end + +%%%%%%%%%%%%%%%%%%%%%% +%Jacobian +function J = jacob0(q, model) +% e = 1E-6; +% J = zeros(model.nbVarF, model.nbVarX); +% for n=1:size(q,1) +% qtmp = q; +% qtmp(n) = qtmp(n) + e; +% J(:,n) = (fkine(qtmp, model) - fkine(q, model)) / e; %Numeric computation +% end +% J + + J = 1i * exp(1i * tril(ones(model.nbVarU)) * q)' * tril(ones(model.nbVarU)) * diag(model.l); %Computation in matrix form + J = [-real(J); imag(J)]; +end \ No newline at end of file diff --git a/demos/demo_OC_DDP_pendulum01.m b/demos/demo_OC_DDP_pendulum01.m new file mode 100644 index 0000000000000000000000000000000000000000..fc4e5a1c6e8e98e0abda06058aa387cd2d04597d --- /dev/null +++ b/demos/demo_OC_DDP_pendulum01.m @@ -0,0 +1,266 @@ +function demo_OC_DDP_pendulum01 +% iLQR applied to an inverted pendulum problem +% +% Sylvain Calinon, 2020 +% +% Reference: +% W. Li and E. Todorov, "Iterative linear quadratic regulator design for nonlinear biological movement systems," +% in Intl Conf. on InfoRatics in Control, Automation and Robotics, 2004, pp. 222–229 + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +model.sim_time = 2; %Simulation time +model.dt = 2E-2; %Time step size +model.nbData = model.sim_time / model.dt; %Number of datapoints +model.nbIter = 10; %Number of iterations for iLQR + +model.nbVarPos = 1; %Dimension of position +model.nbDeriv = 2; %Number of derivatives (nbDeriv=2 for [x; dx] state) +model.nbVarX = model.nbVarPos * model.nbDeriv; %State space dimension +model.nbVarU = 1; %Control space dimension + +model.rfactor = 1E-5; %Control weight teR +model.Mu = [pi/2; 0]; %Target + +model.l = 1; %Link length +model.m = 1; %Mass +model.g = 9.81; %Acceleration due to gravity +model.b = 0.01; %Friction (optional) + +R = speye((model.nbData-1)*model.nbVarU) * model.rfactor; %Control weight matrix (at trajectory level) +Rx = speye(model.nbData*model.nbVarX) * model.rfactor; + +Q = blkdiag(sparse((model.nbData-1)*model.nbVarX, (model.nbData-1)*model.nbVarX), speye(model.nbVarX)*1E0); %Sparse precision matrix (at trajectory level) +MuQ = [sparse((model.nbData-1)*model.nbVarX,1); model.Mu]; %Sparse reference (at trajectory level) + + +%% Iterative LQR (iLQR) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% delta_x0 = zeros(model.nbVarX, 1); +u = zeros(model.nbVarU, model.nbData-1); +% x0 = zeros(model.nbVarX,1); +x0 = [-pi/2; 0]; + +% uSigma = zeros(model.nbVarU*(model.nbData-1)); +% xSigma = zeros(model.nbVarX*model.nbData); + +for n=1:model.nbIter + %System evolution + x = dynSysSimulation(x0, u, model); +% if n>1 +% x = reshape(Sx * x0 + Su * u(:), model.nbVarX, model.nbData); %Approximated dynamics +% end + + %Linearization + [A, B] = linSys(x, u, model); + [Su, Sx] = transferMatrices(A, B); + +% du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:) - Su' * Q * Sx * delta_x0); %Control trajectory + du_vec = (Su' * Q * Su + R) \ (Su' * Q * (MuQ - x(:)) - R * u(:)); %Control trajectory + delta_u = reshape(du_vec, model.nbVarU, model.nbData-1); +% delta_x = reshape(Sx * delta_x0 + Su * delta_u(:), model.nbVarX, model.nbData); + + %Estimate step size with line search method + alpha = 1; + cost0 = (MuQ - x(:))' * Q * (MuQ - x(:)) + u(:)' * R * u(:); + while 1 + utmp = u + delta_u * alpha; + xtmp = dynSysSimulation(x0, utmp, model); +% xtmp = reshape(Sx * x0 + Su * utmp(:), model.nbVarX, model.nbData); %Approximated dynamics + + cost = (MuQ - xtmp(:))' * Q * (MuQ - xtmp(:)) + utmp(:)' * R * utmp(:); %Compute the cost + if cost < cost0 || alpha < 1E-4 + break; + end + alpha = alpha * 0.5; + end +% disp(alpha); + u = u + delta_u * alpha; %Update control by following gradient + +% uSigmaTmp = inv(Su' * Q * Su + R); +% uSigma = uSigma + uSigmaTmp * alpha^2; +% xSigma = xSigma + Su * uSigmaTmp * Su' * alpha^2; + + %Log data + r(n).x = x; + r(n).u = u; +end + + +%% Stochastic sampling by exploiting the nullspace structure of the problem +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% %Standard stochastic sampling +% uSigma = inv(Su' * Q * Su + R); +% % xSigma = Su * uSigma * Su'; +% [V, D] = eig(full(uSigma)); +% U = real(V * D.^.5); +% nbSamples = 50; +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% for n=1:nbSamples +% utmp = u(:) + U * randn(model.nbVarU*(model.nbData-1), 1) * 1E-2; +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + +% %Generate structured stochastic u through Bezier curves +% nbSamples = 50; +% nbRBF = 18; +% H = zeros(nbRBF, model.nbData-1); +% tl = linspace(0, 1, model.nbData-1); +% nbDeg = nbRBF - 1; +% for i=0:nbDeg +% H(i+1,:) = factorial(nbDeg) / (factorial(i) * factorial(nbDeg-i)) * (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions +% end +% %Nullspace planning +% [V,D] = eig(full(Q)); +% U = V * D.^.5; +% N = eye((model.nbData-1)*model.nbVarU) - Su' * U / (U' * (Su * Su') * U + Rx) * U' * Su; %Nullspace projection matrix +% sx = zeros(model.nbData*model.nbVarX, nbSamples); +% for n=1:nbSamples +% w = randn(model.nbVarU, nbRBF) * 2E0; %Random weights +% un = w * H; %Reconstruction of signals by weighted superposition of basis functions +% utmp = u(:) + N * un(:); +% xtmp = dynSysSimulation(x0, reshape(utmp, model.nbVarU, model.nbData-1) , model); +% sx(:,n) = xtmp(:); +% end + + +%% Plot state space +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10,10,800,800]); hold on; axis on; grid on; box on; +% for t=1:model.nbData +% plotGMM(r(end).x(1:2,t), xSigma(2*(t-1)+[1,2],2*(t-1)+[1,2]).*3E-4, [.8 0 0], .05); +% end + +%iLQR refinement steps +for k=1:length(r) + plot(r(k).x(1,:), r(k).x(2,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +end + +% %Stochastic samples +% for n=1:nbSamples +% plot(sx(1:model.nbVarX:end,n), sx(2:model.nbVarX:end,n), '-','linewidth',1,'color',(ones(1,3)-n/nbSamples)*.9); +% end + +plot(r(end).x(1,:),r(end).x(2,:), '-','linewidth',2,'color',[.8 0 0]); +h(1) = plot(r(end).x(1,1),r(end).x(2,1), '.','markersize',30,'color',[0 0 0]); +h(2) = plot(model.Mu(1), model.Mu(2), '.','markersize',30,'color',[.8 0 0]); +legend(h,{'Initial state','Target'},'location','southeast','fontsize',20); +axis equal; axis([-pi pi -2 5]); +set(gca,'xtick',[-pi, -pi/2, 0, pi/2, pi],'xticklabel',{'-\pi','-\pi/2','0','\pi/2','\pi'},'ytick',0,'fontsize',22); +xlabel('$q$','interpreter','latex','fontsize',30); +ylabel('$\dot{q}$','interpreter','latex','fontsize',30); +% print('-dpng','graphs/DDP_pendulum_q_dq01.png'); + + +% %% Plot control space +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[1020,10,1000,1000]); +% t = model.dt:model.dt:model.dt*model.nbData; +% for kk=1:size(r(1).u,1) +% subplot(size(r(1).u,1), 1, kk); grid on; hold on; box on; box on; +% for k=1:length(r) +% plot(t(1:end-1), r(k).u(kk,:), '-','linewidth',1,'color',(ones(1,3)-k/length(r))*.9); +% end +% plot(t(1:end-1), r(end).u(kk,:), '-','linewidth',2,'color',[0 0 0]); +% axis([min(t), max(t(1:end-1)), min(r(end).u(kk,:))-2, max(r(end).u(kk,:))+2]); +% xlabel('t'); ylabel(['u_' num2str(kk)]); +% end + + +% %% Plot robot (static) +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 700 700],'color',[1 1 1]); hold on; axis off; +% plotArm(model.Mu(1), model.l, [0;0;20], .05, [.8 0 0]); +% for t=floor(linspace(1, model.nbData, 30)) +% plotArm(r(end).x(1,t), model.l, [0; 0; t*.1], .05, [.7 .7 .7]-.7*t/model.nbData); +% end +% axis equal; axis([-1.2 1.2 -1.2 1.2]); +% % print('-dpng','graphs/DDP_pendulum01.png'); + + +% %% Plot animated robot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 700 700],'color',[1 1 1]); hold on; axis off; +% plotArm(model.Mu(1), model.l, [0;0;-1], .05, [.8 0 0]); +% axis equal; axis([-1.2 1.2 -1.2 1.2]); +% h=[]; +% for t=1:model.nbData +% % delete(h); +% h = plotArm(r(end).x(1,t), model.l, zeros(3,1), .05, [0 0 0]); +% drawnow; +% % print('-dpng',['graphs/anim/DDP_pendulum_anim' num2str(t,'%.3d') '.png']); +% end +% % for t=model.nbData+1:model.nbData+10 +% % print('-dpng',['graphs/anim/DDP_pendulum_anim' num2str(t,'%.3d') '.png']); +% % end + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Given the control trajectory u and initial state x0, compute the whole state trajectory +function x = dynSysSimulation(x0, u, model) + b = model.b; + l = model.l; + m = model.m; + g = model.g; + x = zeros(model.nbVarX, model.nbData); + f = zeros(model.nbVarX, 1); + x(:,1) = x0; + for t=1:model.nbData-1 + f(1) = x(2,t); +% f(2) = u(t) / (m * l^2) - cos(x(1,t)) * g / l - (b / (m * l^2)) * x(2,t); %With friction + f(2) = u(t) / (m * l^2) - cos(x(1,t)) * g / l; %Without friction + x(:,t+1) = x(:,t) + f * model.dt; + end +end + +%%%%%%%%%%%%%%%%%%%%%% +%Linearize the system along the trajectory computing the matrices A and B +function [A, B] = linSys(x, u, model) + b = model.b; + g = model.g; + l = model.l; + m = model.m; + A = zeros(model.nbVarX, model.nbVarX, model.nbData-1); + B = zeros(model.nbVarX, model.nbVarU, model.nbData-1); + Bc = [0; (m * l^2)^2]; + for t=1:model.nbData-1 + %Linearize the system +% Ac = [0, 1; sin(x(1,t)) * g / l, -b / (m * l^2)]; %With friction + Ac = [0, 1; sin(x(1,t)) * g / l, 0]; %Without friction + + %Discretize the linear system + A(:,:,t) = eye(model.nbVarX) + Ac * model.dt; + B(:,:,t) = Bc * model.dt; + end + +% %Symbolic expressions to find linearized system +% syms b m l g x u +% x = sym('x',[2 1]); +% f(1) = x(2); +% f(2) = u / (m * l^2) - (g / l) * sin(x(1)) - (b / (m * l^2)) * x(2); +% jacobian(f, x) +% jacobian(f, u) +end \ No newline at end of file diff --git a/demos/demo_MPC01.m b/demos/demo_OC_LQT01.m similarity index 95% rename from demos/demo_MPC01.m rename to demos/demo_OC_LQT01.m index a6bac4861b914c654c953fbbafe2465cbd7354e8..6a06826be8ab106f1f8d0698ed053a88deb4ef6b 100644 --- a/demos/demo_MPC01.m +++ b/demos/demo_OC_LQT01.m @@ -1,5 +1,5 @@ -function demo_MPC01 -% Batch LQR with viapoints and a double integrator system. +function demo_OC_LQT01 +% Batch LQR with viapoints and simple/double/triple integrator system. % % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, @@ -36,7 +36,7 @@ addpath('./m_fcts/'); %% Parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nbData = 200; %Number of datapoints -nbPoints = 3; %Number of keypoints +nbPoints = 3; %Number of viapoints nbVarPos = 2; %Dimension of position data (here: x1,x2) nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) nbVar = nbVarPos * nbDeriv; %Dimension of state vector @@ -72,7 +72,7 @@ for n=2:nbData end -%% Task setting +%% Task setting (viapoints passing) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% tl = linspace(1, nbData, nbPoints+1); tl = round(tl(2:end)); diff --git a/demos/demo_MPC02.m b/demos/demo_OC_LQT02.m similarity index 99% rename from demos/demo_MPC02.m rename to demos/demo_OC_LQT02.m index 36135c3a0a909dc19ed98e68b6f8f8dc31619b72..837ddfdfd1afd6c5064615f4ab678d865c614f6f 100644 --- a/demos/demo_MPC02.m +++ b/demos/demo_OC_LQT02.m @@ -1,4 +1,4 @@ -function demo_MPC02 +function demo_OC_LQT02 % Batch computation of linear quadratic tracking problem, by tracking position and velocity references. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC03.m b/demos/demo_OC_LQT03.m similarity index 99% rename from demos/demo_MPC03.m rename to demos/demo_OC_LQT03.m index 0c7fb581194044b1aeef132e961fec844e47024b..6a9af095c637cb43cf8ac88fc9c9f7408bed91d5 100644 --- a/demos/demo_MPC03.m +++ b/demos/demo_OC_LQT03.m @@ -1,4 +1,4 @@ -function demo_MPC03 +function demo_OC_LQT03 % Batch computation of linear quadratic tracking problem, by tracking only position references. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC04.m b/demos/demo_OC_LQT04.m similarity index 99% rename from demos/demo_MPC04.m rename to demos/demo_OC_LQT04.m index 3d28f9a93b14deaccb8cd3d34791e9ac088da098..7a7a6462417416323bfcce8c0604ba19bb978b99 100644 --- a/demos/demo_MPC04.m +++ b/demos/demo_OC_LQT04.m @@ -1,4 +1,4 @@ -function demo_MPC04 +function demo_MPC_LQT04 % Control of a spring attached to a point with batch LQR (with augmented state space) % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_Lagrangian01.m b/demos/demo_OC_LQT_Lagrangian01.m similarity index 91% rename from demos/demo_MPC_Lagrangian01.m rename to demos/demo_OC_LQT_Lagrangian01.m index dc414780f0778c69d4b1b2f2afcfb2750686b80e..b9e4f38b90ef75c3e870b211239a6771f3c37f30 100644 --- a/demos/demo_MPC_Lagrangian01.m +++ b/demos/demo_OC_LQT_Lagrangian01.m @@ -1,5 +1,6 @@ -function demo_MPC_Lagrangian01 +function demo_OC_LQT_Lagrangian01 % Batch LQT with Lagrangian in matrix form to force first and last point to coincide in order to form a periodic motion. +% (see also demo_MPC_noInitialState01.m) % % If this code is useful for your research, please cite the related publication: % @incollection{Berio19MM, @@ -87,6 +88,11 @@ end Mu0 = [[-1;1], [1;1], [1;-1], [-1;-1]]; tl = linspace(1,nbData,nbPoints+2); tl = round(tl(2:end-1)); %[nbData/2, nbData]; + +% Mu0 = [[-1;1], [1;1], [1;-1], [-1;-1], [-1;1]]; +% tl = linspace(1,nbData,nbPoints); %+2); +% tl = round(tl); %%(2:end-1)); %[nbData/2, nbData]; + MuQ = zeros(nbVar*nbData,1); Q = zeros(nbVar*nbData); for t=1:length(tl) @@ -106,8 +112,8 @@ end %% Batch LQT with Lagrangian in matrix form %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% C = zeros(nbVar,nbData*nbVar); %Linear constraint C*x=0 -C(:,1:nbVar) = -eye(nbVar) .* 1E3; %p1-p2=0 (for both position and speed) -C(:,end-nbVar+1:end) = eye(nbVar) .* 1E3; %p1-p2=0 (for both position and speed) +C(:,1:nbVar) = -eye(nbVar) * 1E3; %p1-p2=0 (for both position and speed) +C(:,end-nbVar+1:end) = eye(nbVar) * 1E3; %p1-p2=0 (for both position and speed) %Augmented solution by finding the optimal initial state together with the optimal control commands S = [Su, Sx]; @@ -133,7 +139,7 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1000 1000],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; +figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; for t=1:nbData plotGMM(rx(nbVar*(t-1)+[1,2]), xSigma(nbVar*(t-1)+[1,2],nbVar*(t-1)+[1,2]).*1E-7, [.2 .2 .2], .1); end diff --git a/demos/demo_MPC_augmSigma01.m b/demos/demo_OC_LQT_augmSigma01.m similarity index 99% rename from demos/demo_MPC_augmSigma01.m rename to demos/demo_OC_LQT_augmSigma01.m index dde31d88b59d57b0d6bb85c26d7ceadc168d8412..eff9c7b18756819eb3a8891fd610f9b87d939105 100644 --- a/demos/demo_MPC_augmSigma01.m +++ b/demos/demo_OC_LQT_augmSigma01.m @@ -1,4 +1,4 @@ -function demo_MPC_augmSigma01 +function demo_OC_LQT_augmSigma01 % Batch LQR with augmented covariance to transform the tracking problem to a regulation problem. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_OC_LQT_ballistic01.m b/demos/demo_OC_LQT_ballistic01.m new file mode 100644 index 0000000000000000000000000000000000000000..c2f0af6a73fdbf37115ebe4451d4b3433ba2ee00 --- /dev/null +++ b/demos/demo_OC_LQT_ballistic01.m @@ -0,0 +1,134 @@ +function demo_OC_LQT_ballistic01 +% Batch LQT with augmented state to solve simple ballistic problem +% +% Sylvain Calinon, 2020 + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +nbData = 100; %Number of datapoints +nbVarX = 6; %Dimension of state vector +nbVarU = 2; %Dimension of state vector +dt = 1E-2; %Time step duration +rfactor = 1E-7; %dt^nbDeriv; %Control cost in LQR +R = speye((nbData-1)*nbVarU) * rfactor; %Control cost matrix + +m = 1; %Object mass +f = [0; -m*9.81]; %Gravity vector +x01 = [0; 0]; %Initial position +xTar = [1; 0]; %Target position +tRelease = 10; %Time step when ball is released + + +%% Linear dynamical system parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Ac = kron([0, 1, 0; 0, 0, 1; 0, 0, 0], eye(2)); +Bc = kron([0; 1; 0], eye(2)); +Ad = eye(nbVarX) + Ac * dt; %Parameters for discrete dynamical system +Bd = Bc * dt; %Parameters for discrete dynamical system + +%Build Sx and Su matrices for heterogeneous A and B +A = repmat(Ad,[1,1,nbData-1]); +B = repmat(Bd,[1,1,nbData-1]); +% B(:,:,2:end) = 0; %Control command at first time step only +B(:,:,tRelease:end) = 0; %Ball released at time step tRelease + +[Su, Sx] = transferMatrices(A, B); + + +%% Task setting (sparse reference to reach target at end of the motion) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Q = blkdiag(sparse((nbData-1)*nbVarX,(nbData-1)*nbVarX), diag([1E4, 1E4, 0, 0, 0, 0])); %Sparse precision matrix (at trajectory level) +MuQ = [sparse((nbData-1)*nbVarX,1); [xTar; 0; 0; 0; 0]]; %Sparse reference (at trajectory level) + + +%% Batch LQT +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +x0 = [x01; zeros(2,1); f]; +u = (Su' * Q * Su + R) \ Su' * Q * (MuQ - Sx * x0); +rx = reshape(Sx*x0+Su*u, nbVarX, nbData); %Reshape data for plotting + +uSigma = inv(Su' * Q * Su + R); +xSigma = Su * uSigma * Su'; + + +%% 2D plot +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10 10 800 800],'color',[1 1 1]); hold on; axis off; +set(0,'DefaultAxesLooseInset',[0,0,0,0]); +set(gca,'LooseInset',[0,0,0,0]); +% %Uncertainty +% for t=1:nbData +% plotGMM(rx(1:2,t), xSigma(nbVar*(t-1)+[1,2],nbVar*(t-1)+[1,2]) * 1E-3, [0 0 0], .04); %Ball motion +% end +%Ball motion +plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]); +h(1) = plot(rx(1,1), rx(2,1), '.','markersize',70,'color',[0 0 0]); %Initial position +h(2) = plot(rx(1,tRelease), rx(2,tRelease), '.','markersize',70,'color',[0 .6 0]); %Release position +h(3) = plot(xTar(1), xTar(2), '.','markersize',70,'color',[.8 0 0]); %Target position +axis equal; %axis([-.05 1.2,-.05 1.1]); +% %Animation +% for t=1:nbData +% ha(1) = plot(rx(1,t), rx(2,t), '.','markersize',70,'color',[0 0 0]); +% drawnow; +% delete(ha); +% end +legend(h,{'Initial point','Release point','Target point'},'fontsize',30,'location','northwest'); +legend('boxoff'); +% print('-dpng','graphs/MPC_ballistic_basic01.png'); + + +% %% 2D sampling plot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 1200 1200],'color',[1 1 1]); hold on; axis off; +% set(0,'DefaultAxesLooseInset',[0,0,0,0]); +% set(gca,'LooseInset',[0,0,0,0]); +% nbSamples = 50; +% [V,D] = eig(uSigma); +% for n=1:nbSamples +% u2 = u + real(V*D.^.5) * randn(size(u)).*1E-2; +% rx2 = reshape(Sx*x0+Su*u2, nbVar, nbData); %Reshape data for plotting +% patch('xdata',rx2(1,[1:t,t:-1:1]),'ydata',rx2(2,[1:t,t:-1:1]),'linewidth',4,'edgecolor',[0 0 0],'edgealpha',.05); %Ball motion +% plot(rx2(1,tRelease), rx2(2,tRelease), '.','markersize',30,'color',[0 .6 0]); %Release of ball +% % plot2DArrow(rx(1:2,tEvent(1)), diff(rx(1:2,tEvent(1):tEvent(1)+1),1,2)*12E0, [0 .6 0], 4, .01); +% % plot2DArrow(rx(7:8,tEvent(2)), diff(rx(7:8,tEvent(2):tEvent(2)+1),1,2)*12E0, [0 0 .8], 4, .01); +% end +% +% plot(rx(1,1), rx(2,1), '.','markersize',70,'color',[0 0 0]); %Initial position +% plot(xTar(1), xTar(2), '.','markersize',70,'color',[.8 0 0]); %Target position +% axis equal; axis([-.05 1.2,-.05 1.1]); +% % print('-dpng','graphs/MPC_ballistic02.png'); + + +% %% Additional plot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 1600 1200]); hold on; axis off; +% colormap(repmat(linspace(1,0,64),3,1)'); +% imagesc(Su); +% axis tight; axis equal; axis ij; + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), eye(nbVarX)); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + end + Su = zeros(nbVarX*(nbData-1), nbVarU*(nbData-1)); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end \ No newline at end of file diff --git a/demos/demo_MPC_constrained01.m b/demos/demo_OC_LQT_constrained01.m similarity index 99% rename from demos/demo_MPC_constrained01.m rename to demos/demo_OC_LQT_constrained01.m index cf4c9eadd1b277dc8304dc2623853c3bae02fdde..72cf633fb6542400e923b8627d1d2628c04d0eac 100644 --- a/demos/demo_MPC_constrained01.m +++ b/demos/demo_OC_LQT_constrained01.m @@ -1,4 +1,4 @@ -function demo_MPC_constrained01 +function demo_OC_LQT_constrained01 % Constrained batch LQT by using quadratic programming solver, with an encoding of position and velocity data. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_fullQ01.m b/demos/demo_OC_LQT_fullQ01.m similarity index 88% rename from demos/demo_MPC_fullQ01.m rename to demos/demo_OC_LQT_fullQ01.m index d0c1746a9289056bf16f7a7c078ce20734419a98..e33c71963551a7d0e57027c2714c7d72d39a54a1 100644 --- a/demos/demo_MPC_fullQ01.m +++ b/demos/demo_OC_LQT_fullQ01.m @@ -1,4 +1,4 @@ -function demo_MPC_fullQ01 +function demo_OC_LQT_fullQ01 % Batch LQT exploiting full Q matrix (e.g., by constraining the motion to pass through a common point at different time steps). % % If this code is useful for your research, please cite the related publication: @@ -39,7 +39,7 @@ nbData = 200; %Number of datapoints % nbData = 40; %Number of datapoints nbPoints = 3; %Number of keypoints nbVarPos = 2; %Dimension of position data (here: x1,x2) -nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) +nbDeriv = 1; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) nbVar = nbVarPos * nbDeriv; %Dimension of state vector dt = 1E-2; %Time step duration rfactor = 1E-8; %dt^nbDeriv; %Control cost in LQR @@ -109,18 +109,18 @@ end % Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0; % end -%Constraining the velocity before and after the keypoints to be correlated, effectively creating a straight line (version 2) -toff = 12; -for k=1:nbPoints-1 - for t=1:toff - id2(1:2,1) = id(:,k) - t * nbVar + nbVarPos; - id2(1:2,2) = id(:,k) + t * nbVar + nbVarPos; - Q(id2(:,1), id2(:,1)) = eye(nbVarPos)*1E0; - Q(id2(:,2), id2(:,2)) = eye(nbVarPos)*1E0; - Q(id2(:,1), id2(:,2)) = -eye(nbVarPos)*1E0; - Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0; - end -end +% %Constraining the velocity before and after the keypoints to be correlated, effectively creating a straight line (version 2) +% toff = 12; +% for k=1:nbPoints-1 +% for t=1:toff +% id2(1:2,1) = id(:,k) - t * nbVar + nbVarPos; +% id2(1:2,2) = id(:,k) + t * nbVar + nbVarPos; +% Q(id2(:,1), id2(:,1)) = eye(nbVarPos)*1E0; +% Q(id2(:,2), id2(:,2)) = eye(nbVarPos)*1E0; +% Q(id2(:,1), id2(:,2)) = -eye(nbVarPos)*1E0; +% Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0; +% end +% end % %Constraining the velocity before and after the keypoints to form a desired angle (version 1) % a = pi/2; %desired angle @@ -192,6 +192,15 @@ end % Q(id2(:,2), id2(:,1)) = -eye(nbVarPos)*1E0; % end +%Constraining R (same control command applied during a time interval) +toff = 12; +for k=1:nbPoints-1 + tt = tl(k) + [-toff,toff]; + id2 = tt(1) * nbVarPos +1 : tt(2) * nbVarPos; + R(id2,id2) = -1E-1 * kron(ones(2*toff), eye(nbVarPos)) + 2 * 1E-1 * eye(length(id2)); +end + + %% Batch LQR reproduction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -202,7 +211,7 @@ rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1000 1000],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; +figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]); plot(rx(1,1), rx(2,1), '.','markersize',35,'color',[0 0 0]); for k=1:nbPoints-1 @@ -213,6 +222,12 @@ plot(MuQ(id(1,:)), MuQ(id(2,:)), '.','markersize',35,'color',[.8 0 0]); axis equal; % print('-dpng','graphs/MPC_fullQ01a.png'); +%Plot 1D +figure; hold on; +plot(u(1:nbVarPos:end),'k-'); +plot(tl, 0, '.','markersize',25,'color',[0 .6 0]); +xlabel('t'); ylabel('u_1'); + % %Visualize Q % xlim = [1 size(Q,1); 1 size(Q,1)]; % figure('position',[1030 10 1000 1000],'color',[1 1 1]); hold on; axis off; diff --git a/demos/demo_MPC_fullQ02.m b/demos/demo_OC_LQT_fullQ02.m similarity index 99% rename from demos/demo_MPC_fullQ02.m rename to demos/demo_OC_LQT_fullQ02.m index 7e4f57773f0048db6d562b780d85df2f5dcea567..b19be31e5c82df5766d487ab0e8ce3270eb53d9f 100644 --- a/demos/demo_MPC_fullQ02.m +++ b/demos/demo_OC_LQT_fullQ02.m @@ -1,4 +1,4 @@ -function demo_MPC_fullQ02 +function demo_OC_LQT_fullQ02 % Batch LQT exploiting full Q matrix to constrain the motion of two agents. % % If this code is useful for your research, please cite the related publication: @@ -187,7 +187,7 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 2500 600]); +figure('position',[10 10 1200 600]); subplot(1,4,1); hold on; axis off; % set(0,'DefaultAxesLooseInset',[1,1,1,1]*1E2); % set(gca,'LooseInset',[1,1,1,1]*1E2); diff --git a/demos/demo_MPC_fullQ03.m b/demos/demo_OC_LQT_fullQ03.m similarity index 98% rename from demos/demo_MPC_fullQ03.m rename to demos/demo_OC_LQT_fullQ03.m index 7b12623e545c19b9931ca0a8339c195e5712e292..2c5f41425ec2f35bf54a00e4a16f9349cac6920d 100644 --- a/demos/demo_MPC_fullQ03.m +++ b/demos/demo_OC_LQT_fullQ03.m @@ -1,4 +1,4 @@ -function demo_MPC_fullQ03 +function demo_OC_LQT_fullQ03 % Batch LQT problem exploiting full Q matrix to constrain the motion of two agents in a simple ballistic task. % % If this code is useful for your research, please cite the related publication: @@ -117,7 +117,7 @@ rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1000 1000],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; +figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; %Agent 1 % for t=1:nbData diff --git a/demos/demo_OC_LQT_fullQ04.m b/demos/demo_OC_LQT_fullQ04.m new file mode 100644 index 0000000000000000000000000000000000000000..9ab144e73ff0c3f56e764eb6c7c704596d5d5688 --- /dev/null +++ b/demos/demo_OC_LQT_fullQ04.m @@ -0,0 +1,347 @@ +function demo_OC_LQT_fullQ04 +% Batch LQT problem exploiting full Q matrix to constrain the motion of two agents in a ballistic task mimicking a bimanual tennis serve problem +% +% If this code is useful for your research, please cite the related publication: +% @incollection{Calinon19chapter, +% author="Calinon, S. and Lee, D.", +% title="Learning Control", +% booktitle="Humanoid Robotics: a Reference", +% publisher="Springer", +% editor="Vadakkepat, P. and Goswami, A.", +% year="2019", +% pages="1261--1312", +% doi="10.1007/978-94-007-6046-2_68" +% } +% +% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ +% Written by Sylvain Calinon, http://calinon.ch/ +% +% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ +% +% PbDlib is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License version 3 as +% published by the Free Software Foundation. +% +% PbDlib is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +nbData = 200; %Number of datapoints +nbAgents = 3; %Number of agents +nbVarPos = 2 * nbAgents; %Dimension of position data (here: x1,x2 for the three agents) +nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) +nbVar = nbVarPos * (nbDeriv+1); %Dimension of state vector (incl. offset to apply gravity effect) +nbVarU = 4; %Number of control variables (acceleration commands of the two hands) +dt = 1E-2; %Time step duration +rfactor = 1E-8; %dt^nbDeriv; %Control cost in LQR +R = speye((nbData-1)*nbVarU) * rfactor; %Control cost matrix + +m = [2*1E-1, 2*1E-1, 2*1E-1]; %Mass of agents (left hand, right hand and ball) +g = [0; -9.81]; %Gravity vector + +tEvent = [50, 100, 150]; %Time steps for ball release and ball hitting +x01 = [1.6; 0]; %Inital position of Agent 1 (left hand) +x02 = [2; 0]; %Inital position of Agent 2 (right hand) +xTar = [1; -.2]; %Final position of Agent 3 (ball) + +% tEvent = [40, 110, 190]; %40 50 %Time steps for ball release and ball hitting +% x01 = [1.4; .2]; %Inital position of Agent 1 (left hand) +% x02 = [2; -.1]; %Inital position of Agent 2 (right hand) +% xTar = [1.3; 0]; %Final position of Agent 3 (ball) + + +%% Linear dynamical system parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Ac1 = kron([0, 1, 0; 0, 0, 1; 0, 0, 0], eye(2)); +Bc1 = kron([0; 1; 0], eye(2)); +Ac = kron(eye(nbAgents), Ac1); +Bc = [kron(eye(2), Bc1); zeros(6,nbVarU)]; %Ball is not directly controlled + +Ad = eye(nbVar) + Ac * dt; %Parameters for discrete dynamical system +Bd = Bc * dt; %Parameters for discrete dynamical system + +%Set heterogeneous A and B +A = repmat(Ad, [1,1,nbData-1]); +B = repmat(Bd, [1,1,nbData-1]); + +%Set Agent 3 state (ball) equals to Agent 1 state (left hand) until tEvent(1) +A(13:16,:,1:tEvent(1)) = 0; +% A(13:14,13:14,1:tEvent(1)) = repmat(eye(2),[1,1,tEvent(1)]); +A(13:14,1:2,1:tEvent(1)) = repmat(eye(2),[1,1,tEvent(1)]); +A(13:14,3:4,1:tEvent(1)) = repmat(eye(2),[1,1,tEvent(1)]) * dt; +A(15:16,3:4,1:tEvent(1)) = repmat(eye(2),[1,1,tEvent(1)]); +A(15:16,5:6,1:tEvent(1)) = repmat(eye(2),[1,1,tEvent(1)]) * dt; +% A(13:18,:,1) + +%Set Agent 3 state (ball) equals to Agent 2 state (right hand) at tEvent(2) +A(13:16,:,tEvent(2)) = 0; +% A(13:14,13:14,tEvent(2)) = eye(2); +A(13:14,7:8,tEvent(2)) = eye(2); +A(13:14,9:10,tEvent(2)) = eye(2) * dt; +A(15:16,9:10,tEvent(2)) = eye(2); +A(15:16,11:12,tEvent(2)) = eye(2) * dt; +% A(13:18,:,tEvent(2)) + +[Su, Sx] = transferMatrices(A, B); %Build transfer matrices + +% figure('position',[10 10 1600 1200]); hold on; axis off; +% imagesc(Su); +% axis tight; axis equal; axis ij; + + +%% Task setting +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +MuQ = zeros(nbVar*nbData,1); +Q = zeros(nbVar*nbData); + +%Agent 1 (left hand) and Agent 2 (right hand) must come back to initial pose at tEvent(3) and stay here +for t=tEvent(3):nbData + id = [1:4] + (t-1) * nbVar; %Left hand + Q(id,id) = eye(4) * 1E3; + MuQ(id) = [x01; zeros(2,1)]; + id = [7:10] + (t-1) * nbVar; %Right hand + Q(id,id) = eye(4) * 1E3; + MuQ(id) = [x02; zeros(2,1)]; + +% id = [1:2] + (t-1) * nbVar; %Left hand +% Q(id,id) = eye(2); +% MuQ(id) = x01; +% id = [7:8] + (t-1) * nbVar; %Right hand +% Q(id,id) = eye(2); +% MuQ(id) = x02; + +% id = [3:4] + (t-1) * nbVar; %Left hand +% Q(id,id) = eye(2); +% MuQ(id) = zeros(2,1); +% id = [9:10] + (t-1) * nbVar; %Right hand +% Q(id,id) = eye(2); +% MuQ(id) = zeros(2,1); +end + +%Agent 3 (ball) must reach desired target at the end of the movement +id = [13:14] + (nbData-1) * nbVar; +Q(id,id) = eye(2); +MuQ(id) = xTar; + +%Agent 2 and Agent 3 must meet at tEvent(2) (right hand hitting the ball) +id = [7:8,13,14] + (tEvent(2)-1) * nbVar; +MuQ(id) = rand(4,1); +MuQ(id(3:4)) = MuQ(id(1:2)); %Proposed common meeting point for the two agents (can be any point) +Q(id,id) = eye(4); +Q(id(1:2), id(3:4)) = -eye(2); +Q(id(3:4), id(1:2)) = -eye(2); + + +%% Batch LQT reproduction +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +x0 = [x01; zeros(2,1); m(1)*g; ... + x02; zeros(2,1); m(2)*g; ... + x01; zeros(2,1); m(3)*g]; +u = (Su' * Q * Su + R) \ Su' * Q * (MuQ - Sx * x0); +rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting + +% uSigma = inv(Su' * Q * Su + R); +% xSigma = Su * uSigma * Su'; + + +%% 2D plot +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10 10 1200 800],'color',[1 1 1]); hold on; axis off; +% %Uncertainty +% for t=1:nbData +% plotGMM(rx(1:2,t), xSigma(nbVar*(t-1)+[1,2],nbVar*(t-1)+[1,2])*3E-7, [0 0 0], .04); %Agent 1 (left hand) +% end +% for t=1:nbData +% plotGMM(rx(7:8,t), xSigma(nbVar*(t-1)+[7,8],nbVar*(t-1)+[7,8])*3E-7, [.6 .6 .6], .08); %Agent 2 (right hand) +% end +% for t=1:nbData +% plotGMM(rx(13:14,t), xSigma(nbVar*(t-1)+[13,14],nbVar*(t-1)+[13,14])*3E-7, [.8 .4 0], .08); %Agent 3 (ball) +% end + +%Agents +h(1) = plot(rx(1,:), rx(2,:), '-','linewidth',4,'color',[0 0 0]); %Agent 1 (left hand) +h(2) = plot(rx(7,:), rx(8,:), '-','linewidth',4,'color',[.6 .6 .6]); %Agent 2 (right hand) +h(3) = plot(rx(13,:), rx(14,:), ':','linewidth',4,'color',[.8 .4 0]); %Agent 3 (ball) + +%Events +h(4) = plot(rx(1,1), rx(2,1), '.','markersize',40,'color',[0 0 0]); %Initial position (left hand) +h(5) = plot(rx(7,1), rx(8,1), '.','markersize',40,'color',[.6 .6 .6]); %Initial position (right hand) +h(6) = plot(rx(1,tEvent(1)), rx(2,tEvent(1)), '.','markersize',40,'color',[0 .6 0]); %Release of ball +h(7) = plot(rx(7,tEvent(2)), rx(8,tEvent(2)), '.','markersize',40,'color',[0 0 .8]); %Hitting of ball +h(8) = plot(xTar(1), xTar(2), '.','markersize',40,'color',[.8 0 0]); %Ball target +plot2DArrow(rx(1:2,tEvent(1)), diff(rx(1:2,tEvent(1):tEvent(1)+1),1,2)*12E0, [0 .6 0], 4, .01); +plot2DArrow(rx(7:8,tEvent(2)), diff(rx(7:8,tEvent(2):tEvent(2)+1),1,2)*12E0, [0 0 .8], 4, .01); +axis equal; axis([1, 2.2, -0.3, 0.2]); + +% text(rx(1,1)+.01, rx(2,1)-.01,'$t=0$','interpreter','latex','fontsize',20); +% text(rx(1,1)+.01, rx(2,1)-.03,'$t=\frac{3T}{4}$','interpreter','latex','fontsize',20); +% text(rx(7,1)+.01, rx(8,1)+.02,'$t=0$','interpreter','latex','fontsize',20); +% text(rx(7,1)+.01, rx(8,1),'$t=\frac{3T}{4}$','interpreter','latex','fontsize',20); +% text(rx(1,tEvent(1))-.01, rx(2,tEvent(1))-.02,'$t=\frac{T}{4}$','interpreter','latex','fontsize',20); +% text(rx(13,tEvent(2))+.01, rx(14,tEvent(2))+.01,'$t=\frac{T}{2}$','interpreter','latex','fontsize',20); +% text(xTar(1)+.02, xTar(2),'$t=T$','interpreter','latex','fontsize',20); +% legend(h, {'Left hand motion (Agent 1)','Right hand motion (Agent 2)','Ball motion (Agent 3)', ... +% 'Left hand initial point','Right hand initial point','Ball releasing point','Ball hitting point','Ball target'}, 'fontsize',20,'location','northwest'); +% legend('boxoff'); +% print('-dpng','graphs/MPC_tennisServe01.png'); + + +% %% 2D animated plot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 1100 450],'color',[1 1 1]); hold on; axis off; +% plot(rx(1,1), rx(2,1), '.','markersize',40,'color',[0 0 0]); %Initial position (left hand) +% plot(rx(7,1), rx(8,1), '.','markersize',40,'color',[.6 .6 .6]); %Initial position (right hand) +% plot(xTar(1), xTar(2), '.','markersize',40,'color',[.8 0 0]); %Ball target +% axis equal; axis([1, 2.2, -0.3, 0.2]); +% %Animation +% for t=1:nbData +% h(1) = plot(rx(1,1:t), rx(2,1:t), '-','linewidth',4,'color',[0 0 0]); %Agent 1 (left hand) +% h(2) = plot(rx(7,1:t), rx(8,1:t), '-','linewidth',4,'color',[.6 .6 .6]); %Agent 2 (right hand) +% h(3) = plot(rx(13,1:t), rx(14,1:t), ':','linewidth',4,'color',[.8 .4 0]); %Agent 3 (ball) +% % h(1) = patch('xdata',rx(1,[1:t,t:-1:1]),'ydata',rx(2,[1:t,t:-1:1]),'linewidth',4,'edgecolor',[0 0 0],'edgealpha',.2); %Agent 1 (left hand) +% % h(2) = patch('xdata',rx(7,[1:t,t:-1:1]),'ydata', rx(8,[1:t,t:-1:1]),'linewidth',4,'edgecolor',[.6 .6 .6],'edgealpha',.2); %Agent 2 (right hand) +% % h(3) = patch('xdata',rx(13,[1:t,t:-1:1]),'ydata', rx(14,[1:t,t:-1:1]),'linewidth',4,'edgecolor',[.8 .4 0],'edgealpha',.2); %Agent 3 (ball) %'linestyle',':' +% +% h(4) = plot(rx(1,t), rx(2,t), '.','markersize',60,'color',[0 0 0]); +% h(5) = plot(rx(7,t), rx(8,t), '.','markersize',60,'color',[.6 .6 .6]); +% h(6) = plot(rx(13,t), rx(14,t), '.','markersize',50,'color',[.8 .4 0]); +% drawnow; +% print('-dpng',['graphs/anim/mpc01_' num2str(t,'%.3d') '.png']); +% delete(h); +% end + + +% %% Sampling plot +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 2200 900],'color',[1 1 1]); hold on; axis off; +% nbSamples = 50; +% [V,D] = eig(uSigma); +% plot(rx(1,1), rx(2,1), '.','markersize',40,'color',[0 0 0]); %Initial position (left hand) +% plot(rx(7,1), rx(8,1), '.','markersize',40,'color',[.6 .6 .6]); %Initial position (right hand) +% plot(xTar(1), xTar(2), '.','markersize',40,'color',[.8 0 0]); %Ball target +% for n=1:nbSamples +% u2 = u + real(V*D.^.5) * randn(size(u)).*2E-4; +% rx = reshape(Sx*x0+Su*u2, nbVar, nbData); %Reshape data for plotting +% %Agents +% patch('xdata',rx(1,[1:t,t:-1:1]),'ydata',rx(2,[1:t,t:-1:1]),'linewidth',4,'edgecolor',[0 0 0],'edgealpha',.2); %Agent 1 (left hand) +% patch('xdata',rx(7,[1:t,t:-1:1]),'ydata', rx(8,[1:t,t:-1:1]),'linewidth',4,'edgecolor',[.6 .6 .6],'edgealpha',.2); %Agent 2 (right hand) +% patch('xdata',rx(13,[1:t,t:-1:1]),'ydata', rx(14,[1:t,t:-1:1]),'linewidth',4,'edgecolor',[.8 .4 0],'edgealpha',.2); %Agent 3 (ball) %'linestyle',': +% %Events +% plot(rx(1,tEvent(1)), rx(2,tEvent(1)), '.','markersize',20,'color',[0 .6 0]); %Release of ball +% plot(rx(7,tEvent(2)), rx(8,tEvent(2)), '.','markersize',20,'color',[0 0 .8]); %Hitting of ball +% % plot2DArrow(rx(1:2,tEvent(1)), diff(rx(1:2,tEvent(1):tEvent(1)+1),1,2)*12E0, [0 .6 0], 4, .01); +% % plot2DArrow(rx(7:8,tEvent(2)), diff(rx(7:8,tEvent(2):tEvent(2)+1),1,2)*12E0, [0 0 .8], 4, .01); +% end +% axis equal; axis([1, 2.2, -0.3, 0.2]); +% % print('-dpng','graphs/MPC_tennisServe01f.png'); %convert -gravity Center -crop 80x80%+10-50 MPC_tennisServe01f.png MPC_tennisServe_cropped01f.png + + +% %% Timeline plots +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% figure('position',[10 10 2200 1200],'color',[1 1 1]); +% ttl = {'Left hand','','Right hand','','Ball',''}; +% %x +% id = [1:2,7:8,13:14]; +% for n=1:6 +% subplot(6,2,1+2*(n-1)); hold on; grid on; box on; title(ttl(n)); +% plot(rx(id(n),:),'k.'); +% if n<3 +% plot([1,tEvent(3)], [rx(id(n),1) rx(id(n),tEvent(3))], '.','markersize',40,'color',[0 0 0]); +% end +% if n>2 && n<5 +% plot([1,tEvent(3)], [rx(id(n),1) rx(id(n),tEvent(3))], '.','markersize',40,'color',[.6 .6 .6]); +% end +% if n<3 || n>4 +% plot(tEvent(1), rx(id(n),tEvent(1)), '.','markersize',40,'color',[0 .6 0]); +% end +% if n>2 +% plot(tEvent(2), rx(id(n),tEvent(2)), '.','markersize',40,'color',[0 0 .8]); +% end +% if n>4 +% plot(nbData, rx(id(n),nbData), '.','markersize',40,'color',[.8 0 0]); +% end +% m = round(min(rx(id(n),:)) + (max(rx(id(n),:)) - min(rx(id(n),:))) / 2, 1); +% axis([1, nbData, m-.6, m+.6]); +% set(gca,'xtick',[1,tEvent,nbData],'xticklabel',{},'ytick',sort([m-.6, m+.6, 0]),'fontsize',14); +% ylabel(['$x_' num2str(n) '$'],'interpreter','latex','fontsize',22); +% end +% set(gca,'xtick',[1,tEvent,nbData],'xticklabel',{'0','T/4','T/2','3T/4','T'},'fontsize',14); +% ylabel(['$x_' num2str(n) '$'],'interpreter','latex','fontsize',22); +% %dx +% id = [3:4,9:10,15:16]; +% for n=1:6 +% subplot(6,2,2*n); hold on; grid on; box on; title(ttl(n)); +% plot(rx(id(n),:),'k.'); +% if n<3 +% plot([1,tEvent(3)], [rx(id(n),1) rx(id(n),tEvent(3))], '.','markersize',40,'color',[0 0 0]); +% end +% if n>2 && n<5 +% plot([1,tEvent(3)], [rx(id(n),1) rx(id(n),tEvent(3))], '.','markersize',40,'color',[.6 .6 .6]); +% end +% if n<3 || n>4 +% plot(tEvent(1), rx(id(n),tEvent(1)), '.','markersize',40,'color',[0 .6 0]); +% end +% if n>2 && n<5 +% plot(tEvent(2), rx(id(n),tEvent(2)), '.','markersize',40,'color',[0 0 .8]); +% end +% if n>4 +% plot(tEvent(2)+1, rx(id(n),tEvent(2)+1), '.','markersize',40,'color',[0 0 .8]); +% end +% axis([1, nbData, -1.2, 1.2]); +% set(gca,'xtick',[1,tEvent,nbData],'xticklabel',{},'ytick',[-1.2, 0, 1.2],'fontsize',14); +% ylabel(['$\dot{x}_' num2str(n) '$'],'interpreter','latex','fontsize',22); +% end +% set(gca,'xtick',[1,tEvent,nbData],'xticklabel',{'0','T/4','T/2','3T/4','T'},'fontsize',14); +% ylabel(['$\dot{x}_' num2str(n) '$'],'interpreter','latex','fontsize',22); +% % print('-dpng','graphs/MPC_tennisServe02.png'); + + +%% Additional plots +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% %Timeline plots (u) +% figure('position',[10 10 2200 1200],'color',[1 1 1]); +% ttl = {'Left hand','','Right hand','','Ball (not controlled)',''}; +% for n=1:nbVarPos +% subplot(6,1,n); hold on; grid on; box on; title(ttl(n)); +% plot(u(n:nbVarPos:end),'k.'); +% set(gca,'xtick',[1,tEvent,nbData],'ytick',[0]); +% ylabel(['$u_' num2str(n) '$'],'interpreter','latex','fontsize',14); +% end + +% %Visualize Q +% figure('position',[1030 10 1000 1000],'color',[1 1 1],'name','Covariances'); hold on; box on; +% set(gca,'linewidth',2); title('Q','fontsize',14); +% colormap(gca, flipud(gray)); +% pcolor(abs(Q)); +% set(gca,'xtick',[1,size(Q,1)],'ytick',[1,size(Q,1)]); +% axis square; axis([1 size(Q,1) 1 size(Q,1)]); shading flat; + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end \ No newline at end of file diff --git a/demos/demo_MPC_infHor01.m b/demos/demo_OC_LQT_infHor01.m similarity index 97% rename from demos/demo_MPC_infHor01.m rename to demos/demo_OC_LQT_infHor01.m index c0272a5e691780e68bc31ef86a84ec18466b2f48..a9d46802022fb9cfa7875df2ac43bbdcd8dd785c 100644 --- a/demos/demo_MPC_infHor01.m +++ b/demos/demo_OC_LQT_infHor01.m @@ -1,4 +1,4 @@ -function demo_MPC_infHor01 +function demo_OC_LQT_infHor01 % Discrete infinite horizon linear quadratic regulation (with precision matrix only on position). % % If this code is useful for your research, please cite the related publication: @@ -39,7 +39,7 @@ nbData = 100; %Number of datapoints nbRepros = 10; %Number of reproductions nbVarPos = 2; %Dimension of position data (here: x1,x2) -nbDeriv = 1; %Number of static & dynamic features (D=2 for [x,dx]) +nbDeriv = 2; %Number of static & dynamic features (D=2 for [x,dx]) nbVar = nbVarPos * nbDeriv; %Dimension of state vector in the tangent space dt = 1E-2; %Time step duration rfactor = 4E-2; %Control cost in LQR @@ -80,7 +80,7 @@ L = (B' * P * B + R) \ B' * P * A; %Feedback gain (discrete version) if nbDeriv>1 kp = eigs(L(:,1:nbVarPos)); kv = eigs(L(:,nbVarPos+1:end)); - ratio = kv ./ (2.*kp).^.5 + ratio = kv ./ (2 * kp.^.5) end % figure; hold on; diff --git a/demos/demo_MPC_infHor02.m b/demos/demo_OC_LQT_infHor02.m similarity index 91% rename from demos/demo_MPC_infHor02.m rename to demos/demo_OC_LQT_infHor02.m index d2f2c4fcca7992bcccbd663a82691894d08425a2..5b6a0ef644bc98bb339112cb16b8f93326e45a03 100644 --- a/demos/demo_MPC_infHor02.m +++ b/demos/demo_OC_LQT_infHor02.m @@ -1,4 +1,4 @@ -function demo_MPC_infHor02 +function demo_OC_LQT_infHor02 % Discrete infinite horizon linear quadratic regulation (with precision matrix on position and velocity). % % If this code is useful for your research, please cite the related publication: @@ -50,11 +50,11 @@ R = eye(nbVarPos) * rfactor; % R = Ar*diag([1,.1])*Ar' * rfactor; %Target and desired covariance -Utar = [-1; .2; zeros(nbVarPos*(nbDeriv-1),1)]; +xTar = [-1; .2; zeros(nbVarPos*(nbDeriv-1),1)]; % [Ar,~] = qr(randn(nbVarPos)); % uCov = blkdiag(Ar*diag([.1,.1])*Ar' * 1E-1, eye(nbVarPos)); -uCov = diag([.1, .1, .1/dt, .1/dt]) * 1E-1; +xCov = diag([.1, .1, .1/dt, .1/dt]) * 1E-1; %% Discrete dynamical System settings (in tangent space) @@ -73,16 +73,16 @@ B = kron(B1d, eye(nbVarPos)); %Discrete nD %% Iterative discrete LQR with infinite horizon %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -Q = inv(uCov); %Precision matrix +Q = inv(xCov); %Precision matrix P = solveAlgebraicRiccati_eig_discrete(A, B*(R\B'), (Q+Q')/2); L = (B'*P*B + R) \ B'*P*A; %Feedback gain (discrete version) for n=1:nbRepros - U = [[-1; -1]+randn(nbVarPos,1)*5E-1; zeros(nbVarPos*(nbDeriv-1),1)]; + x = [[-1; -1]+randn(nbVarPos,1)*5E-1; zeros(nbVarPos*(nbDeriv-1),1)]; for t=1:nbData - r(n).Data(:,t) = U; - ddu = L * (Utar-U); %Compute acceleration (with only feedback terms) - U = A*U + B*ddu; + r(n).Data(:,t) = x; + u = L * (xTar - x); %Compute acceleration (with only feedback terms) + x = A*x + B*u; end end @@ -91,7 +91,7 @@ end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Plots figure('position',[10,10,650,650]); hold on; axis off; grid off; -plotGMM(Utar(1:nbVarPos), uCov(1:2,1:2), [.8 0 0],.3); +plotGMM(xTar(1:nbVarPos), xCov(1:2,1:2), [.8 0 0],.3); for n=1:nbRepros % for t=1:nbData % coltmp = [.3 1 .3] * (nbData-t)/nbData; diff --git a/demos/demo_MPC_infHor03.m b/demos/demo_OC_LQT_infHor03.m similarity index 98% rename from demos/demo_MPC_infHor03.m rename to demos/demo_OC_LQT_infHor03.m index 5d6bdfbfdb8735b566313bad49bef7b83a4c2a04..4c122776a692a95d7b3aa13d3072a29b812586b5 100644 --- a/demos/demo_MPC_infHor03.m +++ b/demos/demo_OC_LQT_infHor03.m @@ -1,4 +1,4 @@ -function demo_MPC_infHor03 +function demo_OC_LQT_infHor03 % Continuous infinite horizon linear quadratic tracking, by relying on a GMM encoding of position and velocity data. % (see also demo_MPC_infHor02.m for the corresponding discrete version, recommended for stability) % @@ -61,6 +61,7 @@ R = eye(model.nbVarPos) * model.rfactor; %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +demos=[]; load('data/2Dletters/G.mat'); Data=[]; for n=1:nbSamples @@ -167,7 +168,7 @@ end %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Plot position -figure('position',[10 10 1000 1000],'color',[1 1 1]); hold on; +figure('position',[10 10 800 800],'color',[1 1 1]); hold on; plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [0.5 0.5 0.5], .3); for n=1:nbSamples plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]); diff --git a/demos/demo_MPC_infHor04.m b/demos/demo_OC_LQT_infHor04.m similarity index 97% rename from demos/demo_MPC_infHor04.m rename to demos/demo_OC_LQT_infHor04.m index 0d2b9a939aaa76c1413e9b6dfddd03c491a4f09e..f2744dab1f947a139a17b599210003cb278725a4 100644 --- a/demos/demo_MPC_infHor04.m +++ b/demos/demo_OC_LQT_infHor04.m @@ -1,4 +1,4 @@ -function demo_MPC_infHor04 +function demo_OC_LQT_infHor04 % Discrete infinite horizon linear quadratic tracking, by relying on a GMM encoding of position and velocity data. % Compared to the continuous version, the discrete version is less sensitive to numerical instability when defining the R cost. % @@ -83,6 +83,7 @@ B = kron(B1d, eye(model.nbVarPos)); %Discrete nD %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +demos=[]; load('data/2Dletters/G.mat') Data=[]; for n=1:nbSamples @@ -170,7 +171,7 @@ end %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Plot position -figure('position',[10 10 1000 1000],'color',[1 1 1]); hold on; +figure('position',[10 10 800 800],'color',[1 1 1]); hold on; plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [0.5 0.5 0.5], .3); for n=1:nbSamples plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]); @@ -200,7 +201,7 @@ xlabel('x_1'); ylabel('x_2'); %% Timeline plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% labList = {'$x_1$','$x_2$','$\dot{x}_1$','$\dot{x}_2$','$\ddot{x}_1$','$\ddot{x}_2$'}; -figure('position',[1020 10 1000 1000],'color',[1 1 1]); hold on; +figure('position',[820 10 800 800],'color',[1 1 1]); hold on; for j=1:model.nbVar subplot(model.nbVar+1,1,j); hold on; for n=1:nbSamples diff --git a/demos/demo_MPC_noInitialState01.m b/demos/demo_OC_LQT_noInitialState01.m similarity index 94% rename from demos/demo_MPC_noInitialState01.m rename to demos/demo_OC_LQT_noInitialState01.m index 194f4f3d9307cc1baa932048e945d0d148196021..64da55a059a122e23d46ca0df31702b037085035 100644 --- a/demos/demo_MPC_noInitialState01.m +++ b/demos/demo_OC_LQT_noInitialState01.m @@ -1,5 +1,6 @@ -function demo_MPC_noInitialState01 +function demo_OC_LQT_noInitialState01 % Batch LQT solution determining the optimal initial state together with the optimal control commands. +% (see also demo_MPC_Lagrangian01.m) % % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, @@ -41,7 +42,7 @@ nbVarPos = 2; %Dimension of position data (here: x1,x2) nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) nbVar = nbVarPos * nbDeriv; %Dimension of state vector dt = 1E-2; %Time step duration -rfactor = 1E-8; %dt^nbDeriv; %Control cost in LQR +rfactor = 1E-8; %1E10; dt^nbDeriv; %Control cost in LQR R = speye((nbData-1)*nbVarPos) * rfactor; %Control cost matrix @@ -92,7 +93,7 @@ Ra = blkdiag(zeros(nbVar), R); ua = (S' * Q * S + Ra) \ S' * Q * MuQ; rx = reshape(S*ua, nbVar, nbData); %Reshape data for plotting -% x0 = ua(1:nbVar,1); %Optimal starting point +x0 = ua(1:nbVar,1); %Optimal starting point % u = ua(nbVar+1:end,1); %Optimal control commands % %Standard LQT solution @@ -106,6 +107,7 @@ rx = reshape(S*ua, nbVar, nbData); %Reshape data for plotting figure('position',[10 10 1000 1000],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]); plot(rx(1,1), rx(2,1), '.','markersize',40,'color',[0 0 0]); +plot(x0(1,1), x0(2,1), 'o','markersize',20,'color',[0 0 0]); plot(MuQ(id(1,:)), MuQ(id(2,:)), '.','markersize',40,'color',[.8 0 0]); axis equal; % print('-dpng','graphs/demo_MPC_noInitialState01.png'); diff --git a/demos/demo_MPC_nullspace01.m b/demos/demo_OC_LQT_nullspace01.m similarity index 96% rename from demos/demo_MPC_nullspace01.m rename to demos/demo_OC_LQT_nullspace01.m index 0b18b8f795140da5142b4698ef00c19b238ee35e..95d8ff5b3497df62e0c9f2da7d19c242ffee872d 100644 --- a/demos/demo_MPC_nullspace01.m +++ b/demos/demo_OC_LQT_nullspace01.m @@ -1,5 +1,6 @@ -function demo_MPC_nullspace01 +function demo_OC_LQT_nullspace01 % Batch LQT with nullspace formulation. +% (see also demo_MPC_legibility01.m) % % If this code is useful for your research, please cite the related publication: % @article{Girgin19, @@ -130,7 +131,7 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1000 1000],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; +figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; plotGMM(Mu, Sigma, [.8 0 0], .2); for n=1:nbRepros plot(r(n).x(1,:), r(n).x(2,:), '-','linewidth',1,'color',.9-[.7 .7 .7].*rand(1)); diff --git a/demos/demo_OC_LQT_nullspace02.m b/demos/demo_OC_LQT_nullspace02.m new file mode 100644 index 0000000000000000000000000000000000000000..6ea330143d7abdf105779fb9166c4f9f7cdabde2 --- /dev/null +++ b/demos/demo_OC_LQT_nullspace02.m @@ -0,0 +1,177 @@ +function demo_OC_LQT_nullspace02 +% Batch LQT with nullspace formulation: ballistic task with an augmented state space +% +% If this code is useful for your research, please cite the related publication: +% @article{Girgin19, +% author="Girgin, H. and Calinon, S.", +% title="Nullspace Structure in Model Predictive Control", +% journal="arXiv:1905.09679", +% year="2019", +% pages="1--16" +% } +% +% Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ +% Written by Sylvain Calinon and Hakan Girgin +% +% This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ +% +% PbDlib is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License version 3 as +% published by the Free Software Foundation. +% +% PbDlib is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with PbDlib. If not, see <http://www.gnu.org/licenses/>. + +addpath('./m_fcts/'); + + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +nbData = 200; %Number of datapoints +t_release = 50; %Time step when object is released +nbVarPos = 2; %Dimension of position data (here: x1,x2) +nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) +nbVar = nbVarPos * (nbDeriv+1); %Dimension of augmented state vector +dt = 1E-2; %Time step duration +rfactor = 1E-8; %dt^nbDeriv; %Control cost in LQR +R = speye((nbData-1)*nbVarPos) * rfactor; +Rx = speye(nbData*nbVar) * rfactor; + + +%% Dynamical System settings (augmented state space, discrete version) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Ac0 = kron([0, 1, 0; 0, 0, 0; 0, 0, 0], speye(nbVarPos)); +Ad0 = speye(nbVar) + Ac0 * dt; + +% Ac = kron([0, 1, 0; 0, 0, 0; 0, 0, 0], speye(nbVarPos)); +% Ac(4,end) = -9.81 * 1E0; %gravity +% Ad = speye(nbVar) + Ac * dt; + +Ac = kron([0, 1, 0; 0, 0, 1; 0, 0, 0], speye(nbVarPos)); +Ad = speye(nbVar) + Ac * dt; + +% Bd = kron([dt^2/2; dt; 0], speye(nbVarPos)); +Bc = kron([0; 1; 0], speye(nbVarPos)); +Bd = Bc * dt; + +% %Build Sx and Su transfer matrices(for homogeneous A and B) +% Su = sparse(nbVar*nbData, nbVarPos*(nbData-1)); +% Sx = kron(ones(nbData,1), speye(nbVar)); +% M = Bd; +% for n=2:nbData +% id1 = (n-1)*nbVar+1:nbData*nbVar; +% Sx(id1,:) = Sx(id1,:) * Ad; +% id1 = (n-1)*nbVar+1:n*nbVar; +% id2 = 1:(n-1)*nbVarPos; +% Su(id1,id2) = M; +% M = [Ad*M(:,1:nbVarPos), M]; +% end + +%Build Sx and Su transfer matrices(for heterogeneous A and B) +A = zeros(nbVar,nbVar,nbData-1); +B = zeros(nbVar,nbVarPos,nbData-1); +for t=1:nbData-1 + A(:,:,t) = Ad; + if t<t_release +% A(:,:,t) = Ad0; + B(:,:,t) = Bd; + end +end +[Su, Sx] = transferMatrices(A, B); + + +%% Task setting +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +MuQ = zeros(nbVar*nbData,1); +Q = zeros(nbVar*nbData); +id = [1:nbVarPos] + (nbData-1) * nbVar; +Q(id,id) = eye(nbVarPos); +MuQ(id) = rand(nbVarPos,1) - 0.5; + + +%% Batch LQR reproduction +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Generate structured stochastic u through Bezier curves +nbRBF = 18; +H = zeros(nbRBF,nbData-1); +tl = linspace(0,1,nbData-1); +nbDeg = nbRBF - 1; +for i=0:nbDeg + H(i+1,:) = factorial(nbDeg) ./ (factorial(i) .* factorial(nbDeg-i)) .* (1-tl).^(nbDeg-i) .* tl.^i; %Bernstein basis functions +end +w = randn(nbVarPos,nbRBF) .* 1E1; %Random weights +un = w * H; %Reconstruction of signals by weighted superposition of basis functions +un(:,t_release+1:end) = 0; + +%Nullspace planning +% x0 = [zeros(nbVarPos*nbDeriv,1); ones(nbVarPos,1)]; +x0 = [zeros(nbVarPos*nbDeriv,1); 0; -9.81*1E-1]; +u0 = (Su' * Q * Su + R) \ Su' * Q * (MuQ - Sx * x0); +rx0 = reshape(Sx*x0+Su*u0, nbVar, nbData); %Reshape data for plotting + +[V,D] = eig(Q); +U = V * D.^.5; +N = eye((nbData-1)*nbVarPos) - Su' * U / (U' * (Su * Su') * U + Rx) * U' * Su; %Nullspace projection matrix +u = Su' * U / (U' * (Su * Su') * U + Rx) * U' * (MuQ - Sx * x0) + N * un(:); +rx = reshape(Sx*x0+Su*u, nbVar, nbData); %Reshape data for plotting + + +%% Plot +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[10 10 800 800],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; +plot(rx0(1,:), rx0(2,:), '-','linewidth',2,'color',[.7 .7 .7]); +plot(rx0(1,1), rx0(2,1), '.','markersize',30,'color',[.7 .7 .7]); +plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]); +h(1) = plot(rx(1,1), rx(2,1), '.','markersize',30,'color',[0 0 0]); +h(2) = plot(rx(1,t_release), rx(2,t_release), '.','markersize',30,'color',[0 .6 0]); +plot(rx0(1,t_release), rx0(2,t_release), '.','markersize',30,'color',[.7 1 .7]); +h(3) = plot(MuQ(id(1)), MuQ(id(2)), '.','markersize',30,'color',[.8 0 0]); +legend(h, {'Initial point','Release of object','Target to reach'}); +axis equal; +% print('-dpng','graphs/demo_MPC_nullspace02.png'); + +%Timeline Plots +figure('position',[830,10,800,800]); +for j=1:nbVarPos + subplot(nbVarPos,1,j); hold on; %axis off; + plot(1:nbData-1, u0(j:nbVarPos:end), '-','linewidth',1,'color',[.7 .7 .7]); + plot(1:nbData-1, u(j:nbVarPos:end), '-','linewidth',1,'color',[0 0 0]); +% set(gca,'xtick',[],'ytick',[]); + plot([t_release,t_release], [min(u(j:nbVarPos:end)), max(u(j:nbVarPos:end))], '-','linewidth',2,'color',[0 .6 0]); + xlabel('$t$','interpreter','latex','fontsize',28); + ylabel(['$u_' num2str(j) '$'],'interpreter','latex','fontsize',28); +end +axis tight; + +% %Visualize Su matrix +% figure('position',[10 1050 400 650],'name','Su'); +% axes('Position',[0.01 0.01 .98 .98]); hold on; set(gca,'linewidth',2); +% colormap(flipud(gray)); +% pcolor([abs(Su) zeros(size(Su,1),1); zeros(1,size(Su,2)+1)]); %dummy values for correct display +% shading flat; axis ij; axis equal tight; +% set(gca,'xtick',[],'ytick',[]); + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%%%%% +function [Su, Sx] = transferMatrices(A, B) + [nbVarX, nbVarU, nbData] = size(B); + nbData = nbData+1; + Sx = kron(ones(nbData,1), speye(nbVarX)); + Su = sparse(zeros(nbVarX*(nbData-1), nbVarU*(nbData-1))); + for t=1:nbData-1 + id1 = (t-1)*nbVarX+1:t*nbVarX; + id2 = t*nbVarX+1:(t+1)*nbVarX; + id3 = (t-1)*nbVarU+1:t*nbVarU; + Sx(id2,:) = squeeze(A(:,:,t)) * Sx(id1,:); + Su(id2,:) = squeeze(A(:,:,t)) * Su(id1,:); + Su(id2,id3) = B(:,:,t); + end +end \ No newline at end of file diff --git a/demos/demo_MPC_online01.m b/demos/demo_OC_LQT_online01.m similarity index 97% rename from demos/demo_MPC_online01.m rename to demos/demo_OC_LQT_online01.m index e8fc21d4aeb491e20499ec6b47da8b0f6804a1d4..5d36cd1340763f0b5c53acf2da3246e51fcf788c 100644 --- a/demos/demo_MPC_online01.m +++ b/demos/demo_OC_LQT_online01.m @@ -1,4 +1,4 @@ -function demo_MPC_online01 +function demo_OC_LQT_online01 % MPC recomputed in an online manner with a time horizon. % % If this code is useful for your research, please cite the related publication: @@ -115,7 +115,7 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1000 1000]); hold on; axis off; +figure('position',[10 10 800 800]); hold on; axis off; plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]); plot(rx(1,1), rx(2,1), '.','markersize',35,'color',[0 0 0]); plot(MuQ0(id0(1,:)), MuQ0(id0(2,:)), '.','markersize',35,'color',[.8 0 0]); diff --git a/demos/demo_MPC_online02.m b/demos/demo_OC_LQT_online02.m similarity index 94% rename from demos/demo_MPC_online02.m rename to demos/demo_OC_LQT_online02.m index 1a79a4068f10ddc776552d5ca01b9a784dfd30cf..c3b713febb752b002144e3ade5f12c86191c6ce4 100644 --- a/demos/demo_MPC_online02.m +++ b/demos/demo_OC_LQT_online02.m @@ -1,4 +1,4 @@ -function demo_MPC_online02 +function demo_OC_LQT_online02 % MPC recomputed in an online manner with a time horizon, by relying on a GMM encoding of position and velocity data (with animation). % % If this code is useful for your research, please cite the related publication: @@ -35,12 +35,12 @@ addpath('./m_fcts/'); %% Parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nbSamples = 5; %Number of demonstrations +nbSamples = 8; %Number of demonstrations nbRepros = 1; %Number of reproductions in new situations nbData = 100; %Number of datapoints -nbD = 20; %Time window for LQR computation +nbD = 30; %Time window for LQR computation -model.nbStates = 3; %Number of Gaussians in the GMM +model.nbStates = 5; %Number of Gaussians in the GMM model.nbVarPos = 2; %Dimension of position data (here: x1,x2) model.nbDeriv = 2; %Number of static and dynamic features (nbDeriv=2 for [x,dx] and u=ddx) model.nbVar = model.nbVarPos * model.nbDeriv; %Dimension of state vector @@ -82,7 +82,8 @@ end %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -load('data/2Dletters/C.mat'); +demos=[]; +load('data/2Dletters/M.mat'); Data=[]; for n=1:nbSamples s(n).Data=[]; @@ -100,7 +101,7 @@ end %% Learning %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%model = init_GMM_kmeans(Data,model); +% model = init_GMM_kmeans(Data,model); model = init_GMM_kbins(Data,model,nbSamples); [model, H] = EM_GMM(Data, model); @@ -180,7 +181,7 @@ end %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 2500 1300],'color',[1 1 1]); +figure('position',[10 10 1600 800],'color',[1 1 1]); %Plot 2D subplot(model.nbVar+model.nbVarPos, 2, [1:2:(model.nbVar+model.nbVarPos)*2]); hold on; axis off; limAxes = [min(r(1).x(1,:))-8E0, max(r(1).x(1,:))+8E0, min(r(1).x(2,:))-8E0, max(r(1).x(2,:))+8E0]; @@ -233,9 +234,10 @@ for j=1:model.nbVar plot(r(n).x(j,:), '-','linewidth',2,'color',[.8 0 0]); end if j<7 - ylabel(labList{j},'fontsize',14,'interpreter','latex'); + ylabel(labList{j},'fontsize',22,'interpreter','latex'); end axis(v(j).limAxes); + set(gca,'xtick',[],'ytick',[]); end %Control profile @@ -247,10 +249,11 @@ for j=1:model.nbVarPos for n=1:nbRepros plot(r(n).u(j,:), '.','markersize',10,'color',[.8 0 0]); end - ylabel(['$u_' num2str(j) '$'],'fontsize',14,'interpreter','latex'); + ylabel(['$u_' num2str(j) '$'],'fontsize',22,'interpreter','latex'); axis(v(model.nbVar+j).limAxes); + set(gca,'xtick',[],'ytick',[]); end -xlabel('$t$','fontsize',14,'interpreter','latex'); +xlabel('$t$','fontsize',22,'interpreter','latex'); %Time window anim for tt=1:nbData diff --git a/demos/demo_MPC_online03.m b/demos/demo_OC_LQT_online03.m similarity index 98% rename from demos/demo_MPC_online03.m rename to demos/demo_OC_LQT_online03.m index 388b462ef03b164b27c9e85b86aef8227e0c3e3e..86289a5586ac864453f95bc6eade2534496ad34b 100644 --- a/demos/demo_MPC_online03.m +++ b/demos/demo_OC_LQT_online03.m @@ -1,4 +1,4 @@ -function demo_MPC_online03 +function demo_OC_LQT_online03 % Obstacle avoidance with MPC recomputed in an online manner. % % If this code is useful for your research, please cite the related publication: @@ -82,6 +82,7 @@ end %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +demos=[]; load('data/2Dletters/S.mat'); Data=[]; for n=1:nbSamples @@ -162,7 +163,7 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1200 1250],'color',[1 1 1]); hold on; axis off; +figure('position',[10 10 800 800],'color',[1 1 1]); hold on; axis off; plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [.8 .8 .8]); % for n=1:nbSamples % plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','lineWidth',1,'color',[.7 .7 .7]); @@ -185,7 +186,7 @@ axis equal; %% Timeline plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% labList = {'$x_1$','$x_2$','$\dot{x}_1$','$\dot{x}_2$','$\ddot{x}_1$','$\ddot{x}_2$'}; -figure('position',[1220 10 1000 1250],'color',[1 1 1]); +figure('position',[820 10 800 800],'color',[1 1 1]); for j=1:model.nbVar subplot(model.nbVar+1,1,j); hold on; limAxes = [1, nbData, min(Data(j,:))-4E0, max(Data(j,:))+4E0]; diff --git a/demos/demo_MPC_nullspace_online01.m b/demos/demo_OC_LQT_online_minimal01.m similarity index 63% rename from demos/demo_MPC_nullspace_online01.m rename to demos/demo_OC_LQT_online_minimal01.m index f042c2d7c94d9efc3b664dafa1c7a3fb9cfba89e..37cef020f5d76407c4b3bb5899c7ec31a7a805db 100644 --- a/demos/demo_MPC_nullspace_online01.m +++ b/demos/demo_OC_LQT_online_minimal01.m @@ -1,17 +1,20 @@ -function demo_MPC_nullspace_online01 -% Batch LQR recomputed in an online manner with nullspace formulation. +function demo_OC_LQT_online_minimal01 +% MPC recomputed in an online manner with a time horizon. % % If this code is useful for your research, please cite the related publication: -% @article{Girgin19, -% author="Girgin, H. and Calinon, S.", -% title="Nullspace Structure in Model Predictive Control", -% journal="arXiv:1905.09679", +% @incollection{Calinon19chapter, +% author="Calinon, S. and Lee, D.", +% title="Learning Control", +% booktitle="Humanoid Robotics: a Reference", +% publisher="Springer", +% editor="Vadakkepat, P. and Goswami, A.", % year="2019", -% pages="1--16" +% pages="1261--1312", +% doi="10.1007/978-94-007-6046-2_68" % } % % Copyright (c) 2019 Idiap Research Institute, http://idiap.ch/ -% Written by Sylvain Calinon and Hakan Girgin +% Written by Sylvain Calinon, http://calinon.ch/ % % This file is part of PbDlib, http://www.idiap.ch/software/pbdlib/ % @@ -70,7 +73,7 @@ for n=2:nbD end -%% Principal task setting +%% Task setting %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% tl = linspace(1,nbData,nbPoints+1); tl = round(tl(2:end)); @@ -83,71 +86,45 @@ for t=1:length(tl) end -%% Secondary task setting (simulating smooth random perturbations) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%Precomputation of basis functions to generate structured stochastic u through Bezier curves -nbRBF = 8; -H = zeros(nbRBF,nbData-1); -tlr = linspace(0,1,nbData-1); -nbDeg = nbRBF - 1; -for i=0:nbDeg - H(i+1,:) = factorial(nbDeg) ./ (factorial(i) .* factorial(nbDeg-i)) .* (1-tlr).^(nbDeg-i) .* tlr.^i; %Bernstein basis functions -end -w = randn(nbVarPos,nbRBF) .* 1E1; %Random weights -u0 = reshape(w * H, [nbVarPos*(nbData-1), 1]); %Reconstruction of signals by weighted superposition of basis functions - -% figure; hold on; -% % plot(u0(1:2:end), u0(2:2:end), 'k-'); -% x = zeros(nbVar,1); -% for t=1:nbData-1 -% x = A * x + B * u0((t-1)*nbVarPos+[1:nbVarPos]); %Update state with first control command -% plot(x(1), x(2), 'k.'); -% end -% pause; -% close all; -% return - - -%% Reproduction +%% Batch LQR reproduction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% x = zeros(nbVar,1); rx = zeros(nbVar,nbData); +% figure; hold on; +% h = []; for t=1:nbData rx(:,t) = x; %Log data - id = [t:min(t+nbD-1,nbData), ones(1,t-nbData+nbD-1)]; %Time steps involved in the MPC computation - id2=[]; - for s=1:nbD - id2 = [id2, [1:nbVar] + (id(s)-1) * nbVar]; + if t==20 + tl = linspace(1,nbData-20,nbPoints+1); + tl = round(tl(2:end)); + MuQ0 = zeros(nbVar*nbData,1); + Q0 = zeros(nbVar*nbData); + for t=1:length(tl) + id0(:,t) = [1:nbVarPos] + (tl(t)-1) * nbVar; + Q0(id0(:,t), id0(:,t)) = eye(nbVarPos); + MuQ0(id0(:,t)) = rand(nbVarPos,1) - 0.5; + end end - id = [t:min(t+nbD-1,nbData-1), ones(1,t-nbData+nbD-1)]; %Time steps involved in the MPC computation - id3=[]; - for s=1:nbD-1 - id3 = [id3, [1:nbVarPos] + (id(s)-1) * nbVarPos]; + id = [t:min(t+nbD-1,nbData), ones(1,t-nbData+nbD-1)]; %Time steps involved in the MPC computation + id2 = []; + for s=1:nbD + id2 = [id2; [1:nbVar]' + (id(s)-1) * nbVar]; end - MuQ = MuQ0(id2,1); Q = Q0(id2,id2); - - %Reproduction with nullspace planning - [V,D] = eig(Q); - U = V * D.^.5; - J = U' * Su; %Jacobian - %Left pseudoinverse solution - % pinvJ = pinv(J); - pinvJ = (J' * J + R) \ J'; %Left pseudoinverse - N = speye((nbD-1)*nbVarPos) - pinvJ * J; %Nullspace projection matrix - u1 = pinvJ * U' * (MuQ - Sx * x); %Principal task - - u = u1 + N * u0(id3); -% u = u0(id3); - + u = (Su' * Q * Su + R) \ Su' * Q * (MuQ - Sx * x); %Compute control commands x = A * x + B * u(1:nbVarPos); %Update state with first control command + +% delete(h); +% h(1) = plot(MuQ(1:nbVar:end),'k.'); +% h(2) = plot(x(1),'r.'); +% axis([1,nbD,min(MuQ0),max(MuQ0)]); +% pause(.001); end - %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% figure('position',[10 10 1000 1000]); hold on; axis off; @@ -158,7 +135,7 @@ for t=1:length(tl) text(MuQ0(id0(1,t)), MuQ0(id0(2,t))+2E-2, num2str(t)); end axis equal; -% print('-dpng','graphs/MPC_nullspace_online01.png'); +% print('-dpng','graphs/MPC_minimal01.png'); pause; close all; \ No newline at end of file diff --git a/demos/demo_MPC_iterativeLQR01.m b/demos/demo_OC_LQT_recursive01.m similarity index 87% rename from demos/demo_MPC_iterativeLQR01.m rename to demos/demo_OC_LQT_recursive01.m index 1bdddf87b42f44b72cc11b672ad5e82e0916d26e..2189ed5b153e3c03493bda06e9a657b5e2ace911 100644 --- a/demos/demo_MPC_iterativeLQR01.m +++ b/demos/demo_OC_LQT_recursive01.m @@ -1,4 +1,4 @@ -function demo_MPC_iterativeLQR01 +function demo_OC_LQT_recursive01 % Recursive computation of linear quadratic tracking (with feedback and feedforward terms). % % If this code is useful for your research, please cite the related publication: @@ -61,10 +61,10 @@ B = kron(B1d, speye(nbVarPos)); %Discrete nD %% Task setting %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -tl = linspace(1,nbData/2,nbPoints+1); +tl = linspace(1, nbData/2, nbPoints+1); tl = round(tl(2:end)); -MuQ = zeros(nbVar*nbData,1); -Q = zeros(nbVar*nbData); +% MuQ = zeros(nbVar*nbData,1); +% Q = zeros(nbVar*nbData); for t=1:length(tl) id(:,t) = [1:nbVarPos] + (tl(t)-1) * nbVar; % MuQ(id(:,t)) = rand(nbVarPos,1) - 0.5; @@ -75,8 +75,8 @@ for t=1:length(tl) end % Mu = reshape(MuQ, nbVar, nbData); -MuQ = kron(ones(nbData,1), [1;1;0;0]); -Q = blkdiag(zeros((nbData/2)*nbVar), kron(eye(nbData/2), diag([1,1,0,0])) .* 1E1); +MuQ = kron(ones(nbData,1), [1; 1; zeros(nbVar-nbVarPos,1)]); +Q = blkdiag(zeros((nbData/2)*nbVar), kron(eye(nbData/2), diag([1,1,zeros(1,nbVar-nbVarPos)])) * 1E1); Mu = reshape(MuQ, nbVar, nbData); % Q(end-1:end,end-1:end) = eye(2) .* 1E3; @@ -120,26 +120,26 @@ Mu = reshape(MuQ, nbVar, nbData); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% K = zeros(nbVarPos, nbVar, nbData-1); Kff = zeros(nbVarPos, nbVar, nbData-1); -S = zeros(nbVar, nbVar, nbData); -S(:,:,end) = Q(end-nbVar+1:end,end-nbVar+1:end); +P = zeros(nbVar, nbVar, nbData); +P(:,:,end) = Q(end-nbVar+1:end,end-nbVar+1:end); v = zeros(nbVar, nbData); v(:,end) = Q(end-nbVar+1:end,end-nbVar+1:end) * Mu(:,end); %Backward computation for t=nbData-1:-1:1 - Kff(:,:,t) = (B' * S(:,:,t+1) * B + R) \ B'; %FF - K(:,:,t) = Kff(:,:,t) * S(:,:,t+1) * A; %FB - S(:,:,t) = A' * S(:,:,t+1) * (A - B * K(:,:,t)) + Q((t-1)*nbVar+1:t*nbVar,(t-1)*nbVar+1:t*nbVar); + Kff(:,:,t) = (B' * P(:,:,t+1) * B + R) \ B'; %FF + K(:,:,t) = Kff(:,:,t) * P(:,:,t+1) * A; %FB + P(:,:,t) = A' * P(:,:,t+1) * (A - B * K(:,:,t)) + Q((t-1)*nbVar+1:t*nbVar,(t-1)*nbVar+1:t*nbVar); v(:,t) = (A - B * K(:,:,t))' * v(:,t+1) + Q((t-1)*nbVar+1:t*nbVar,(t-1)*nbVar+1:t*nbVar) * Mu(:,t); kp(:,t) = eigs(K(:,1:2,t)); kv(:,t) = eigs(K(:,3:4,t)); -% %Test ratio between kp and kv -% ratio(:,t) = kv(:,t) ./ (2.*kp(:,t)).^.5; + %Test ratio between kp and kv + ratio(:,t) = kv(:,t) ./ (2*kp(:,t)).^.5; end %Reproduction with feedback (FB) and feedforward (FF) terms x = zeros(nbVar,1); -rx(:,1) = X; %Log data +rx(:,1) = x; %Log data for t=2:nbData u = -K(:,:,t-1) * x + Kff(:,:,t-1) * v(:,t); %Acceleration command with FB and FF terms x = A * x + B * u; %Update of state vector @@ -149,14 +149,17 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -figure('position',[10 10 1000 1000]); hold on; axis off; +figure('position',[10 10 800 800]); hold on; axis off; plot(rx(1,:), rx(2,:), '-','linewidth',2,'color',[0 0 0]); plot(rx(1,1), rx(2,1), '.','markersize',50,'color',[0 0 0]); plot(MuQ(id(1,:)), MuQ(id(2,:)), '.','markersize',50,'color',[.8 0 0]); axis equal; %print('-dpng','graphs/LQT_x01.png'); -figure('position',[1020 10 800 1000]); + +%% Plot timeline +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +figure('position',[820 10 800 800]); % %phase % alpha = 2; % tIn = [1:nbData]*dt; @@ -175,6 +178,7 @@ figure('position',[1020 10 800 1000]); % subplot(2,1,1); hold on; grid on; % plot(ratio(1,:), '-','linewidth',2,'color',[0 0 0]); % xlabel('t'); ylabel('kp-kv ratio'); +% axis([1, nbData/2+20, 0, max(ratio(1,:))+.1]); %x subplot(2,1,1); hold on; grid on; @@ -194,6 +198,12 @@ set(gca,'linewidth',2,'xtick',100,'ytick',[kv(1,120),kp(1,120)],'xticklabel',{}, xlabel('$t$','interpreter','latex','fontsize',34); ylabel('$\kappa^{\scriptscriptstyle{P}},\kappa^{\scriptscriptstyle{V}}$','interpreter','latex','fontsize',34); %print('-dpng','graphs/demo_MPC_iterativeLQT01.png'); - + +% %Plot P +% figure('position',[820 10 800 800]); hold on; axis off; +% for t=round(linspace(nbData-1, 1, 20)) +% plotGMM(zeros(2,1), P(1:2,1:2,t), [.7 .7 .7], .1); +% end + pause; close all; \ No newline at end of file diff --git a/demos/demo_MPC_iterativeLQR02.m b/demos/demo_OC_LQT_recursive02.m similarity index 95% rename from demos/demo_MPC_iterativeLQR02.m rename to demos/demo_OC_LQT_recursive02.m index ac4505e1211da57e23d89c220a5a82b43ebbed09..50caf8fe03db1bed88399b4825a3806b760c7bbe 100644 --- a/demos/demo_MPC_iterativeLQR02.m +++ b/demos/demo_OC_LQT_recursive02.m @@ -1,4 +1,4 @@ -function demo_MPC_iterativeLQR02 +function demo_OC_LQT_recursive02 % Recursive computation of linear quadratic tracking (with feedback and feedforward terms), % by relying on a GMM encoding of position and velocity data, including comparison with batch LQT. % @@ -81,6 +81,7 @@ B = kron(B1d, eye(model.nbVarPos)); %Discrete nD %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +demos=[]; load('data/2Dletters/S.mat'); Data=[]; for n=1:nbSamples @@ -164,19 +165,19 @@ end % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % K = zeros(model.nbVarPos, model.nbVar, nbData-1); % Kff = zeros(model.nbVarPos, model.nbVar, nbData-1); -% S = zeros(model.nbVar, model.nbVar, nbData); -% S(:,:,end) = inv(model.Sigma(:,:,qList(nbData))); +% P = zeros(model.nbVar, model.nbVar, nbData); +% P(:,:,end) = inv(model.Sigma(:,:,qList(nbData))); % v = zeros(model.nbVar, nbData); % v(:,end) = inv(model.Sigma(:,:,qList(nbData))) * model.Mu(:,qList(nbData)); % % r(1).xx = zeros(model.nbVar, nbData-1); % %Backward computation % for t=nbData-1:-1:1 % Q = inv(model.Sigma(:,:,qList(t))); -% Kff(:,:,t) = (B' * S(:,:,t+1) * B + R) \ B'; %FF -% K(:,:,t) = Kff(:,:,t) * S(:,:,t+1) * A; %FB -% S(:,:,t) = A' * S(:,:,t+1) * (A - B * K(:,:,t)) + Q; +% Kff(:,:,t) = (B' * P(:,:,t+1) * B + R) \ B'; %FF +% K(:,:,t) = Kff(:,:,t) * P(:,:,t+1) * A; %FB +% P(:,:,t) = A' * P(:,:,t+1) * (A - B * K(:,:,t)) + Q; % v(:,t) = (A - B * K(:,:,t))' * v(:,t+1) + Q * model.Mu(:,qList(t)); -% % r(1).xx(:,t) = (S(:,:,t) * A) \ v(:,t); +% % r(1).xx(:,t) = (P(:,:,t) * A) \ v(:,t); % end % %Reproduction with feedback (FB) and feedforward (FF) terms % for n=1:nbRepros @@ -223,7 +224,7 @@ end %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Plot position -figure('position',[10 10 1000 1000],'color',[1 1 1]); hold on; +figure('position',[10 10 800 800],'color',[1 1 1]); hold on; plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [0.5 0.5 0.5], .3); for n=1:nbSamples plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]); diff --git a/demos/demo_MPC_iterativeLQR03.m b/demos/demo_OC_LQT_recursive03.m similarity index 98% rename from demos/demo_MPC_iterativeLQR03.m rename to demos/demo_OC_LQT_recursive03.m index f8fc44416de4d9723b9f8263696572f02f179f5e..7ee66e9d94b439a5bb01e6fca8b56d4541324737 100644 --- a/demos/demo_MPC_iterativeLQR03.m +++ b/demos/demo_OC_LQT_recursive03.m @@ -1,4 +1,4 @@ -function demo_MPC_iterativeLQR03 +function demo_OC_LQT_recursive03 % Recursive computation of linear quadratic tracking (with feedback and feedforward terms), % by relying on a GMM encoding of only position data. % @@ -87,6 +87,7 @@ C = kron([1, 0], eye(model.nbVarPos)); %% Load handwriting data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +demos=[]; load('data/2Dletters/G.mat'); Data=[]; for n=1:nbSamples @@ -142,7 +143,7 @@ end %% Plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Plot position -figure('position',[10 10 1000 1000],'color',[1 1 1]); hold on; +figure('position',[10 10 800 800],'color',[1 1 1]); hold on; plotGMM(model.Mu(1:2,:), model.Sigma(1:2,1:2,:), [0.5 0.5 0.5], .3); for n=1:nbSamples plot(Data(1,(n-1)*nbData+1:n*nbData), Data(2,(n-1)*nbData+1:n*nbData), '-','color',[.7 .7 .7]); diff --git a/demos/demo_MPC_iterativeLQR_augmSigma01.m b/demos/demo_OC_LQT_recursive_augmSigma01.m similarity index 99% rename from demos/demo_MPC_iterativeLQR_augmSigma01.m rename to demos/demo_OC_LQT_recursive_augmSigma01.m index a17f034107cf19210f8874ad375a8e73a82996fb..93fed8540554036d1f596114c5a9a4cc0460554d 100644 --- a/demos/demo_MPC_iterativeLQR_augmSigma01.m +++ b/demos/demo_OC_LQT_recursive_augmSigma01.m @@ -1,4 +1,4 @@ -function demo_MPC_iterativeLQR_augmSigma01 +function demo_OC_LQT_recursive_augmSigma01 % Recursive LQR with augmented covariance to transform the tracking problem to a regulation problem. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_skillsRepr01.m b/demos/demo_OC_LQT_skillsRepr01.m similarity index 99% rename from demos/demo_MPC_skillsRepr01.m rename to demos/demo_OC_LQT_skillsRepr01.m index 749bd97bfa72075671b0b356cf62e8112048b6c8..d2a3c5ee10f4d486e395977f0259c4c2536b5016 100644 --- a/demos/demo_MPC_skillsRepr01.m +++ b/demos/demo_OC_LQT_skillsRepr01.m @@ -1,4 +1,4 @@ -function demo_MPC_skillsRepr01 +function demo_OC_LQT_skillsRepr01 % Representation of skills combined in parallel and in series through a batch LQT formulation. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_viapoints01.m b/demos/demo_OC_LQT_viapoints01.m similarity index 98% rename from demos/demo_MPC_viapoints01.m rename to demos/demo_OC_LQT_viapoints01.m index 3041a97a9a788ac7eb33fd548dfcfe650e10ccfc..a4ec38bfce7e7bb75265bbb710941b6db1c15d0e 100644 --- a/demos/demo_MPC_viapoints01.m +++ b/demos/demo_OC_LQT_viapoints01.m @@ -1,5 +1,5 @@ -function demo_MPC_viapoints01 -% Batch LQR with viapoints and a double integrator system, and an encoding of position and velocity. +function demo_OC_LQT_viapoints01 +% Batch LQT with viapoints and a double integrator system, and an encoding of position and velocity. % % If this code is useful for your research, please cite the related publication: % @incollection{Calinon19chapter, @@ -242,7 +242,7 @@ end %% Plot 2D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %x1-x2 -figure('position',[10 10 600 600],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; +figure('position',[10 10 500 500],'color',[1 1 1],'name','x1-x2 plot'); hold on; axis off; %Plot uncertainty for t=1:nbData plotGMM(r(1).x(1:2,t), xSigma(model.nbVar*(t-1)+[1,2],model.nbVar*(t-1)+[1,2]).*1E1, [.2 .2 .2], .1); @@ -284,7 +284,7 @@ axis equal; % end %model.nbDeriv %u1-u2 -figure('position',[10 700 600 600],'color',[1 1 1],'name','u1-u2 plot'); hold on; axis off; +figure('position',[260 560 250 250],'color',[1 1 1],'name','u1-u2 plot'); hold on; axis off; %Plot uncertainty for t=1:nbData-1 plotGMM(r(1).u(1:2,t), uSigma(model.nbVarPos*(t-1)+[1,2],model.nbVarPos*(t-1)+[1,2]).*1E0, [.2 .2 .2], .02); @@ -300,7 +300,7 @@ end %% Timeline plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% labList = {'$x_1$','$x_2$','$\dot{x}_1$','$\dot{x}_2$','$\ddot{x}_1$','$\ddot{x}_2$'}; -figure('position',[620 10 1000 1290],'color',[1 1 1]); +figure('position',[520 10 600 800],'color',[1 1 1]); for j=1:model.nbVar subplot(model.nbVar+model.nbVarPos+1,1,j); hold on; if j>model.nbVarPos @@ -497,4 +497,4 @@ xlabel('$t$','fontsize',14,'interpreter','latex'); % print('-dpng','graphs/batchLQR_Su01.png'); pause; -close all; \ No newline at end of file +close all; diff --git a/demos/demo_MPC_viapoints02.m b/demos/demo_OC_LQT_viapoints02.m similarity index 99% rename from demos/demo_MPC_viapoints02.m rename to demos/demo_OC_LQT_viapoints02.m index 96d1f1de036611d0531c0f127ed2ced1501382c6..9501ca0f90ed160945fcf665f025826f77ddfb8f 100644 --- a/demos/demo_MPC_viapoints02.m +++ b/demos/demo_OC_LQT_viapoints02.m @@ -1,4 +1,4 @@ -function demo_MPC_viapoints02 +function demo_OC_LQT_viapoints02 % Batch LQR with viapoints and a double integrator system, and an encoding of only position. % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_viapoints03.m b/demos/demo_OC_LQT_viapoints03.m similarity index 99% rename from demos/demo_MPC_viapoints03.m rename to demos/demo_OC_LQT_viapoints03.m index 9af0132bd2c05c0f38cce4581a464b0ec58bac1d..d10e6c9d4d5ef805216a361ff3048a728735718b 100644 --- a/demos/demo_MPC_viapoints03.m +++ b/demos/demo_OC_LQT_viapoints03.m @@ -1,4 +1,4 @@ -function demo_MPC_viapoints03 +function demo_OC_LQT_viapoints03 % Equivalence between cubic Bezier curve and batch LQR with double integrator (formulation with position and velocity). % % If this code is useful for your research, please cite the related publication: diff --git a/demos/demo_MPC_viapoints_withProd01.m b/demos/demo_OC_LQT_viapoints_withProd01.m similarity index 99% rename from demos/demo_MPC_viapoints_withProd01.m rename to demos/demo_OC_LQT_viapoints_withProd01.m index 1caeace13f1fea187b109565d84c247b5bc98bd5..468f473c2fb2168c027267989fabec8a7ae688d5 100644 --- a/demos/demo_MPC_viapoints_withProd01.m +++ b/demos/demo_OC_LQT_viapoints_withProd01.m @@ -1,4 +1,4 @@ -function demo_MPC_viapoints_withProd01 +function demo_OC_LQT_viapoints_withProd01 % Batch LQT with viapoints computed as a product of trajectory distributions in control space. % % If this code is useful for your research, please cite the related publication: