#!/usr/bin/env python
# coding: utf-8
# # Human Standing Control Parameter Identification with Direct Collocation
#
# Jason K. Moore
# Ton van den Bogert
#
#
#
# July 10, 2015
# ISB TGCS 2015, Edinburgh, UK
# # Parameter Identification
#
# Find the parameters $\mathbf{p}$ such that the difference between the model simulation, $\mathbf{y}$, and measurements, $\mathbf{y}_m$ is minimized.
#
# ### Dynamic system
#
# - Equations of Motion: $\dot{\mathbf{x}} = \mathbf{f}(\mathbf{x}, \mathbf{p})$
# - Measurement variables: $\mathbf{y} = \mathbf{g}(\mathbf{x}, \mathbf{p})$
#
# ### Objective
#
# $$\min\limits_\mathbf{p} J(\mathbf{p})$$
# where
# $$J(\mathbf{p}) = \int [\mathbf{y}_m - \mathbf{y}(\mathbf{p})]^2 dt$$
# # Parameter Identification By Shooting
#
# - Repeated simulations are computationally costly
# - Systems may be unstable and thus have an ill-defined objective
# - Local minima are inevitable
# - May requires a superb guess
# - May need time intensive global optimization methods
# # Local Minima Example: Simple pendulum
#
# > Vyasarayani, Chandrika P., Thomas Uchida, Ashwin Carvalho, and John McPhee.
# "Parameter Identification in Dynamic Systems Using the Homotopy Optimization
# Approach". Multibody System Dynamics 26, no. 4 (2011): 411-24.
#
#
#
# ## 1-DoF, 1 parameter pendulum equations of motion
#
# $\dot{\mathbf{x}} = \begin{bmatrix} \dot{\theta}(t) \\ \dot{\omega}(t) \end{bmatrix} = \begin{bmatrix} \omega(t) \\ -p \sin{\theta}(t) \end{bmatrix}$
#
# ## Objective: Minimize least squares
#
# $J(p) = \min\limits_{p} \int_{t_0}^{t_f} [\theta_m(t) - \theta(\mathbf{x}, p, t)]^2 dt$
# # Direct Collocation
#
# > Betts, J., and W. Huffman. “Large Scale Parameter Estimation Using Sparse Nonlinear Programming Methods.” SIAM Journal on Optimization 14, no. 1 (January 1, 2003): 223–44. doi:10.1137/S1052623401399216.
#
# ## Benefits
#
# - Fast computation times
# - Handles unstable systems with ease
# - Less susceptible to local minima
#
# ## Disadvantages
#
# - Accurate solution requires large number of nodes
# - Memory management for large sparse matrices and operations
# - Tedious and error prone to form gradients, Jacobians, and Hessians
# # Our Direct Collocation Implementation
#
# ### Implicit Continous Equations of Motion
#
# No need to solve for $\dot{\mathbf{x}}$.
#
# $$\mathbf{f}(\dot{\mathbf{x}}, \mathbf{x}, \mathbf{r}, \mathbf{p}, t) = 0$$
#
# - $\mathbf{x}, \dot{\mathbf{x}}$: states and their derivatives
# - $\mathbf{r}$: exogenous inputs
# - $\mathbf{p}$: constant parameters
# # Discretization
#
# ### First order discrete integration options:
#
# Backward Euler:
#
# $\mathbf{f}(\frac{\mathbf{x}_i - \mathbf{x}_{i-1}}{h} , \mathbf{x}_i, \mathbf{r}_i, \mathbf{p}, t_i) = 0$
#
# Midpoint Rule:
#
# $\mathbf{f}(\frac{\mathbf{x}_{i + 1} - \mathbf{x}_i}{h}, \frac{\mathbf{x}_i + \mathbf{x}_{i + 1}}{2}, \frac{\mathbf{r}_i + \mathbf{r}_{i + 1}}{2}, \mathbf{p}, t_i) = 0$
#
# ### Nonlinear Programming Formulation
#
# $$\min\limits_{\theta} J(\theta)$$
#
# $$\textrm{where } \mathbf{\theta} = [\mathbf{x}_i, \dots, \mathbf{x}_N, \mathbf{r}_i, \ldots, \mathbf{r}_N, \mathbf{p}]$$
#
# $$\textrm{subject to } \mathbf{f}(\mathbf{x}_i, \mathbf{x}_{i+1}, \mathbf{r}_i, \mathbf{r}_{i + 1}, \mathbf{p}, t_i) = 0 \textrm{ and } \theta_L \leq \theta \leq \theta_U$$
# # Software Tool: opty
#
# - User specifies continous symbolic:
# - objective
# - equations of motion (explicit or implicit)
# - additional constraints
# - bounds on free variables: $\mathbf{x}, \mathbf{r}, \mathbf{p}$
# - EoMs can be generated with PyDy (http://pydy.org)
# - Effficient just-in-time compiled C code is generated for functions that evaluate:
# - objective and its gradient
# - constraints and its Jacobian
# - NLP problem automatically formed for IPOPT
# - Open source: BSD license
# - Written in Python
# - http://github.com/csu-hmc/opty
#
# # Example Code: 1 DoF, 1 Parameter Pendulum
#
#
#
# $$\dot{\mathbf{x}} = \begin{bmatrix} \dot{\theta}(t) \\ \dot{\omega}(t) \end{bmatrix} = \begin{bmatrix} \omega(t) \\ -p \sin{\theta}(t) \end{bmatrix}$$
#
# Paraphrased from https://github.com/csu-hmc/opty/blob/master/examples/vyasarayani2011.py
#
# ### Symbolics
#
# ```python
# # Specify symbols for the parameters
# p, t = symbols('p, t')
#
# # Specify the functions of time
# theta, omega, theta_m = symbols('theta, omega, theta_m', cls=Function)
#
# # Specify the symbolic equations of motion
# eom = (Matrix([theta(t), omega(t)]).diff(t) -
# Matrix([omega(t), -p * sin(theta(t))]))
#
# # Specify the symbolic objective function
# obj = Integral((theta_m(t) - theta(t))**2, t)
# ```
# # Example Code: 1 DoF, 1 Parameter Pendulum
#
# ### Numerics
#
# ```python
# # Choose discritzation values
# num_nodes = 1000
# interval = 0.01 # seconds
#
# # Form the problem
# prob = Problem(obj, eom, (theta(t), omega(t)), num_nodes, interval,
# known_trajectory_map={y1_m(t): measured_data},
# integration_method='midpoint')
#
# # Set an initial guess
# initial_guess = random(prob.num_free)
#
# # Solve the system
# solution, info = prob.solve(initial_guess)
# ```
# # Computational Speed
#
# ### Example Larger System
#
#
$$\dot{\mathbf{x}} = \mathbf{f}_o(\mathbf{x}, \mathbf{r}_c, \mathbf{r}_k, \mathbf{p}_k, t)$$
## | Known | #Identified | #Error | #
---|---|---|---|
$k_{00}$ | #950 | #946 | #-0.4% | #
$k_{01}$ | #175 | #177 | #1.4% | #
$k_{02}$ | #185 | #185 | #-0.2% | #
$k_{03}$ | #50 | #55 | #9.4% | #
$k_{10}$ | #45 | #45 | #1.1% | #
$k_{11}$ | #290 | #289 | #-0.3% | #
$k_{12}$ | #60 | #59 | #-2.1% | #
$k_{13}$ | #26 | #27 | #4.2% | #