dynobud-1.0.0.0: examples/MultipleShooting.hs
{-# OPTIONS_GHC -Wall #-}
{-# Language ScopedTypeVariables #-}
{-# Language DeriveGeneric #-}
{-# Language DeriveFunctor #-}
module Main
( main
) where
import GHC.Generics ( Generic )
import qualified Data.Vector as V
import qualified Data.Foldable as F
import Control.Applicative ( Applicative(..) )
import Linear
import Graphics.Rendering.Chart hiding ( x0 )
import Graphics.Rendering.Chart.Gtk
import Data.Default.Class
import Data.Colour
import Data.Colour.Names
import Control.Lens
import Dyno.View.View
import Dyno.View.JV
import Dyno.Nlp
import Dyno.NlpSolver
import Dyno.Solvers
import Dyno.Vectorize
import Dyno.View.CasadiMat ( MX )
import Dyno.Nats
import Dyno.MultipleShooting
-- state/control/parameter definitions
data X a = X a a deriving (Functor, Generic, Generic1, Show)
data U a = U a deriving (Functor, Generic, Generic1, Show)
data P a = P deriving (Functor, Generic, Generic1, Show)
-- boilerplate
instance Vectorize X
instance Vectorize U
instance Vectorize P
instance Applicative X where
pure = fill
x0 <*> x1 = devectorize (V.zipWith id (vectorize x0) (vectorize x1))
instance Applicative U where
pure = fill
x0 <*> x1 = devectorize (V.zipWith id (vectorize x0) (vectorize x1))
instance Additive X where
zero = fill 0
instance Additive U where
zero = fill 0
-- ocp specification
ocp :: MsOcp X U P
ocp =
MsOcp
{ msOde = ode
, msEndTime = 10
, msXBnds = X (Just (-2), Just 2) (Just (-2), Just 2)
, msUBnds = U (Just (-3), Just 3)
, msPBnds = P
, msMayer = \_ -> 0
, msLagrangeSum = \(X p v) (U u) -> p*p + v*v + u*u
, msX0 = X (Just 0) (Just 0)
, msXF = X (Just 1) (Just 1)
, msNumRk4Steps = Just 10
}
-- dynamics
ode :: Floating a => X a -> U a -> P a -> a -> X a
ode (X x v) (U u) _p _t = X v (-x -0.1*v + u)
-- run the thing
main :: IO ()
main = do
myNlp <- makeMsNlp ocp :: IO (Nlp' (MsDvs X U P D40) JNone (MsConstraints X D40) MX)
(msg,opt') <- solveNlp' ipoptSolver myNlp Nothing
opt <- case msg of
Left err -> error err
Right _ -> return opt'
let xopt = split $ xOpt' opt
splitXU xu = (splitJV x, splitJV u)
where
JTuple x u = split xu
(xs', us) = unzip $ map splitXU $ F.toList $ unJVec $ split (dvXus xopt)
xf = splitJV (dvXf xopt)
xs = xs' ++ [xf]
renderableToWindow (chart [ ("u", (map (\(U u) -> u) us) ++ [0])
, ("p", map (\(X p _) -> p) xs)
, ("v", map (\(X _ v) -> v) xs)
]) 600 600
chart :: [(String, [Double])] -> Renderable ()
chart vals = toRenderable layout
where
points :: (String, [Double]) -> PlotPoints Double Double
points (name, ys) = plot_points_style .~ filledCircles 2 (opaque red)
$ plot_points_values .~ (zip [0..] ys)
$ plot_points_title .~ name
$ def
layout :: Layout Double Double
layout = layout_title .~ "a plot"
$ layout_plots .~ (map (toPlot . points) vals)
$ def