dynobud-1.1.0.0: src/Dyno/DirectCollocation/Export.hs
{-# OPTIONS_GHC -Wall #-}
{-# Language ScopedTypeVariables #-}
{-# Language PolyKinds #-}
module Dyno.DirectCollocation.Export
( toMatlab
) where
import Data.Proxy ( Proxy(..) )
import Linear.V ( Dim(..) )
import Data.Vector ( Vector )
import qualified Data.Vector as V
import qualified Data.Foldable as F
import Dyno.View.Unsafe.View ( unJ )
import Dyno.Server.Accessors ( Lookup, flatten, accessors )
import Dyno.TypeVecs ( Vec )
import Dyno.Vectorize ( Vectorize, fill )
import Dyno.View.View ( View(..) )
import Dyno.View.JV ( JV, splitJV )
import Dyno.View.JVec ( JVec(..) )
import Dyno.DirectCollocation.Formulate ( CollProblem(..) )
import Dyno.DirectCollocation.Types ( CollTraj(..), CollStage(..), CollPoint(..) )
import Dyno.DirectCollocation.Quadratures ( timesFromTaus )
toMatlab ::
forall x z u p r c h o n deg
. ( Lookup (x Double), Vectorize x
, Lookup (z Double), Vectorize z
, Lookup (u Double), Vectorize u
, Lookup (o Double), Vectorize o
, Lookup (p Double), Vectorize p
, Dim deg
, Dim n
)
=> CollProblem x z u p r c h o n deg
-> CollTraj x z u p n deg (Vector Double)
-> IO String
toMatlab cp ct@(CollTraj tf' p' stages' xf) = do
outs <- cpOutputs cp (cat ct)
let taus :: Vec deg Double
taus = cpTaus cp
tf = V.head (unJ tf')
n = reflectDim (Proxy :: Proxy n)
times :: Vec n (Double, Vec deg Double)
times = timesFromTaus 0 taus dt
where
dt = tf / fromIntegral n
xTimes = concatMap (\(t0,ts) -> t0 : F.toList ts) (F.toList times) ++ [tf]
zuoTimes = concatMap (\(_,ts) -> F.toList ts) (F.toList times)
stages :: [CollStage (JV x) (JV z) (JV u) deg (Vector Double)]
stages = map split $ F.toList $ unJVec $ split stages'
xs :: [x Double]
xs = concatMap getXs stages ++ [splitJV xf]
zs :: [z Double]
zs = concatMap getZs stages
us :: [u Double]
us = concatMap getUs stages
os :: [o Double]
xdots :: [x Double]
(os, xdots) = unzip $ F.concatMap (F.toList . fst) outs -- drop the interpolated value
getXs (CollStage x0 xzus) = splitJV x0 : map (getX . split) (F.toList (unJVec (split xzus)))
getZs (CollStage _ xzus) = map (getZ . split) (F.toList (unJVec (split xzus)))
getUs (CollStage _ xzus) = map (getU . split) (F.toList (unJVec (split xzus)))
getX :: CollPoint (JV x) (JV z) (JV u) (Vector Double) -> x Double
getX (CollPoint x _ _) = splitJV x
getZ :: CollPoint (JV x) (JV z) (JV u) (Vector Double) -> z Double
getZ (CollPoint _ z _) = splitJV z
getU :: CollPoint (JV x) (JV z) (JV u) (Vector Double) -> u Double
getU (CollPoint _ _ u) = splitJV u
at :: (Vectorize xzu, Lookup (xzu Double)) => [(String, xzu Double -> Double)]
at = flatten $ accessors (fill 0)
p = splitJV p'
woo :: String -> [xzu Double] -> String -> (xzu Double -> Double) -> String
woo topName xzus name get = topName ++ "." ++ name ++ " = " ++ show (map get xzus) ++ ";"
wooP :: String -> (p Double -> Double) -> String
wooP name get = "params." ++ name ++ " = " ++ show (get p) ++ ";"
ret :: String
ret = init $ unlines $
map (uncurry (woo "ret.diffStates" xs)) at ++
map (uncurry (woo "ret.diffStateDerivs" xdots)) at ++
map (uncurry (woo "ret.algVars" zs)) at ++
map (uncurry (woo "ret.controls" us)) at ++
map (uncurry (woo "ret.outputs" os)) at ++
map (uncurry wooP) at ++
[ ""
, "ret.tx = " ++ show xTimes
, "ret.tzuo = " ++ show zuoTimes
, "ret.N = " ++ show n
, "ret.deg = " ++ show (reflectDim (Proxy :: Proxy deg))
, "ret.collocationRoots = '" ++ show (cpRoots cp) ++ "'"
]
return ret