Porting acados' example ocp_qp_hpmpc to ARM Cortex M4 microcontroller TM4C129
http://www.ti.com/tool/ek-tm4c1294xl
Tiva C Series TM4C1294 Connected LaunchPad Evaluation Kit (the kit we used is indeed Rev. A of this board)
The second test in the code (partial condensing) could not finish due to large memory requirement, the first test (full sparse HPMPC) finished successfully, with output:
HPMPC -- Library for High-Performance implementation of solvers for MPC. Copyright (C) 2014-2015 by Technical University of Denmark. All rights reserved.
HPMPC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
Test problem: mass-spring system with 4 masses and 3 controls.
MPC problem size: 8 states, 3 inputs, 15 horizon length, 11 two-sided box constraints, 0 two-sided general constraints.
IP method parameters: predictor-corrector IP, double precision, 10 maximum iterations, 1.0e-08 exit tolerance in duality measure.
work space size: 112348 bytes
ACADOS status: solution found in 8 iterations
u = 0.15667 -0.50000 -0.50000
0.50000 0.25181 -0.50000
0.50000 0.50000 -0.50000
0.50000 0.50000 -0.50000
0.44444 0.24107 0.37914
-0.50000 -0.09610 0.50000
-0.50000 -0.41883 0.50000
-0.50000 -0.50000 0.50000
-0.50000 -0.50000 0.07756
-0.03450 -0.50000 -0.14724
0.46227 -0.48597 -0.21080
0.46297 0.36571 -0.27691
0.20041 0.50000 -0.37781
-0.02661 0.50000 -0.42720
-0.07827 0.40142 -0.35408
x =
2.31152 2.23938 0.33223 0.10497 -1.03596 -1.28640 0.95970 0.13887
1.68032 1.55471 0.98834 0.30509 -1.73239 -1.63471 1.21310 0.39214
0.79556 0.89504 1.54824 0.65274 -2.00532 -1.22029 0.60584 0.69597
-0.07104 0.52703 1.67354 1.10828 -1.63794 -0.55265 -0.41813 0.76863
-0.59944 0.42646 1.42596 1.48468 -0.68669 -0.19861 -0.80687 0.36103
-0.68458 0.39262 1.10092 1.54841 0.06611 -0.26584 -0.73588 -0.43597
-0.41034 0.26626 0.87033 1.19466 0.68243 -0.51447 -0.48841 -1.23052
0.06194 0.06655 0.73248 0.53771 0.81864 -0.52212 -0.41251 -1.58984
0.46131 -0.04995 0.50676 -0.14439 0.41020 -0.20928 -0.82014 -1.33437
0.62615 0.00753 0.04003 -0.58201 -0.06518 0.10403 -1.30029 -0.67355
0.60450 0.14383 -0.56957 -0.67513 -0.29758 0.06463 -1.33157 -0.02656
0.49676 0.25414 -1.03931 -0.51927 -0.39731 0.00899 -0.74555 0.29232
0.34817 0.27191 -1.10552 -0.29617 -0.46212 -0.25925 0.21230 0.26527
0.17463 0.15501 -0.70020 -0.12722 -0.50445 -0.46905 1.04501 0.12486
-0.00000 -0.00000 0.00000 0.00000 -0.46964 -0.38038 1.33528 0.13041
inf norm res: 4.699943e-09, 1.152566e-11, 5.010791e-13, 5.716404e-08, 2.394717e-10
Average solution time over 10 runs: 8.61e-01 seconds
For comparison, the same code executed on laptop Dell XPS 9350 (Intel Core i7-6560U 2.2 GHz) with Ubuntu 14.04: Average solution time over 1000 runs: 2.71e-04 seconds
The main modifications include:
- Do not use posix_memalign in d_aux_extern_depend_lib.c
- Provide a function gettimeofday() so that acados uses for measuring computational time.
Detailed steps that have been done for this example:
-
Add clock-arch.h, linux_time.h, linux_time.c (using SysTick and interrupt for measuring time, can switch to Timer0 instead of SysTick)
-
In Project Build_settings:
- General: Choose Connection = Stellaris In-Circuit Debug Interface, tick "Manage the project's target-configuration automatically Compiler version: TI v16.9.1.LTS
- ARM Compiler / Optimization: Optimization level 2 -- Global Optimizations. Speed vs size trade-off: seems not affect much on the speed (leave it default = 2)
- ARM Compiler / Include Options: "${PROJECT_ROOT}" "${PROJECT_ROOT}/include" "${CG_TOOL_ROOT}/include" path_to_folder/TivaWare_C_Series-2.1.3.156
- ARM Compiler / ULP Advisor: None
- ARM Compiler / Advanced Options / Language Options: Choose C Dialect = C99
- ARM Linker / Basic Options: Heap size for C/C++ dynamic memory allocation: 0x2fa00 (this can be up to 0x3fa00) Set C system stack size: 1024
- ARM Linker / File Search Path: Include library files: libc.a path_to_folder/TivaWare_C_Series-2.1.3.156/driverlib/ccs/Debug/driverlib.lib
-
Change the CCS generated file tm4c129encpdt_startup_ccs.c (or startup_ccs.c):
- Add: extern void SysTickIntHandler(void);
- Change the vector of interrupt handlers: use "SysTickIntHandler"
-
Change some code in acados project (here is the summary for ocp_qp_hpmpc example as of 2017.05.05):
-
In function main(), add: // // Set the clocking to run directly from the crystal at 120MHz. // g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); // // Enable the GPIO port that is used for the on-board LEDs. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
// // Enable processor interrupts. // IntMasterEnable();
// // Set SysTick timer to CLOCK_CONF_SECOND rounds per round. // SysTickPeriodSet(g_ui32SysClock/CLOCK_CONF_SECOND-1);
// // Enable the SysTick Interrupt. // SysTickIntEnable();
// // Enable SysTick timer // printf("Start SysTick counter\n"); SysTickEnable();
-
In file d_aux_extern_depend_lib.c: avoid running the posix_memalign() function, as it is not supported in ARM Cortex M4 non-eabi
-
In file include/timing.h: instead of libraries <sys/stat.h> and <sys/time.h>, use: #include "linux_time.h"
-
-
Compile the Debug build, and run the Debug on the dev board.