-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
restructured integrators, added midpoint (#16)
* restructured integrators, added midpoint * modified rollout example * modified the integrators, added doc strings * modified the integrators, added doc strings * removed example 01 * Delete examples/01_intro.ipynb * restorted example 01 from master * added example 01
- Loading branch information
1 parent
cbe2836
commit 7c6be93
Showing
15 changed files
with
541 additions
and
163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,101 @@ | ||
"""Module for base class of integrators""" | ||
"""Module for base class of integrators.""" | ||
|
||
from abc import ABC, abstractstaticmethod | ||
from ..base import StateSpaceBase | ||
from abc import ABC, abstractmethod | ||
from ..base import ModelBase | ||
from ...arrays import ArrayLike | ||
import casadi as cs | ||
from typing import Callable | ||
|
||
|
||
class Integrator(ABC): | ||
@abstractstaticmethod | ||
def forward( | ||
state_space: StateSpaceBase, | ||
x0: ArrayLike, | ||
qfrc_u: ArrayLike, | ||
dt: float | cs.SX, | ||
) -> ArrayLike: | ||
pass | ||
class IntegratorBase(ABC): | ||
""" | ||
Abstract base class for integrators. | ||
This class provides the interface that all derived integrator classes should implement. | ||
""" | ||
|
||
def __init__(self, model: ModelBase): | ||
""" | ||
Initialize the IntegratorBase with a model of the dynamic system. | ||
Args: | ||
model (ModelBase): The model on which the integration will be performed. | ||
""" | ||
# simplify notation for integration on manifold | ||
|
||
@abstractmethod | ||
def tangent_step(self, x: ArrayLike, tang_x: ArrayLike) -> ArrayLike: | ||
""" | ||
Abstract method to perform step assuming the configuration is on a manifold. | ||
Args: | ||
x (ArrayLike): The current state vector of the system. | ||
tang_x (ArrayLike): The tangent vector at state x. | ||
Returns: | ||
ArrayLike: The state vector after performing the tangent step. | ||
""" | ||
|
||
@abstractmethod | ||
def forward(self, x0: ArrayLike, u: ArrayLike, dt: float | cs.SX) -> ArrayLike: | ||
""" | ||
Abstract method to perform a forward integration step. | ||
Args: | ||
derivative (Callable[[ArrayLike, ArrayLike, ArrayLike], ArrayLike]): | ||
A function that computes the tangent of the state. | ||
x0 (ArrayLike): | ||
The initial state from which to start the integration. | ||
u (ArrayLike): The input forces affecting the system's dynamics. | ||
dt (float | cs.SX): | ||
The timestep over which to integrate. | ||
Returns: | ||
ArrayLike: The state vector after performing the forward integration. | ||
""" | ||
|
||
def derivative(self, x: ArrayLike, u: ArrayLike) -> ArrayLike: | ||
"""Calculate the derivative (tangent) of the state vector for particular model""" | ||
|
||
|
||
class Integrator(IntegratorBase): | ||
def __init__(self, model: ModelBase): | ||
""" | ||
Initialize the Integrator with a dynamic system model. | ||
Args: | ||
model (ModelBase): The model on which the integration will be performed. | ||
""" | ||
super().__init__(model) | ||
self.__model = model | ||
self.nq = self.__model.nq | ||
self.nv = self.__model.nv | ||
self.__manifold_integrate = self.__model.backend.integrate_configuration | ||
|
||
def tangent_step(self, x: ArrayLike, tang_x: ArrayLike) -> ArrayLike: | ||
""" | ||
Concrete implementation of the tangent step for manifold integration. | ||
Args: | ||
x (ArrayLike): The current state vector of the system. | ||
tang_x (ArrayLike): The tangent vector at state x. | ||
Returns: | ||
ArrayLike: The state vector after performing the tangent step. | ||
""" | ||
# Create a container for the new state | ||
container = self.__model.backend.math.zeros(self.nq + self.nv) | ||
# Integrate configuration on the manifold | ||
container[: self.nq] = self.__manifold_integrate( | ||
q=x[: self.nq], v=tang_x[: self.nv] | ||
) | ||
# Velocity and acceleration are simply updated | ||
container[self.nq :] = x[self.nq :] + tang_x[self.nv :] | ||
|
||
return container.array | ||
|
||
def derivative(self, x: ArrayLike, u: ArrayLike) -> ArrayLike: | ||
q, v = x[: self.nq], x[self.nq :] | ||
container = self.__model.backend.math.zeros(2 * self.nv) | ||
container[: self.nv] = v | ||
container[self.nv :] = self.__model.forward_dynamics(q, v, u) | ||
return container.array |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,53 @@ | ||
"""Module for forward euler integrator""" | ||
from .base import Integrator, StateSpaceBase, ArrayLike, cs | ||
"""Module for forward euler integrator.""" | ||
|
||
from .base import Integrator, ModelBase, ArrayLike, cs | ||
from typing import Callable | ||
|
||
|
||
class ForwardEuler(Integrator): | ||
@staticmethod | ||
""" | ||
Implements the Euler method for numerical integration. | ||
The Euler method is a simple first-order integration method that updates | ||
the state by taking a single step forward using the derivative of the | ||
state at the current position. This method can be used for systems | ||
evolving on manifolds and is computationally less intensive than higher-order methods. | ||
""" | ||
|
||
def __init__(self, model: ModelBase): | ||
""" | ||
Initialize the Euler integrator with a model that defines system dynamics, | ||
which may include evolution on a manifold. | ||
Args: | ||
model (ModelBase): The DARLI model providing the system dynamics. | ||
""" | ||
super().__init__(model) | ||
|
||
def forward( | ||
state_space: StateSpaceBase, | ||
self, | ||
x0: ArrayLike, | ||
qfrc_u: ArrayLike, | ||
u: ArrayLike, | ||
dt: cs.SX | float, | ||
): | ||
nq = state_space.model.nq | ||
nv = state_space.model.nv | ||
) -> ArrayLike: | ||
""" | ||
Perform a single Euler integration step. | ||
q, v = x0[:nq], x0[nq:] | ||
vdot = state_space.model.forward_dynamics(q, v, qfrc_u) | ||
Args: | ||
derivative: A function that computes the tangent of the state. | ||
x0: Initial state vector, which may include manifold-valued components. | ||
u: Inputs forces acting on the system. | ||
dt: Time step for integration. | ||
# forward euler to integrate velocity | ||
integrated_v = v + dt * vdot | ||
Returns: | ||
The estimated state vector after the Euler integration step. | ||
""" | ||
|
||
# pinocchio fancy lie-group integration | ||
integrated_q = state_space.model.backend.integrate_configuration( | ||
dt, q, integrated_v | ||
) | ||
# Calculate the derivative at the current position | ||
log = self.derivative(x0, u) | ||
|
||
container = state_space.model.backend.math.zeros(nq + nv).array | ||
container[:nq] = integrated_q | ||
container[nq:] = integrated_v | ||
# Update the state on manifold by taking a step along the tangent | ||
# and projecting back onto the manifold | ||
exp = self.tangent_step(x0, dt * log) | ||
|
||
return container | ||
return exp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"""Module for forward euler integrator""" | ||
from .base import Integrator, ModelBase, ArrayLike, cs | ||
from typing import Callable | ||
|
||
|
||
class MidPoint(Integrator): | ||
""" | ||
Implements the Midpoint method for numerical integration. | ||
The Midpoint method is a second-order method that computes the derivative | ||
at the midpoint of the interval to update the state. It provides a better | ||
approximation than the Euler method with modest computational requirements. | ||
This method can handle systems with state spaces that include manifolds. | ||
""" | ||
|
||
def __init__(self, model: ModelBase): | ||
""" | ||
Initialize the Midpoint integrator with a model that defines system dynamics, | ||
which may include manifold evolution. | ||
Args: | ||
model (ModelBase): The DARLI model providing the system dynamics. | ||
""" | ||
super().__init__(model) | ||
|
||
def forward( | ||
self, | ||
x0: ArrayLike, | ||
u: ArrayLike, | ||
dt: cs.SX | float, | ||
) -> ArrayLike: | ||
""" | ||
Perform a single Midpoint integration step. | ||
Args: | ||
derivative: A function that computes the tangent of the state. | ||
x0: Initial state vector, which may include manifold-valued components. | ||
u: Inputs forces acting on the system. | ||
dt: Time step for integration. | ||
Returns: | ||
The estimated state vector after the Midpoint integration step. | ||
""" | ||
# Compute the first time derivative of the state (Euler step) | ||
k1_log = self.derivative(x0, u) | ||
|
||
# Compute the state at the mid-point using the initial slope (k1_log) | ||
k2_exp = self.tangent_step(x0, 0.5 * dt * k1_log) | ||
|
||
# Compute the time derivative at the mid-point, based on the estimated state (k2_exp) | ||
k2_log = self.derivative(k2_exp, u) | ||
|
||
# Perform the full step using the slope at the mid-point (k2_log) | ||
return self.tangent_step(x0, dt * k2_log) |
Oops, something went wrong.