### Install Example Requirements Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/README.md Installs the necessary Python packages for the example. Ensure you have pip installed. ```bash pip install -r requirements.txt ``` -------------------------------- ### Clone Repository and Setup Path Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Clones the L4CasADi repository and adds its examples directory to the system path for subsequent imports. ```bash !git clone https://github.com/Tim-Salzmann/l4casadi /tmp/l4casadi sys.path.append('/tmp/l4casadi/examples/fish_turbulent_flow') ``` -------------------------------- ### Install PyTorch (CPU version) Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Installs the CPU-only version of PyTorch. Use this if a GPU is not available or not required. ```python !pip install torch --index-url https://download.pytorch.org/whl/cpu ``` -------------------------------- ### Install ffmpeg for Animations (Linux) Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/README.md Installs the ffmpeg tool required for generating animations on Linux systems. ```bash sudo apt install ffmpeg ``` -------------------------------- ### Install Dependencies Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Installs necessary libraries including PyTorch, scikit-build, cmake, ninja, and the l4casadi package. Ensure you have a compatible Python environment. ```python import sys ``` ```python !pip install torch --index-url https://download.pytorch.org/whl/cpu !pip install scikit-build cmake ninja !pip install git+https://github.com/Tim-Salzmann/l4casadi --no-build-isolation ``` ```python !git clone https://github.com/Tim-Salzmann/l4casadi /tmp/l4casadi sys.path.append('/tmp/l4casadi/examples/nerf_trajectory_optimization') ``` -------------------------------- ### Install L4CasADi Build Dependencies from Requirements Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Install all build dependencies required for L4CasADi when building from source. This is done by installing from the requirements_build.txt file. ```bash pip install -r requirements_build.txt ``` -------------------------------- ### Set Fish Start and Goal Points Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Defines the starting position, goal position, and simulation parameters for the fish trajectory. ```python # @title Set Fish Start Point Position y_start_pos = 1.5 # @param {type:"slider", min:-1.8, max:1.8, step:0.1} p_start = np.array([7.75, y_start_pos]) p_goal = np.array([-0.85, -0.4]) u_lim = 1 T = 20 N = 151 dt = T / N ``` -------------------------------- ### Install PyTorch CPU Version Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Install the CPU-only version of PyTorch using pip. This is a prerequisite for CPU-only L4CasADi installations. ```bash pip install torch>=2.0 --index-url https://download.pytorch.org/whl/cpu ``` -------------------------------- ### Install L4CasADi via Pip (CPU Only) Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Install L4CasADi using pip. The --no-build-isolation flag is crucial for L4CasADi to correctly link against the installed PyTorch. ```bash pip install l4casadi --no-build-isolation ``` -------------------------------- ### Build L4CasADi from Source Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Build and install L4CasADi from the source code after cloning the repository and installing dependencies. The --no-build-isolation flag is required. ```bash pip install . --no-build-isolation ``` -------------------------------- ### Install ffmpeg for Animations (OSX) Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/README.md Installs the ffmpeg tool required for generating animations on macOS systems using Homebrew. ```bash brew install ffmpeg ``` -------------------------------- ### Install Build Tools Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Installs essential build tools: scikit-build for managing Python package builds, cmake for cross-platform builds, and ninja for faster build execution. ```python !pip install scikit-build cmake ninja ``` -------------------------------- ### Install L4CasADi with CUDA Support Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md To build L4CasADi from source with CUDA support, ensure the CUDA toolkit is installed and nvcc is accessible. You may need to specify the nvcc path during installation. ```bash CUDACXX=/usr/local/cuda/bin/nvcc pip install l4casadi --no-build-isolation ``` ```bash CUDACXX= pip install . --no-build-isolation ``` -------------------------------- ### Install L4CasADi Build Dependencies Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Install the necessary build dependencies for L4CasADi using pip. This includes setuptools, scikit-build, cmake, and ninja. ```bash setuptools>=68.1 scikit-build>=0.17 cmake>=3.27 ninja>=1.11 ``` -------------------------------- ### Define and Solve Phase 1 NLP (Warm-up) Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Sets up and solves an initial Non-Linear Programming (NLP) problem for trajectory generation. This serves as a warm-up to get an initial feasible solution before the main optimization. ```python # Define Phase 1 NLP nlp_warm = trajectory_generator_solver( n, n_eval, l4c_nerf, warmup=True, threshold=optimization_threshold) # Solve Phase 1 NLP params_flat = piecewise_points.T.flatten() # update nlp to take this as input! sol = nlp_warm["solver"](p=params_flat, lbg=nlp_warm["lbg"], ubg=nlp_warm["ubg"]) # Extract Phase 1 Solution coeffs_warm = np.squeeze(sol["x"]).reshape(2, n).T coeffs_warm = np.hstack([np.zeros((n, 1)), coeffs_warm]) ``` -------------------------------- ### Install l4casadi Library Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Installs the l4casadi library from its GitHub repository. The --no-build-isolation flag ensures that the build process uses the project's own dependencies. ```python !pip install git+https://github.com/Tim-Salzmann/l4casadi --no-build-isolation ``` -------------------------------- ### Install L4CasADi Dependencies Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Import the sys module for system-specific parameters and functions. This is a common first step in Python scripts. ```python import sys ``` -------------------------------- ### Check PyTorch Version Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Verify that PyTorch is installed and check its version. Ensure it meets the minimum requirement of 2.0. ```python python -c "import torch; print(torch.__version__)" ``` -------------------------------- ### Real-time L4CasADi Example Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md This snippet demonstrates the usage of Real-time L4CasADi, which replaces complex models with local Taylor approximations for potentially faster optimization times in specific scenarios like MPC. Note its limitations, including Python-only support and no C(++) code generation. ```python from l4casadi.realtime import RealtimeL4CasADi realtime_l4c_model = RealtimeL4CasADi(pyTorch_model) ``` -------------------------------- ### Set DYLD_LIBRARY_PATH and Launch Matlab (MacOS) Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/matlab/README.md Example of how to set the DYLD_LIBRARY_PATH environment variable in the shell before launching Matlab on MacOS. This is the recommended method for ensuring Matlab can find the L4CasADi library. ```bash export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH: DYLD_LIBRARY_PATH="${DYLD_LIBRARY_PATH}" /Applications/MATLAB_R2023b.app/Contents/MacOS/MATLAB ``` -------------------------------- ### Clone L4CasADi Repository Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Clone the L4CasADi GitHub repository to build from source. This is an alternative installation method. ```bash git clone https://github.com/Tim-Salzmann/l4casadi.git ``` -------------------------------- ### Define Trajectory Optimization Case Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Sets up different starting and goal points for trajectory optimization based on a selected case. This allows for testing the optimization algorithm under various scenarios. ```python # @title Select example case (different start- and goal-points) { run: "auto" } n = 9 n_eval = 150 optimization_threshold = 1. viz_threshold = 10. CASE = "1" # @param ["1", "2", "3"] CASE = int(CASE) if CASE == 1: # case 1 p_start = np.array([0.0, -0.8, -0.2]) p_goal = np.array([-0.0, 1.2, 0.8]) elif CASE == 2: # case 2 p_start = np.array([0.0, -0.8, -0.2]) p_goal = np.array([-0.0, 1.2, -0.2]) elif CASE == 3: # case 3 p_start = np.array([0.0, -1, 1]) p_goal = np.array([-0.0, 1.2, -0.2]) else: raise ValueError("Invalid case.") if CASE == 1: points = np.array( [[0, -0.8, -0.2], [0, -0.5, 0.4], [0, 0, 0.8], [0, 0.75, 0.3], [0, 1.2, 0.8]] ) elif CASE == 2: points = np.array( [[0, -0.8, -0.2], [0, -0.5, 0.4], [0, 0, 0.8], [0, 0.75, 0.4], [0, 1.2, -0.2]] ) elif CASE == 3: points = np.array( [[0.0, -1, 1], [0, -0.85, 0.4], [0, 0, 0.7], [0, 0.75, 0.45], [0, 1.2, -0.2]] ) else: raise ValueError("Invalid case") dists = np.linalg.norm(np.diff(points, axis=0), axis=1) n_eval_points = np.squeeze(dists / np.sum(dists) * n_eval).astype(int) if np.sum(n_eval_points) != n_eval: n_eval_points[-1] += n_eval - np.sum(n_eval_points) piecewise_points = np.zeros((n_eval, 3)) for k in range(len(points) - 1): piecewise_points[ np.sum(n_eval_points[:k]) : np.sum(n_eval_points[: k + 1]), : ] = np.linspace(points[k], points[k + 1], n_eval_points[k] + 1)[:-1, :] ``` -------------------------------- ### Get LD_LIBRARY_PATH in Matlab Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/matlab/README.md Retrieves the current value of the LD_LIBRARY_PATH environment variable within a Matlab session. Note that setting environment variables directly in Matlab using `setenv` is often ineffective for library loading. ```matlab getenv("LD_LIBRARY_PATH") ``` -------------------------------- ### Configure CMakeLists.txt Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/cpp_usage/README.md Replace the placeholder with the actual path to your L4CasADi library directory. ```bash sed -i 's//$(pwd)\/..\/l4casadi\/lib/g' CMakeLists.txt ``` -------------------------------- ### Initialize NaiveL4CasADiModule Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Use NaiveL4CasADiModule for smaller models to avoid PyTorch overhead by directly recreating the computational graph with CasADi operations. This is limited to specific PyTorch operations and CPU inference. ```python from l4casadi.naive import NaiveL4CasADiModule naive_l4c_model = NaiveL4CasADiModule(pyTorch_model) ``` -------------------------------- ### Compile C++ Project Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/cpp_usage/README.md Steps to compile the C++ project using CMake and make. ```bash mkdir build && cd build cmake .. make ``` -------------------------------- ### Run Trajectory Generation Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/README.md Executes the main script to optimize and generate an energy-efficient trajectory for the fish using a pre-trained model. ```python python trajectory_generation.py ``` -------------------------------- ### Import Trajectory Generation Utilities Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Imports necessary functions for trajectory generation and plotting from local utility modules. ```python # @title from trajectory_generation import trajectory_generator_solver from utils import plot_velocity_field_particle ``` -------------------------------- ### Generate and Solve Optimization Problem Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Sets up and solves a nonlinear programming (NLP) problem to find an energy-efficient trajectory for the fish. ```python # Generate solver nlp = trajectory_generator_solver( fU=fU, fV=fV, dt=dt, N=N, T=T, u_lim=u_lim, GT=False) # Set Initial Guess and Parameters params = np.vstack([p_start, np.tile(p_goal[:, None], N).T]) u_init = np.zeros((N - 1, 2)) p_init = np.zeros((N, 2)) p_init[:, :] = p_start x_init = np.vstack([p_init, u_init]) # Solve NLP x_init_flat = cs.reshape(x_init, 4 * N - 2, 1) params_flat = cs.reshape(params, (N + 1) * 2, 1) sol = nlp["solver"](x0=x_init_flat, p=params_flat, lbg=nlp["lbg"], ubg=nlp["ubg"]) # extract solution p_sol = np.squeeze(sol["x"]) [: N * 2].reshape(2, N).T u_sol = np.squeeze(sol["x"])[N * 2 :].reshape(2, N - 1).T ``` -------------------------------- ### Import Core Libraries Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Imports essential libraries for numerical computation, plotting, symbolic math, and machine learning. ```python import os from matplotlib.animation import FuncAnimation import matplotlib.pyplot as plt import casadi as cs import torch import numpy as np ``` -------------------------------- ### Import NeRF and Trajectory Modules Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Imports the DensityNeRF model and trajectory generation/solver components from the l4casadi library. These are essential for defining and solving the optimization problem. ```python from density_nerf import DensityNeRF from nerf_trajectory_optimization import trajectory_generator_solver, polynomial ``` -------------------------------- ### Calculate Jacobian with CasADi Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Demonstrates calculating the Jacobian of a symbolic function using CasADi. Requires defining symbolic variables and the function. ```python import casadi as cs x_sym = cs.MX.sym('x', 10, 4) y_sym = x_sym @ cs.DM.ones(4, 1) jac_f = cs.Function('jac', [x_sym], [cs.jacobian(y_sym, x_sym)]) print(jac_f(cs.DM.ones(10, 4))) ``` -------------------------------- ### Online Learning with L4CasADi Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Enable online learning by initializing L4CasADi with `mutable=True`. The model can then be updated using the `update` function. ```python l4c_model = l4c.L4CasADi(pyTorch_model, mutable=True) l4c_model.update() ``` -------------------------------- ### L4CasADi Constructor Parameters Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Configure L4CasADi compilation, device, derivative generation, and mutability. Parameters control tradeoffs between compilation time, runtime speed, and memory usage. ```python import l4casadi as l4c import torch model = torch.nn.Sequential( torch.nn.Linear(3, 64), torch.nn.Tanh(), torch.nn.Linear(64, 2) ) l4c_model = l4c.L4CasADi( model, batched=False, # True: treat first dim as batch (sparse Jacobians) device='cpu', # 'cuda' or 'cuda:0' for GPU name='my_model', # unique name — determines generated file names build_dir='./_l4c_gen', # where .pt traces and .so library are written generate_jac=True, # generate Jacobian trace generate_adj1=True, # generate adjoint (VJP) trace generate_jac_adj1=True, # generate Jacobian of adjoint (for 2nd-order solvers) generate_jac_jac=False, # True to generate full Hessian (expensive) mutable=False, # True to allow online weight updates via .update() ) ``` -------------------------------- ### Set LD_LIBRARY_PATH Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/cpp_usage/README.md Configure the library path to include Torch and the generated L4CasADi library for runtime. ```bash export LD_LIBRARY_PATH=::$LD_LIBRARY_PATH ``` -------------------------------- ### Import Core Libraries Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Imports essential libraries for numerical operations, plotting, symbolic math, and deep learning. These are standard tools for scientific computing and machine learning tasks. ```python import os import matplotlib.pyplot as plt import casadi as cs import torch import numpy as np ``` -------------------------------- ### Import L4CasADi Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Imports the L4CasADi library, which bridges PyTorch models with CasADi for optimization. This import is crucial for using L4CasADi's functionalities. ```python import l4casadi as l4c ``` -------------------------------- ### Citation for Real-time Neural-MPC Paper Source: https://github.com/tim-salzmann/l4casadi/blob/main/l4casadi/realtime/README.md BibTeX citation for the Real-time Neural-MPC paper. Use this when citing the work. ```bibtex @article{salzmann2023neural, title={Real-time Neural-MPC: Deep Learning Model Predictive Control for Quadrotors and Agile Robotic Platforms}, author={Salzmann, Tim and Kaufmann, Elia and Arrizabalaga, Jon and Pavone, Marco and Scaramuzza, Davide and Ryll, Markus}, journal={IEEE Robotics and Automation Letters}, doi={10.1109/LRA.2023.3246839}, year={2023} } ``` -------------------------------- ### Run L4CasADi Executable Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/cpp_usage/README.md Execute the compiled L4CasADi program and provide input when prompted. ```bash ./l4cpp ``` -------------------------------- ### Real-time Neural-MPC Paper Source: https://github.com/tim-salzmann/l4casadi/blob/main/l4casadi/realtime/README.md This is the title of the paper introducing Real-time Neural-MPC. ```text Real-time Neural-MPC: Deep Learning Model Predictive Control for Quadrotors and Agile Robotic Platforms ``` -------------------------------- ### Initialize L4CasADi Model Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Quickly initialize an L4CasADi model from a pre-defined PyTorch model. Supports CPU and GPU ('cuda') devices. ```python import l4casadi as l4c l4c_model = l4c.L4CasADi(pyTorch_model, device='cpu') ``` ```python import l4casadi as l4c l4c_model = l4c.L4CasADi(pyTorch_model, device='cuda') ``` -------------------------------- ### Wrap PyTorch Model with L4CasADi Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Wraps a PyTorch model into a CasADi-compatible function. Triggers TorchScript tracing, C++ bridge generation, and compilation on the first call with a symbolic variable. Ensure the symbolic input shape matches the model's expected input exactly. ```python import casadi as cs import torch import l4casadi as l4c # Define any PyTorch model class MultiLayerPerceptron(torch.nn.Module): def __init__(self): super().__init__() self.input_layer = torch.nn.Linear(2, 512) self.hidden_layers = torch.nn.ModuleList( [torch.nn.Linear(512, 512) for _ in range(20)] ) self.out_layer = torch.nn.Linear(512, 1) def forward(self, x): x = self.input_layer(x) for layer in self.hidden_layers: x = torch.tanh(layer(x)) return self.out_layer(x) pytorch_model = MultiLayerPerceptron() # Wrap with L4CasADi (use device='cuda' for GPU) l4c_model = l4c.L4CasADi(pytorch_model, device='cpu') # Use with CasADi symbolic variables — only cs.MX is supported x_sym = cs.MX.sym('x', 1, 2) # shape must match model input exactly y_sym = l4c_model(x_sym) # triggers build on first call # Build CasADi functions with automatic differentiation f = cs.Function('y', [x_sym], [y_sym]) df = cs.Function('dy', [x_sym], [cs.jacobian(y_sym, x_sym)]) ddf = cs.Function('ddy', [x_sym], [cs.hessian(y_sym, x_sym)[0]]) # Evaluate numerically x_val = cs.DM([[0.], [2.]]) print(f(x_val)) # forward pass print(df(x_val)) # Jacobian print(ddf(x_val)) # Hessian (requires generate_jac_jac=True at init) ``` -------------------------------- ### Run Trajectory Optimization Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/README.md To run the optimization, first specify the problem configuration by changing the `CASE` variable in the `nerf_trajectory_optimization.py` script. Then, execute the optimization process using the provided command. ```python nerf_trajectory_optimization.py ``` -------------------------------- ### Use L4CasADi in Nonlinear Programming (NLP) Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Integrate L4CasADi-wrapped PyTorch models directly into CasADi NLP solvers. Both objective and constraint models can be wrapped independently. ```python import casadi as cs import torch import l4casadi as l4c x = cs.MX.sym('x', 2) # PyTorch objective: f(x) = x[0]^2 + x[1]^2 class ObjectiveModel(torch.nn.Module): def forward(self, inp): return torch.square(inp[0]) + torch.square(inp[1])[..., None] # PyTorch constraint: g(x) = x[0] + x[1] - 10 >= 0 class ConstraintModel(torch.nn.Module): def forward(self, inp): return (inp[0] + inp[1] - 10)[..., None] f = l4c.L4CasADi(ObjectiveModel(), name='f')(x) g = l4c.L4CasADi(ConstraintModel(), name='g')(x) nlp = {'x': x, 'f': f, 'g': g} solver = cs.nlpsol('solver', 'ipopt', nlp) sol = solver(lbg=0) print("Objective at solution:", sol['f']) # ~50.0 print("Primal solution: ", sol['x']) # ~[5, 5] print("Dual solution (g): ", sol['lam_g']) ``` -------------------------------- ### CMakeLists.txt Configuration for L4CasADi C++ Executable Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/cpp_usage/CMakeLists.txt This snippet configures the CMake build system for a C++ executable. It specifies the minimum CMake version, project name, library directory, executable target, linking directories and libraries, and the C++ standard. ```cmake cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(L4CasADiCppExecutable) set(L4CASADI_LIB_DIR ) add_executable(l4cpp sin.cpp) target_link_directories(l4cpp PRIVATE ${L4CASADI_LIB_DIR}) target_link_directories(l4cpp PRIVATE _l4c_generated) target_link_libraries(l4cpp l4casadi sin_l4c) set_property(TARGET l4cpp PROPERTY CXX_STANDARD 17) ``` -------------------------------- ### Optimize Minimum Snap Collision-free Trajectory Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Defines and solves the main NLP problem for optimizing a minimum snap trajectory, ensuring collision avoidance through the NeRF model. It uses the solution from the warm-up phase as an initial guess. ```python # Define NLP nlp = trajectory_generator_solver( n, n_eval, l4c_nerf, warmup=False, threshold=optimization_threshold) # Solve NLP x_init = coeffs_warm[:, 1:].T.flatten() sol = nlp["solver"](x0=x_init, p=params_flat, lbg=nlp["lbg"], ubg=nlp["ubg"]) # Extract Solution coeffs_sol = np.squeeze(sol["x"]).reshape(2, n).T coeffs_sol = np.hstack([np.zeros((n, 1)), coeffs_sol]) _, f_eval = polynomial(n, n_eval) p_sol = np.squeeze(f_eval(coeffs=coeffs_sol)["p"]) ``` -------------------------------- ### Compute Taylor Linearization Parameters with RealTimeL4CasADi Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Evaluates a PyTorch model and its Jacobian (and optionally Hessian) at given states to compute parameters for Taylor approximation. This can be batched over multiple states, useful for MPC shooting nodes. ```python import numpy as np import torch import l4casadi as l4c class ResidualModel(torch.nn.Module): def __init__(self): super().__init__() self.net = torch.nn.Sequential( torch.nn.Linear(4, 64), torch.nn.Tanh(), torch.nn.Linear(64, 2) ) def forward(self, x): return self.net(x) rt_model = l4c.realtime.RealTimeL4CasADi(ResidualModel(), approximation_order=1) # Trigger build with a dummy symbolic variable import casadi as cs x_sym = cs.MX.sym('x', 4, 1) _ = rt_model(x_sym) # Batch of 10 states (e.g., MPC shooting nodes) — shape [10, 4] states = np.random.randn(10, 4).astype(np.float32) # Returns numpy array of flattened [a, f(a), df/da] for each state params = rt_model.get_params(states) print("params shape:", params.shape) # (10, 4 + 2 + 4*2) = (10, 14) for order=1 # In an Acados MPC loop, set per-node parameters: # for i in range(N): # solver.set(i, "p", params[i]) ``` -------------------------------- ### Custom CasADi-Native Layers with NaiveL4CasADiModule Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Base class for custom PyTorch modules providing an explicit CasADi-native forward pass. Enables custom layers to run as PyTorch with tensors and as CasADi symbolic operations with `cs.MX`. ```python import torch import casadi as cs from l4casadi.naive import NaiveL4CasADiModule import l4casadi as l4c class SoftplusLayer(NaiveL4CasADiModule): """Custom activation: Softplus — works in both PyTorch and CasADi.""" def forward(self, x): return torch.nn.functional.softplus(x) def cs_forward(self, x): # CasADi equivalent of softplus: log(1 + exp(x)) return cs.log(1 + cs.exp(x)) class SmallNet(NaiveL4CasADiModule): def __init__(self): super().__init__() from l4casadi.naive.nn.linear import Linear self.fc1 = Linear(2, 16) self.act = SoftplusLayer() self.fc2 = Linear(16, 1) def forward(self, x): return self.fc2(self.act(self.fc1(x))) net = SmallNet() l4c_model = l4c.L4CasADi(net) x_sym = cs.MX.sym('x', 1, 2) y_sym = l4c_model(x_sym) f = cs.Function('net_f', [x_sym], [y_sym]) print(f(cs.DM([[1.0, -0.5]]))) # doctest: +SKIP ``` -------------------------------- ### Configure Acados Solver Options with L4CasADi Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md Set the shared library directory and name for the L4CasADi model within the Acados OCP solver options. This is necessary when using a PyTorch model as a dynamics model in Acados. ```python ocp.solver_options.model_external_shared_lib_dir = l4c_model.shared_lib_dir ocp.solver_options.model_external_shared_lib_name = l4c_model.name ``` -------------------------------- ### Generate Interpolators for PyTorch Model Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/README.md This script generates necessary interpolator files. This process may take some time to complete. ```python python generate_interpolators.py ``` -------------------------------- ### Create Animation of Fish Movement Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Generates an animation showing the fish's trajectory overlaid on the turbulent velocity field. ```python %%capture # Create Animation fig, ax = plt.subplots(figsize=(10, 5.)) frames = N anim = FuncAnimation( fig, lambda frame_num: plot_velocity_field_particle( Xgrid, Ygrid, U[frame_num], V[frame_num], p_sol[max(0, frame_num - 10): frame_num + 1, 0], p_sol[max(0, frame_num - 10): frame_num + 1, 1], p_start, p_goal, round(frame_num / frames * T, 3), ), frames=frames, interval=100, ) anim.save('anim.gif') ``` -------------------------------- ### Create L4CasADi Model from PyTorch Model Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Converts the loaded PyTorch model into an L4CasADi model for use in optimization, applying standardization and denormalization. ```python x = cs.MX.sym("x", 3) xn = (x - meanX) / stdX y = l4c.L4CasADi(model, name="turbulent_model")(xn.T).T y = y * stdY + meanY fU = cs.Function("fU", [x], [y[0]]) fV = cs.Function("fV", [x], [y[1]]) ``` -------------------------------- ### Load PyTorch Turbulent Flow Model Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Loads a pre-trained PyTorch model for turbulent flow simulation, including its parameters for standardization. ```python checkpoint = torch.load( "/tmp/l4casadi/examples/fish_turbulent_flow/models/turbolent_flow_model.pt", map_location=torch.device('cpu'), weights_only=False ) # Standardization model = checkpoint["model"] meanX = checkpoint["mean"]["x"] stdX = checkpoint["std"]["x"] meanY = checkpoint["mean"]["y"] stdY = checkpoint["std"]["y"] ``` -------------------------------- ### Generate C++ Code Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/cpp_usage/README.md Run this command to generate the necessary C++ code for L4CasADi integration. ```bash python generate.py ``` -------------------------------- ### Online Model Update with L4CasADi (Mutable Mode) Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Enables hot-swapping PyTorch model weights at runtime without rebuilding the CasADi function. Use when model weights are updated between optimization steps. ```python import casadi as cs import torch import l4casadi as l4c class LearnedModel(torch.nn.Module): def __init__(self): super().__init__() self.fc = torch.nn.Linear(2, 1) def forward(self, x): return self.fc(x) model = LearnedModel() # Enable mutable mode (not supported on Windows) l4c_model = l4c.L4CasADi(model, mutable=True, name='online_model') x_sym = cs.MX.sym('x', 1, 2) y_sym = l4c_model(x_sym) # builds on first call f = cs.Function('f', [x_sym], [y_sym]) print("Before update:", f(cs.DM([[1., 0.]]))) # doctest: +SKIP # Simulate an online weight update (e.g., after a training step) with torch.no_grad(): model.fc.weight.fill_(1.0) model.fc.bias.fill_(0.5) # Update the live CasADi function — no rebuild required l4c_model.update() # uses existing model reference # l4c_model.update(new_model) # or pass a new model print("After update:", f(cs.DM([[1., 0.]]))) # doctest: +SKIP ``` -------------------------------- ### Real-Time MPC Dynamics Model Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Defines a PyTorch dynamics model for use with RealTimeL4CasADi, which replaces the full neural network call with a local Taylor expansion for real-time MPC. ```python import casadi as cs import numpy as np import torch import l4casadi as l4c class DynamicsModel(torch.nn.Module): def __init__(self): super().__init__() self.net = torch.nn.Sequential( torch.nn.Linear(2, 512), torch.nn.Tanh(), torch.nn.Linear(512, 1) ) def forward(self, x): return self.net(x) pytorch_model = DynamicsModel() ``` -------------------------------- ### Pure CasADi MLP with NaiveL4CasADi Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Re-implements MLP computational graphs directly using CasADi symbolic operations for reduced overhead. Limited to built-in MLP architecture and CPU inference. ```python import casadi as cs import l4casadi as l4c # Built-in MLP: (in_features, hidden_features, out_features, hidden_layers, activation) naive_mlp = l4c.naive.MultiLayerPerceptron( in_features=2, hidden_features=128, out_features=1, hidden_layers=2, activation='Tanh' # 'Sigmoid', 'ReLU', 'LeakyReLU', or None ) l4c_model = l4c.L4CasADi(naive_mlp) # Supports batched symbolic inputs natively x_sym = cs.MX.sym('x', 3, 2) # 3 rows × 2 features y_sym = l4c_model(x_sym) f = cs.Function('y', [x_sym], [y_sym]) df = cs.Function('dy', [x_sym], [cs.jacobian(y_sym, x_sym)]) ddf = cs.Function('ddy', [x_sym], [cs.jacobian(cs.jacobian(y_sym, x_sym), x_sym)]) x_val = cs.DM([[0., 2.], [0., 2.], [0., 2.]]) print(f(x_val)) # doctest: +SKIP print(df(x_val)) # doctest: +SKIP print(ddf(x_val)) # doctest: +SKIP ``` -------------------------------- ### Verify Collision-Free Trajectory with NeRF Density Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Calculates the maximum density along a proposed trajectory using a NeRF model and checks if it exceeds a defined optimization threshold. Requires PyTorch and a pre-trained NeRF model. ```python with torch.no_grad(): density_sol = model(torch.tensor(p_sol, dtype=torch.float32)).detach()[..., 0] print(f"Maximum Density in Solution: {density_sol.max()} < Threshold {optimization_threshold:.2f}") ``` -------------------------------- ### Train PyTorch Model Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/README.md Trains the PyTorch model in a supervised learning manner after the interpolators have been generated. ```python python learn_turbulent_flow.py ``` -------------------------------- ### Load PyTorch NeRF Model Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Loads a pre-trained NeRF model from a specified path. This model is used to represent the environment for collision checking during trajectory optimization. ```python model = DensityNeRF() model_path = "/tmp/l4casadi/examples/nerf_trajectory_optimization/nerf_model.tar" model.load_state_dict( torch.load(model_path, map_location="cpu")["network_fn_state_dict"], strict=False, ) ``` -------------------------------- ### Export L4CasADi Functions to C++ Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Export L4CasADi functions as self-contained C++ source files using CasADi's `.generate()` method. This allows usage in pure C/C++ projects without a Python runtime. ```python import os import torch import casadi as cs import l4casadi as l4c class SinModel(torch.nn.Module): def forward(self, x): return torch.sin(x) # Example usage (assuming SinModel is defined and instantiated) sin_model = SinModel() l4c_sin = l4c.L4CasADi(sin_model, name='sin_model') x_sym = cs.MX.sym('x', 1) y_sym = l4c_sin(x_sym) # Generate C++ code # Note: This requires CasADi to be installed with C++ code generation support # and PyTorch TorchScript to be available. # The actual generation call would look like: # l4c_sin.generate(x_sym, y_sym, 'sin_model_generated.cpp') # For demonstration, we only show the setup. print("Setup for C++ code generation complete.") ``` -------------------------------- ### Visualize Trajectory within NeRF Density Field Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Generates a 2D visualization of the robot's trajectory overlaid on the NeRF's density field. This helps in visually inspecting potential collisions. Requires Matplotlib and PyTorch. ```python meshgrid = torch.meshgrid( torch.linspace(0, 0, 1), torch.linspace(-1.0, 1.2, 200), torch.linspace(-0.5, 1, 200), indexing='ij' ) points = torch.stack(meshgrid, dim=-1).reshape(-1, 3) with torch.no_grad(): density = model(points).detach()[..., 0] points = points.numpy() ax = plt.figure().add_subplot(111) ax.plot(p_sol[:, 1], p_sol[:, 2], "-", color=(0.8, 0.12, 0.12), linewidth=3) g = ax.scatter( points[density > viz_threshold][:, 1], points[density > viz_threshold][:, 2], cmap="jet", c=density[density > viz_threshold], s=0.5, ) cb = plt.colorbar(g, ax=ax) ax.scatter(p_start[1], p_start[2], color=(0.12, 0.12, 0.8), s=50., zorder=10) ax.scatter(p_goal[1], p_goal[2], color=(0.12, 0.8, 0.12), s=50., zorder=10) cb.set_label('NeRF Density') plt.xticks([], []) plt.yticks([], []) plt.tight_layout() plt.show() ``` -------------------------------- ### Display Animation Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/fish_turbulent_flow/Fish_Turbulent_Flow.ipynb Displays the generated animation of the fish's movement in the turbulent flow. ```python from IPython.display import Image Image('./anim.gif') ``` -------------------------------- ### L4CasADi Input Requirements Source: https://github.com/tim-salzmann/l4casadi/blob/main/README.md When using L4CasADi, ensure that only `casadi.MX` symbolic variables are provided as input. Multi-input/output functions can be handled by concatenating inputs and splitting them within the PyTorch function. ```python import casadi symbolic_input = casadi.MX.sym('input', input_dim) l4c_model.predict(symbolic_input) ``` -------------------------------- ### Generate C++ Source from CasADi Function Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Generates C++ source code for a CasADi function, including a main entry point for standalone compilation. Ensure correct library paths are printed for linking. ```python l4c_model = l4c.L4CasADi(SinModel(), name='sin_l4c') sym_in = cs.MX.sym('x', 1, 1) sym_out = l4c_model(sym_in) f = cs.Function('sin_torch', [sym_in], [sym_out]) f.generate('sin.cpp', {'main': True, 'with_header': True}) print(f'L4CASADI_LIB_DIR: {os.path.dirname(os.path.abspath(l4c.__file__))}/lib') print(f'TORCH_LIB_DIR: {os.path.dirname(os.path.abspath(torch.__file__))}/lib') print(f'L4CASADI_GEN_LIB_DIR: {l4c_model.shared_lib_dir}') ``` ```bash # gcc -fPIC -shared sin.cpp -o sin_exec \ # -I -L \ # -L -L \ # -ll4casadi -lsin_l4c -ltorch -lstdc++ -std=c++17 ``` -------------------------------- ### RealTimeL4CasADi.get_params Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Computes Taylor Linearization Parameters by evaluating the PyTorch model and its Jacobian (and optionally Hessian) at a given state. This is useful for updating the linearization in an MPC loop. ```APIDOC ## RealTimeL4CasADi.get_params — Compute Taylor Linearization Parameters ### Description `get_params` evaluates the PyTorch model and its Jacobian (and optionally Hessian) at a given state to produce the flat parameter vector that feeds the symbolic Taylor approximation. In an MPC loop this is called once per iteration to update the linearization, and can be batched over all shooting nodes simultaneously. ### Method Signature ```python rt_model.get_params(states) ``` ### Parameters #### states - **states** (numpy.ndarray) - A batch of states for which to compute parameters. Shape should be `[N, state_dim]` where N is the number of states. ### Returns - **params** (numpy.ndarray) - A numpy array of flattened parameters, typically `[a, f(a), df/da]` for each state, depending on the `approximation_order`. ### Example ```python import numpy as np import torch import l4casadi as l4c class ResidualModel(torch.nn.Module): def __init__(self): super().__init__() self.net = torch.nn.Sequential( torch.nn.Linear(4, 64), torch.nn.Tanh(), torch.nn.Linear(64, 2) ) def forward(self, x): return self.net(x) rt_model = l4c.realtime.RealTimeL4CasADi(ResidualModel(), approximation_order=1) # Trigger build with a dummy symbolic variable import casadi as cs x_sym = cs.MX.sym('x', 4, 1) _ = rt_model(x_sym) # Batch of 10 states (e.g., MPC shooting nodes) — shape [10, 4] states = np.random.randn(10, 4).astype(np.float32) # Returns numpy array of flattened [a, f(a), df/da] for each state params = rt_model.get_params(states) print("params shape:", params.shape) # (10, 4 + 2 + 4*2) = (10, 14) for order=1 # In an Acados MPC loop, set per-node parameters: # for i in range(N): # solver.set(i, "p", params[i]) ``` ``` -------------------------------- ### Create L4CasADi Model from PyTorch NeRF Source: https://github.com/tim-salzmann/l4casadi/blob/main/examples/nerf_trajectory_optimization/NeRF_Trajectory_Optimization.ipynb Converts the loaded PyTorch NeRF model into an L4CasADi model. This allows the NeRF to be used within the CasADi optimization framework. ```python l4c_nerf = l4c.L4CasADi(model) ``` -------------------------------- ### L4CasADi Batched Mode Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Enable batched mode by setting `batched=True` to treat the first input dimension as a batch. This exploits block-diagonal Jacobian sparsity for significant speedups when multiple model evaluations are needed, such as in MPC shooting nodes. ```python import casadi as cs import torch import l4casadi as l4c class DynamicsModel(torch.nn.Module): def forward(self, x): return torch.sin(x) # maps [B, 4] -> [B, 4] model = DynamicsModel() # batched=True: first dim is batch; block-diagonal Jacobian sparsity exploited l4c_model = l4c.L4CasADi(model, batched=True, name='batched_dyn') # Input: [batch=10, features=4] — first dim is batch x_sym = cs.MX.sym('x', 10, 4) y_sym = l4c_model(x_sym) ``` -------------------------------- ### Acados Integration with L4CasADi for Neural MPC Source: https://context7.com/tim-salzmann/l4casadi/llms.txt Integrate L4CasADi with Acados for high-performance MPC. The compiled shared library is passed directly to the Acados OCP solver. ```python import casadi as cs import numpy as np import torch import l4casadi as l4c from acados_template import AcadosOcpSolver, AcadosOcp, AcadosModel class LearnedResidual(torch.nn.Module): def __init__(self): super().__init__() self.net = torch.nn.Sequential( torch.nn.Linear(2, 512), torch.nn.Tanh(), torch.nn.Linear(512, 512), torch.nn.Tanh(), torch.nn.Linear(512, 1) ) def forward(self, x): return self.net(x) # Wrap learned residual — name is used for the .so filename learned_dyn = l4c.L4CasADi(LearnedResidual(), name='learned_dyn') # Build CasADi/Acados model with learned residual s, s_dot, u = cs.MX.sym('s',1), cs.MX.sym('s_dot',1), cs.MX.sym('u',1) x = cs.vertcat(s, s_dot) res = learned_dyn(x.T).T # learned residual on state f_expl = cs.vertcat(s_dot, u) + res model_ac = AcadosModel() model_ac.name = 'wr' model_ac.x = x model_ac.xdot = cs.MX.sym('x_dot', 2) model_ac.u = u model_ac.f_expl_expr = f_expl model_ac.f_impl_expr = model_ac.xdot - f_expl ocp = AcadosOcp() ocp.model = model_ac ocp.dims.N = 10 ocp.solver_options.tf = 1.0 ocp.solver_options.nlp_solver_type = 'SQP_RTI' ocp.solver_options.integrator_type = 'ERK' # Key: link the L4CasADi compiled shared library into Acados ocp.solver_options.model_external_shared_lib_dir = learned_dyn.shared_lib_dir ocp.solver_options.model_external_shared_lib_name = learned_dyn.name ocp.constraints.x0 = np.array([1., 0.]) ocp.cost.cost_type = 'LINEAR_LS' ocp.cost.cost_type_e = 'LINEAR_LS' ocp.cost.W = np.array([[1.]]) ocp.cost.Vx = np.array([[1., 0.]]) ocp.cost.Vu = np.zeros((1, 1)) ocp.cost.Vx_e = np.zeros((1, 2)) ocp.cost.W_e = np.array([[0.]]) ocp.cost.yref = np.zeros(1) ocp.cost.yref_e = np.zeros(1) ocp.constraints.lbu = np.array([-10.]) ocp.constraints.ubu = np.array([ 10.]) ocp.constraints.idxbu = np.array([0]) ocp.parameter_values = np.array([]) solver = AcadosOcpSolver(ocp) solver.solve() print("State at node 1:", solver.get(1, 'x')) ```