diff --git a/Jenkinsfile b/Jenkinsfile
index f6d07bc85..d41a1f904 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -70,7 +70,7 @@ pipeline {
}
steps {
phone_steps("eon-build", [
- ["build release2-staging & dashcam-staging", "cd release && PUSH=1 ./build_release2.sh"],
+ ["build release2-staging & dashcam-staging", "PUSH=1 $SOURCE_DIR/release/build_release.sh"],
])
}
}
@@ -87,7 +87,7 @@ pipeline {
}
steps {
phone_steps("tici", [
- ["build release3-staging & dashcam3-staging", "PUSH=1 $SOURCE_DIR/release/build_release3.sh"],
+ ["build release3-staging & dashcam3-staging", "PUSH=1 $SOURCE_DIR/release/build_release.sh"],
])
}
}
@@ -170,13 +170,12 @@ pipeline {
steps {
phone_steps("eon", [
["build", "cd selfdrive/manager && ./build.py"],
- ["test athena", "nosetests -s selfdrive/athena/tests/test_athenad_old.py"],
- ["test sounds", "nosetests -s selfdrive/ui/tests/test_sounds.py"],
- ["test boardd loopback", "nosetests -s selfdrive/boardd/tests/test_boardd_loopback.py"],
+ ["test sounds", "python selfdrive/ui/tests/test_soundd.py"],
+ ["test boardd loopback", "python selfdrive/boardd/tests/test_boardd_loopback.py"],
["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"],
["test encoder", "python selfdrive/loggerd/tests/test_encoder.py"],
["test logcatd", "python selfdrive/logcatd/tests/test_logcatd_android.py"],
- //["test updater", "python installer/updater/test_updater.py"],
+ ["test updater", "python selfdrive/hardware/eon/test_neos_updater.py"],
])
}
}
@@ -224,7 +223,7 @@ pipeline {
}
}
- stage('camerad') {
+ stage('EON camerad') {
steps {
phone_steps("eon-party", [
["build", "cd selfdrive/manager && ./build.py"],
@@ -234,7 +233,7 @@ pipeline {
}
}
- stage('Tici camerad') {
+ stage('tici camerad') {
steps {
phone_steps("tici-party", [
["build", "cd selfdrive/manager && ./build.py"],
diff --git a/README.md b/README.md
index 74906943b..abe87a72f 100755
--- a/README.md
+++ b/README.md
@@ -4,18 +4,11 @@ Table of Contents
=======================
* [What is openpilot?](#what-is-openpilot)
-* [Integration with Stock Features](#integration-with-stock-features)
-* [Supported Hardware](#supported-hardware)
-* [Supported Cars](#supported-cars)
-* [Community Maintained Cars and Features](#community-maintained-cars-and-features)
-* [Installation Instructions](#installation-instructions)
-* [Limitations of openpilot ALC and LDW](#limitations-of-openpilot-alc-and-ldw)
-* [Limitations of openpilot ACC and FCW](#limitations-of-openpilot-acc-and-fcw)
-* [Limitations of openpilot DM](#limitations-of-openpilot-dm)
+* [Running in a car](#running-in-a-car)
+* [Running on PC](#running-on-pc)
+* [Community and Contributing](#community-and-contributing)
* [User Data and comma Account](#user-data-and-comma-account)
* [Safety and Testing](#safety-and-testing)
-* [Testing on PC](#testing-on-pc)
-* [Community and Contributing](#community-and-contributing)
* [Directory Structure](#directory-structure)
* [Licensing](#licensing)
@@ -24,7 +17,7 @@ Table of Contents
What is openpilot?
------
-[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW) and Lane Departure Warning (LDW) for a growing variety of supported [car makes, models and model years](#supported-cars). In addition, while openpilot is engaged, a camera based Driver Monitoring (DM) feature alerts distracted and asleep drivers.
+[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW) and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models and model years](docs/CARS.md). In addition, while openpilot is engaged, a camera based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration and limitations here](docs/INTEGRATION.md).
@@ -41,306 +34,32 @@ What is openpilot?
-Integration with Stock Features
+
+Running in a car
------
-In all supported cars:
-* Stock Lane Keep Assist (LKA) and stock ALC are replaced by openpilot ALC, which only functions when openpilot is engaged by the user.
-* Stock LDW is replaced by openpilot LDW.
+To use openpilot in a car, you need four things
+* This software. It's free and available right here.
+* One of [the 140+ supported cars](docs/CARS.md). We support Honda, Toyota, Hyundai, Nissan, Kia, Chrysler, Lexus, Acura, Audi, VW, and more. If your car is not supported, but has adaptive cruise control and lane keeping assist, it's likely able to run openpilot.
+* A supported device to run this software. This can be a [comma two](https://comma.ai/shop/products/two), [comma three](https://comma.ai/shop/products/three), or if you like to experiment, a [Ubuntu computer with webcams](https://github.com/commaai/openpilot/tree/master/tools/webcam).
+* A way to connect to your car. With a comma two or three, you need only a [car harness](https://comma.ai/shop/products/car-harness). With an EON Gold or PC, you also need a [black panda](https://comma.ai/shop/products/panda).
-Additionally, on specific supported cars (see ACC column in [supported cars](#supported-cars)):
-* Stock ACC is replaced by openpilot ACC.
-* openpilot FCW operates in addition to stock FCW.
+We have detailed instructions for [how to install the device in a car](https://comma.ai/setup).
-openpilot should preserve all other vehicle's stock features, including, but are not limited to: FCW, Automatic Emergency Braking (AEB), auto high-beam, blind spot warning, and side collision warning.
-
-Supported Hardware
+Running on PC
------
-At the moment, openpilot supports the EON Gold DevKit, [comma two](https://comma.ai/shop/products/two), and [comma three](https://comma.ai/shop/products/three). A [car harness](https://comma.ai/shop/products/car-harness) is recommended to connect your device to the car. For experimental purposes, openpilot can also run on an Ubuntu computer with external [webcams](https://github.com/commaai/openpilot/tree/master/tools/webcam).
+All of openpilot's services can run as normal on a PC, even without special hardware or a car. To develop or experiment with openpilot you can run openpilot on recorded or simulated data.
-Supported Cars
-------
+With openpilot's tools you can plot logs, replay drives and watch the full-res camera streams. See [the tools README](tools/README.md) for more information.
-| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
-| ----------| ------------------------------| ------------------| -----------------| -------------------| ------------------|
-| Acura | ILX 2016-19 | AcuraWatch Plus | openpilot | 25mph1 | 25mph |
-| Acura | RDX 2016-18 | AcuraWatch Plus | openpilot | 25mph1 | 12mph |
-| Acura | RDX 2019-21 | All | Stock | 0mph | 3mph |
-| Honda | Accord 2018-20 | All | Stock | 0mph | 3mph |
-| Honda | Accord Hybrid 2018-20 | All | Stock | 0mph | 3mph |
-| Honda | Civic Hatchback 2017-21 | Honda Sensing | Stock | 0mph | 12mph |
-| Honda | Civic Coupe 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
-| Honda | Civic Coupe 2019-20 | All | Stock | 0mph | 2mph2 |
-| Honda | Civic Sedan 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
-| Honda | Civic Sedan 2019-20 | All | Stock | 0mph | 2mph2 |
-| Honda | CR-V 2015-16 | Touring | openpilot | 25mph1 | 12mph |
-| Honda | CR-V 2017-21 | Honda Sensing | Stock | 0mph | 12mph |
-| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Stock | 0mph | 12mph |
-| Honda | e 2020 | All | Stock | 0mph | 3mph |
-| Honda | Fit 2018-19 | Honda Sensing | openpilot | 25mph1 | 12mph |
-| Honda | HR-V 2019-20 | Honda Sensing | openpilot | 25mph1 | 12mph |
-| Honda | Insight 2019-21 | All | Stock | 0mph | 3mph |
-| Honda | Inspire 2018 | All | Stock | 0mph | 3mph |
-| Honda | Odyssey 2018-20 | Honda Sensing | openpilot | 25mph1 | 0mph |
-| Honda | Passport 2019 | All | openpilot | 25mph1 | 12mph |
-| Honda | Pilot 2016-19 | Honda Sensing | openpilot | 25mph1 | 12mph |
-| Honda | Ridgeline 2017-21 | Honda Sensing | openpilot | 25mph1 | 12mph |
-| Hyundai | Palisade 2020-21 | All | Stock | 0mph | 0mph |
-| Hyundai | Sonata 2020-21 | All | Stock | 0mph | 0mph |
-| Lexus | CT Hybrid 2017-18 | LSS | Stock3| 0mph | 0mph |
-| Lexus | ES 2019-21 | All | openpilot | 0mph | 0mph |
-| Lexus | ES Hybrid 2017-18 | LSS | Stock3| 0mph | 0mph |
-| Lexus | ES Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
-| Lexus | IS 2017-2019 | All | Stock | 22mph | 0mph |
-| Lexus | NX 2018 | All | Stock3| 0mph | 0mph |
-| Lexus | NX 2020 | All | openpilot | 0mph | 0mph |
-| Lexus | NX Hybrid 2018-19 | All | Stock3| 0mph | 0mph |
-| Lexus | RX 2016-18 | All | Stock3| 0mph | 0mph |
-| Lexus | RX 2020-21 | All | openpilot | 0mph | 0mph |
-| Lexus | RX Hybrid 2016-19 | All | Stock3| 0mph | 0mph |
-| Lexus | RX Hybrid 2020-21 | All | openpilot | 0mph | 0mph |
-| Lexus | UX Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
-| Toyota | Alphard 2020 | All | openpilot | 0mph | 0mph |
-| Toyota | Avalon 2016-21 | TSS-P | Stock3| 20mph1 | 0mph |
-| Toyota | Avalon Hybrid 2019-21 | TSS-P | Stock3| 20mph1 | 0mph |
-| Toyota | Camry 2018-20 | All | Stock | 0mph4 | 0mph |
-| Toyota | Camry 2021 | All | openpilot | 0mph4 | 0mph |
-| Toyota | Camry Hybrid 2018-20 | All | Stock | 0mph4 | 0mph |
-| Toyota | Camry Hybrid 2021 | All | openpilot | 0mph | 0mph |
-| Toyota | C-HR 2017-20 | All | Stock | 0mph | 0mph |
-| Toyota | C-HR Hybrid 2017-19 | All | Stock | 0mph | 0mph |
-| Toyota | Corolla 2017-19 | All | Stock3| 20mph1 | 0mph |
-| Toyota | Corolla 2020-22 | All | openpilot | 0mph | 0mph |
-| Toyota | Corolla Hatchback 2019-21 | All | openpilot | 0mph | 0mph |
-| Toyota | Corolla Hybrid 2020-21 | All | openpilot | 0mph | 0mph |
-| Toyota | Highlander 2017-19 | All | Stock3| 0mph | 0mph |
-| Toyota | Highlander 2020-21 | All | openpilot | 0mph | 0mph |
-| Toyota | Highlander Hybrid 2017-19 | All | Stock3| 0mph | 0mph |
-| Toyota | Highlander Hybrid 2020-21 | All | openpilot | 0mph | 0mph |
-| Toyota | Mirai 2021 | All | openpilot | 0mph | 0mph |
-| Toyota | Prius 2016-20 | TSS-P | Stock3| 0mph | 0mph |
-| Toyota | Prius 2021 | All | openpilot | 0mph | 0mph |
-| Toyota | Prius Prime 2017-20 | All | Stock3| 0mph | 0mph |
-| Toyota | Prius Prime 2021 | All | openpilot | 0mph | 0mph |
-| Toyota | Rav4 2016-18 | TSS-P | Stock3| 20mph1 | 0mph |
-| Toyota | Rav4 2019-21 | All | openpilot | 0mph | 0mph |
-| Toyota | Rav4 Hybrid 2016-18 | TSS-P | Stock3| 0mph | 0mph |
-| Toyota | Rav4 Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
-| Toyota | Sienna 2018-20 | All | Stock3| 0mph | 0mph |
-
-1[Comma Pedal](https://github.com/commaai/openpilot/wiki/comma-pedal) is used to provide stop-and-go capability to some of the openpilot-supported cars that don't currently support stop-and-go. ***NOTE: The Comma Pedal is not officially supported by [comma](https://comma.ai).***
-22019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph.
-3When disconnecting the Driver Support Unit (DSU), openpilot ACC will replace stock ACC. ***NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).***
-428mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control.
-
-Community Maintained Cars and Features
-------
-
-| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
-| ----------| ------------------------------| ------------------| -----------------| -------------------| -------------|
-| Audi | A3 2014-19 | Prestige | Stock | 0mph | 0mph |
-| Audi | A3 Sportback e-tron 2017-18 | Prestige | Stock | 0mph | 0mph |
-| Audi | Q2 2018 | Driver Assistance | Stock | 0mph | 0mph |
-| Buick | Regal 20181 | Adaptive Cruise | openpilot | 0mph | 7mph |
-| Cadillac | ATS 20181 | Adaptive Cruise | openpilot | 0mph | 7mph |
-| Chevrolet | Malibu 20171 | Adaptive Cruise | openpilot | 0mph | 7mph |
-| Chevrolet | Volt 2017-181 | Adaptive Cruise | openpilot | 0mph | 7mph |
-| Chrysler | Pacifica 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
-| Chrysler | Pacifica 2020 | Adaptive Cruise | Stock | 0mph | 39mph |
-| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
-| Chrysler | Pacifica Hybrid 2019-21 | Adaptive Cruise | Stock | 0mph | 39mph |
-| Genesis | G70 2018 | All | Stock | 0mph | 0mph |
-| Genesis | G80 2018 | All | Stock | 0mph | 0mph |
-| Genesis | G90 2018 | All | Stock | 0mph | 0mph |
-| GMC | Acadia 20181 | Adaptive Cruise | openpilot | 0mph | 7mph |
-| Holden | Astra 20171 | Adaptive Cruise | openpilot | 0mph | 7mph |
-| Hyundai | Elantra 2017-19 | SCC + LKAS | Stock | 19mph | 34mph |
-| Hyundai | Elantra 2021 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Elantra Hybrid 2021 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Genesis 2015-16 | SCC + LKAS | Stock | 19mph | 37mph |
-| Hyundai | Ioniq Electric 2019 | SCC + LKAS | Stock | 0mph | 32mph |
-| Hyundai | Ioniq Electric 2020 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Ioniq PHEV 2020 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Kona 2020 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Kona EV 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Kona Hybrid 2020 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Santa Fe 2019-20 | All | Stock | 0mph | 0mph |
-| Hyundai | Sonata 2018-2019 | SCC + LKAS | Stock | 0mph | 0mph |
-| Hyundai | Sonata Hybrid 2021 | All | Stock | 0mph | 0mph |
-| Hyundai | Veloster 2019-20 | SCC + LKAS | Stock | 5mph | 0mph |
-| Jeep | Grand Cherokee 2016-18 | Adaptive Cruise | Stock | 0mph | 9mph |
-| Jeep | Grand Cherokee 2019-20 | Adaptive Cruise | Stock | 0mph | 39mph |
-| Kia | Forte 2018-21 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Niro EV 2019-21 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Niro Hybrid 2021 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Niro PHEV 2019 | SCC + LKAS | Stock | 10mph | 32mph |
-| Kia | Optima 2017 | SCC + LKAS | Stock | 0mph | 32mph |
-| Kia | Optima 2019 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Seltos 2021 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Sorento 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Stinger 2018 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Ceed 2019 | SCC + LKAS | Stock | 0mph | 0mph |
-| Kia | Telluride 2020 | SCC + LKAS | Stock | 0mph | 0mph |
-| Nissan | Altima 2019-20 | ProPILOT | Stock | 0mph | 0mph |
-| Nissan | Leaf 2018-20 | ProPILOT | Stock | 0mph | 0mph |
-| Nissan | Rogue 2018-20 | ProPILOT | Stock | 0mph | 0mph |
-| Nissan | X-Trail 2017 | ProPILOT | Stock | 0mph | 0mph |
-| SEAT | Ateca 2018 | Driver Assistance | Stock | 0mph | 0mph |
-| SEAT | Leon 2014-2020 | Driver Assistance | Stock | 0mph | 0mph |
-| Škoda | Kodiaq 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
-| Škoda | Octavia 2015, 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
-| Škoda | Octavia RS 2016 | Driver Assistance | Stock | 0mph | 0mph |
-| Škoda | Scala 2020 | Driver Assistance | Stock | 0mph | 0mph |
-| Škoda | Superb 2015-18 | Driver Assistance | Stock | 0mph | 0mph |
-| Subaru | Ascent 2019 | EyeSight | Stock | 0mph | 0mph |
-| Subaru | Crosstrek 2018-19 | EyeSight | Stock | 0mph | 0mph |
-| Subaru | Forester 2019-21 | EyeSight | Stock | 0mph | 0mph |
-| Subaru | Impreza 2017-19 | EyeSight | Stock | 0mph | 0mph |
-| Volkswagen| Atlas 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| e-Golf 2014, 2019-20 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Golf 2015-20 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Golf Alltrack 2017-18 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Golf GTE 2016 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Golf GTI 2018-20 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Golf R 2016-19 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Golf SportsVan 2016 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Golf SportWagen 2015 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Jetta 2018-20 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Jetta GLI 2021 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Passat 2016-172 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| T-Cross 2021 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Tiguan 2020 | Driver Assistance | Stock | 0mph | 0mph |
-| Volkswagen| Touran 2017 | Driver Assistance | Stock | 0mph | 0mph |
-
-1Requires an [OBD-II car harness](https://comma.ai/shop/products/comma-car-harness) and [community built ASCM harness](https://github.com/commaai/openpilot/wiki/GM#hardware). ***NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).***
-2Only includes the MQB Passat sold outside of North America. The NMS Passat made in Chattanooga TN is not yet supported.
-
-Community Maintained Cars and Features are not verified by comma to meet our [safety model](SAFETY.md). Be extra cautious using them. They are only available after enabling the toggle in `Settings->Developer->Enable Community Features`.
-
-To promote a car from community maintained, it must meet a few requirements. We must own one from the brand, we must sell the harness for it, has full ISO26262 in both panda and openpilot, there must be a path forward for longitudinal control, it must have AEB still enabled, and it must support fingerprinting 2.0
-
-Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
-
-Installation Instructions
-------
-
-Install openpilot on a supported device by entering ``https://openpilot.comma.ai`` during the installer setup.
-
-Follow these [video instructions](https://youtu.be/lcjqxCymins) to properly mount the device on the windshield. Note: openpilot features an automatic pose calibration routine and openpilot performance should not be affected by small pitch and yaw misalignments caused by imprecise device mounting.
-
-Before placing the device on your windshield, check the state and local laws and ordinances where you drive. Some state laws prohibit or restrict the placement of objects on the windshield of a motor vehicle.
-
-You will be able to engage openpilot after reviewing the onboarding screens and finishing the calibration procedure.
-
-Limitations of openpilot ALC and LDW
-------
-
-openpilot ALC and openpilot LDW do not automatically drive the vehicle or reduce the amount of attention that must be paid to operate your vehicle. The driver must always keep control of the steering wheel and be ready to correct the openpilot ALC action at all times.
-
-While changing lanes, openpilot is not capable of looking next to you or checking your blind spot. Only nudge the wheel to initiate a lane change after you have confirmed it's safe to do so.
-
-Many factors can impact the performance of openpilot ALC and openpilot LDW, causing them to be unable to function as intended. These include, but are not limited to:
-
-* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation.
-* The road facing camera is obstructed, covered or damaged by mud, ice, snow, etc.
-* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle.
-* The device is mounted incorrectly.
-* When in sharp curves, like on-off ramps, intersections etc...; openpilot is designed to be limited in the amount of steering torque it can produce.
-* In the presence of restricted lanes or construction zones.
-* When driving on highly banked roads or in presence of strong cross-wind.
-* Extremely hot or cold temperatures.
-* Bright light (due to oncoming headlights, direct sunlight, etc.).
-* Driving on hills, narrow, or winding roads.
-
-The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times.
-
-Limitations of openpilot ACC and FCW
-------
-
-openpilot ACC and openpilot FCW are not systems that allow careless or inattentive driving. It is still necessary for the driver to pay close attention to the vehicle’s surroundings and to be ready to re-take control of the gas and the brake at all times.
-
-Many factors can impact the performance of openpilot ACC and openpilot FCW, causing them to be unable to function as intended. These include, but are not limited to:
-
-* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation.
-* The road facing camera or radar are obstructed, covered, or damaged by mud, ice, snow, etc.
-* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle.
-* The device is mounted incorrectly.
-* Approaching a toll booth, a bridge or a large metal plate.
-* When driving on roads with pedestrians, cyclists, etc...
-* In presence of traffic signs or stop lights, which are not detected by openpilot at this time.
-* When the posted speed limit is below the user selected set speed. openpilot does not detect speed limits at this time.
-* In presence of vehicles in the same lane that are not moving.
-* When abrupt braking maneuvers are required. openpilot is designed to be limited in the amount of deceleration and acceleration that it can produce.
-* When surrounding vehicles perform close cut-ins from neighbor lanes.
-* Driving on hills, narrow, or winding roads.
-* Extremely hot or cold temperatures.
-* Bright light (due to oncoming headlights, direct sunlight, etc.).
-* Interference from other equipment that generates radar waves.
-
-The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times.
-
-Limitations of openpilot DM
-------
-
-openpilot DM should not be considered an exact measurement of the alertness of the driver.
-
-Many factors can impact the performance of openpilot DM, causing it to be unable to function as intended. These include, but are not limited to:
-
-* Low light conditions, such as driving at night or in dark tunnels.
-* Bright light (due to oncoming headlights, direct sunlight, etc.).
-* The driver's face is partially or completely outside field of view of the driver facing camera.
-* The driver facing camera is obstructed, covered, or damaged.
-
-The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. A driver should not rely on openpilot DM to assess their level of attention.
-
-User Data and comma Account
-------
-
-By default, openpilot uploads the driving data to our servers. You can also access your data by pairing with the comma connect app ([iOS](https://apps.apple.com/us/app/comma-connect/id1456551889), [Android](https://play.google.com/store/apps/details?id=ai.comma.connect&hl=en_US)). We use your data to train better models and improve openpilot for everyone.
-
-openpilot is open source software: the user is free to disable data collection if they wish to do so.
-
-openpilot logs the road facing camera, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
-The driver facing camera is only logged if you explicitly opt-in in settings. The microphone is not recorded.
-
-By using openpilot, you agree to [our Privacy Policy](https://connect.comma.ai/privacy). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data.
-
-Safety and Testing
-----
-
-* openpilot observes ISO26262 guidelines, see [SAFETY.md](SAFETY.md) for more details.
-* openpilot has software in the loop [tests](.github/workflows/selfdrive_tests.yaml) that run on every commit.
-* The safety model code lives in panda and is written in C, see [code rigor](https://github.com/commaai/panda#code-rigor) for more details.
-* panda has software in the loop [safety tests](https://github.com/commaai/panda/tree/master/tests/safety).
-* Internally, we have a hardware in the loop Jenkins test suite that builds and unit tests the various processes.
-* panda has additional hardware in the loop [tests](https://github.com/commaai/panda/blob/master/Jenkinsfile).
-* We run the latest openpilot in a testing closet containing 10 comma devices continuously replaying routes.
-
-Testing on PC
-------
-For simplified development and experimentation, openpilot can be run in the CARLA driving simulator, which allows you to develop openpilot without a car. The whole setup should only take a few minutes.
-
-Steps:
-1) Start the CARLA server on first terminal
-```
-bash -c "$(curl https://raw.githubusercontent.com/commaai/openpilot/master/tools/sim/start_carla.sh)"
-```
-2) Start openpilot on second terminal
-```
-bash -c "$(curl https://raw.githubusercontent.com/commaai/openpilot/master/tools/sim/start_openpilot_docker.sh)"
-```
-3) Press 1 to engage openpilot
-
-See the full [README](tools/sim/README.md)
-
-You should also take a look at the tools directory in master: lots of tools you can use to replay driving data, test, and develop openpilot from your PC.
+You can also run openpilot in simulation [with the CARLA simulator](tools/sim/README.md). This allows openpilot to drive around a virtual car on your Ubuntu machine. The whole setup should only take a few minutes, but does require a decent GPU.
Community and Contributing
------
-openpilot is developed by [comma](https://comma.ai/) and by users like you. We welcome both pull requests and issues on [GitHub](http://github.com/commaai/openpilot). Bug fixes and new car ports are encouraged.
+openpilot is developed by [comma](https://comma.ai/) and by users like you. We welcome both pull requests and issues on [GitHub](http://github.com/commaai/openpilot). Bug fixes and new car ports are encouraged. Check out [the contributing docs](docs/CONTRIBUTING.md).
You can add support for your car by following guides we have written for [Brand](https://blog.comma.ai/how-to-write-a-car-port-for-openpilot/) and [Model](https://blog.comma.ai/openpilot-port-guide-for-toyota-models/) ports. Generally, a car with adaptive cruise control and lane keep assist is a good candidate. [Join our Discord](https://discord.comma.ai) to discuss car ports: most car makes have a dedicated channel.
@@ -348,16 +67,39 @@ Want to get paid to work on openpilot? [comma is hiring](https://comma.ai/jobs/)
And [follow us on Twitter](https://twitter.com/comma_ai).
+User Data and comma Account
+------
+
+By default, openpilot uploads the driving data to our servers. You can also access your data through [comma connect](https://connect.comma.ai/). We use your data to train better models and improve openpilot for everyone.
+
+openpilot is open source software: the user is free to disable data collection if they wish to do so.
+
+openpilot logs the road facing cameras, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
+The driver facing camera is only logged if you explicitly opt-in in settings. The microphone is not recorded.
+
+By using openpilot, you agree to [our Privacy Policy](https://comma.ai/privacy). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data.
+
+Safety and Testing
+----
+
+* openpilot observes ISO26262 guidelines, see [SAFETY.md](docs/SAFETY.md) for more details.
+* openpilot has software in the loop [tests](.github/workflows/selfdrive_tests.yaml) that run on every commit.
+* The code enforcing the safety model lives in panda and is written in C, see [code rigor](https://github.com/commaai/panda#code-rigor) for more details.
+* panda has software in the loop [safety tests](https://github.com/commaai/panda/tree/master/tests/safety).
+* Internally, we have a hardware in the loop Jenkins test suite that builds and unit tests the various processes.
+* panda has additional hardware in the loop [tests](https://github.com/commaai/panda/blob/master/Jenkinsfile).
+* We run the latest openpilot in a testing closet containing 10 comma devices continuously replaying routes.
+
Directory Structure
------
.
├── cereal # The messaging spec and libs used for all logs
├── common # Library like functionality we've developed here
- ├── installer/updater # Manages updates of NEOS
+ ├── docs # Documentation
├── opendbc # Files showing how to interpret data from cars
├── panda # Code used to communicate on CAN
- ├── phonelibs # External libraries
- ├── pyextra # Extra python packages not shipped in NEOS
+ ├── third_party # External libraries
+ ├── pyextra # Extra python packages
└── selfdrive # Code needed to drive the car
├── assets # Fonts, images, and sounds for UI
├── athena # Allows communication with the app
@@ -381,7 +123,7 @@ Licensing
openpilot is released under the MIT license. Some parts of the software are released under other licenses as specified.
-Any user of this software shall indemnify and hold harmless comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys’ fees and costs) which arise out of, relate to or result from any use of this software by user.
+Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys’ fees and costs) which arise out of, relate to or result from any use of this software by user.
**THIS IS ALPHA QUALITY SOFTWARE FOR RESEARCH PURPOSES ONLY. THIS IS NOT A PRODUCT.
YOU ARE RESPONSIBLE FOR COMPLYING WITH LOCAL LAWS AND REGULATIONS.
diff --git a/RELEASES.md b/RELEASES.md
index ca5fea849..64f0814e2 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,34 @@
+Version 0.8.10 (2021-11-01)
+========================
+ * New driving model
+ * Trained on one million minutes!!!
+ * Fixed lead training making lead predictions significantly more accurate
+ * Fixed several localizer dataset bugs and loss function bugs, overall improved accuracy
+ * New driver monitoring model
+ * Trained on latest data from both comma two and comma three
+ * Increased model field of view by 40% on comma three
+ * Improved model stability on masked users
+ * Improved pose prediction with reworked ground-truth stack
+ * Lateral and longitudinal planning MPCs now in ACADOS
+ * Combined longitudinal MPCs
+ * All longitudinal planning now happens in a single MPC system
+ * Fixed instability in MPC problem to prevent sporadic CPU usage
+ * AGNOS 2: minor stability improvements and builder repo open sourced
+ * tools: new and improved replay thanks to deanlee!
+ * Moved community-supported cars outside of the Community Features toggle
+ * Improved FW fingerprinting reliability for Hyundai/Kia/Genesis
+ * Added prerequisites for longitudinal control on Hyundai/Kia/Genesis and Honda Bosch
+ * Audi S3 2015 support thanks to jyoung8607!
+ * Honda Freed 2020 support thanks to belm0!
+ * Hyundai Ioniq Hybrid 2020-2022 support thanks to sunnyhaibin!
+ * Hyundai Santa Fe 2022 support thanks to sunnyhaibin!
+ * Kia K5 2021 support thanks to sunnyhaibin!
+ * Škoda Kamiq 2021 support thanks to jyoung8607!
+ * Škoda Karoq 2019 support thanks to jyoung8607!
+ * Volkswagen Arteon 2021 support thanks to jyoung8607!
+ * Volkswagen California 2021 support thanks to jyoung8607!
+ * Volkswagen Taos 2022 support thanks to jyoung8607!
+
Version 0.8.9 (2021-09-14)
========================
* Improved fan control on comma three
diff --git a/SConstruct b/SConstruct
index 02a93eb98..18c8d2f12 100644
--- a/SConstruct
+++ b/SConstruct
@@ -37,10 +37,6 @@ AddOption('--compile_db',
action='store_true',
help='build clang compilation database')
-AddOption('--mpc-generate',
- action='store_true',
- help='regenerates the mpc sources')
-
AddOption('--snpe',
action='store_true',
help='use SNPE on PC')
@@ -64,13 +60,21 @@ if arch == "aarch64" and TICI:
arch = "larch64"
USE_WEBCAM = os.getenv("USE_WEBCAM") is not None
+USE_FRAME_STREAM = os.getenv("USE_FRAME_STREAM") is not None
lenv = {
"PATH": os.environ['PATH'],
+ "LD_LIBRARY_PATH": [Dir(f"#third_party/acados/{arch}/lib").abspath],
+ "PYTHONPATH": Dir("#").abspath + ":" + Dir("#pyextra/").abspath,
+
+ "ACADOS_SOURCE_DIR": Dir("#third_party/acados/acados").abspath,
+ "TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer",
}
+rpath = lenv["LD_LIBRARY_PATH"].copy()
+
if arch == "aarch64" or arch == "larch64":
- lenv["LD_LIBRARY_PATH"] = '/data/data/com.termux/files/usr/lib'
+ lenv["LD_LIBRARY_PATH"] += ['/data/data/com.termux/files/usr/lib']
if arch == "aarch64":
# android
@@ -78,7 +82,7 @@ if arch == "aarch64" or arch == "larch64":
lenv["ANDROID_ROOT"] = os.environ['ANDROID_ROOT']
cpppath = [
- "#phonelibs/opencl/include",
+ "#third_party/opencl/include",
]
libpath = [
@@ -86,13 +90,14 @@ if arch == "aarch64" or arch == "larch64":
"/usr/lib",
"/system/vendor/lib64",
"/system/comma/usr/lib",
- "#phonelibs/nanovg",
+ "#third_party/nanovg",
+ f"#third_party/acados/{arch}/lib",
]
if arch == "larch64":
libpath += [
- "#phonelibs/snpe/larch64",
- "#phonelibs/libyuv/larch64/lib",
+ "#third_party/snpe/larch64",
+ "#third_party/libyuv/larch64/lib",
"/usr/lib/aarch64-linux-gnu"
]
cpppath += [
@@ -100,16 +105,16 @@ if arch == "aarch64" or arch == "larch64":
]
cflags = ["-DQCOM2", "-mcpu=cortex-a57"]
cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"]
- rpath = ["/usr/local/lib"]
+ rpath += ["/usr/local/lib"]
else:
+ rpath = []
libpath += [
- "#phonelibs/snpe/aarch64",
- "#phonelibs/libyuv/lib",
+ "#third_party/snpe/aarch64",
+ "#third_party/libyuv/lib",
"/system/vendor/lib64"
]
cflags = ["-DQCOM", "-D_USING_LIBCXX", "-mcpu=cortex-a57"]
cxxflags = ["-DQCOM", "-D_USING_LIBCXX", "-mcpu=cortex-a57"]
- rpath = []
else:
cflags = []
cxxflags = []
@@ -118,7 +123,7 @@ else:
if arch == "Darwin":
yuv_dir = "mac" if real_arch != "arm64" else "mac_arm64"
libpath = [
- f"#phonelibs/libyuv/{yuv_dir}/lib",
+ f"#third_party/libyuv/{yuv_dir}/lib",
"/usr/local/lib",
"/opt/homebrew/lib",
"/usr/local/opt/openssl/lib",
@@ -134,24 +139,22 @@ else:
]
else:
libpath = [
- "#phonelibs/snpe/x86_64-linux-clang",
- "#phonelibs/libyuv/x64/lib",
- "#phonelibs/mapbox-gl-native-qt/x86_64",
+ "#third_party/acados/x86_64/lib",
+ "#third_party/snpe/x86_64-linux-clang",
+ "#third_party/libyuv/x64/lib",
+ "#third_party/mapbox-gl-native-qt/x86_64",
"#cereal",
"#selfdrive/common",
"/usr/lib",
"/usr/local/lib",
]
- rpath = [
- "phonelibs/snpe/x86_64-linux-clang",
- "cereal",
- "selfdrive/common"
+ rpath += [
+ Dir("#third_party/snpe/x86_64-linux-clang").abspath,
+ Dir("#cereal").abspath,
+ Dir("#selfdrive/common").abspath
]
- # allows shared libraries to work globally
- rpath = [os.path.join(os.getcwd(), x) for x in rpath]
-
if GetOption('asan'):
ccflags = ["-fsanitize=address", "-fno-omit-frame-pointer"]
ldflags = ["-fsanitize=address"]
@@ -164,15 +167,12 @@ else:
# no --as-needed on mac linker
if arch != "Darwin":
- ldflags += ["-Wl,--as-needed"]
+ ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"]
# Enable swaglog include in submodules
cflags += ["-DSWAGLOG"]
cxxflags += ["-DSWAGLOG"]
-# change pythonpath to this
-lenv["PYTHONPATH"] = Dir("#").path
-
env = Environment(
ENV=lenv,
CCFLAGS=[
@@ -191,22 +191,25 @@ env = Environment(
CPPPATH=cpppath + [
"#",
- "#phonelibs/catch2/include",
- "#phonelibs/bzip2",
- "#phonelibs/libyuv/include",
- "#phonelibs/openmax/include",
- "#phonelibs/json11",
- "#phonelibs/curl/include",
- "#phonelibs/libgralloc/include",
- "#phonelibs/android_frameworks_native/include",
- "#phonelibs/android_hardware_libhardware/include",
- "#phonelibs/android_system_core/include",
- "#phonelibs/linux/include",
- "#phonelibs/snpe/include",
- "#phonelibs/mapbox-gl-native-qt/include",
- "#phonelibs/nanovg",
- "#phonelibs/qrcode",
- "#phonelibs",
+ "#third_party/acados/include",
+ "#third_party/acados/include/blasfeo/include",
+ "#third_party/acados/include/hpipm/include",
+ "#third_party/catch2/include",
+ "#third_party/bzip2",
+ "#third_party/libyuv/include",
+ "#third_party/openmax/include",
+ "#third_party/json11",
+ "#third_party/curl/include",
+ "#third_party/libgralloc/include",
+ "#third_party/android_frameworks_native/include",
+ "#third_party/android_hardware_libhardware/include",
+ "#third_party/android_system_core/include",
+ "#third_party/linux/include",
+ "#third_party/snpe/include",
+ "#third_party/mapbox-gl-native-qt/include",
+ "#third_party/nanovg",
+ "#third_party/qrcode",
+ "#third_party",
"#cereal",
"#opendbc/can",
],
@@ -221,7 +224,7 @@ env = Environment(
CXXFLAGS=["-std=c++1z"] + cxxflags,
LIBPATH=libpath + [
"#cereal",
- "#phonelibs",
+ "#third_party",
"#opendbc/can",
"#selfdrive/boardd",
"#selfdrive/common",
@@ -346,7 +349,7 @@ if GetOption("clazy"):
qt_env['ENV']['CLAZY_IGNORE_DIRS'] = qt_dirs[0]
qt_env['ENV']['CLAZY_CHECKS'] = ','.join(checks)
-Export('env', 'qt_env', 'arch', 'real_arch', 'SHARED', 'USE_WEBCAM')
+Export('env', 'qt_env', 'arch', 'real_arch', 'SHARED', 'USE_WEBCAM', 'USE_FRAME_STREAM')
SConscript(['selfdrive/common/SConscript'])
Import('_common', '_gpucommon', '_gpu_libs')
@@ -400,7 +403,7 @@ SConscript(['cereal/SConscript'])
SConscript(['panda/board/SConscript'])
SConscript(['opendbc/can/SConscript'])
-SConscript(['phonelibs/SConscript'])
+SConscript(['third_party/SConscript'])
SConscript(['common/SConscript'])
SConscript(['common/kalman/SConscript'])
@@ -410,8 +413,7 @@ SConscript(['selfdrive/camerad/SConscript'])
SConscript(['selfdrive/modeld/SConscript'])
SConscript(['selfdrive/controls/lib/cluster/SConscript'])
-SConscript(['selfdrive/controls/lib/lateral_mpc/SConscript'])
-SConscript(['selfdrive/controls/lib/lead_mpc_lib/SConscript'])
+SConscript(['selfdrive/controls/lib/lateral_mpc_lib/SConscript'])
SConscript(['selfdrive/controls/lib/longitudinal_mpc_lib/SConscript'])
SConscript(['selfdrive/boardd/SConscript'])
diff --git a/cereal/SConscript b/cereal/SConscript
index 10f3ab7f5..df066dc51 100644
--- a/cereal/SConscript
+++ b/cereal/SConscript
@@ -9,16 +9,11 @@ messaging_dir = Dir('messaging')
# Build cereal
schema_files = ['log.capnp', 'car.capnp', 'legacy.capnp']
-env.Command(["gen/c/include/c++.capnp.h", "gen/c/include/java.capnp.h"], [], "mkdir -p " + gen_dir.path + "/c/include && touch $TARGETS")
+env.Command(["gen/c/include/c++.capnp.h"], [], "mkdir -p " + gen_dir.path + "/c/include && touch $TARGETS")
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
schema_files,
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
-if shutil.which('capnpc-java'):
- env.Command(['gen/java/Car.java', 'gen/java/Log.java'],
- schema_files,
- f"capnpc $SOURCES --src-prefix={cereal_dir.path} -o java:{gen_dir.path}/java/")
-
# TODO: remove non shared cereal and messaging
cereal_objects = env.SharedObject([f'gen/cpp/{s}.c++' for s in schema_files])
diff --git a/cereal/car.capnp b/cereal/car.capnp
index 686e0e2df..d78acb28e 100644
--- a/cereal/car.capnp
+++ b/cereal/car.capnp
@@ -1,10 +1,6 @@
using Cxx = import "./include/c++.capnp";
$Cxx.namespace("cereal");
-using Java = import "./include/java.capnp";
-$Java.package("ai.comma.openpilot.cereal");
-$Java.outerClassname("Car");
-
@0x8e2af1e708af8b8d;
# ******* events causing controls state machine transition *******
@@ -88,7 +84,6 @@ struct CarEvent @0x9b1657f34caf3ad3 {
startupNoCar @76;
startupNoControl @77;
startupMaster @78;
- startupFuzzyFingerprint @97;
startupNoFw @104;
fcw @79;
steerSaturated @80;
@@ -130,6 +125,7 @@ struct CarEvent @0x9b1657f34caf3ad3 {
neosUpdateRequiredDEPRECATED @88;
modelLagWarningDEPRECATED @93;
startupOneplusDEPRECATED @82;
+ startupFuzzyFingerprintDEPRECATED @97;
}
}
@@ -148,7 +144,7 @@ struct CarState {
wheelSpeeds @2 :WheelSpeeds;
# gas pedal, 0.0-1.0
- gas @3 :Float32; # this is user + computer
+ gas @3 :Float32; # this is user pedal only
gasPressed @4 :Bool; # this is user pedal only
# brake pedal, 0.0-1.0
@@ -379,14 +375,11 @@ struct CarParams {
enableDsu @5 :Bool; # driving support unit
enableApgs @6 :Bool; # advanced parking guidance system
enableBsm @56 :Bool; # blind spot monitoring
- hasStockCamera @57 :Bool; # factory LKAS/LDW camera is present
minEnableSpeed @7 :Float32;
minSteerSpeed @8 :Float32;
maxSteeringAngleDeg @54 :Float32;
- safetyModel @9 :SafetyModel;
- safetyModelPassive @42 :SafetyModel = silent;
- safetyParam @10 :Int16;
+ safetyConfigs @62 :List(SafetyConfig);
steerMaxBP @11 :List(Float32);
steerMaxV @12 :List(Float32);
@@ -419,9 +412,11 @@ struct CarParams {
steerLimitTimer @47 :Float32; # time before steerLimitAlert is issued
vEgoStopping @29 :Float32; # Speed at which the car goes into stopping state
+ vEgoStarting @59 :Float32; # Speed at which the car goes into starting state
directAccelControl @30 :Bool; # Does the car have direct accel control or just gas/brake
stoppingControl @31 :Bool; # Does the car allows full control even at lows speeds when stopping
startAccel @32 :Float32; # Required acceleraton to overcome creep braking
+ stopAccel @60 :Float32; # Required acceleraton to keep vehicle stationary
steerRateCost @33 :Float32; # Lateral MPC cost on steering rate
steerControlType @34 :SteerControlType;
radarOffCan @35 :Bool; # True when radar objects aren't visible on CAN
@@ -430,7 +425,8 @@ struct CarParams {
startingAccelRate @53 :Float32; # m/s^2/s while trying to start
steerActuatorDelay @36 :Float32; # Steering wheel actuator delay in seconds
- longitudinalActuatorDelay @58 :Float32; # Gas/Brake actuator delay in seconds
+ longitudinalActuatorDelayLowerBound @61 :Float32; # Gas/Brake actuator delay in seconds, lower bound
+ longitudinalActuatorDelayUpperBound @58 :Float32; # Gas/Brake actuator delay in seconds, upper bound
openpilotLongitudinalControl @37 :Bool; # is openpilot doing the longitudinal control?
carVin @38 :Text; # VIN number queried during fingerprinting
dashcamOnly @41: Bool;
@@ -442,6 +438,11 @@ struct CarParams {
fingerprintSource @49: FingerprintSource;
networkLocation @50 :NetworkLocation; # Where Panda/C2 is integrated into the car's CAN network
+ struct SafetyConfig {
+ safetyModel @0 :SafetyModel;
+ safetyParam @1 :Int16;
+ }
+
struct LateralParams {
torqueBP @0 :List(Int32);
torqueV @1 :List(Int32);
@@ -520,6 +521,7 @@ struct CarParams {
subaruLegacy @22; # pre-Global platform
hyundaiLegacy @23;
hyundaiCommunity @24;
+ stellantis @25;
}
enum SteerControlType {
@@ -579,4 +581,8 @@ struct CarParams {
enableCameraDEPRECATED @4 :Bool;
isPandaBlackDEPRECATED @39: Bool;
+ hasStockCameraDEPRECATED @57 :Bool;
+ safetyParamDEPRECATED @10 :Int16;
+ safetyModelDEPRECATED @9 :SafetyModel;
+ safetyModelPassiveDEPRECATED @42 :SafetyModel = silent;
}
diff --git a/cereal/include/java.capnp b/cereal/include/java.capnp
deleted file mode 100644
index cddf6eba3..000000000
--- a/cereal/include/java.capnp
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
-# Licensed under the MIT License:
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-@0xc5f1af96651f70ea;
-
-annotation package @0x9ee4c8f803b3b596 (file) : Text;
-# Name of the package, such as "org.example.foo", in which the generated code will reside.
-
-annotation outerClassname @0x9b066bb4881f7cd3 (file) : Text;
-# Name of the outer class that will wrap the generated code.
diff --git a/cereal/legacy.capnp b/cereal/legacy.capnp
index 0534dabc1..9a4891681 100644
--- a/cereal/legacy.capnp
+++ b/cereal/legacy.capnp
@@ -1,10 +1,6 @@
using Cxx = import "./include/c++.capnp";
$Cxx.namespace("cereal");
-using Java = import "./include/java.capnp";
-$Java.package("ai.comma.openpilot.cereal");
-$Java.outerClassname("Legacy");
-
@0x80ef1ec4889c2a63;
# legacy.capnp: a home for deprecated structs
diff --git a/cereal/log.capnp b/cereal/log.capnp
index e87c41fe0..8c6245ab5 100644
--- a/cereal/log.capnp
+++ b/cereal/log.capnp
@@ -1,10 +1,6 @@
using Cxx = import "./include/c++.capnp";
$Cxx.namespace("cereal");
-using Java = import "./include/java.capnp";
-$Java.package("ai.comma.openpilot.cereal");
-$Java.outerClassname("Log");
-
using Car = import "car.capnp";
using Legacy = import "legacy.capnp";
@@ -293,15 +289,11 @@ struct DeviceState @0xa4d8b5af2aa492eb {
networkType @22 :NetworkType;
networkInfo @31 :NetworkInfo;
networkStrength @24 :NetworkStrength;
- offroadPowerUsageUwh @23 :UInt32;
- carBatteryCapacityUwh @25 :UInt32;
+ lastAthenaPingTime @32 :UInt64;
- fanSpeedPercentDesired @10 :UInt16;
started @11 :Bool;
startedMonoTime @13 :UInt64;
- lastAthenaPingTime @32 :UInt64;
-
# system utilization
freeSpacePercent @7 :Float32;
memoryUsagePercent @19 :Int8;
@@ -313,14 +305,21 @@ struct DeviceState @0xa4d8b5af2aa492eb {
batteryCurrent @15 :Int32;
chargingError @17 :Bool;
chargingDisabled @18 :Bool;
+ offroadPowerUsageUwh @23 :UInt32;
+ carBatteryCapacityUwh @25 :UInt32;
# device thermals
cpuTempC @26 :List(Float32);
gpuTempC @27 :List(Float32);
memoryTempC @28 :Float32;
ambientTempC @30 :Float32;
+ nvmeTempC @35 :List(Float32);
+ modemTempC @36 :List(Float32);
thermalStatus @14 :ThermalStatus;
+ fanSpeedPercentDesired @10 :UInt16;
+ screenBrightnessPercent @37 :Int8;
+
enum ThermalStatus {
green @0;
yellow @1;
@@ -371,20 +370,14 @@ struct DeviceState @0xa4d8b5af2aa492eb {
}
struct PandaState @0xa7649e2575e4591e {
- # from can health
- voltage @0 :UInt32;
- current @1 :UInt32;
ignitionLine @2 :Bool;
controlsAllowed @3 :Bool;
gasInterceptorDetected @4 :Bool;
- hasGps @6 :Bool;
canSendErrs @7 :UInt32;
canFwdErrs @8 :UInt32;
canRxErrs @19 :UInt32;
gmlanSendErrs @9 :UInt32;
pandaType @10 :PandaType;
- fanSpeedRpm @11 :UInt16;
- usbPowerMode @12 :UsbPowerMode;
ignitionCan @13 :Bool;
safetyModel @14 :Car.CarParams.SafetyModel;
safetyParam @20 :Int16;
@@ -438,13 +431,6 @@ struct PandaState @0xa7649e2575e4591e {
redPanda @7;
}
- enum UsbPowerMode {
- none @0;
- client @1;
- cdp @2;
- dcp @3;
- }
-
enum HarnessStatus {
notConnected @0;
normal @1;
@@ -452,6 +438,26 @@ struct PandaState @0xa7649e2575e4591e {
}
startedSignalDetectedDEPRECATED @5 :Bool;
+ voltageDEPRECATED @0 :UInt32;
+ currentDEPRECATED @1 :UInt32;
+ hasGpsDEPRECATED @6 :Bool;
+ fanSpeedRpmDEPRECATED @11 :UInt16;
+ usbPowerModeDEPRECATED @12 :PeripheralState.UsbPowerMode;
+}
+
+struct PeripheralState {
+ pandaType @0 :PandaState.PandaType;
+ voltage @1 :UInt32;
+ current @2 :UInt32;
+ fanSpeedRpm @3 :UInt16;
+ usbPowerMode @4 :UsbPowerMode;
+
+ enum UsbPowerMode @0xa8883583b32c9877 {
+ none @0;
+ client @1;
+ cdp @2;
+ dcp @3;
+ }
}
struct RadarState @0x9a185389d6fdd05f {
@@ -859,7 +865,7 @@ struct LateralPlan @0xe1e9318e2ae8b51e {
desire @17 :Desire;
laneChangeState @18 :LaneChangeState;
laneChangeDirection @19 :LaneChangeDirection;
-
+ useLaneLines @29 :Bool;
# desired curvatures over next 2.5s in rad/m
psis @26 :List(Float32);
@@ -1248,6 +1254,7 @@ struct DriverState {
distractedEyes @20 :Float32;
eyesOnRoad @21 :Float32;
phoneUse @22 :Float32;
+ occludedProb @23 :Float32;
irPwrDEPRECATED @10 :Float32;
descriptorDEPRECATED @1 :List(Float32);
@@ -1295,6 +1302,10 @@ struct LiveParametersData {
yawRate @7 :Float32;
posenetSpeed @8 :Float32;
posenetValid @9 :Bool;
+ angleOffsetFastStd @10 :Float32;
+ angleOffsetAverageStd @11 :Float32;
+ stiffnessFactorStd @12 :Float32;
+ steerRatioStd @13 :Float32;
}
struct LiveMapDataDEPRECATED {
@@ -1344,6 +1355,7 @@ struct ManagerState {
name @0 :Text;
pid @1 :Int32;
running @2 :Bool;
+ shouldBeRunning @4 :Bool;
exitCode @3 :Int32;
}
}
@@ -1377,7 +1389,8 @@ struct Event {
can @5 :List(CanData);
controlsState @7 :ControlsState;
sensorEvents @11 :List(SensorEventData);
- pandaState @12 :PandaState;
+ pandaStates @81 :List(PandaState);
+ peripheralState @80 :PeripheralState;
radarState @13 :RadarState;
liveTracks @16 :List(LiveTracks);
sendcan @17 :List(CanData);
@@ -1457,5 +1470,6 @@ struct Event {
kalmanOdometryDEPRECATED @65 :Legacy.KalmanOdometry;
gpsLocationDEPRECATED @21 :GpsLocationData;
uiLayoutStateDEPRECATED @57 :Legacy.UiLayoutState;
+ pandaStateDEPRECATED @12 :PandaState;
}
}
diff --git a/cereal/services.py b/cereal/services.py
index 406d9d146..4cf10a344 100755
--- a/cereal/services.py
+++ b/cereal/services.py
@@ -28,14 +28,15 @@ services = {
"deviceState": (True, 2., 1),
"can": (True, 100.),
"controlsState": (True, 100., 10),
- "pandaState": (True, 2., 1),
+ "pandaStates": (True, 2., 1),
+ "peripheralState": (True, 2., 1),
"radarState": (True, 20., 5),
"roadEncodeIdx": (True, 20., 1),
"liveTracks": (True, 20.),
- "sendcan": (True, 100.),
+ "sendcan": (True, 100., 139),
"logMessage": (True, 0.),
"liveCalibration": (True, 4., 4),
- "androidLog": (True, 0., 1),
+ "androidLog": (True, 0.),
"carState": (True, 100., 10),
"carControl": (True, 100., 10),
"longitudinalPlan": (True, 20., 5),
diff --git a/cereal/visionipc/visionbuf_ion.cc b/cereal/visionipc/visionbuf_ion.cc
index 60f7c66e1..c367304e9 100644
--- a/cereal/visionipc/visionbuf_ion.cc
+++ b/cereal/visionipc/visionbuf_ion.cc
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -15,6 +16,16 @@
#include "visionbuf.h"
+// keep trying if x gets interrupted by a signal
+#define HANDLE_EINTR(x) \
+ ({ \
+ decltype(x) ret; \
+ int try_cnt = 0; \
+ do { \
+ ret = (x); \
+ } while (ret == -1 && errno == EINTR && try_cnt++ < 100); \
+ ret; \
+ })
// just hard-code these for convenience
// size_t device_page_size = 0;
@@ -47,12 +58,12 @@ void VisionBuf::allocate(size_t len) {
ion_alloc.heap_id_mask = 1 << ION_IOMMU_HEAP_ID;
ion_alloc.flags = ION_FLAG_CACHED;
- err = ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc);
+ err = HANDLE_EINTR(ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc));
assert(err == 0);
struct ion_fd_data ion_fd_data = {0};
ion_fd_data.handle = ion_alloc.handle;
- err = ioctl(ion_fd, ION_IOC_SHARE, &ion_fd_data);
+ err = HANDLE_EINTR(ioctl(ion_fd, ION_IOC_SHARE, &ion_fd_data));
assert(err == 0);
void *addr = mmap(NULL, ion_alloc.len,
@@ -78,7 +89,7 @@ void VisionBuf::import(){
// Get handle
struct ion_fd_data fd_data = {0};
fd_data.fd = this->fd;
- err = ioctl(ion_fd, ION_IOC_IMPORT, &fd_data);
+ err = HANDLE_EINTR(ioctl(ion_fd, ION_IOC_IMPORT, &fd_data));
assert(err == 0);
this->handle = fd_data.handle;
@@ -122,7 +133,7 @@ int VisionBuf::sync(int dir) {
ION_IOC_INV_CACHES : ION_IOC_CLEAN_CACHES;
custom_data.arg = (unsigned long)&flush_data;
- return ioctl(ion_fd, ION_IOC_CUSTOM, &custom_data);
+ return HANDLE_EINTR(ioctl(ion_fd, ION_IOC_CUSTOM, &custom_data));
}
int VisionBuf::free() {
@@ -140,5 +151,5 @@ int VisionBuf::free() {
if (err != 0) return err;
struct ion_handle_data handle_data = {.handle = this->handle};
- return ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+ return HANDLE_EINTR(ioctl(ion_fd, ION_IOC_FREE, &handle_data));
}
diff --git a/cereal/visionipc/visionipc.pxd b/cereal/visionipc/visionipc.pxd
index 5e2b3a3a1..5cb729f7e 100644
--- a/cereal/visionipc/visionipc.pxd
+++ b/cereal/visionipc/visionipc.pxd
@@ -36,3 +36,4 @@ cdef extern from "visionipc_client.h":
VisionIpcClient(string, VisionStreamType, bool, void*, void*)
VisionBuf * recv(VisionIpcBufExtra *, int)
bool connect(bool)
+ bool is_connected()
diff --git a/cereal/visionipc/visionipc_client.cc b/cereal/visionipc/visionipc_client.cc
index 69ae8b133..da406067a 100644
--- a/cereal/visionipc/visionipc_client.cc
+++ b/cereal/visionipc/visionipc_client.cc
@@ -72,6 +72,7 @@ bool VisionIpcClient::connect(bool blocking){
if (device_id) buffers[i].init_cl(device_id, ctx);
}
+ close(socket_fd);
connected = true;
return true;
}
diff --git a/cereal/visionipc/visionipc_client.h b/cereal/visionipc/visionipc_client.h
index 04b2db6b0..a6426ce92 100644
--- a/cereal/visionipc/visionipc_client.h
+++ b/cereal/visionipc/visionipc_client.h
@@ -29,4 +29,5 @@ public:
~VisionIpcClient();
VisionBuf * recv(VisionIpcBufExtra * extra=nullptr, const int timeout_ms=100);
bool connect(bool blocking=true);
+ bool is_connected() { return connected; }
};
diff --git a/cereal/visionipc/visionipc_pyx.pyx b/cereal/visionipc/visionipc_pyx.pyx
index d1eef64ec..c0ba4c3ee 100644
--- a/cereal/visionipc/visionipc_pyx.pyx
+++ b/cereal/visionipc/visionipc_pyx.pyx
@@ -88,3 +88,6 @@ cdef class VisionIpcClient:
def connect(self, bool blocking):
return self.client.connect(blocking)
+
+ def is_connected(self):
+ return self.client.is_connected()
diff --git a/common/params.py b/common/params.py
index d0a37cce1..2cfca3712 100644
--- a/common/params.py
+++ b/common/params.py
@@ -6,19 +6,14 @@ assert put_nonblocking
if __name__ == "__main__":
import sys
- from common.params_pyx import keys # pylint: disable=no-name-in-module, import-error
params = Params()
+ key = sys.argv[1]
+ assert params.check_key(key), f"unknown param: {key}"
+
if len(sys.argv) == 3:
- name = sys.argv[1]
val = sys.argv[2]
- assert name.encode("utf-8") in keys.keys(), f"unknown param: {name}"
- print(f"SET: {name} = {val}")
- params.put(name, val)
+ print(f"SET: {key} = {val}")
+ params.put(key, val)
elif len(sys.argv) == 2:
- name = sys.argv[1]
- assert name.encode("utf-8") in keys.keys(), f"unknown param: {name}"
- print(f"GET: {name} = {params.get(name)}")
- else:
- for k in keys.keys():
- print(f"GET: {k} = {params.get(k)}")
+ print(f"GET: {key} = {params.get(key)}")
diff --git a/common/transformations/camera.py b/common/transformations/camera.py
index 29ce3277d..d71f865ca 100644
--- a/common/transformations/camera.py
+++ b/common/transformations/camera.py
@@ -131,7 +131,7 @@ def denormalize(img_pts, intrinsics=fcam_intrinsics, width=W, height=H):
img_pts = np.array(img_pts)
input_shape = img_pts.shape
img_pts = np.atleast_2d(img_pts)
- img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0], 1))))
+ img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0], 1), dtype=img_pts.dtype)))
img_pts_denormalized = img_pts.dot(intrinsics.T)
img_pts_denormalized[img_pts_denormalized[:, 0] > width] = np.nan
img_pts_denormalized[img_pts_denormalized[:, 0] < 0] = np.nan
diff --git a/docs/CARS.md b/docs/CARS.md
new file mode 100644
index 000000000..9766a7264
--- /dev/null
+++ b/docs/CARS.md
@@ -0,0 +1,176 @@
+Supported Cars
+------
+
+| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
+| ----------| ------------------------------| ------------------| -----------------| -------------------| ------------------|
+| Acura | ILX 2016-19 | AcuraWatch Plus | openpilot | 25mph1 | 25mph |
+| Acura | RDX 2016-18 | AcuraWatch Plus | openpilot | 25mph1 | 12mph |
+| Acura | RDX 2019-21 | All | Stock | 0mph | 3mph |
+| Honda | Accord 2018-20 | All | Stock | 0mph | 3mph |
+| Honda | Accord Hybrid 2018-20 | All | Stock | 0mph | 3mph |
+| Honda | Civic Hatchback 2017-21 | Honda Sensing | Stock | 0mph | 12mph |
+| Honda | Civic Coupe 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
+| Honda | Civic Coupe 2019-20 | All | Stock | 0mph | 2mph2 |
+| Honda | Civic Sedan 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
+| Honda | Civic Sedan 2019-20 | All | Stock | 0mph | 2mph2 |
+| Honda | CR-V 2015-16 | Touring | openpilot | 25mph1 | 12mph |
+| Honda | CR-V 2017-21 | Honda Sensing | Stock | 0mph | 12mph |
+| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Stock | 0mph | 12mph |
+| Honda | e 2020 | All | Stock | 0mph | 3mph |
+| Honda | Fit 2018-19 | Honda Sensing | openpilot | 25mph1 | 12mph |
+| Honda | Freed 2020 | Honda Sensing | openpilot | 25mph1 | 12mph |
+| Honda | HR-V 2019-20 | Honda Sensing | openpilot | 25mph1 | 12mph |
+| Honda | Insight 2019-21 | All | Stock | 0mph | 3mph |
+| Honda | Inspire 2018 | All | Stock | 0mph | 3mph |
+| Honda | Odyssey 2018-20 | Honda Sensing | openpilot | 25mph1 | 0mph |
+| Honda | Passport 2019 | All | openpilot | 25mph1 | 12mph |
+| Honda | Pilot 2016-21 | Honda Sensing | openpilot | 25mph1 | 12mph |
+| Honda | Ridgeline 2017-21 | Honda Sensing | openpilot | 25mph1 | 12mph |
+| Hyundai | Palisade 2020-21 | All | Stock | 0mph | 0mph |
+| Hyundai | Sonata 2020-21 | All | Stock | 0mph | 0mph |
+| Lexus | CT Hybrid 2017-18 | LSS | Stock3| 0mph | 0mph |
+| Lexus | ES 2019-21 | All | openpilot | 0mph | 0mph |
+| Lexus | ES Hybrid 2017-18 | LSS | Stock3| 0mph | 0mph |
+| Lexus | ES Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
+| Lexus | IS 2017-2019 | All | Stock | 22mph | 0mph |
+| Lexus | NX 2018 | All | Stock3| 0mph | 0mph |
+| Lexus | NX 2020 | All | openpilot | 0mph | 0mph |
+| Lexus | NX Hybrid 2018-19 | All | Stock3| 0mph | 0mph |
+| Lexus | RX 2016-18 | All | Stock3| 0mph | 0mph |
+| Lexus | RX 2020-21 | All | openpilot | 0mph | 0mph |
+| Lexus | RX Hybrid 2016-19 | All | Stock3| 0mph | 0mph |
+| Lexus | RX Hybrid 2020-21 | All | openpilot | 0mph | 0mph |
+| Lexus | UX Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
+| Toyota | Alphard 2020 | All | openpilot | 0mph | 0mph |
+| Toyota | Avalon 2016-21 | TSS-P | Stock3| 20mph1 | 0mph |
+| Toyota | Avalon Hybrid 2019-21 | TSS-P | Stock3| 20mph1 | 0mph |
+| Toyota | Camry 2018-20 | All | Stock | 0mph4 | 0mph |
+| Toyota | Camry 2021 | All | openpilot | 0mph4 | 0mph |
+| Toyota | Camry Hybrid 2018-20 | All | Stock | 0mph4 | 0mph |
+| Toyota | Camry Hybrid 2021-22 | All | openpilot | 0mph | 0mph |
+| Toyota | C-HR 2017-20 | All | Stock | 0mph | 0mph |
+| Toyota | C-HR Hybrid 2017-19 | All | Stock | 0mph | 0mph |
+| Toyota | Corolla 2017-19 | All | Stock3| 20mph1 | 0mph |
+| Toyota | Corolla 2020-22 | All | openpilot | 0mph | 0mph |
+| Toyota | Corolla Hatchback 2019-22 | All | openpilot | 0mph | 0mph |
+| Toyota | Corolla Hybrid 2020-22 | All | openpilot | 0mph | 0mph |
+| Toyota | Highlander 2017-19 | All | Stock3| 0mph | 0mph |
+| Toyota | Highlander 2020-21 | All | openpilot | 0mph | 0mph |
+| Toyota | Highlander Hybrid 2017-19 | All | Stock3| 0mph | 0mph |
+| Toyota | Highlander Hybrid 2020-21 | All | openpilot | 0mph | 0mph |
+| Toyota | Mirai 2021 | All | openpilot | 0mph | 0mph |
+| Toyota | Prius 2016-20 | TSS-P | Stock3| 0mph | 0mph |
+| Toyota | Prius 2021 | All | openpilot | 0mph | 0mph |
+| Toyota | Prius Prime 2017-20 | All | Stock3| 0mph | 0mph |
+| Toyota | Prius Prime 2021 | All | openpilot | 0mph | 0mph |
+| Toyota | Rav4 2016-18 | TSS-P | Stock3| 20mph1 | 0mph |
+| Toyota | Rav4 2019-21 | All | openpilot | 0mph | 0mph |
+| Toyota | Rav4 Hybrid 2016-18 | TSS-P | Stock3| 0mph | 0mph |
+| Toyota | Rav4 Hybrid 2019-21 | All | openpilot | 0mph | 0mph |
+| Toyota | Sienna 2018-20 | All | Stock3| 0mph | 0mph |
+
+1[Comma Pedal](https://github.com/commaai/openpilot/wiki/comma-pedal) is used to provide stop-and-go capability to some of the openpilot-supported cars that don't currently support stop-and-go. ***NOTE: The Comma Pedal is not officially supported by [comma](https://comma.ai).***
+22019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph.
+3When disconnecting the Driver Support Unit (DSU), openpilot ACC will replace stock ACC. ***NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).***
+428mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control.
+
+Community Maintained Cars and Features
+------
+
+| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
+| ----------| ------------------------------| ------------------| -----------------| -------------------| -------------|
+| Audi | A3 2014-19 | ACC + Lane Assist | Stock | 0mph | 0mph |
+| Audi | A3 Sportback e-tron 2017-18 | ACC + Lane Assist | Stock | 0mph | 0mph |
+| Audi | Q2 2018 | ACC + Lane Assist | Stock | 0mph | 0mph |
+| Audi | S3 2015 | ACC + Lane Assist | Stock | 0mph | 0mph |
+| Buick | Regal 20181 | Adaptive Cruise | openpilot | 0mph | 7mph |
+| Cadillac | ATS 20181 | Adaptive Cruise | openpilot | 0mph | 7mph |
+| Chevrolet | Malibu 20171 | Adaptive Cruise | openpilot | 0mph | 7mph |
+| Chevrolet | Volt 2017-181 | Adaptive Cruise | openpilot | 0mph | 7mph |
+| Chrysler | Pacifica 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
+| Chrysler | Pacifica 2020 | Adaptive Cruise | Stock | 0mph | 39mph |
+| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
+| Chrysler | Pacifica Hybrid 2019-21 | Adaptive Cruise | Stock | 0mph | 39mph |
+| Genesis | G70 2018 | All | Stock | 0mph | 0mph |
+| Genesis | G80 2018 | All | Stock | 0mph | 0mph |
+| Genesis | G90 2018 | All | Stock | 0mph | 0mph |
+| GMC | Acadia 20181 | Adaptive Cruise | openpilot | 0mph | 7mph |
+| Holden | Astra 20171 | Adaptive Cruise | openpilot | 0mph | 7mph |
+| Hyundai | Elantra 2017-19 | SCC + LKAS | Stock | 19mph | 34mph |
+| Hyundai | Elantra 2021 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Elantra Hybrid 2021 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Genesis 2015-16 | SCC + LKAS | Stock | 19mph | 37mph |
+| Hyundai | Ioniq Electric 2019 | SCC + LKAS | Stock | 0mph | 32mph |
+| Hyundai | Ioniq Electric 2020 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Ioniq Hybrid 2017-19 | SCC + LKAS | Stock | 0mph | 32mph |
+| Hyundai | Ioniq Hybrid 2020-22 | SCC + LFA | Stock | 0mph | 0mph |
+| Hyundai | Ioniq PHEV 2020-21 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Kona 2020 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Kona EV 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Kona Hybrid 2020 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Santa Fe 2019-20 | All | Stock | 0mph | 0mph |
+| Hyundai | Santa Fe 2021-22 | All | Stock | 0mph | 0mph |
+| Hyundai | Sonata 2018-2019 | SCC + LKAS | Stock | 0mph | 0mph |
+| Hyundai | Sonata Hybrid 2021-22 | All | Stock | 0mph | 0mph |
+| Hyundai | Veloster 2019-20 | SCC + LKAS | Stock | 5mph | 0mph |
+| Jeep | Grand Cherokee 2016-18 | Adaptive Cruise | Stock | 0mph | 9mph |
+| Jeep | Grand Cherokee 2019-20 | Adaptive Cruise | Stock | 0mph | 39mph |
+| Kia | Ceed 2019 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Forte 2018-21 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | K5 2021 | SCC + LFA | Stock | 0mph | 0mph |
+| Kia | Niro EV 2019-21 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Niro Hybrid 2021 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Niro PHEV 2019 | SCC + LKAS | Stock | 10mph | 32mph |
+| Kia | Optima 2017 | SCC + LKAS | Stock | 0mph | 32mph |
+| Kia | Optima 2019 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Seltos 2021 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Sorento 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Stinger 2018 | SCC + LKAS | Stock | 0mph | 0mph |
+| Kia | Telluride 2020 | SCC + LKAS | Stock | 0mph | 0mph |
+| Nissan | Altima 2019-20 | ProPILOT | Stock | 0mph | 0mph |
+| Nissan | Leaf 2018-22 | ProPILOT | Stock | 0mph | 0mph |
+| Nissan | Rogue 2018-20 | ProPILOT | Stock | 0mph | 0mph |
+| Nissan | X-Trail 2017 | ProPILOT | Stock | 0mph | 0mph |
+| SEAT | Ateca 2018 | Driver Assistance | Stock | 0mph | 0mph |
+| SEAT | Leon 2014-2020 | Driver Assistance | Stock | 0mph | 0mph |
+| Škoda | Kamiq 20212 | Driver Assistance | Stock | 0mph | 0mph |
+| Škoda | Karoq 2019 | Driver Assistance | Stock | 0mph | 0mph |
+| Škoda | Kodiaq 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
+| Škoda | Octavia 2015, 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
+| Škoda | Octavia RS 2016 | Driver Assistance | Stock | 0mph | 0mph |
+| Škoda | Scala 2020 | Driver Assistance | Stock | 0mph | 0mph |
+| Škoda | Superb 2015-18 | Driver Assistance | Stock | 0mph | 0mph |
+| Subaru | Ascent 2019 | EyeSight | Stock | 0mph | 0mph |
+| Subaru | Crosstrek 2018-19 | EyeSight | Stock | 0mph | 0mph |
+| Subaru | Forester 2019-21 | EyeSight | Stock | 0mph | 0mph |
+| Subaru | Impreza 2017-19 | EyeSight | Stock | 0mph | 0mph |
+| Volkswagen| Arteon 20214 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Atlas 2018-19 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| California 20214 | Driver Assistance | Stock | 0mph | 32mph |
+| Volkswagen| e-Golf 2014, 2019-20 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Golf 2015-20 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Golf Alltrack 2017-18 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Golf GTE 2016 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Golf GTI 2018-20 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Golf R 2016-19 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Golf SportsVan 2016 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Golf SportWagen 2015 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Jetta 2018-20 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Jetta GLI 2021 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Passat 2016-183 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| T-Cross 20214 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Taos 20224 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Tiguan 2020 | Driver Assistance | Stock | 0mph | 0mph |
+| Volkswagen| Touran 2017 | Driver Assistance | Stock | 0mph | 0mph |
+
+1Requires an [OBD-II car harness](https://comma.ai/shop/products/comma-car-harness) and [community built ASCM harness](https://github.com/commaai/openpilot/wiki/GM#hardware). ***NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).***
+2Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform.
+3Not including the USA/China market Passat, which is based on the (currently) unsupported PQ35/NMS platform.
+4Model-years 2021 and beyond may have a new camera harness design, which isn't yet available from the comma store. Before ordering,
+remove the Lane Assist camera cover and check to see if the connector is black (older design) or light brown (newer design). For the newer design,
+in the interim, choose "VW J533 Development" from the vehicle drop-down for a harness that integrates at the CAN gateway inside the dashboard.
+Community Maintained Cars and Features are not verified by comma to meet our [safety model](SAFETY.md). Be extra cautious using them. They are only available after enabling the toggle in `Settings->Developer->Enable Community Features`.
+
+To promote a car from community maintained, it must meet a few requirements. We must own one from the brand, we must sell the harness for it, has full ISO26262 in both panda and openpilot, there must be a path forward for longitudinal control, it must have AEB still enabled, and it must support fingerprinting 2.0
+
+Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md
similarity index 96%
rename from CONTRIBUTING.md
rename to docs/CONTRIBUTING.md
index bcf05016c..8dcdeee50 100644
--- a/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -6,6 +6,7 @@ Most open source development activity is coordinated through our [GitHub Discuss
## Getting Started
+ * Setup your [development environment](../tools/)
* Join our [Discord](https://discord.comma.ai)
* Make sure you have a [GitHub account](https://github.com/signup/free)
* Fork [our repositories](https://github.com/commaai) on GitHub
@@ -20,7 +21,7 @@ All PRs and commits are automatically checked by GitHub Actions. Check out `.git
Code is automatically checked for style by GitHub Actions as part of the automated tests. You can also run these tests yourself by running `pre-commit run --all`.
-## Car Ports (openpilot)
+## Car Ports
We've released a [Model Port guide](https://blog.comma.ai/openpilot-port-guide-for-toyota-models/) for porting to Toyota/Lexus models.
diff --git a/docs/INTEGRATION.md b/docs/INTEGRATION.md
new file mode 100644
index 000000000..a6b8194aa
--- /dev/null
+++ b/docs/INTEGRATION.md
@@ -0,0 +1,73 @@
+Integration with Stock Features
+------
+
+In all supported cars:
+* Stock Lane Keep Assist (LKA) and stock ALC are replaced by openpilot ALC, which only functions when openpilot is engaged by the user.
+* Stock LDW is replaced by openpilot LDW.
+
+Additionally, on specific supported cars (see ACC column in [supported cars](CARS.md)):
+* Stock ACC is replaced by openpilot ACC.
+* openpilot FCW operates in addition to stock FCW.
+
+openpilot should preserve all other vehicle's stock features, including, but are not limited to: FCW, Automatic Emergency Braking (AEB), auto high-beam, blind spot warning, and side collision warning.
+
+Limitations of openpilot ALC and LDW
+------
+
+openpilot ALC and openpilot LDW do not automatically drive the vehicle or reduce the amount of attention that must be paid to operate your vehicle. The driver must always keep control of the steering wheel and be ready to correct the openpilot ALC action at all times.
+
+While changing lanes, openpilot is not capable of looking next to you or checking your blind spot. Only nudge the wheel to initiate a lane change after you have confirmed it's safe to do so.
+
+Many factors can impact the performance of openpilot ALC and openpilot LDW, causing them to be unable to function as intended. These include, but are not limited to:
+
+* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation.
+* The road facing camera is obstructed, covered or damaged by mud, ice, snow, etc.
+* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle.
+* The device is mounted incorrectly.
+* When in sharp curves, like on-off ramps, intersections etc...; openpilot is designed to be limited in the amount of steering torque it can produce.
+* In the presence of restricted lanes or construction zones.
+* When driving on highly banked roads or in presence of strong cross-wind.
+* Extremely hot or cold temperatures.
+* Bright light (due to oncoming headlights, direct sunlight, etc.).
+* Driving on hills, narrow, or winding roads.
+
+The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times.
+
+Limitations of openpilot ACC and FCW
+------
+
+openpilot ACC and openpilot FCW are not systems that allow careless or inattentive driving. It is still necessary for the driver to pay close attention to the vehicle’s surroundings and to be ready to re-take control of the gas and the brake at all times.
+
+Many factors can impact the performance of openpilot ACC and openpilot FCW, causing them to be unable to function as intended. These include, but are not limited to:
+
+* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation.
+* The road facing camera or radar are obstructed, covered, or damaged by mud, ice, snow, etc.
+* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle.
+* The device is mounted incorrectly.
+* Approaching a toll booth, a bridge or a large metal plate.
+* When driving on roads with pedestrians, cyclists, etc...
+* In presence of traffic signs or stop lights, which are not detected by openpilot at this time.
+* When the posted speed limit is below the user selected set speed. openpilot does not detect speed limits at this time.
+* In presence of vehicles in the same lane that are not moving.
+* When abrupt braking maneuvers are required. openpilot is designed to be limited in the amount of deceleration and acceleration that it can produce.
+* When surrounding vehicles perform close cut-ins from neighbor lanes.
+* Driving on hills, narrow, or winding roads.
+* Extremely hot or cold temperatures.
+* Bright light (due to oncoming headlights, direct sunlight, etc.).
+* Interference from other equipment that generates radar waves.
+
+The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times.
+
+Limitations of openpilot DM
+------
+
+openpilot DM should not be considered an exact measurement of the alertness of the driver.
+
+Many factors can impact the performance of openpilot DM, causing it to be unable to function as intended. These include, but are not limited to:
+
+* Low light conditions, such as driving at night or in dark tunnels.
+* Bright light (due to oncoming headlights, direct sunlight, etc.).
+* The driver's face is partially or completely outside field of view of the driver facing camera.
+* The driver facing camera is obstructed, covered, or damaged.
+
+The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. A driver should not rely on openpilot DM to assess their level of attention.
diff --git a/SAFETY.md b/docs/SAFETY.md
similarity index 100%
rename from SAFETY.md
rename to docs/SAFETY.md
diff --git a/installer/updater/Makefile b/installer/updater/Makefile
deleted file mode 100644
index 54bd7c9df..000000000
--- a/installer/updater/Makefile
+++ /dev/null
@@ -1,99 +0,0 @@
-CC = clang
-CXX = clang++
-
-PHONELIBS = ../../phonelibs
-
-WARN_FLAGS = -Werror=implicit-function-declaration \
- -Werror=incompatible-pointer-types \
- -Werror=int-conversion \
- -Werror=return-type \
- -Werror=format-extra-args
-
-CFLAGS = -std=gnu11 -g -fPIC -O2 $(WARN_FLAGS)
-CXXFLAGS = -std=c++1z -g -fPIC -O2 $(WARN_FLAGS)
-
-CURL_FLAGS = -I$(PHONELIBS)/curl/include
-CURL_LIBS = $(PHONELIBS)/curl/lib/libcurl.a \
- $(PHONELIBS)/zlib/lib/libz.a
-
-BORINGSSL_FLAGS = -I$(PHONELIBS)/boringssl/include
-BORINGSSL_LIBS = $(PHONELIBS)/boringssl/lib/libssl_static.a \
- $(PHONELIBS)/boringssl/lib/libcrypto_static.a \
-
-NANOVG_FLAGS = -I$(PHONELIBS)/nanovg
-
-JSON11_FLAGS = -I$(PHONELIBS)/json11
-
-OPENGL_LIBS = -lGLESv3
-
-FRAMEBUFFER_LIBS = -lutils -lgui -lEGL
-
-.PHONY: all
-all: updater
-
-OBJS = opensans_regular.ttf.o \
- opensans_semibold.ttf.o \
- opensans_bold.ttf.o \
- ../../selfdrive/common/util.o \
- ../../selfdrive/common/touch.o \
- ../../selfdrive/common/framebuffer.o \
- $(PHONELIBS)/json11/json11.o \
- $(PHONELIBS)/nanovg/nanovg.o
-
-DEPS := $(OBJS:.o=.d)
-
-updater: updater.o $(OBJS)
- @echo "[ LINK ] $@"
- $(CXX) $(CPPFLAGS) -fPIC -o 'updater' $^ \
- $(FRAMEBUFFER_LIBS) \
- $(CURL_LIBS) \
- $(BORINGSSL_LIBS) \
- -L/system/vendor/lib64 \
- $(OPENGL_LIBS) \
- -lcutils -lm -llog
- strip updater
-
-opensans_regular.ttf.o: ../../selfdrive/assets/fonts/opensans_regular.ttf
- @echo "[ bin2o ] $@"
- cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
-
-opensans_bold.ttf.o: ../../selfdrive/assets/fonts/opensans_bold.ttf
- @echo "[ bin2o ] $@"
- cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
-
-opensans_semibold.ttf.o: ../../selfdrive/assets/fonts/opensans_semibold.ttf
- @echo "[ bin2o ] $@"
- cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
-
-%.o: %.c
- mkdir -p $(@D)
- @echo "[ CC ] $@"
- $(CC) $(CPPFLAGS) $(CFLAGS) \
- -I../.. \
- -I$(PHONELIBS)/android_frameworks_native/include \
- -I$(PHONELIBS)/android_system_core/include \
- -I$(PHONELIBS)/android_hardware_libhardware/include \
- $(NANOVG_FLAGS) \
- -c -o '$@' '$<'
-
-%.o: %.cc
- mkdir -p $(@D)
- @echo "[ CXX ] $@"
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) \
- -I../../selfdrive \
- -I../../ \
- -I$(PHONELIBS)/android_frameworks_native/include \
- -I$(PHONELIBS)/android_system_core/include \
- -I$(PHONELIBS)/android_hardware_libhardware/include \
- $(NANOVG_FLAGS) \
- $(JSON11_FLAGS) \
- $(CURL_FLAGS) \
- $(BORINGSSL_FLAGS) \
- -c -o '$@' '$<'
-
-
-.PHONY: clean
-clean:
- rm -f $(OBJS) $(DEPS)
-
--include $(DEPS)
diff --git a/installer/updater/updater b/installer/updater/updater
index d833cb782..8bf40708a 100755
Binary files a/installer/updater/updater and b/installer/updater/updater differ
diff --git a/installer/updater/updater.cc b/installer/updater/updater.cc
deleted file mode 100644
index d1a694ef9..000000000
--- a/installer/updater/updater.cc
+++ /dev/null
@@ -1,803 +0,0 @@
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include "nanovg.h"
-#define NANOVG_GLES3_IMPLEMENTATION
-#include "json11.hpp"
-#include "nanovg_gl.h"
-#include "nanovg_gl_utils.h"
-
-#include "selfdrive/common/framebuffer.h"
-#include "selfdrive/common/touch.h"
-#include "selfdrive/common/util.h"
-
-#define USER_AGENT "NEOSUpdater-0.2"
-
-#define MANIFEST_URL_NEOS_STAGING "https://github.com/commaai/eon-neos/raw/master/update.staging.json"
-#define MANIFEST_URL_NEOS_LOCAL "http://192.168.5.1:8000/neosupdate/update.local.json"
-#define MANIFEST_URL_NEOS "https://github.com/commaai/eon-neos/raw/master/update.json"
-const char *manifest_url = MANIFEST_URL_NEOS;
-
-#define RECOVERY_DEV "/dev/block/bootdevice/by-name/recovery"
-#define RECOVERY_COMMAND "/cache/recovery/command"
-
-#define UPDATE_DIR "/data/neoupdate"
-
-extern const uint8_t bin_opensans_regular[] asm("_binary_opensans_regular_ttf_start");
-extern const uint8_t bin_opensans_regular_end[] asm("_binary_opensans_regular_ttf_end");
-extern const uint8_t bin_opensans_semibold[] asm("_binary_opensans_semibold_ttf_start");
-extern const uint8_t bin_opensans_semibold_end[] asm("_binary_opensans_semibold_ttf_end");
-extern const uint8_t bin_opensans_bold[] asm("_binary_opensans_bold_ttf_start");
-extern const uint8_t bin_opensans_bold_end[] asm("_binary_opensans_bold_ttf_end");
-
-namespace {
-
-std::string sha256_file(std::string fn, size_t limit=0) {
- SHA256_CTX ctx;
- SHA256_Init(&ctx);
-
- FILE *file = fopen(fn.c_str(), "rb");
- if (!file) return "";
-
- const size_t buf_size = 8192;
- std::unique_ptr buffer( new char[ buf_size ] );
-
- bool read_limit = (limit != 0);
- while (true) {
- size_t read_size = buf_size;
- if (read_limit) read_size = std::min(read_size, limit);
- size_t bytes_read = fread(buffer.get(), 1, read_size, file);
- if (!bytes_read) break;
-
- SHA256_Update(&ctx, buffer.get(), bytes_read);
-
- if (read_limit) {
- limit -= bytes_read;
- if (limit == 0) break;
- }
- }
-
- uint8_t hash[SHA256_DIGEST_LENGTH];
- SHA256_Final(hash, &ctx);
-
- fclose(file);
-
- return util::tohex(hash, sizeof(hash));
-}
-
-size_t download_string_write(void *ptr, size_t size, size_t nmeb, void *up) {
- size_t sz = size * nmeb;
- ((std::string*)up)->append((char*)ptr, sz);
- return sz;
-}
-
-std::string download_string(CURL *curl, std::string url) {
- std::string os;
-
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 0);
- curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
- curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
- curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 0);
-
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
-
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_string_write);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &os);
- CURLcode res = curl_easy_perform(curl);
- if (res != CURLE_OK) {
- return "";
- }
-
- return os;
-}
-
-size_t download_file_write(void *ptr, size_t size, size_t nmeb, void *up) {
- return fwrite(ptr, size, nmeb, (FILE*)up);
-}
-
-int battery_capacity() {
- std::string bat_cap_s = util::read_file("/sys/class/power_supply/battery/capacity");
- return atoi(bat_cap_s.c_str());
-}
-
-int battery_current() {
- std::string current_now_s = util::read_file("/sys/class/power_supply/battery/current_now");
- return atoi(current_now_s.c_str());
-}
-
-bool check_battery() {
- int bat_cap = battery_capacity();
- int current_now = battery_current();
- return bat_cap > 35 || (current_now < 0 && bat_cap > 10);
-}
-
-bool check_space() {
- struct statvfs stat;
- if (statvfs("/data/", &stat) != 0) {
- return false;
- }
- size_t space = stat.f_bsize * stat.f_bavail;
- return space > 2000000000ULL; // 2GB
-}
-
-static void start_settings_activity(const char* name) {
- char launch_cmd[1024];
- snprintf(launch_cmd, sizeof(launch_cmd),
- "am start -W --ez :settings:show_fragment_as_subsetting true -n 'com.android.settings/.%s'", name);
- system(launch_cmd);
-}
-
-bool is_settings_active() {
- FILE *fp;
- char sys_output[4096];
-
- fp = popen("/bin/dumpsys window windows", "r");
- if (fp == NULL) {
- return false;
- }
-
- bool active = false;
- while (fgets(sys_output, sizeof(sys_output), fp) != NULL) {
- if (strstr(sys_output, "mCurrentFocus=null") != NULL) {
- break;
- }
-
- if (strstr(sys_output, "mCurrentFocus=Window") != NULL) {
- active = true;
- break;
- }
- }
-
- pclose(fp);
-
- return active;
-}
-
-struct Updater {
- bool do_exit = false;
-
- TouchState touch;
-
- int fb_w, fb_h;
-
- std::unique_ptr fb;
- NVGcontext *vg = NULL;
- int font_regular;
- int font_semibold;
- int font_bold;
-
- std::thread update_thread_handle;
-
- std::mutex lock;
-
- enum UpdateState {
- CONFIRMATION,
- LOW_BATTERY,
- RUNNING,
- ERROR,
- };
- UpdateState state;
-
- std::string progress_text;
- float progress_frac;
-
- std::string error_text;
-
- std::string low_battery_text;
- std::string low_battery_title;
- std::string low_battery_context;
- std::string battery_cap_text;
- int min_battery_cap = 35;
-
- // button
- int b_x, b_w, b_y, b_h;
- int balt_x;
-
- // download stage writes these for the installation stage
- int recovery_len;
- std::string recovery_hash;
- std::string recovery_fn;
- std::string ota_fn;
-
- CURL *curl = NULL;
-
- void ui_init() {
- touch_init(&touch);
-
- fb = std::make_unique("updater", 0x00001000, false, &fb_w, &fb_h);
-
- fb->set_power(HWC_POWER_MODE_NORMAL);
-
- vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
- assert(vg);
-
- font_regular = nvgCreateFontMem(vg, "opensans_regular", (unsigned char*)bin_opensans_regular, (bin_opensans_regular_end - bin_opensans_regular), 0);
- assert(font_regular >= 0);
-
- font_semibold = nvgCreateFontMem(vg, "opensans_semibold", (unsigned char*)bin_opensans_semibold, (bin_opensans_semibold_end - bin_opensans_semibold), 0);
- assert(font_semibold >= 0);
-
- font_bold = nvgCreateFontMem(vg, "opensans_bold", (unsigned char*)bin_opensans_bold, (bin_opensans_bold_end - bin_opensans_bold), 0);
- assert(font_bold >= 0);
-
- b_w = 640;
- balt_x = 200;
- b_x = fb_w-b_w-200;
- b_y = 720;
- b_h = 220;
-
- if (download_stage(true)) {
- state = RUNNING;
- update_thread_handle = std::thread(&Updater::run_stages, this);
- } else {
- state = CONFIRMATION;
- }
- }
-
- int download_file_xferinfo(curl_off_t dltotal, curl_off_t dlno,
- curl_off_t ultotal, curl_off_t ulnow) {
- {
- std::lock_guard guard(lock);
- if (dltotal != 0) {
- progress_frac = (float) dlno / dltotal;
- }
- }
- // printf("info: %ld %ld %f\n", dltotal, dlno, progress_frac);
- return 0;
- }
-
- bool download_file(std::string url, std::string out_fn) {
- FILE *of = fopen(out_fn.c_str(), "ab");
- assert(of);
-
- CURLcode res;
- long last_resume_from = 0;
-
- fseek(of, 0, SEEK_END);
-
- int tries = 4;
-
- bool ret = false;
-
- while (true) {
- long resume_from = ftell(of);
-
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 0);
- curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
- curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
- curl_easy_setopt(curl, CURLOPT_RESUME_FROM, resume_from);
-
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_file_write);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, of);
-
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
-
- curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
- curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &Updater::download_file_xferinfo);
-
- CURLcode res = curl_easy_perform(curl);
-
- long response_code = 0;
- curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
-
- // double content_length = 0.0;
- // curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length);
-
- printf("download %s res %d, code %ld, resume from %ld\n", url.c_str(), res, response_code, resume_from);
- if (res == CURLE_OK) {
- ret = true;
- break;
- } else if (res == CURLE_HTTP_RETURNED_ERROR && response_code == 416) {
- // failed because the file is already complete?
- ret = true;
- break;
- } else if (resume_from == last_resume_from) {
- // failed and dind't make make forward progress. only retry a couple times
- tries--;
- if (tries <= 0) {
- break;
- }
- }
- last_resume_from = resume_from;
- }
- // printf("res %d\n", res);
-
- // printf("- %ld %f\n", response_code, content_length);
-
- fclose(of);
-
- return ret;
- }
-
- void set_progress(std::string text) {
- std::lock_guard guard(lock);
- progress_text = text;
- }
-
- void set_error(std::string text) {
- std::lock_guard guard(lock);
- error_text = text;
- state = ERROR;
- }
-
- void set_battery_low() {
- std::lock_guard guard(lock);
- state = LOW_BATTERY;
- }
-
- void set_running() {
- std::lock_guard guard(lock);
- state = RUNNING;
- }
-
- std::string download(std::string url, std::string hash, std::string name, bool dry_run) {
- std::string out_fn = UPDATE_DIR "/" + util::base_name(url);
-
- std::string fn_hash = sha256_file(out_fn);
- if (dry_run) {
- return (hash.compare(fn_hash) != 0) ? "" : out_fn;
- }
-
- // start or resume downloading if hash doesn't match
- if (hash.compare(fn_hash) != 0) {
- set_progress("Downloading " + name + "...");
- bool r = download_file(url, out_fn);
- if (!r) {
- set_error("failed to download " + name);
- unlink(out_fn.c_str());
- return "";
- }
- fn_hash = sha256_file(out_fn);
- }
-
- set_progress("Verifying " + name + "...");
- printf("got %s hash: %s\n", name.c_str(), hash.c_str());
- if (fn_hash != hash) {
- set_error(name + " was corrupt");
- unlink(out_fn.c_str());
- return "";
- }
- return out_fn;
- }
-
- bool download_stage(bool dry_run = false) {
- curl = curl_easy_init();
- assert(curl);
-
- // ** quick checks before download **
-
- if (!check_space()) {
- if (!dry_run) set_error("2GB of free space required to update");
- return false;
- }
-
- mkdir(UPDATE_DIR, 0777);
-
- set_progress("Finding latest version...");
- std::string manifest_s = download_string(curl, manifest_url);
- printf("manifest: %s\n", manifest_s.c_str());
-
- std::string err;
- auto manifest = json11::Json::parse(manifest_s, err);
- if (manifest.is_null() || !err.empty()) {
- set_error("failed to load update manifest");
- return false;
- }
-
- std::string ota_url = manifest["ota_url"].string_value();
- std::string ota_hash = manifest["ota_hash"].string_value();
-
- std::string recovery_url = manifest["recovery_url"].string_value();
- recovery_hash = manifest["recovery_hash"].string_value();
- recovery_len = manifest["recovery_len"].int_value();
-
- // std::string installer_url = manifest["installer_url"].string_value();
- // std::string installer_hash = manifest["installer_hash"].string_value();
-
- if (ota_url.empty() || ota_hash.empty()) {
- set_error("invalid update manifest");
- return false;
- }
-
- // std::string installer_fn = download(installer_url, installer_hash, "installer");
- // if (installer_fn.empty()) {
- // //error'd
- // return;
- // }
-
- // ** handle recovery download **
- if (recovery_url.empty() || recovery_hash.empty() || recovery_len == 0) {
- set_progress("Skipping recovery flash...");
- } else {
- // only download the recovery if it differs from what's flashed
- set_progress("Checking recovery...");
- std::string existing_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
- printf("existing recovery hash: %s\n", existing_recovery_hash.c_str());
-
- if (existing_recovery_hash != recovery_hash) {
- recovery_fn = download(recovery_url, recovery_hash, "recovery", dry_run);
- if (recovery_fn.empty()) {
- // error'd
- return false;
- }
- }
- }
-
- // ** handle ota download **
- ota_fn = download(ota_url, ota_hash, "update", dry_run);
- if (ota_fn.empty()) {
- //error'd
- return false;
- }
-
- // download sucessful
- return true;
- }
-
- // thread that handles downloading and installing the update
- void run_stages() {
- printf("run_stages start\n");
-
-
- // ** download update **
-
- if (!check_battery()) {
- set_battery_low();
- int battery_cap = battery_capacity();
- while(battery_cap < min_battery_cap) {
- battery_cap = battery_capacity();
- battery_cap_text = std::to_string(battery_cap);
- util::sleep_for(1000);
- }
- set_running();
- }
-
- bool sucess = download_stage();
- if (!sucess) {
- return;
- }
-
- // ** install update **
-
- if (!check_battery()) {
- set_battery_low();
- int battery_cap = battery_capacity();
- while(battery_cap < min_battery_cap) {
- battery_cap = battery_capacity();
- battery_cap_text = std::to_string(battery_cap);
- util::sleep_for(1000);
- }
- set_running();
- }
-
- if (!recovery_fn.empty()) {
- // flash recovery
- set_progress("Flashing recovery...");
-
- FILE *flash_file = fopen(recovery_fn.c_str(), "rb");
- if (!flash_file) {
- set_error("failed to flash recovery");
- return;
- }
-
- FILE *recovery_dev = fopen(RECOVERY_DEV, "w+b");
- if (!recovery_dev) {
- fclose(flash_file);
- set_error("failed to flash recovery");
- return;
- }
-
- const size_t buf_size = 4096;
- std::unique_ptr buffer( new char[ buf_size ] );
-
- while (true) {
- size_t bytes_read = fread(buffer.get(), 1, buf_size, flash_file);
- if (!bytes_read) break;
-
- size_t bytes_written = fwrite(buffer.get(), 1, bytes_read, recovery_dev);
- if (bytes_read != bytes_written) {
- fclose(recovery_dev);
- fclose(flash_file);
- set_error("failed to flash recovery: write failed");
- return;
- }
- }
-
- fclose(recovery_dev);
- fclose(flash_file);
-
- set_progress("Verifying flash...");
- std::string new_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
- printf("new recovery hash: %s\n", new_recovery_hash.c_str());
-
- if (new_recovery_hash != recovery_hash) {
- set_error("recovery flash corrupted");
- return;
- }
-
- }
-
- // write arguments to recovery
- FILE *cmd_file = fopen(RECOVERY_COMMAND, "wb");
- if (!cmd_file) {
- set_error("failed to reboot into recovery");
- return;
- }
- fprintf(cmd_file, "--update_package=%s\n", ota_fn.c_str());
- fclose(cmd_file);
-
- set_progress("Rebooting");
-
- // remove the continue.sh so we come back into the setup.
- // maybe we should go directly into the installer, but what if we don't come back with internet? :/
- //unlink("/data/data/com.termux/files/continue.sh");
-
- // TODO: this should be generic between android versions
- // IPowerManager.reboot(confirm=false, reason="recovery", wait=true)
- system("service call power 16 i32 0 s16 recovery i32 1");
- while (true) pause();
-
- // execl("/system/bin/reboot", "recovery");
- // set_error("failed to reboot into recovery");
- }
-
- void draw_ack_screen(const char *title, const char *message, const char *button, const char *altbutton) {
- nvgFillColor(vg, nvgRGBA(255,255,255,255));
- nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
-
- nvgFontFace(vg, "opensans_bold");
- nvgFontSize(vg, 120.0f);
- nvgTextBox(vg, 110, 220, fb_w-240, title, NULL);
-
- nvgFontFace(vg, "opensans_regular");
- nvgFontSize(vg, 86.0f);
- nvgTextBox(vg, 130, 380, fb_w-260, message, NULL);
-
- // draw button
- if (button) {
- nvgBeginPath(vg);
- nvgFillColor(vg, nvgRGBA(8, 8, 8, 255));
- nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
- nvgFill(vg);
-
- nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
- nvgFontFace(vg, "opensans_semibold");
- nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
- nvgText(vg, b_x+b_w/2, b_y+b_h/2, button, NULL);
-
- nvgBeginPath(vg);
- nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 50));
- nvgStrokeWidth(vg, 5);
- nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
- nvgStroke(vg);
- }
-
- // draw button
- if (altbutton) {
- nvgBeginPath(vg);
- nvgFillColor(vg, nvgRGBA(8, 8, 8, 255));
- nvgRoundedRect(vg, balt_x, b_y, b_w, b_h, 20);
- nvgFill(vg);
-
- nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
- nvgFontFace(vg, "opensans_semibold");
- nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
- nvgText(vg, balt_x+b_w/2, b_y+b_h/2, altbutton, NULL);
-
- nvgBeginPath(vg);
- nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 50));
- nvgStrokeWidth(vg, 5);
- nvgRoundedRect(vg, balt_x, b_y, b_w, b_h, 20);
- nvgStroke(vg);
- }
- }
-
- void draw_battery_screen() {
- low_battery_title = "Low Battery";
- low_battery_text = "Please connect EON to your charger. Update will continue once EON battery reaches 35%.";
- low_battery_context = "Current battery charge: " + battery_cap_text + "%";
-
- nvgFillColor(vg, nvgRGBA(255,255,255,255));
- nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
-
- nvgFontFace(vg, "opensans_bold");
- nvgFontSize(vg, 120.0f);
- nvgTextBox(vg, 110, 220, fb_w-240, low_battery_title.c_str(), NULL);
-
- nvgFontFace(vg, "opensans_regular");
- nvgFontSize(vg, 86.0f);
- nvgTextBox(vg, 130, 380, fb_w-260, low_battery_text.c_str(), NULL);
-
- nvgFontFace(vg, "opensans_bold");
- nvgFontSize(vg, 86.0f);
- nvgTextBox(vg, 130, 700, fb_w-260, low_battery_context.c_str(), NULL);
- }
-
- void draw_progress_screen() {
- // draw progress message
- nvgFontSize(vg, 64.0f);
- nvgFillColor(vg, nvgRGBA(255,255,255,255));
- nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
- nvgFontFace(vg, "opensans_bold");
- nvgFontSize(vg, 86.0f);
- nvgTextBox(vg, 0, 380, fb_w, progress_text.c_str(), NULL);
-
- // draw progress bar
- {
- int progress_width = 1000;
- int progress_x = fb_w/2-progress_width/2;
- int progress_y = 520;
- int progress_height = 50;
-
- int powerprompt_y = 312;
- nvgFontFace(vg, "opensans_regular");
- nvgFontSize(vg, 64.0f);
- nvgText(vg, fb_w/2, 740, "Ensure your device remains connected to a power source.", NULL);
-
- NVGpaint paint = nvgBoxGradient(
- vg, progress_x + 1, progress_y + 1,
- progress_width - 2, progress_height, 3, 4, nvgRGB(27, 27, 27), nvgRGB(27, 27, 27));
- nvgBeginPath(vg);
- nvgRoundedRect(vg, progress_x, progress_y, progress_width, progress_height, 12);
- nvgFillPaint(vg, paint);
- nvgFill(vg);
-
- float value = std::min(std::max(0.0f, progress_frac), 1.0f);
- int bar_pos = ((progress_width - 2) * value);
-
- paint = nvgBoxGradient(
- vg, progress_x, progress_y,
- bar_pos+1.5f, progress_height-1, 3, 4,
- nvgRGB(245, 245, 245), nvgRGB(105, 105, 105));
-
- nvgBeginPath(vg);
- nvgRoundedRect(
- vg, progress_x+1, progress_y+1,
- bar_pos, progress_height-2, 12);
- nvgFillPaint(vg, paint);
- nvgFill(vg);
- }
- }
-
- void ui_draw() {
- std::lock_guard guard(lock);
-
- nvgBeginFrame(vg, fb_w, fb_h, 1.0f);
-
- switch (state) {
- case CONFIRMATION:
- draw_ack_screen("An update to NEOS is required.",
- "Your device will now be reset and upgraded. You may want to connect to wifi as download is around 1 GB. Existing data on device should not be lost.",
- "Continue",
- "Connect to WiFi");
- break;
- case LOW_BATTERY:
- draw_battery_screen();
- break;
- case RUNNING:
- draw_progress_screen();
- break;
- case ERROR:
- draw_ack_screen("There was an error", (error_text).c_str(), NULL, "Reboot");
- break;
- }
-
- nvgEndFrame(vg);
- }
-
- void ui_update() {
- std::lock_guard guard(lock);
-
- if (state == ERROR || state == CONFIRMATION) {
- int touch_x = -1, touch_y = -1;
- int res = touch_poll(&touch, &touch_x, &touch_y, 0);
- if (res == 1 && !is_settings_active()) {
- if (touch_x >= b_x && touch_x < b_x+b_w && touch_y >= b_y && touch_y < b_y+b_h) {
- if (state == CONFIRMATION) {
- state = RUNNING;
- update_thread_handle = std::thread(&Updater::run_stages, this);
- }
- }
- if (touch_x >= balt_x && touch_x < balt_x+b_w && touch_y >= b_y && touch_y < b_y+b_h) {
- if (state == CONFIRMATION) {
- start_settings_activity("Settings$WifiSettingsActivity");
- } else if (state == ERROR) {
- do_exit = 1;
- }
- }
- }
- }
- }
-
- void go() {
- ui_init();
-
- while (!do_exit) {
- ui_update();
-
- glClearColor(0.08, 0.08, 0.08, 1.0);
- glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-
- // background
- nvgBeginPath(vg);
- NVGpaint bg = nvgLinearGradient(vg, fb_w, 0, fb_w, fb_h,
- nvgRGBA(0, 0, 0, 0), nvgRGBA(0, 0, 0, 255));
- nvgFillPaint(vg, bg);
- nvgRect(vg, 0, 0, fb_w, fb_h);
- nvgFill(vg);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- ui_draw();
-
- glDisable(GL_BLEND);
-
- fb->swap();
-
- assert(glGetError() == GL_NO_ERROR);
-
- // no simple way to do 30fps vsync with surfaceflinger...
- util::sleep_for(30);
- }
-
- if (update_thread_handle.joinable()) {
- update_thread_handle.join();
- }
-
- // reboot
- system("service call power 16 i32 0 i32 0 i32 1");
- }
-
-};
-
-}
-
-int main(int argc, char *argv[]) {
- bool background_cache = false;
- if (argc > 1) {
- if (strcmp(argv[1], "local") == 0) {
- manifest_url = MANIFEST_URL_NEOS_LOCAL;
- } else if (strcmp(argv[1], "staging") == 0) {
- manifest_url = MANIFEST_URL_NEOS_STAGING;
- } else if (strcmp(argv[1], "bgcache") == 0) {
- manifest_url = argv[2];
- background_cache = true;
- } else {
- manifest_url = argv[1];
- }
- }
-
- printf("updating from %s\n", manifest_url);
- Updater updater;
-
- int err = 0;
- if (background_cache) {
- err = !updater.download_stage();
- } else {
- updater.go();
- }
- return err;
-}
diff --git a/launch_chffrplus.sh b/launch_chffrplus.sh
index 730b383a5..7ef671c26 100755
--- a/launch_chffrplus.sh
+++ b/launch_chffrplus.sh
@@ -90,18 +90,11 @@ function two_init {
# Check for NEOS update
if [ $(< /VERSION) != "$REQUIRED_NEOS_VERSION" ]; then
- if [ -f "$DIR/scripts/continue.sh" ]; then
- cp "$DIR/scripts/continue.sh" "/data/data/com.termux/files/continue.sh"
- fi
-
- if [ ! -f "$BASEDIR/prebuilt" ]; then
- # Clean old build products, but preserve the scons cache
- cd $DIR
- git clean -xdf
- git submodule foreach --recursive git clean -xdf
- fi
-
- "$DIR/installer/updater/updater" "file://$DIR/installer/updater/update.json"
+ echo "Installing NEOS update"
+ NEOS_PY="$DIR/selfdrive/hardware/eon/neos.py"
+ MANIFEST="$DIR/selfdrive/hardware/eon/neos.json"
+ $NEOS_PY --swap-if-ready $MANIFEST
+ $DIR/selfdrive/hardware/eon/updater $NEOS_PY $MANIFEST
fi
}
@@ -165,11 +158,6 @@ function launch {
mv "${STAGING_ROOT}/finalized" $BASEDIR
cd $BASEDIR
- # Partial mitigation for symlink-related filesystem corruption
- # Ensure all files match the repo versions after update
- git reset --hard
- git submodule foreach --recursive git reset --hard
-
echo "Restarting launch script ${LAUNCHER_LOCATION}"
unset REQUIRED_NEOS_VERSION
unset AGNOS_VERSION
diff --git a/launch_env.sh b/launch_env.sh
index 69c989f23..47d98cc92 100755
--- a/launch_env.sh
+++ b/launch_env.sh
@@ -11,7 +11,7 @@ if [ -z "$REQUIRED_NEOS_VERSION" ]; then
fi
if [ -z "$AGNOS_VERSION" ]; then
- export AGNOS_VERSION="1.5"
+ export AGNOS_VERSION="2"
fi
if [ -z "$PASSIVE" ]; then
diff --git a/models/dmonitoring_model_q.dlc b/models/dmonitoring_model_q.dlc
index 941020e28..be61a6c30 100644
Binary files a/models/dmonitoring_model_q.dlc and b/models/dmonitoring_model_q.dlc differ
diff --git a/models/supercombo.dlc b/models/supercombo.dlc
index 2641f23e4..3a4657590 100644
Binary files a/models/supercombo.dlc and b/models/supercombo.dlc differ
diff --git a/opendbc/acura_rdx_2020_can_generated.dbc b/opendbc/acura_rdx_2020_can_generated.dbc
index f9720ce5a..a114e4e13 100644
--- a/opendbc/acura_rdx_2020_can_generated.dbc
+++ b/opendbc/acura_rdx_2020_can_generated.dbc
@@ -281,6 +281,7 @@ BO_ 777 CAR_SPEED: 8 PCM
SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX
+ SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX
BO_ 780 ACC_HUD: 8 ADAS
SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY
diff --git a/opendbc/can/dbc.py b/opendbc/can/dbc.py
index 32d8fffa4..043a674a3 100755
--- a/opendbc/can/dbc.py
+++ b/opendbc/can/dbc.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
import re
import os
import struct
@@ -148,7 +149,7 @@ class dbc():
ival = dd.get(s.name)
if ival is not None:
- ival = (ival / s.factor) - s.offset
+ ival = (ival - s.offset) / s.factor
ival = int(round(ival))
if s.is_signed and ival < 0:
@@ -254,23 +255,3 @@ class dbc():
def get_signals(self, msg):
msg = self.lookup_msg_id(msg)
return [sgs.name for sgs in self.msgs[msg][1]]
-
-
-if __name__ == "__main__":
- from opendbc import DBC_PATH
-
- dbc_test = dbc(os.path.join(DBC_PATH, 'toyota_prius_2017_pt_generated.dbc'))
- msg = ('STEER_ANGLE_SENSOR', {'STEER_ANGLE': -6.0, 'STEER_RATE': 4, 'STEER_FRACTION': -0.2})
- encoded = dbc_test.encode(*msg)
- decoded = dbc_test.decode((0x25, 0, encoded))
- assert decoded == msg
-
- dbc_test = dbc(os.path.join(DBC_PATH, 'hyundai_santa_fe_2019_ccan.dbc'))
- decoded = dbc_test.decode((0x2b0, 0, "\xfa\xfe\x00\x07\x12"))
- assert abs(decoded[1]['SAS_Angle'] - (-26.2)) < 0.001
-
- msg = ('SAS11', {'SAS_Stat': 7.0, 'MsgCount': 0.0, 'SAS_Angle': -26.200000000000003, 'SAS_Speed': 0.0, 'CheckSum': 0.0})
- encoded = dbc_test.encode(*msg)
- decoded = dbc_test.decode((0x2b0, 0, encoded))
-
- assert decoded == msg
diff --git a/opendbc/can/process_dbc.py b/opendbc/can/process_dbc.py
index 811e59b2f..04a67db95 100755
--- a/opendbc/can/process_dbc.py
+++ b/opendbc/can/process_dbc.py
@@ -54,7 +54,7 @@ def process(in_fn, out_fn):
checksum_start_bit = 0
counter_start_bit = None
little_endian = True
- elif can_dbc.name.startswith(("chrysler_")):
+ elif can_dbc.name.startswith(("chrysler_", "stellantis_")):
checksum_type = "chrysler"
checksum_size = 8
counter_size = None
diff --git a/opendbc/gm_global_a_powertrain.dbc b/opendbc/gm_global_a_powertrain.dbc
index 2b830c9bb..cf34478d0 100644
--- a/opendbc/gm_global_a_powertrain.dbc
+++ b/opendbc/gm_global_a_powertrain.dbc
@@ -72,8 +72,13 @@ BO_ 201 ECMEngineStatus: 8 K20_ECM
SG_ Brake_Pressed : 40|1@0+ (1,0) [0|1] "" NEO
SG_ Standstill : 2|1@0+ (1,0) [0|1] "" NEO
-BO_ 209 EBCMBrakePedalTorque: 7 K17_EBCM
- SG_ BrakePedalTorque : 3|12@0+ (1,0) [0|0] "" NEO
+BO_ 209 EBCMBrakePedalSensors: 7 K17_EBCM
+ SG_ Counter1 : 7|2@0+ (1,0) [0|3] "" XXX
+ SG_ Counter2 : 23|2@0+ (1,0) [0|3] "" XXX
+ SG_ BrakePedalPosition1 : 5|14@0+ (1,0) [0|16383] "" XXX
+ SG_ BrakePedalPosition2 : 21|14@0- (-1,0) [0|16383] "" XXX
+ SG_ BrakeNormalized1 : 39|8@0+ (1,0) [0|255] "" XXX
+ SG_ BrakeNormalized2 : 47|8@0- (-1,0) [0|255] "" XXX
BO_ 241 EBCMBrakePedalPosition: 6 K17_EBCM
SG_ BrakePedalPosition : 15|8@0+ (1,0) [0|255] "" NEO
diff --git a/opendbc/honda_accord_2018_can_generated.dbc b/opendbc/honda_accord_2018_can_generated.dbc
index ff286c73d..1c78b38b6 100644
--- a/opendbc/honda_accord_2018_can_generated.dbc
+++ b/opendbc/honda_accord_2018_can_generated.dbc
@@ -285,6 +285,7 @@ BO_ 777 CAR_SPEED: 8 PCM
SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX
+ SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX
BO_ 780 ACC_HUD: 8 ADAS
SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY
diff --git a/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc b/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc
index c2bd5c52e..fe9a13af8 100644
--- a/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc
+++ b/opendbc/honda_civic_hatchback_ex_2017_can_generated.dbc
@@ -285,6 +285,7 @@ BO_ 777 CAR_SPEED: 8 PCM
SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX
+ SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX
BO_ 780 ACC_HUD: 8 ADAS
SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY
diff --git a/opendbc/honda_civic_sedan_16_diesel_2019_can_generated.dbc b/opendbc/honda_civic_sedan_16_diesel_2019_can_generated.dbc
index 085ee1de3..8e7199cc9 100644
--- a/opendbc/honda_civic_sedan_16_diesel_2019_can_generated.dbc
+++ b/opendbc/honda_civic_sedan_16_diesel_2019_can_generated.dbc
@@ -285,6 +285,7 @@ BO_ 777 CAR_SPEED: 8 PCM
SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX
+ SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX
BO_ 780 ACC_HUD: 8 ADAS
SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY
diff --git a/opendbc/honda_crv_ex_2017_can_generated.dbc b/opendbc/honda_crv_ex_2017_can_generated.dbc
index 2f1c85604..cef50babc 100644
--- a/opendbc/honda_crv_ex_2017_can_generated.dbc
+++ b/opendbc/honda_crv_ex_2017_can_generated.dbc
@@ -285,6 +285,7 @@ BO_ 777 CAR_SPEED: 8 PCM
SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX
+ SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX
BO_ 780 ACC_HUD: 8 ADAS
SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY
diff --git a/opendbc/honda_crv_hybrid_2019_can_generated.dbc b/opendbc/honda_crv_hybrid_2019_can_generated.dbc
index 99d3a8d1a..4a6ad4b82 100644
--- a/opendbc/honda_crv_hybrid_2019_can_generated.dbc
+++ b/opendbc/honda_crv_hybrid_2019_can_generated.dbc
@@ -285,6 +285,7 @@ BO_ 777 CAR_SPEED: 8 PCM
SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX
+ SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX
BO_ 780 ACC_HUD: 8 ADAS
SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY
diff --git a/opendbc/honda_insight_ex_2019_can_generated.dbc b/opendbc/honda_insight_ex_2019_can_generated.dbc
index 7a511751f..024f68d3c 100644
--- a/opendbc/honda_insight_ex_2019_can_generated.dbc
+++ b/opendbc/honda_insight_ex_2019_can_generated.dbc
@@ -285,6 +285,7 @@ BO_ 777 CAR_SPEED: 8 PCM
SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX
+ SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX
BO_ 780 ACC_HUD: 8 ADAS
SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY
diff --git a/opendbc/hyundai_kia_mando_front_radar.dbc b/opendbc/hyundai_kia_mando_front_radar.dbc
new file mode 100644
index 000000000..552cdddea
--- /dev/null
+++ b/opendbc/hyundai_kia_mando_front_radar.dbc
@@ -0,0 +1,454 @@
+
+VERSION ""
+
+
+NS_ :
+ NS_DESC_
+ CM_
+ BA_DEF_
+ BA_
+ VAL_
+ CAT_DEF_
+ CAT_
+ FILTER
+ BA_DEF_DEF_
+ EV_DATA_
+ ENVVAR_DATA_
+ SGTYPE_
+ SGTYPE_VAL_
+ BA_DEF_SGTYPE_
+ BA_SGTYPE_
+ SIG_TYPE_REF_
+ VAL_TABLE_
+ SIG_GROUP_
+ SIG_VALTYPE_
+ SIGTYPE_VALTYPE_
+ BO_TX_BU_
+ BA_DEF_REL_
+ BA_REL_
+ BA_DEF_DEF_REL_
+ BU_SG_REL_
+ BU_EV_REL_
+ BU_BO_REL_
+ SG_MUL_VAL_
+
+BS_:
+
+BU_: XXX
+
+
+BO_ 1280 RADAR_TRACK_500: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1281 RADAR_TRACK_501: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1282 RADAR_TRACK_502: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1283 RADAR_TRACK_503: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1284 RADAR_TRACK_504: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1285 RADAR_TRACK_505: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1286 RADAR_TRACK_506: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1287 RADAR_TRACK_507: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1288 RADAR_TRACK_508: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1289 RADAR_TRACK_509: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1290 RADAR_TRACK_50a: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1291 RADAR_TRACK_50b: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1292 RADAR_TRACK_50c: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1293 RADAR_TRACK_50d: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1294 RADAR_TRACK_50e: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1295 RADAR_TRACK_50f: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1296 RADAR_TRACK_510: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1297 RADAR_TRACK_511: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1298 RADAR_TRACK_512: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1299 RADAR_TRACK_513: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1300 RADAR_TRACK_514: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1301 RADAR_TRACK_515: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1302 RADAR_TRACK_516: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1303 RADAR_TRACK_517: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1304 RADAR_TRACK_518: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1305 RADAR_TRACK_519: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1306 RADAR_TRACK_51a: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1307 RADAR_TRACK_51b: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1308 RADAR_TRACK_51c: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1309 RADAR_TRACK_51d: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1310 RADAR_TRACK_51e: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
+
+BO_ 1311 RADAR_TRACK_51f: 8 RADAR
+ SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX
+ SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX
+ SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX
+ SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX
+ SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX
+ SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX
+ SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX
+ SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX
+ SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX
+ SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX
+
diff --git a/opendbc/lexus_ct200h_2018_pt_generated.dbc b/opendbc/lexus_ct200h_2018_pt_generated.dbc
index 818ab6f3f..3b225c73e 100644
--- a/opendbc/lexus_ct200h_2018_pt_generated.dbc
+++ b/opendbc/lexus_ct200h_2018_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "lexus_ct200h_2018_pt.dbc starts here";
diff --git a/opendbc/lexus_is_2018_pt_generated.dbc b/opendbc/lexus_is_2018_pt_generated.dbc
index 711944283..51c584df6 100644
--- a/opendbc/lexus_is_2018_pt_generated.dbc
+++ b/opendbc/lexus_is_2018_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "lexus_is_2018_pt.dbc starts here";
diff --git a/opendbc/lexus_nx300_2018_pt_generated.dbc b/opendbc/lexus_nx300_2018_pt_generated.dbc
index 705d87d37..f00cd2c65 100644
--- a/opendbc/lexus_nx300_2018_pt_generated.dbc
+++ b/opendbc/lexus_nx300_2018_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "lexus_nx300_2018_pt.dbc starts here";
diff --git a/opendbc/lexus_nx300h_2018_pt_generated.dbc b/opendbc/lexus_nx300h_2018_pt_generated.dbc
index f4bfb86cb..ddb4ad6de 100644
--- a/opendbc/lexus_nx300h_2018_pt_generated.dbc
+++ b/opendbc/lexus_nx300h_2018_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "lexus_nx300h_2018_pt.dbc starts here";
diff --git a/opendbc/lexus_rx_350_2016_pt_generated.dbc b/opendbc/lexus_rx_350_2016_pt_generated.dbc
index 6144153cd..4c316fee7 100644
--- a/opendbc/lexus_rx_350_2016_pt_generated.dbc
+++ b/opendbc/lexus_rx_350_2016_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "lexus_rx_350_2016_pt.dbc starts here";
diff --git a/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc b/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc
index 92437357c..c1d67f5c9 100644
--- a/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc
+++ b/opendbc/lexus_rx_hybrid_2017_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "lexus_rx_hybrid_2017_pt.dbc starts here";
diff --git a/opendbc/mazda_2017.dbc b/opendbc/mazda_2017.dbc
index 9ee492928..fdd6d2824 100644
--- a/opendbc/mazda_2017.dbc
+++ b/opendbc/mazda_2017.dbc
@@ -498,32 +498,17 @@ BO_ 552 GEAR: 8 XXX
SG_ GEAR_BOX : 36|4@0+ (1,0) [0|15] "" XXX
BO_ 543 CRZ_EVENTS: 8 XXX
- SG_ NEW_SIGNAL_3 : 34|1@0+ (1,0) [0|1] "" XXX
- SG_ CHKSUM : 63|8@0+ (1,0) [0|15] "" XXX
- SG_ NEW_SIGNAL_1 : 55|4@0+ (1,0) [0|15] "" XXX
- SG_ NEW_SIGNAL_5 : 47|4@0+ (1,0) [0|15] "" XXX
- SG_ NEW_SIGNAL_6 : 6|1@0+ (1,0) [0|255] "" XXX
- SG_ NEW_SIGNAL_8 : 0|1@0+ (1,0) [0|31] "" XXX
- SG_ NEW_SIGNAL_9 : 1|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_10 : 2|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_12 : 10|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_13 : 9|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_18 : 12|1@0+ (1,0) [0|15] "" XXX
- SG_ NEW_SIGNAL_19 : 14|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_20 : 15|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_21 : 23|1@0+ (1,0) [0|15] "" XXX
- SG_ NEW_SIGNAL_24 : 31|1@0+ (1,0) [0|1] "" XXX
- SG_ GAS_PEDAL_PRESSED : 32|1@0+ (1,0) [0|255] "" XXX
- SG_ CRZ_STARTED : 18|1@0+ (1,0) [0|1] "" XXX
- SG_ PLUS_ONE_CRZ : 17|1@0+ (1,0) [0|255] "" XXX
- SG_ PLUS_ONE_CRZ_2 : 19|1@0+ (1,0) [0|1] "" XXX
- SG_ GAS_MAYBE : 22|1@0+ (1,0) [0|1] "" XXX
- SG_ NONACC_ACTIVE : 5|1@0+ (1,0) [0|1] "" XXX
- SG_ CRUISE_ACTIVE_CAR_MOVING : 16|1@0+ (1,0) [0|1] "" XXX
- SG_ NONACC_RELATED : 11|1@0+ (1,0) [0|255] "" XXX
SG_ CTR : 51|4@0+ (1,0) [0|15] "" XXX
- SG_ CAS_CMD_MAYBE : 30|7@0- (1,0) [0|255] "" XXX
- SG_ NEW_SIGNAL_4 : 43|4@0+ (1,0) [0|255] "" XXX
+ SG_ NEW_SIGNAL_21 : 23|1@0+ (1,0) [0|15] "" XXX
+ SG_ GAS_MAYBE : 22|1@0+ (1,0) [0|1] "" XXX
+ SG_ ACCEL_CMD : 46|8@0- (1,0) [0|15] "" XXX
+ SG_ CRUISE_ACTIVE_CAR_MOVING : 16|1@0+ (1,0) [0|1] "" XXX
+ SG_ PLUS_ONE_CRZ : 17|1@0+ (1,0) [0|255] "" XXX
+ SG_ CRZ_STARTED : 18|1@0+ (1,0) [0|1] "" XXX
+ SG_ CHKSUM : 63|8@0+ (1,0) [0|15] "" XXX
+ SG_ PLUS_ONE_CRZ_2 : 19|1@0+ (1,0) [0|1] "" XXX
+ SG_ ACCEL_CMD_LOW_RES : 29|8@0- (1,0) [0|255] "" XXX
+ SG_ CRZ_SPEED : 7|16@0+ (0.005,-0.5) [0|328] "kph" XXX
BO_ 542 NEW_MSG_33: 8 XXX
SG_ CTR : 48|4@1+ (1,0) [0|15] "" XXX
@@ -564,32 +549,32 @@ BO_ 535 CURVE_CTRS: 8 XXX
SG_ NEW_SIGNAL_4 : 9|1@0+ (1,0) [0|1] "" XXX
BO_ 540 CRZ_CTRL: 8 XXX
- SG_ NEW_SIGNAL_3 : 1|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_4 : 8|1@0+ (1,0) [0|255] "" XXX
- SG_ NEW_SIGNAL_5 : 9|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_6 : 10|1@0+ (1,0) [0|1] "" XXX
- SG_ NEW_SIGNAL_7 : 18|3@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_9 : 31|1@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_10 : 30|1@0+ (1,0) [0|1] "" XXX
SG_ ACC_GAS_MAYBE : 23|1@0+ (1,0) [0|31] "" XXX
SG_ ACC_GAS_MAYBE2 : 29|1@0+ (1,0) [0|1] "" XXX
- SG_ CRZ_ACTIVE : 3|1@0+ (1,0) [0|1] "" XXX
SG_ HANDS_OFF_STEERING : 48|1@0+ (1,0) [0|1] "" XXX
SG_ HANDS_ON_STEER_WARN : 59|4@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_1 : 52|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_2 : 45|3@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_8 : 0|1@0+ (1,0) [0|1] "" XXX
+ SG_ NEW_SIGNAL_3 : 1|1@0+ (1,0) [0|1] "" XXX
+ SG_ CRZ_ACTIVE : 3|1@0+ (1,0) [0|1] "" XXX
+ SG_ NEW_SIGNAL_4 : 8|1@0+ (1,0) [0|255] "" XXX
+ SG_ NEW_SIGNAL_5 : 9|1@0+ (1,0) [0|1] "" XXX
+ SG_ CRZ_AVAILABLE : 17|1@0+ (1,0) [0|255] "" XXX
+ SG_ DISTANCE_SETTING : 20|3@0+ (1,0) [0|7] "" XXX
BO_ 539 CRZ_INFO: 8 XXX
- SG_ NEW_SIGNAL_1 : 17|1@0+ (1,0) [0|255] "" XXX
- SG_ NEW_SIGNAL_2 : 16|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_5 : 34|1@0+ (1,0) [0|1] "" XXX
SG_ NEW_SIGNAL_7 : 47|1@0+ (1,0) [0|255] "" XXX
SG_ CTR1 : 55|8@0+ (1,0) [0|255] "" XXX
SG_ NEW_SIGNAL_3 : 37|1@0+ (1,0) [0|255] "" XXX
SG_ ACC_ACTIVE : 33|1@0+ (1,0) [0|1] "" XXX
- SG_ ACCEL_CMD : 31|10@0- (1,0) [0|1] "" XXX
+ SG_ ACCEL_CMD : 31|8@0- (1,0) [0|1] "" XXX
SG_ CHKSUM : 63|8@0+ (1,0) [0|255] "" XXX
+ SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|65535] "" XXX
BO_ 121 EPB: 8 XXX
SG_ NEW_SIGNAL_1 : 4|4@0+ (1,0) [0|255] "" XXX
@@ -774,5 +759,6 @@ CM_ SG_ 552 MORE_GEAR "";
CM_ SG_ 552 GEAR "0 Shifting, 1 P, 2 R, 3 N, 4 D";
CM_ SG_ 552 GEAR_BOX "0 P, 14 R, 1 though 6 D for speeds, 15 Shift";
CM_ SG_ 540 HANDS_ON_STEER_WARN "0 no warning, b warning";
+CM_ SG_ 540 DISTANCE_SETTING "Radar distance 0: disabled, 1: 4 bars, 2: 3 bars, 3: 2 bars, 4: 1 bar";
CM_ SG_ 1143 REAR_CT_ALERT "Rear Cross Traffic Alert";
VAL_ 552 GEAR 1 "P" 2 "R" 3 "N" 4 "D" ;
diff --git a/opendbc/tesla_can.dbc b/opendbc/tesla_can.dbc
index cdc665dc7..57a63e128 100644
--- a/opendbc/tesla_can.dbc
+++ b/opendbc/tesla_can.dbc
@@ -34,14 +34,14 @@ NS_ :
BS_:
BU_:
- NEO
- MCU
- GTW
- EPAS
- DI
- ESP
- SBW
- STW
+ NEO
+ MCU
+ GTW
+ EPAS
+ DI
+ ESP
+ SBW
+ STW
APP
DAS
XXX
@@ -71,6 +71,17 @@ BO_ 1160 DAS_steeringControl: 4 NEO
SG_ DAS_steeringAngleRequest : 6|15@0+ (0.1,-1638.35) [-1638.35|1638.35] "deg" EPAS
SG_ DAS_steeringHapticRequest : 7|1@0+ (1,0) [0|0] "" EPAS
+BO_ 697 DAS_control: 8 NEO
+ SG_ DAS_setSpeed : 0|12@1+ (0.1,0) [0|409.4] "kph" NEO
+ SG_ DAS_accState : 12|4@1+ (1,0) [0|0] "" NEO
+ SG_ DAS_aebEvent : 16|2@1+ (1,0) [0|3] "" NEO
+ SG_ DAS_jerkMin : 18|9@1+ (0.03,-15.232) [-15.232|0.098] "m/s^3" NEO
+ SG_ DAS_jerkMax : 27|8@1+ (0.059,0) [0|15.045] "m/s^3" NEO
+ SG_ DAS_accelMin : 35|9@1+ (0.04,-15) [-15|5.44] "m/s^2" NEO
+ SG_ DAS_accelMax : 44|9@1+ (0.04,-15) [-15|5.44] "m/s^2" NEO
+ SG_ DAS_controlCounter : 53|3@1+ (1,0) [0|0] "" NEO
+ SG_ DAS_controlChecksum : 56|8@1+ (1,0) [0|0] "" NEO
+
BO_ 257 GTW_epasControl: 3 NEO
SG_ GTW_epasControlChecksum : 23|8@0+ (1,0) [0|255] "" NEO
SG_ GTW_epasControlCounter : 11|4@0+ (1,0) [0|15] "" NEO
@@ -102,7 +113,6 @@ BO_ 3 STW_ANGL_STAT: 8 STW
SG_ CRC_STW_ANGL_STAT : 63|8@0+ (1,0) [0|255] "" NEO
BO_ 14 STW_ANGLHP_STAT: 8 STW
-
SG_ StW_AnglHP : 5|14@0+ (0.1,-819.2) [-819.2|819] "deg" NEO
SG_ StW_AnglHP_Spd : 21|14@0+ (0.5,-4096) [-4096|4095.5] "deg/s" NEO
SG_ StW_AnglHP_Sens_Stat : 33|2@0+ (1,0) [0|0] "" NEO
@@ -691,6 +701,13 @@ VAL_ 643 MPkBrk_Stat 1 "ENGG" 0 "RELS" ;
VAL_ 643 RevGr_Engg 0 "DISENGG" 1 "ENGG" 2 "NDEF2" 3 "SNA" ;
VAL_ 643 StW_Cond_Stat 3 "BLINK" 1 "NDEF1" 0 "OFF" 2 "ON" ;
VAL_ 643 Trlr_Stat 2 "NDEF2" 0 "NONE" 1 "OK" 3 "SNA" ;
+VAL_ 697 DAS_setSpeed 4095 "SNA" ;
+VAL_ 697 DAS_accState 15 "FAULT_SNA" 13 "ACC_CANCEL_GENERIC_SILENT" 11 "APC_SELFPARK_START" 10 "APC_UNPARK_COMPLETE" 9 "APC_PAUSE" 8 "APC_ABORT" 7 "APC_COMPLETE" 6 "APC_FORWARD" 5 "APC_BACKWARD" 4 "ACC_ON" 3 "ACC_HOLD" 0 "ACC_CANCEL_GENERIC" ;
+VAL_ 697 DAS_aebEvent 3 "AEB_SNA" 2 "AEB_FAULT" 1 "AEB_ACTIVE" 0 "AEB_NOT_ACTIVE" ;
+VAL_ 697 DAS_jerkMin 511 "SNA" ;
+VAL_ 697 DAS_jerkMax 255 "SNA" ;
+VAL_ 697 DAS_accelMin 511 "SNA" ;
+VAL_ 697 DAS_accelMax 511 "SNA" ;
VAL_ 792 BOOT_STATE 2 "Init" 3 "SNA" 0 "closed" 1 "open" ;
VAL_ 792 CERRD 1 "CAN error detect" 0 "no Can error detected" ;
VAL_ 792 DAY 1 "Init" 0 "SNA" ;
diff --git a/opendbc/toyota_avalon_2017_pt_generated.dbc b/opendbc/toyota_avalon_2017_pt_generated.dbc
index b7da0d4bd..25753613d 100644
--- a/opendbc/toyota_avalon_2017_pt_generated.dbc
+++ b/opendbc/toyota_avalon_2017_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_avalon_2017_pt.dbc starts here";
diff --git a/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc b/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc
index 4798539c4..ec35feef2 100644
--- a/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc
+++ b/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_camry_hybrid_2018_pt.dbc starts here";
diff --git a/opendbc/toyota_corolla_2017_pt_generated.dbc b/opendbc/toyota_corolla_2017_pt_generated.dbc
index bea949426..db13a143a 100644
--- a/opendbc/toyota_corolla_2017_pt_generated.dbc
+++ b/opendbc/toyota_corolla_2017_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_corolla_2017_pt.dbc starts here";
diff --git a/opendbc/toyota_highlander_2017_pt_generated.dbc b/opendbc/toyota_highlander_2017_pt_generated.dbc
index 878ec9a74..ca7c16b1e 100644
--- a/opendbc/toyota_highlander_2017_pt_generated.dbc
+++ b/opendbc/toyota_highlander_2017_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_highlander_2017_pt.dbc starts here";
diff --git a/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc b/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc
index 38368bac6..843d1e2ce 100644
--- a/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc
+++ b/opendbc/toyota_highlander_hybrid_2018_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_highlander_hybrid_2018_pt.dbc starts here";
diff --git a/opendbc/toyota_nodsu_hybrid_pt_generated.dbc b/opendbc/toyota_nodsu_hybrid_pt_generated.dbc
index 64b04707b..0f94c584c 100644
--- a/opendbc/toyota_nodsu_hybrid_pt_generated.dbc
+++ b/opendbc/toyota_nodsu_hybrid_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "Imported file _toyota_nodsu_common.dbc starts here";
BO_ 401 STEERING_LTA: 8 XXX
diff --git a/opendbc/toyota_nodsu_pt_generated.dbc b/opendbc/toyota_nodsu_pt_generated.dbc
index 057546027..10cf508b7 100644
--- a/opendbc/toyota_nodsu_pt_generated.dbc
+++ b/opendbc/toyota_nodsu_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "Imported file _toyota_nodsu_common.dbc starts here";
BO_ 401 STEERING_LTA: 8 XXX
diff --git a/opendbc/toyota_prius_2017_pt_generated.dbc b/opendbc/toyota_prius_2017_pt_generated.dbc
index 59bbf368a..1d29dbf81 100644
--- a/opendbc/toyota_prius_2017_pt_generated.dbc
+++ b/opendbc/toyota_prius_2017_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_prius_2017_pt.dbc starts here";
diff --git a/opendbc/toyota_rav4_2017_pt_generated.dbc b/opendbc/toyota_rav4_2017_pt_generated.dbc
index 5bb60ce7e..7a2f0bd4c 100644
--- a/opendbc/toyota_rav4_2017_pt_generated.dbc
+++ b/opendbc/toyota_rav4_2017_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_rav4_2017_pt.dbc starts here";
diff --git a/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc b/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc
index 966984f65..61ff80a6d 100644
--- a/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc
+++ b/opendbc/toyota_rav4_hybrid_2017_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_rav4_hybrid_2017_pt.dbc starts here";
diff --git a/opendbc/toyota_sienna_xle_2018_pt_generated.dbc b/opendbc/toyota_sienna_xle_2018_pt_generated.dbc
index 883a45b99..ac7660643 100644
--- a/opendbc/toyota_sienna_xle_2018_pt_generated.dbc
+++ b/opendbc/toyota_sienna_xle_2018_pt_generated.dbc
@@ -165,10 +165,12 @@ BO_ 1020 SOLAR_SENSOR: 8 XXX
SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX
BO_ 1041 ACC_HUD: 8 DSU
+ SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
- SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
+ SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX
+ SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX
BO_ 1042 LKAS_HUD: 8 XXX
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
@@ -313,6 +315,8 @@ CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front
CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file.";
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
+CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator";
+CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity";
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit.";
@@ -338,6 +342,8 @@ VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking";
VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok";
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
+VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled";
+VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off";
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none";
@@ -388,6 +394,13 @@ BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX
CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss";
+BO_ 767 SDSU: 8 XXX
+ SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX
+
+CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS1 Toyotas. Learn more: https://github.com/wocsor/panda/tree/smart_dsu";
+
+CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu";
+
CM_ "toyota_sienna_xle_2018_pt.dbc starts here";
diff --git a/panda/board/SConscript b/panda/board/SConscript
index c16d191bd..4570bf1a5 100644
--- a/panda/board/SConscript
+++ b/panda/board/SConscript
@@ -4,49 +4,35 @@ import subprocess
PREFIX = "arm-none-eabi-"
BUILDER = "DEV"
+common_flags = []
+build_projects = {}
+
if os.getenv("PEDAL"):
- PROJECT = "pedal"
- STARTUP_FILE = "stm32fx/startup_stm32f205xx.s"
- LINKER_SCRIPT = "stm32fx/stm32fx_flash.ld"
- APP_START_ADDRESS = "0x8004000"
- MAIN = "pedal/main.c"
- PROJECT_FLAGS = [
- "-mcpu=cortex-m3",
- "-msoft-float",
- "-DSTM32F2",
- "-DSTM32F205xx",
- "-O2",
- "-DPEDAL",
- ]
+ build_projects["pedal"] = {
+ "MAIN": "pedal/main.c",
+ "STARTUP_FILE": "stm32fx/startup_stm32f205xx.s",
+ "LINKER_SCRIPT": "stm32fx/stm32fx_flash.ld",
+ "APP_START_ADDRESS": "0x8004000",
+ "PROJECT_FLAGS": [
+ "-mcpu=cortex-m3",
+ "-msoft-float",
+ "-DSTM32F2",
+ "-DSTM32F205xx",
+ "-O2",
+ "-DPEDAL",
+ ],
+ }
+
if os.getenv("PEDAL_USB"):
- PROJECT = "pedal_usb"
- PROJECT_FLAGS.append("-DPEDAL_USB")
+ build_projects["pedal_usb"] = build_projects.pop("pedal")
+ build_projects["pedal_usb"]["PROJECT_FLAGS"].append("-DPEDAL_USB")
-elif os.getenv("PANDA_H7"):
- PROJECT = "panda_h7"
- STARTUP_FILE = "stm32h7/startup_stm32h7x5xx.s"
- LINKER_SCRIPT = "stm32h7/stm32h7x5_flash.ld"
- APP_START_ADDRESS = "0x8020000"
- MAIN = "main.c"
- PROJECT_FLAGS = [
- "-mcpu=cortex-m7",
- "-mhard-float",
- "-DSTM32H7",
- "-DSTM32H725xx",
- "-mfpu=fpv5-d16",
- "-fsingle-precision-constant",
- "-Os",
- "-g",
- "-DPANDA",
- ]
-
-else:
- PROJECT = "panda"
- STARTUP_FILE = "stm32fx/startup_stm32f413xx.s"
- LINKER_SCRIPT = "stm32fx/stm32fx_flash.ld"
- APP_START_ADDRESS = "0x8004000"
- MAIN = "main.c"
- PROJECT_FLAGS = [
+build_projects["panda"] = {
+ "MAIN": "main.c",
+ "STARTUP_FILE": "stm32fx/startup_stm32f413xx.s",
+ "LINKER_SCRIPT": "stm32fx/stm32fx_flash.ld",
+ "APP_START_ADDRESS": "0x8004000",
+ "PROJECT_FLAGS": [
"-mcpu=cortex-m4",
"-mhard-float",
"-DSTM32F4",
@@ -56,8 +42,48 @@ else:
"-Os",
"-g",
"-DPANDA",
- ]
+ ],
+}
+# arm-none-eabi-gcc on comma two has no cortex-m7 support
+if not os.path.exists("/EON"):
+ build_projects["panda_h7"] = {
+ "MAIN": "main.c",
+ "STARTUP_FILE": "stm32h7/startup_stm32h7x5xx.s",
+ "LINKER_SCRIPT": "stm32h7/stm32h7x5_flash.ld",
+ "APP_START_ADDRESS": "0x8020000",
+ "PROJECT_FLAGS": [
+ "-mcpu=cortex-m7",
+ "-mhard-float",
+ "-DSTM32H7",
+ "-DSTM32H725xx",
+ "-mfpu=fpv5-d16",
+ "-fsingle-precision-constant",
+ "-Os",
+ "-g",
+ "-DPANDA",
+ ],
+ }
+
+if os.getenv("RELEASE"):
+ BUILD_TYPE = "RELEASE"
+ cert_fn = os.getenv("CERT")
+ assert cert_fn is not None, 'No certificate file specified. Please set CERT env variable'
+ assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path'
+else:
+ BUILD_TYPE = "DEBUG"
+ cert_fn = File("../certs/debug").srcnode().abspath
+ common_flags += ["-DALLOW_DEBUG"]
+
+if os.getenv("DEBUG"):
+ common_flags += ["-DDEBUG"]
+
+includes = [
+ "stm32fx/inc",
+ "stm32h7/inc",
+ "..",
+ ".",
+]
def get_version(builder, build_type):
try:
@@ -96,83 +122,67 @@ def get_key_header(name):
]
return r
-
def objcopy(source, target, env, for_signature):
return '$OBJCOPY -O binary %s %s' % (source[0], target[0])
-
-linkerscript_fn = File(LINKER_SCRIPT).srcnode().abspath
-
-flags = [
- "-Wall",
- "-Wextra",
- "-Wstrict-prototypes",
- "-Werror",
- "-mlittle-endian",
- "-mthumb",
- "-nostdlib",
- "-fno-builtin",
- f"-T{linkerscript_fn}",
- "-std=gnu11",
-] + PROJECT_FLAGS
-
-
-if os.getenv("RELEASE"):
- BUILD_TYPE = "RELEASE"
- cert_fn = os.getenv("CERT")
- assert cert_fn is not None, 'No certificate file specified. Please set CERT env variable'
- assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path'
-else:
- BUILD_TYPE = "DEBUG"
- cert_fn = File("../certs/debug").srcnode().abspath
- flags += ["-DALLOW_DEBUG"]
-
-includes = [
- "stm32fx/inc",
- "stm32h7/inc",
- "..",
- ".",
-]
-
-panda_env = Environment(
- ENV=os.environ,
- CC=PREFIX + 'gcc',
- AS=PREFIX + 'gcc',
- OBJCOPY=PREFIX + 'objcopy',
- OBJDUMP=PREFIX + 'objdump',
- ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES",
- CFLAGS=flags,
- ASFLAGS=flags,
- LINKFLAGS=flags,
- CPPPATH=includes,
- BUILDERS={
- 'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf')
- }
-)
-
# Common autogenerated includes
-version = f'const uint8_t gitversion[] = "{get_version(BUILDER, BUILD_TYPE)}";'
-gitversion = panda_env.Textfile("obj/gitversion.h", [version, ""])
-Ignore('bootstub.o', gitversion)
-Requires('bootstub.o', gitversion)
-Ignore('main.o', gitversion)
-Requires('main.o', gitversion)
+with open("obj/gitversion.h", "w") as f:
+ f.write(f'const uint8_t gitversion[] = "{get_version(BUILDER, BUILD_TYPE)}";\n')
certs = [get_key_header(n) for n in ["debug", "release"]]
-certheader = panda_env.Textfile("obj/cert.h", certs + [""])
+with open("obj/cert.h", "w") as f:
+ for cert in certs:
+ f.write("\n".join(cert) + "\n")
-startup = panda_env.Object(STARTUP_FILE)
+for project_name in build_projects:
+ project = build_projects[project_name]
+ linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().abspath
-# Bootstub
-crypto = ["../crypto/rsa.c", "../crypto/sha.c"]
-bootstub_elf = panda_env.Program(f"obj/bootstub.{PROJECT}.elf", [startup] + crypto + ["bootstub.c"])
-bootstub_bin = panda_env.Objcopy(f"obj/bootstub.{PROJECT}.bin", bootstub_elf)
+ flags = [
+ "-Wall",
+ "-Wextra",
+ "-Wstrict-prototypes",
+ "-Werror",
+ "-mlittle-endian",
+ "-mthumb",
+ "-nostdlib",
+ "-fno-builtin",
+ f"-T{linkerscript_fn}",
+ "-std=gnu11",
+ ] + project["PROJECT_FLAGS"] + common_flags
-# Build main
-main_elf = panda_env.Program(f"obj/{PROJECT}.elf", [startup, MAIN],
- LINKFLAGS=[f"-Wl,--section-start,.isr_vector={APP_START_ADDRESS}"] + flags)
-main_bin = panda_env.Objcopy(f"obj/{PROJECT}.bin", main_elf)
+ project_env = Environment(
+ ENV=os.environ,
+ CC=PREFIX + 'gcc',
+ AS=PREFIX + 'gcc',
+ OBJCOPY=PREFIX + 'objcopy',
+ OBJDUMP=PREFIX + 'objdump',
+ ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES",
+ CFLAGS=flags,
+ ASFLAGS=flags,
+ LINKFLAGS=flags,
+ CPPPATH=includes,
+ BUILDERS={
+ 'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf')
+ }
+ )
+ startup = project_env.Object(project["STARTUP_FILE"])
-# Sign main
-sign_py = File("../crypto/sign.py").srcnode().abspath
-panda_bin_signed = panda_env.Command(f"obj/{PROJECT}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}")
+ # Bootstub
+ crypto_obj = [
+ project_env.Object(f"rsa-{project_name}", "../crypto/rsa.c"),
+ project_env.Object(f"sha-{project_name}", "../crypto/sha.c")
+ ]
+ bootstub_obj = project_env.Object(f"bootstub-{project_name}", "bootstub.c")
+ bootstub_elf = project_env.Program(f"obj/bootstub.{project_name}.elf", [startup] + crypto_obj + [bootstub_obj])
+ bootstub_bin = project_env.Objcopy(f"obj/bootstub.{project_name}.bin", bootstub_elf)
+
+ # Build main
+ main_obj = project_env.Object(f"main-{project_name}", project["MAIN"])
+ main_elf = project_env.Program(f"obj/{project_name}.elf", [startup, main_obj],
+ LINKFLAGS=[f"-Wl,--section-start,.isr_vector={project['APP_START_ADDRESS']}"] + flags)
+ main_bin = project_env.Objcopy(f"obj/{project_name}.bin", main_elf)
+
+ # Sign main
+ sign_py = File("../crypto/sign.py").srcnode().abspath
+ panda_bin_signed = project_env.Command(f"obj/{project_name}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}")
diff --git a/panda/board/bootstub_declarations.h b/panda/board/bootstub_declarations.h
index b247458f9..8e9f07312 100644
--- a/panda/board/bootstub_declarations.h
+++ b/panda/board/bootstub_declarations.h
@@ -2,6 +2,7 @@
void puts(const char *a){ UNUSED(a); }
void puth(uint8_t i){ UNUSED(i); }
void puth2(uint8_t i){ UNUSED(i); }
+void puth4(uint8_t i){ UNUSED(i); }
typedef struct board board;
typedef struct harness_configuration harness_configuration;
// No CAN support on bootloader
diff --git a/panda/board/build_all.sh b/panda/board/build_all.sh
index b7e681108..a461f6fa7 100755
--- a/panda/board/build_all.sh
+++ b/panda/board/build_all.sh
@@ -2,6 +2,5 @@
set -e
scons -u
-PANDA_H7=1 scons -u
PEDAL=1 scons -u
PEDAL=1 PEDAL_USB=1 scons -u
diff --git a/panda/board/drivers/bxcan.h b/panda/board/drivers/bxcan.h
index d631f0c72..7828925bd 100644
--- a/panda/board/drivers/bxcan.h
+++ b/panda/board/drivers/bxcan.h
@@ -141,9 +141,7 @@ void process_can(uint8_t can_number) {
CAN->sTxMailBox[0].TDTR = to_send.RDTR;
CAN->sTxMailBox[0].TIR = to_send.RIR;
- if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
- usb_outep3_resume_if_paused();
- }
+ usb_cb_ep3_out_complete();
}
}
diff --git a/panda/board/drivers/can_common.h b/panda/board/drivers/can_common.h
index 73d37aa84..cbce796d8 100644
--- a/panda/board/drivers/can_common.h
+++ b/panda/board/drivers/can_common.h
@@ -100,7 +100,21 @@ bool can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
if (!ret) {
can_overflow_cnt++;
#ifdef DEBUG
- puts("can_push failed!\n");
+ puts("can_push to ");
+ if (q == &can_rx_q) {
+ puts("can_rx_q");
+ } else if (q == &can_tx1_q) {
+ puts("can_tx1_q");
+ } else if (q == &can_tx2_q) {
+ puts("can_tx2_q");
+ } else if (q == &can_tx3_q) {
+ puts("can_tx3_q");
+ } else if (q == &can_txgmlan_q) {
+ puts("can_txgmlan_q");
+ } else {
+ puts("unknown");
+ }
+ puts(" failed!\n");
#endif
}
return ret;
@@ -125,6 +139,8 @@ void can_clear(can_ring *q) {
q->w_ptr = 0;
q->r_ptr = 0;
EXIT_CRITICAL();
+ // handle TX buffer full with zero ECUs awake on the bus
+ usb_cb_ep3_out_complete();
}
// assign CAN numbering
diff --git a/panda/board/drivers/fdcan.h b/panda/board/drivers/fdcan.h
index d9eed3efc..b0931e226 100644
--- a/panda/board/drivers/fdcan.h
+++ b/panda/board/drivers/fdcan.h
@@ -74,9 +74,7 @@ void process_can(uint8_t can_number) {
to_push.RDHR = to_send.RDHR;
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
- if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
- usb_outep3_resume_if_paused();
- }
+ usb_cb_ep3_out_complete();
}
}
diff --git a/panda/board/drivers/uart.h b/panda/board/drivers/uart.h
index ecb3241a7..d6107a6c3 100644
--- a/panda/board/drivers/uart.h
+++ b/panda/board/drivers/uart.h
@@ -181,18 +181,23 @@ void putui(uint32_t i) {
puts(&str[idx + 1U]);
}
-void puth(unsigned int i) {
+void puthx(uint32_t i, uint8_t len) {
const char c[] = "0123456789abcdef";
- for (int pos = 28; pos != -4; pos -= 4) {
+ for (int pos = ((int)len * 4) - 4; pos > -4; pos -= 4) {
putch(c[(i >> (unsigned int)(pos)) & 0xFU]);
}
}
+void puth(unsigned int i) {
+ puthx(i, 8U);
+}
+
void puth2(unsigned int i) {
- const char c[] = "0123456789abcdef";
- for (int pos = 4; pos != -4; pos -= 4) {
- putch(c[(i >> (unsigned int)(pos)) & 0xFU]);
- }
+ puthx(i, 2U);
+}
+
+void puth4(unsigned int i) {
+ puthx(i, 4U);
}
void hexdump(const void *a, int l) {
diff --git a/panda/board/drivers/usb.h b/panda/board/drivers/usb.h
index abe88c7e1..2316f7220 100644
--- a/panda/board/drivers/usb.h
+++ b/panda/board/drivers/usb.h
@@ -823,9 +823,11 @@ void usb_irqhandler(void) {
// USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
// USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
} else if ((USBx_OUTEP(3)->DOEPINT) != 0) {
- puts("OUTEP3 error ");
- puth(USBx_OUTEP(3)->DOEPINT);
- puts("\n");
+ #ifdef DEBUG_USB
+ puts("OUTEP3 error ");
+ puth(USBx_OUTEP(3)->DOEPINT);
+ puts("\n");
+ #endif
} else {
// USBx_OUTEP(3)->DOEPINT is 0, ok to skip
}
diff --git a/panda/board/flash_h7.sh b/panda/board/flash_h7.sh
index 9b7566189..a7372c3f3 100755
--- a/panda/board/flash_h7.sh
+++ b/panda/board/flash_h7.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env sh
set -e
-PANDA_GEN3=1 scons -u
+scons -u
PYTHONPATH=.. python3 -c "from python import Panda; Panda().flash('obj/panda_h7.bin.signed')"
diff --git a/panda/board/main.c b/panda/board/main.c
index 5ace83530..9ac7bd90f 100644
--- a/panda/board/main.c
+++ b/panda/board/main.c
@@ -679,9 +679,10 @@ void tick_handler(void) {
}
#ifdef DEBUG
puts("** blink ");
- puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" ");
- puth(can_tx1_q.r_ptr); puts(" "); puth(can_tx1_q.w_ptr); puts(" ");
- puth(can_tx2_q.r_ptr); puts(" "); puth(can_tx2_q.w_ptr); puts("\n");
+ puts("rx:"); puth4(can_rx_q.r_ptr); puts("-"); puth4(can_rx_q.w_ptr); puts(" ");
+ puts("tx1:"); puth4(can_tx1_q.r_ptr); puts("-"); puth4(can_tx1_q.w_ptr); puts(" ");
+ puts("tx2:"); puth4(can_tx2_q.r_ptr); puts("-"); puth4(can_tx2_q.w_ptr); puts(" ");
+ puts("tx3:"); puth4(can_tx3_q.r_ptr); puts("-"); puth4(can_tx3_q.w_ptr); puts("\n");
#endif
// Tick drivers
diff --git a/panda/board/main_declarations.h b/panda/board/main_declarations.h
index bbfb1a126..c211e5988 100644
--- a/panda/board/main_declarations.h
+++ b/panda/board/main_declarations.h
@@ -2,6 +2,7 @@
void puts(const char *a);
void puth(unsigned int i);
void puth2(unsigned int i);
+void puth4(unsigned int i);
typedef struct board board;
typedef struct harness_configuration harness_configuration;
void can_flip_buses(uint8_t bus1, uint8_t bus2);
diff --git a/panda/board/pedal/main_declarations.h b/panda/board/pedal/main_declarations.h
index 2f2fe6fee..13bf7ebc0 100644
--- a/panda/board/pedal/main_declarations.h
+++ b/panda/board/pedal/main_declarations.h
@@ -2,6 +2,7 @@
void puts(const char *a);
void puth(unsigned int i);
void puth2(unsigned int i);
+void puth4(unsigned int i);
typedef struct board board;
typedef struct harness_configuration harness_configuration;
diff --git a/panda/board/recover_h7.sh b/panda/board/recover_h7.sh
index 737f954a9..1ca11884f 100755
--- a/panda/board/recover_h7.sh
+++ b/panda/board/recover_h7.sh
@@ -3,7 +3,7 @@ set -e
DFU_UTIL="dfu-util"
-PANDA_H7=1 scons -u
+scons -u
PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true
sleep 1
diff --git a/panda/board/safety/safety_honda.h b/panda/board/safety/safety_honda.h
index e810015e9..82a48d635 100644
--- a/panda/board/safety/safety_honda.h
+++ b/panda/board/safety/safety_honda.h
@@ -323,8 +323,12 @@ static const addr_checks* honda_bosch_giraffe_init(int16_t param) {
honda_hw = HONDA_BG_HW;
// Checking for alternate brake override from safety parameter
honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE);
+
// radar disabled so allow gas/brakes
+#ifdef ALLOW_DEBUG
honda_bosch_long = GET_FLAG(param, HONDA_PARAM_BOSCH_LONG);
+#endif
+
honda_rx_checks = (addr_checks){honda_addr_checks, HONDA_ADDR_CHECKS_LEN};
return &honda_rx_checks;
}
@@ -335,8 +339,12 @@ static const addr_checks* honda_bosch_harness_init(int16_t param) {
honda_hw = HONDA_BH_HW;
// Checking for alternate brake override from safety parameter
honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE);
+
// radar disabled so allow gas/brakes
+#ifdef ALLOW_DEBUG
honda_bosch_long = GET_FLAG(param, HONDA_PARAM_BOSCH_LONG);
+#endif
+
honda_rx_checks = (addr_checks){honda_bh_addr_checks, HONDA_BH_ADDR_CHECKS_LEN};
return &honda_rx_checks;
}
diff --git a/panda/board/safety/safety_hyundai.h b/panda/board/safety/safety_hyundai.h
index 286724c3b..6ed94c8ac 100644
--- a/panda/board/safety/safety_hyundai.h
+++ b/panda/board/safety/safety_hyundai.h
@@ -6,15 +6,28 @@ const int HYUNDAI_MAX_RATE_DOWN = 7;
const int HYUNDAI_DRIVER_TORQUE_ALLOWANCE = 50;
const int HYUNDAI_DRIVER_TORQUE_FACTOR = 2;
const int HYUNDAI_STANDSTILL_THRSLD = 30; // ~1kph
+
+const int HYUNDAI_MAX_ACCEL = 200; // 1/100 m/s2
+const int HYUNDAI_MIN_ACCEL = -350; // 1/100 m/s2
+
const CanMsg HYUNDAI_TX_MSGS[] = {
{832, 0, 8}, // LKAS11 Bus 0
{1265, 0, 4}, // CLU11 Bus 0
{1157, 0, 4}, // LFAHDA_MFC Bus 0
- // {1056, 0, 8}, // SCC11, Bus 0
- // {1057, 0, 8}, // SCC12, Bus 0
- // {1290, 0, 8}, // SCC13, Bus 0
- // {905, 0, 8}, // SCC14, Bus 0
- // {1186, 0, 8} // 4a2SCC, Bus 0
+ };
+
+const CanMsg HYUNDAI_LONG_TX_MSGS[] = {
+ {832, 0, 8}, // LKAS11 Bus 0
+ {1265, 0, 4}, // CLU11 Bus 0
+ {1157, 0, 4}, // LFAHDA_MFC Bus 0
+ {1056, 0, 8}, // SCC11 Bus 0
+ {1057, 0, 8}, // SCC12 Bus 0
+ {1290, 0, 8}, // SCC13 Bus 0
+ {905, 0, 8}, // SCC14 Bus 0
+ {1186, 0, 2}, // FRT_RADAR11 Bus 0
+ {909, 0, 8}, // FCA11 Bus 0
+ {1155, 0, 8}, // FCA12 Bus 0
+ {2000, 0, 8}, // radar UDS TX addr Bus 0 (for radar disable)
};
AddrCheckStruct hyundai_addr_checks[] = {
@@ -26,6 +39,15 @@ AddrCheckStruct hyundai_addr_checks[] = {
};
#define HYUNDAI_ADDR_CHECK_LEN (sizeof(hyundai_addr_checks) / sizeof(hyundai_addr_checks[0]))
+AddrCheckStruct hyundai_long_addr_checks[] = {
+ {.msg = {{608, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
+ {881, 0, 8, .expected_timestep = 10000U}, { 0 }}},
+ {.msg = {{902, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
+ {.msg = {{916, 0, 8, .check_checksum = true, .max_counter = 7U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
+ {.msg = {{1265, 0, 4, .check_checksum = false, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}},
+};
+#define HYUNDAI_LONG_ADDR_CHECK_LEN (sizeof(hyundai_long_addr_checks) / sizeof(hyundai_long_addr_checks[0]))
+
// older hyundai models have less checks due to missing counters and checksums
AddrCheckStruct hyundai_legacy_addr_checks[] = {
{.msg = {{608, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
@@ -38,10 +60,12 @@ AddrCheckStruct hyundai_legacy_addr_checks[] = {
const int HYUNDAI_PARAM_EV_GAS = 1;
const int HYUNDAI_PARAM_HYBRID_GAS = 2;
+const int HYUNDAI_PARAM_LONGITUDINAL = 4;
bool hyundai_legacy = false;
bool hyundai_ev_gas_signal = false;
bool hyundai_hybrid_gas_signal = false;
+bool hyundai_longitudinal = false;
addr_checks hyundai_rx_checks = {hyundai_addr_checks, HYUNDAI_ADDR_CHECK_LEN};
@@ -57,6 +81,8 @@ static uint8_t hyundai_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
cnt = (GET_BYTE(to_push, 1) >> 5) & 0x7;
} else if (addr == 1057) {
cnt = GET_BYTE(to_push, 7) & 0xF;
+ } else if (addr == 1265) {
+ cnt = (GET_BYTE(to_push, 3) >> 4) & 0xF;
} else {
cnt = 0;
}
@@ -132,17 +158,35 @@ static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
update_sample(&torque_driver, torque_driver_new);
}
- // enter controls on rising edge of ACC, exit controls on ACC off
- if (addr == 1057) {
- // 2 bits: 13-14
- int cruise_engaged = (GET_BYTES_04(to_push) >> 13) & 0x3;
- if (cruise_engaged && !cruise_engaged_prev) {
- controls_allowed = 1;
+ if (hyundai_longitudinal) {
+ // ACC steering wheel buttons
+ if (addr == 1265) {
+ int button = GET_BYTE(to_push, 0) & 0x7;
+ switch (button) {
+ case 1: // resume
+ case 2: // set
+ controls_allowed = 1;
+ break;
+ case 4: // cancel
+ controls_allowed = 0;
+ break;
+ default:
+ break; // any other button is irrelevant
+ }
}
- if (!cruise_engaged) {
- controls_allowed = 0;
+ } else {
+ // enter controls on rising edge of ACC, exit controls on ACC off
+ if (addr == 1057) {
+ // 2 bits: 13-14
+ int cruise_engaged = (GET_BYTES_04(to_push) >> 13) & 0x3;
+ if (cruise_engaged && !cruise_engaged_prev) {
+ controls_allowed = 1;
+ }
+ if (!cruise_engaged) {
+ controls_allowed = 0;
+ }
+ cruise_engaged_prev = cruise_engaged;
}
- cruise_engaged_prev = cruise_engaged;
}
// read gas pressed signal
@@ -167,7 +211,14 @@ static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
brake_pressed = (GET_BYTE(to_push, 6) >> 7) != 0;
}
- generic_rx_checks((addr == 832));
+ bool stock_ecu_detected = (addr == 832);
+
+ // If openpilot is controlling longitudinal we need to ensure the radar is turned off
+ // Enforce by checking we don't see SCC12
+ if (hyundai_longitudinal && (addr == 1057)) {
+ stock_ecu_detected = true;
+ }
+ generic_rx_checks(stock_ecu_detected);
}
return valid;
}
@@ -177,14 +228,53 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
- if (!msg_allowed(to_send, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]))) {
- tx = 0;
+ if (hyundai_longitudinal) {
+ tx = msg_allowed(to_send, HYUNDAI_LONG_TX_MSGS, sizeof(HYUNDAI_LONG_TX_MSGS)/sizeof(HYUNDAI_LONG_TX_MSGS[0]));
+ } else {
+ tx = msg_allowed(to_send, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]));
}
if (relay_malfunction) {
tx = 0;
}
+ // FCA11: Block any potential actuation
+ if (addr == 909) {
+ int CR_VSM_DecCmd = GET_BYTE(to_send, 1);
+ int FCA_CmdAct = (GET_BYTE(to_send, 2) >> 5) & 1;
+ int CF_VSM_DecCmdAct = (GET_BYTE(to_send, 3) >> 7) & 1;
+
+ if ((CR_VSM_DecCmd != 0) || (FCA_CmdAct != 0) || (CF_VSM_DecCmdAct != 0)) {
+ tx = 0;
+ }
+ }
+
+ // ACCEL: safety check
+ if (addr == 1057) {
+ int desired_accel_raw = (((GET_BYTE(to_send, 4) & 0x7) << 8) | GET_BYTE(to_send, 3)) - 1023;
+ int desired_accel_val = ((GET_BYTE(to_send, 5) << 3) | (GET_BYTE(to_send, 4) >> 5)) - 1023;
+
+ int aeb_decel_cmd = GET_BYTE(to_send, 2);
+ int aeb_req = (GET_BYTE(to_send, 6) >> 6) & 1;
+
+ bool violation = 0;
+
+ if (!controls_allowed) {
+ if ((desired_accel_raw != 0) || (desired_accel_val != 0)) {
+ violation = 1;
+ }
+ }
+ violation |= max_limit_check(desired_accel_raw, HYUNDAI_MAX_ACCEL, HYUNDAI_MIN_ACCEL);
+ violation |= max_limit_check(desired_accel_val, HYUNDAI_MAX_ACCEL, HYUNDAI_MIN_ACCEL);
+
+ violation |= (aeb_decel_cmd != 0);
+ violation |= (aeb_req != 0);
+
+ if (violation) {
+ tx = 0;
+ }
+ }
+
// LKA STEER: safety check
if (addr == 832) {
int desired_torque = ((GET_BYTES_04(to_send) >> 16) & 0x7ff) - 1024;
@@ -232,6 +322,13 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
}
+ // UDS: Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address
+ if (addr == 2000) {
+ if ((GET_BYTES_04(to_send) != 0x00803E02) || (GET_BYTES_48(to_send) != 0x0)) {
+ tx = 0;
+ }
+ }
+
// FORCE CANCEL: safety check only relevant when spamming the cancel button.
// ensuring that only the cancel button press is sent (VAL 4) when controls are off.
// This avoids unintended engagements while still allowing resume spam
@@ -268,7 +365,16 @@ static const addr_checks* hyundai_init(int16_t param) {
hyundai_legacy = false;
hyundai_ev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_EV_GAS);
hyundai_hybrid_gas_signal = !hyundai_ev_gas_signal && GET_FLAG(param, HYUNDAI_PARAM_HYBRID_GAS);
- hyundai_rx_checks = (addr_checks){hyundai_addr_checks, HYUNDAI_ADDR_CHECK_LEN};
+
+#ifdef ALLOW_DEBUG
+ hyundai_longitudinal = GET_FLAG(param, HYUNDAI_PARAM_LONGITUDINAL);
+#endif
+
+ if (hyundai_longitudinal) {
+ hyundai_rx_checks = (addr_checks){hyundai_long_addr_checks, HYUNDAI_LONG_ADDR_CHECK_LEN};
+ } else {
+ hyundai_rx_checks = (addr_checks){hyundai_addr_checks, HYUNDAI_ADDR_CHECK_LEN};
+ }
return &hyundai_rx_checks;
}
@@ -277,6 +383,7 @@ static const addr_checks* hyundai_legacy_init(int16_t param) {
relay_malfunction_reset();
hyundai_legacy = true;
+ hyundai_longitudinal = false;
hyundai_ev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_EV_GAS);
hyundai_hybrid_gas_signal = !hyundai_ev_gas_signal && GET_FLAG(param, HYUNDAI_PARAM_HYBRID_GAS);
hyundai_rx_checks = (addr_checks){hyundai_legacy_addr_checks, HYUNDAI_LEGACY_ADDR_CHECK_LEN};
diff --git a/panda/board/safety/safety_subaru.h b/panda/board/safety/safety_subaru.h
index faff35a3d..cde90980c 100644
--- a/panda/board/safety/safety_subaru.h
+++ b/panda/board/safety/safety_subaru.h
@@ -18,8 +18,8 @@ const CanMsg SUBARU_TX_MSGS[] = {{0x122, 0, 8}, {0x221, 0, 8}, {0x322, 0, 8}};
AddrCheckStruct subaru_addr_checks[] = {
{.msg = {{ 0x40, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
{.msg = {{0x119, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}},
- {.msg = {{0x139, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}},
{.msg = {{0x13a, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}},
+ {.msg = {{0x13c, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}},
{.msg = {{0x240, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 50000U}, { 0 }, { 0 }}},
};
#define SUBARU_ADDR_CHECK_LEN (sizeof(subaru_addr_checks) / sizeof(subaru_addr_checks[0]))
@@ -89,8 +89,8 @@ static int subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
vehicle_moving = subaru_speed > SUBARU_STANDSTILL_THRSLD;
}
- if (addr == 0x139) {
- brake_pressed = (GET_BYTES_48(to_push) & 0xFFF0) > 0;
+ if (addr == 0x13c) {
+ brake_pressed = ((GET_BYTE(to_push, 7) >> 6) & 1);
}
if (addr == 0x40) {
diff --git a/panda/board/safety/safety_volkswagen.h b/panda/board/safety/safety_volkswagen.h
index 67372757d..3332fe20a 100644
--- a/panda/board/safety/safety_volkswagen.h
+++ b/panda/board/safety/safety_volkswagen.h
@@ -37,7 +37,7 @@ addr_checks volkswagen_mqb_rx_checks = {volkswagen_mqb_addr_checks, VOLKSWAGEN_M
#define MSG_MOTOR_2 0x288 // RX from ECU, for CC state and brake switch state
#define MSG_MOTOR_3 0x380 // RX from ECU, for driver throttle input
#define MSG_GRA_NEU 0x38A // TX by OP, ACC control buttons for cancel/resume
-#define MSG_BREMSE_3 0x4A0 // RX from ABS, for wheel speeds
+#define MSG_BREMSE_1 0x1A0 // RX from ABS, for ego speed
#define MSG_LDW_1 0x5BE // TX by OP, Lane line recognition and text alerts
// Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration
@@ -48,7 +48,7 @@ AddrCheckStruct volkswagen_pq_addr_checks[] = {
{.msg = {{MSG_LENKHILFE_3, 0, 6, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
{.msg = {{MSG_MOTOR_2, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 20000U}, { 0 }, { 0 }}},
{.msg = {{MSG_MOTOR_3, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
- {.msg = {{MSG_BREMSE_3, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
+ {.msg = {{MSG_BREMSE_1, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
};
#define VOLKSWAGEN_PQ_ADDR_CHECKS_LEN (sizeof(volkswagen_pq_addr_checks) / sizeof(volkswagen_pq_addr_checks[0]))
addr_checks volkswagen_pq_rx_checks = {volkswagen_pq_addr_checks, VOLKSWAGEN_PQ_ADDR_CHECKS_LEN};
@@ -208,15 +208,12 @@ static int volkswagen_pq_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
if (valid && (GET_BUS(to_push) == 0)) {
int addr = GET_ADDR(to_push);
- // Update in-motion state by sampling front wheel speeds
- // Signal: Bremse_3.Radgeschw__VL_4_1 (front left)
- // Signal: Bremse_3.Radgeschw__VR_4_1 (front right)
- if (addr == MSG_BREMSE_3) {
- int wheel_speed_fl = (GET_BYTE(to_push, 0) | (GET_BYTE(to_push, 1) << 8)) >> 1;
- int wheel_speed_fr = (GET_BYTE(to_push, 2) | (GET_BYTE(to_push, 3) << 8)) >> 1;
- // Check for average front speed in excess of 0.3m/s, 1.08km/h
- // DBC speed scale 0.01: 0.3m/s = 108, sum both wheels to compare
- vehicle_moving = (wheel_speed_fl + wheel_speed_fr) > 216;
+ // Update in-motion state from speed value.
+ // Signal: Bremse_1.Geschwindigkeit_neu__Bremse_1_
+ if (addr == MSG_BREMSE_1) {
+ int speed = ((GET_BYTE(to_push, 2) & 0xFE) >> 1) | (GET_BYTE(to_push, 3) << 7);
+ // DBC speed scale 0.01: 0.3m/s = 108.
+ vehicle_moving = speed > 108;
}
// Update driver input torque samples
diff --git a/panda/examples/query_fw_versions.py b/panda/examples/query_fw_versions.py
index 6795f62c2..4132959be 100755
--- a/panda/examples/query_fw_versions.py
+++ b/panda/examples/query_fw_versions.py
@@ -6,7 +6,7 @@ from panda.python.uds import UdsClient, MessageTimeoutError, NegativeResponseErr
if __name__ == "__main__":
parser = argparse.ArgumentParser()
- parser.add_argument('--rxoffset', default="0x8")
+ parser.add_argument('--rxoffset', default="")
parser.add_argument('--nonstandard', action='store_true')
parser.add_argument('--debug', action='store_true')
parser.add_argument('--addr')
@@ -32,7 +32,6 @@ if __name__ == "__main__":
panda = Panda()
panda.set_safety_mode(Panda.SAFETY_ELM327)
- panda.set_power_save(0)
print("querying addresses ...")
with tqdm(addrs) as t:
for addr in t:
@@ -40,8 +39,11 @@ if __name__ == "__main__":
if addr == 0x7df or addr == 0x18db33f1:
continue
t.set_description(hex(addr))
+ panda.send_heartbeat()
- uds_client = UdsClient(panda, addr, addr + int(args.rxoffset, base=16), bus=1 if panda.has_obd() else 0, timeout=0.2, debug=args.debug)
+ bus = 1 if panda.has_obd() else 0
+ rx_addr = addr + int(args.rxoffset, base=16) if args.rxoffset else None
+ uds_client = UdsClient(panda, addr, rx_addr, bus, timeout=0.2, debug=args.debug)
# Check for anything alive at this address, and switch to the highest
# available diagnostic session without security access
try:
diff --git a/panda/python/__init__.py b/panda/python/__init__.py
index 5d0d15186..be9ef492d 100644
--- a/panda/python/__init__.py
+++ b/panda/python/__init__.py
@@ -150,6 +150,7 @@ class Panda(object):
FLAG_HONDA_ALT_BRAKE = 1
FLAG_HONDA_BOSCH_LONG = 2
+ FLAG_HYUNDAI_LONG = 4
def __init__(self, serial=None, claim=True):
self._serial = serial
@@ -452,10 +453,11 @@ class Panda(object):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xda, int(bootmode), 0, b'')
time.sleep(0.2)
- def set_safety_mode(self, mode=SAFETY_SILENT, disable_heartbeat=True):
+ def set_safety_mode(self, mode=SAFETY_SILENT, disable_checks=True):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xdc, mode, 0, b'')
- if disable_heartbeat:
+ if disable_checks:
self.set_heartbeat_disabled()
+ self.set_power_save(0)
def set_can_forwarding(self, from_bus, to_bus):
# TODO: This feature may not work correctly with saturated buses
diff --git a/panda/python/flash_release.py b/panda/python/flash_release.py
index 6e77d6a7f..ae50e6dc0 100755
--- a/panda/python/flash_release.py
+++ b/panda/python/flash_release.py
@@ -34,7 +34,7 @@ def flash_release(path=None, st_serial=None):
zf = ZipFile(path)
zf.printdir()
- version = zf.read("version").decode()
+ version = zf.read("version").decode().strip()
status("0. Preparing to flash " + str(version))
code_bootstub = zf.read("bootstub.panda.bin")
diff --git a/panda/python/uds.py b/panda/python/uds.py
index 5106e6de8..48fcf5322 100644
--- a/panda/python/uds.py
+++ b/panda/python/uds.py
@@ -4,6 +4,7 @@ import struct
from collections import deque
from typing import Callable, NamedTuple, Tuple, List, Deque, Generator, Optional, cast
from enum import IntEnum
+from functools import partial
class SERVICE_TYPE(IntEnum):
DIAGNOSTIC_SESSION_CONTROL = 0x10
@@ -376,39 +377,43 @@ class IsoTpMessage():
self.rx_done = False
if self.debug:
- print(f"ISO-TP: REQUEST - 0x{bytes.hex(self.tx_dat)}")
+ print(f"ISO-TP: REQUEST - {hex(self._can_client.tx_addr)} 0x{bytes.hex(self.tx_dat)}")
self._tx_first_frame()
def _tx_first_frame(self) -> None:
if self.tx_len < self.max_len:
# single frame (send all bytes)
if self.debug:
- print("ISO-TP: TX - single frame")
+ print(f"ISO-TP: TX - single frame - {hex(self._can_client.tx_addr)}")
msg = (bytes([self.tx_len]) + self.tx_dat).ljust(self.max_len, b"\x00")
self.tx_done = True
else:
# first frame (send first 6 bytes)
if self.debug:
- print("ISO-TP: TX - first frame")
+ print(f"ISO-TP: TX - first frame - {hex(self._can_client.tx_addr)}")
msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:self.max_len - 2]).ljust(self.max_len - 2, b"\x00")
self._can_client.send([msg])
- def recv(self) -> Optional[bytes]:
- start_time = time.time()
+ def recv(self, timeout=None) -> Optional[bytes]:
+ if timeout is None:
+ timeout = self.timeout
+
+ start_time = time.monotonic()
try:
while True:
for msg in self._can_client.recv():
self._isotp_rx_next(msg)
+ start_time = time.monotonic()
if self.tx_done and self.rx_done:
return self.rx_dat
# no timeout indicates non-blocking
- if self.timeout == 0:
+ if timeout == 0:
return None
- if time.time() - start_time > self.timeout:
+ if time.monotonic() - start_time > timeout:
raise MessageTimeoutError("timeout waiting for response")
finally:
if self.debug and self.rx_dat:
- print(f"ISO-TP: RESPONSE - 0x{bytes.hex(self.rx_dat)}")
+ print(f"ISO-TP: RESPONSE - {hex(self._can_client.rx_addr)} 0x{bytes.hex(self.rx_dat)}")
def _isotp_rx_next(self, rx_data: bytes) -> None:
# single rx_frame
@@ -418,7 +423,7 @@ class IsoTpMessage():
self.rx_idx = 0
self.rx_done = True
if self.debug:
- print(f"ISO-TP: RX - single frame - idx={self.rx_idx} done={self.rx_done}")
+ print(f"ISO-TP: RX - single frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}")
return
# first rx_frame
@@ -428,9 +433,9 @@ class IsoTpMessage():
self.rx_idx = 0
self.rx_done = False
if self.debug:
- print(f"ISO-TP: RX - first frame - idx={self.rx_idx} done={self.rx_done}")
+ print(f"ISO-TP: RX - first frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}")
if self.debug:
- print("ISO-TP: TX - flow control continue")
+ print(f"ISO-TP: TX - flow control continue - {hex(self._can_client.tx_addr)}")
# send flow control message (send all bytes)
msg = b"\x30\x00\x00".ljust(self.max_len, b"\x00")
self._can_client.send([msg])
@@ -446,7 +451,7 @@ class IsoTpMessage():
if self.rx_len == len(self.rx_dat):
self.rx_done = True
if self.debug:
- print(f"ISO-TP: RX - consecutive frame - idx={self.rx_idx} done={self.rx_done}")
+ print(f"ISO-TP: RX - consecutive frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}")
return
# flow control
@@ -456,7 +461,7 @@ class IsoTpMessage():
assert rx_data[0] == 0x30 or rx_data[0] == 0x31, "isotp - rx: flow-control transfer state indicator invalid"
if rx_data[0] == 0x30:
if self.debug:
- print("ISO-TP: RX - flow control continue")
+ print(f"ISO-TP: RX - flow control continue - {hex(self._can_client.tx_addr)}")
delay_ts = rx_data[2] & 0x7F
# scale is 1 milliseconds if first bit == 0, 100 micro seconds if first bit == 1
delay_div = 1000. if rx_data[2] & 0x80 == 0 else 10000.
@@ -478,11 +483,11 @@ class IsoTpMessage():
if end >= self.tx_len:
self.tx_done = True
if self.debug:
- print(f"ISO-TP: TX - consecutive frame - idx={self.tx_idx} done={self.tx_done}")
+ print(f"ISO-TP: TX - consecutive frame - {hex(self._can_client.tx_addr)} idx={self.tx_idx} done={self.tx_done}")
elif rx_data[0] == 0x31:
# wait (do nothing until next flow control message)
if self.debug:
- print("ISO-TP: TX - flow control wait")
+ print(f"ISO-TP: TX - flow control wait - {hex(self._can_client.tx_addr)}")
FUNCTIONAL_ADDRS = [0x7DF, 0x18DB33F1]
@@ -503,13 +508,16 @@ def get_rx_addr_for_tx_addr(tx_addr, rx_offset=0x8):
class UdsClient():
- def __init__(self, panda, tx_addr: int, rx_addr: int = None, bus: int = 0, timeout: float = 1, debug: bool = False):
+ def __init__(self, panda, tx_addr: int, rx_addr: int = None, bus: int = 0, timeout: float = 1, debug: bool = False,
+ tx_timeout: float = 1, response_pending_timeout: float = 10):
self.bus = bus
self.tx_addr = tx_addr
self.rx_addr = rx_addr if rx_addr is not None else get_rx_addr_for_tx_addr(tx_addr)
self.timeout = timeout
self.debug = debug
- self._can_client = CanClient(panda.can_send, panda.can_recv, self.tx_addr, self.rx_addr, self.bus, debug=self.debug)
+ can_send_with_timeout = partial(panda.can_send, timeout=int(tx_timeout*1000))
+ self._can_client = CanClient(can_send_with_timeout, panda.can_recv, self.tx_addr, self.rx_addr, self.bus, debug=self.debug)
+ self.response_pending_timeout = response_pending_timeout
# generic uds request
def _uds_request(self, service_type: SERVICE_TYPE, subfunction: int = None, data: bytes = None) -> bytes:
@@ -522,12 +530,15 @@ class UdsClient():
# send request, wait for response
isotp_msg = IsoTpMessage(self._can_client, self.timeout, self.debug)
isotp_msg.send(req)
+ response_pending = False
while True:
- resp = isotp_msg.recv()
+ timeout = self.response_pending_timeout if response_pending else self.timeout
+ resp = isotp_msg.recv(timeout)
if resp is None:
continue
+ response_pending = False
resp_sid = resp[0] if len(resp) > 0 else None
# negative response
@@ -544,6 +555,7 @@ class UdsClient():
error_desc = resp[3:].hex()
# wait for another message if response pending
if error_code == 0x78:
+ response_pending = True
if self.debug:
print("UDS-RX: response pending")
continue
@@ -654,7 +666,7 @@ class UdsClient():
resp = self._uds_request(SERVICE_TYPE.READ_DATA_BY_IDENTIFIER, subfunction=None, data=data)
resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None
if resp_id != data_identifier_type:
- raise ValueError('invalid response data identifier: {}'.format(hex(resp_id)))
+ raise ValueError('invalid response data identifier: {} expected: {}'.format(hex(resp_id), hex(data_identifier_type)))
return resp[2:]
def read_memory_by_address(self, memory_address: int, memory_size: int, memory_address_bytes: int = 4, memory_size_bytes: int = 1):
diff --git a/phonelibs/qpoases/EXAMPLES/example1.cpp b/phonelibs/qpoases/EXAMPLES/example1.cpp
deleted file mode 100644
index 92b47fc93..000000000
--- a/phonelibs/qpoases/EXAMPLES/example1.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file EXAMPLES/example1.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Very simple example for testing qpOASES (using QProblem class).
- */
-
-
-#include
-
-
-/** Example for qpOASES main function using the QProblem class. */
-int main( )
-{
- /* Setup data of first QP. */
- real_t H[2*2] = { 1.0, 0.0, 0.0, 0.5 };
- real_t A[1*2] = { 1.0, 1.0 };
- real_t g[2] = { 1.5, 1.0 };
- real_t lb[2] = { 0.5, -2.0 };
- real_t ub[2] = { 5.0, 2.0 };
- real_t lbA[1] = { -1.0 };
- real_t ubA[1] = { 2.0 };
-
- /* Setup data of second QP. */
- real_t g_new[2] = { 1.0, 1.5 };
- real_t lb_new[2] = { 0.0, -1.0 };
- real_t ub_new[2] = { 5.0, -0.5 };
- real_t lbA_new[1] = { -2.0 };
- real_t ubA_new[1] = { 1.0 };
-
-
- /* Setting up QProblem object. */
- QProblem example( 2,1 );
-
- /* Solve first QP. */
- int nWSR = 10;
- example.init( H,g,A,lb,ub,lbA,ubA, nWSR,0 );
-
- /* Solve second QP. */
- nWSR = 10;
- example.hotstart( g_new,lb_new,ub_new,lbA_new,ubA_new, nWSR,0 );
-
- return 0;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/EXAMPLES/example1b.cpp b/phonelibs/qpoases/EXAMPLES/example1b.cpp
deleted file mode 100644
index 331f19d8d..000000000
--- a/phonelibs/qpoases/EXAMPLES/example1b.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file EXAMPLES/example1b.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3
- * \date 2007-2008
- *
- * Very simple example for testing qpOASES using the QProblemB class.
- */
-
-
-#include
-
-
-/** Example for qpOASES main function using the QProblemB class. */
-int main( )
-{
- /* Setup data of first QP. */
- real_t H[2*2] = { 1.0, 0.0, 0.0, 0.5 };
- real_t g[2] = { 1.5, 1.0 };
- real_t lb[2] = { 0.5, -2.0 };
- real_t ub[2] = { 5.0, 2.0 };
-
- /* Setup data of second QP. */
- real_t g_new[2] = { 1.0, 1.5 };
- real_t lb_new[2] = { 0.0, -1.0 };
- real_t ub_new[2] = { 5.0, -0.5 };
-
-
- /* Setting up QProblemB object. */
- QProblemB example( 2 );
-
- /* Solve first QP. */
- int nWSR = 10;
- example.init( H,g,lb,ub, nWSR,0 );
-
- /* Solve second QP. */
- nWSR = 10;
- example.hotstart( g_new,lb_new,ub_new, nWSR,0 );
-
- return 0;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/Bounds.hpp b/phonelibs/qpoases/INCLUDE/Bounds.hpp
deleted file mode 100644
index 7260756da..000000000
--- a/phonelibs/qpoases/INCLUDE/Bounds.hpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/Bounds.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the Bounds class designed to manage working sets of
- * bounds within a QProblem.
- */
-
-
-#ifndef QPOASES_BOUNDS_HPP
-#define QPOASES_BOUNDS_HPP
-
-
-#include
-
-
-
-/** This class manages working sets of bounds by storing
- * index sets and other status information.
- *
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- */
-class Bounds : public SubjectTo
-{
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- Bounds( );
-
- /** Copy constructor (deep copy). */
- Bounds( const Bounds& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~Bounds( );
-
- /** Assignment operator (deep copy). */
- Bounds& operator=( const Bounds& rhs /**< Rhs object. */
- );
-
-
- /** Pseudo-constructor takes the number of bounds.
- * \return SUCCESSFUL_RETURN */
- returnValue init( int n /**< Number of bounds. */
- );
-
-
- /** Initially adds number of a new (i.e. not yet in the list) bound to
- * given index set.
- * \return SUCCESSFUL_RETURN \n
- RET_SETUP_BOUND_FAILED \n
- RET_INDEX_OUT_OF_BOUNDS \n
- RET_INVALID_ARGUMENTS */
- returnValue setupBound( int _number, /**< Number of new bound. */
- SubjectToStatus _status /**< Status of new bound. */
- );
-
- /** Initially adds all numbers of new (i.e. not yet in the list) bounds to
- * to the index set of free bounds; the order depends on the SujectToType
- * of each index.
- * \return SUCCESSFUL_RETURN \n
- RET_SETUP_BOUND_FAILED */
- returnValue setupAllFree( );
-
-
- /** Moves index of a bound from index list of fixed to that of free bounds.
- * \return SUCCESSFUL_RETURN \n
- RET_MOVING_BOUND_FAILED \n
- RET_INDEX_OUT_OF_BOUNDS */
- returnValue moveFixedToFree( int _number /**< Number of bound to be freed. */
- );
-
- /** Moves index of a bound from index list of free to that of fixed bounds.
- * \return SUCCESSFUL_RETURN \n
- RET_MOVING_BOUND_FAILED \n
- RET_INDEX_OUT_OF_BOUNDS */
- returnValue moveFreeToFixed( int _number, /**< Number of bound to be fixed. */
- SubjectToStatus _status /**< Status of bound to be fixed. */
- );
-
- /** Swaps the indices of two free bounds within the index set.
- * \return SUCCESSFUL_RETURN \n
- RET_SWAPINDEX_FAILED */
- returnValue swapFree( int number1, /**< Number of first constraint or bound. */
- int number2 /**< Number of second constraint or bound. */
- );
-
-
- /** Returns number of variables.
- * \return Number of variables. */
- inline int getNV( ) const;
-
- /** Returns number of implicitly fixed variables.
- * \return Number of implicitly fixed variables. */
- inline int getNFV( ) const;
-
- /** Returns number of bounded (but possibly free) variables.
- * \return Number of bounded (but possibly free) variables. */
- inline int getNBV( ) const;
-
- /** Returns number of unbounded variables.
- * \return Number of unbounded variables. */
- inline int getNUV( ) const;
-
-
- /** Sets number of implicitly fixed variables.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setNFV( int n /**< Number of implicitly fixed variables. */
- );
-
- /** Sets number of bounded (but possibly free) variables.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setNBV( int n /**< Number of bounded (but possibly free) variables. */
- );
-
- /** Sets number of unbounded variables.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setNUV( int n /**< Number of unbounded variables */
- );
-
-
- /** Returns number of free variables.
- * \return Number of free variables. */
- inline int getNFR( );
-
- /** Returns number of fixed variables.
- * \return Number of fixed variables. */
- inline int getNFX( );
-
-
- /** Returns a pointer to free variables index list.
- * \return Pointer to free variables index list. */
- inline Indexlist* getFree( );
-
- /** Returns a pointer to fixed variables index list.
- * \return Pointer to fixed variables index list. */
- inline Indexlist* getFixed( );
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- int nV; /**< Number of variables (nV = nFV + nBV + nUV). */
- int nFV; /**< Number of implicitly fixed variables. */
- int nBV; /**< Number of bounded (but possibly free) variables. */
- int nUV; /**< Number of unbounded variables. */
-
- Indexlist free; /**< Index list of free variables. */
- Indexlist fixed; /**< Index list of fixed variables. */
-};
-
-#include
-
-#endif /* QPOASES_BOUNDS_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/Constants.hpp b/phonelibs/qpoases/INCLUDE/Constants.hpp
deleted file mode 100644
index 92ee81229..000000000
--- a/phonelibs/qpoases/INCLUDE/Constants.hpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/Constants.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2008
- *
- * Definition of all global constants.
- */
-
-
-#ifndef QPOASES_CONSTANTS_HPP
-#define QPOASES_CONSTANTS_HPP
-
-#ifndef QPOASES_CUSTOM_INTERFACE
-#include "acado_qpoases_interface.hpp"
-#else
- #define XSTR(x) #x
- #define STR(x) XSTR(x)
- #include STR(QPOASES_CUSTOM_INTERFACE)
-#endif
-
-/** Maximum number of variables within a QP formulation.
- Note: this value has to be positive! */
-const int NVMAX = QPOASES_NVMAX;
-
-/** Maximum number of constraints within a QP formulation.
- Note: this value has to be positive! */
-const int NCMAX = QPOASES_NCMAX;
-
-/** Redefinition of NCMAX used for memory allocation, to avoid zero sized arrays
- and compiler errors. */
-const int NCMAX_ALLOC = (NCMAX == 0) ? 1 : NCMAX;
-
-/**< Maximum number of working set recalculations.
- Note: this value has to be positive! */
-const int NWSRMAX = QPOASES_NWSRMAX;
-
-/** Desired KKT tolerance of QP solution; a warning RET_INACCURATE_SOLUTION is
- * issued if this tolerance is not met.
- * Note: this value has to be positive! */
-const real_t DESIREDACCURACY = (real_t) 1.0e-3;
-
-/** Critical KKT tolerance of QP solution; an error is issued if this
- * tolerance is not met.
- * Note: this value has to be positive! */
-const real_t CRITICALACCURACY = (real_t) 1.0e-2;
-
-
-
-/** Numerical value of machine precision (min eps, s.t. 1+eps > 1).
- Note: this value has to be positive! */
-const real_t EPS = (real_t) QPOASES_EPS;
-
-/** Numerical value of zero (for situations in which it would be
- * unreasonable to compare with 0.0).
- * Note: this value has to be positive! */
-const real_t ZERO = (real_t) 1.0e-50;
-
-/** Numerical value of infinity (e.g. for non-existing bounds).
- * Note: this value has to be positive! */
-const real_t INFTY = (real_t) 1.0e12;
-
-
-/** Lower/upper (constraints') bound tolerance (an inequality constraint
- * whose lower and upper bound differ by less than BOUNDTOL is regarded
- * to be an equality constraint).
- * Note: this value has to be positive! */
-const real_t BOUNDTOL = (real_t) 1.0e-10;
-
-/** Offset for relaxing (constraints') bounds at beginning of an initial homotopy.
- * Note: this value has to be positive! */
-const real_t BOUNDRELAXATION = (real_t) 1.0e3;
-
-
-/** Factor that determines physical lengths of index lists.
- * Note: this value has to be greater than 1! */
-const int INDEXLISTFACTOR = 5;
-
-
-#endif /* QPOASES_CONSTANTS_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/Constraints.hpp b/phonelibs/qpoases/INCLUDE/Constraints.hpp
deleted file mode 100644
index 899167942..000000000
--- a/phonelibs/qpoases/INCLUDE/Constraints.hpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/Constraints.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the Constraints class designed to manage working sets of
- * constraints within a QProblem.
- */
-
-
-#ifndef QPOASES_CONSTRAINTS_HPP
-#define QPOASES_CONSTRAINTS_HPP
-
-
-#include
-
-
-
-/** This class manages working sets of constraints by storing
- * index sets and other status information.
- *
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- */
-class Constraints : public SubjectTo
-{
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- Constraints( );
-
- /** Copy constructor (deep copy). */
- Constraints( const Constraints& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~Constraints( );
-
- /** Assignment operator (deep copy). */
- Constraints& operator=( const Constraints& rhs /**< Rhs object. */
- );
-
-
- /** Pseudo-constructor takes the number of constraints.
- * \return SUCCESSFUL_RETURN */
- returnValue init( int n /**< Number of constraints. */
- );
-
-
- /** Initially adds number of a new (i.e. not yet in the list) constraint to
- * a given index set.
- * \return SUCCESSFUL_RETURN \n
- RET_SETUP_CONSTRAINT_FAILED \n
- RET_INDEX_OUT_OF_BOUNDS \n
- RET_INVALID_ARGUMENTS */
- returnValue setupConstraint( int _number, /**< Number of new constraint. */
- SubjectToStatus _status /**< Status of new constraint. */
- );
-
- /** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to
- * to the index set of inactive constraints; the order depends on the SujectToType
- * of each index. Only disabled constraints are added to index set of disabled constraints!
- * \return SUCCESSFUL_RETURN \n
- RET_SETUP_CONSTRAINT_FAILED */
- returnValue setupAllInactive( );
-
-
- /** Moves index of a constraint from index list of active to that of inactive constraints.
- * \return SUCCESSFUL_RETURN \n
- RET_MOVING_CONSTRAINT_FAILED */
- returnValue moveActiveToInactive( int _number /**< Number of constraint to become inactive. */
- );
-
- /** Moves index of a constraint from index list of inactive to that of active constraints.
- * \return SUCCESSFUL_RETURN \n
- RET_MOVING_CONSTRAINT_FAILED */
- returnValue moveInactiveToActive( int _number, /**< Number of constraint to become active. */
- SubjectToStatus _status /**< Status of constraint to become active. */
- );
-
-
- /** Returns the number of constraints.
- * \return Number of constraints. */
- inline int getNC( ) const;
-
- /** Returns the number of implicit equality constraints.
- * \return Number of implicit equality constraints. */
- inline int getNEC( ) const;
-
- /** Returns the number of "real" inequality constraints.
- * \return Number of "real" inequality constraints. */
- inline int getNIC( ) const;
-
- /** Returns the number of unbounded constraints (i.e. without any bounds).
- * \return Number of unbounded constraints (i.e. without any bounds). */
- inline int getNUC( ) const;
-
-
- /** Sets number of implicit equality constraints.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setNEC( int n /**< Number of implicit equality constraints. */
- );
-
- /** Sets number of "real" inequality constraints.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setNIC( int n /**< Number of "real" inequality constraints. */
- );
-
- /** Sets number of unbounded constraints (i.e. without any bounds).
- * \return SUCCESSFUL_RETURN */
- inline returnValue setNUC( int n /**< Number of unbounded constraints (i.e. without any bounds). */
- );
-
-
- /** Returns the number of active constraints.
- * \return Number of constraints. */
- inline int getNAC( );
-
- /** Returns the number of inactive constraints.
- * \return Number of constraints. */
- inline int getNIAC( );
-
-
- /** Returns a pointer to active constraints index list.
- * \return Pointer to active constraints index list. */
- inline Indexlist* getActive( );
-
- /** Returns a pointer to inactive constraints index list.
- * \return Pointer to inactive constraints index list. */
- inline Indexlist* getInactive( );
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- int nC; /**< Number of constraints (nC = nEC + nIC + nUC). */
- int nEC; /**< Number of implicit equality constraints. */
- int nIC; /**< Number of "real" inequality constraints. */
- int nUC; /**< Number of unbounded constraints (i.e. without any bounds). */
-
- Indexlist active; /**< Index list of active constraints. */
- Indexlist inactive; /**< Index list of inactive constraints. */
-};
-
-
-#include
-
-#endif /* QPOASES_CONSTRAINTS_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/CyclingManager.hpp b/phonelibs/qpoases/INCLUDE/CyclingManager.hpp
deleted file mode 100644
index b4410b106..000000000
--- a/phonelibs/qpoases/INCLUDE/CyclingManager.hpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/CyclingManager.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the CyclingManager class designed to detect
- * and handle possible cycling during QP iterations.
- */
-
-
-#ifndef QPOASES_CYCLINGMANAGER_HPP
-#define QPOASES_CYCLINGMANAGER_HPP
-
-
-#include
-
-
-
-/** This class is intended to detect and handle possible cycling during QP iterations.
- * As cycling seems to occur quite rarely, this class is NOT FULLY IMPLEMENTED YET!
- *
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- */
-class CyclingManager
-{
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- CyclingManager( );
-
- /** Copy constructor (deep copy). */
- CyclingManager( const CyclingManager& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~CyclingManager( );
-
- /** Copy asingment operator (deep copy). */
- CyclingManager& operator=( const CyclingManager& rhs /**< Rhs object. */
- );
-
-
- /** Pseudo-constructor which takes the number of bounds/constraints.
- * \return SUCCESSFUL_RETURN */
- returnValue init( int _nV, /**< Number of bounds to be managed. */
- int _nC /**< Number of constraints to be managed. */
- );
-
-
- /** Stores index of a bound/constraint that might cause cycling.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- returnValue setCyclingStatus( int number, /**< Number of bound/constraint. */
- BooleanType isBound, /**< Flag that indicates if given number corresponds to a
- * bound (BT_TRUE) or a constraint (BT_FALSE). */
- CyclingStatus _status /**< Cycling status of bound/constraint. */
- );
-
- /** Returns if bound/constraint might cause cycling.
- * \return BT_TRUE: bound/constraint might cause cycling \n
- BT_FALSE: otherwise */
- CyclingStatus getCyclingStatus( int number, /**< Number of bound/constraint. */
- BooleanType isBound /**< Flag that indicates if given number corresponds to
- * a bound (BT_TRUE) or a constraint (BT_FALSE). */
- ) const;
-
-
- /** Clears all previous cycling information.
- * \return SUCCESSFUL_RETURN */
- returnValue clearCyclingData( );
-
-
- /** Returns if cycling was detected.
- * \return BT_TRUE iff cycling was detected. */
- inline BooleanType isCyclingDetected( ) const;
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- int nV; /**< Number of managed bounds. */
- int nC; /**< Number of managed constraints. */
-
- CyclingStatus status[NVMAX+NCMAX]; /**< Array to store cycling status of all bounds/constraints. */
-
- BooleanType cyclingDetected; /**< Flag if cycling was detected. */
-};
-
-
-#include
-
-#endif /* QPOASES_CYCLINGMANAGER_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/EXTRAS/SolutionAnalysis.hpp b/phonelibs/qpoases/INCLUDE/EXTRAS/SolutionAnalysis.hpp
deleted file mode 100644
index 056bb26f0..000000000
--- a/phonelibs/qpoases/INCLUDE/EXTRAS/SolutionAnalysis.hpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/EXTRAS/SolutionAnalysis.hpp
- * \author Milan Vukov, Boris Houska, Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2012
- *
- * Solution analysis class, based on a class in the standard version of the qpOASES
- */
-
-
-//
-
-#ifndef QPOASES_SOLUTIONANALYSIS_HPP
-#define QPOASES_SOLUTIONANALYSIS_HPP
-
-#include
-
-/** Enables the computation of variance as is in the standard version of qpOASES */
-#define QPOASES_USE_OLD_VERSION 0
-
-#if QPOASES_USE_OLD_VERSION
-#define KKT_DIM (2 * NVMAX + NCMAX)
-#endif
-
-class SolutionAnalysis
-{
-public:
-
- /** Default constructor. */
- SolutionAnalysis( );
-
- /** Copy constructor (deep copy). */
- SolutionAnalysis( const SolutionAnalysis& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~SolutionAnalysis( );
-
- /** Copy asingment operator (deep copy). */
- SolutionAnalysis& operator=( const SolutionAnalysis& rhs /**< Rhs object. */
- );
-
- /** A routine for computation of inverse of the Hessian matrix. */
- returnValue getHessianInverse(
- QProblem* qp, /** QP */
- real_t* hessianInverse /** Inverse of the Hessian matrix*/
- );
-
- /** A routine for computation of inverse of the Hessian matrix. */
- returnValue getHessianInverse( QProblemB* qp, /** QP */
- real_t* hessianInverse /** Inverse of the Hessian matrix*/
- );
-
-#if QPOASES_USE_OLD_VERSION
- returnValue getVarianceCovariance(
- QProblem* qp,
- real_t* g_b_bA_VAR,
- real_t* Primal_Dual_VAR
- );
-#endif
-
-private:
-
- real_t delta_g_cov[ NVMAX ]; /** A covariance-vector of g */
- real_t delta_lb_cov[ NVMAX ]; /** A covariance-vector of lb */
- real_t delta_ub_cov[ NVMAX ]; /** A covariance-vector of ub */
- real_t delta_lbA_cov[ NCMAX_ALLOC ]; /** A covariance-vector of lbA */
- real_t delta_ubA_cov[ NCMAX_ALLOC ]; /** A covariance-vector of ubA */
-
-#if QPOASES_USE_OLD_VERSION
- real_t K[KKT_DIM * KKT_DIM]; /** A matrix to store an intermediate result */
-#endif
-
- int FR_idx[ NVMAX ]; /** Index array for free variables */
- int FX_idx[ NVMAX ]; /** Index array for fixed variables */
- int AC_idx[ NCMAX_ALLOC ]; /** Index array for active constraints */
-
- real_t delta_xFR[ NVMAX ]; /** QP reaction, primal, w.r.t. free */
- real_t delta_xFX[ NVMAX ]; /** QP reaction, primal, w.r.t. fixed */
- real_t delta_yAC[ NVMAX ]; /** QP reaction, dual, w.r.t. active */
- real_t delta_yFX[ NVMAX ]; /** QP reaction, dual, w.r.t. fixed*/
-};
-
-#endif // QPOASES_SOLUTIONANALYSIS_HPP
diff --git a/phonelibs/qpoases/INCLUDE/Indexlist.hpp b/phonelibs/qpoases/INCLUDE/Indexlist.hpp
deleted file mode 100644
index 21c31ddb9..000000000
--- a/phonelibs/qpoases/INCLUDE/Indexlist.hpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/Indexlist.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the Indexlist class designed to manage index lists of
- * constraints and bounds within a SubjectTo object.
- */
-
-
-#ifndef QPOASES_INDEXLIST_HPP
-#define QPOASES_INDEXLIST_HPP
-
-
-#include
-
-
-/** This class manages index lists.
- *
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- */
-class Indexlist
-{
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- Indexlist( );
-
- /** Copy constructor (deep copy). */
- Indexlist( const Indexlist& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~Indexlist( );
-
- /** Assingment operator (deep copy). */
- Indexlist& operator=( const Indexlist& rhs /**< Rhs object. */
- );
-
- /** Pseudo-constructor.
- * \return SUCCESSFUL_RETURN */
- returnValue init( );
-
-
- /** Creates an array of all numbers within the index set in correct order.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEXLIST_CORRUPTED */
- returnValue getNumberArray( int* const numberarray /**< Output: Array of numbers (NULL on error). */
- ) const;
-
-
- /** Determines the index within the index list at with a given number is stored.
- * \return >= 0: Index of given number. \n
- -1: Number not found. */
- int getIndex( int givennumber /**< Number whose index shall be determined. */
- ) const;
-
- /** Determines the physical index within the index list at with a given number is stored.
- * \return >= 0: Index of given number. \n
- -1: Number not found. */
- int getPhysicalIndex( int givennumber /**< Number whose physical index shall be determined. */
- ) const;
-
- /** Returns the number stored at a given physical index.
- * \return >= 0: Number stored at given physical index. \n
- -RET_INDEXLIST_OUTOFBOUNDS */
- int getNumber( int physicalindex /**< Physical index of the number to be returned. */
- ) const;
-
-
- /** Returns the current length of the index list.
- * \return Current length of the index list. */
- inline int getLength( );
-
- /** Returns last number within the index list.
- * \return Last number within the index list. */
- inline int getLastNumber( ) const;
-
-
- /** Adds number to index list.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEXLIST_MUST_BE_REORDERD \n
- RET_INDEXLIST_EXCEEDS_MAX_LENGTH */
- returnValue addNumber( int addnumber /**< Number to be added. */
- );
-
- /** Removes number from index list.
- * \return SUCCESSFUL_RETURN */
- returnValue removeNumber( int removenumber /**< Number to be removed. */
- );
-
- /** Swaps two numbers within index list.
- * \return SUCCESSFUL_RETURN */
- returnValue swapNumbers( int number1,/**< First number for swapping. */
- int number2 /**< Second number for swapping. */
- );
-
- /** Determines if a given number is contained in the index set.
- * \return BT_TRUE iff number is contain in the index set */
- inline BooleanType isMember( int _number /**< Number to be tested for membership. */
- ) const;
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- int number[INDEXLISTFACTOR*(NVMAX+NCMAX)]; /**< Array to store numbers of constraints or bounds. */
- int next[INDEXLISTFACTOR*(NVMAX+NCMAX)]; /**< Array to store physical index of successor. */
- int previous[INDEXLISTFACTOR*(NVMAX+NCMAX)]; /**< Array to store physical index of predecossor. */
- int length; /**< Length of index list. */
- int first; /**< Physical index of first element. */
- int last; /**< Physical index of last element. */
- int lastusedindex; /**< Physical index of last entry in index list. */
- int physicallength; /**< Physical length of index list. */
-};
-
-
-#include
-
-#endif /* QPOASES_INDEXLIST_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/MessageHandling.hpp b/phonelibs/qpoases/INCLUDE/MessageHandling.hpp
deleted file mode 100644
index 3d17498ad..000000000
--- a/phonelibs/qpoases/INCLUDE/MessageHandling.hpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/MessageHandling.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the MessageHandling class including global return values.
- */
-
-
-#ifndef QPOASES_MESSAGEHANDLING_HPP
-#define QPOASES_MESSAGEHANDLING_HPP
-
-// #define PC_DEBUG
-
-#ifdef PC_DEBUG
- #include
-
- /** Defines an alias for FILE from stdio.h. */
- #define myFILE FILE
- /** Defines an alias for stderr from stdio.h. */
- #define myStderr stderr
- /** Defines an alias for stdout from stdio.h. */
- #define myStdout stdout
-#else
- /** Defines an alias for FILE from stdio.h. */
- #define myFILE int
- /** Defines an alias for stderr from stdio.h. */
- #define myStderr 0
- /** Defines an alias for stdout from stdio.h. */
- #define myStdout 0
-#endif
-
-
-#include
-#include
-
-
-/** Defines symbols for global return values. \n
- * Important: All return values are assumed to be nonnegative! */
-enum returnValue
-{
-TERMINAL_LIST_ELEMENT = -1, /**< Terminal list element, internal usage only! */
-/* miscellaneous */
-SUCCESSFUL_RETURN = 0, /**< Successful return. */
-RET_DIV_BY_ZERO, /**< Division by zero. */
-RET_INDEX_OUT_OF_BOUNDS, /**< Index out of bounds. */
-RET_INVALID_ARGUMENTS, /**< At least one of the arguments is invalid. */
-RET_ERROR_UNDEFINED, /**< Error number undefined. */
-RET_WARNING_UNDEFINED, /**< Warning number undefined. */
-RET_INFO_UNDEFINED, /**< Info number undefined. */
-RET_EWI_UNDEFINED, /**< Error/warning/info number undefined. */
-RET_AVAILABLE_WITH_LINUX_ONLY, /**< This function is available under Linux only. */
-RET_UNKNOWN_BUG, /**< The error occured is not yet known. */
-RET_PRINTLEVEL_CHANGED, /**< 10 Print level changed. */
-RET_NOT_YET_IMPLEMENTED, /**< Requested function is not yet implemented in this version of qpOASES. */
-/* Indexlist */
-RET_INDEXLIST_MUST_BE_REORDERD, /**< Index list has to be reordered. */
-RET_INDEXLIST_EXCEEDS_MAX_LENGTH, /**< Index list exceeds its maximal physical length. */
-RET_INDEXLIST_CORRUPTED, /**< Index list corrupted. */
-RET_INDEXLIST_OUTOFBOUNDS, /**< Physical index is out of bounds. */
-RET_INDEXLIST_ADD_FAILED, /**< Adding indices from another index set failed. */
-RET_INDEXLIST_INTERSECT_FAILED, /**< Intersection with another index set failed. */
-/* SubjectTo / Bounds / Constraints */
-RET_INDEX_ALREADY_OF_DESIRED_STATUS, /**< Index is already of desired status. */
-RET_ADDINDEX_FAILED, /**< Cannot swap between different indexsets. */
-RET_SWAPINDEX_FAILED, /**< 20 Adding index to index set failed. */
-RET_NOTHING_TO_DO, /**< Nothing to do. */
-RET_SETUP_BOUND_FAILED, /**< Setting up bound index failed. */
-RET_SETUP_CONSTRAINT_FAILED, /**< Setting up constraint index failed. */
-RET_MOVING_BOUND_FAILED, /**< Moving bound between index sets failed. */
-RET_MOVING_CONSTRAINT_FAILED, /**< Moving constraint between index sets failed. */
-/* QProblem */
-RET_QP_ALREADY_INITIALISED, /**< QProblem has already been initialised. */
-RET_NO_INIT_WITH_STANDARD_SOLVER, /**< Initialisation via extern QP solver is not yet implemented. */
-RET_RESET_FAILED, /**< Reset failed. */
-RET_INIT_FAILED, /**< Initialisation failed. */
-RET_INIT_FAILED_TQ, /**< 30 Initialisation failed due to TQ factorisation. */
-RET_INIT_FAILED_CHOLESKY, /**< Initialisation failed due to Cholesky decomposition. */
-RET_INIT_FAILED_HOTSTART, /**< Initialisation failed! QP could not be solved! */
-RET_INIT_FAILED_INFEASIBILITY, /**< Initial QP could not be solved due to infeasibility! */
-RET_INIT_FAILED_UNBOUNDEDNESS, /**< Initial QP could not be solved due to unboundedness! */
-RET_INIT_SUCCESSFUL, /**< Initialisation done. */
-RET_OBTAINING_WORKINGSET_FAILED, /**< Failed to obtain working set for auxiliary QP. */
-RET_SETUP_WORKINGSET_FAILED, /**< Failed to setup working set for auxiliary QP. */
-RET_SETUP_AUXILIARYQP_FAILED, /**< Failed to setup auxiliary QP for initialised homotopy. */
-RET_NO_EXTERN_SOLVER, /**< No extern QP solver available. */
-RET_QP_UNBOUNDED, /**< 40 QP is unbounded. */
-RET_QP_INFEASIBLE, /**< QP is infeasible. */
-RET_QP_NOT_SOLVED, /**< Problems occured while solving QP with standard solver. */
-RET_QP_SOLVED, /**< QP successfully solved. */
-RET_UNABLE_TO_SOLVE_QP, /**< Problems occured while solving QP. */
-RET_INITIALISATION_STARTED, /**< Starting problem initialisation. */
-RET_HOTSTART_FAILED, /**< Unable to perform homotopy due to internal error. */
-RET_HOTSTART_FAILED_TO_INIT, /**< Unable to initialise problem. */
-RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED, /**< Unable to perform homotopy as previous QP is not solved. */
-RET_ITERATION_STARTED, /**< Iteration... */
-RET_SHIFT_DETERMINATION_FAILED, /**< 50 Determination of shift of the QP data failed. */
-RET_STEPDIRECTION_DETERMINATION_FAILED, /**< Determination of step direction failed. */
-RET_STEPLENGTH_DETERMINATION_FAILED, /**< Determination of step direction failed. */
-RET_OPTIMAL_SOLUTION_FOUND, /**< Optimal solution of neighbouring QP found. */
-RET_HOMOTOPY_STEP_FAILED, /**< Unable to perform homotopy step. */
-RET_HOTSTART_STOPPED_INFEASIBILITY, /**< Premature homotopy termination because QP is infeasible. */
-RET_HOTSTART_STOPPED_UNBOUNDEDNESS, /**< Premature homotopy termination because QP is unbounded. */
-RET_WORKINGSET_UPDATE_FAILED, /**< Unable to update working sets according to initial guesses. */
-RET_MAX_NWSR_REACHED, /**< Maximum number of working set recalculations performed. */
-RET_CONSTRAINTS_NOT_SPECIFIED, /**< Problem does comprise constraints! You also have to specify new constraints' bounds. */
-RET_INVALID_FACTORISATION_FLAG, /**< 60 Invalid factorisation flag. */
-RET_UNABLE_TO_SAVE_QPDATA, /**< Unable to save QP data. */
-RET_STEPDIRECTION_FAILED_TQ, /**< Abnormal termination due to TQ factorisation. */
-RET_STEPDIRECTION_FAILED_CHOLESKY, /**< Abnormal termination due to Cholesky factorisation. */
-RET_CYCLING_DETECTED, /**< Cycling detected. */
-RET_CYCLING_NOT_RESOLVED, /**< Cycling cannot be resolved, QP probably infeasible. */
-RET_CYCLING_RESOLVED, /**< Cycling probably resolved. */
-RET_STEPSIZE, /**< For displaying performed stepsize. */
-RET_STEPSIZE_NONPOSITIVE, /**< For displaying non-positive stepsize. */
-RET_SETUPSUBJECTTOTYPE_FAILED, /**< Setup of SubjectToTypes failed. */
-RET_ADDCONSTRAINT_FAILED, /**< 70 Addition of constraint to working set failed. */
-RET_ADDCONSTRAINT_FAILED_INFEASIBILITY, /**< Addition of constraint to working set failed (due to QP infeasibility). */
-RET_ADDBOUND_FAILED, /**< Addition of bound to working set failed. */
-RET_ADDBOUND_FAILED_INFEASIBILITY, /**< Addition of bound to working set failed (due to QP infeasibility). */
-RET_REMOVECONSTRAINT_FAILED, /**< Removal of constraint from working set failed. */
-RET_REMOVEBOUND_FAILED, /**< Removal of bound from working set failed. */
-RET_REMOVE_FROM_ACTIVESET, /**< Removing from active set... */
-RET_ADD_TO_ACTIVESET, /**< Adding to active set... */
-RET_REMOVE_FROM_ACTIVESET_FAILED, /**< Removing from active set failed. */
-RET_ADD_TO_ACTIVESET_FAILED, /**< Adding to active set failed. */
-RET_CONSTRAINT_ALREADY_ACTIVE, /**< 80 Constraint is already active. */
-RET_ALL_CONSTRAINTS_ACTIVE, /**< All constraints are active, no further constraint can be added. */
-RET_LINEARLY_DEPENDENT, /**< New bound/constraint is linearly dependent. */
-RET_LINEARLY_INDEPENDENT, /**< New bound/constraint is linearly independent. */
-RET_LI_RESOLVED, /**< Linear independence of active contraint matrix successfully resolved. */
-RET_ENSURELI_FAILED, /**< Failed to ensure linear indepence of active contraint matrix. */
-RET_ENSURELI_FAILED_TQ, /**< Abnormal termination due to TQ factorisation. */
-RET_ENSURELI_FAILED_NOINDEX, /**< No index found, QP probably infeasible. */
-RET_ENSURELI_FAILED_CYCLING, /**< Cycling detected, QP probably infeasible. */
-RET_BOUND_ALREADY_ACTIVE, /**< Bound is already active. */
-RET_ALL_BOUNDS_ACTIVE, /**< 90 All bounds are active, no further bound can be added. */
-RET_CONSTRAINT_NOT_ACTIVE, /**< Constraint is not active. */
-RET_BOUND_NOT_ACTIVE, /**< Bound is not active. */
-RET_HESSIAN_NOT_SPD, /**< Projected Hessian matrix not positive definite. */
-RET_MATRIX_SHIFT_FAILED, /**< Unable to update matrices or to transform vectors. */
-RET_MATRIX_FACTORISATION_FAILED, /**< Unable to calculate new matrix factorisations. */
-RET_PRINT_ITERATION_FAILED, /**< Unable to print information on current iteration. */
-RET_NO_GLOBAL_MESSAGE_OUTPUTFILE, /**< No global message output file initialised. */
-/* Utils */
-RET_UNABLE_TO_OPEN_FILE, /**< Unable to open file. */
-RET_UNABLE_TO_WRITE_FILE, /**< Unable to write into file. */
-RET_UNABLE_TO_READ_FILE, /**< 100 Unable to read from file. */
-RET_FILEDATA_INCONSISTENT, /**< File contains inconsistent data. */
-/* SolutionAnalysis */
-RET_NO_SOLUTION, /**< QP solution does not satisfy KKT optimality conditions. */
-RET_INACCURATE_SOLUTION /**< KKT optimality conditions not satisfied to sufficient accuracy. */
-};
-
-
-
-/** This class handles all kinds of messages (errors, warnings, infos) initiated
- * by qpOASES modules and stores the correspoding global preferences.
- *
- * \author Hans Joachim Ferreau (special thanks to Leonard Wirsching)
- * \version 1.3embedded
- * \date 2007-2008
- */
-class MessageHandling
-{
- /*
- * INTERNAL DATA STRUCTURES
- */
- public:
- /** Data structure for entries in global message list. */
- typedef struct {
- returnValue key; /**< Global return value. */
- const char* data; /**< Corresponding message. */
- VisibilityStatus globalVisibilityStatus; /**< Determines if message can be printed.
- * If this value is set to VS_HIDDEN, no message is printed! */
- } ReturnValueList;
-
-
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- MessageHandling( );
-
- /** Constructor which takes the desired output file. */
- MessageHandling( myFILE* _outputFile /**< Output file. */
- );
-
- /** Constructor which takes the desired visibility states. */
- MessageHandling( VisibilityStatus _errorVisibility, /**< Visibility status for error messages. */
- VisibilityStatus _warningVisibility,/**< Visibility status for warning messages. */
- VisibilityStatus _infoVisibility /**< Visibility status for info messages. */
- );
-
- /** Constructor which takes the desired output file and desired visibility states. */
- MessageHandling( myFILE* _outputFile, /**< Output file. */
- VisibilityStatus _errorVisibility, /**< Visibility status for error messages. */
- VisibilityStatus _warningVisibility,/**< Visibility status for warning messages. */
- VisibilityStatus _infoVisibility /**< Visibility status for info messages. */
- );
-
- /** Copy constructor (deep copy). */
- MessageHandling( const MessageHandling& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~MessageHandling( );
-
- /** Assignment operator (deep copy). */
- MessageHandling& operator=( const MessageHandling& rhs /**< Rhs object. */
- );
-
-
- /** Prints an error message(a simplified macro THROWERROR is also provided). \n
- * Errors are definied as abnormal events which cause an immediate termination of the current (sub) function.
- * Errors of a sub function should be commented by the calling function by means of a warning message
- * (if this error does not cause an error of the calling function, either)!
- * \return Error number returned by sub function call
- */
- returnValue throwError(
- returnValue Enumber, /**< Error number returned by sub function call. */
- const char* additionaltext, /**< Additional error text (0, if none). */
- const char* functionname, /**< Name of function which caused the error. */
- const char* filename, /**< Name of file which caused the error. */
- const unsigned long linenumber, /**< Number of line which caused the error.incompatible binary file */
- VisibilityStatus localVisibilityStatus /**< Determines (locally) if error message can be printed to myStderr.
- * If GLOBAL visibility status of the message is set to VS_HIDDEN,
- * no message is printed, anyway! */
- );
-
- /** Prints a warning message (a simplified macro THROWWARNING is also provided).
- * Warnings are definied as abnormal events which does NOT cause an immediate termination of the current (sub) function.
- * \return Warning number returned by sub function call
- */
- returnValue throwWarning(
- returnValue Wnumber, /**< Warning number returned by sub function call. */
- const char* additionaltext, /**< Additional warning text (0, if none). */
- const char* functionname, /**< Name of function which caused the warning. */
- const char* filename, /**< Name of file which caused the warning. */
- const unsigned long linenumber, /**< Number of line which caused the warning. */
- VisibilityStatus localVisibilityStatus /**< Determines (locally) if warning message can be printed to myStderr.
- * If GLOBAL visibility status of the message is set to VS_HIDDEN,
- * no message is printed, anyway! */
- );
-
- /** Prints a info message (a simplified macro THROWINFO is also provided).
- * \return Info number returned by sub function call
- */
- returnValue throwInfo(
- returnValue Inumber, /**< Info number returned by sub function call. */
- const char* additionaltext, /**< Additional warning text (0, if none). */
- const char* functionname, /**< Name of function which submitted the info. */
- const char* filename, /**< Name of file which submitted the info. */
- const unsigned long linenumber, /**< Number of line which submitted the info. */
- VisibilityStatus localVisibilityStatus /**< Determines (locally) if info message can be printed to myStderr.
- * If GLOBAL visibility status of the message is set to VS_HIDDEN,
- * no message is printed, anyway! */
- );
-
-
- /** Resets all preferences to default values.
- * \return SUCCESSFUL_RETURN */
- returnValue reset( );
-
-
- /** Prints a complete list of all messages to output file.
- * \return SUCCESSFUL_RETURN */
- returnValue listAllMessages( );
-
-
- /** Returns visibility status for error messages.
- * \return Visibility status for error messages. */
- inline VisibilityStatus getErrorVisibilityStatus( ) const;
-
- /** Returns visibility status for warning messages.
- * \return Visibility status for warning messages. */
- inline VisibilityStatus getWarningVisibilityStatus( ) const;
-
- /** Returns visibility status for info messages.
- * \return Visibility status for info messages. */
- inline VisibilityStatus getInfoVisibilityStatus( ) const;
-
- /** Returns pointer to output file.
- * \return Pointer to output file. */
- inline myFILE* getOutputFile( ) const;
-
- /** Returns error count value.
- * \return Error count value. */
- inline int getErrorCount( ) const;
-
-
- /** Changes visibility status for error messages. */
- inline void setErrorVisibilityStatus( VisibilityStatus _errorVisibility /**< New visibility status for error messages. */
- );
-
- /** Changes visibility status for warning messages. */
- inline void setWarningVisibilityStatus( VisibilityStatus _warningVisibility /**< New visibility status for warning messages. */
- );
-
- /** Changes visibility status for info messages. */
- inline void setInfoVisibilityStatus( VisibilityStatus _infoVisibility /**< New visibility status for info messages. */
- );
-
- /** Changes output file for messages. */
- inline void setOutputFile( myFILE* _outputFile /**< New output file for messages. */
- );
-
- /** Changes error count.
- * \return SUCCESSFUL_RETURN \n
- * RET_INVALID_ARGUMENT */
- inline returnValue setErrorCount( int _errorCount /**< New error count value. */
- );
-
- /** Return the error code string. */
- static const char* getErrorString(int error);
-
- /*
- * PROTECTED MEMBER FUNCTIONS
- */
- protected:
- /** Prints a info message to myStderr (auxiliary function).
- * \return Error/warning/info number returned by sub function call
- */
- returnValue throwMessage(
- returnValue RETnumber, /**< Error/warning/info number returned by sub function call. */
- const char* additionaltext, /**< Additional warning text (0, if none). */
- const char* functionname, /**< Name of function which caused the error/warning/info. */
- const char* filename, /**< Name of file which caused the error/warning/info. */
- const unsigned long linenumber, /**< Number of line which caused the error/warning/info. */
- VisibilityStatus localVisibilityStatus, /**< Determines (locally) if info message can be printed to myStderr.
- * If GLOBAL visibility status of the message is set to VS_HIDDEN,
- * no message is printed, anyway! */
- const char* RETstring /**< Leading string of error/warning/info message. */
- );
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- VisibilityStatus errorVisibility; /**< Error messages visible? */
- VisibilityStatus warningVisibility; /**< Warning messages visible? */
- VisibilityStatus infoVisibility; /**< Info messages visible? */
-
- myFILE* outputFile; /**< Output file for messages. */
-
- int errorCount; /**< Counts number of errors (for nicer output only). */
-};
-
-
-#ifndef __FUNCTION__
- /** Ensures that __FUNCTION__ macro is defined. */
- #define __FUNCTION__ 0
-#endif
-
-#ifndef __FILE__
- /** Ensures that __FILE__ macro is defined. */
- #define __FILE__ 0
-#endif
-
-#ifndef __LINE__
- /** Ensures that __LINE__ macro is defined. */
- #define __LINE__ 0
-#endif
-
-
-/** Short version of throwError with default values, only returnValue is needed */
-#define THROWERROR(retval) ( getGlobalMessageHandler( )->throwError((retval),0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE) )
-
-/** Short version of throwWarning with default values, only returnValue is needed */
-#define THROWWARNING(retval) ( getGlobalMessageHandler( )->throwWarning((retval),0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE) )
-
-/** Short version of throwInfo with default values, only returnValue is needed */
-#define THROWINFO(retval) ( getGlobalMessageHandler( )->throwInfo((retval),0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE) )
-
-
-/** Returns a pointer to global message handler.
- * \return Pointer to global message handler.
- */
-MessageHandling* getGlobalMessageHandler( );
-
-
-#include
-
-#endif /* QPOASES_MESSAGEHANDLING_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/QProblem.hpp b/phonelibs/qpoases/INCLUDE/QProblem.hpp
deleted file mode 100644
index 91dc43417..000000000
--- a/phonelibs/qpoases/INCLUDE/QProblem.hpp
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/QProblem.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the QProblem class which is able to use the newly
- * developed online active set strategy for parametric quadratic programming.
- */
-
-
-
-#ifndef QPOASES_QPROBLEM_HPP
-#define QPOASES_QPROBLEM_HPP
-
-
-#include
-#include
-#include
-
-
-/** A class for setting up and solving quadratic programs. The main feature is
- * the possibily to use the newly developed online active set strategy for
- * parametric quadratic programming.
- *
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- */
-class QProblem : public QProblemB
-{
- /* allow SolutionAnalysis class to access private members */
- friend class SolutionAnalysis;
-
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- QProblem( );
-
- /** Constructor which takes the QP dimensions only. */
- QProblem( int _nV, /**< Number of variables. */
- int _nC /**< Number of constraints. */
- );
-
- /** Copy constructor (deep copy). */
- QProblem( const QProblem& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~QProblem( );
-
- /** Assignment operator (deep copy). */
- QProblem& operator=( const QProblem& rhs /**< Rhs object. */
- );
-
-
- /** Clears all data structures of QProblemB except for QP data.
- * \return SUCCESSFUL_RETURN \n
- RET_RESET_FAILED */
- returnValue reset( );
-
-
- /** Initialises a QProblem with given QP data and solves it
- * using an initial homotopy with empty working set (at most nWSR iterations).
- * \return SUCCESSFUL_RETURN \n
- RET_INIT_FAILED \n
- RET_INIT_FAILED_CHOLESKY \n
- RET_INIT_FAILED_TQ \n
- RET_INIT_FAILED_HOTSTART \n
- RET_INIT_FAILED_INFEASIBILITY \n
- RET_INIT_FAILED_UNBOUNDEDNESS \n
- RET_MAX_NWSR_REACHED \n
- RET_INVALID_ARGUMENTS \n
- RET_INACCURATE_SOLUTION \n
- RET_NO_SOLUTION */
- returnValue init( const real_t* const _H, /**< Hessian matrix. */
- const real_t* const _g, /**< Gradient vector. */
- const real_t* const _A, /**< Constraint matrix. */
- const real_t* const _lb, /**< Lower bound vector (on variables). \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const _ub, /**< Upper bound vector (on variables). \n
- If no upper bounds exist, a NULL pointer can be passed. */
- const real_t* const _lbA, /**< Lower constraints' bound vector. \n
- If no lower constraints' bounds exist, a NULL pointer can be passed. */
- const real_t* const _ubA, /**< Upper constraints' bound vector. \n
- If no lower constraints' bounds exist, a NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy.
- Output: Number of performed working set recalculations. */
- const real_t* const yOpt = 0, /**< Initial guess for dual solution vector. */
- real_t* const cputime = 0 /**< Output: CPU time required to initialise QP. */
- );
-
-
- /** Initialises a QProblem with given QP data and solves it
- * using an initial homotopy with empty working set (at most nWSR iterations).
- * \return SUCCESSFUL_RETURN \n
- RET_INIT_FAILED \n
- RET_INIT_FAILED_CHOLESKY \n
- RET_INIT_FAILED_TQ \n
- RET_INIT_FAILED_HOTSTART \n
- RET_INIT_FAILED_INFEASIBILITY \n
- RET_INIT_FAILED_UNBOUNDEDNESS \n
- RET_MAX_NWSR_REACHED \n
- RET_INVALID_ARGUMENTS \n
- RET_INACCURATE_SOLUTION \n
- RET_NO_SOLUTION */
- returnValue init( const real_t* const _H, /**< Hessian matrix. */
- const real_t* const _R, /**< Cholesky factorization of the Hessian matrix. */
- const real_t* const _g, /**< Gradient vector. */
- const real_t* const _A, /**< Constraint matrix. */
- const real_t* const _lb, /**< Lower bound vector (on variables). \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const _ub, /**< Upper bound vector (on variables). \n
- If no upper bounds exist, a NULL pointer can be passed. */
- const real_t* const _lbA, /**< Lower constraints' bound vector. \n
- If no lower constraints' bounds exist, a NULL pointer can be passed. */
- const real_t* const _ubA, /**< Upper constraints' bound vector. \n
- If no lower constraints' bounds exist, a NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy.
- Output: Number of performed working set recalculations. */
- const real_t* const yOpt = 0, /**< Initial guess for dual solution vector. */
- real_t* const cputime = 0 /**< Output: CPU time required to initialise QP. */
- );
-
-
- /** Solves QProblem using online active set strategy.
- * \return SUCCESSFUL_RETURN \n
- RET_MAX_NWSR_REACHED \n
- RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n
- RET_HOTSTART_FAILED \n
- RET_SHIFT_DETERMINATION_FAILED \n
- RET_STEPDIRECTION_DETERMINATION_FAILED \n
- RET_STEPLENGTH_DETERMINATION_FAILED \n
- RET_HOMOTOPY_STEP_FAILED \n
- RET_HOTSTART_STOPPED_INFEASIBILITY \n
- RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n
- RET_INACCURATE_SOLUTION \n
- RET_NO_SOLUTION */
- returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */
- const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n
- If no upper bounds exist, a NULL pointer can be passed. */
- const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n
- If no lower constraints' bounds exist, a NULL pointer can be passed. */
- const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n
- If no upper constraints' bounds exist, a NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations; \n
- Output: Number of performed working set recalculations. */
- real_t* const cputime /**< Output: CPU time required to solve QP (or to perform nWSR iterations). */
- );
-
-
- /** Returns constraint matrix of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getA( real_t* const _A /**< Array of appropriate dimension for copying constraint matrix.*/
- ) const;
-
- /** Returns a single row of constraint matrix of the QP (deep copy).
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue getA( int number, /**< Number of entry to be returned. */
- real_t* const row /**< Array of appropriate dimension for copying (number)th constraint. */
- ) const;
-
- /** Returns lower constraints' bound vector of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getLBA( real_t* const _lbA /**< Array of appropriate dimension for copying lower constraints' bound vector.*/
- ) const;
-
- /** Returns single entry of lower constraints' bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue getLBA( int number, /**< Number of entry to be returned. */
- real_t& value /**< Output: lbA[number].*/
- ) const;
-
- /** Returns upper constraints' bound vector of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getUBA( real_t* const _ubA /**< Array of appropriate dimension for copying upper constraints' bound vector.*/
- ) const;
-
- /** Returns single entry of upper constraints' bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue getUBA( int number, /**< Number of entry to be returned. */
- real_t& value /**< Output: ubA[number].*/
- ) const;
-
-
- /** Returns current constraints object of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getConstraints( Constraints* const _constraints /** Output: Constraints object. */
- ) const;
-
-
- /** Returns the number of constraints.
- * \return Number of constraints. */
- inline int getNC( ) const;
-
- /** Returns the number of (implicitly defined) equality constraints.
- * \return Number of (implicitly defined) equality constraints. */
- inline int getNEC( ) const;
-
- /** Returns the number of active constraints.
- * \return Number of active constraints. */
- inline int getNAC( );
-
- /** Returns the number of inactive constraints.
- * \return Number of inactive constraints. */
- inline int getNIAC( );
-
- /** Returns the dimension of null space.
- * \return Dimension of null space. */
- int getNZ( );
-
-
- /** Returns the dual solution vector (deep copy).
- * \return SUCCESSFUL_RETURN \n
- RET_QP_NOT_SOLVED */
- returnValue getDualSolution( real_t* const yOpt /**< Output: Dual solution vector (if QP has been solved). */
- ) const;
-
-
- /*
- * PROTECTED MEMBER FUNCTIONS
- */
- protected:
- /** Determines type of constraints and bounds (i.e. implicitly fixed, unbounded etc.).
- * \return SUCCESSFUL_RETURN \n
- RET_SETUPSUBJECTTOTYPE_FAILED */
- returnValue setupSubjectToType( );
-
- /** Computes the Cholesky decomposition R of the projected Hessian (i.e. R^T*R = Z^T*H*Z).
- * \return SUCCESSFUL_RETURN \n
- * RET_INDEXLIST_CORRUPTED */
- returnValue setupCholeskyDecompositionProjected( );
-
- /** Initialises TQ factorisation of A (i.e. A*Q = [0 T]) if NO constraint is active.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEXLIST_CORRUPTED */
- returnValue setupTQfactorisation( );
-
-
- /** Solves a QProblem whose QP data is assumed to be stored in the member variables.
- * A guess for its primal/dual optimal solution vectors and the corresponding
- * working sets of bounds and constraints can be provided.
- * \return SUCCESSFUL_RETURN \n
- RET_INIT_FAILED \n
- RET_INIT_FAILED_CHOLESKY \n
- RET_INIT_FAILED_TQ \n
- RET_INIT_FAILED_HOTSTART \n
- RET_INIT_FAILED_INFEASIBILITY \n
- RET_INIT_FAILED_UNBOUNDEDNESS \n
- RET_MAX_NWSR_REACHED */
- returnValue solveInitialQP( const real_t* const xOpt, /**< Optimal primal solution vector.
- * A NULL pointer can be passed. */
- const real_t* const yOpt, /**< Optimal dual solution vector.
- * A NULL pointer can be passed. */
- const Bounds* const guessedBounds, /**< Guessed working set of bounds for solution (xOpt,yOpt).
- * A NULL pointer can be passed. */
- const Constraints* const guessedConstraints, /**< Optimal working set of constraints for solution (xOpt,yOpt).
- * A NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations; \n
- * Output: Number of performed working set recalculations. */
- real_t* const cputime /**< Output: CPU time required to solve QP (or to perform nWSR iterations). */
- );
-
- /** Obtains the desired working set for the auxiliary initial QP in
- * accordance with the user specifications
- * (assumes that member AX has already been initialised!)
- * \return SUCCESSFUL_RETURN \n
- RET_OBTAINING_WORKINGSET_FAILED \n
- RET_INVALID_ARGUMENTS */
- returnValue obtainAuxiliaryWorkingSet( const real_t* const xOpt, /**< Optimal primal solution vector.
- * If a NULL pointer is passed, all entries are assumed to be zero. */
- const real_t* const yOpt, /**< Optimal dual solution vector.
- * If a NULL pointer is passed, all entries are assumed to be zero. */
- const Bounds* const guessedBounds, /**< Guessed working set of bounds for solution (xOpt,yOpt). */
- const Constraints* const guessedConstraints, /**< Guessed working set for solution (xOpt,yOpt). */
- Bounds* auxiliaryBounds, /**< Input: Allocated bound object. \n
- * Ouput: Working set of constraints for auxiliary QP. */
- Constraints* auxiliaryConstraints /**< Input: Allocated bound object. \n
- * Ouput: Working set for auxiliary QP. */
- ) const;
-
- /** Setups bound and constraints data structures according to auxiliaryBounds/Constraints.
- * (If the working set shall be setup afresh, make sure that
- * bounds and constraints data structure have been resetted
- * and the TQ factorisation has been initialised!)
- * \return SUCCESSFUL_RETURN \n
- RET_SETUP_WORKINGSET_FAILED \n
- RET_INVALID_ARGUMENTS \n
- RET_UNKNOWN BUG */
- returnValue setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds, /**< Working set of bounds for auxiliary QP. */
- const Constraints* const auxiliaryConstraints, /**< Working set of constraints for auxiliary QP. */
- BooleanType setupAfresh /**< Flag indicating if given working set shall be
- * setup afresh or by updating the current one. */
- );
-
- /** Setups the optimal primal/dual solution of the auxiliary initial QP.
- * \return SUCCESSFUL_RETURN */
- returnValue setupAuxiliaryQPsolution( const real_t* const xOpt, /**< Optimal primal solution vector.
- * If a NULL pointer is passed, all entries are set to zero. */
- const real_t* const yOpt /**< Optimal dual solution vector.
- * If a NULL pointer is passed, all entries are set to zero. */
- );
-
- /** Setups gradient of the auxiliary initial QP for given
- * optimal primal/dual solution and given initial working set
- * (assumes that members X, Y and BOUNDS, CONSTRAINTS have already been initialised!).
- * \return SUCCESSFUL_RETURN */
- returnValue setupAuxiliaryQPgradient( );
-
- /** Setups (constraints') bounds of the auxiliary initial QP for given
- * optimal primal/dual solution and given initial working set
- * (assumes that members X, Y and BOUNDS, CONSTRAINTS have already been initialised!).
- * \return SUCCESSFUL_RETURN \n
- RET_UNKNOWN BUG */
- returnValue setupAuxiliaryQPbounds( const Bounds* const auxiliaryBounds, /**< Working set of bounds for auxiliary QP. */
- const Constraints* const auxiliaryConstraints, /**< Working set of constraints for auxiliary QP. */
- BooleanType useRelaxation /**< Flag indicating if inactive (constraints') bounds shall be relaxed. */
- );
-
-
- /** Adds a constraint to active set.
- * \return SUCCESSFUL_RETURN \n
- RET_ADDCONSTRAINT_FAILED \n
- RET_ADDCONSTRAINT_FAILED_INFEASIBILITY \n
- RET_ENSURELI_FAILED */
- returnValue addConstraint( int number, /**< Number of constraint to be added to active set. */
- SubjectToStatus C_status, /**< Status of new active constraint. */
- BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */
- );
-
- /** Checks if new active constraint to be added is linearly dependent from
- * from row of the active constraints matrix.
- * \return RET_LINEARLY_DEPENDENT \n
- RET_LINEARLY_INDEPENDENT \n
- RET_INDEXLIST_CORRUPTED */
- returnValue addConstraint_checkLI( int number /**< Number of constraint to be added to active set. */
- );
-
- /** Ensures linear independence of constraint matrix when a new constraint is added.
- * To this end a bound or constraint is removed simultaneously if necessary.
- * \return SUCCESSFUL_RETURN \n
- RET_LI_RESOLVED \n
- RET_ENSURELI_FAILED \n
- RET_ENSURELI_FAILED_TQ \n
- RET_ENSURELI_FAILED_NOINDEX \n
- RET_REMOVE_FROM_ACTIVESET */
- returnValue addConstraint_ensureLI( int number, /**< Number of constraint to be added to active set. */
- SubjectToStatus C_status /**< Status of new active bound. */
- );
-
- /** Adds a bound to active set.
- * \return SUCCESSFUL_RETURN \n
- RET_ADDBOUND_FAILED \n
- RET_ADDBOUND_FAILED_INFEASIBILITY \n
- RET_ENSURELI_FAILED */
- returnValue addBound( int number, /**< Number of bound to be added to active set. */
- SubjectToStatus B_status, /**< Status of new active bound. */
- BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */
- );
-
- /** Checks if new active bound to be added is linearly dependent from
- * from row of the active constraints matrix.
- * \return RET_LINEARLY_DEPENDENT \n
- RET_LINEARLY_INDEPENDENT */
- returnValue addBound_checkLI( int number /**< Number of bound to be added to active set. */
- );
-
- /** Ensures linear independence of constraint matrix when a new bound is added.
- * To this end a bound or constraint is removed simultaneously if necessary.
- * \return SUCCESSFUL_RETURN \n
- RET_LI_RESOLVED \n
- RET_ENSURELI_FAILED \n
- RET_ENSURELI_FAILED_TQ \n
- RET_ENSURELI_FAILED_NOINDEX \n
- RET_REMOVE_FROM_ACTIVESET */
- returnValue addBound_ensureLI( int number, /**< Number of bound to be added to active set. */
- SubjectToStatus B_status /**< Status of new active bound. */
- );
-
- /** Removes a constraint from active set.
- * \return SUCCESSFUL_RETURN \n
- RET_CONSTRAINT_NOT_ACTIVE \n
- RET_REMOVECONSTRAINT_FAILED \n
- RET_HESSIAN_NOT_SPD */
- returnValue removeConstraint( int number, /**< Number of constraint to be removed from active set. */
- BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */
- );
-
- /** Removes a bounds from active set.
- * \return SUCCESSFUL_RETURN \n
- RET_BOUND_NOT_ACTIVE \n
- RET_HESSIAN_NOT_SPD \n
- RET_REMOVEBOUND_FAILED */
- returnValue removeBound( int number, /**< Number of bound to be removed from active set. */
- BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */
- );
-
-
- /** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix.
- * \return SUCCESSFUL_RETURN \n
- RET_DIV_BY_ZERO */
- returnValue backsolveR( const real_t* const b, /**< Right hand side vector. */
- BooleanType transposed, /**< Indicates if the transposed system shall be solved. */
- real_t* const a /**< Output: Solution vector */
- );
-
- /** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. \n
- * Special variant for the case that this function is called from within "removeBound()".
- * \return SUCCESSFUL_RETURN \n
- RET_DIV_BY_ZERO */
- returnValue backsolveR( const real_t* const b, /**< Right hand side vector. */
- BooleanType transposed, /**< Indicates if the transposed system shall be solved. */
- BooleanType removingBound, /**< Indicates if function is called from "removeBound()". */
- real_t* const a /**< Output: Solution vector */
- );
-
-
- /** Solves the system Ta = b or T^Ta = b where T is a reverse upper triangular matrix.
- * \return SUCCESSFUL_RETURN \n
- RET_DIV_BY_ZERO */
- returnValue backsolveT( const real_t* const b, /**< Right hand side vector. */
- BooleanType transposed, /**< Indicates if the transposed system shall be solved. */
- real_t* const a /**< Output: Solution vector */
- );
-
-
- /** Determines step direction of the shift of the QP data.
- * \return SUCCESSFUL_RETURN */
- returnValue hotstart_determineDataShift(const int* const FX_idx, /**< Index array of fixed variables. */
- const int* const AC_idx, /**< Index array of active constraints. */
- const real_t* const g_new, /**< New gradient vector. */
- const real_t* const lbA_new,/**< New lower constraints' bounds. */
- const real_t* const ubA_new,/**< New upper constraints' bounds. */
- const real_t* const lb_new, /**< New lower bounds. */
- const real_t* const ub_new, /**< New upper bounds. */
- real_t* const delta_g, /**< Output: Step direction of gradient vector. */
- real_t* const delta_lbA, /**< Output: Step direction of lower constraints' bounds. */
- real_t* const delta_ubA, /**< Output: Step direction of upper constraints' bounds. */
- real_t* const delta_lb, /**< Output: Step direction of lower bounds. */
- real_t* const delta_ub, /**< Output: Step direction of upper bounds. */
- BooleanType& Delta_bC_isZero,/**< Output: Indicates if active constraints' bounds are to be shifted. */
- BooleanType& Delta_bB_isZero/**< Output: Indicates if active bounds are to be shifted. */
- );
-
- /** Determines step direction of the homotopy path.
- * \return SUCCESSFUL_RETURN \n
- RET_STEPDIRECTION_FAILED_TQ \n
- RET_STEPDIRECTION_FAILED_CHOLESKY */
- returnValue hotstart_determineStepDirection(const int* const FR_idx, /**< Index array of free variables. */
- const int* const FX_idx, /**< Index array of fixed variables. */
- const int* const AC_idx, /**< Index array of active constraints. */
- const real_t* const delta_g, /**< Step direction of gradient vector. */
- const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */
- const real_t* const delta_ubA, /**< Step direction of upper constraints' bounds. */
- const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub, /**< Step direction of upper bounds. */
- BooleanType Delta_bC_isZero, /**< Indicates if active constraints' bounds are to be shifted. */
- BooleanType Delta_bB_isZero, /**< Indicates if active bounds are to be shifted. */
- real_t* const delta_xFX, /**< Output: Primal homotopy step direction of fixed variables. */
- real_t* const delta_xFR, /**< Output: Primal homotopy step direction of free variables. */
- real_t* const delta_yAC, /**< Output: Dual homotopy step direction of active constraints' multiplier. */
- real_t* const delta_yFX /**< Output: Dual homotopy step direction of fixed variables' multiplier. */
- );
-
- /** Determines the maximum possible step length along the homotopy path.
- * \return SUCCESSFUL_RETURN */
- returnValue hotstart_determineStepLength( const int* const FR_idx, /**< Index array of free variables. */
- const int* const FX_idx, /**< Index array of fixed variables. */
- const int* const AC_idx, /**< Index array of active constraints. */
- const int* const IAC_idx, /**< Index array of inactive constraints. */
- const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */
- const real_t* const delta_ubA, /**< Step direction of upper constraints' bounds. */
- const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub, /**< Step direction of upper bounds. */
- const real_t* const delta_xFX, /**< Primal homotopy step direction of fixed variables. */
- const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */
- const real_t* const delta_yAC, /**< Dual homotopy step direction of active constraints' multiplier. */
- const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */
- real_t* const delta_Ax, /**< Output: Step in vector Ax. */
- int& BC_idx, /**< Output: Index of blocking constraint. */
- SubjectToStatus& BC_status, /**< Output: Status of blocking constraint. */
- BooleanType& BC_isBound /**< Output: Indicates if blocking constraint is a bound. */
- );
-
- /** Performs a step along the homotopy path (and updates active set).
- * \return SUCCESSFUL_RETURN \n
- RET_OPTIMAL_SOLUTION_FOUND \n
- RET_REMOVE_FROM_ACTIVESET_FAILED \n
- RET_ADD_TO_ACTIVESET_FAILED \n
- RET_QP_INFEASIBLE */
- returnValue hotstart_performStep( const int* const FR_idx, /**< Index array of free variables. */
- const int* const FX_idx, /**< Index array of fixed variables. */
- const int* const AC_idx, /**< Index array of active constraints. */
- const int* const IAC_idx, /**< Index array of inactive constraints. */
- const real_t* const delta_g, /**< Step direction of gradient vector. */
- const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */
- const real_t* const delta_ubA, /**< Step direction of upper constraints' bounds. */
- const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub, /**< Step direction of upper bounds. */
- const real_t* const delta_xFX, /**< Primal homotopy step direction of fixed variables. */
- const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */
- const real_t* const delta_yAC, /**< Dual homotopy step direction of active constraints' multiplier. */
- const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */
- const real_t* const delta_Ax, /**< Step in vector Ax. */
- int BC_idx, /**< Index of blocking constraint. */
- SubjectToStatus BC_status, /**< Status of blocking constraint. */
- BooleanType BC_isBound /**< Indicates if blocking constraint is a bound. */
- );
-
-
- /** Checks if lower/upper (constraints') bounds remain consistent
- * (i.e. if lb <= ub and lbA <= ubA ) during the current step.
- * \return BT_TRUE iff (constraints") bounds remain consistent
- */
- BooleanType areBoundsConsistent( const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub, /**< Step direction of upper bounds. */
- const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */
- const real_t* const delta_ubA /**< Step direction of upper constraints' bounds. */
- ) const;
-
-
- /** Setups internal QP data.
- * \return SUCCESSFUL_RETURN \n
- RET_INVALID_ARGUMENTS */
- returnValue setupQPdata( const real_t* const _H, /**< Hessian matrix. */
- const real_t* const _R, /**< Cholesky factorization of the Hessian matrix. */
- const real_t* const _g, /**< Gradient vector. */
- const real_t* const _A, /**< Constraint matrix. */
- const real_t* const _lb, /**< Lower bound vector (on variables). \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const _ub, /**< Upper bound vector (on variables). \n
- If no upper bounds exist, a NULL pointer can be passed. */
- const real_t* const _lbA, /**< Lower constraints' bound vector. \n
- If no lower constraints' bounds exist, a NULL pointer can be passed. */
- const real_t* const _ubA /**< Upper constraints' bound vector. \n
- If no lower constraints' bounds exist, a NULL pointer can be passed. */
- );
-
-
- #ifdef PC_DEBUG /* Define print functions only for debugging! */
-
- /** Prints concise information on the current iteration.
- * \return SUCCESSFUL_RETURN \n */
- returnValue printIteration( int iteration, /**< Number of current iteration. */
- int BC_idx, /**< Index of blocking constraint. */
- SubjectToStatus BC_status, /**< Status of blocking constraint. */
- BooleanType BC_isBound /**< Indicates if blocking constraint is a bound. */
- );
-
- /** Prints concise information on the current iteration.
- * NOTE: ONLY DEFINED FOR SUPPRESSING A COMPILER WARNING!!
- * \return SUCCESSFUL_RETURN \n */
- returnValue printIteration( int iteration, /**< Number of current iteration. */
- int BC_idx, /**< Index of blocking bound. */
- SubjectToStatus BC_status /**< Status of blocking bound. */
- );
-
- #endif /* PC_DEBUG */
-
-
- /** Determines the maximum violation of the KKT optimality conditions
- * of the current iterate within the QProblem object.
- * \return SUCCESSFUL_RETURN \n
- * RET_INACCURATE_SOLUTION \n
- * RET_NO_SOLUTION */
- returnValue checkKKTconditions( );
-
-
- /** Sets constraint matrix of the QP. \n
- (Remark: Also internal vector Ax is recomputed!)
- * \return SUCCESSFUL_RETURN */
- inline returnValue setA( const real_t* const A_new /**< New constraint matrix (with correct dimension!). */
- );
-
- /** Changes single row of constraint matrix of the QP. \n
- (Remark: Also correponding component of internal vector Ax is recomputed!)
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue setA( int number, /**< Number of row to be changed. */
- const real_t* const value /**< New (number)th constraint (with correct dimension!). */
- );
-
-
- /** Sets constraints' lower bound vector of the QP.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setLBA( const real_t* const lbA_new /**< New constraints' lower bound vector (with correct dimension!). */
- );
-
- /** Changes single entry of lower constraints' bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue setLBA( int number, /**< Number of entry to be changed. */
- real_t value /**< New value for entry of lower constraints' bound vector (with correct dimension!). */
- );
-
- /** Sets constraints' upper bound vector of the QP.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setUBA( const real_t* const ubA_new /**< New constraints' upper bound vector (with correct dimension!). */
- );
-
- /** Changes single entry of upper constraints' bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue setUBA( int number, /**< Number of entry to be changed. */
- real_t value /**< New value for entry of upper constraints' bound vector (with correct dimension!). */
- );
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- real_t A[NCMAX_ALLOC*NVMAX]; /**< Constraint matrix. */
- real_t lbA[NCMAX_ALLOC]; /**< Lower constraints' bound vector. */
- real_t ubA[NCMAX_ALLOC]; /**< Upper constraints' bound vector. */
-
- Constraints constraints; /**< Data structure for problem's constraints. */
-
- real_t T[NVMAX*NVMAX]; /**< Reverse triangular matrix, A = [0 T]*Q'. */
- real_t Q[NVMAX*NVMAX]; /**< Orthonormal quadratic matrix, A = [0 T]*Q'. */
- int sizeT; /**< Matrix T is stored in a (sizeT x sizeT) array. */
-
- real_t Ax[NCMAX_ALLOC]; /**< Stores the current product A*x (for increased efficiency only). */
-
- CyclingManager cyclingManager; /**< Data structure for storing (possible) cycling information (NOT YET IMPLEMENTED!). */
-};
-
-
-#include
-
-#endif /* QPOASES_QPROBLEM_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/QProblemB.hpp b/phonelibs/qpoases/INCLUDE/QProblemB.hpp
deleted file mode 100644
index 49ace9ef9..000000000
--- a/phonelibs/qpoases/INCLUDE/QProblemB.hpp
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/QProblemB.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the QProblemB class which is able to use the newly
- * developed online active set strategy for parametric quadratic programming
- * for problems with (simple) bounds only.
- */
-
-
-
-#ifndef QPOASES_QPROBLEMB_HPP
-#define QPOASES_QPROBLEMB_HPP
-
-
-#include
-
-
-
-class SolutionAnalysis;
-
-/** Class for setting up and solving quadratic programs with (simple) bounds only.
- * The main feature is the possibily to use the newly developed online active set strategy
- * for parametric quadratic programming.
- *
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- */
-class QProblemB
-{
- /* allow SolutionAnalysis class to access private members */
- friend class SolutionAnalysis;
-
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- QProblemB( );
-
- /** Constructor which takes the QP dimension only. */
- QProblemB( int _nV /**< Number of variables. */
- );
-
- /** Copy constructor (deep copy). */
- QProblemB( const QProblemB& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~QProblemB( );
-
- /** Assignment operator (deep copy). */
- QProblemB& operator=( const QProblemB& rhs /**< Rhs object. */
- );
-
-
- /** Clears all data structures of QProblemB except for QP data.
- * \return SUCCESSFUL_RETURN \n
- RET_RESET_FAILED */
- returnValue reset( );
-
-
- /** Initialises a QProblemB with given QP data and solves it
- * using an initial homotopy with empty working set (at most nWSR iterations).
- * \return SUCCESSFUL_RETURN \n
- RET_INIT_FAILED \n
- RET_INIT_FAILED_CHOLESKY \n
- RET_INIT_FAILED_HOTSTART \n
- RET_INIT_FAILED_INFEASIBILITY \n
- RET_INIT_FAILED_UNBOUNDEDNESS \n
- RET_MAX_NWSR_REACHED \n
- RET_INVALID_ARGUMENTS \n
- RET_INACCURATE_SOLUTION \n
- RET_NO_SOLUTION */
- returnValue init( const real_t* const _H, /**< Hessian matrix. */
- const real_t* const _g, /**< Gradient vector. */
- const real_t* const _lb, /**< Lower bounds (on variables). \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const _ub, /**< Upper bounds (on variables). \n
- If no upper bounds exist, a NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n
- Output: Number of performed working set recalculations. */
- const real_t* const yOpt = 0, /**< Initial guess for dual solution vector. */
- real_t* const cputime = 0 /**< Output: CPU time required to initialise QP. */
- );
-
-
- /** Initialises a QProblemB with given QP data and solves it
- * using an initial homotopy with empty working set (at most nWSR iterations).
- * \return SUCCESSFUL_RETURN \n
- RET_INIT_FAILED \n
- RET_INIT_FAILED_CHOLESKY \n
- RET_INIT_FAILED_HOTSTART \n
- RET_INIT_FAILED_INFEASIBILITY \n
- RET_INIT_FAILED_UNBOUNDEDNESS \n
- RET_MAX_NWSR_REACHED \n
- RET_INVALID_ARGUMENTS \n
- RET_INACCURATE_SOLUTION \n
- RET_NO_SOLUTION */
- returnValue init( const real_t* const _H, /**< Hessian matrix. */
- const real_t* const _R, /**< Cholesky factorization of the Hessian matrix. */
- const real_t* const _g, /**< Gradient vector. */
- const real_t* const _lb, /**< Lower bounds (on variables). \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const _ub, /**< Upper bounds (on variables). \n
- If no upper bounds exist, a NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n
- Output: Number of performed working set recalculations. */
- const real_t* const yOpt = 0, /**< Initial guess for dual solution vector. */
- real_t* const cputime = 0 /**< Output: CPU time required to initialise QP. */
- );
-
-
- /** Solves an initialised QProblemB using online active set strategy.
- * \return SUCCESSFUL_RETURN \n
- RET_MAX_NWSR_REACHED \n
- RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n
- RET_HOTSTART_FAILED \n
- RET_SHIFT_DETERMINATION_FAILED \n
- RET_STEPDIRECTION_DETERMINATION_FAILED \n
- RET_STEPLENGTH_DETERMINATION_FAILED \n
- RET_HOMOTOPY_STEP_FAILED \n
- RET_HOTSTART_STOPPED_INFEASIBILITY \n
- RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n
- RET_INACCURATE_SOLUTION \n
- RET_NO_SOLUTION */
- returnValue hotstart( const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */
- const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n
- If no upper bounds exist, a NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations; \n
- Output: Number of performed working set recalculations. */
- real_t* const cputime /**< Output: CPU time required to solve QP (or to perform nWSR iterations). */
- );
-
-
- /** Returns Hessian matrix of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getH( real_t* const _H /**< Array of appropriate dimension for copying Hessian matrix.*/
- ) const;
-
- /** Returns gradient vector of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getG( real_t* const _g /**< Array of appropriate dimension for copying gradient vector.*/
- ) const;
-
- /** Returns lower bound vector of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getLB( real_t* const _lb /**< Array of appropriate dimension for copying lower bound vector.*/
- ) const;
-
- /** Returns single entry of lower bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue getLB( int number, /**< Number of entry to be returned. */
- real_t& value /**< Output: lb[number].*/
- ) const;
-
- /** Returns upper bound vector of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getUB( real_t* const _ub /**< Array of appropriate dimension for copying upper bound vector.*/
- ) const;
-
- /** Returns single entry of upper bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue getUB( int number, /**< Number of entry to be returned. */
- real_t& value /**< Output: ub[number].*/
- ) const;
-
-
- /** Returns current bounds object of the QP (deep copy).
- * \return SUCCESSFUL_RETURN */
- inline returnValue getBounds( Bounds* const _bounds /** Output: Bounds object. */
- ) const;
-
-
- /** Returns the number of variables.
- * \return Number of variables. */
- inline int getNV( ) const;
-
- /** Returns the number of free variables.
- * \return Number of free variables. */
- inline int getNFR( );
-
- /** Returns the number of fixed variables.
- * \return Number of fixed variables. */
- inline int getNFX( );
-
- /** Returns the number of implicitly fixed variables.
- * \return Number of implicitly fixed variables. */
- inline int getNFV( ) const;
-
- /** Returns the dimension of null space.
- * \return Dimension of null space. */
- int getNZ( );
-
-
- /** Returns the optimal objective function value.
- * \return finite value: Optimal objective function value (QP was solved) \n
- +infinity: QP was not yet solved */
- real_t getObjVal( ) const;
-
- /** Returns the objective function value at an arbitrary point x.
- * \return Objective function value at point x */
- real_t getObjVal( const real_t* const _x /**< Point at which the objective function shall be evaluated. */
- ) const;
-
- /** Returns the primal solution vector.
- * \return SUCCESSFUL_RETURN \n
- RET_QP_NOT_SOLVED */
- returnValue getPrimalSolution( real_t* const xOpt /**< Output: Primal solution vector (if QP has been solved). */
- ) const;
-
- /** Returns the dual solution vector.
- * \return SUCCESSFUL_RETURN \n
- RET_QP_NOT_SOLVED */
- returnValue getDualSolution( real_t* const yOpt /**< Output: Dual solution vector (if QP has been solved). */
- ) const;
-
-
- /** Returns status of the solution process.
- * \return Status of solution process. */
- inline QProblemStatus getStatus( ) const;
-
-
- /** Returns if the QProblem object is initialised.
- * \return BT_TRUE: QProblemB initialised \n
- BT_FALSE: QProblemB not initialised */
- inline BooleanType isInitialised( ) const;
-
- /** Returns if the QP has been solved.
- * \return BT_TRUE: QProblemB solved \n
- BT_FALSE: QProblemB not solved */
- inline BooleanType isSolved( ) const;
-
- /** Returns if the QP is infeasible.
- * \return BT_TRUE: QP infeasible \n
- BT_FALSE: QP feasible (or not known to be infeasible!) */
- inline BooleanType isInfeasible( ) const;
-
- /** Returns if the QP is unbounded.
- * \return BT_TRUE: QP unbounded \n
- BT_FALSE: QP unbounded (or not known to be unbounded!) */
- inline BooleanType isUnbounded( ) const;
-
-
- /** Returns the print level.
- * \return Print level. */
- inline PrintLevel getPrintLevel( ) const;
-
- /** Changes the print level.
- * \return SUCCESSFUL_RETURN */
- returnValue setPrintLevel( PrintLevel _printlevel /**< New print level. */
- );
-
-
- /** Returns Hessian type flag (type is not determined due to this call!).
- * \return Hessian type. */
- inline HessianType getHessianType( ) const;
-
- /** Changes the print level.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setHessianType( HessianType _hessianType /**< New Hessian type. */
- );
-
-
- /*
- * PROTECTED MEMBER FUNCTIONS
- */
- protected:
- /** Checks if Hessian happens to be the identity matrix,
- * and sets corresponding status flag (otherwise the flag remains unaltered!).
- * \return SUCCESSFUL_RETURN */
- returnValue checkForIdentityHessian( );
-
- /** Determines type of constraints and bounds (i.e. implicitly fixed, unbounded etc.).
- * \return SUCCESSFUL_RETURN \n
- RET_SETUPSUBJECTTOTYPE_FAILED */
- returnValue setupSubjectToType( );
-
- /** Computes the Cholesky decomposition R of the (simply projected) Hessian (i.e. R^T*R = Z^T*H*Z).
- * It only works in the case where Z is a simple projection matrix!
- * \return SUCCESSFUL_RETURN \n
- * RET_INDEXLIST_CORRUPTED */
- returnValue setupCholeskyDecomposition( );
-
-
- /** Solves a QProblemB whose QP data is assumed to be stored in the member variables.
- * A guess for its primal/dual optimal solution vectors and the corresponding
- * optimal working set can be provided.
- * \return SUCCESSFUL_RETURN \n
- RET_INIT_FAILED \n
- RET_INIT_FAILED_CHOLESKY \n
- RET_INIT_FAILED_HOTSTART \n
- RET_INIT_FAILED_INFEASIBILITY \n
- RET_INIT_FAILED_UNBOUNDEDNESS \n
- RET_MAX_NWSR_REACHED */
- returnValue solveInitialQP( const real_t* const xOpt, /**< Optimal primal solution vector.
- * A NULL pointer can be passed. */
- const real_t* const yOpt, /**< Optimal dual solution vector.
- * A NULL pointer can be passed. */
- const Bounds* const guessedBounds, /**< Guessed working set for solution (xOpt,yOpt).
- * A NULL pointer can be passed. */
- int& nWSR, /**< Input: Maximum number of working set recalculations; \n
- * Output: Number of performed working set recalculations. */
- real_t* const cputime /**< Output: CPU time required to solve QP (or to perform nWSR iterations). */
- );
-
-
- /** Obtains the desired working set for the auxiliary initial QP in
- * accordance with the user specifications
- * \return SUCCESSFUL_RETURN \n
- RET_OBTAINING_WORKINGSET_FAILED \n
- RET_INVALID_ARGUMENTS */
- returnValue obtainAuxiliaryWorkingSet( const real_t* const xOpt, /**< Optimal primal solution vector.
- * If a NULL pointer is passed, all entries are assumed to be zero. */
- const real_t* const yOpt, /**< Optimal dual solution vector.
- * If a NULL pointer is passed, all entries are assumed to be zero. */
- const Bounds* const guessedBounds, /**< Guessed working set for solution (xOpt,yOpt). */
- Bounds* auxiliaryBounds /**< Input: Allocated bound object. \n
- * Ouput: Working set for auxiliary QP. */
- ) const;
-
- /** Setups bound data structure according to auxiliaryBounds.
- * (If the working set shall be setup afresh, make sure that
- * bounds data structure has been resetted!)
- * \return SUCCESSFUL_RETURN \n
- RET_SETUP_WORKINGSET_FAILED \n
- RET_INVALID_ARGUMENTS \n
- RET_UNKNOWN BUG */
- returnValue setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds, /**< Working set for auxiliary QP. */
- BooleanType setupAfresh /**< Flag indicating if given working set shall be
- * setup afresh or by updating the current one. */
- );
-
- /** Setups the optimal primal/dual solution of the auxiliary initial QP.
- * \return SUCCESSFUL_RETURN */
- returnValue setupAuxiliaryQPsolution( const real_t* const xOpt, /**< Optimal primal solution vector.
- * If a NULL pointer is passed, all entries are set to zero. */
- const real_t* const yOpt /**< Optimal dual solution vector.
- * If a NULL pointer is passed, all entries are set to zero. */
- );
-
- /** Setups gradient of the auxiliary initial QP for given
- * optimal primal/dual solution and given initial working set
- * (assumes that members X, Y and BOUNDS have already been initialised!).
- * \return SUCCESSFUL_RETURN */
- returnValue setupAuxiliaryQPgradient( );
-
- /** Setups bounds of the auxiliary initial QP for given
- * optimal primal/dual solution and given initial working set
- * (assumes that members X, Y and BOUNDS have already been initialised!).
- * \return SUCCESSFUL_RETURN \n
- RET_UNKNOWN BUG */
- returnValue setupAuxiliaryQPbounds( BooleanType useRelaxation /**< Flag indicating if inactive bounds shall be relaxed. */
- );
-
-
- /** Adds a bound to active set (specialised version for the case where no constraints exist).
- * \return SUCCESSFUL_RETURN \n
- RET_ADDBOUND_FAILED */
- returnValue addBound( int number, /**< Number of bound to be added to active set. */
- SubjectToStatus B_status, /**< Status of new active bound. */
- BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */
- );
-
- /** Removes a bounds from active set (specialised version for the case where no constraints exist).
- * \return SUCCESSFUL_RETURN \n
- RET_HESSIAN_NOT_SPD \n
- RET_REMOVEBOUND_FAILED */
- returnValue removeBound( int number, /**< Number of bound to be removed from active set. */
- BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */
- );
-
-
- /** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix.
- * \return SUCCESSFUL_RETURN \n
- RET_DIV_BY_ZERO */
- returnValue backsolveR( const real_t* const b, /**< Right hand side vector. */
- BooleanType transposed, /**< Indicates if the transposed system shall be solved. */
- real_t* const a /**< Output: Solution vector */
- );
-
- /** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. \n
- * Special variant for the case that this function is called from within "removeBound()".
- * \return SUCCESSFUL_RETURN \n
- RET_DIV_BY_ZERO */
- returnValue backsolveR( const real_t* const b, /**< Right hand side vector. */
- BooleanType transposed, /**< Indicates if the transposed system shall be solved. */
- BooleanType removingBound, /**< Indicates if function is called from "removeBound()". */
- real_t* const a /**< Output: Solution vector */
- );
-
-
- /** Determines step direction of the shift of the QP data.
- * \return SUCCESSFUL_RETURN */
- returnValue hotstart_determineDataShift(const int* const FX_idx, /**< Index array of fixed variables. */
- const real_t* const g_new, /**< New gradient vector. */
- const real_t* const lb_new, /**< New lower bounds. */
- const real_t* const ub_new, /**< New upper bounds. */
- real_t* const delta_g, /**< Output: Step direction of gradient vector. */
- real_t* const delta_lb, /**< Output: Step direction of lower bounds. */
- real_t* const delta_ub, /**< Output: Step direction of upper bounds. */
- BooleanType& Delta_bB_isZero/**< Output: Indicates if active bounds are to be shifted. */
- );
-
-
- /** Checks if lower/upper bounds remain consistent
- * (i.e. if lb <= ub) during the current step.
- * \return BT_TRUE iff bounds remain consistent
- */
- BooleanType areBoundsConsistent( const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub /**< Step direction of upper bounds. */
- ) const;
-
-
- /** Setups internal QP data.
- * \return SUCCESSFUL_RETURN \n
- RET_INVALID_ARGUMENTS */
- returnValue setupQPdata( const real_t* const _H, /**< Hessian matrix. */
- const real_t* const _R, /**< Cholesky factorization of the Hessian matrix. */
- const real_t* const _g, /**< Gradient vector. */
- const real_t* const _lb, /**< Lower bounds (on variables). \n
- If no lower bounds exist, a NULL pointer can be passed. */
- const real_t* const _ub /**< Upper bounds (on variables). \n
- If no upper bounds exist, a NULL pointer can be passed. */
- );
-
-
- /** Sets Hessian matrix of the QP.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setH( const real_t* const H_new /**< New Hessian matrix (with correct dimension!). */
- );
-
- /** Changes gradient vector of the QP.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setG( const real_t* const g_new /**< New gradient vector (with correct dimension!). */
- );
-
- /** Changes lower bound vector of the QP.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setLB( const real_t* const lb_new /**< New lower bound vector (with correct dimension!). */
- );
-
- /** Changes single entry of lower bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue setLB( int number, /**< Number of entry to be changed. */
- real_t value /**< New value for entry of lower bound vector. */
- );
-
- /** Changes upper bound vector of the QP.
- * \return SUCCESSFUL_RETURN */
- inline returnValue setUB( const real_t* const ub_new /**< New upper bound vector (with correct dimension!). */
- );
-
- /** Changes single entry of upper bound vector of the QP.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue setUB( int number, /**< Number of entry to be changed. */
- real_t value /**< New value for entry of upper bound vector. */
- );
-
-
- /** Computes parameters for the Givens matrix G for which [x,y]*G = [z,0]
- * \return SUCCESSFUL_RETURN */
- inline void computeGivens( real_t xold, /**< Matrix entry to be normalised. */
- real_t yold, /**< Matrix entry to be annihilated. */
- real_t& xnew, /**< Output: Normalised matrix entry. */
- real_t& ynew, /**< Output: Annihilated matrix entry. */
- real_t& c, /**< Output: Cosine entry of Givens matrix. */
- real_t& s /**< Output: Sine entry of Givens matrix. */
- ) const;
-
- /** Applies Givens matrix determined by c and s (cf. computeGivens).
- * \return SUCCESSFUL_RETURN */
- inline void applyGivens( real_t c, /**< Cosine entry of Givens matrix. */
- real_t s, /**< Sine entry of Givens matrix. */
- real_t xold, /**< Matrix entry to be transformed corresponding to
- * the normalised entry of the original matrix. */
- real_t yold, /**< Matrix entry to be transformed corresponding to
- * the annihilated entry of the original matrix. */
- real_t& xnew, /**< Output: Transformed matrix entry corresponding to
- * the normalised entry of the original matrix. */
- real_t& ynew /**< Output: Transformed matrix entry corresponding to
- * the annihilated entry of the original matrix. */
- ) const;
-
-
- /*
- * PRIVATE MEMBER FUNCTIONS
- */
- private:
- /** Determines step direction of the homotopy path.
- * \return SUCCESSFUL_RETURN \n
- RET_STEPDIRECTION_FAILED_CHOLESKY */
- returnValue hotstart_determineStepDirection(const int* const FR_idx, /**< Index array of free variables. */
- const int* const FX_idx, /**< Index array of fixed variables. */
- const real_t* const delta_g, /**< Step direction of gradient vector. */
- const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub, /**< Step direction of upper bounds. */
- BooleanType Delta_bB_isZero, /**< Indicates if active bounds are to be shifted. */
- real_t* const delta_xFX, /**< Output: Primal homotopy step direction of fixed variables. */
- real_t* const delta_xFR, /**< Output: Primal homotopy step direction of free variables. */
- real_t* const delta_yFX /**< Output: Dual homotopy step direction of fixed variables' multiplier. */
- );
-
- /** Determines the maximum possible step length along the homotopy path.
- * \return SUCCESSFUL_RETURN */
- returnValue hotstart_determineStepLength( const int* const FR_idx, /**< Index array of free variables. */
- const int* const FX_idx, /**< Index array of fixed variables. */
- const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub, /**< Step direction of upper bounds. */
- const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */
- const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */
- int& BC_idx, /**< Output: Index of blocking constraint. */
- SubjectToStatus& BC_status /**< Output: Status of blocking constraint. */
- );
-
- /** Performs a step along the homotopy path (and updates active set).
- * \return SUCCESSFUL_RETURN \n
- RET_OPTIMAL_SOLUTION_FOUND \n
- RET_REMOVE_FROM_ACTIVESET_FAILED \n
- RET_ADD_TO_ACTIVESET_FAILED \n
- RET_QP_INFEASIBLE */
- returnValue hotstart_performStep( const int* const FR_idx, /**< Index array of free variables. */
- const int* const FX_idx, /**< Index array of fixed variables. */
- const real_t* const delta_g, /**< Step direction of gradient vector. */
- const real_t* const delta_lb, /**< Step direction of lower bounds. */
- const real_t* const delta_ub, /**< Step direction of upper bounds. */
- const real_t* const delta_xFX, /**< Primal homotopy step direction of fixed variables. */
- const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */
- const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */
- int BC_idx, /**< Index of blocking constraint. */
- SubjectToStatus BC_status /**< Status of blocking constraint. */
- );
-
-
- #ifdef PC_DEBUG /* Define print functions only for debugging! */
-
- /** Prints concise information on the current iteration.
- * \return SUCCESSFUL_RETURN \n */
- returnValue printIteration( int iteration, /**< Number of current iteration. */
- int BC_idx, /**< Index of blocking bound. */
- SubjectToStatus BC_status /**< Status of blocking bound. */
- );
-
- #endif /* PC_DEBUG */
-
-
- /** Determines the maximum violation of the KKT optimality conditions
- * of the current iterate within the QProblemB object.
- * \return SUCCESSFUL_RETURN \n
- * RET_INACCURATE_SOLUTION \n
- * RET_NO_SOLUTION */
- returnValue checkKKTconditions( );
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- real_t H[NVMAX*NVMAX]; /**< Hessian matrix. */
- BooleanType hasHessian; /**< Flag indicating whether H contains Hessian or corresponding Cholesky factor R; \sa init. */
-
- real_t g[NVMAX]; /**< Gradient. */
- real_t lb[NVMAX]; /**< Lower bound vector (on variables). */
- real_t ub[NVMAX]; /**< Upper bound vector (on variables). */
-
- Bounds bounds; /**< Data structure for problem's bounds. */
-
- real_t R[NVMAX*NVMAX]; /**< Cholesky decomposition of H (i.e. H = R^T*R). */
- BooleanType hasCholesky; /**< Flag indicating whether Cholesky decomposition has already been setup. */
-
- real_t x[NVMAX]; /**< Primal solution vector. */
- real_t y[NVMAX+NCMAX]; /**< Dual solution vector. */
-
- real_t tau; /**< Last homotopy step length. */
-
- QProblemStatus status; /**< Current status of the solution process. */
-
- BooleanType infeasible; /**< QP infeasible? */
- BooleanType unbounded; /**< QP unbounded? */
-
- HessianType hessianType; /**< Type of Hessian matrix. */
-
- PrintLevel printlevel; /**< Print level. */
-
- int count; /**< Counts the number of hotstart function calls (internal usage only!). */
-};
-
-
-#include
-
-#endif /* QPOASES_QPROBLEMB_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/SubjectTo.hpp b/phonelibs/qpoases/INCLUDE/SubjectTo.hpp
deleted file mode 100644
index e07bf0421..000000000
--- a/phonelibs/qpoases/INCLUDE/SubjectTo.hpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/SubjectTo.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of the SubjectTo class designed to manage working sets of
- * constraints and bounds within a QProblem.
- */
-
-
-#ifndef QPOASES_SUBJECTTO_HPP
-#define QPOASES_SUBJECTTO_HPP
-
-
-#include
-
-
-
-/** This class manages working sets of constraints and bounds by storing
- * index sets and other status information.
- *
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- */
-class SubjectTo
-{
- /*
- * PUBLIC MEMBER FUNCTIONS
- */
- public:
- /** Default constructor. */
- SubjectTo( );
-
- /** Copy constructor (deep copy). */
- SubjectTo( const SubjectTo& rhs /**< Rhs object. */
- );
-
- /** Destructor. */
- ~SubjectTo( );
-
- /** Assignment operator (deep copy). */
- SubjectTo& operator=( const SubjectTo& rhs /**< Rhs object. */
- );
-
-
- /** Pseudo-constructor takes the number of constraints or bounds.
- * \return SUCCESSFUL_RETURN */
- returnValue init( int n /**< Number of constraints or bounds. */
- );
-
-
- /** Returns type of (constraints') bound.
- * \return Type of (constraints') bound \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline SubjectToType getType( int i /**< Number of (constraints') bound. */
- ) const ;
-
- /** Returns status of (constraints') bound.
- * \return Status of (constraints') bound \n
- ST_UNDEFINED */
- inline SubjectToStatus getStatus( int i /**< Number of (constraints') bound. */
- ) const;
-
-
- /** Sets type of (constraints') bound.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue setType( int i, /**< Number of (constraints') bound. */
- SubjectToType value /**< Type of (constraints') bound. */
- );
-
- /** Sets status of (constraints') bound.
- * \return SUCCESSFUL_RETURN \n
- RET_INDEX_OUT_OF_BOUNDS */
- inline returnValue setStatus( int i, /**< Number of (constraints') bound. */
- SubjectToStatus value /**< Status of (constraints') bound. */
- );
-
-
- /** Sets status of lower (constraints') bounds. */
- inline void setNoLower( BooleanType _status /**< Status of lower (constraints') bounds. */
- );
-
- /** Sets status of upper (constraints') bounds. */
- inline void setNoUpper( BooleanType _status /**< Status of upper (constraints') bounds. */
- );
-
-
- /** Returns status of lower (constraints') bounds.
- * \return BT_TRUE if there is no lower (constraints') bound on any variable. */
- inline BooleanType isNoLower( ) const;
-
- /** Returns status of upper bounds.
- * \return BT_TRUE if there is no upper (constraints') bound on any variable. */
- inline BooleanType isNoUpper( ) const;
-
-
- /*
- * PROTECTED MEMBER FUNCTIONS
- */
- protected:
- /** Adds the index of a new constraint or bound to index set.
- * \return SUCCESSFUL_RETURN \n
- RET_ADDINDEX_FAILED */
- returnValue addIndex( Indexlist* const indexlist, /**< Index list to which the new index shall be added. */
- int newnumber, /**< Number of new constraint or bound. */
- SubjectToStatus newstatus /**< Status of new constraint or bound. */
- );
-
- /** Removes the index of a constraint or bound from index set.
- * \return SUCCESSFUL_RETURN \n
- RET_UNKNOWN_BUG */
- returnValue removeIndex( Indexlist* const indexlist, /**< Index list from which the new index shall be removed. */
- int removenumber /**< Number of constraint or bound to be removed. */
- );
-
- /** Swaps the indices of two constraints or bounds within the index set.
- * \return SUCCESSFUL_RETURN \n
- RET_SWAPINDEX_FAILED */
- returnValue swapIndex( Indexlist* const indexlist, /**< Index list in which the indices shold be swapped. */
- int number1, /**< Number of first constraint or bound. */
- int number2 /**< Number of second constraint or bound. */
- );
-
-
- /*
- * PROTECTED MEMBER VARIABLES
- */
- protected:
- SubjectToType type[NVMAX+NCMAX]; /**< Type of constraints/bounds. */
- SubjectToStatus status[NVMAX+NCMAX]; /**< Status of constraints/bounds. */
-
- BooleanType noLower; /**< This flag indicates if there is no lower bound on any variable. */
- BooleanType noUpper; /**< This flag indicates if there is no upper bound on any variable. */
-
-
- /*
- * PRIVATE MEMBER VARIABLES
- */
- private:
- int size;
-};
-
-
-
-#include
-
-#endif /* QPOASES_SUBJECTTO_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/Types.hpp b/phonelibs/qpoases/INCLUDE/Types.hpp
deleted file mode 100644
index 5b873ad07..000000000
--- a/phonelibs/qpoases/INCLUDE/Types.hpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/Types.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2008
- *
- * Declaration of all non-built-in types (except for classes).
- */
-
-
-#ifndef QPOASES_TYPES_HPP
-#define QPOASES_TYPES_HPP
-
-
-
-/** Define real_t for facilitating switching between double and float. */
-// typedef double real_t;
-
-
-/** Summarises all possible logical values. */
-enum BooleanType
-{
- BT_FALSE, /**< Logical value for "false". */
- BT_TRUE /**< Logical value for "true". */
-};
-
-
-/** Summarises all possible print levels. Print levels are used to describe
- * the desired amount of output during runtime of qpOASES. */
-enum PrintLevel
-{
- PL_NONE, /**< No output. */
- PL_LOW, /**< Print error messages only. */
- PL_MEDIUM, /**< Print error and warning messages as well as concise info messages. */
- PL_HIGH /**< Print all messages with full details. */
-};
-
-
-/** Defines visibility status of a message. */
-enum VisibilityStatus
-{
- VS_VISIBLE, /**< Message visible. */
- VS_HIDDEN /**< Message not visible. */
-};
-
-
-/** Summarises all possible states of the (S)QProblem(B) object during the
-solution process of a QP sequence. */
-enum QProblemStatus
-{
- QPS_NOTINITIALISED, /**< QProblem object is freshly instantiated or reset. */
- QPS_PREPARINGAUXILIARYQP, /**< An auxiliary problem is currently setup, either at the very beginning
- * via an initial homotopy or after changing the QP matrices. */
- QPS_AUXILIARYQPSOLVED, /**< An auxilary problem was solved, either at the very beginning
- * via an initial homotopy or after changing the QP matrices. */
- QPS_PERFORMINGHOMOTOPY, /**< A homotopy according to the main idea of the online active
- * set strategy is performed. */
- QPS_HOMOTOPYQPSOLVED, /**< An intermediate QP along the homotopy path was solved. */
- QPS_SOLVED /**< The solution of the actual QP was found. */
-};
-
-
-/** Summarises all possible types of bounds and constraints. */
-enum SubjectToType
-{
- ST_UNBOUNDED, /**< Bound/constraint is unbounded. */
- ST_BOUNDED, /**< Bound/constraint is bounded but not fixed. */
- ST_EQUALITY, /**< Bound/constraint is fixed (implicit equality bound/constraint). */
- ST_UNKNOWN /**< Type of bound/constraint unknown. */
-};
-
-
-/** Summarises all possible states of bounds and constraints. */
-enum SubjectToStatus
-{
- ST_INACTIVE, /**< Bound/constraint is inactive. */
- ST_LOWER, /**< Bound/constraint is at its lower bound. */
- ST_UPPER, /**< Bound/constraint is at its upper bound. */
- ST_UNDEFINED /**< Status of bound/constraint undefined. */
-};
-
-
-/** Summarises all possible cycling states of bounds and constraints. */
-enum CyclingStatus
-{
- CYC_NOT_INVOLVED, /**< Bound/constraint is not involved in current cycling. */
- CYC_PREV_ADDED, /**< Bound/constraint has previously been added during the current cycling. */
- CYC_PREV_REMOVED /**< Bound/constraint has previously been removed during the current cycling. */
-};
-
-
-/** Summarises all possible types of the QP's Hessian matrix. */
-enum HessianType
-{
- HST_SEMIDEF, /**< Hessian is positive semi-definite. */
- HST_POSDEF_NULLSPACE, /**< Hessian is positive definite on null space of active bounds/constraints. */
- HST_POSDEF, /**< Hessian is (strictly) positive definite. */
- HST_IDENTITY /**< Hessian is identity matrix. */
-};
-
-
-
-#endif /* QPOASES_TYPES_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/INCLUDE/Utils.hpp b/phonelibs/qpoases/INCLUDE/Utils.hpp
deleted file mode 100644
index a91ee78cc..000000000
--- a/phonelibs/qpoases/INCLUDE/Utils.hpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file INCLUDE/Utils.hpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of global utility functions for working with qpOASES.
- */
-
-
-#ifndef QPOASES_UTILS_HPP
-#define QPOASES_UTILS_HPP
-
-
-#include
-
-
-#ifdef PC_DEBUG /* Define print functions only for debugging! */
-
-/** Prints a vector.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const real_t* const v, /**< Vector to be printed. */
- int n /**< Length of vector. */
- );
-
-/** Prints a permuted vector.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const real_t* const v, /**< Vector to be printed. */
- int n, /**< Length of vector. */
- const int* const V_idx /**< Pemutation vector. */
- );
-
-/** Prints a named vector.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const real_t* const v, /**< Vector to be printed. */
- int n, /**< Length of vector. */
- const char* name /** Name of vector. */
- );
-
-/** Prints a matrix.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const real_t* const M, /**< Matrix to be printed. */
- int nrow, /**< Row number of matrix. */
- int ncol /**< Column number of matrix. */
- );
-
-/** Prints a permuted matrix.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const real_t* const M, /**< Matrix to be printed. */
- int nrow, /**< Row number of matrix. */
- int ncol , /**< Column number of matrix. */
- const int* const ROW_idx, /**< Row pemutation vector. */
- const int* const COL_idx /**< Column pemutation vector. */
- );
-
-/** Prints a named matrix.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const real_t* const M, /**< Matrix to be printed. */
- int nrow, /**< Row number of matrix. */
- int ncol, /**< Column number of matrix. */
- const char* name /** Name of matrix. */
- );
-
-/** Prints an index array.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const int* const index, /**< Index array to be printed. */
- int n /**< Length of index array. */
- );
-
-/** Prints a named index array.
- * \return SUCCESSFUL_RETURN */
-returnValue print( const int* const index, /**< Index array to be printed. */
- int n, /**< Length of index array. */
- const char* name /**< Name of index array. */
- );
-
-
-/** Prints a string to desired output target (useful also for MATLAB output!).
- * \return SUCCESSFUL_RETURN */
-returnValue myPrintf( const char* s /**< String to be written. */
- );
-
-
-/** Prints qpOASES copyright notice.
- * \return SUCCESSFUL_RETURN */
-returnValue printCopyrightNotice( );
-
-
-/** Reads a real_t matrix from file.
- * \return SUCCESSFUL_RETURN \n
- RET_UNABLE_TO_OPEN_FILE \n
- RET_UNABLE_TO_READ_FILE */
-returnValue readFromFile( real_t* data, /**< Matrix to be read from file. */
- int nrow, /**< Row number of matrix. */
- int ncol, /**< Column number of matrix. */
- const char* datafilename /**< Data file name. */
- );
-
-/** Reads a real_t vector from file.
- * \return SUCCESSFUL_RETURN \n
- RET_UNABLE_TO_OPEN_FILE \n
- RET_UNABLE_TO_READ_FILE */
-returnValue readFromFile( real_t* data, /**< Vector to be read from file. */
- int n, /**< Length of vector. */
- const char* datafilename /**< Data file name. */
- );
-
-/** Reads an integer (column) vector from file.
- * \return SUCCESSFUL_RETURN \n
- RET_UNABLE_TO_OPEN_FILE \n
- RET_UNABLE_TO_READ_FILE */
-returnValue readFromFile( int* data, /**< Vector to be read from file. */
- int n, /**< Length of vector. */
- const char* datafilename /**< Data file name. */
- );
-
-
-/** Writes a real_t matrix into a file.
- * \return SUCCESSFUL_RETURN \n
- RET_UNABLE_TO_OPEN_FILE */
-returnValue writeIntoFile( const real_t* const data, /**< Matrix to be written into file. */
- int nrow, /**< Row number of matrix. */
- int ncol, /**< Column number of matrix. */
- const char* datafilename, /**< Data file name. */
- BooleanType append /**< Indicates if data shall be appended if the file already exists (otherwise it is overwritten). */
- );
-
-/** Writes a real_t vector into a file.
- * \return SUCCESSFUL_RETURN \n
- RET_UNABLE_TO_OPEN_FILE */
-returnValue writeIntoFile( const real_t* const data, /**< Vector to be written into file. */
- int n, /**< Length of vector. */
- const char* datafilename, /**< Data file name. */
- BooleanType append /**< Indicates if data shall be appended if the file already exists (otherwise it is overwritten). */
- );
-
-/** Writes an integer (column) vector into a file.
- * \return SUCCESSFUL_RETURN \n
- RET_UNABLE_TO_OPEN_FILE */
-returnValue writeIntoFile( const int* const integer, /**< Integer vector to be written into file. */
- int n, /**< Length of vector. */
- const char* datafilename, /**< Data file name. */
- BooleanType append /**< Indicates if integer shall be appended if the file already exists (otherwise it is overwritten). */
- );
-
-#endif /* PC_DEBUG */
-
-
-/** Returns the current system time.
- * \return current system time */
-real_t getCPUtime( );
-
-
-/** Returns the Euclidean norm of a vector.
- * \return 0: successful */
-real_t getNorm( const real_t* const v, /**< Vector. */
- int n /**< Vector's dimension. */
- );
-
-/** Returns the absolute value of a real_t.
- * \return Absolute value of a real_t */
-inline real_t getAbs( real_t x /**< Input argument. */
- );
-
-
-
-#include
-
-#endif /* QPOASES_UTILS_HPP */
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/LICENSE.txt b/phonelibs/qpoases/LICENSE.txt
deleted file mode 100644
index 5ab7695ab..000000000
--- a/phonelibs/qpoases/LICENSE.txt
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- , 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/phonelibs/qpoases/README.txt b/phonelibs/qpoases/README.txt
deleted file mode 100644
index 53fc2ab4f..000000000
--- a/phonelibs/qpoases/README.txt
+++ /dev/null
@@ -1,92 +0,0 @@
-##
-## qpOASES -- An Implementation of the Online Active Set Strategy.
-## Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
-##
-## qpOASES is free software; you can redistribute it and/or
-## modify it under the terms of the GNU Lesser General Public
-## License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-##
-## qpOASES 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.
-##
-## You should have received a copy of the GNU Lesser General Public
-## License along with qpOASES; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-##
-
-
-
-INTRODUCTION
-=============
-
-qpOASES is an open-source C++ implementation of the recently proposed
-online active set strategy (see [1], [2]), which was inspired by important
-observations from the field of parametric quadratic programming. It has
-several theoretical features that make it particularly suited for model
-predictive control (MPC) applications.
-
-The software package qpOASES implements these ideas and has already been
-successfully used for closed-loop control of a real-world Diesel engine [3].
-
-
-References:
-
-[1] H.J. Ferreau. An Online Active Set Strategy for Fast Solution of
-Parametric Quadratic Programs with Applications to Predictive Engine Control.
-Diplom thesis, University of Heidelberg, 2006.
-
-[2] H.J. Ferreau, H.G. Bock, M. Diehl. An online active set strategy to
-overcome the limitations of explicit MPC. International Journal of Robust
-and Nonlinear Control, 18 (8), pp. 816-830, 2008.
-
-[3] H.J. Ferreau, P. Ortner, P. Langthaler, L. del Re, M. Diehl. Predictive
-Control of a Real-World Diesel Engine using an Extended Online Active Set
-Strategy. Annual Reviews in Control, 31 (2), pp. 293-301, 2007.
-
-
-
-GETTING STARTED
-================
-
-1. For installation, usage and additional information on this software package
- see the qpOASES User's Manual located at ./DOC/manual.pdf!
-
-
-2. The file ./LICENSE.txt contains a copy of the GNU Lesser General Public
- License. Please read it carefully before using qpOASES!
-
-
-3. The whole software package can be downloaded from
-
- http://homes.esat.kuleuven.be/~optec/software/qpOASES/
-
- On this webpage you will also find a list of frequently asked questions.
-
-
-
-CONTACT THE AUTHORS
-====================
-
-If you have got questions, remarks or comments on qpOASES
-please contact the main author:
-
- Hans Joachim Ferreau
- Katholieke Universiteit Leuven
- Department of Electrical Engineering (ESAT)
- Kasteelpark Arenberg 10, bus 2446
- B-3001 Leuven-Heverlee, Belgium
-
- Phone: +32 16 32 03 63
- E-mail: joachim.ferreau@esat.kuleuven.be
- qpOASES@esat.kuleuven.be
-
-Also bug reports and source code extensions are most welcome!
-
-
-
-##
-## end of file
-##
diff --git a/phonelibs/qpoases/SConscript b/phonelibs/qpoases/SConscript
deleted file mode 100644
index 932dbc700..000000000
--- a/phonelibs/qpoases/SConscript
+++ /dev/null
@@ -1,16 +0,0 @@
-Import('env', 'interface_dir')
-
-qp_files = [
- Glob("SRC/*.cpp"),
- Glob("SRC/EXTRAS/*.cpp"),
-]
-
-cpp_path = [
- ".",
- "INCLUDE",
- "INCLUDE/EXTRAS",
- "SRC/",
- interface_dir,
-]
-
-env.Library('qpoases', qp_files, CPPPATH=cpp_path)
diff --git a/phonelibs/qpoases/SRC/Bounds.cpp b/phonelibs/qpoases/SRC/Bounds.cpp
deleted file mode 100644
index cf8ed6989..000000000
--- a/phonelibs/qpoases/SRC/Bounds.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/Bounds.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the Bounds class designed to manage working sets of
- * bounds within a QProblem.
- */
-
-
-#include
-
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * B o u n d s
- */
-Bounds::Bounds( ) : SubjectTo( ),
- nV( 0 ),
- nFV( 0 ),
- nBV( 0 ),
- nUV( 0 )
-{
-}
-
-
-/*
- * B o u n d s
- */
-Bounds::Bounds( const Bounds& rhs ) : SubjectTo( rhs ),
- nV( rhs.nV ),
- nFV( rhs.nFV ),
- nBV( rhs.nBV ),
- nUV( rhs.nUV )
-{
- free = rhs.free;
- fixed = rhs.fixed;
-}
-
-
-/*
- * ~ B o u n d s
- */
-Bounds::~Bounds( )
-{
-}
-
-
-/*
- * o p e r a t o r =
- */
-Bounds& Bounds::operator=( const Bounds& rhs )
-{
- if ( this != &rhs )
- {
- SubjectTo::operator=( rhs );
-
- nV = rhs.nV;
- nFV = rhs.nFV;
- nBV = rhs.nBV;
- nUV = rhs.nUV;
-
- free = rhs.free;
- fixed = rhs.fixed;
- }
-
- return *this;
-}
-
-
-/*
- * i n i t
- */
-returnValue Bounds::init( int n )
-{
- nV = n;
- nFV = 0;
- nBV = 0;
- nUV = 0;
-
- free.init( );
- fixed.init( );
-
- return SubjectTo::init( n );
-}
-
-
-/*
- * s e t u p B o u n d
- */
-returnValue Bounds::setupBound( int _number, SubjectToStatus _status
- )
-{
- /* consistency check */
- if ( ( _number < 0 ) || ( _number >= getNV( ) ) )
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-
- /* Add bound index to respective index list. */
- switch ( _status )
- {
- case ST_INACTIVE:
- if ( this->addIndex( this->getFree( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_BOUND_FAILED );
- break;
-
- case ST_LOWER:
- if ( this->addIndex( this->getFixed( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_BOUND_FAILED );
- break;
-
- case ST_UPPER:
- if ( this->addIndex( this->getFixed( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_BOUND_FAILED );
- break;
-
- default:
- return THROWERROR( RET_INVALID_ARGUMENTS );
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t u p A l l F r e e
- */
-returnValue Bounds::setupAllFree( )
-{
- int i;
-
- /* 1) Place unbounded variables at the beginning of the index list of free variables. */
- for( i=0; i= getNV( ) ) )
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-
- /* Move index from indexlist of fixed variables to that of free ones. */
- if ( this->removeIndex( this->getFixed( ),_number ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- if ( this->addIndex( this->getFree( ),_number,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * m o v e F r e e T o F i x e d
- */
-returnValue Bounds::moveFreeToFixed( int _number, SubjectToStatus _status
- )
-{
- /* consistency check */
- if ( ( _number < 0 ) || ( _number >= getNV( ) ) )
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-
- /* Move index from indexlist of free variables to that of fixed ones. */
- if ( this->removeIndex( this->getFree( ),_number ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- if ( this->addIndex( this->getFixed( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s w a p F r e e
- */
-returnValue Bounds::swapFree( int number1, int number2
- )
-{
- /* consistency check */
- if ( ( number1 < 0 ) || ( number1 >= getNV( ) ) || ( number2 < 0 ) || ( number2 >= getNV( ) ) )
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-
- /* Swap index within indexlist of free variables. */
- return this->swapIndex( this->getFree( ),number1,number2 );
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/Bounds.ipp b/phonelibs/qpoases/SRC/Bounds.ipp
deleted file mode 100644
index d2ab1ba2d..000000000
--- a/phonelibs/qpoases/SRC/Bounds.ipp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/Bounds.ipp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of inlined member functions of the Bounds class designed
- * to manage working sets of bounds within a QProblem.
- */
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-/*
- * g e t N V
- */
-inline int Bounds::getNV( ) const
-{
- return nV;
-}
-
-
-/*
- * g e t N F X
- */
-inline int Bounds::getNFV( ) const
-{
- return nFV;
-}
-
-
-/*
- * g e t N B V
- */
-inline int Bounds::getNBV( ) const
-{
- return nBV;
-}
-
-
-/*
- * g e t N U V
- */
-inline int Bounds::getNUV( ) const
-{
- return nUV;
-}
-
-
-
-/*
- * s e t N F X
- */
-inline returnValue Bounds::setNFV( int n )
-{
- nFV = n;
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t N B V
- */
-inline returnValue Bounds::setNBV( int n )
-{
- nBV = n;
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t N U V
- */
-inline returnValue Bounds::setNUV( int n )
-{
- nUV = n;
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * g e t N F R
- */
-inline int Bounds::getNFR( )
-{
- return free.getLength( );
-}
-
-
-/*
- * g e t N F X
- */
-inline int Bounds::getNFX( )
-{
- return fixed.getLength( );
-}
-
-
-/*
- * g e t F r e e
- */
-inline Indexlist* Bounds::getFree( )
-{
- return &free;
-}
-
-
-/*
- * g e t F i x e d
- */
-inline Indexlist* Bounds::getFixed( )
-{
- return &fixed;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/Constraints.cpp b/phonelibs/qpoases/SRC/Constraints.cpp
deleted file mode 100644
index b2ad5bd11..000000000
--- a/phonelibs/qpoases/SRC/Constraints.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/Constraints.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the Constraints class designed to manage working sets of
- * constraints within a QProblem.
- */
-
-
-#include
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * C o n s t r a i n t s
- */
-Constraints::Constraints( ) : SubjectTo( ),
- nC( 0 ),
- nEC( 0 ),
- nIC( 0 ),
- nUC( 0 )
-{
-}
-
-
-/*
- * C o n s t r a i n t s
- */
-Constraints::Constraints( const Constraints& rhs ) : SubjectTo( rhs ),
- nC( rhs.nC ),
- nEC( rhs.nEC ),
- nIC( rhs.nIC ),
- nUC( rhs.nUC )
-{
- active = rhs.active;
- inactive = rhs.inactive;
-}
-
-
-/*
- * ~ C o n s t r a i n t s
- */
-Constraints::~Constraints( )
-{
-}
-
-
-/*
- * o p e r a t o r =
- */
-Constraints& Constraints::operator=( const Constraints& rhs )
-{
- if ( this != &rhs )
- {
- SubjectTo::operator=( rhs );
-
- nC = rhs.nC;
- nEC = rhs.nEC;
- nIC = rhs.nIC;
- nUC = rhs.nUC;
-
- active = rhs.active;
- inactive = rhs.inactive;
- }
-
- return *this;
-}
-
-
-/*
- * i n i t
- */
-returnValue Constraints::init( int n )
-{
- nC = n;
- nEC = 0;
- nIC = 0;
- nUC = 0;
-
- active.init( );
- inactive.init( );
-
- return SubjectTo::init( n );
-}
-
-
-/*
- * s e t u p C o n s t r a i n t
- */
-returnValue Constraints::setupConstraint( int _number, SubjectToStatus _status
- )
-{
- /* consistency check */
- if ( ( _number < 0 ) || ( _number >= getNC( ) ) )
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-
- /* Add constraint index to respective index list. */
- switch ( _status )
- {
- case ST_INACTIVE:
- if ( this->addIndex( this->getInactive( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_CONSTRAINT_FAILED );
- break;
-
- case ST_LOWER:
- if ( this->addIndex( this->getActive( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_CONSTRAINT_FAILED );
- break;
-
- case ST_UPPER:
- if ( this->addIndex( this->getActive( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_CONSTRAINT_FAILED );
- break;
-
- default:
- return THROWERROR( RET_INVALID_ARGUMENTS );
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t u p A l l I n a c t i v e
- */
-returnValue Constraints::setupAllInactive( )
-{
- int i;
-
-
- /* 1) Place unbounded constraints at the beginning of the index list of inactive constraints. */
- for( i=0; i= getNC( ) ) )
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-
- /* Move index from indexlist of active constraints to that of inactive ones. */
- if ( this->removeIndex( this->getActive( ),_number ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- if ( this->addIndex( this->getInactive( ),_number,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * m o v e I n a c t i v e T o A c t i v e
- */
-returnValue Constraints::moveInactiveToActive( int _number, SubjectToStatus _status
- )
-{
- /* consistency check */
- if ( ( _number < 0 ) || ( _number >= getNC( ) ) )
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-
- /* Move index from indexlist of inactive constraints to that of active ones. */
- if ( this->removeIndex( this->getInactive( ),_number ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- if ( this->addIndex( this->getActive( ),_number,_status ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_MOVING_BOUND_FAILED );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/Constraints.ipp b/phonelibs/qpoases/SRC/Constraints.ipp
deleted file mode 100644
index 1b874ef3c..000000000
--- a/phonelibs/qpoases/SRC/Constraints.ipp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/Constraints.ipp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Declaration of inlined member functions of the Constraints class designed
- * to manage working sets of constraints within a QProblem.
- */
-
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-/*
- * g e t N C
- */
-inline int Constraints::getNC( ) const
-{
- return nC;
-}
-
-
-/*
- * g e t N E C
- */
-inline int Constraints::getNEC( ) const
-{
- return nEC;
-}
-
-
-/*
- * g e t N I C
- */
-inline int Constraints::getNIC( ) const
-{
- return nIC;
-}
-
-
-/*
- * g e t N U C
- */
-inline int Constraints::getNUC( ) const
-{
- return nUC;
-}
-
-
-/*
- * s e t N E C
- */
-inline returnValue Constraints::setNEC( int n )
-{
- nEC = n;
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t N I C
- */
-inline returnValue Constraints::setNIC( int n )
-{
- nIC = n;
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t N U C
- */
-inline returnValue Constraints::setNUC( int n )
-{
- nUC = n;
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * g e t N A C
- */
-inline int Constraints::getNAC( )
-{
- return active.getLength( );
-}
-
-
-/*
- * g e t N I A C
- */
-inline int Constraints::getNIAC( )
-{
- return inactive.getLength( );
-}
-
-
-/*
- * g e t A c t i v e
- */
-inline Indexlist* Constraints::getActive( )
-{
- return &active;
-}
-
-
-/*
- * g e t I n a c t i v e
- */
-inline Indexlist* Constraints::getInactive( )
-{
- return &inactive;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/CyclingManager.cpp b/phonelibs/qpoases/SRC/CyclingManager.cpp
deleted file mode 100644
index 27c2996ef..000000000
--- a/phonelibs/qpoases/SRC/CyclingManager.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/CyclingManager.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the CyclingManager class designed to detect
- * and handle possible cycling during QP iterations.
- *
- */
-
-
-#include
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * C y c l i n g M a n a g e r
- */
-CyclingManager::CyclingManager( ) : nV( 0 ),
- nC( 0 )
-{
- cyclingDetected = BT_FALSE;
-}
-
-
-/*
- * C y c l i n g M a n a g e r
- */
-CyclingManager::CyclingManager( const CyclingManager& rhs ) : nV( rhs.nV ),
- nC( rhs.nC ),
- cyclingDetected( rhs.cyclingDetected )
-{
- int i;
-
- for( i=0; i= 0 ) && ( number < nV ) )
- {
- status[number] = _status;
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
- }
- else
- {
- /* Set cycling status of a constraint. */
- if ( ( number >= 0 ) && ( number < nC ) )
- {
- status[nV+number] = _status;
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
- }
-}
-
-
-/*
- * g e t C y c l i n g S t a t u s
- */
-CyclingStatus CyclingManager::getCyclingStatus( int number, BooleanType isBound ) const
-{
- if ( isBound == BT_TRUE )
- {
- /* Return cycling status of a bound. */
- if ( ( number >= 0 ) && ( number < nV ) )
- return status[number];
- }
- else
- {
- /* Return cycling status of a constraint. */
- if ( ( number >= 0 ) && ( number < nC ) )
- return status[nV+number];
- }
-
- return CYC_NOT_INVOLVED;
-}
-
-
-/*
- * c l e a r C y c l i n g D a t a
- */
-returnValue CyclingManager::clearCyclingData( )
-{
- int i;
-
- /* Reset all status values ... */
- for( i=0; i
-
-/*
- * S o l u t i o n A n a l y s i s
- */
-SolutionAnalysis::SolutionAnalysis( )
-{
-
-}
-
-/*
- * S o l u t i o n A n a l y s i s
- */
-SolutionAnalysis::SolutionAnalysis( const SolutionAnalysis& rhs )
-{
-
-}
-
-/*
- * ~ S o l u t i o n A n a l y s i s
- */
-SolutionAnalysis::~SolutionAnalysis( )
-{
-
-}
-
-/*
- * o p e r a t o r =
- */
-SolutionAnalysis& SolutionAnalysis::operator=( const SolutionAnalysis& rhs )
-{
- if ( this != &rhs )
- {
-
- }
-
- return *this;
-}
-
-/*
- * g e t H e s s i a n I n v e r s e
- */
-returnValue SolutionAnalysis::getHessianInverse( QProblem* qp, real_t* hessianInverse )
-{
- returnValue returnvalue; /* the return value */
- BooleanType Delta_bC_isZero = BT_FALSE; /* (just use FALSE here) */
- BooleanType Delta_bB_isZero = BT_FALSE; /* (just use FALSE here) */
-
- register int run1, run2, run3;
-
- register int nFR, nFX;
-
- /* Ask for the number of free and fixed variables, assumes that active set
- * is constant for the covariance evaluation */
- nFR = qp->getNFR( );
- nFX = qp->getNFX( );
-
- /* Ask for the corresponding index arrays: */
- if ( qp->bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( qp->bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( qp->constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- /* Initialization: */
- for( run1 = 0; run1 < NVMAX; run1++ )
- delta_g_cov[ run1 ] = 0.0;
-
- for( run1 = 0; run1 < NVMAX; run1++ )
- delta_lb_cov[ run1 ] = 0.0;
-
- for( run1 = 0; run1 < NVMAX; run1++ )
- delta_ub_cov[ run1 ] = 0.0;
-
- for( run1 = 0; run1 < NCMAX; run1++ )
- delta_lbA_cov[ run1 ] = 0.0;
-
- for( run1 = 0; run1 < NCMAX; run1++ )
- delta_ubA_cov[ run1 ] = 0.0;
-
- /* The following loop solves the following:
- *
- * KKT * x =
- * [delta_g_cov', delta_lbA_cov', delta_ubA_cov', delta_lb_cov', delta_ub_cov]'
- *
- * for the first NVMAX (negative) elementary vectors in order to get
- * transposed inverse of the Hessian. Assuming that the Hessian is
- * symmetric, the function will return transposed inverse, instead of the
- * true inverse.
- *
- * Note, that we use negative elementary vectors due because internal
- * implementation of the function hotstart_determineStepDirection requires
- * so.
- *
- * */
-
- for( run3 = 0; run3 < NVMAX; run3++ )
- {
- /* Line wise loading of the corresponding (negative) elementary vector: */
- delta_g_cov[ run3 ] = -1.0;
-
- /* Evaluation of the step: */
- returnvalue = qp->hotstart_determineStepDirection(
- FR_idx, FX_idx, AC_idx,
- delta_g_cov, delta_lbA_cov, delta_ubA_cov, delta_lb_cov, delta_ub_cov,
- Delta_bC_isZero, Delta_bB_isZero,
- delta_xFX, delta_xFR, delta_yAC, delta_yFX
- );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- return returnvalue;
- }
-
- /* Line wise storage of the QP reaction: */
- for( run1 = 0; run1 < nFR; run1++ )
- {
- run2 = FR_idx[ run1 ];
-
- hessianInverse[run3 * NVMAX + run2] = delta_xFR[ run1 ];
- }
-
- for( run1 = 0; run1 < nFX; run1++ )
- {
- run2 = FX_idx[ run1 ];
-
- hessianInverse[run3 * NVMAX + run2] = delta_xFX[ run1 ];
- }
-
- /* Prepare for the next iteration */
- delta_g_cov[ run3 ] = 0.0;
- }
-
- // TODO: Perform the transpose of the inverse of the Hessian matrix
-
- return SUCCESSFUL_RETURN;
-}
-
-/*
- * g e t H e s s i a n I n v e r s e
- */
-returnValue SolutionAnalysis::getHessianInverse( QProblemB* qp, real_t* hessianInverse )
-{
- returnValue returnvalue; /* the return value */
- BooleanType Delta_bB_isZero = BT_FALSE; /* (just use FALSE here) */
-
- register int run1, run2, run3;
-
- register int nFR, nFX;
-
- /* Ask for the number of free and fixed variables, assumes that active set
- * is constant for the covariance evaluation */
- nFR = qp->getNFR( );
- nFX = qp->getNFX( );
-
- /* Ask for the corresponding index arrays: */
- if ( qp->bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( qp->bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- /* Initialization: */
- for( run1 = 0; run1 < NVMAX; run1++ )
- delta_g_cov[ run1 ] = 0.0;
-
- for( run1 = 0; run1 < NVMAX; run1++ )
- delta_lb_cov[ run1 ] = 0.0;
-
- for( run1 = 0; run1 < NVMAX; run1++ )
- delta_ub_cov[ run1 ] = 0.0;
-
- /* The following loop solves the following:
- *
- * KKT * x =
- * [delta_g_cov', delta_lb_cov', delta_ub_cov']'
- *
- * for the first NVMAX (negative) elementary vectors in order to get
- * transposed inverse of the Hessian. Assuming that the Hessian is
- * symmetric, the function will return transposed inverse, instead of the
- * true inverse.
- *
- * Note, that we use negative elementary vectors due because internal
- * implementation of the function hotstart_determineStepDirection requires
- * so.
- *
- * */
-
- for( run3 = 0; run3 < NVMAX; run3++ )
- {
- /* Line wise loading of the corresponding (negative) elementary vector: */
- delta_g_cov[ run3 ] = -1.0;
-
- /* Evaluation of the step: */
- returnvalue = qp->hotstart_determineStepDirection(
- FR_idx, FX_idx,
- delta_g_cov, delta_lb_cov, delta_ub_cov,
- Delta_bB_isZero,
- delta_xFX, delta_xFR, delta_yFX
- );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- return returnvalue;
- }
-
- /* Line wise storage of the QP reaction: */
- for( run1 = 0; run1 < nFR; run1++ )
- {
- run2 = FR_idx[ run1 ];
-
- hessianInverse[run3 * NVMAX + run2] = delta_xFR[ run1 ];
- }
-
- for( run1 = 0; run1 < nFX; run1++ )
- {
- run2 = FX_idx[ run1 ];
-
- hessianInverse[run3 * NVMAX + run2] = delta_xFX[ run1 ];
- }
-
- /* Prepare for the next iteration */
- delta_g_cov[ run3 ] = 0.0;
- }
-
- // TODO: Perform the transpose of the inverse of the Hessian matrix
-
- return SUCCESSFUL_RETURN;
-}
-
-/*
- * g e t V a r i a n c e C o v a r i a n c e
- */
-
-#if QPOASES_USE_OLD_VERSION
-
-returnValue SolutionAnalysis::getVarianceCovariance( QProblem* qp, real_t* g_b_bA_VAR, real_t* Primal_Dual_VAR )
-{
- int run1, run2, run3; /* simple run variables (for loops). */
-
- returnValue returnvalue; /* the return value */
- BooleanType Delta_bC_isZero = BT_FALSE; /* (just use FALSE here) */
- BooleanType Delta_bB_isZero = BT_FALSE; /* (just use FALSE here) */
-
- /* ASK FOR THE NUMBER OF FREE AND FIXED VARIABLES:
- * (ASSUMES THAT ACTIVE SET IS CONSTANT FOR THE
- * VARIANCE-COVARIANCE EVALUATION)
- * ----------------------------------------------- */
- int nFR, nFX, nAC;
-
- nFR = qp->getNFR( );
- nFX = qp->getNFX( );
- nAC = qp->getNAC( );
-
- if ( qp->bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( qp->bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( qp->constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- /* SOME INITIALIZATIONS:
- * --------------------- */
- for( run1 = 0; run1 < KKT_DIM * KKT_DIM; run1++ )
- {
- K [run1] = 0.0;
- Primal_Dual_VAR[run1] = 0.0;
- }
-
- /* ================================================================= */
-
- /* FIRST MATRIX MULTIPLICATION (OBTAINS THE INTERMEDIATE RESULT
- * K := [ ("ACTIVE" KKT-MATRIX OF THE QP)^(-1) * g_b_bA_VAR ]^T )
- * THE EVALUATION OF THE INVERSE OF THE KKT-MATRIX OF THE QP
- * WITH RESPECT TO THE CURRENT ACTIVE SET
- * USES THE EXISTING CHOLESKY AND TQ-DECOMPOSITIONS. FOR DETAILS
- * cf. THE (protected) FUNCTION determineStepDirection. */
-
- for( run3 = 0; run3 < KKT_DIM; run3++ )
- {
-
- for( run1 = 0; run1 < NVMAX; run1++ )
- {
- delta_g_cov [run1] = g_b_bA_VAR[run3*KKT_DIM+run1];
- delta_lb_cov [run1] = g_b_bA_VAR[run3*KKT_DIM+NVMAX+run1]; /* LINE-WISE LOADING OF THE INPUT */
- delta_ub_cov [run1] = g_b_bA_VAR[run3*KKT_DIM+NVMAX+run1]; /* VARIANCE-COVARIANCE */
- }
- for( run1 = 0; run1 < NCMAX; run1++ )
- {
- delta_lbA_cov [run1] = g_b_bA_VAR[run3*KKT_DIM+2*NVMAX+run1];
- delta_ubA_cov [run1] = g_b_bA_VAR[run3*KKT_DIM+2*NVMAX+run1];
- }
-
- /* EVALUATION OF THE STEP:
- * ------------------------------------------------------------------------------ */
-
- returnvalue = qp->hotstart_determineStepDirection(
- FR_idx, FX_idx, AC_idx,
- delta_g_cov, delta_lbA_cov, delta_ubA_cov, delta_lb_cov, delta_ub_cov,
- Delta_bC_isZero, Delta_bB_isZero, delta_xFX,delta_xFR,
- delta_yAC,delta_yFX );
-
- /* ------------------------------------------------------------------------------ */
-
- /* STOP THE ALGORITHM IN THE CASE OF NO SUCCESFUL RETURN:
- * ------------------------------------------------------ */
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- return returnvalue;
- }
-
- /* LINE WISE */
- /* STORAGE OF THE QP-REACTION */
- /* (uses the index list) */
-
- for( run1=0; run1hotstart_determineStepDirection(
- FR_idx, FX_idx, AC_idx,
- delta_g_cov, delta_lbA_cov, delta_ubA_cov, delta_lb_cov, delta_ub_cov,
- Delta_bC_isZero, Delta_bB_isZero, delta_xFX,delta_xFR,
- delta_yAC,delta_yFX );
-
- /* ------------------------------------------------------------------------------ */
-
- /* STOP THE ALGORITHM IN THE CASE OF NO SUCCESFUL RETURN:
- * ------------------------------------------------------ */
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- return returnvalue;
- }
-
- /* ROW-WISE STORAGE */
- /* OF THE RESULT. */
-
- for( run1=0; run1
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * I n d e x l i s t
- */
-Indexlist::Indexlist( ) : length( 0 ),
- first( -1 ),
- last( -1 ),
- lastusedindex( -1 ),
- physicallength( INDEXLISTFACTOR*(NVMAX+NCMAX) )
-{
- int i;
-
- for( i=0; i= 0 ) && ( number[n] >= 0 ) )
- numberarray[i] = number[n];
- else
- return THROWERROR( RET_INDEXLIST_CORRUPTED );
-
- n = next[n];
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * g e t I n d e x
- */
-int Indexlist::getIndex( int givennumber ) const
-{
- int i;
- int n = first;
- int index = -1; /* return -1 by default */
-
- /* Run trough indexlist until number is found, if so return it index. */
- for ( i=0; i length ) )
- return -RET_INDEXLIST_OUTOFBOUNDS;
-
- return number[physicalindex];
-}
-
-
-/*
- * g e t L e n g t h
- */
-inline int Indexlist::getLength( )
-{
- return length;
-}
-
-
-/*
- * g e t L a s t N u m b e r
- */
-inline int Indexlist::getLastNumber( ) const
-{
- return number[last];
-}
-
-
-/*
- * g e t L a s t N u m b e r
- */
-inline BooleanType Indexlist::isMember( int _number ) const
-{
- if ( getIndex( _number ) >= 0 )
- return BT_TRUE;
- else
- return BT_FALSE;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/MessageHandling.cpp b/phonelibs/qpoases/SRC/MessageHandling.cpp
deleted file mode 100644
index 18a7654a1..000000000
--- a/phonelibs/qpoases/SRC/MessageHandling.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/MessageHandling.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the MessageHandling class including global return values.
- *
- */
-
-
-
-#include
-#include
-
-
-
-
-/** Defines pairs of global return values and messages. */
-MessageHandling::ReturnValueList returnValueList[] =
-{
-/* miscellaneous */
-{ SUCCESSFUL_RETURN, "Successful return", VS_VISIBLE },
-{ RET_DIV_BY_ZERO, "Division by zero", VS_VISIBLE },
-{ RET_INDEX_OUT_OF_BOUNDS, "Index out of bounds", VS_VISIBLE },
-{ RET_INVALID_ARGUMENTS, "At least one of the arguments is invalid", VS_VISIBLE },
-{ RET_ERROR_UNDEFINED, "Error number undefined", VS_VISIBLE },
-{ RET_WARNING_UNDEFINED, "Warning number undefined", VS_VISIBLE },
-{ RET_INFO_UNDEFINED, "Info number undefined", VS_VISIBLE },
-{ RET_EWI_UNDEFINED, "Error/warning/info number undefined", VS_VISIBLE },
-{ RET_AVAILABLE_WITH_LINUX_ONLY, "This function is available under Linux only", VS_HIDDEN },
-{ RET_UNKNOWN_BUG, "The error occured is not yet known", VS_VISIBLE },
-{ RET_PRINTLEVEL_CHANGED, "Print level changed", VS_VISIBLE },
-{ RET_NOT_YET_IMPLEMENTED, "Requested function is not yet implemented.", VS_VISIBLE },
-/* Indexlist */
-{ RET_INDEXLIST_MUST_BE_REORDERD, "Index list has to be reordered", VS_VISIBLE },
-{ RET_INDEXLIST_EXCEEDS_MAX_LENGTH, "Index list exceeds its maximal physical length", VS_VISIBLE },
-{ RET_INDEXLIST_CORRUPTED, "Index list corrupted", VS_VISIBLE },
-{ RET_INDEXLIST_OUTOFBOUNDS, "Physical index is out of bounds", VS_VISIBLE },
-{ RET_INDEXLIST_ADD_FAILED, "Adding indices from another index set failed", VS_VISIBLE },
-{ RET_INDEXLIST_INTERSECT_FAILED, "Intersection with another index set failed", VS_VISIBLE },
-/* SubjectTo / Bounds / Constraints */
-{ RET_INDEX_ALREADY_OF_DESIRED_STATUS, "Index is already of desired status", VS_VISIBLE },
-{ RET_SWAPINDEX_FAILED, "Cannot swap between different indexsets", VS_VISIBLE },
-{ RET_ADDINDEX_FAILED, "Adding index to index set failed", VS_VISIBLE },
-{ RET_NOTHING_TO_DO, "Nothing to do", VS_VISIBLE },
-{ RET_SETUP_BOUND_FAILED, "Setting up bound index failed", VS_VISIBLE },
-{ RET_SETUP_CONSTRAINT_FAILED, "Setting up constraint index failed", VS_VISIBLE },
-{ RET_MOVING_BOUND_FAILED, "Moving bound between index sets failed", VS_VISIBLE },
-{ RET_MOVING_CONSTRAINT_FAILED, "Moving constraint between index sets failed", VS_VISIBLE },
-/* QProblem */
-{ RET_QP_ALREADY_INITIALISED, "QProblem has already been initialised", VS_VISIBLE },
-{ RET_NO_INIT_WITH_STANDARD_SOLVER, "Initialisation via extern QP solver is not yet implemented", VS_VISIBLE },
-{ RET_RESET_FAILED, "Reset failed", VS_VISIBLE },
-{ RET_INIT_FAILED, "Initialisation failed", VS_VISIBLE },
-{ RET_INIT_FAILED_TQ, "Initialisation failed due to TQ factorisation", VS_VISIBLE },
-{ RET_INIT_FAILED_CHOLESKY, "Initialisation failed due to Cholesky decomposition", VS_VISIBLE },
-{ RET_INIT_FAILED_HOTSTART, "Initialisation failed! QP could not be solved!", VS_VISIBLE },
-{ RET_INIT_FAILED_INFEASIBILITY, "Initial QP could not be solved due to infeasibility!", VS_VISIBLE },
-{ RET_INIT_FAILED_UNBOUNDEDNESS, "Initial QP could not be solved due to unboundedness!", VS_VISIBLE },
-{ RET_INIT_SUCCESSFUL, "Initialisation done", VS_VISIBLE },
-{ RET_OBTAINING_WORKINGSET_FAILED, "Failed to obtain working set for auxiliary QP", VS_VISIBLE },
-{ RET_SETUP_WORKINGSET_FAILED, "Failed to setup working set for auxiliary QP", VS_VISIBLE },
-{ RET_SETUP_AUXILIARYQP_FAILED, "Failed to setup auxiliary QP for initialised homotopy", VS_VISIBLE },
-{ RET_NO_EXTERN_SOLVER, "No extern QP solver available", VS_VISIBLE },
-{ RET_QP_UNBOUNDED, "QP is unbounded", VS_VISIBLE },
-{ RET_QP_INFEASIBLE, "QP is infeasible", VS_VISIBLE },
-{ RET_QP_NOT_SOLVED, "Problems occured while solving QP with standard solver", VS_VISIBLE },
-{ RET_QP_SOLVED, "QP successfully solved", VS_VISIBLE },
-{ RET_UNABLE_TO_SOLVE_QP, "Problems occured while solving QP", VS_VISIBLE },
-{ RET_INITIALISATION_STARTED, "Starting problem initialisation...", VS_VISIBLE },
-{ RET_HOTSTART_FAILED, "Unable to perform homotopy due to internal error", VS_VISIBLE },
-{ RET_HOTSTART_FAILED_TO_INIT, "Unable to initialise problem", VS_VISIBLE },
-{ RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED, "Unable to perform homotopy as previous QP is not solved", VS_VISIBLE },
-{ RET_ITERATION_STARTED, "Iteration", VS_VISIBLE },
-{ RET_SHIFT_DETERMINATION_FAILED, "Determination of shift of the QP data failed", VS_VISIBLE },
-{ RET_STEPDIRECTION_DETERMINATION_FAILED, "Determination of step direction failed", VS_VISIBLE },
-{ RET_STEPLENGTH_DETERMINATION_FAILED, "Determination of step direction failed", VS_VISIBLE },
-{ RET_OPTIMAL_SOLUTION_FOUND, "Optimal solution of neighbouring QP found", VS_VISIBLE },
-{ RET_HOMOTOPY_STEP_FAILED, "Unable to perform homotopy step", VS_VISIBLE },
-{ RET_HOTSTART_STOPPED_INFEASIBILITY, "Premature homotopy termination because QP is infeasible", VS_VISIBLE },
-{ RET_HOTSTART_STOPPED_UNBOUNDEDNESS, "Premature homotopy termination because QP is unbounded", VS_VISIBLE },
-{ RET_WORKINGSET_UPDATE_FAILED, "Unable to update working sets according to initial guesses", VS_VISIBLE },
-{ RET_MAX_NWSR_REACHED, "Maximum number of working set recalculations performed", VS_VISIBLE },
-{ RET_CONSTRAINTS_NOT_SPECIFIED, "Problem does comprise constraints! You have to specify new constraints' bounds", VS_VISIBLE },
-{ RET_INVALID_FACTORISATION_FLAG, "Invalid factorisation flag", VS_VISIBLE },
-{ RET_UNABLE_TO_SAVE_QPDATA, "Unable to save QP data", VS_VISIBLE },
-{ RET_STEPDIRECTION_FAILED_TQ, "Abnormal termination due to TQ factorisation", VS_VISIBLE },
-{ RET_STEPDIRECTION_FAILED_CHOLESKY, "Abnormal termination due to Cholesky factorisation", VS_VISIBLE },
-{ RET_CYCLING_DETECTED, "Cycling detected", VS_VISIBLE },
-{ RET_CYCLING_NOT_RESOLVED, "Cycling cannot be resolved, QP is probably infeasible", VS_VISIBLE },
-{ RET_CYCLING_RESOLVED, "Cycling probably resolved", VS_VISIBLE },
-{ RET_STEPSIZE, "", VS_VISIBLE },
-{ RET_STEPSIZE_NONPOSITIVE, "", VS_VISIBLE },
-{ RET_SETUPSUBJECTTOTYPE_FAILED, "Setup of SubjectToTypes failed", VS_VISIBLE },
-{ RET_ADDCONSTRAINT_FAILED, "Addition of constraint to working set failed", VS_VISIBLE },
-{ RET_ADDCONSTRAINT_FAILED_INFEASIBILITY, "Addition of constraint to working set failed", VS_VISIBLE },
-{ RET_ADDBOUND_FAILED, "Addition of bound to working set failed", VS_VISIBLE },
-{ RET_ADDBOUND_FAILED_INFEASIBILITY, "Addition of bound to working set failed", VS_VISIBLE },
-{ RET_REMOVECONSTRAINT_FAILED, "Removal of constraint from working set failed", VS_VISIBLE },
-{ RET_REMOVEBOUND_FAILED, "Removal of bound from working set failed", VS_VISIBLE },
-{ RET_REMOVE_FROM_ACTIVESET, "Removing from active set:", VS_VISIBLE },
-{ RET_ADD_TO_ACTIVESET, "Adding to active set:", VS_VISIBLE },
-{ RET_REMOVE_FROM_ACTIVESET_FAILED, "Removing from active set failed", VS_VISIBLE },
-{ RET_ADD_TO_ACTIVESET_FAILED, "Adding to active set failed", VS_VISIBLE },
-{ RET_CONSTRAINT_ALREADY_ACTIVE, "Constraint is already active", VS_VISIBLE },
-{ RET_ALL_CONSTRAINTS_ACTIVE, "All constraints are active, no further constraint can be added", VS_VISIBLE },
-{ RET_LINEARLY_DEPENDENT, "New bound/constraint is linearly dependent", VS_VISIBLE },
-{ RET_LINEARLY_INDEPENDENT, "New bound/constraint is linearly independent", VS_VISIBLE },
-{ RET_LI_RESOLVED, "Linear independence of active contraint matrix successfully resolved", VS_VISIBLE },
-{ RET_ENSURELI_FAILED, "Failed to ensure linear indepence of active contraint matrix", VS_VISIBLE },
-{ RET_ENSURELI_FAILED_TQ, "Abnormal termination due to TQ factorisation", VS_VISIBLE },
-{ RET_ENSURELI_FAILED_NOINDEX, "No index found, QP is probably infeasible", VS_VISIBLE },
-{ RET_ENSURELI_FAILED_CYCLING, "Cycling detected, QP is probably infeasible", VS_VISIBLE },
-{ RET_BOUND_ALREADY_ACTIVE, "Bound is already active", VS_VISIBLE },
-{ RET_ALL_BOUNDS_ACTIVE, "All bounds are active, no further bound can be added", VS_VISIBLE },
-{ RET_CONSTRAINT_NOT_ACTIVE, "Constraint is not active", VS_VISIBLE },
-{ RET_BOUND_NOT_ACTIVE, "Bound is not active", VS_VISIBLE },
-{ RET_HESSIAN_NOT_SPD, "Projected Hessian matrix not positive definite", VS_VISIBLE },
-{ RET_MATRIX_SHIFT_FAILED, "Unable to update matrices or to transform vectors", VS_VISIBLE },
-{ RET_MATRIX_FACTORISATION_FAILED, "Unable to calculate new matrix factorisations", VS_VISIBLE },
-{ RET_PRINT_ITERATION_FAILED, "Unable to print information on current iteration", VS_VISIBLE },
-{ RET_NO_GLOBAL_MESSAGE_OUTPUTFILE, "No global message output file initialised", VS_VISIBLE },
-/* Utils */
-{ RET_UNABLE_TO_OPEN_FILE, "Unable to open file", VS_VISIBLE },
-{ RET_UNABLE_TO_WRITE_FILE, "Unable to write into file", VS_VISIBLE },
-{ RET_UNABLE_TO_READ_FILE, "Unable to read from file", VS_VISIBLE },
-{ RET_FILEDATA_INCONSISTENT, "File contains inconsistent data", VS_VISIBLE },
-/* SolutionAnalysis */
-{ RET_NO_SOLUTION, "QP solution does not satisfy KKT optimality conditions", VS_VISIBLE },
-{ RET_INACCURATE_SOLUTION, "KKT optimality conditions not satisfied to sufficient accuracy", VS_VISIBLE },
-{ TERMINAL_LIST_ELEMENT, "", VS_HIDDEN } /* IMPORTANT: Terminal list element! */
-};
-
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * M e s s a g e H a n d l i n g
- */
-MessageHandling::MessageHandling( ) : errorVisibility( VS_VISIBLE ),
- warningVisibility( VS_VISIBLE ),
- infoVisibility( VS_VISIBLE ),
- outputFile( myStdout ),
- errorCount( 0 )
-{
-}
-
-/*
- * M e s s a g e H a n d l i n g
- */
-MessageHandling::MessageHandling( myFILE* _outputFile ) :
- errorVisibility( VS_VISIBLE ),
- warningVisibility( VS_VISIBLE ),
- infoVisibility( VS_VISIBLE ),
- outputFile( _outputFile ),
- errorCount( 0 )
-{
-}
-
-/*
- * M e s s a g e H a n d l i n g
- */
-MessageHandling::MessageHandling( VisibilityStatus _errorVisibility,
- VisibilityStatus _warningVisibility,
- VisibilityStatus _infoVisibility
- ) :
- errorVisibility( _errorVisibility ),
- warningVisibility( _warningVisibility ),
- infoVisibility( _infoVisibility ),
- outputFile( myStderr ),
- errorCount( 0 )
-{
-}
-
-/*
- * M e s s a g e H a n d l i n g
- */
-MessageHandling::MessageHandling( myFILE* _outputFile,
- VisibilityStatus _errorVisibility,
- VisibilityStatus _warningVisibility,
- VisibilityStatus _infoVisibility
- ) :
- errorVisibility( _errorVisibility ),
- warningVisibility( _warningVisibility ),
- infoVisibility( _infoVisibility ),
- outputFile( _outputFile ),
- errorCount( 0 )
-{
-}
-
-
-
-/*
- * M e s s a g e H a n d l i n g
- */
-MessageHandling::MessageHandling( const MessageHandling& rhs ) :
- errorVisibility( rhs.errorVisibility ),
- warningVisibility( rhs.warningVisibility ),
- infoVisibility( rhs.infoVisibility ),
- outputFile( rhs.outputFile ),
- errorCount( rhs.errorCount )
-{
-}
-
-
-/*
- * ~ M e s s a g e H a n d l i n g
- */
-MessageHandling::~MessageHandling( )
-{
- #ifdef PC_DEBUG
- if ( outputFile != 0 )
- fclose( outputFile );
- #endif
-}
-
-
-/*
- * o p e r a t o r =
- */
-MessageHandling& MessageHandling::operator=( const MessageHandling& rhs )
-{
- if ( this != &rhs )
- {
- errorVisibility = rhs.errorVisibility;
- warningVisibility = rhs.warningVisibility;
- infoVisibility = rhs.infoVisibility;
- outputFile = rhs.outputFile;
- errorCount = rhs.errorCount;
- }
-
- return *this;
-}
-
-
-/*
- * t h r o w E r r o r
- */
-returnValue MessageHandling::throwError(
- returnValue Enumber,
- const char* additionaltext,
- const char* functionname,
- const char* filename,
- const unsigned long linenumber,
- VisibilityStatus localVisibilityStatus
- )
-{
- /* consistency check */
- if ( Enumber <= SUCCESSFUL_RETURN )
- return throwError( RET_ERROR_UNDEFINED,0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
-
- /* Call to common throwMessage function if error shall be displayed. */
- if ( errorVisibility == VS_VISIBLE )
- return throwMessage( Enumber,additionaltext,functionname,filename,linenumber,localVisibilityStatus,"ERROR" );
- else
- return Enumber;
-}
-
-
-/*
- * t h r o w W a r n i n g
- */
-returnValue MessageHandling::throwWarning(
- returnValue Wnumber,
- const char* additionaltext,
- const char* functionname,
- const char* filename,
- const unsigned long linenumber,
- VisibilityStatus localVisibilityStatus
- )
-{
- /* consistency check */
- if ( Wnumber <= SUCCESSFUL_RETURN )
- return throwError( RET_WARNING_UNDEFINED,0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
-
- /* Call to common throwMessage function if warning shall be displayed. */
- if ( warningVisibility == VS_VISIBLE )
- return throwMessage( Wnumber,additionaltext,functionname,filename,linenumber,localVisibilityStatus,"WARNING" );
- else
- return Wnumber;
-}
-
-
-/*
- * t h r o w I n f o
- */
-returnValue MessageHandling::throwInfo(
- returnValue Inumber,
- const char* additionaltext,
- const char* functionname,
- const char* filename,
- const unsigned long linenumber,
- VisibilityStatus localVisibilityStatus
- )
-{
- /* consistency check */
- if ( Inumber < SUCCESSFUL_RETURN )
- return throwError( RET_INFO_UNDEFINED,0,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
-
- /* Call to common throwMessage function if info shall be displayed. */
- if ( infoVisibility == VS_VISIBLE )
- return throwMessage( Inumber,additionaltext,functionname,filename,linenumber,localVisibilityStatus,"INFO" );
- else
- return Inumber;
-}
-
-
-/*
- * r e s e t
- */
-returnValue MessageHandling::reset( )
-{
- setErrorVisibilityStatus( VS_VISIBLE );
- setWarningVisibilityStatus( VS_VISIBLE );
- setInfoVisibilityStatus( VS_VISIBLE );
-
- setOutputFile( myStderr );
- setErrorCount( 0 );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * l i s t A l l M e s s a g e s
- */
-returnValue MessageHandling::listAllMessages( )
-{
- #ifdef PC_DEBUG
- int keypos = 0;
- char myPrintfString[160];
-
- /* Run through whole returnValueList and print each item. */
- while ( returnValueList[keypos].key != TERMINAL_LIST_ELEMENT )
- {
- sprintf( myPrintfString," %d - %s \n",keypos,returnValueList[keypos].data );
- myPrintf( myPrintfString );
-
- ++keypos;
- }
- #endif
-
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*****************************************************************************
- * P R O T E C T E D *
- *****************************************************************************/
-
-
-#ifdef PC_DEBUG /* Re-define throwMessage function for embedded code! */
-
-/*
- * t h r o w M e s s a g e
- */
-returnValue MessageHandling::throwMessage(
- returnValue RETnumber,
- const char* additionaltext,
- const char* functionname,
- const char* filename,
- const unsigned long linenumber,
- VisibilityStatus localVisibilityStatus,
- const char* RETstring
- )
-{
- int i;
-
- int keypos = 0;
- char myPrintfString[160];
-
- /* 1) Determine number of whitespace for output. */
- char whitespaces[41];
- int numberOfWhitespaces = (errorCount-1)*2;
-
- if ( numberOfWhitespaces < 0 )
- numberOfWhitespaces = 0;
-
- if ( numberOfWhitespaces > 40 )
- numberOfWhitespaces = 40;
-
- for( i=0; i 0 )
- {
- sprintf( myPrintfString,"%s->", whitespaces );
- myPrintf( myPrintfString );
- }
-
- if ( additionaltext == 0 )
- {
- sprintf( myPrintfString,"%s (%s, %s:%d): \t%s\n",
- RETstring,functionname,filename,(int)linenumber,returnValueList[keypos].data
- );
- myPrintf( myPrintfString );
- }
- else
- {
- sprintf( myPrintfString,"%s (%s, %s:%d): \t%s %s\n",
- RETstring,functionname,filename,(int)linenumber,returnValueList[keypos].data,additionaltext
- );
- myPrintf( myPrintfString );
- }
-
- /* take care of proper indention for subsequent error messages */
- if ( RETstring[0] == 'E' )
- {
- ++errorCount;
- }
- else
- {
- if ( errorCount > 0 )
- myPrintf( "\n" );
- errorCount = 0;
- }
- }
-
- return RETnumber;
-}
-
-#else /* = PC_DEBUG not defined */
-
-/*
- * t h r o w M e s s a g e
- */
-returnValue MessageHandling::throwMessage(
- returnValue RETnumber,
- const char* additionaltext,
- const char* functionname,
- const char* filename,
- const unsigned long linenumber,
- VisibilityStatus localVisibilityStatus,
- const char* RETstring
- )
-{
- /* DUMMY CODE FOR PRETENDING USE OF ARGUMENTS
- * FOR SUPPRESSING COMPILER WARNINGS! */
- int i = 0;
- if ( additionaltext == 0 ) i++;
- if ( functionname == 0 ) i++;
- if ( filename == 0 ) i++;
- if ( linenumber == 0 ) i++;
- if ( localVisibilityStatus == VS_VISIBLE ) i++;
- if ( RETstring == 0 ) i++;
- /* END OF DUMMY CODE */
-
- return RETnumber;
-}
-
-#endif /* PC_DEBUG */
-
-
-
-/*****************************************************************************
- * G L O B A L M E S S A G E H A N D L E R *
- *****************************************************************************/
-
-
-/** Global message handler for all qpOASES modules.*/
-MessageHandling globalMessageHandler( myStderr,VS_VISIBLE,VS_VISIBLE,VS_VISIBLE );
-
-
-/*
- * g e t G l o b a l M e s s a g e H a n d l e r
- */
-MessageHandling* getGlobalMessageHandler( )
-{
- return &globalMessageHandler;
-}
-
-const char* MessageHandling::getErrorString(int error)
-{
- return returnValueList[ error ].data;
-}
-
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/MessageHandling.ipp b/phonelibs/qpoases/SRC/MessageHandling.ipp
deleted file mode 100644
index 033957b28..000000000
--- a/phonelibs/qpoases/SRC/MessageHandling.ipp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/MessageHandling.ipp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of inlined member functions of the MessageHandling class.
- */
-
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-/*
- * g e t E r r o r V i s i b i l i t y S t a t u s
- */
-inline VisibilityStatus MessageHandling::getErrorVisibilityStatus( ) const
-{
- return errorVisibility;
-}
-
-
-/*
- * g e t W a r n i n g V i s i b i l i t y S t a t u s
- */
-inline VisibilityStatus MessageHandling::getWarningVisibilityStatus( ) const
-{
- return warningVisibility;
-}
-
-
-/*
- * g e t I n f o V i s i b i l i t y S t a t u s
- */
-inline VisibilityStatus MessageHandling::getInfoVisibilityStatus( ) const
-{
- return infoVisibility;
-}
-
-
-/*
- * g e t O u t p u t F i l e
- */
-inline myFILE* MessageHandling::getOutputFile( ) const
-{
- return outputFile;
-}
-
-
-/*
- * g e t E r r o r C o u n t
- */
-inline int MessageHandling::getErrorCount( ) const
-{
- return errorCount;
-}
-
-
-/*
- * s e t E r r o r V i s i b i l i t y S t a t u s
- */
-inline void MessageHandling::setErrorVisibilityStatus( VisibilityStatus _errorVisibility )
-{
- errorVisibility = _errorVisibility;
-}
-
-
-/*
- * s e t W a r n i n g V i s i b i l i t y S t a t u s
- */
-inline void MessageHandling::setWarningVisibilityStatus( VisibilityStatus _warningVisibility )
-{
- warningVisibility = _warningVisibility;
-}
-
-
-/*
- * s e t I n f o V i s i b i l i t y S t a t u s
- */
-inline void MessageHandling::setInfoVisibilityStatus( VisibilityStatus _infoVisibility )
-{
- infoVisibility = _infoVisibility;
-}
-
-
-/*
- * s e t O u t p u t F i l e
- */
-inline void MessageHandling::setOutputFile( myFILE* _outputFile )
-{
- outputFile = _outputFile;
-}
-
-
-/*
- * s e t E r r o r C o u n t
- */
-inline returnValue MessageHandling::setErrorCount( int _errorCount )
-{
- if ( _errorCount >= 0 )
- {
- errorCount = _errorCount;
- return SUCCESSFUL_RETURN;
- }
- else
- return RET_INVALID_ARGUMENTS;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/QProblem.cpp b/phonelibs/qpoases/SRC/QProblem.cpp
deleted file mode 100644
index 75e2f324d..000000000
--- a/phonelibs/qpoases/SRC/QProblem.cpp
+++ /dev/null
@@ -1,3867 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/QProblem.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the QProblem class which is able to use the newly
- * developed online active set strategy for parametric quadratic programming.
- */
-
-
-#include
-
-#include
-
-void printmatrix2(char *name, double *A, int m, int n) {
- int i, j;
-
- printf("%s = [...\n", name);
- for (i = 0; i < m; i++) {
- for (j = 0; j < n; j++)
- printf(" % 9.4f", A[i*n+j]);
- printf(",\n");
- }
- printf("];\n");
-}
-
-//#define __PERFORM_KKT_TEST__
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * Q P r o b l e m
- */
-QProblem::QProblem( ) : QProblemB( )
-{
- constraints.init( 0 );
-
- sizeT = 0;
-
- cyclingManager.init( 0,0 );
-}
-
-
-/*
- * Q P r o b l e m
- */
-QProblem::QProblem( int _nV, int _nC ) : QProblemB( _nV )
-{
- /* consistency checks */
- if ( _nV <= 0 )
- _nV = 1;
-
- if ( _nC < 0 )
- {
- _nC = 0;
- THROWERROR( RET_INVALID_ARGUMENTS );
- }
-
- constraints.init( _nC );
-
-
- sizeT = _nC;
- if ( _nC > _nV )
- sizeT = _nV;
-
- cyclingManager.init( _nV,_nC );
-}
-
-
-/*
- * Q P r o b l e m
- */
-QProblem::QProblem( const QProblem& rhs ) : QProblemB( rhs )
-{
- int i, j;
-
- int _nV = rhs.bounds.getNV( );
- int _nC = rhs.constraints.getNC( );
-
- for( i=0; i<_nC; ++i )
- for( j=0; j<_nV; ++j )
- A[i*NVMAX + j] = rhs.A[i*NVMAX + j];
-
- for( i=0; i<_nC; ++i )
- lbA[i] = rhs.lbA[i];
-
- for( i=0; i<_nC; ++i )
- ubA[i] = rhs.ubA[i];
-
- constraints = rhs.constraints;
-
- for( i=0; i<(_nV+_nC); ++i )
- y[i] = rhs.y[i];
-
-
- sizeT = rhs.sizeT;
-
- for( i=0; ithrowInfo( RET_ITERATION_STARTED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- #endif
- }
-
- /* 1) Setup index arrays. */
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( constraints.getInactive( )->getNumberArray( IAC_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- /* 2) Detemination of shift direction of the gradient and the (constraints') bounds. */
- returnvalue = hotstart_determineDataShift( FX_idx, AC_idx,
- g_new,lbA_new,ubA_new,lb_new,ub_new,
- delta_g,delta_lbA,delta_ubA,delta_lb,delta_ub,
- Delta_bC_isZero, Delta_bB_isZero );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
- THROWERROR( RET_SHIFT_DETERMINATION_FAILED );
- return returnvalue;
- }
-
- /* 3) Determination of step direction of X and Y. */
- returnvalue = hotstart_determineStepDirection( FR_idx,FX_idx,AC_idx,
- delta_g,delta_lbA,delta_ubA,delta_lb,delta_ub,
- Delta_bC_isZero, Delta_bB_isZero,
- delta_xFX,delta_xFR,delta_yAC,delta_yFX
- );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
- THROWERROR( RET_STEPDIRECTION_DETERMINATION_FAILED );
- return returnvalue;
- }
-
- /* 4) Determination of step length TAU. */
- returnvalue = hotstart_determineStepLength( FR_idx,FX_idx,AC_idx,IAC_idx,
- delta_lbA,delta_ubA,delta_lb,delta_ub,
- delta_xFX,delta_xFR,delta_yAC,delta_yFX,delta_Ax,
- BC_idx,BC_status,BC_isBound
- );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
- THROWERROR( RET_STEPLENGTH_DETERMINATION_FAILED );
- return returnvalue;
- }
-
- /* 5) Realisation of the homotopy step. */
- returnvalue = hotstart_performStep( FR_idx,FX_idx,AC_idx,IAC_idx,
- delta_g,delta_lbA,delta_ubA,delta_lb,delta_ub,
- delta_xFX,delta_xFR,delta_yAC,delta_yFX,delta_Ax,
- BC_idx,BC_status,BC_isBound
- );
-
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
-
- /* stop runtime measurement */
- if ( cputime != 0 )
- *cputime = getCPUtime( ) - starttime;
-
- /* optimal solution found? */
- if ( returnvalue == RET_OPTIMAL_SOLUTION_FOUND )
- {
- status = QPS_SOLVED;
-
- if ( printlevel == PL_HIGH )
- THROWINFO( RET_OPTIMAL_SOLUTION_FOUND );
-
- #ifdef PC_DEBUG
- if ( printIteration( l,BC_idx,BC_status,BC_isBound ) != SUCCESSFUL_RETURN )
- THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
- #endif
-
- /* check KKT optimality conditions */
- return checkKKTconditions( );
- }
- else
- {
- /* checks for infeasibility... */
- if ( isInfeasible( ) == BT_TRUE )
- {
- status = QPS_HOMOTOPYQPSOLVED;
- return THROWERROR( RET_HOTSTART_STOPPED_INFEASIBILITY );
- }
-
- /* ...unboundedness... */
- if ( unbounded == BT_TRUE ) /* not necessary since objective function convex! */
- return THROWERROR( RET_HOTSTART_STOPPED_UNBOUNDEDNESS );
-
- /* ... and throw unspecific error otherwise */
- THROWERROR( RET_HOMOTOPY_STEP_FAILED );
- return returnvalue;
- }
- }
-
- /* 6) Output information of successful QP iteration. */
- status = QPS_HOMOTOPYQPSOLVED;
-
- #ifdef PC_DEBUG
- if ( printIteration( l,BC_idx,BC_status,BC_isBound ) != SUCCESSFUL_RETURN )
- THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
- #endif
- }
-
-
- /* stop runtime measurement */
- if ( cputime != 0 )
- *cputime = getCPUtime( ) - starttime;
-
-
- /* if programm gets to here, output information that QP could not be solved
- * within the given maximum numbers of working set changes */
- if ( printlevel == PL_HIGH )
- {
- #ifdef PC_DEBUG
- sprintf( messageString,"(nWSR = %d)",nWSR );
- return getGlobalMessageHandler( )->throwWarning( RET_MAX_NWSR_REACHED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- #endif
- }
-
- /* Finally check KKT optimality conditions. */
- returnValue returnvalueKKTcheck = checkKKTconditions( );
-
- if ( returnvalueKKTcheck != SUCCESSFUL_RETURN )
- return returnvalueKKTcheck;
- else
- return RET_MAX_NWSR_REACHED;
-}
-
-
-/*
- * g e t N Z
- */
-int QProblem::getNZ( )
-{
- /* nZ = nFR - nAC */
- return bounds.getFree( )->getLength( ) - constraints.getActive( )->getLength( );
-}
-
-
-/*
- * g e t D u a l S o l u t i o n
- */
-returnValue QProblem::getDualSolution( real_t* const yOpt ) const
-{
- int i;
-
- /* return optimal dual solution vector
- * only if current QP has been solved */
- if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
- ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
- ( getStatus( ) == QPS_SOLVED ) )
- {
- for( i=0; i -INFTY )
- {
- constraints.setNoLower( BT_FALSE );
- break;
- }
- }
-
- /* 2) Check if upper constraints' bounds are present. */
- constraints.setNoUpper( BT_TRUE );
- for( i=0; i INFTY - BOUNDTOL ) )
- {
- constraints.setType( i,ST_UNBOUNDED );
- ++nUC;
- }
- else
- {
- if ( lbA[i] > ubA[i] - BOUNDTOL )
- {
- constraints.setType( i,ST_EQUALITY );
- ++nEC;
- }
- else
- {
- constraints.setType( i,ST_BOUNDED );
- }
- }
- }
-
- /* 4) Set dimensions of constraints structure. */
- constraints.setNEC( nEC );
- constraints.setNUC( nUC );
- constraints.setNIC( nC - nEC - nUC );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * c h o l e s k y D e c o m p o s i t i o n P r o j e c t e d
- */
-returnValue QProblem::setupCholeskyDecompositionProjected( )
-{
- int i, j, k, ii, kk;
- int nV = getNV( );
- int nFR = getNFR( );
- int nZ = getNZ( );
-
- /* 1) Initialises R with all zeros. */
- for( i=0; i 0 )
- {
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INDEXLIST_CORRUPTED );
-
-#if 0
- real_t HZ[NVMAX*NVMAX];
- real_t ZHZ[NVMAX*NVMAX];
-
- /* calculate H*Z */
- for ( i=0; i=0; --k )
- sum -= R[k*NVMAX + i] * R[k*NVMAX + i];
-
- if ( sum > 0.0 )
- {
- R[i*NVMAX + i] = sqrt( sum );
- inv = 1.0 / R[i * NVMAX + i];
- }
- else
- {
- hessianType = HST_SEMIDEF;
- return THROWERROR( RET_HESSIAN_NOT_SPD );
- }
-
- for( j=(i+1); j=0; --k )
- sum -= R[k*NVMAX + i] * R[k*NVMAX + j];
-
- R[i*NVMAX + j] = sum * inv;
- }
- }
-#else
- real_t HZ[NVMAX];
- real_t ZHZ[NVMAX];
-
- real_t sum, inv;
- for (j = 0; j < nZ; ++j)
- {
- /* Cache one column of Z. */
- for (i = 0; i < NVMAX; ++i)
- ZHZ[i] = Q[i * NVMAX + j];
-
- /* Create one column of the product H * Z. */
- for (i = 0; i < nFR; ++i)
- {
- ii = FR_idx[i];
-
- sum = 0.0;
- for (k = 0; k < nFR; ++k)
- {
- kk = FR_idx[k];
- sum += H[ii * NVMAX + kk] * ZHZ[kk];
- }
- HZ[ii] = sum;
- }
-
- /* Create one column of the product Z^T * H * Z. */
- for (i = j; i < nZ; ++i)
- ZHZ[ i ] = 0.0;
-
- for (k = 0; k < nFR; ++k)
- {
- kk = FR_idx[k];
- real_t q = HZ[kk];
- for (i = j; i < nZ; ++i)
- {
- ZHZ[i] += Q[kk * NVMAX + i] * q;
- }
- }
-
- /* Use the computed column to update the factorization. */
- /* j == i */
- sum = ZHZ[j];
-
- for (k = (j - 1); k >= 0; --k)
- sum -= R[k * NVMAX + j] * R[k * NVMAX + j];
-
- if (sum > 0.0)
- {
- R[j * NVMAX + j] = sqrt(sum);
- inv = 1.0 / R[j * NVMAX + j];
- }
- else
- {
- hessianType = HST_SEMIDEF;
- return THROWERROR( RET_HESSIAN_NOT_SPD );
- }
-
- for (i = (j + 1); i < nZ; ++i)
- {
- sum = ZHZ[i];
-
- for (k = (j - 1); k >= 0; --k)
- sum -= R[k * NVMAX + j] * R[k * NVMAX + i];
-
- R[j * NVMAX + i] = sum * inv;
- }
- }
-#endif
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t u p T Q f a c t o r i s a t i o n
- */
-returnValue QProblem::setupTQfactorisation( )
-{
- int i, j, ii;
- int nV = getNV( );
- int nFR = getNFR( );
-
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INDEXLIST_CORRUPTED );
-
- /* 1) Set Q to unity matrix. */
- for( i=0; igetStatus( i );
-
- if ( constraints.getType( i ) == ST_EQUALITY )
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryConstraints->setupConstraint( i,guessedStatus ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
- else /* No initial working set specified. */
- {
- /* Obtain initial working set by "clipping". */
- if ( ( xOpt != 0 ) && ( yOpt == 0 ) )
- {
- for( i=0; isetupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- if ( Ax[i] >= ubA[i] - BOUNDTOL )
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_UPPER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- /* Moreover, add all equality constraints if specified. */
- if ( constraints.getType( i ) == ST_EQUALITY )
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
-
- /* Obtain initial working set in accordance to sign of dual solution vector. */
- if ( ( xOpt == 0 ) && ( yOpt != 0 ) )
- {
- for( i=0; i ZERO )
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- if ( yOpt[nV+i] < -ZERO )
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_UPPER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- /* Moreover, add all equality constraints if specified. */
- if ( constraints.getType( i ) == ST_EQUALITY )
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
-
- /* If xOpt and yOpt are null pointer and no initial working is specified,
- * start with empty working set (or implicitly fixed bounds and equality constraints only)
- * for auxiliary QP. */
- if ( ( xOpt == 0 ) && ( yOpt == 0 ) )
- {
- for( i=0; isetupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryConstraints->setupConstraint( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*
- * s e t u p A u x i l i a r y W o r k i n g S e t
- */
-returnValue QProblem::setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds,
- const Constraints* const auxiliaryConstraints,
- BooleanType setupAfresh
- )
-{
- int i;
- int nV = getNV( );
- int nC = getNC( );
-
- /* consistency checks */
- if ( auxiliaryBounds != 0 )
- {
- for( i=0; igetStatus( i ) == ST_UNDEFINED ) )
- return THROWERROR( RET_UNKNOWN_BUG );
- }
- else
- {
- return THROWERROR( RET_INVALID_ARGUMENTS );
- }
-
- if ( auxiliaryConstraints != 0 )
- {
- for( i=0; igetStatus( i ) == ST_UNDEFINED ) )
- return THROWERROR( RET_UNKNOWN_BUG );
- }
- else
- {
- return THROWERROR( RET_INVALID_ARGUMENTS );
- }
-
-
- /* I) SETUP CHOLESKY FLAG:
- * Cholesky decomposition shall only be updated if working set
- * shall be updated (i.e. NOT setup afresh!) */
- BooleanType updateCholesky;
- if ( setupAfresh == BT_TRUE )
- updateCholesky = BT_FALSE;
- else
- updateCholesky = BT_TRUE;
-
-
- /* II) REMOVE FORMERLY ACTIVE (CONSTRAINTS') BOUNDS (IF NECESSARY): */
- if ( setupAfresh == BT_FALSE )
- {
- /* 1) Remove all active constraints that shall be inactive AND
- * all active constraints that are active at the wrong bound. */
- for( i=0; igetStatus( i ) != ST_LOWER ) )
- if ( removeConstraint( i,updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
-
- if ( ( constraints.getStatus( i ) == ST_UPPER ) && ( auxiliaryConstraints->getStatus( i ) != ST_UPPER ) )
- if ( removeConstraint( i,updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
- }
-
- /* 2) Remove all active bounds that shall be inactive AND
- * all active bounds that are active at the wrong bound. */
- for( i=0; igetStatus( i ) != ST_LOWER ) )
- if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
-
- if ( ( bounds.getStatus( i ) == ST_UPPER ) && ( auxiliaryBounds->getStatus( i ) != ST_UPPER ) )
- if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
- }
- }
-
-
- /* III) ADD NEWLY ACTIVE (CONSTRAINTS') BOUNDS: */
- /* 1) Add all inactive bounds that shall be active AND
- * all formerly active bounds that have been active at the wrong bound. */
- for( i=0; igetStatus( i ) != ST_INACTIVE ) )
- {
- /* Add bound only if it is linearly independent from the current working set. */
- if ( addBound_checkLI( i ) == RET_LINEARLY_INDEPENDENT )
- {
- if ( addBound( i,auxiliaryBounds->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
- }
- }
- }
-
- /* 2) Add all inactive constraints that shall be active AND
- * all formerly active constraints that have been active at the wrong bound. */
- for( i=0; igetStatus( i ) == ST_LOWER ) || ( auxiliaryConstraints->getStatus( i ) == ST_UPPER ) )
- {
- /* formerly inactive */
- if ( constraints.getStatus( i ) == ST_INACTIVE )
- {
- /* Add constraint only if it is linearly independent from the current working set. */
- if ( addConstraint_checkLI( i ) == RET_LINEARLY_INDEPENDENT )
- {
- if ( addConstraint( i,auxiliaryConstraints->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
- }
- }
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t u p A u x i l i a r y Q P s o l u t i o n
- */
-returnValue QProblem::setupAuxiliaryQPsolution( const real_t* const xOpt, const real_t* const yOpt
- )
-{
- int i, j;
- int nV = getNV( );
- int nC = getNC( );
-
-
- /* Setup primal/dual solution vector for auxiliary initial QP:
- * if a null pointer is passed, a zero vector is assigned;
- * old solution vector is kept if pointer to internal solution vevtor is passed. */
- if ( xOpt != 0 )
- {
- if ( xOpt != x )
- for( i=0; igetStatus( i ) == ST_LOWER )
- lb[i] = x[i];
- else
- lb[i] = x[i] - BOUNDRELAXATION;
-
- if ( auxiliaryBounds->getStatus( i ) == ST_UPPER )
- ub[i] = x[i];
- else
- ub[i] = x[i] + BOUNDRELAXATION;
- }
- }
- break;
-
- case ST_LOWER:
- lb[i] = x[i];
- if ( bounds.getType( i ) == ST_EQUALITY )
- {
- ub[i] = x[i];
- }
- else
- {
- if ( useRelaxation == BT_TRUE )
- ub[i] = x[i] + BOUNDRELAXATION;
- }
- break;
-
- case ST_UPPER:
- ub[i] = x[i];
- if ( bounds.getType( i ) == ST_EQUALITY )
- {
- lb[i] = x[i];
- }
- else
- {
- if ( useRelaxation == BT_TRUE )
- lb[i] = x[i] - BOUNDRELAXATION;
- }
- break;
-
- default:
- return THROWERROR( RET_UNKNOWN_BUG );
- }
- }
-
- /* 2) Setup constraints vectors. */
- for ( i=0; igetStatus( i ) == ST_LOWER )
- lbA[i] = Ax[i];
- else
- lbA[i] = Ax[i] - BOUNDRELAXATION;
-
- if ( auxiliaryConstraints->getStatus( i ) == ST_UPPER )
- ubA[i] = Ax[i];
- else
- ubA[i] = Ax[i] + BOUNDRELAXATION;
- }
- }
- break;
-
- case ST_LOWER:
- lbA[i] = Ax[i];
- if ( constraints.getType( i ) == ST_EQUALITY )
- {
- ubA[i] = Ax[i];
- }
- else
- {
- if ( useRelaxation == BT_TRUE )
- ubA[i] = Ax[i] + BOUNDRELAXATION;
- }
- break;
-
- case ST_UPPER:
- ubA[i] = Ax[i];
- if ( constraints.getType( i ) == ST_EQUALITY )
- {
- lbA[i] = Ax[i];
- }
- else
- {
- if ( useRelaxation == BT_TRUE )
- lbA[i] = Ax[i] - BOUNDRELAXATION;
- }
- break;
-
- default:
- return THROWERROR( RET_UNKNOWN_BUG );
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * a d d C o n s t r a i n t
- */
-returnValue QProblem::addConstraint( int number, SubjectToStatus C_status,
- BooleanType updateCholesky
- )
-{
- int i, j, ii;
-
- /* consistency checks */
- if ( constraints.getStatus( number ) != ST_INACTIVE )
- return THROWERROR( RET_CONSTRAINT_ALREADY_ACTIVE );
-
- if ( ( constraints.getNC( ) - getNAC( ) ) == constraints.getNUC( ) )
- return THROWERROR( RET_ALL_CONSTRAINTS_ACTIVE );
-
- if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
- ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
- ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
- ( getStatus( ) == QPS_SOLVED ) )
- {
- return THROWERROR( RET_UNKNOWN_BUG );
- }
-
-
- /* I) ENSURE LINEAR INDEPENDENCE OF THE WORKING SET,
- * i.e. remove a constraint or bound if linear dependence occurs. */
- /* check for LI only if Cholesky decomposition shall be updated! */
- if ( updateCholesky == BT_TRUE )
- {
- returnValue ensureLIreturnvalue = addConstraint_ensureLI( number,C_status );
-
- switch ( ensureLIreturnvalue )
- {
- case SUCCESSFUL_RETURN:
- break;
-
- case RET_LI_RESOLVED:
- break;
-
- case RET_ENSURELI_FAILED_NOINDEX:
- return THROWERROR( RET_ADDCONSTRAINT_FAILED_INFEASIBILITY );
-
- case RET_ENSURELI_FAILED_CYCLING:
- return THROWERROR( RET_ADDCONSTRAINT_FAILED_INFEASIBILITY );
-
- default:
- return THROWERROR( RET_ENSURELI_FAILED );
- }
- }
-
- /* some definitions */
- int nFR = getNFR( );
- int nAC = getNAC( );
- int nZ = getNZ( );
-
- int tcol = sizeT - nAC;
-
-
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ADDCONSTRAINT_FAILED );
-
- real_t aFR[NVMAX];
- real_t wZ[NVMAX];
- for( i=0; i 0 )
- {
- for( j=0; j 0 )
- {
- /* II) RESTORE TRIANGULAR FORM OF T: */
- /* Use column-wise Givens rotations to restore reverse triangular form
- * of T, simultanenous change of Q (i.e. Z) and R. */
- for( j=0; jgetNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INDEXLIST_CORRUPTED );
-
- /* Check if constraint is linearly independent from the
- the active ones (<=> is element of null space of Afr). */
- real_t sum;
-
- for( i=0; i 10.0*EPS )
- return RET_LINEARLY_INDEPENDENT;
- }
-
- return RET_LINEARLY_DEPENDENT;
-}
-
-
-/*
- * a d d C o n s t r a i n t _ e n s u r e L I
- */
-returnValue QProblem::addConstraint_ensureLI( int number, SubjectToStatus C_status )
-{
- int i, j, ii, jj;
- int nV = getNV( );
- int nFR = getNFR( );
- int nFX = getNFX( );
- int nAC = getNAC( );
- int nZ = getNZ( );
-
-
- /* I) Check if new constraint is linearly independent from the active ones. */
- returnValue returnvalueCheckLI = addConstraint_checkLI( number );
-
- if ( returnvalueCheckLI == RET_INDEXLIST_CORRUPTED )
- return THROWERROR( RET_ENSURELI_FAILED );
-
- if ( returnvalueCheckLI == RET_LINEARLY_INDEPENDENT )
- return SUCCESSFUL_RETURN;
-
-
- /* II) NEW CONSTRAINT IS LINEARLY DEPENDENT: */
- /* 1) Determine coefficients of linear combination,
- * cf. M.J. Best. Applied Mathematics and Parallel Computing, chapter:
- * An Algorithm for the Solution of the Parametric Quadratic Programming
- * Problem, pages 57-76. Physica-Verlag, Heidelberg, 1996. */
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ENSURELI_FAILED );
-
- int FX_idx[NVMAX];
- if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ENSURELI_FAILED );
-
- real_t xiC[NCMAX_ALLOC];
- real_t xiC_TMP[NCMAX_ALLOC];
- real_t xiB[NVMAX];
-
- /* 2) Calculate xiC */
- if ( nAC > 0 )
- {
- if ( C_status == ST_LOWER )
- {
- for( i=0; igetNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ENSURELI_FAILED );
-
- if ( C_status == ST_LOWER )
- {
- for( i=0; i ZERO ) && ( y[nV+ii] >= 0.0 ) )
- {
- if ( y[nV+ii]/xiC[i] < y_min )
- {
- y_min = y[nV+ii]/xiC[i];
- y_min_number = ii;
- }
- }
- }
- else
- {
- if ( ( xiC[i] < -ZERO ) && ( y[nV+ii] <= 0.0 ) )
- {
- if ( y[nV+ii]/xiC[i] < y_min )
- {
- y_min = y[nV+ii]/xiC[i];
- y_min_number = ii;
- }
- }
- }
- }
-
- /* 2) Bounds. */
- for( i=0; i ZERO ) && ( y[ii] >= 0.0 ) )
- {
- if ( y[ii]/xiB[i] < y_min )
- {
- y_min = y[ii]/xiB[i];
- y_min_number = ii;
- y_min_isBound = BT_TRUE;
- }
- }
- }
- else
- {
- if ( ( xiB[i] < -ZERO ) && ( y[ii] <= 0.0 ) )
- {
- if ( y[ii]/xiB[i] < y_min )
- {
- y_min = y[ii]/xiB[i];
- y_min_number = ii;
- y_min_isBound = BT_TRUE;
- }
- }
- }
- }
-
- /* setup output preferences */
- #ifdef PC_DEBUG
- char messageString[80];
- VisibilityStatus visibilityStatus;
-
- if ( printlevel == PL_HIGH )
- visibilityStatus = VS_VISIBLE;
- else
- visibilityStatus = VS_HIDDEN;
- #endif
-
-
- /* IV) REMOVE CONSTRAINT/BOUND FOR RESOLVING LINEAR DEPENDENCE: */
- if ( y_min_number >= 0 )
- {
- /* 1) Check for cycling due to infeasibility. */
- if ( ( cyclingManager.getCyclingStatus( number,BT_FALSE ) == CYC_PREV_REMOVED ) &&
- ( cyclingManager.getCyclingStatus( y_min_number,y_min_isBound ) == CYC_PREV_ADDED ) )
- {
- infeasible = BT_TRUE;
-
- return THROWERROR( RET_ENSURELI_FAILED_CYCLING );
- }
- else
- {
- /* set cycling data */
- cyclingManager.clearCyclingData( );
- cyclingManager.setCyclingStatus( number,BT_FALSE, CYC_PREV_ADDED );
- cyclingManager.setCyclingStatus( y_min_number,y_min_isBound, CYC_PREV_REMOVED );
- }
-
- /* 2) Update Lagrange multiplier... */
- for( i=0; ithrowInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( removeBound( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
-
- y[y_min_number] = 0.0;
- }
- else
- {
- #ifdef PC_DEBUG
- sprintf( messageString,"constraint no. %d.",y_min_number );
- getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( removeConstraint( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
-
- y[nV+y_min_number] = 0.0;
- }
- }
- else
- {
- /* no constraint/bound can be removed => QP is infeasible! */
- infeasible = BT_TRUE;
-
- return THROWERROR( RET_ENSURELI_FAILED_NOINDEX );
- }
-
- return getGlobalMessageHandler( )->throwInfo( RET_LI_RESOLVED,0,__FUNCTION__,__FILE__,__LINE__,VS_HIDDEN );
-}
-
-
-
-/*
- * a d d B o u n d
- */
-returnValue QProblem::addBound( int number, SubjectToStatus B_status,
- BooleanType updateCholesky
- )
-{
- int i, j, ii;
-
- /* consistency checks */
- if ( bounds.getStatus( number ) != ST_INACTIVE )
- return THROWERROR( RET_BOUND_ALREADY_ACTIVE );
-
- if ( getNFR( ) == bounds.getNUV( ) )
- return THROWERROR( RET_ALL_BOUNDS_ACTIVE );
-
- if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
- ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
- ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
- ( getStatus( ) == QPS_SOLVED ) )
- {
- return THROWERROR( RET_UNKNOWN_BUG );
- }
-
-
- /* I) ENSURE LINEAR INDEPENDENCE OF THE WORKING SET,
- * i.e. remove a constraint or bound if linear dependence occurs. */
- /* check for LI only if Cholesky decomposition shall be updated! */
- if ( updateCholesky == BT_TRUE )
- {
- returnValue ensureLIreturnvalue = addBound_ensureLI( number,B_status );
-
- switch ( ensureLIreturnvalue )
- {
- case SUCCESSFUL_RETURN:
- break;
-
- case RET_LI_RESOLVED:
- break;
-
- case RET_ENSURELI_FAILED_NOINDEX:
- return THROWERROR( RET_ADDBOUND_FAILED_INFEASIBILITY );
-
- case RET_ENSURELI_FAILED_CYCLING:
- return THROWERROR( RET_ADDBOUND_FAILED_INFEASIBILITY );
-
- default:
- return THROWERROR( RET_ENSURELI_FAILED );
- }
- }
-
-
- /* some definitions */
- int nFR = getNFR( );
- int nAC = getNAC( );
- int nZ = getNZ( );
-
- int tcol = sizeT - nAC;
-
-
- /* I) SWAP INDEXLIST OF FREE VARIABLES:
- * move the variable to be fixed to the end of the list of free variables. */
- int lastfreenumber = bounds.getFree( )->getLastNumber( );
- if ( lastfreenumber != number )
- if ( bounds.swapFree( number,lastfreenumber ) != SUCCESSFUL_RETURN )
- THROWERROR( RET_ADDBOUND_FAILED );
-
-
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ADDBOUND_FAILED );
-
- real_t w[NVMAX];
-
-
- /* II) ADD NEW ACTIVE BOUND TO TOP OF MATRIX T: */
- /* 1) add row [wZ wY] = [Z Y](number) at the top of T: assign w */
- for( i=0; i 0 ) /* ( nAC == 0 ) <=> ( nZ == nFR ) <=> Y and T are empty => nothing to do */
- {
- /* store new column a in a temporary vector instead of shifting T one column to the left */
- real_t tmp[NCMAX_ALLOC];
- for( i=0; i is linearly independent from the
- the active ones (<=> is element of null space of Afr). */
- for( i=0; i EPS )
- return RET_LINEARLY_INDEPENDENT;
- }
-
- return RET_LINEARLY_DEPENDENT;
-}
-
-
-/*
- * a d d B o u n d _ e n s u r e L I
- */
-returnValue QProblem::addBound_ensureLI( int number, SubjectToStatus B_status )
-{
- int i, j, ii, jj;
- int nV = getNV( );
- int nFX = getNFX( );
- int nAC = getNAC( );
- int nZ = getNZ( );
-
-
- /* I) Check if new constraint is linearly independent from the active ones. */
- returnValue returnvalueCheckLI = addBound_checkLI( number );
-
- if ( returnvalueCheckLI == RET_LINEARLY_INDEPENDENT )
- return SUCCESSFUL_RETURN;
-
-
- /* II) NEW BOUND IS LINEARLY DEPENDENT: */
- /* 1) Determine coefficients of linear combination,
- * cf. M.J. Best. Applied Mathematics and Parallel Computing, chapter:
- * An Algorithm for the Solution of the Parametric Quadratic Programming
- * Problem, pages 57-76. Physica-Verlag, Heidelberg, 1996. */
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ENSURELI_FAILED );
-
- int FX_idx[NVMAX];
- if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ENSURELI_FAILED );
-
- int AC_idx[NCMAX_ALLOC];
- if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ENSURELI_FAILED );
-
- real_t xiC[NCMAX_ALLOC];
- real_t xiC_TMP[NCMAX_ALLOC];
- real_t xiB[NVMAX];
-
- /* 2) Calculate xiC. */
- if ( nAC > 0 )
- {
- if ( B_status == ST_LOWER )
- {
- for( i=0; i ZERO ) && ( y[nV+ii] >= 0.0 ) )
- {
- if ( y[nV+ii]/xiC[i] < y_min )
- {
- y_min = y[nV+ii]/xiC[i];
- y_min_number = ii;
- }
- }
- }
- else
- {
- if ( ( xiC[i] < -ZERO ) && ( y[nV+ii] <= 0.0 ) )
- {
- if ( y[nV+ii]/xiC[i] < y_min )
- {
- y_min = y[nV+ii]/xiC[i];
- y_min_number = ii;
- }
- }
- }
- }
-
- /* 2) Bounds. */
- for( i=0; i ZERO ) && ( y[ii] >= 0.0 ) )
- {
- if ( y[ii]/xiB[i] < y_min )
- {
- y_min = y[ii]/xiB[i];
- y_min_number = ii;
- y_min_isBound = BT_TRUE;
- }
- }
- }
- else
- {
- if ( ( xiB[i] < -ZERO ) && ( y[ii] <= 0.0 ) )
- {
- if ( y[ii]/xiB[i] < y_min )
- {
- y_min = y[ii]/xiB[i];
- y_min_number = ii;
- y_min_isBound = BT_TRUE;
- }
- }
- }
- }
-
- /* setup output preferences */
- #ifdef PC_DEBUG
- char messageString[80];
- VisibilityStatus visibilityStatus;
-
- if ( printlevel == PL_HIGH )
- visibilityStatus = VS_VISIBLE;
- else
- visibilityStatus = VS_HIDDEN;
- #endif
-
-
- /* IV) REMOVE CONSTRAINT/BOUND FOR RESOLVING LINEAR DEPENDENCE: */
- if ( y_min_number >= 0 )
- {
- /* 1) Check for cycling due to infeasibility. */
- if ( ( cyclingManager.getCyclingStatus( number,BT_TRUE ) == CYC_PREV_REMOVED ) &&
- ( cyclingManager.getCyclingStatus( y_min_number,y_min_isBound ) == CYC_PREV_ADDED ) )
- {
- infeasible = BT_TRUE;
-
- return THROWERROR( RET_ENSURELI_FAILED_CYCLING );
- }
- else
- {
- /* set cycling data */
- cyclingManager.clearCyclingData( );
- cyclingManager.setCyclingStatus( number,BT_TRUE, CYC_PREV_ADDED );
- cyclingManager.setCyclingStatus( y_min_number,y_min_isBound, CYC_PREV_REMOVED );
- }
-
-
- /* 2) Update Lagrange multiplier... */
- for( i=0; ithrowInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( removeBound( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
-
- y[y_min_number] = 0.0;
- }
- else
- {
- #ifdef PC_DEBUG
- sprintf( messageString,"constraint no. %d.",y_min_number );
- getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( removeConstraint( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
-
- y[nV+y_min_number] = 0.0;
- }
- }
- else
- {
- /* no constraint/bound can be removed => QP is infeasible! */
- infeasible = BT_TRUE;
-
- return THROWERROR( RET_ENSURELI_FAILED_NOINDEX );
- }
-
- return getGlobalMessageHandler( )->throwInfo( RET_LI_RESOLVED,0,__FUNCTION__,__FILE__,__LINE__,VS_HIDDEN );
-}
-
-
-
-/*
- * r e m o v e C o n s t r a i n t
- */
-returnValue QProblem::removeConstraint( int number,
- BooleanType updateCholesky
- )
-{
- int i, j, ii, jj;
-
- /* consistency check */
- if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
- ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
- ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
- ( getStatus( ) == QPS_SOLVED ) )
- {
- return THROWERROR( RET_UNKNOWN_BUG );
- }
-
- /* some definitions */
- int nFR = getNFR( );
- int nAC = getNAC( );
- int nZ = getNZ( );
-
- int tcol = sizeT - nAC;
- int number_idx = constraints.getActive( )->getIndex( number );
-
-
- /* consistency checks */
- if ( constraints.getStatus( number ) == ST_INACTIVE )
- return THROWERROR( RET_CONSTRAINT_NOT_ACTIVE );
-
- if ( ( number_idx < 0 ) || ( number_idx >= nAC ) )
- return THROWERROR( RET_CONSTRAINT_NOT_ACTIVE );
-
-
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVECONSTRAINT_FAILED );
-
-
- /* I) REMOVE th ROW FROM T,
- * i.e. shift rows number+1 through nAC upwards (instead of the actual
- * constraint number its corresponding index within matrix A is used). */
- if ( number_idx < nAC-1 )
- {
- for( i=(number_idx+1); i=0; --j )
- {
- computeGivens( T[(nAC-2-j)*NVMAX + tcol+1+j],T[(nAC-2-j)*NVMAX + tcol+j], T[(nAC-2-j)*NVMAX + tcol+1+j],T[(nAC-2-j)*NVMAX + tcol+j],c,s );
-
- for( i=(nAC-j-1); i<(nAC-1); ++i )
- applyGivens( c,s,T[i*NVMAX + tcol+1+j],T[i*NVMAX + tcol+j], T[i*NVMAX + tcol+1+j],T[i*NVMAX + tcol+j] );
-
- for( i=0; i 0 )
- {
- real_t ZHz[NVMAX];
- for ( i=0; i 0.0 )
- R[nZ*NVMAX + nZ] = sqrt( rho2 );
- else
- {
- hessianType = HST_SEMIDEF;
- return THROWERROR( RET_HESSIAN_NOT_SPD );
- }
- }
-
- /* IV) UPDATE INDICES */
- if ( constraints.moveActiveToInactive( number ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVECONSTRAINT_FAILED );
-
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * r e m o v e B o u n d
- */
-returnValue QProblem::removeBound( int number,
- BooleanType updateCholesky
- )
-{
- int i, j, ii, jj;
-
- /* consistency checks */
- if ( bounds.getStatus( number ) == ST_INACTIVE )
- return THROWERROR( RET_BOUND_NOT_ACTIVE );
-
- if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
- ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
- ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
- ( getStatus( ) == QPS_SOLVED ) )
- {
- return THROWERROR( RET_UNKNOWN_BUG );
- }
-
- /* some definitions */
- int nFR = getNFR( );
- int nAC = getNAC( );
- int nZ = getNZ( );
-
- int tcol = sizeT - nAC;
-
-
- /* I) UPDATE INDICES */
- if ( bounds.moveFixedToFree( number ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVEBOUND_FAILED );
-
-
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVEBOUND_FAILED );
-
- /* I) APPEND th UNITY VECOTR TO Q. */
- int nnFRp1 = FR_idx[nFR];
- for( i=0; i 0 )
- {
- /* store new column a in a temporary vector instead of shifting T one column to the left and appending a */
- int AC_idx[NCMAX_ALLOC];
- if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVEBOUND_FAILED );
-
- real_t tmp[NCMAX_ALLOC];
- for( i=0; i=0; --j )
- {
- computeGivens( tmp[nAC-1-j],T[(nAC-1-j)*NVMAX + tcol+j],T[(nAC-1-j)*NVMAX + tcol+j],tmp[nAC-1-j],c,s );
-
- for( i=(nAC-j); i 0 )
- {
- real_t Hz[NVMAX];
- for( i=0; i 0 )
- {
- real_t r[NVMAX];
- real_t rhs[NVMAX];
- for( i=0; i 0.0 )
- R[nZ*NVMAX + nZ] = sqrt( rho2 );
- else
- {
- hessianType = HST_SEMIDEF;
- return THROWERROR( RET_HESSIAN_NOT_SPD );
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * b a c k s o l v e R (CODE DUPLICATE OF QProblemB CLASS!!!)
- */
-returnValue QProblem::backsolveR( const real_t* const b, BooleanType transposed,
- real_t* const a
- )
-{
- /* Call standard backsolve procedure (i.e. removingBound == BT_FALSE). */
- return backsolveR( b,transposed,BT_FALSE,a );
-}
-
-
-/*
- * b a c k s o l v e R (CODE DUPLICATE OF QProblemB CLASS!!!)
- */
-returnValue QProblem::backsolveR( const real_t* const b, BooleanType transposed,
- BooleanType removingBound,
- real_t* const a
- )
-{
- int i, j;
- int nR = getNZ( );
-
- real_t sum;
-
- /* if backsolve is called while removing a bound, reduce nZ by one. */
- if ( removingBound == BT_TRUE )
- --nR;
-
- /* nothing to do */
- if ( nR <= 0 )
- return SUCCESSFUL_RETURN;
-
-
- /* Solve Ra = b, where R might be transposed. */
- if ( transposed == BT_FALSE )
- {
- /* solve Ra = b */
- for( i=(nR-1); i>=0; --i )
- {
- sum = b[i];
- for( j=(i+1); j ZERO )
- a[i] = sum / R[i*NVMAX + i];
- else
- return THROWERROR( RET_DIV_BY_ZERO );
- }
- }
- else
- {
- /* solve R^T*a = b */
- for( i=0; i ZERO )
- a[i] = sum / R[i*NVMAX + i];
- else
- return THROWERROR( RET_DIV_BY_ZERO );
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*
- * b a c k s o l v e T
- */
-returnValue QProblem::backsolveT( const real_t* const b, BooleanType transposed, real_t* const a )
-{
- int i, j;
- int nT = getNAC( );
- int tcol = sizeT - nT;
-
- real_t sum;
-
- /* nothing to do */
- if ( nT <= 0 )
- return SUCCESSFUL_RETURN;
-
-
- /* Solve Ta = b, where T might be transposed. */
- if ( transposed == BT_FALSE )
- {
- /* solve Ta = b */
- for( i=0; i ZERO )
- a[nT-1-i] = sum / T[i*NVMAX + sizeT-1-i];
- else
- return THROWERROR( RET_DIV_BY_ZERO );
- }
- }
- else
- {
- /* solve T^T*a = b */
- for( i=0; i ZERO )
- a[nT-1-i] = sum / T[(nT-1-i)*NVMAX + tcol+i];
- else
- return THROWERROR( RET_DIV_BY_ZERO );
- }
- }
-
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * h o t s t a r t _ d e t e r m i n e D a t a S h i f t
- */
-returnValue QProblem::hotstart_determineDataShift( const int* const FX_idx, const int* const AC_idx,
- const real_t* const g_new, const real_t* const lbA_new, const real_t* const ubA_new,
- const real_t* const lb_new, const real_t* const ub_new,
- real_t* const delta_g, real_t* const delta_lbA, real_t* const delta_ubA,
- real_t* const delta_lb, real_t* const delta_ub,
- BooleanType& Delta_bC_isZero, BooleanType& Delta_bB_isZero
- )
-{
- int i, ii;
- int nC = getNC( );
- int nAC = getNAC( );
-
-
- /* I) DETERMINE DATA SHIFT FOR BOUNDS */
- QProblemB::hotstart_determineDataShift( FX_idx,g_new,lb_new,ub_new, delta_g,delta_lb,delta_ub, Delta_bB_isZero );
-
-
- /* II) DETERMINE DATA SHIFT FOR CONSTRAINTS */
- /* 1) Calculate shift directions. */
- for( i=0; i EPS ) || ( getAbs( delta_ubA[ii] ) > EPS ) )
- {
- Delta_bC_isZero = BT_FALSE;
- break;
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * h o t s t a r t _ d e t e r m i n e S t e p D i r e c t i o n
- */
-returnValue QProblem::hotstart_determineStepDirection( const int* const FR_idx, const int* const FX_idx, const int* const AC_idx,
- const real_t* const delta_g, const real_t* const delta_lbA, const real_t* const delta_ubA,
- const real_t* const delta_lb, const real_t* const delta_ub,
- BooleanType Delta_bC_isZero, BooleanType Delta_bB_isZero,
- real_t* const delta_xFX, real_t* const delta_xFR,
- real_t* const delta_yAC, real_t* const delta_yFX
- )
-{
- int i, j, ii, jj;
- int nFR = getNFR( );
- int nFX = getNFX( );
- int nAC = getNAC( );
- int nZ = getNZ( );
-
- /* initialise auxiliary vectors */
- real_t HMX_delta_xFX[NVMAX];
- real_t YFR_delta_xFRy[NVMAX];
- real_t ZFR_delta_xFRz[NVMAX];
- real_t HFR_YFR_delta_xFRy[NVMAX];
- for( i=0; i 0 )
- {
- for( i=0; i 0 )
- {
- /* 1) Determine delta_xFRy. */
- if ( nAC > 0 )
- {
- if ( ( Delta_bC_isZero == BT_TRUE ) && ( Delta_bB_isZero == BT_TRUE ) )
- {
- for( i=0; i 0 )
- {
- for( i=0; i 0 )
- {
- if ( ( Delta_bC_isZero == BT_FALSE ) || ( Delta_bB_isZero == BT_FALSE ) )
- {
- for( i=0; i 0 )
- {
- /* auxiliary variable */
- real_t delta_xFRz_TMP[NVMAX];
- real_t delta_xFRz_RHS[NVMAX];
-
-
- if ( ( nAC > 0 ) && ( nFX > 0 ) && ( Delta_bB_isZero == BT_FALSE ) )
- {
- for( j=0; j 0 ) /* => Delta_bB_isZero == BT_TRUE, as BT_FALSE would imply nFX>0 */
- {
- for( j=0; j 0 ) /* => ( nFR = nZ + nAC > 0 ) */
- {
- /* auxiliary variables */
- real_t delta_yAC_TMP[NCMAX_ALLOC];
- for( i=0; i 0 )
- {
- for( i=0; i 0 )
- {
- if ( Delta_bB_isZero == BT_FALSE )
- {
- for( i=0; i 0 )
- {
- for( i=0; i 0.0 )
- maxStepLength[nV+ii] = y[nV+ii] / ( -delta_yAC[i] );
- else
- maxStepLength[nV+ii] = 0.0;
- }
- }
- else
- {
- /* active upper constraints' bounds */
- if ( delta_yAC[i] > ZERO )
- {
- if ( y[nV+ii] < 0.0 )
- maxStepLength[nV+ii] = y[nV+ii] / ( -delta_yAC[i] );
- else
- maxStepLength[nV+ii] = 0.0;
- }
- }
- }
- }
-
- /* 2) Ensure that active dual bounds remain valid
- * (ignoring implicitly fixed variables). */
- for( i=0; i 0.0 )
- maxStepLength[ii] = y[ii] / ( -delta_yFX[i] );
- else
- maxStepLength[ii] = 0.0;
- }
- }
- else
- {
- /* active upper bounds */
- if ( delta_yFX[i] > ZERO )
- {
- if ( y[ii] < 0.0 )
- maxStepLength[ii] = y[ii] / ( -delta_yFX[i] );
- else
- maxStepLength[ii] = 0.0;
- }
- }
- }
- }
-
-
- /* II) DETERMINE MAXIMUM PRIMAL STEPLENGTH */
- /* 1) Ensure that inactive constraints' bounds remain valid
- * (ignoring unbounded constraints). */
- real_t delta_x[NVMAX];
- for( j=0; j delta_Ax[ii] )
- {
- if ( Ax[ii] > lbA[ii] )
- maxStepLength[nV+ii] = ( Ax[ii] - lbA[ii] ) / ( delta_lbA[ii] - delta_Ax[ii] );
- else
- maxStepLength[nV+ii] = 0.0;
- }
- }
-
- /* inactive upper constraints' bounds */
- if ( constraints.isNoUpper( ) == BT_FALSE )
- {
- if ( delta_ubA[ii] < delta_Ax[ii] )
- {
- if ( Ax[ii] < ubA[ii] )
- maxStepLength[nV+nC+nV+ii] = ( Ax[ii] - ubA[ii] ) / ( delta_ubA[ii] - delta_Ax[ii] );
- else
- maxStepLength[nV+nC+nV+ii] = 0.0;
- }
- }
- }
- }
-
-
- /* 2) Ensure that inactive bounds remain valid
- * (ignoring unbounded variables). */
- /* inactive lower bounds */
- if ( bounds.isNoLower( ) == BT_FALSE )
- {
- for( i=0; i delta_xFR[i] )
- {
- if ( x[ii] > lb[ii] )
- maxStepLength[ii] = ( x[ii] - lb[ii] ) / ( delta_lb[ii] - delta_xFR[i] );
- else
- maxStepLength[ii] = 0.0;
- }
- }
- }
-
- /* inactive upper bounds */
- if ( bounds.isNoUpper( ) == BT_FALSE )
- {
- for( i=0; i EPS )
- cyclingManager.clearCyclingData( );
-
-
- /* V) SET MAXIMUM HOMOTOPY STEPLENGTH */
- tau = tau_new;
-
- #ifdef PC_DEBUG
- if ( printlevel == PL_HIGH )
- {
-
- char messageString[80];
-
- if ( BC_status == ST_UNDEFINED )
- sprintf( messageString,"Stepsize is %.6e!",tau );
- else
- sprintf( messageString,"Stepsize is %.6e! (BC_idx = %d, BC_isBound = %d, BC_status = %d)",tau,BC_idx,BC_isBound,BC_status );
-
- getGlobalMessageHandler( )->throwInfo( RET_STEPSIZE_NONPOSITIVE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
- #endif
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * h o t s t a r t _ p e r f o r m S t e p
- */
-returnValue QProblem::hotstart_performStep( const int* const FR_idx, const int* const FX_idx, const int* const AC_idx, const int* const IAC_idx,
- const real_t* const delta_g, const real_t* const delta_lbA, const real_t* const delta_ubA,
- const real_t* const delta_lb, const real_t* const delta_ub,
- const real_t* const delta_xFX, const real_t* const delta_xFR,
- const real_t* const delta_yAC, const real_t* const delta_yFX,
- const real_t* const delta_Ax, int BC_idx, SubjectToStatus BC_status, BooleanType BC_isBound
- )
-{
- int i, j, ii;
- int nV = getNV( );
- int nC = getNC( );
- int nFR = getNFR( );
- int nFX = getNFX( );
- int nAC = getNAC( );
- int nIAC = getNIAC( );
-
-
- /* I) CHECK (CONSTRAINTS') BOUNDS' CONSISTENCY */
- if ( areBoundsConsistent( delta_lb,delta_ub,delta_lbA,delta_ubA ) == BT_FALSE )
- {
- infeasible = BT_TRUE;
- tau = 0.0;
-
- return THROWERROR( RET_QP_INFEASIBLE );
- }
-
-
- /* II) GO TO ACTIVE SET CHANGE */
- if ( tau > ZERO )
- {
- /* 1) Perform step in primal und dual space... */
- for( i=0; ithrowWarning( RET_STEPSIZE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- #endif
- }
-
-
- /* setup output preferences */
- #ifdef PC_DEBUG
- char messageString[80];
- VisibilityStatus visibilityStatus;
-
- if ( printlevel == PL_HIGH )
- visibilityStatus = VS_VISIBLE;
- else
- visibilityStatus = VS_HIDDEN;
- #endif
-
-
- /* III) UPDATE ACTIVE SET */
- switch ( BC_status )
- {
- /* Optimal solution found as no working set change detected. */
- case ST_UNDEFINED:
- return RET_OPTIMAL_SOLUTION_FOUND;
-
-
- /* Remove one variable from active set. */
- case ST_INACTIVE:
- if ( BC_isBound == BT_TRUE )
- {
- #ifdef PC_DEBUG
- sprintf( messageString,"bound no. %d.", BC_idx );
- getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( removeBound( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
-
- y[BC_idx] = 0.0;
- }
- else
- {
- #ifdef PC_DEBUG
- sprintf( messageString,"constraint no. %d.", BC_idx );
- getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( removeConstraint( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
-
- y[nV+BC_idx] = 0.0;
- }
- break;
-
-
- /* Add one variable to active set. */
- default:
- if ( BC_isBound == BT_TRUE )
- {
- #ifdef PC_DEBUG
- if ( BC_status == ST_LOWER )
- sprintf( messageString,"lower bound no. %d.", BC_idx );
- else
- sprintf( messageString,"upper bound no. %d.", BC_idx );
- getGlobalMessageHandler( )->throwInfo( RET_ADD_TO_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( addBound( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ADD_TO_ACTIVESET_FAILED );
- }
- else
- {
- #ifdef PC_DEBUG
- if ( BC_status == ST_LOWER )
- sprintf( messageString,"lower constraint's bound no. %d.", BC_idx );
- else
- sprintf( messageString,"upper constraint's bound no. %d.", BC_idx );
- getGlobalMessageHandler( )->throwInfo( RET_ADD_TO_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( addConstraint( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ADD_TO_ACTIVESET_FAILED );
- }
- break;
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * a r e B o u n d s C o n s i s t e n t
- */
-BooleanType QProblem::areBoundsConsistent( const real_t* const delta_lb, const real_t* const delta_ub,
- const real_t* const delta_lbA, const real_t* const delta_ubA
- ) const
-{
- int i;
-
- /* 1) Check bounds' consistency. */
- if ( QProblemB::areBoundsConsistent( delta_lb,delta_ub ) == BT_FALSE )
- return BT_FALSE;
-
- /* 2) Check constraints' consistency, i.e.
- * check if delta_lb[i] is greater than delta_ub[i]
- * for a component i whose bounds are already (numerically) equal. */
- for( i=0; i ubA[i] - BOUNDTOL ) && ( delta_lbA[i] > delta_ubA[i] + EPS ) )
- return BT_FALSE;
-
- return BT_TRUE;
-}
-
-
-/*
- * s e t u p Q P d a t a
- */
-returnValue QProblem::setupQPdata( const real_t* const _H, const real_t* const _R, const real_t* const _g, const real_t* const _A,
- const real_t* const _lb, const real_t* const _ub,
- const real_t* const _lbA, const real_t* const _ubA
- )
-{
- int i, j;
- int nV = getNV( );
- int nC = getNC( );
-
-
- /* 1) Load Hessian matrix as well as lower and upper bounds vectors. */
- if (QProblemB::setupQPdata(_H, _R, _g, _lb, _ub) != SUCCESSFUL_RETURN)
- return THROWERROR( RET_INVALID_ARGUMENTS );
-
- /* 2) Load constraint matrix. */
- if ( ( nC > 0 ) && ( _A == 0 ) )
- return THROWERROR( RET_INVALID_ARGUMENTS );
-
- if ( nC > 0 )
- {
- for( i=0; igetNumberArray( AC_idx );
-
- /* 1) check for Hx + g - [yFX yAC]*[Id A]' = 0. */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = getAbs( tmp );
- }
-
- /* 2) Check for [lb lbA] <= [Id A]*x <= [ub ubA]. */
- /* lbA <= Ax <= ubA */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = lbA[i] - Ax[i];
-
- if ( Ax[i] - ubA[i] > maxKKTviolation )
- maxKKTviolation = Ax[i] - ubA[i];
- }
-
- /* lb <= x <= ub */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = lb[i] - x[i];
-
- if ( x[i] - ub[i] > maxKKTviolation )
- maxKKTviolation = x[i] - ub[i];
- }
-
- /* 3) Check for correct sign of y and for complementary slackness. */
- /* bounds */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = -y[i];
- if ( getAbs( x[i] - lb[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( x[i] - lb[i] );
- break;
-
- case ST_UPPER:
- if ( y[i] > maxKKTviolation )
- maxKKTviolation = y[i];
- if ( getAbs( ub[i] - x[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( ub[i] - x[i] );
- break;
-
- default: /* inactive */
- if ( getAbs( y[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( y[i] );
- break;
- }
- }
-
- /* constraints */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = -y[nV+i];
- if ( getAbs( Ax[i] - lbA[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( Ax[i] - lbA[i] );
- break;
-
- case ST_UPPER:
- if ( y[nV+i] > maxKKTviolation )
- maxKKTviolation = y[nV+i];
- if ( getAbs( ubA[i] - Ax[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( ubA[i] - Ax[i] );
- break;
-
- default: /* inactive */
- if ( getAbs( y[nV+i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( y[nV+i] );
- break;
- }
- }
-
- if ( maxKKTviolation > CRITICALACCURACY )
- return RET_NO_SOLUTION;
-
- if ( maxKKTviolation > DESIREDACCURACY )
- return RET_INACCURATE_SOLUTION;
-
- #endif /* __PERFORM_KKT_TEST__ */
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/QProblem.ipp b/phonelibs/qpoases/SRC/QProblem.ipp
deleted file mode 100644
index e98ada633..000000000
--- a/phonelibs/qpoases/SRC/QProblem.ipp
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/QProblem.ipp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of inlined member functions of the QProblem class which
- * is able to use the newly developed online active set strategy for
- * parametric quadratic programming.
- */
-
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-/*
- * g e t A
- */
-inline returnValue QProblem::getA( real_t* const _A ) const
-{
- int i;
-
- for ( i=0; i= 0 ) && ( number < getNC( ) ) )
- {
- for ( int i=0; i= 0 ) && ( number < getNC( ) ) )
- {
- value = lbA[number];
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-}
-
-
-/*
- * g e t U B A
- */
-inline returnValue QProblem::getUBA( real_t* const _ubA ) const
-{
- int i;
-
- for ( i=0; i= 0 ) && ( number < getNC( ) ) )
- {
- value = ubA[number];
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-}
-
-
-/*
- * g e t C o n s t r a i n t s
- */
-inline returnValue QProblem::getConstraints( Constraints* const _constraints ) const
-{
- *_constraints = constraints;
-
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*
- * g e t N C
- */
-inline int QProblem::getNC( ) const
-{
- return constraints.getNC( );
-}
-
-
-/*
- * g e t N E C
- */
-inline int QProblem::getNEC( ) const
-{
- return constraints.getNEC( );
-}
-
-
-/*
- * g e t N A C
- */
-inline int QProblem::getNAC( )
-{
- return constraints.getNAC( );
-}
-
-
-/*
- * g e t N I A C
- */
-inline int QProblem::getNIAC( )
-{
- return constraints.getNIAC( );
-}
-
-
-
-/*****************************************************************************
- * P R O T E C T E D *
- *****************************************************************************/
-
-
-/*
- * s e t A
- */
-inline returnValue QProblem::setA( const real_t* const A_new )
-{
- int i, j;
- int nV = getNV( );
- int nC = getNC( );
-
- /* Set constraint matrix AND update member AX. */
- for( j=0; j= 0 ) && ( number < getNC( ) ) )
- {
- Ax[number] = 0.0;
-
- for( i=0; i= 0 ) && ( number < getNC( ) ) )
- {
- lbA[number] = value;
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-}
-
-
-/*
- * s e t U B A
- */
-inline returnValue QProblem::setUBA( const real_t* const ubA_new )
-{
- int i;
- int nC = getNC();
-
- for( i=0; i= 0 ) && ( number < getNC( ) ) )
- {
- ubA[number] = value;
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/QProblemB.cpp b/phonelibs/qpoases/SRC/QProblemB.cpp
deleted file mode 100644
index 47ac3536f..000000000
--- a/phonelibs/qpoases/SRC/QProblemB.cpp
+++ /dev/null
@@ -1,2151 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/QProblemB.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the QProblemB class which is able to use the newly
- * developed online active set strategy for parametric quadratic programming.
- */
-
-
-#include
-
-#include
-
-void printmatrix(char *name, double *A, int m, int n) {
- int i, j;
-
- printf("%s = [...\n", name);
- for (i = 0; i < m; i++) {
- for (j = 0; j < n; j++)
- printf(" % 9.4f", A[i*n+j]);
- printf(",\n");
- }
- printf("];\n");
-}
-
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * Q P r o b l e m B
- */
-QProblemB::QProblemB( )
-{
- /* reset global message handler */
- getGlobalMessageHandler( )->reset( );
-
- hasHessian = BT_FALSE;
-
- bounds.init( 0 );
-
- hasCholesky = BT_FALSE;
-
- tau = 0.0;
-
- hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
- infeasible = BT_FALSE;
- unbounded = BT_FALSE;
-
- status = QPS_NOTINITIALISED;
-
- #ifdef PC_DEBUG
- printlevel = PL_MEDIUM;
- setPrintLevel( PL_MEDIUM );
- #else
- printlevel = QPOASES_PRINTLEVEL;
- #endif
-
- count = 0;
-}
-
-
-/*
- * Q P r o b l e m B
- */
-QProblemB::QProblemB( int _nV )
-{
- /* consistency check */
- if ( _nV <= 0 )
- {
- _nV = 1;
- THROWERROR( RET_INVALID_ARGUMENTS );
- }
-
- hasHessian = BT_FALSE;
-
- /* reset global message handler */
- getGlobalMessageHandler( )->reset( );
-
- bounds.init( _nV );
-
- hasCholesky = BT_FALSE;
-
- tau = 0.0;
-
- hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
- infeasible = BT_FALSE;
- unbounded = BT_FALSE;
-
- status = QPS_NOTINITIALISED;
-
- #ifdef PC_DEBUG
- printlevel = PL_MEDIUM;
- setPrintLevel( PL_MEDIUM );
- #else
- printlevel = QPOASES_PRINTLEVEL;
- #endif
-
- count = 0;
-}
-
-
-/*
- * Q P r o b l e m B
- */
-QProblemB::QProblemB( const QProblemB& rhs )
-{
- int i, j;
-
- int _nV = rhs.bounds.getNV( );
-
- for( i=0; i<_nV; ++i )
- for( j=0; j<_nV; ++j )
- H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
-
- hasHessian = rhs.hasHessian;
-
- for( i=0; i<_nV; ++i )
- g[i] = rhs.g[i];
-
- for( i=0; i<_nV; ++i )
- lb[i] = rhs.lb[i];
-
- for( i=0; i<_nV; ++i )
- ub[i] = rhs.ub[i];
-
-
- bounds = rhs.bounds;
-
- for( i=0; i<_nV; ++i )
- for( j=0; j<_nV; ++j )
- R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
- hasCholesky = rhs.hasCholesky;
-
- for( i=0; i<_nV; ++i )
- x[i] = rhs.x[i];
-
- for( i=0; i<_nV; ++i )
- y[i] = rhs.y[i];
-
- tau = rhs.tau;
-
- hessianType = rhs.hessianType;
- infeasible = rhs.infeasible;
- unbounded = rhs.unbounded;
-
- status = rhs.status;
-
- printlevel = rhs.printlevel;
-
- count = rhs.count;
-}
-
-
-/*
- * ~ Q P r o b l e m B
- */
-QProblemB::~QProblemB( )
-{
-}
-
-
-/*
- * o p e r a t o r =
- */
-QProblemB& QProblemB::operator=( const QProblemB& rhs )
-{
- int i, j;
-
- if ( this != &rhs )
- {
- int _nV = rhs.bounds.getNV( );
-
- for( i=0; i<_nV; ++i )
- for( j=0; j<_nV; ++j )
- H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
-
- hasHessian = rhs.hasHessian;
-
- for( i=0; i<_nV; ++i )
- g[i] = rhs.g[i];
-
- for( i=0; i<_nV; ++i )
- lb[i] = rhs.lb[i];
-
- for( i=0; i<_nV; ++i )
- ub[i] = rhs.ub[i];
-
- bounds = rhs.bounds;
-
- for( i=0; i<_nV; ++i )
- for( j=0; j<_nV; ++j )
- R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
- hasCholesky = rhs.hasCholesky;
-
-
- for( i=0; i<_nV; ++i )
- x[i] = rhs.x[i];
-
- for( i=0; i<_nV; ++i )
- y[i] = rhs.y[i];
-
- tau = rhs.tau;
-
- hessianType = rhs.hessianType;
- infeasible = rhs.infeasible;
- unbounded = rhs.unbounded;
-
- status = rhs.status;
-
- printlevel = rhs.printlevel;
- setPrintLevel( rhs.printlevel );
-
- count = rhs.count;
- }
-
- return *this;
-}
-
-
-/*
- * r e s e t
- */
-returnValue QProblemB::reset( )
-{
- int i, j;
- int nV = getNV( );
-
- /** 0) Reset has Hessian flag. */
- hasHessian = BT_FALSE;
-
- /* 1) Reset bounds. */
- bounds.init( nV );
-
- /* 2) Reset Cholesky decomposition. */
- for( i=0; ithrowInfo( RET_ITERATION_STARTED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- #endif
- }
-
- /* 1) Setup index arrays. */
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_HOTSTART_FAILED );
-
- /* 2) Initialize shift direction of the gradient and the bounds. */
- returnvalue = hotstart_determineDataShift( FX_idx,
- g_new,lb_new,ub_new,
- delta_g,delta_lb,delta_ub,
- Delta_bB_isZero
- );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
- THROWERROR( RET_SHIFT_DETERMINATION_FAILED );
- return returnvalue;
- }
-
- /* 3) Determination of step direction of X and Y. */
- returnvalue = hotstart_determineStepDirection( FR_idx,FX_idx,
- delta_g,delta_lb,delta_ub,
- Delta_bB_isZero,
- delta_xFX,delta_xFR,delta_yFX
- );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
- THROWERROR( RET_STEPDIRECTION_DETERMINATION_FAILED );
- return returnvalue;
- }
-
-
- /* 4) Determination of step length TAU. */
- returnvalue = hotstart_determineStepLength( FR_idx,FX_idx,
- delta_lb,delta_ub,
- delta_xFR,delta_yFX,
- BC_idx,BC_status );
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
- THROWERROR( RET_STEPLENGTH_DETERMINATION_FAILED );
- return returnvalue;
- }
-
- /* 5) Realization of the homotopy step. */
- returnvalue = hotstart_performStep( FR_idx,FX_idx,
- delta_g,delta_lb,delta_ub,
- delta_xFX,delta_xFR,delta_yFX,
- BC_idx,BC_status
- );
-
-
- if ( returnvalue != SUCCESSFUL_RETURN )
- {
- nWSR = l;
-
- /* stop runtime measurement */
- if ( cputime != 0 )
- *cputime = getCPUtime( ) - starttime;
-
- /* optimal solution found? */
- if ( returnvalue == RET_OPTIMAL_SOLUTION_FOUND )
- {
- status = QPS_SOLVED;
-
- if ( printlevel == PL_HIGH )
- THROWINFO( RET_OPTIMAL_SOLUTION_FOUND );
-
- #ifdef PC_DEBUG
- if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
- THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
- #endif
-
- /* check KKT optimality conditions */
- return checkKKTconditions( );
- }
- else
- {
- /* checks for infeasibility... */
- if ( infeasible == BT_TRUE )
- {
- status = QPS_HOMOTOPYQPSOLVED;
- return THROWERROR( RET_HOTSTART_STOPPED_INFEASIBILITY );
- }
-
- /* ...unboundedness... */
- if ( unbounded == BT_TRUE ) /* not necessary since objective function convex! */
- return THROWERROR( RET_HOTSTART_STOPPED_UNBOUNDEDNESS );
-
- /* ... and throw unspecific error otherwise */
- THROWERROR( RET_HOMOTOPY_STEP_FAILED );
- return returnvalue;
- }
- }
-
- /* 6) Output information of successful QP iteration. */
- status = QPS_HOMOTOPYQPSOLVED;
-
- #ifdef PC_DEBUG
- if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
- THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
- #endif
- }
-
-
- /* stop runtime measurement */
- if ( cputime != 0 )
- *cputime = getCPUtime( ) - starttime;
-
-
- /* if programm gets to here, output information that QP could not be solved
- * within the given maximum numbers of working set changes */
- if ( printlevel == PL_HIGH )
- {
- #ifdef PC_DEBUG
- sprintf( messageString,"(nWSR = %d)",nWSR );
- return getGlobalMessageHandler( )->throwWarning( RET_MAX_NWSR_REACHED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- #endif
- }
-
- /* Finally check KKT optimality conditions. */
- returnValue returnvalueKKTcheck = checkKKTconditions( );
-
- if ( returnvalueKKTcheck != SUCCESSFUL_RETURN )
- return returnvalueKKTcheck;
- else
- return RET_MAX_NWSR_REACHED;
-}
-
-
-/*
- * g e t N Z
- */
-int QProblemB::getNZ( )
-{
- /* if no constraints are present: nZ=nFR */
- return bounds.getFree( )->getLength( );
-}
-
-
-/*
- * g e t O b j V a l
- */
-real_t QProblemB::getObjVal( ) const
-{
- real_t objVal;
-
- /* calculated optimal objective function value
- * only if current QP has been solved */
- if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
- ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
- ( getStatus( ) == QPS_SOLVED ) )
- {
- objVal = getObjVal( x );
- }
- else
- {
- objVal = INFTY;
- }
-
- return objVal;
-}
-
-
-/*
- * g e t O b j V a l
- */
-real_t QProblemB::getObjVal( const real_t* const _x ) const
-{
- int i, j;
- int nV = getNV( );
-
- real_t obj_tmp = 0.0;
-
- for( i=0; i= PL_MEDIUM ) && ( printlevel != _printlevel ) )
- THROWINFO( RET_PRINTLEVEL_CHANGED );
- #endif
-
- printlevel = _printlevel;
-
- /* update message handler preferences */
- switch ( printlevel )
- {
- case PL_NONE:
- getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_HIDDEN );
- getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_HIDDEN );
- getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_HIDDEN );
- break;
-
- case PL_LOW:
- getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_VISIBLE );
- getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_HIDDEN );
- getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_HIDDEN );
- break;
-
- default: /* PL_MEDIUM, PL_HIGH */
- getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_VISIBLE );
- getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_VISIBLE );
- getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_VISIBLE );
- break;
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*****************************************************************************
- * P R O T E C T E D *
- *****************************************************************************/
-
-/*
- * c h e c k F o r I d e n t i t y H e s s i a n
- */
-returnValue QProblemB::checkForIdentityHessian( )
-{
- int i, j;
- int nV = getNV( );
-
- /* nothing to do as status flag remains unaltered
- * if Hessian differs from identity matrix */
- if ( hessianType == HST_IDENTITY )
- return SUCCESSFUL_RETURN;
-
- /* 1) If Hessian differs from identity matrix,
- * return without changing the internal HessianType. */
- for ( i=0; i EPS )
- return SUCCESSFUL_RETURN;
-
- for ( i=0; i EPS ) || ( getAbs( H[j*NVMAX + i] ) > EPS ) )
- return SUCCESSFUL_RETURN;
- }
-
- /* 2) If this point is reached, Hessian equals the idetity matrix. */
- hessianType = HST_IDENTITY;
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t u p S u b j e c t T o T y p e
- */
-returnValue QProblemB::setupSubjectToType( )
-{
- int i;
- int nV = getNV( );
-
-
- /* 1) Check if lower bounds are present. */
- bounds.setNoLower( BT_TRUE );
- for( i=0; i -INFTY )
- {
- bounds.setNoLower( BT_FALSE );
- break;
- }
-
- /* 2) Check if upper bounds are present. */
- bounds.setNoUpper( BT_TRUE );
- for( i=0; i INFTY - BOUNDTOL ) )
- {
- bounds.setType( i,ST_UNBOUNDED );
- ++nUV;
- }
- else
- {
- if ( lb[i] > ub[i] - BOUNDTOL )
- {
- bounds.setType( i,ST_EQUALITY );
- ++nFV;
- }
- else
- {
- bounds.setType( i,ST_BOUNDED );
- }
- }
-
- /* 4) Set dimensions of bounds structure. */
- bounds.setNFV( nFV );
- bounds.setNUV( nUV );
- bounds.setNBV( nV - nFV - nUV );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * c h o l e s k y D e c o m p o s i t i o n
- */
-returnValue QProblemB::setupCholeskyDecomposition( )
-{
- int i, j, k, ii, jj;
- int nV = getNV( );
- int nFR = getNFR( );
-
- /* If Hessian flag is false, it means that H & R already contain Cholesky
- * factorization -- provided from outside. */
- if (hasHessian == BT_FALSE)
- return SUCCESSFUL_RETURN;
-
- /* 1) Initialises R with all zeros. */
- for( i=0; i 0 )
- {
- int FR_idx[NVMAX];
- if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INDEXLIST_CORRUPTED );
-
- /* R'*R = H */
- real_t sum;
- real_t inv;
-
- for( i=0; i=0; --k )
- sum -= R[k*NVMAX + i] * R[k*NVMAX + i];
-
- if ( sum > 0.0 )
- {
- R[i*NVMAX + i] = sqrt( sum );
- inv = 1.0 / R[i*NVMAX + i];
- }
- else
- {
- hessianType = HST_SEMIDEF;
- return THROWERROR( RET_HESSIAN_NOT_SPD );
- }
-
- /* j > i */
- for( j=(i+1); j=0; --k )
- sum -= R[k*NVMAX + i] * R[k*NVMAX + j];
-
- R[i*NVMAX + j] = sum * inv;
- }
- }
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s o l v e I n i t i a l Q P
- */
-returnValue QProblemB::solveInitialQP( const real_t* const xOpt, const real_t* const yOpt,
- const Bounds* const guessedBounds,
- int& nWSR, real_t* const cputime
- )
-{
- int i, nFR;
- int nV = getNV( );
-
-
- /* start runtime measurement */
- real_t starttime = 0.0;
- if ( cputime != 0 )
- starttime = getCPUtime( );
-
-
- status = QPS_NOTINITIALISED;
-
- /* I) ANALYSE QP DATA: */
- /* 1) Check if Hessian happens to be the identity matrix. */
- if ( checkForIdentityHessian( ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INIT_FAILED );
-
- /* 2) Setup type of bounds (i.e. unbounded, implicitly fixed etc.). */
- if ( setupSubjectToType( ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INIT_FAILED );
-
- status = QPS_PREPARINGAUXILIARYQP;
-
-
- /* II) SETUP AUXILIARY QP WITH GIVEN OPTIMAL SOLUTION: */
- /* 1) Setup bounds data structure. */
- if ( bounds.setupAllFree( ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INIT_FAILED );
-
- /* 2) Setup optimal primal/dual solution for auxiliary QP. */
- if ( setupAuxiliaryQPsolution( xOpt,yOpt ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INIT_FAILED );
-
- /* 3) Obtain linear independent working set for auxiliary QP. */
-
- static Bounds auxiliaryBounds;
-
- auxiliaryBounds.init( nV );
-
- if ( obtainAuxiliaryWorkingSet( xOpt,yOpt,guessedBounds, &auxiliaryBounds ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INIT_FAILED );
-
- /* 4) Setup working set of auxiliary QP and setup cholesky decomposition. */
- if ( setupAuxiliaryWorkingSet( &auxiliaryBounds,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_INIT_FAILED );
-
- nFR = getNFR();
- /* At the moment we can only provide a Cholesky of the Hessian if
- * the solver is cold-started. */
- if (hasCholesky == BT_FALSE || nFR != nV)
- if (setupCholeskyDecomposition() != SUCCESSFUL_RETURN)
- return THROWERROR( RET_INIT_FAILED_CHOLESKY );
-
- /* 5) Store original QP formulation... */
- real_t g_original[NVMAX];
- real_t lb_original[NVMAX];
- real_t ub_original[NVMAX];
-
- for( i=0; isetupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryBounds->setupBound( i,guessedBounds->getStatus( i ) ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
- else /* No initial working set specified. */
- {
- if ( ( xOpt != 0 ) && ( yOpt == 0 ) )
- {
- /* Obtain initial working set by "clipping". */
- for( i=0; isetupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- if ( xOpt[i] >= ub[i] - BOUNDTOL )
- {
- if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- /* Moreover, add all implictly fixed variables if specified. */
- if ( bounds.getType( i ) == ST_EQUALITY )
- {
- if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
-
- if ( ( xOpt == 0 ) && ( yOpt != 0 ) )
- {
- /* Obtain initial working set in accordance to sign of dual solution vector. */
- for( i=0; i ZERO )
- {
- if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- if ( yOpt[i] < -ZERO )
- {
- if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- continue;
- }
-
- /* Moreover, add all implictly fixed variables if specified. */
- if ( bounds.getType( i ) == ST_EQUALITY )
- {
- if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
-
- /* If xOpt and yOpt are null pointer and no initial working is specified,
- * start with empty working set (or implicitly fixed bounds only)
- * for auxiliary QP. */
- if ( ( xOpt == 0 ) && ( yOpt == 0 ) )
- {
- for( i=0; isetupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- else
- {
- if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
- }
- }
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t u p A u x i l i a r y W o r k i n g S e t
- */
-returnValue QProblemB::setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds,
- BooleanType setupAfresh
- )
-{
- int i;
- int nV = getNV( );
-
- /* consistency checks */
- if ( auxiliaryBounds != 0 )
- {
- for( i=0; igetStatus( i ) == ST_UNDEFINED ) )
- return THROWERROR( RET_UNKNOWN_BUG );
- }
- else
- {
- return THROWERROR( RET_INVALID_ARGUMENTS );
- }
-
-
- /* I) SETUP CHOLESKY FLAG:
- * Cholesky decomposition shall only be updated if working set
- * shall be updated (i.e. NOT setup afresh!) */
- BooleanType updateCholesky;
- if ( setupAfresh == BT_TRUE )
- updateCholesky = BT_FALSE;
- else
- updateCholesky = BT_TRUE;
-
-
- /* II) REMOVE FORMERLY ACTIVE BOUNDS (IF NECESSARY): */
- if ( setupAfresh == BT_FALSE )
- {
- /* Remove all active bounds that shall be inactive AND
- * all active bounds that are active at the wrong bound. */
- for( i=0; igetStatus( i ) != ST_LOWER ) )
- if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
-
- if ( ( bounds.getStatus( i ) == ST_UPPER ) && ( auxiliaryBounds->getStatus( i ) != ST_UPPER ) )
- if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
- }
- }
-
-
- /* III) ADD NEWLY ACTIVE BOUNDS: */
- /* Add all inactive bounds that shall be active AND
- * all formerly active bounds that have been active at the wrong bound. */
- for( i=0; igetStatus( i ) != ST_INACTIVE ) )
- {
- if ( addBound( i,auxiliaryBounds->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s e t u p A u x i l i a r y Q P s o l u t i o n
- */
-returnValue QProblemB::setupAuxiliaryQPsolution( const real_t* const xOpt, const real_t* const yOpt
- )
-{
- int i;
- int nV = getNV( );
-
-
- /* Setup primal/dual solution vectors for auxiliary initial QP:
- * if a null pointer is passed, a zero vector is assigned;
- * old solution vector is kept if pointer to internal solution vector is passed. */
- if ( xOpt != 0 )
- {
- if ( xOpt != x )
- for( i=0; igetIndex( number );
-
- real_t c, s;
-
- /* 2) Use row-wise Givens rotations to restore upper triangular form of R. */
- for( i=number_idx+1; ith column and ... */
- for( i=0; igetNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVEBOUND_FAILED );
-
- /* 1) Calculate new column of cholesky decomposition. */
- real_t rhs[NVMAX];
- real_t r[NVMAX];
- real_t r0 = H[number*NVMAX + number];
-
- for( i=0; i 0.0 )
- R[nFR*NVMAX + nFR] = sqrt( r0 );
- else
- {
- hessianType = HST_SEMIDEF;
- return THROWERROR( RET_HESSIAN_NOT_SPD );
- }
-
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * b a c k s o l v e R (CODE DUPLICATED IN QProblem CLASS!!!)
- */
-returnValue QProblemB::backsolveR( const real_t* const b, BooleanType transposed,
- real_t* const a
- )
-{
- /* Call standard backsolve procedure (i.e. removingBound == BT_FALSE). */
- return backsolveR( b,transposed,BT_FALSE,a );
-}
-
-
-/*
- * b a c k s o l v e R (CODE DUPLICATED IN QProblem CLASS!!!)
- */
-returnValue QProblemB::backsolveR( const real_t* const b, BooleanType transposed,
- BooleanType removingBound,
- real_t* const a
- )
-{
- int i, j;
- int nR = getNZ( );
-
- real_t sum;
-
- /* if backsolve is called while removing a bound, reduce nZ by one. */
- if ( removingBound == BT_TRUE )
- --nR;
-
- /* nothing to do */
- if ( nR <= 0 )
- return SUCCESSFUL_RETURN;
-
-
- /* Solve Ra = b, where R might be transposed. */
- if ( transposed == BT_FALSE )
- {
- /* solve Ra = b */
- for( i=(nR-1); i>=0; --i )
- {
- sum = b[i];
- for( j=(i+1); j ZERO )
- a[i] = sum / R[i*NVMAX + i];
- else
- return THROWERROR( RET_DIV_BY_ZERO );
- }
- }
- else
- {
- /* solve R^T*a = b */
- for( i=0; i ZERO )
- a[i] = sum / R[i*NVMAX + i];
- else
- return THROWERROR( RET_DIV_BY_ZERO );
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * h o t s t a r t _ d e t e r m i n e D a t a S h i f t
- */
-returnValue QProblemB::hotstart_determineDataShift( const int* const FX_idx,
- const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
- real_t* const delta_g, real_t* const delta_lb, real_t* const delta_ub,
- BooleanType& Delta_bB_isZero
- )
-{
- int i, ii;
- int nV = getNV( );
- int nFX = getNFX( );
-
-
- /* 1) Calculate shift directions. */
- for( i=0; i EPS ) || ( getAbs( delta_ub[ii] ) > EPS ) )
- {
- Delta_bB_isZero = BT_FALSE;
- break;
- }
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * a r e B o u n d s C o n s i s t e n t
- */
-BooleanType QProblemB::areBoundsConsistent( const real_t* const delta_lb, const real_t* const delta_ub
- ) const
-{
- int i;
-
- /* Check if delta_lb[i] is greater than delta_ub[i]
- * for a component i whose bounds are already (numerically) equal. */
- for( i=0; i ub[i] - BOUNDTOL ) && ( delta_lb[i] > delta_ub[i] + EPS ) )
- return BT_FALSE;
-
- return BT_TRUE;
-}
-
-
-/*
- * s e t u p Q P d a t a
- */
-returnValue QProblemB::setupQPdata( const real_t* const _H, const real_t* const _R, const real_t* const _g,
- const real_t* const _lb, const real_t* const _ub
- )
-{
- int i, j;
- int nV = getNV( );
-
- /* 1) Setup Hessian matrix and it's Cholesky factorization. */
- if (_H != 0)
- {
- for( i=0; i 0 )
- {
- for( i=0; i 0 )
- {
- /* auxiliary variables */
- real_t delta_xFRz_TMP[NVMAX];
- real_t delta_xFRz_RHS[NVMAX];
-
- /* Determine delta_xFRz. */
- if ( Delta_bB_isZero == BT_FALSE )
- {
- for( i=0; i 0 )
- {
- for( i=0; i= 0.0 ) )
- {
- tau_tmp = y[ii] / ( -delta_yFX[i] );
- if ( tau_tmp < tau_new )
- {
- if ( tau_tmp >= 0.0 )
- {
- tau_new = tau_tmp;
- BC_idx = ii;
- BC_status = ST_INACTIVE;
- }
- }
- }
- }
- else
- {
- /* 2) Active upper bounds. */
- if ( ( delta_yFX[i] > ZERO ) && ( y[ii] <= 0.0 ) )
- {
- tau_tmp = y[ii] / ( -delta_yFX[i] );
- if ( tau_tmp < tau_new )
- {
- if ( tau_tmp >= 0.0 )
- {
- tau_new = tau_tmp;
- BC_idx = ii;
- BC_status = ST_INACTIVE;
- }
- }
- }
- }
- }
- }
-
-
- /* II) DETERMINE MAXIMUM PRIMAL STEPLENGTH, i.e. ensure that
- * inactive bounds remain valid (ignoring unbounded variables). */
- /* 1) Inactive lower bounds. */
- if ( bounds.isNoLower( ) == BT_FALSE )
- {
- for( i=0; i delta_xFR[i] )
- {
- if ( x[ii] > lb[ii] )
- tau_tmp = ( x[ii] - lb[ii] ) / ( delta_lb[ii] - delta_xFR[i] );
- else
- tau_tmp = 0.0;
-
- if ( tau_tmp < tau_new )
- {
- if ( tau_tmp >= 0.0 )
- {
- tau_new = tau_tmp;
- BC_idx = ii;
- BC_status = ST_LOWER;
- }
- }
- }
- }
- }
- }
-
- /* 2) Inactive upper bounds. */
- if ( bounds.isNoUpper( ) == BT_FALSE )
- {
- for( i=0; i= 0.0 )
- {
- tau_new = tau_tmp;
- BC_idx = ii;
- BC_status = ST_UPPER;
- }
- }
- }
- }
- }
- }
-
-
- /* III) SET MAXIMUM HOMOTOPY STEPLENGTH */
- tau = tau_new;
-
- if ( printlevel == PL_HIGH )
- {
- #ifdef PC_DEBUG
- char messageString[80];
-
- if ( BC_status == ST_UNDEFINED )
- sprintf( messageString,"Stepsize is %.6e!",tau );
- else
- sprintf( messageString,"Stepsize is %.6e! (BC_idx = %d, BC_status = %d)",tau,BC_idx,BC_status );
-
- getGlobalMessageHandler( )->throwInfo( RET_STEPSIZE_NONPOSITIVE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- #endif
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * h o t s t a r t _ p e r f o r m S t e p
- */
-returnValue QProblemB::hotstart_performStep( const int* const FR_idx, const int* const FX_idx,
- const real_t* const delta_g, const real_t* const delta_lb, const real_t* const delta_ub,
- const real_t* const delta_xFX, const real_t* const delta_xFR,
- const real_t* const delta_yFX,
- int BC_idx, SubjectToStatus BC_status
- )
-{
- int i, ii;
- int nV = getNV( );
- int nFR = getNFR( );
- int nFX = getNFX( );
-
-
- /* I) CHECK BOUNDS' CONSISTENCY */
- if ( areBoundsConsistent( delta_lb,delta_ub ) == BT_FALSE )
- {
- infeasible = BT_TRUE;
- tau = 0.0;
-
- return THROWERROR( RET_QP_INFEASIBLE );
- }
-
-
- /* II) GO TO ACTIVE SET CHANGE */
- if ( tau > ZERO )
- {
- /* 1) Perform step in primal und dual space. */
- for( i=0; ithrowWarning( RET_STEPSIZE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- #endif
- }
-
-
- /* setup output preferences */
- #ifdef PC_DEBUG
- char messageString[80];
- VisibilityStatus visibilityStatus;
-
- if ( printlevel == PL_HIGH )
- visibilityStatus = VS_VISIBLE;
- else
- visibilityStatus = VS_HIDDEN;
- #endif
-
-
- /* III) UPDATE ACTIVE SET */
- switch ( BC_status )
- {
- /* Optimal solution found as no working set change detected. */
- case ST_UNDEFINED:
- return RET_OPTIMAL_SOLUTION_FOUND;
-
-
- /* Remove one variable from active set. */
- case ST_INACTIVE:
- #ifdef PC_DEBUG
- sprintf( messageString,"bound no. %d.", BC_idx );
- getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( removeBound( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
-
- y[BC_idx] = 0.0;
- break;
-
-
- /* Add one variable to active set. */
- default:
- #ifdef PC_DEBUG
- if ( BC_status == ST_LOWER )
- sprintf( messageString,"lower bound no. %d.", BC_idx );
- else
- sprintf( messageString,"upper bound no. %d.", BC_idx );
- getGlobalMessageHandler( )->throwInfo( RET_ADD_TO_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
- #endif
-
- if ( addBound( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_ADD_TO_ACTIVESET_FAILED );
- break;
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-
-#ifdef PC_DEBUG /* Define print functions only for debugging! */
-
-/*
- * p r i n t I t e r a t i o n
- */
-returnValue QProblemB::printIteration( int iteration,
- int BC_idx, SubjectToStatus BC_status
- )
-{
- char myPrintfString[160];
-
- /* consistency check */
- if ( iteration < 0 )
- return THROWERROR( RET_INVALID_ARGUMENTS );
-
- /* nothing to do */
- if ( printlevel != PL_MEDIUM )
- return SUCCESSFUL_RETURN;
-
-
- /* 1) Print header at first iteration. */
- if ( iteration == 0 )
- {
- sprintf( myPrintfString,"\n############## qpOASES -- QP NO.%4.1d ###############\n", count );
- myPrintf( myPrintfString );
-
- sprintf( myPrintfString," Iter | StepLength | Info | nFX \n" );
- myPrintf( myPrintfString );
- }
-
- /* 2) Print iteration line. */
- if ( BC_status == ST_UNDEFINED )
- {
- sprintf( myPrintfString," %4.1d | %1.5e | QP SOLVED | %4.1d \n", iteration,tau,getNFX( ) );
- myPrintf( myPrintfString );
- }
- else
- {
- char info[8];
-
- if ( BC_status == ST_INACTIVE )
- sprintf( info,"REM BND" );
- else
- sprintf( info,"ADD BND" );
-
- sprintf( myPrintfString," %4.1d | %1.5e | %s%4.1d | %4.1d \n", iteration,tau,info,BC_idx,getNFX( ) );
- myPrintf( myPrintfString );
- }
-
- return SUCCESSFUL_RETURN;
-}
-
-#endif /* PC_DEBUG */
-
-
-
-/*
- * c h e c k K K T c o n d i t i o n s
- */
-returnValue QProblemB::checkKKTconditions( )
-{
- #ifdef __PERFORM_KKT_TEST__
-
- int i, j;
- int nV = getNV( );
-
- real_t tmp;
- real_t maxKKTviolation = 0.0;
-
-
- /* 1) Check for Hx + g - y*A' = 0 (here: A = Id). */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = getAbs( tmp );
- }
-
- /* 2) Check for lb <= x <= ub. */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = lb[i] - x[i];
-
- if ( x[i] - ub[i] > maxKKTviolation )
- maxKKTviolation = x[i] - ub[i];
- }
-
- /* 3) Check for correct sign of y and for complementary slackness. */
- for( i=0; i maxKKTviolation )
- maxKKTviolation = -y[i];
- if ( getAbs( ( x[i] - lb[i] ) * y[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( ( x[i] - lb[i] ) * y[i] );
- break;
-
- case ST_UPPER:
- if ( y[i] > maxKKTviolation )
- maxKKTviolation = y[i];
- if ( getAbs( ( ub[i] - x[i] ) * y[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( ( ub[i] - x[i] ) * y[i] );
- break;
-
- default: /* inactive */
- if ( getAbs( y[i] ) > maxKKTviolation )
- maxKKTviolation = getAbs( y[i] );
- break;
- }
- }
-
- if ( maxKKTviolation > CRITICALACCURACY )
- return RET_NO_SOLUTION;
-
- if ( maxKKTviolation > DESIREDACCURACY )
- return RET_INACCURATE_SOLUTION;
-
- #endif /* __PERFORM_KKT_TEST__ */
-
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/QProblemB.ipp b/phonelibs/qpoases/SRC/QProblemB.ipp
deleted file mode 100644
index 0b031301e..000000000
--- a/phonelibs/qpoases/SRC/QProblemB.ipp
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/QProblemB.ipp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of inlined member functions of the QProblemB class which
- * is able to use the newly developed online active set strategy for
- * parametric quadratic programming.
- */
-
-
-
-#include
-
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-/*
- * g e t H
- */
-inline returnValue QProblemB::getH( real_t* const _H ) const
-{
- int i;
-
- for ( i=0; i= 0 ) && ( number < getNV( ) ) )
- {
- value = lb[number];
- return SUCCESSFUL_RETURN;
- }
- else
- {
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
- }
-}
-
-
-/*
- * g e t U B
- */
-inline returnValue QProblemB::getUB( real_t* const _ub ) const
-{
- int i;
-
- for ( i=0; i= 0 ) && ( number < getNV( ) ) )
- {
- value = ub[number];
- return SUCCESSFUL_RETURN;
- }
- else
- {
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
- }
-}
-
-
-/*
- * g e t B o u n d s
- */
-inline returnValue QProblemB::getBounds( Bounds* const _bounds ) const
-{
- *_bounds = bounds;
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * g e t N V
- */
-inline int QProblemB::getNV( ) const
-{
- return bounds.getNV( );
-}
-
-
-/*
- * g e t N F R
- */
-inline int QProblemB::getNFR( )
-{
- return bounds.getNFR( );
-}
-
-
-/*
- * g e t N F X
- */
-inline int QProblemB::getNFX( )
-{
- return bounds.getNFX( );
-}
-
-
-/*
- * g e t N F V
- */
-inline int QProblemB::getNFV( ) const
-{
- return bounds.getNFV( );
-}
-
-
-/*
- * g e t S t a t u s
- */
-inline QProblemStatus QProblemB::getStatus( ) const
-{
- return status;
-}
-
-
-/*
- * i s I n i t i a l i s e d
- */
-inline BooleanType QProblemB::isInitialised( ) const
-{
- if ( status == QPS_NOTINITIALISED )
- return BT_FALSE;
- else
- return BT_TRUE;
-}
-
-
-/*
- * i s S o l v e d
- */
-inline BooleanType QProblemB::isSolved( ) const
-{
- if ( status == QPS_SOLVED )
- return BT_TRUE;
- else
- return BT_FALSE;
-}
-
-
-/*
- * i s I n f e a s i b l e
- */
-inline BooleanType QProblemB::isInfeasible( ) const
-{
- return infeasible;
-}
-
-
-/*
- * i s U n b o u n d e d
- */
-inline BooleanType QProblemB::isUnbounded( ) const
-{
- return unbounded;
-}
-
-
-/*
- * g e t P r i n t L e v e l
- */
-inline PrintLevel QProblemB::getPrintLevel( ) const
-{
- return printlevel;
-}
-
-
-/*
- * g e t H e s s i a n T y p e
- */
-inline HessianType QProblemB::getHessianType( ) const
-{
- return hessianType;
-}
-
-
-/*
- * s e t H e s s i a n T y p e
- */
-inline returnValue QProblemB::setHessianType( HessianType _hessianType )
-{
- hessianType = _hessianType;
- return SUCCESSFUL_RETURN;
-}
-
-
-
-/*****************************************************************************
- * P R O T E C T E D *
- *****************************************************************************/
-
-/*
- * s e t H
- */
-inline returnValue QProblemB::setH( const real_t* const H_new )
-{
- int i, j;
-
- int nV = getNV();
-
- for( i=0; i= 0 ) && ( number < getNV( ) ) )
- {
- lb[number] = value;
- return SUCCESSFUL_RETURN;
- }
- else
- {
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
- }
-}
-
-
-/*
- * s e t U B
- */
-inline returnValue QProblemB::setUB( const real_t* const ub_new )
-{
- int i;
-
- int nV = getNV();
-
- for( i=0; i= 0 ) && ( number < getNV( ) ) )
- {
- ub[number] = value;
-
- return SUCCESSFUL_RETURN;
- }
- else
- {
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
- }
-}
-
-
-/*
- * c o m p u t e G i v e n s
- */
-inline void QProblemB::computeGivens( real_t xold, real_t yold, real_t& xnew, real_t& ynew,
- real_t& c, real_t& s
- ) const
-{
- if ( getAbs( yold ) <= ZERO )
- {
- c = 1.0;
- s = 0.0;
-
- xnew = xold;
- ynew = yold;
- }
- else
- {
- real_t t, mu;
-
- mu = getAbs( xold );
- if ( getAbs( yold ) > mu )
- mu = getAbs( yold );
-
- t = mu * sqrt( (xold/mu)*(xold/mu) + (yold/mu)*(yold/mu) );
-
- if ( xold < 0.0 )
- t = -t;
-
- c = xold/t;
- s = yold/t;
- xnew = t;
- ynew = 0.0;
- }
-
- return;
-}
-
-
-/*
- * a p p l y G i v e n s
- */
-inline void QProblemB::applyGivens( real_t c, real_t s, real_t xold, real_t yold,
- real_t& xnew, real_t& ynew
- ) const
-{
- /* Usual Givens plane rotation requiring four multiplications. */
- xnew = c*xold + s*yold;
- ynew = -s*xold + c*yold;
-// double nu = s/(1.0+c);
-//
-// xnew = xold*c + yold*s;
-// ynew = (xnew+xold)*nu - yold;
-
- return;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/SubjectTo.cpp b/phonelibs/qpoases/SRC/SubjectTo.cpp
deleted file mode 100644
index 371f0d76d..000000000
--- a/phonelibs/qpoases/SRC/SubjectTo.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/SubjectTo.cpp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the SubjectTo class designed to manage working sets of
- * constraints and bounds within a QProblem.
- */
-
-
-#include
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * S u b j e c t T o
- */
-SubjectTo::SubjectTo( ) : noLower( BT_TRUE ),
- noUpper( BT_TRUE ),
- size( 0 )
-{
- int i;
-
- for( i=0; iaddNumber( newnumber ) == RET_INDEXLIST_EXCEEDS_MAX_LENGTH )
- return THROWERROR( RET_ADDINDEX_FAILED );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * r e m o v e I n d e x
- */
-returnValue SubjectTo::removeIndex( Indexlist* const indexlist,
- int removenumber
- )
-{
- status[removenumber] = ST_UNDEFINED;
-
- if ( indexlist->removeNumber( removenumber ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_UNKNOWN_BUG );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * s w a p I n d e x
- */
-returnValue SubjectTo::swapIndex( Indexlist* const indexlist,
- int number1, int number2
- )
-{
- /* consistency checks */
- if ( status[number1] != status[number2] )
- return THROWERROR( RET_SWAPINDEX_FAILED );
-
- if ( number1 == number2 )
- {
- THROWWARNING( RET_NOTHING_TO_DO );
- return SUCCESSFUL_RETURN;
- }
-
- if ( indexlist->swapNumbers( number1,number2 ) != SUCCESSFUL_RETURN )
- return THROWERROR( RET_SWAPINDEX_FAILED );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/SubjectTo.ipp b/phonelibs/qpoases/SRC/SubjectTo.ipp
deleted file mode 100644
index 32215ba7e..000000000
--- a/phonelibs/qpoases/SRC/SubjectTo.ipp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/SubjectTo.ipp
- * \author Hans Joachim Ferreau
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of the inlined member functions of the SubjectTo class
- * designed to manage working sets of constraints and bounds within a QProblem.
- */
-
-
-/*****************************************************************************
- * P U B L I C *
- *****************************************************************************/
-
-
-/*
- * g e t T y p e
- */
-inline SubjectToType SubjectTo::getType( int i ) const
-{
- if ( ( i >= 0 ) && ( i < size ) )
- return type[i];
- else
- return ST_UNKNOWN;
-}
-
-
-/*
- * g e t S t a t u s
- */
-inline SubjectToStatus SubjectTo::getStatus( int i ) const
-{
- if ( ( i >= 0 ) && ( i < size ) )
- return status[i];
- else
- return ST_UNDEFINED;
-}
-
-
-/*
- * s e t T y p e
- */
-inline returnValue SubjectTo::setType( int i, SubjectToType value )
-{
- if ( ( i >= 0 ) && ( i < size ) )
- {
- type[i] = value;
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-}
-
-
-/*
- * s e t S t a t u s
- */
-inline returnValue SubjectTo::setStatus( int i, SubjectToStatus value )
-{
- if ( ( i >= 0 ) && ( i < size ) )
- {
- status[i] = value;
- return SUCCESSFUL_RETURN;
- }
- else
- return THROWERROR( RET_INDEX_OUT_OF_BOUNDS );
-}
-
-
-/*
- * s e t N o L o w e r
- */
-inline void SubjectTo::setNoLower( BooleanType _status )
-{
- noLower = _status;
-}
-
-
-/*
- * s e t N o U p p e r
- */
-inline void SubjectTo::setNoUpper( BooleanType _status )
-{
- noUpper = _status;
-}
-
-
-/*
- * i s N o L o w e r
- */
-inline BooleanType SubjectTo::isNoLower( ) const
-{
- return noLower;
-}
-
-
-/*
- * i s N o L o w e r
- */
-inline BooleanType SubjectTo::isNoUpper( ) const
-{
- return noUpper;
-}
-
-
-/*
- * end of file
- */
diff --git a/phonelibs/qpoases/SRC/Utils.cpp b/phonelibs/qpoases/SRC/Utils.cpp
deleted file mode 100644
index c11722c47..000000000
--- a/phonelibs/qpoases/SRC/Utils.cpp
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * This file is part of qpOASES.
- *
- * qpOASES -- An Implementation of the Online Active Set Strategy.
- * Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
- *
- * qpOASES is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * qpOASES 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with qpOASES; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-
-/**
- * \file SRC/Utils.cpp
- * \author Hans Joachim Ferreau, Eckhard Arnold
- * \version 1.3embedded
- * \date 2007-2008
- *
- * Implementation of some inlined utilities for working with the different QProblem
- * classes.
- */
-
-
-#include
-
-#if defined(__WIN32__) || defined(WIN32)
- #include
-#elif defined(LINUX)
- #include
- #include
-#endif
-
-#ifdef __MATLAB__
- #include
-#endif
-
-
-#include
-
-
-
-#ifdef PC_DEBUG /* Define print functions only for debugging! */
-/*
- * p r i n t
- */
-returnValue print( const real_t* const v, int n )
-{
- int i;
- char myPrintfString[160];
-
- /* Print a vector. */
- myPrintf( "[\t" );
- for( i=0; igetOutputFile( );
- if ( outputfile == 0 )
- return THROWERROR( RET_NO_GLOBAL_MESSAGE_OUTPUTFILE );
-
- fprintf( outputfile, "%s", s );
- #endif
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * p r i n t C o p y r i g h t N o t i c e
- */
-returnValue printCopyrightNotice( )
-{
- return myPrintf( "\nqpOASES -- An Implementation of the Online Active Set Strategy.\nCopyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.\n\nqpOASES is distributed under the terms of the \nGNU Lesser General Public License 2.1 in the hope that it will be \nuseful, but WITHOUT ANY WARRANTY; without even the implied warranty \nof MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \nSee the GNU Lesser General Public License for more details.\n\n" );
-}
-
-
-/*
- * r e a d F r o m F i l e
- */
-returnValue readFromFile( real_t* data, int nrow, int ncol,
- const char* datafilename
- )
-{
- int i, j;
- float float_data;
- myFILE* datafile;
-
- /* 1) Open file. */
- if ( ( datafile = fopen( datafilename, "r" ) ) == 0 )
- {
- char errstr[80];
- sprintf( errstr,"(%s)",datafilename );
- return getGlobalMessageHandler( )->throwError( RET_UNABLE_TO_OPEN_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
-
- /* 2) Read data from file. */
- for( i=0; ithrowError( RET_UNABLE_TO_READ_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
- data[i*ncol + j] = ( (real_t) float_data );
- }
- }
-
- /* 3) Close file. */
- fclose( datafile );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * r e a d F r o m F i l e
- */
-returnValue readFromFile( real_t* data, int n,
- const char* datafilename
- )
-{
- return readFromFile( data, n, 1, datafilename );
-}
-
-
-
-/*
- * r e a d F r o m F i l e
- */
-returnValue readFromFile( int* data, int n,
- const char* datafilename
- )
-{
- int i;
- myFILE* datafile;
-
- /* 1) Open file. */
- if ( ( datafile = fopen( datafilename, "r" ) ) == 0 )
- {
- char errstr[80];
- sprintf( errstr,"(%s)",datafilename );
- return getGlobalMessageHandler( )->throwError( RET_UNABLE_TO_OPEN_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
-
- /* 2) Read data from file. */
- for( i=0; ithrowError( RET_UNABLE_TO_READ_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
- }
-
- /* 3) Close file. */
- fclose( datafile );
-
- return SUCCESSFUL_RETURN;
-}
-
-
-/*
- * w r i t e I n t o F i l e
- */
-returnValue writeIntoFile( const real_t* const data, int nrow, int ncol,
- const char* datafilename, BooleanType append
- )
-{
- int i, j;
- myFILE* datafile;
-
- /* 1) Open file. */
- if ( append == BT_TRUE )
- {
- /* append data */
- if ( ( datafile = fopen( datafilename, "a" ) ) == 0 )
- {
- char errstr[80];
- sprintf( errstr,"(%s)",datafilename );
- return getGlobalMessageHandler( )->throwError( RET_UNABLE_TO_OPEN_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
- }
- else
- {
- /* do not append data */
- if ( ( datafile = fopen( datafilename, "w" ) ) == 0 )
- {
- char errstr[80];
- sprintf( errstr,"(%s)",datafilename );
- return getGlobalMessageHandler( )->throwError( RET_UNABLE_TO_OPEN_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
- }
-
- /* 2) Write data into file. */
- for( i=0; ithrowError( RET_UNABLE_TO_OPEN_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
- }
- else
- {
- /* do not append data */
- if ( ( datafile = fopen( datafilename, "w" ) ) == 0 )
- {
- char errstr[80];
- sprintf( errstr,"(%s)",datafilename );
- return getGlobalMessageHandler( )->throwError( RET_UNABLE_TO_OPEN_FILE,errstr,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
- }
- }
-
- /* 2) Write data into file. */
- for( i=0; i 0:
+ self.__nx = nx
+ else:
+ raise Exception('Invalid nx value, expected positive integer. Exiting.')
+
+ @nz.setter
+ def nz(self, nz):
+ if type(nz) == int and nz > -1:
+ self.__nz = nz
+ else:
+ raise Exception('Invalid nz value, expected nonnegative integer. Exiting.')
+
+ @nu.setter
+ def nu(self, nu):
+ if type(nu) == int and nu > -1:
+ self.__nu = nu
+ else:
+ raise Exception('Invalid nu value, expected nonnegative integer. Exiting.')
+
+ @np.setter
+ def np(self, np):
+ if type(np) == int and np > -1:
+ self.__np = np
+ else:
+ raise Exception('Invalid np value, expected nonnegative integer. Exiting.')
+
+ @ny_0.setter
+ def ny_0(self, ny_0):
+ if isinstance(ny_0, int) and ny_0 > -1:
+ self.__ny_0 = ny_0
+ else:
+ raise Exception('Invalid ny_0 value, expected nonnegative integer. Exiting.')
+
+ @ny.setter
+ def ny(self, ny):
+ if isinstance(ny, int) and ny > -1:
+ self.__ny = ny
+ else:
+ raise Exception('Invalid ny value, expected nonnegative integer. Exiting.')
+
+ @ny_e.setter
+ def ny_e(self, ny_e):
+ if type(ny_e) == int and ny_e > -1:
+ self.__ny_e = ny_e
+ else:
+ raise Exception('Invalid ny_e value, expected nonnegative integer. Exiting.')
+
+ @nr.setter
+ def nr(self, nr):
+ if type(nr) == int and nr > -1:
+ self.__nr = nr
+ else:
+ raise Exception('Invalid nr value, expected nonnegative integer. Exiting.')
+
+ @nr_e.setter
+ def nr_e(self, nr_e):
+ if type(nr_e) == int and nr_e > -1:
+ self.__nr_e = nr_e
+ else:
+ raise Exception('Invalid nr_e value, expected nonnegative integer. Exiting.')
+
+ @nh.setter
+ def nh(self, nh):
+ if type(nh) == int and nh > -1:
+ self.__nh = nh
+ else:
+ raise Exception('Invalid nh value, expected nonnegative integer. Exiting.')
+
+ @nh_e.setter
+ def nh_e(self, nh_e):
+ if type(nh_e) == int and nh_e > -1:
+ self.__nh_e = nh_e
+ else:
+ raise Exception('Invalid nh_e value, expected nonnegative integer. Exiting.')
+
+ @nphi.setter
+ def nphi(self, nphi):
+ if type(nphi) == int and nphi > -1:
+ self.__nphi = nphi
+ else:
+ raise Exception('Invalid nphi value, expected nonnegative integer. Exiting.')
+
+ @nphi_e.setter
+ def nphi_e(self, nphi_e):
+ if type(nphi_e) == int and nphi_e > -1:
+ self.__nphi_e = nphi_e
+ else:
+ raise Exception('Invalid nphi_e value, expected nonnegative integer. Exiting.')
+
+ @nbx.setter
+ def nbx(self, nbx):
+ if isinstance(nbx, int) and nbx > -1:
+ self.__nbx = nbx
+ else:
+ raise Exception('Invalid nbx value, expected nonnegative integer. Exiting.')
+
+ @nbxe_0.setter
+ def nbxe_0(self, nbxe_0):
+ if isinstance(nbxe_0, int) and nbxe_0 > -1:
+ self.__nbxe_0 = nbxe_0
+ else:
+ raise Exception('Invalid nbxe_0 value, expected nonnegative integer. Exiting.')
+
+ @nbx_0.setter
+ def nbx_0(self, nbx_0):
+ if type(nbx_0) == int and nbx_0 > -1:
+ self.__nbx_0 = nbx_0
+ else:
+ raise Exception('Invalid nbx_0 value, expected nonnegative integer. Exiting.')
+
+ @nbx_e.setter
+ def nbx_e(self, nbx_e):
+ if type(nbx_e) == int and nbx_e > -1:
+ self.__nbx_e = nbx_e
+ else:
+ raise Exception('Invalid nbx_e value, expected nonnegative integer. Exiting.')
+
+ @nbu.setter
+ def nbu(self, nbu):
+ if type(nbu) == int and nbu > -1:
+ self.__nbu = nbu
+ else:
+ raise Exception('Invalid nbu value, expected nonnegative integer. Exiting.')
+
+ @nsbx.setter
+ def nsbx(self, nsbx):
+ if type(nsbx) == int and nsbx > -1:
+ self.__nsbx = nsbx
+ else:
+ raise Exception('Invalid nsbx value, expected nonnegative integer. Exiting.')
+
+ @nsbx_e.setter
+ def nsbx_e(self, nsbx_e):
+ if type(nsbx_e) == int and nsbx_e > -1:
+ self.__nsbx_e = nsbx_e
+ else:
+ raise Exception('Invalid nsbx_e value, expected nonnegative integer. Exiting.')
+
+ @nsbu.setter
+ def nsbu(self, nsbu):
+ if type(nsbu) == int and nsbu > -1:
+ self.__nsbu = nsbu
+ else:
+ raise Exception('Invalid nsbu value, expected nonnegative integer. Exiting.')
+
+ @nsg.setter
+ def nsg(self, nsg):
+ if isinstance(nsg, int) and nsg > -1:
+ self.__nsg = nsg
+ else:
+ raise Exception('Invalid nsg value, expected nonnegative integer. Exiting.')
+
+ @nsg_e.setter
+ def nsg_e(self, nsg_e):
+ if isinstance(nsg_e, int) and nsg_e > -1:
+ self.__nsg_e = nsg_e
+ else:
+ raise Exception('Invalid nsg_e value, expected nonnegative integer. Exiting.')
+
+ @nsh.setter
+ def nsh(self, nsh):
+ if isinstance(nsh, int) and nsh > -1:
+ self.__nsh = nsh
+ else:
+ raise Exception('Invalid nsh value, expected nonnegative integer. Exiting.')
+
+ @nsh_e.setter
+ def nsh_e(self, nsh_e):
+ if isinstance(nsh_e, int) and nsh_e > -1:
+ self.__nsh_e = nsh_e
+ else:
+ raise Exception('Invalid nsh_e value, expected nonnegative integer. Exiting.')
+
+ @nsphi.setter
+ def nsphi(self, nsphi):
+ if isinstance(nsphi, int) and nsphi > -1:
+ self.__nsphi = nsphi
+ else:
+ raise Exception('Invalid nsphi value, expected nonnegative integer. Exiting.')
+
+ @nsphi_e.setter
+ def nsphi_e(self, nsphi_e):
+ if isinstance(nsphi_e, int) and nsphi_e > -1:
+ self.__nsphi_e = nsphi_e
+ else:
+ raise Exception('Invalid nsphi_e value, expected nonnegative integer. Exiting.')
+
+ @ns.setter
+ def ns(self, ns):
+ if isinstance(ns, int) and ns > -1:
+ self.__ns = ns
+ else:
+ raise Exception('Invalid ns value, expected nonnegative integer. Exiting.')
+
+ @ns_e.setter
+ def ns_e(self, ns_e):
+ if isinstance(ns_e, int) and ns_e > -1:
+ self.__ns_e = ns_e
+ else:
+ raise Exception('Invalid ns_e value, expected nonnegative integer. Exiting.')
+
+ @ng.setter
+ def ng(self, ng):
+ if isinstance(ng, int) and ng > -1:
+ self.__ng = ng
+ else:
+ raise Exception('Invalid ng value, expected nonnegative integer. Exiting.')
+
+ @ng_e.setter
+ def ng_e(self, ng_e):
+ if isinstance(ng_e, int) and ng_e > -1:
+ self.__ng_e = ng_e
+ else:
+ raise Exception('Invalid ng_e value, expected nonnegative integer. Exiting.')
+
+ @N.setter
+ def N(self, N):
+ if isinstance(N, int) and N > 0:
+ self.__N = N
+ else:
+ raise Exception('Invalid N value, expected positive integer. Exiting.')
+
+ def set(self, attr, value):
+ setattr(self, attr, value)
+
+
+class AcadosOcpCost:
+ """
+ Class containing the numerical data of the cost:
+
+ In case of LINEAR_LS:
+ stage cost is
+ :math:`l(x,u,z) = || V_x \, x + V_u \, u + V_z \, z - y_\\text{ref}||^2_W`,
+ terminal cost is
+ :math:`m(x) = || V^e_x \, x - y_\\text{ref}^e||^2_{W^e}`
+
+ In case of NONLINEAR_LS:
+ stage cost is
+ :math:`l(x,u,z) = || y(x,u,z) - y_\\text{ref}||^2_W`,
+ terminal cost is
+ :math:`m(x) = || y^e(x) - y_\\text{ref}^e||^2_{W^e}`
+ """
+ def __init__(self):
+ # initial stage
+ self.__cost_type_0 = None
+ self.__W_0 = None
+ self.__Vx_0 = None
+ self.__Vu_0 = None
+ self.__Vz_0 = None
+ self.__yref_0 = None
+ self.__cost_ext_fun_type_0 = 'casadi'
+ # Lagrange term
+ self.__cost_type = 'LINEAR_LS' # cost type
+ self.__W = np.zeros((0,0))
+ self.__Vx = np.zeros((0,0))
+ self.__Vu = np.zeros((0,0))
+ self.__Vz = np.zeros((0,0))
+ self.__yref = np.array([])
+ self.__Zl = np.array([])
+ self.__Zu = np.array([])
+ self.__zl = np.array([])
+ self.__zu = np.array([])
+ self.__cost_ext_fun_type = 'casadi'
+ # Mayer term
+ self.__cost_type_e = 'LINEAR_LS'
+ self.__W_e = np.zeros((0,0))
+ self.__Vx_e = np.zeros((0,0))
+ self.__yref_e = np.array([])
+ self.__Zl_e = np.array([])
+ self.__Zu_e = np.array([])
+ self.__zl_e = np.array([])
+ self.__zu_e = np.array([])
+ self.__cost_ext_fun_type_e = 'casadi'
+
+ # initial stage
+ @property
+ def cost_type_0(self):
+ """Cost type at initial shooting node (0)
+ -- string in {EXTERNAL, LINEAR_LS, NONLINEAR_LS} or :code:`None`.
+ Default: :code:`None`.
+
+ .. note:: Cost at initial stage is the same as for intermediate shooting nodes if not set differently explicitly.
+
+ .. note:: If :py:attr:`cost_type_0` is set to :code:`None` values in :py:attr:`W_0`, :py:attr:`Vx_0`, :py:attr:`Vu_0`, :py:attr:`Vz_0` and :py:attr:`yref_0` are ignored (set to :code:`None`).
+ """
+ return self.__cost_type_0
+
+ @property
+ def W_0(self):
+ """:math:`W_0` - weight matrix at initial shooting node (0).
+ Default: :code:`None`.
+ """
+ return self.__W_0
+
+ @property
+ def Vx_0(self):
+ """:math:`V_x^0` - x matrix coefficient at initial shooting node (0).
+ Default: :code:`None`.
+ """
+ return self.__Vx_0
+
+ @property
+ def Vu_0(self):
+ """:math:`V_u^0` - u matrix coefficient at initial shooting node (0).
+ Default: :code:`None`.
+ """
+ return self.__Vu_0
+
+ @property
+ def Vz_0(self):
+ """:math:`V_z^0` - z matrix coefficient at initial shooting node (0).
+ Default: :code:`None`.
+ """
+ return self.__Vz_0
+
+ @property
+ def yref_0(self):
+ """:math:`y_\\text{ref}^0` - reference at initial shooting node (0).
+ Default: :code:`None`.
+ """
+ return self.__yref_0
+
+ @property
+ def cost_ext_fun_type_0(self):
+ """Type of external function for cost at initial shooting node (0)
+ -- string in {casadi, generic} or :code:`None`
+ Default: :code:'casadi'.
+
+ .. note:: Cost at initial stage is the same as for intermediate shooting nodes if not set differently explicitly.
+ """
+ return self.__cost_ext_fun_type_0
+
+ @yref_0.setter
+ def yref_0(self, yref_0):
+ if isinstance(yref_0, np.ndarray):
+ self.__yref_0 = yref_0
+ else:
+ raise Exception('Invalid yref_0 value, expected numpy array. Exiting.')
+
+ @W_0.setter
+ def W_0(self, W_0):
+ if isinstance(W_0, np.ndarray) and len(W_0.shape) == 2:
+ self.__W_0 = W_0
+ else:
+ raise Exception('Invalid cost W_0 value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @Vx_0.setter
+ def Vx_0(self, Vx_0):
+ if isinstance(Vx_0, np.ndarray) and len(Vx_0.shape) == 2:
+ self.__Vx_0 = Vx_0
+ else:
+ raise Exception('Invalid cost Vx_0 value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @Vu_0.setter
+ def Vu_0(self, Vu_0):
+ if isinstance(Vu_0, np.ndarray) and len(Vu_0.shape) == 2:
+ self.__Vu_0 = Vu_0
+ else:
+ raise Exception('Invalid cost Vu_0 value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @Vz_0.setter
+ def Vz_0(self, Vz_0):
+ if isinstance(Vz_0, np.ndarray) and len(Vz_0.shape) == 2:
+ self.__Vz_0 = Vz_0
+ else:
+ raise Exception('Invalid cost Vz_0 value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @cost_ext_fun_type_0.setter
+ def cost_ext_fun_type_0(self, cost_ext_fun_type_0):
+ if cost_ext_fun_type_0 in ['casadi', 'generic']:
+ self.__cost_ext_fun_type_0 = cost_ext_fun_type_0
+ else:
+ raise Exception('Invalid cost_ext_fun_type_0 value, expected numpy array. Exiting.')
+
+ # Lagrange term
+ @property
+ def cost_type(self):
+ """
+ Cost type at intermediate shooting nodes (1 to N-1)
+ -- string in {EXTERNAL, LINEAR_LS, NONLINEAR_LS}.
+ Default: 'LINEAR_LS'.
+ """
+ return self.__cost_type
+
+ @property
+ def W(self):
+ """:math:`W` - weight matrix at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.zeros((0,0))`.
+ """
+ return self.__W
+
+ @property
+ def Vx(self):
+ """:math:`V_x` - x matrix coefficient at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.zeros((0,0))`.
+ """
+ return self.__Vx
+
+ @property
+ def Vu(self):
+ """:math:`V_u` - u matrix coefficient at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.zeros((0,0))`.
+ """
+ return self.__Vu
+
+ @property
+ def Vz(self):
+ """:math:`V_z` - z matrix coefficient at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.zeros((0,0))`.
+ """
+ return self.__Vz
+
+ @property
+ def yref(self):
+ """:math:`y_\\text{ref}` - reference at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.array([])`.
+ """
+ return self.__yref
+
+ @property
+ def Zl(self):
+ """:math:`Z_l` - diagonal of Hessian wrt lower slack at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.array([])`.
+ """
+ return self.__Zl
+
+ @property
+ def Zu(self):
+ """:math:`Z_u` - diagonal of Hessian wrt upper slack at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.array([])`.
+ """
+ return self.__Zu
+
+ @property
+ def zl(self):
+ """:math:`z_l` - gradient wrt lower slack at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.array([])`.
+ """
+ return self.__zl
+
+ @property
+ def zu(self):
+ """:math:`z_u` - gradient wrt upper slack at intermediate shooting nodes (1 to N-1).
+ Default: :code:`np.array([])`.
+ """
+ return self.__zu
+
+ @property
+ def cost_ext_fun_type(self):
+ """Type of external function for cost at intermediate shooting nodes (1 to N-1).
+ -- string in {casadi, generic}
+ Default: :code:'casadi'.
+ """
+ return self.__cost_ext_fun_type
+
+ @cost_type.setter
+ def cost_type(self, cost_type):
+ cost_types = ('LINEAR_LS', 'NONLINEAR_LS', 'EXTERNAL')
+ if cost_type in cost_types:
+ self.__cost_type = cost_type
+ else:
+ raise Exception('Invalid cost_type value. Exiting.')
+
+ @cost_type_0.setter
+ def cost_type_0(self, cost_type_0):
+ cost_types = ('LINEAR_LS', 'NONLINEAR_LS', 'EXTERNAL')
+ if cost_type_0 in cost_types:
+ self.__cost_type_0 = cost_type_0
+ else:
+ raise Exception('Invalid cost_type_0 value. Exiting.')
+
+ @W.setter
+ def W(self, W):
+ if isinstance(W, np.ndarray) and len(W.shape) == 2:
+ self.__W = W
+ else:
+ raise Exception('Invalid cost W value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+
+ @Vx.setter
+ def Vx(self, Vx):
+ if isinstance(Vx, np.ndarray) and len(Vx.shape) == 2:
+ self.__Vx = Vx
+ else:
+ raise Exception('Invalid cost Vx value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @Vu.setter
+ def Vu(self, Vu):
+ if isinstance(Vu, np.ndarray) and len(Vu.shape) == 2:
+ self.__Vu = Vu
+ else:
+ raise Exception('Invalid cost Vu value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @Vz.setter
+ def Vz(self, Vz):
+ if isinstance(Vz, np.ndarray) and len(Vz.shape) == 2:
+ self.__Vz = Vz
+ else:
+ raise Exception('Invalid cost Vz value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @yref.setter
+ def yref(self, yref):
+ if isinstance(yref, np.ndarray):
+ self.__yref = yref
+ else:
+ raise Exception('Invalid yref value, expected numpy array. Exiting.')
+
+ @Zl.setter
+ def Zl(self, Zl):
+ if isinstance(Zl, np.ndarray):
+ self.__Zl = Zl
+ else:
+ raise Exception('Invalid Zl value, expected numpy array. Exiting.')
+
+ @Zu.setter
+ def Zu(self, Zu):
+ if isinstance(Zu, np.ndarray):
+ self.__Zu = Zu
+ else:
+ raise Exception('Invalid Zu value, expected numpy array. Exiting.')
+
+ @zl.setter
+ def zl(self, zl):
+ if isinstance(zl, np.ndarray):
+ self.__zl = zl
+ else:
+ raise Exception('Invalid zl value, expected numpy array. Exiting.')
+
+ @zu.setter
+ def zu(self, zu):
+ if isinstance(zu, np.ndarray):
+ self.__zu = zu
+ else:
+ raise Exception('Invalid zu value, expected numpy array. Exiting.')
+
+ @cost_ext_fun_type.setter
+ def cost_ext_fun_type(self, cost_ext_fun_type):
+ if cost_ext_fun_type in ['casadi', 'generic']:
+ self.__cost_ext_fun_type = cost_ext_fun_type
+ else:
+ raise Exception('Invalid cost_ext_fun_type value, expected numpy array. Exiting.')
+
+ # Mayer term
+ @property
+ def cost_type_e(self):
+ """
+ Cost type at terminal shooting node (N)
+ -- string in {EXTERNAL, LINEAR_LS, NONLINEAR_LS}.
+ Default: 'LINEAR_LS'.
+ """
+ return self.__cost_type_e
+
+ @property
+ def W_e(self):
+ """:math:`W_e` - weight matrix at terminal shooting node (N).
+ Default: :code:`np.zeros((0,0))`.
+ """
+ return self.__W_e
+
+ @property
+ def Vx_e(self):
+ """:math:`V_x^e` - x matrix coefficient for cost at terminal shooting node (N).
+ Default: :code:`np.zeros((0,0))`.
+ """
+ return self.__Vx_e
+
+ @property
+ def yref_e(self):
+ """:math:`y_\\text{ref}^e` - cost reference at terminal shooting node (N).
+ Default: :code:`np.array([])`.
+ """
+ return self.__yref_e
+
+ @property
+ def Zl_e(self):
+ """:math:`Z_l^e` - diagonal of Hessian wrt lower slack at terminal shooting node (N).
+ Default: :code:`np.array([])`.
+ """
+ return self.__Zl_e
+
+ @property
+ def Zu_e(self):
+ """:math:`Z_u^e` - diagonal of Hessian wrt upper slack at terminal shooting node (N).
+ Default: :code:`np.array([])`.
+ """
+ return self.__Zu_e
+
+ @property
+ def zl_e(self):
+ """:math:`z_l^e` - gradient wrt lower slack at terminal shooting node (N).
+ Default: :code:`np.array([])`.
+ """
+ return self.__zl_e
+
+ @property
+ def zu_e(self):
+ """:math:`z_u^e` - gradient wrt upper slack at terminal shooting node (N).
+ Default: :code:`np.array([])`.
+ """
+ return self.__zu_e
+
+ @property
+ def cost_ext_fun_type_e(self):
+ """Type of external function for cost at intermediate shooting nodes (1 to N-1).
+ -- string in {casadi, generic}
+ Default: :code:'casadi'.
+ """
+ return self.__cost_ext_fun_type_e
+
+ @cost_type_e.setter
+ def cost_type_e(self, cost_type_e):
+ cost_types = ('LINEAR_LS', 'NONLINEAR_LS', 'EXTERNAL')
+
+ if cost_type_e in cost_types:
+ self.__cost_type_e = cost_type_e
+ else:
+ raise Exception('Invalid cost_type_e value. Exiting.')
+
+ @W_e.setter
+ def W_e(self, W_e):
+ if isinstance(W_e, np.ndarray) and len(W_e.shape) == 2:
+ self.__W_e = W_e
+ else:
+ raise Exception('Invalid cost W_e value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @Vx_e.setter
+ def Vx_e(self, Vx_e):
+ if isinstance(Vx_e, np.ndarray) and len(Vx_e.shape) == 2:
+ self.__Vx_e = Vx_e
+ else:
+ raise Exception('Invalid cost Vx_e value. ' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @yref_e.setter
+ def yref_e(self, yref_e):
+ if isinstance(yref_e, np.ndarray):
+ self.__yref_e = yref_e
+ else:
+ raise Exception('Invalid yref_e value, expected numpy array. Exiting.')
+
+ @Zl_e.setter
+ def Zl_e(self, Zl_e):
+ if isinstance(Zl_e, np.ndarray):
+ self.__Zl_e = Zl_e
+ else:
+ raise Exception('Invalid Zl_e value, expected numpy array. Exiting.')
+
+ @Zu_e.setter
+ def Zu_e(self, Zu_e):
+ if isinstance(Zu_e, np.ndarray):
+ self.__Zu_e = Zu_e
+ else:
+ raise Exception('Invalid Zu_e value, expected numpy array. Exiting.')
+
+ @zl_e.setter
+ def zl_e(self, zl_e):
+ if isinstance(zl_e, np.ndarray):
+ self.__zl_e = zl_e
+ else:
+ raise Exception('Invalid zl_e value, expected numpy array. Exiting.')
+
+ @zu_e.setter
+ def zu_e(self, zu_e):
+ if isinstance(zu_e, np.ndarray):
+ self.__zu_e = zu_e
+ else:
+ raise Exception('Invalid zu_e value, expected numpy array. Exiting.')
+
+ @cost_ext_fun_type_e.setter
+ def cost_ext_fun_type_e(self, cost_ext_fun_type_e):
+ if cost_ext_fun_type_e in ['casadi', 'generic']:
+ self.__cost_ext_fun_type_e = cost_ext_fun_type_e
+ else:
+ raise Exception('Invalid cost_ext_fun_type_e value, expected numpy array. Exiting.')
+
+ def set(self, attr, value):
+ setattr(self, attr, value)
+
+
+def print_J_to_idx_note():
+ print("NOTE: J* matrix is converted to zero based vector idx* vector, which is returned here.")
+
+
+class AcadosOcpConstraints:
+ """
+ class containing the description of the constraints
+ """
+ def __init__(self):
+ self.__constr_type = 'BGH'
+ self.__constr_type_e = 'BGH'
+ # initial x
+ self.__lbx_0 = np.array([])
+ self.__ubx_0 = np.array([])
+ self.__idxbx_0 = np.array([])
+ self.__idxbxe_0 = np.array([])
+ # state bounds
+ self.__lbx = np.array([])
+ self.__ubx = np.array([])
+ self.__idxbx = np.array([])
+ # bounds on x at shooting node N
+ self.__lbx_e = np.array([])
+ self.__ubx_e = np.array([])
+ self.__idxbx_e = np.array([])
+ # bounds on u
+ self.__lbu = np.array([])
+ self.__ubu = np.array([])
+ self.__idxbu = np.array([])
+ # polytopic constraints
+ self.__lg = np.array([])
+ self.__ug = np.array([])
+ self.__D = np.zeros((0,0))
+ self.__C = np.zeros((0,0))
+ # polytopic constraints at shooting node N
+ self.__C_e = np.zeros((0,0))
+ self.__lg_e = np.array([])
+ self.__ug_e = np.array([])
+ # nonlinear constraints
+ self.__lh = np.array([])
+ self.__uh = np.array([])
+ # nonlinear constraints at shooting node N
+ self.__uh_e = np.array([])
+ self.__lh_e = np.array([])
+ # convex-over-nonlinear constraints
+ self.__lphi = np.array([])
+ self.__uphi = np.array([])
+ # nonlinear constraints at shooting node N
+ self.__uphi_e = np.array([])
+ self.__lphi_e = np.array([])
+ # SLACK BOUNDS
+ # soft bounds on x
+ self.__lsbx = np.array([])
+ self.__usbx = np.array([])
+ self.__idxsbx = np.array([])
+ # soft bounds on u
+ self.__lsbu = np.array([])
+ self.__usbu = np.array([])
+ self.__idxsbu = np.array([])
+ # soft bounds on x at shooting node N
+ self.__lsbx_e = np.array([])
+ self.__usbx_e = np.array([])
+ self.__idxsbx_e= np.array([])
+ # soft bounds on general linear constraints
+ self.__lsg = np.array([])
+ self.__usg = np.array([])
+ self.__idxsg = np.array([])
+ # soft bounds on nonlinear constraints
+ self.__lsh = np.array([])
+ self.__ush = np.array([])
+ self.__idxsh = np.array([])
+ # soft bounds on nonlinear constraints
+ self.__lsphi = np.array([])
+ self.__usphi = np.array([])
+ self.__idxsphi = np.array([])
+ # soft bounds on general linear constraints at shooting node N
+ self.__lsg_e = np.array([])
+ self.__usg_e = np.array([])
+ self.__idxsg_e = np.array([])
+ # soft bounds on nonlinear constraints at shooting node N
+ self.__lsh_e = np.array([])
+ self.__ush_e = np.array([])
+ self.__idxsh_e = np.array([])
+ # soft bounds on nonlinear constraints at shooting node N
+ self.__lsphi_e = np.array([])
+ self.__usphi_e = np.array([])
+ self.__idxsphi_e = np.array([])
+
+
+ # types
+ @property
+ def constr_type(self):
+ """Constraints type for shooting nodes (0 to N-1). string in {BGH, BGP}.
+ Default: BGH; BGP is for convex over nonlinear."""
+ return self.__constr_type
+
+ @property
+ def constr_type_e(self):
+ """Constraints type for terminal shooting node N. string in {BGH, BGP}.
+ Default: BGH; BGP is for convex over nonlinear."""
+ return self.__constr_type_e
+
+ # initial bounds on x
+ @property
+ def lbx_0(self):
+ """:math:`\\underline{x_0}` - lower bounds on x at initial stage 0.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`."""
+ return self.__lbx_0
+
+ @property
+ def ubx_0(self):
+ """:math:`\\bar{x_0}` - upper bounds on x at initial stage 0.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__ubx_0
+
+ @property
+ def Jbx_0(self):
+ """:math:`J_{bx,0}` - matrix coefficient for bounds on x at initial stage 0.
+ Translated internally to :py:attr:`idxbx_0`"""
+ print_J_to_idx_note()
+ return self.__idxbx_0
+
+ @property
+ def idxbx_0(self):
+ """Indices of bounds on x at initial stage 0
+ -- can be set automatically via x0.
+ Can be set by using :py:attr:`Jbx_0`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxbx_0
+
+ @property
+ def idxbxe_0(self):
+ """Indices of bounds on x0 that are equalities -- can be set automatically via :py:attr:`x0`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxbxe_0
+
+ # bounds on x
+ @property
+ def lbx(self):
+ """:math:`\\underline{x}` - lower bounds on x at intermediate shooting nodes (1 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__lbx
+
+ @property
+ def ubx(self):
+ """:math:`\\bar{x}` - upper bounds on x at intermediate shooting nodes (1 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__ubx
+
+ @property
+ def idxbx(self):
+ """indices of bounds on x (defines :math:`J_{bx}`) at intermediate shooting nodes (1 to N-1).
+ Can be set by using :py:attr:`Jbx`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxbx
+
+ @property
+ def Jbx(self):
+ """:math:`J_{bx}` - matrix coefficient for bounds on x
+ at intermediate shooting nodes (1 to N-1).
+ Translated internally into :py:attr:`idxbx`."""
+ print_J_to_idx_note()
+ return self.__idxbx
+
+ # bounds on x at shooting node N
+ @property
+ def lbx_e(self):
+ """:math:`\\underline{x}^e` - lower bounds on x at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__lbx_e
+
+ @property
+ def ubx_e(self):
+ """:math:`\\bar{x}^e` - upper bounds on x at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__ubx_e
+
+ @property
+ def idxbx_e(self):
+ """Indices for bounds on x at terminal shooting node N (defines :math:`J_{bx}^e`).
+ Can be set by using :py:attr:`Jbx_e`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxbx_e
+
+ @property
+ def Jbx_e(self):
+ """:math:`J_{bx}^e` matrix coefficient for bounds on x at terminal shooting node N.
+ Translated internally into :py:attr:`idxbx_e`."""
+ print_J_to_idx_note()
+ return self.__idxbx_e
+
+ # bounds on u
+ @property
+ def lbu(self):
+ """:math:`\\underline{u}` - lower bounds on u at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`
+ """
+ return self.__lbu
+
+ @property
+ def ubu(self):
+ """:math:`\\bar{u}` - upper bounds on u at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`
+ """
+ return self.__ubu
+
+ @property
+ def idxbu(self):
+ """Indices of bounds on u (defines :math:`J_{bu}`) at shooting nodes (0 to N-1).
+ Can be set by using :py:attr:`Jbu`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`
+ """
+ return self.__idxbu
+
+ @property
+ def Jbu(self):
+ """:math:`J_{bu}` - matrix coefficient for bounds on u at shooting nodes (0 to N-1).
+ Translated internally to :py:attr:`idxbu`.
+ """
+ print_J_to_idx_note()
+ return self.__idxbu
+
+ # polytopic constraints
+ @property
+ def C(self):
+ """:math:`C` - C matrix in :math:`\\underline{g} \\leq D \, u + C \, x \\leq \\bar{g}`
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array((0,0))`.
+ """
+ return self.__C
+
+ @property
+ def D(self):
+ """:math:`D` - D matrix in :math:`\\underline{g} \\leq D \, u + C \, x \\leq \\bar{g}`
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array((0,0))`
+ """
+ return self.__D
+
+ @property
+ def lg(self):
+ """:math:`\\underline{g}` - lower bound for general polytopic inequalities
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`
+ """
+ return self.__lg
+
+ @property
+ def ug(self):
+ """:math:`\\bar{g}` - upper bound for general polytopic inequalities
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__ug
+
+ # polytopic constraints at shooting node N
+ @property
+ def C_e(self):
+ """:math:`C^e` - C matrix at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array((0,0))`.
+ """
+ return self.__C_e
+
+ @property
+ def lg_e(self):
+ """:math:`\\underline{g}^e` - lower bound on general polytopic inequalities
+ at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__lg_e
+
+ @property
+ def ug_e(self):
+ """:math:`\\bar{g}^e` - upper bound on general polytopic inequalities
+ at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__ug_e
+
+
+ # nonlinear constraints
+ @property
+ def lh(self):
+ """:math:`\\underline{h}` - lower bound for nonlinear inequalities
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__lh
+
+ @property
+ def uh(self):
+ """:math:`\\bar{h}` - upper bound for nonlinear inequalities
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__uh
+
+ # nonlinear constraints at shooting node N
+ @property
+ def lh_e(self):
+ """:math:`\\underline{h}^e` - lower bound on nonlinear inequalities
+ at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__lh_e
+
+ @property
+ def uh_e(self):
+ """:math:`\\bar{h}^e` - upper bound on nonlinear inequalities
+ at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__uh_e
+
+ # convex-over-nonlinear constraints
+ @property
+ def lphi(self):
+ """:math:`\\underline{\phi}` - lower bound for convex-over-nonlinear inequalities
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__lphi
+
+ @property
+ def uphi(self):
+ """:math:`\\bar{\phi}` - upper bound for convex-over-nonlinear inequalities
+ at shooting nodes (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__uphi
+
+ # convex-over-nonlinear constraints at shooting node N
+ @property
+ def lphi_e(self):
+ """:math:`\\underline{\phi}^e` - lower bound on convex-over-nonlinear inequalities
+ at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__lphi_e
+
+ @property
+ def uphi_e(self):
+ """:math:`\\bar{\phi}^e` - upper bound on convex-over-nonlinear inequalities
+ at terminal shooting node N.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`.
+ """
+ return self.__uphi_e
+
+
+ # SLACK bounds
+ # soft bounds on x
+ @property
+ def lsbx(self):
+ """Lower bounds on slacks corresponding to soft lower bounds on x
+ at stages (1 to N-1);
+ not required - zeros by default"""
+ return self.__lsbx
+
+ @property
+ def usbx(self):
+ """Lower bounds on slacks corresponding to soft upper bounds on x
+ at stages (1 to N-1);
+ not required - zeros by default"""
+ return self.__usbx
+
+ @property
+ def idxsbx(self):
+ """Indices of soft bounds on x within the indices of bounds on x
+ at stages (1 to N-1).
+ Can be set by using :py:attr:`Jsbx`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxsbx
+
+ @property
+ def Jsbx(self):
+ """:math:`J_{sbx}` - matrix coefficient for soft bounds on x
+ at stages (1 to N-1);
+ Translated internally into :py:attr:`idxsbx`."""
+ print_J_to_idx_note()
+ return self.__idxsbx
+
+ # soft bounds on u
+ @property
+ def lsbu(self):
+ """Lower bounds on slacks corresponding to soft lower bounds on u
+ at stages (0 to N-1).
+ Not required - zeros by default."""
+ return self.__lsbu
+
+ @property
+ def usbu(self):
+ """Lower bounds on slacks corresponding to soft upper bounds on u
+ at stages (0 to N-1);
+ not required - zeros by default"""
+ return self.__usbu
+
+ @property
+ def idxsbu(self):
+ """Indices of soft bounds on u within the indices of bounds on u
+ at stages (0 to N-1).
+ Can be set by using :py:attr:`Jsbu`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxsbu
+
+ @property
+ def Jsbu(self):
+ """:math:`J_{sbu}` - matrix coefficient for soft bounds on u
+ at stages (0 to N-1);
+ internally translated into :py:attr:`idxsbu`"""
+ print_J_to_idx_note()
+ return self.__idxsbu
+
+ # soft bounds on x at shooting node N
+ @property
+ def lsbx_e(self):
+ """Lower bounds on slacks corresponding to soft lower bounds on x at shooting node N.
+ Not required - zeros by default"""
+ return self.__lsbx_e
+
+ @property
+ def usbx_e(self):
+ """Lower bounds on slacks corresponding to soft upper bounds on x at shooting node N.
+ Not required - zeros by default"""
+ return self.__usbx_e
+
+ @property
+ def idxsbx_e(self):
+ """Indices of soft bounds on x at shooting node N, within the indices of bounds on x at terminal shooting node N.
+ Can be set by using :py:attr:`Jsbx_e`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxsbx_e
+
+ @property
+ def Jsbx_e(self):
+ """:math:`J_{sbx}^e` - matrix coefficient for soft bounds on x at terminal shooting node N.
+ Translated internally to :py:attr:`idxsbx_e`"""
+ print_J_to_idx_note()
+ return self.__idxsbx_e
+
+ # soft general linear constraints
+ @property
+ def lsg(self):
+ """Lower bounds on slacks corresponding to soft lower bounds for general linear constraints
+ at stages (0 to N-1).
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`
+ """
+ return self.__lsg
+
+ @property
+ def usg(self):
+ """Lower bounds on slacks corresponding to soft upper bounds for general linear constraints.
+ Not required - zeros by default"""
+ return self.__usg
+
+ @property
+ def idxsg(self):
+ """Indices of soft general linear constraints within the indices of general linear constraints.
+ Can be set by using :py:attr:`Jsg`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxsg
+
+ @property
+ def Jsg(self):
+ """:math:`J_{sg}` - matrix coefficient for soft bounds on general linear constraints.
+ Translated internally to :py:attr:`idxsg`"""
+ print_J_to_idx_note()
+ return self.__idxsg
+
+ # soft nonlinear constraints
+ @property
+ def lsh(self):
+ """Lower bounds on slacks corresponding to soft lower bounds for nonlinear constraints.
+ Not required - zeros by default"""
+ return self.__lsh
+
+ @property
+ def ush(self):
+ """Lower bounds on slacks corresponding to soft upper bounds for nonlinear constraints.
+ Not required - zeros by default"""
+ return self.__ush
+
+ @property
+ def idxsh(self):
+ """Indices of soft nonlinear constraints within the indices of nonlinear constraints.
+ Can be set by using :py:attr:`Jbx`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxsh
+
+ @property
+ def Jsh(self):
+ """:math:`J_{sh}` - matrix coefficient for soft bounds on nonlinear constraints.
+ Translated internally to :py:attr:`idxsh`"""
+ print_J_to_idx_note()
+ return self.__idxsh
+
+ # soft bounds on convex-over-nonlinear constraints
+ @property
+ def lsphi(self):
+ """Lower bounds on slacks corresponding to soft lower bounds for convex-over-nonlinear constraints.
+ Not required - zeros by default"""
+ return self.__lsphi
+
+ @property
+ def usphi(self):
+ """Lower bounds on slacks corresponding to soft upper bounds for convex-over-nonlinear constraints.
+ Not required - zeros by default"""
+ return self.__usphi
+
+ @property
+ def idxsphi(self):
+ """Indices of soft convex-over-nonlinear constraints within the indices of nonlinear constraints.
+ Can be set by using :py:attr:`Jsphi`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxsphi
+
+ @property
+ def Jsphi(self):
+ """:math:`J_{s, \phi}` - matrix coefficient for soft bounds on convex-over-nonlinear constraints.
+ Translated internally into :py:attr:`idxsphi`."""
+ print_J_to_idx_note()
+ return self.__idxsphi
+
+
+ # soft bounds on general linear constraints at shooting node N
+ @property
+ def lsg_e(self):
+ """Lower bounds on slacks corresponding to soft lower bounds for general linear constraints at shooting node N.
+ Not required - zeros by default"""
+ return self.__lsg_e
+
+ @property
+ def usg_e(self):
+ """Lower bounds on slacks corresponding to soft upper bounds for general linear constraints at shooting node N.
+ Not required - zeros by default"""
+ return self.__usg_e
+
+ @property
+ def idxsg_e(self):
+ """Indices of soft general linear constraints at shooting node N within the indices of general linear constraints at shooting node N.
+ Can be set by using :py:attr:`Jsg_e`."""
+ return self.__idxsg_e
+
+ @property
+ def Jsg_e(self):
+ """:math:`J_{s,h}^e` - matrix coefficient for soft bounds on general linear constraints at terminal shooting node N.
+ Translated internally to :py:attr:`idxsg_e`"""
+ print_J_to_idx_note()
+ return self.__idxsg_e
+
+
+ # soft bounds on nonlinear constraints at shooting node N
+ @property
+ def lsh_e(self):
+ """Lower bounds on slacks corresponding to soft lower bounds for nonlinear constraints at terminal shooting node N.
+ Not required - zeros by default"""
+ return self.__lsh_e
+
+ @property
+ def ush_e(self):
+ """Lower bounds on slacks corresponding to soft upper bounds for nonlinear constraints at terminal shooting node N.
+ Not required - zeros by default"""
+ return self.__ush_e
+
+ @property
+ def idxsh_e(self):
+ """Indices of soft nonlinear constraints at shooting node N within the indices of nonlinear constraints at terminal shooting node N.
+ Can be set by using :py:attr:`Jsh_e`."""
+ return self.__idxsh_e
+
+ @property
+ def Jsh_e(self):
+ """:math:`J_{s,h}^e` - matrix coefficient for soft bounds on nonlinear constraints at terminal shooting node N; fills :py:attr:`idxsh_e`"""
+ print_J_to_idx_note()
+ return self.__idxsh_e
+
+ # soft bounds on convex-over-nonlinear constraints at shooting node N
+ @property
+ def lsphi_e(self):
+ """Lower bounds on slacks corresponding to soft lower bounds for convex-over-nonlinear constraints at terminal shooting node N.
+ Not required - zeros by default"""
+ return self.__lsphi_e
+
+ @property
+ def usphi_e(self):
+ """Lower bounds on slacks corresponding to soft upper bounds for convex-over-nonlinear constraints at terminal shooting node N.
+ Not required - zeros by default"""
+ return self.__usphi_e
+
+ @property
+ def idxsphi_e(self):
+ """Indices of soft nonlinear constraints at shooting node N within the indices of nonlinear constraints at terminal shooting node N.
+ Can be set by using :py:attr:`Jsphi_e`.
+ Type: :code:`np.ndarray`; default: :code:`np.array([])`"""
+ return self.__idxsphi_e
+
+ @property
+ def Jsphi_e(self):
+ """:math:`J_{sh}^e` - matrix coefficient for soft bounds on convex-over-nonlinear constraints at shooting node N.
+ Translated internally to :py:attr:`idxsphi_e`"""
+ print_J_to_idx_note()
+ return self.__idxsphi_e
+
+ @property
+ def x0(self):
+ """:math:`x_0 \\in \mathbb{R}^{n_x}` - initial state --
+ Translated internally to :py:attr:`idxbx_0`, :py:attr:`lbx_0`, :py:attr:`ubx_0`, :py:attr:`idxbxe_0` """
+ print("x0 is converted to lbx_0, ubx_0, idxbx_0")
+ print("idxbx_0: ", self.__idxbx_0)
+ print("lbx_0: ", self.__lbx_0)
+ print("ubx_0: ", self.__ubx_0)
+ print("idxbxe_0: ", self.__idxbxe_0)
+ return None
+
+ # SETTERS
+ @constr_type.setter
+ def constr_type(self, constr_type):
+ constr_types = ('BGH', 'BGP')
+ if constr_type in constr_types:
+ self.__constr_type = constr_type
+ else:
+ raise Exception('Invalid constr_type value. Possible values are:\n\n' \
+ + ',\n'.join(constr_types) + '.\n\nYou have: ' + constr_type + '.\n\nExiting.')
+
+ @constr_type_e.setter
+ def constr_type_e(self, constr_type_e):
+ constr_types = ('BGH', 'BGP')
+ if constr_type_e in constr_types:
+ self.__constr_type_e = constr_type_e
+ else:
+ raise Exception('Invalid constr_type_e value. Possible values are:\n\n' \
+ + ',\n'.join(constr_types) + '.\n\nYou have: ' + constr_type_e + '.\n\nExiting.')
+
+ # initial x
+ @lbx_0.setter
+ def lbx_0(self, lbx_0):
+ if type(lbx_0) == np.ndarray:
+ self.__lbx_0 = lbx_0
+ else:
+ raise Exception('Invalid lbx_0 value. Exiting.')
+
+ @ubx_0.setter
+ def ubx_0(self, ubx_0):
+ if type(ubx_0) == np.ndarray:
+ self.__ubx_0 = ubx_0
+ else:
+ raise Exception('Invalid ubx_0 value. Exiting.')
+
+ @idxbx_0.setter
+ def idxbx_0(self, idxbx_0):
+ if isinstance(idxbx_0, np.ndarray):
+ self.__idxbx_0 = idxbx_0
+ else:
+ raise Exception('Invalid idxbx_0 value. Exiting.')
+
+ @Jbx_0.setter
+ def Jbx_0(self, Jbx_0):
+ if type(Jbx_0) == np.ndarray:
+ self.__idxbx_0 = J_to_idx(Jbx_0)
+ else:
+ raise Exception('Invalid Jbx_0 value. Exiting.')
+
+ @idxbxe_0.setter
+ def idxbxe_0(self, idxbxe_0):
+ if isinstance(idxbxe_0, np.ndarray):
+ self.__idxbxe_0 = idxbxe_0
+ else:
+ raise Exception('Invalid idxbxe_0 value. Exiting.')
+
+
+ @x0.setter
+ def x0(self, x0):
+ if isinstance(x0, np.ndarray):
+ self.__lbx_0 = x0
+ self.__ubx_0 = x0
+ self.__idxbx_0 = np.arange(x0.size)
+ self.__idxbxe_0 = np.arange(x0.size)
+ else:
+ raise Exception('Invalid x0 value. Exiting.')
+
+ # bounds on x
+ @lbx.setter
+ def lbx(self, lbx):
+ if type(lbx) == np.ndarray:
+ self.__lbx = lbx
+ else:
+ raise Exception('Invalid lbx value. Exiting.')
+
+ @ubx.setter
+ def ubx(self, ubx):
+ if type(ubx) == np.ndarray:
+ self.__ubx = ubx
+ else:
+ raise Exception('Invalid ubx value. Exiting.')
+
+ @idxbx.setter
+ def idxbx(self, idxbx):
+ if type(idxbx) == np.ndarray:
+ self.__idxbx = idxbx
+ else:
+ raise Exception('Invalid idxbx value. Exiting.')
+
+ @Jbx.setter
+ def Jbx(self, Jbx):
+ if type(Jbx) == np.ndarray:
+ self.__idxbx = J_to_idx(Jbx)
+ else:
+ raise Exception('Invalid Jbx value. Exiting.')
+
+ # bounds on u
+ @lbu.setter
+ def lbu(self, lbu):
+ if type(lbu) == np.ndarray:
+ self.__lbu = lbu
+ else:
+ raise Exception('Invalid lbu value. Exiting.')
+
+ @ubu.setter
+ def ubu(self, ubu):
+ if type(ubu) == np.ndarray:
+ self.__ubu = ubu
+ else:
+ raise Exception('Invalid ubu value. Exiting.')
+
+ @idxbu.setter
+ def idxbu(self, idxbu):
+ if type(idxbu) == np.ndarray:
+ self.__idxbu = idxbu
+ else:
+ raise Exception('Invalid idxbu value. Exiting.')
+
+ @Jbu.setter
+ def Jbu(self, Jbu):
+ if type(Jbu) == np.ndarray:
+ self.__idxbu = J_to_idx(Jbu)
+ else:
+ raise Exception('Invalid Jbu value. Exiting.')
+
+ # bounds on x at shooting node N
+ @lbx_e.setter
+ def lbx_e(self, lbx_e):
+ if type(lbx_e) == np.ndarray:
+ self.__lbx_e = lbx_e
+ else:
+ raise Exception('Invalid lbx_e value. Exiting.')
+
+ @ubx_e.setter
+ def ubx_e(self, ubx_e):
+ if type(ubx_e) == np.ndarray:
+ self.__ubx_e = ubx_e
+ else:
+ raise Exception('Invalid ubx_e value. Exiting.')
+
+ @idxbx_e.setter
+ def idxbx_e(self, idxbx_e):
+ if type(idxbx_e) == np.ndarray:
+ self.__idxbx_e = idxbx_e
+ else:
+ raise Exception('Invalid idxbx_e value. Exiting.')
+
+ @Jbx_e.setter
+ def Jbx_e(self, Jbx_e):
+ if type(Jbx_e) == np.ndarray:
+ self.__idxbx_e = J_to_idx(Jbx_e)
+ else:
+ raise Exception('Invalid Jbx_e value. Exiting.')
+
+ # polytopic constraints
+ @D.setter
+ def D(self, D):
+ if isinstance(D, np.ndarray) and len(D.shape) == 2:
+ self.__D = D
+ else:
+ raise Exception('Invalid constraint D value.' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @C.setter
+ def C(self, C):
+ if isinstance(C, np.ndarray) and len(C.shape) == 2:
+ self.__C = C
+ else:
+ raise Exception('Invalid constraint C value.' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @lg.setter
+ def lg(self, lg):
+ if type(lg) == np.ndarray:
+ self.__lg = lg
+ else:
+ raise Exception('Invalid lg value. Exiting.')
+
+ @ug.setter
+ def ug(self, ug):
+ if type(ug) == np.ndarray:
+ self.__ug = ug
+ else:
+ raise Exception('Invalid ug value. Exiting.')
+
+ # polytopic constraints at shooting node N
+ @C_e.setter
+ def C_e(self, C_e):
+ if isinstance(C_e, np.ndarray) and len(C_e.shape) == 2:
+ self.__C_e = C_e
+ else:
+ raise Exception('Invalid constraint C_e value.' \
+ + 'Should be 2 dimensional numpy array. Exiting.')
+
+ @lg_e.setter
+ def lg_e(self, lg_e):
+ if type(lg_e) == np.ndarray:
+ self.__lg_e = lg_e
+ else:
+ raise Exception('Invalid lg_e value. Exiting.')
+
+ @ug_e.setter
+ def ug_e(self, ug_e):
+ if type(ug_e) == np.ndarray:
+ self.__ug_e = ug_e
+ else:
+ raise Exception('Invalid ug_e value. Exiting.')
+
+ # nonlinear constraints
+ @lh.setter
+ def lh(self, lh):
+ if type(lh) == np.ndarray:
+ self.__lh = lh
+ else:
+ raise Exception('Invalid lh value. Exiting.')
+
+ @uh.setter
+ def uh(self, uh):
+ if type(uh) == np.ndarray:
+ self.__uh = uh
+ else:
+ raise Exception('Invalid uh value. Exiting.')
+
+ # convex-over-nonlinear constraints
+ @lphi.setter
+ def lphi(self, lphi):
+ if type(lphi) == np.ndarray:
+ self.__lphi = lphi
+ else:
+ raise Exception('Invalid lphi value. Exiting.')
+
+ @uphi.setter
+ def uphi(self, uphi):
+ if type(uphi) == np.ndarray:
+ self.__uphi = uphi
+ else:
+ raise Exception('Invalid uphi value. Exiting.')
+
+ # nonlinear constraints at shooting node N
+ @lh_e.setter
+ def lh_e(self, lh_e):
+ if type(lh_e) == np.ndarray:
+ self.__lh_e = lh_e
+ else:
+ raise Exception('Invalid lh_e value. Exiting.')
+
+ @uh_e.setter
+ def uh_e(self, uh_e):
+ if type(uh_e) == np.ndarray:
+ self.__uh_e = uh_e
+ else:
+ raise Exception('Invalid uh_e value. Exiting.')
+
+ # convex-over-nonlinear constraints at shooting node N
+ @lphi_e.setter
+ def lphi_e(self, lphi_e):
+ if type(lphi_e) == np.ndarray:
+ self.__lphi_e = lphi_e
+ else:
+ raise Exception('Invalid lphi_e value. Exiting.')
+
+ @uphi_e.setter
+ def uphi_e(self, uphi_e):
+ if type(uphi_e) == np.ndarray:
+ self.__uphi_e = uphi_e
+ else:
+ raise Exception('Invalid uphi_e value. Exiting.')
+
+ # SLACK bounds
+ # soft bounds on x
+ @lsbx.setter
+ def lsbx(self, lsbx):
+ if type(lsbx) == np.ndarray:
+ self.__lsbx = lsbx
+ else:
+ raise Exception('Invalid lsbx value. Exiting.')
+
+ @usbx.setter
+ def usbx(self, usbx):
+ if type(usbx) == np.ndarray:
+ self.__usbx = usbx
+ else:
+ raise Exception('Invalid usbx value. Exiting.')
+
+ @idxsbx.setter
+ def idxsbx(self, idxsbx):
+ if type(idxsbx) == np.ndarray:
+ self.__idxsbx = idxsbx
+ else:
+ raise Exception('Invalid idxsbx value. Exiting.')
+
+ @Jsbx.setter
+ def Jsbx(self, Jsbx):
+ if isinstance(Jsbx, np.ndarray):
+ self.__idxsbx = J_to_idx_slack(Jsbx)
+ else:
+ raise Exception('Invalid Jsbx value, expected numpy array. Exiting.')
+
+ # soft bounds on u
+ @lsbu.setter
+ def lsbu(self, lsbu):
+ if type(lsbu) == np.ndarray:
+ self.__lsbu = lsbu
+ else:
+ raise Exception('Invalid lsbu value. Exiting.')
+
+ @usbu.setter
+ def usbu(self, usbu):
+ if type(usbu) == np.ndarray:
+ self.__usbu = usbu
+ else:
+ raise Exception('Invalid usbu value. Exiting.')
+
+ @idxsbu.setter
+ def idxsbu(self, idxsbu):
+ if type(idxsbu) == np.ndarray:
+ self.__idxsbu = idxsbu
+ else:
+ raise Exception('Invalid idxsbu value. Exiting.')
+
+ @Jsbu.setter
+ def Jsbu(self, Jsbu):
+ if type(Jsbu) == np.ndarray:
+ self.__idxsbu = J_to_idx_slack(Jsbu)
+ else:
+ raise Exception('Invalid Jsbu value. Exiting.')
+
+ # soft bounds on x at shooting node N
+ @lsbx_e.setter
+ def lsbx_e(self, lsbx_e):
+ if type(lsbx_e) == np.ndarray:
+ self.__lsbx_e = lsbx_e
+ else:
+ raise Exception('Invalid lsbx_e value. Exiting.')
+
+ @usbx_e.setter
+ def usbx_e(self, usbx_e):
+ if type(usbx_e) == np.ndarray:
+ self.__usbx_e = usbx_e
+ else:
+ raise Exception('Invalid usbx_e value. Exiting.')
+
+ @idxsbx_e.setter
+ def idxsbx_e(self, idxsbx_e):
+ if type(idxsbx_e) == np.ndarray:
+ self.__idxsbx_e = idxsbx_e
+ else:
+ raise Exception('Invalid idxsbx_e value. Exiting.')
+
+ @Jsbx_e.setter
+ def Jsbx_e(self, Jsbx_e):
+ if type(Jsbx_e) == np.ndarray:
+ self.__idxsbx_e = J_to_idx_slack(Jsbx_e)
+ else:
+ raise Exception('Invalid Jsbx_e value. Exiting.')
+
+
+ # soft bounds on general linear constraints
+ @lsg.setter
+ def lsg(self, lsg):
+ if isinstance(lsg, np.ndarray):
+ self.__lsg = lsg
+ else:
+ raise Exception('Invalid lsg value. Exiting.')
+
+ @usg.setter
+ def usg(self, usg):
+ if isinstance(usg, np.ndarray):
+ self.__usg = usg
+ else:
+ raise Exception('Invalid usg value. Exiting.')
+
+ @idxsg.setter
+ def idxsg(self, idxsg):
+ if isinstance(idxsg, np.ndarray):
+ self.__idxsg = idxsg
+ else:
+ raise Exception('Invalid idxsg value. Exiting.')
+
+ @Jsg.setter
+ def Jsg(self, Jsg):
+ if isinstance(Jsg, np.ndarray):
+ self.__idxsg = J_to_idx_slack(Jsg)
+ else:
+ raise Exception('Invalid Jsg value, expected numpy array. Exiting.')
+
+
+ # soft bounds on nonlinear constraints
+ @lsh.setter
+ def lsh(self, lsh):
+ if type(lsh) == np.ndarray:
+ self.__lsh = lsh
+ else:
+ raise Exception('Invalid lsh value. Exiting.')
+
+ @ush.setter
+ def ush(self, ush):
+ if type(ush) == np.ndarray:
+ self.__ush = ush
+ else:
+ raise Exception('Invalid ush value. Exiting.')
+
+ @idxsh.setter
+ def idxsh(self, idxsh):
+ if type(idxsh) == np.ndarray:
+ self.__idxsh = idxsh
+ else:
+ raise Exception('Invalid idxsh value. Exiting.')
+
+
+ @Jsh.setter
+ def Jsh(self, Jsh):
+ if isinstance(Jsh, np.ndarray):
+ self.__idxsh = J_to_idx_slack(Jsh)
+ else:
+ raise Exception('Invalid Jsh value, expected numpy array. Exiting.')
+
+ # soft bounds on convex-over-nonlinear constraints
+ @lsphi.setter
+ def lsphi(self, lsphi):
+ if type(lsphi) == np.ndarray:
+ self.__lsphi = lsphi
+ else:
+ raise Exception('Invalid lsphi value. Exiting.')
+
+ @usphi.setter
+ def usphi(self, usphi):
+ if type(usphi) == np.ndarray:
+ self.__usphi = usphi
+ else:
+ raise Exception('Invalid usphi value. Exiting.')
+
+ @idxsphi.setter
+ def idxsphi(self, idxsphi):
+ if type(idxsphi) == np.ndarray:
+ self.__idxsphi = idxsphi
+ else:
+ raise Exception('Invalid idxsphi value. Exiting.')
+
+ @Jsphi.setter
+ def Jsphi(self, Jsphi):
+ if isinstance(Jsphi, np.ndarray):
+ self.__idxsphi = J_to_idx_slack(Jsphi)
+ else:
+ raise Exception('Invalid Jsphi value, expected numpy array. Exiting.')
+
+ # soft bounds on general linear constraints at shooting node N
+ @lsg_e.setter
+ def lsg_e(self, lsg_e):
+ if isinstance(lsg_e, np.ndarray):
+ self.__lsg_e = lsg_e
+ else:
+ raise Exception('Invalid lsg_e value. Exiting.')
+
+ @usg_e.setter
+ def usg_e(self, usg_e):
+ if isinstance(usg_e, np.ndarray):
+ self.__usg_e = usg_e
+ else:
+ raise Exception('Invalid usg_e value. Exiting.')
+
+ @idxsg_e.setter
+ def idxsg_e(self, idxsg_e):
+ if isinstance(idxsg_e, np.ndarray):
+ self.__idxsg_e = idxsg_e
+ else:
+ raise Exception('Invalid idxsg_e value. Exiting.')
+
+ @Jsg_e.setter
+ def Jsg_e(self, Jsg_e):
+ if isinstance(Jsg_e, np.ndarray):
+ self.__idxsg_e = J_to_idx_slack(Jsg_e)
+ else:
+ raise Exception('Invalid Jsg_e value, expected numpy array. Exiting.')
+
+ # soft bounds on nonlinear constraints at shooting node N
+ @lsh_e.setter
+ def lsh_e(self, lsh_e):
+ if isinstance(lsh_e, np.ndarray):
+ self.__lsh_e = lsh_e
+ else:
+ raise Exception('Invalid lsh_e value. Exiting.')
+
+ @ush_e.setter
+ def ush_e(self, ush_e):
+ if isinstance(ush_e, np.ndarray):
+ self.__ush_e = ush_e
+ else:
+ raise Exception('Invalid ush_e value. Exiting.')
+
+ @idxsh_e.setter
+ def idxsh_e(self, idxsh_e):
+ if isinstance(idxsh_e, np.ndarray):
+ self.__idxsh_e = idxsh_e
+ else:
+ raise Exception('Invalid idxsh_e value. Exiting.')
+
+ @Jsh_e.setter
+ def Jsh_e(self, Jsh_e):
+ if isinstance(Jsh_e, np.ndarray):
+ self.__idxsh_e = J_to_idx_slack(Jsh_e)
+ else:
+ raise Exception('Invalid Jsh_e value, expected numpy array. Exiting.')
+
+
+ # soft bounds on convex-over-nonlinear constraints at shooting node N
+ @lsphi_e.setter
+ def lsphi_e(self, lsphi_e):
+ if isinstance(lsphi_e, np.ndarray):
+ self.__lsphi_e = lsphi_e
+ else:
+ raise Exception('Invalid lsphi_e value. Exiting.')
+
+ @usphi_e.setter
+ def usphi_e(self, usphi_e):
+ if isinstance(usphi_e, np.ndarray):
+ self.__usphi_e = usphi_e
+ else:
+ raise Exception('Invalid usphi_e value. Exiting.')
+
+ @idxsphi_e.setter
+ def idxsphi_e(self, idxsphi_e):
+ if isinstance(idxsphi_e, np.ndarray):
+ self.__idxsphi_e = idxsphi_e
+ else:
+ raise Exception('Invalid idxsphi_e value. Exiting.')
+
+ @Jsphi_e.setter
+ def Jsphi_e(self, Jsphi_e):
+ if isinstance(Jsphi_e, np.ndarray):
+ self.__idxsphi_e = J_to_idx_slack(Jsphi_e)
+ else:
+ raise Exception('Invalid Jsphi_e value. Exiting.')
+
+ def set(self, attr, value):
+ setattr(self, attr, value)
+
+
+class AcadosOcpOptions:
+ """
+ class containing the description of the solver options
+ """
+ def __init__(self):
+ self.__qp_solver = 'PARTIAL_CONDENSING_HPIPM' # qp solver to be used in the NLP solver
+ self.__hessian_approx = 'GAUSS_NEWTON' # hessian approximation
+ self.__integrator_type = 'ERK' # integrator type
+ self.__tf = None # prediction horizon
+ self.__nlp_solver_type = 'SQP_RTI' # NLP solver
+ self.__globalization = 'FIXED_STEP'
+ self.__nlp_solver_step_length = 1.0 # fixed Newton step length
+ self.__levenberg_marquardt = 0.0
+ self.__sim_method_num_stages = 4 # number of stages in the integrator
+ self.__sim_method_num_steps = 1 # number of steps in the integrator
+ self.__sim_method_newton_iter = 3 # number of Newton iterations in simulation method
+ self.__sim_method_jac_reuse = 0
+ self.__qp_solver_tol_stat = None # QP solver stationarity tolerance
+ self.__qp_solver_tol_eq = None # QP solver equality tolerance
+ self.__qp_solver_tol_ineq = None # QP solver inequality
+ self.__qp_solver_tol_comp = None # QP solver complementarity
+ self.__qp_solver_iter_max = 50 # QP solver max iter
+ self.__qp_solver_cond_N = None # QP solver: new horizon after partial condensing
+ self.__qp_solver_warm_start = 0
+ self.__nlp_solver_tol_stat = 1e-6 # NLP solver stationarity tolerance
+ self.__nlp_solver_tol_eq = 1e-6 # NLP solver equality tolerance
+ self.__nlp_solver_tol_ineq = 1e-6 # NLP solver inequality
+ self.__nlp_solver_tol_comp = 1e-6 # NLP solver complementarity
+ self.__nlp_solver_max_iter = 100 # NLP solver maximum number of iterations
+ self.__Tsim = None # automatically calculated as tf/N
+ self.__print_level = 0 # print level
+ self.__initialize_t_slacks = 0 # possible values: 0, 1
+ self.__model_external_shared_lib_dir = None # path to the the .so lib
+ self.__model_external_shared_lib_name = None # name of the the .so lib
+ self.__regularize_method = None
+ self.__time_steps = None
+ self.__shooting_nodes = None
+ self.__exact_hess_cost = 1
+ self.__exact_hess_dyn = 1
+ self.__exact_hess_constr = 1
+ self.__ext_cost_num_hess = 0
+ self.__alpha_min = 0.05
+ self.__alpha_reduction = 0.7
+
+
+ @property
+ def qp_solver(self):
+ """QP solver to be used in the NLP solver.
+ String in ('PARTIAL_CONDENSING_HPIPM', 'FULL_CONDENSING_QPOASES', 'FULL_CONDENSING_HPIPM', 'PARTIAL_CONDENSING_QPDUNES', 'PARTIAL_CONDENSING_OSQP').
+ Default: 'PARTIAL_CONDENSING_HPIPM'.
+ """
+ return self.__qp_solver
+
+ @property
+ def hessian_approx(self):
+ """Hessian approximation.
+ String in ('GAUSS_NEWTON', 'EXACT').
+ Default: 'GAUSS_NEWTON'.
+ """
+ return self.__hessian_approx
+
+ @property
+ def integrator_type(self):
+ """
+ Integrator type.
+ String in ('ERK', 'IRK', 'GNSF', 'DISCRETE', 'LIFTED_IRK').
+ Default: 'ERK'.
+ """
+ return self.__integrator_type
+
+ @property
+ def nlp_solver_type(self):
+ """NLP solver.
+ String in ('SQP', 'SQP_RTI').
+ Default: 'SQP_RTI'.
+ """
+ return self.__nlp_solver_type
+
+ @property
+ def globalization(self):
+ """Globalization type.
+ String in ('FIXED_STEP', 'MERIT_BACKTRACKING').
+ Default: 'FIXED_STEP'.
+
+ .. note:: preliminary implementation.
+ """
+ return self.__globalization
+
+ @property
+ def regularize_method(self):
+ """Regularization method for the Hessian.
+ String in ('NO_REGULARIZE', 'MIRROR', 'PROJECT', 'PROJECT_REDUC_HESS', 'CONVEXIFY') or :code:`None`.
+
+ Default: :code:`None`.
+ """
+ return self.__regularize_method
+
+ @property
+ def nlp_solver_step_length(self):
+ """
+ Fixed Newton step length.
+ Type: float > 0.
+ Default: 1.0.
+ """
+ return self.__nlp_solver_step_length
+
+ @property
+ def levenberg_marquardt(self):
+ """
+ Factor for LM regularization.
+ Type: float >= 0
+ Default: 0.0.
+ """
+ return self.__levenberg_marquardt
+
+ @property
+ def sim_method_num_stages(self):
+ """
+ Number of stages in the integrator.
+ Type: int > 0 or ndarray of ints > 0 of shape (N,).
+ Default: 4
+ """
+ return self.__sim_method_num_stages
+
+ @property
+ def sim_method_num_steps(self):
+ """
+ Number of steps in the integrator.
+ Type: int > 0 or ndarray of ints > 0 of shape (N,).
+ Default: 1
+ """
+ return self.__sim_method_num_steps
+
+ @property
+ def sim_method_newton_iter(self):
+ """
+ Number of Newton iterations in simulation method.
+ Type: int > 0
+ Default: 3
+ """
+ return self.__sim_method_newton_iter
+
+ @property
+ def sim_method_jac_reuse(self):
+ """
+ Integer determining if jacobians are reused within integrator or ndarray of ints > 0 of shape (N,).
+ 0: False (no reuse); 1: True (reuse)
+ Default: 0
+ """
+ return self.__sim_method_jac_reuse
+
+ @property
+ def qp_solver_tol_stat(self):
+ """
+ QP solver stationarity tolerance.
+ Default: :code:`None`
+ """
+ return self.__qp_solver_tol_stat
+
+ @property
+ def qp_solver_tol_eq(self):
+ """
+ QP solver equality tolerance.
+ Default: :code:`None`
+ """
+ return self.__qp_solver_tol_eq
+
+ @property
+ def qp_solver_tol_ineq(self):
+ """
+ QP solver inequality.
+ Default: :code:`None`
+ """
+ return self.__qp_solver_tol_ineq
+
+ @property
+ def qp_solver_tol_comp(self):
+ """
+ QP solver complementarity.
+ Default: :code:`None`
+ """
+ return self.__qp_solver_tol_comp
+
+ @property
+ def qp_solver_cond_N(self):
+ """QP solver: New horizon after partial condensing.
+ Set to N by default -> no condensing."""
+ return self.__qp_solver_cond_N
+
+ @property
+ def qp_solver_warm_start(self):
+ """QP solver: Warm starting.
+ 0: no warm start; 1: warm start; 2: hot start."""
+ return self.__qp_solver_warm_start
+
+ @property
+ def qp_solver_iter_max(self):
+ """
+ QP solver: maximum number of iterations.
+ Type: int > 0
+ Default: 50
+ """
+ return self.__qp_solver_iter_max
+
+ @property
+ def tol(self):
+ """
+ NLP solver tolerance. Sets or gets the max of :py:attr:`nlp_solver_tol_eq`,
+ :py:attr:`nlp_solver_tol_ineq`, :py:attr:`nlp_solver_tol_comp`
+ and :py:attr:`nlp_solver_tol_stat`.
+ """
+ return max([self.__nlp_solver_tol_eq, self.__nlp_solver_tol_ineq,\
+ self.__nlp_solver_tol_comp, self.__nlp_solver_tol_stat])
+
+ @property
+ def qp_tol(self):
+ """
+ QP solver tolerance.
+ Sets all of the following at once or gets the max of
+ :py:attr:`qp_solver_tol_eq`, :py:attr:`qp_solver_tol_ineq`,
+ :py:attr:`qp_solver_tol_comp` and
+ :py:attr:`qp_solver_tol_stat`.
+ """
+ return max([self.__qp_solver_tol_eq, self.__qp_solver_tol_ineq,\
+ self.__qp_solver_tol_comp, self.__qp_solver_tol_stat])
+
+ @property
+ def nlp_solver_tol_stat(self):
+ """
+ NLP solver stationarity tolerance.
+ Type: float > 0
+ Default: 1e-6
+ """
+ return self.__nlp_solver_tol_stat
+
+ @property
+ def nlp_solver_tol_eq(self):
+ """NLP solver equality tolerance"""
+ return self.__nlp_solver_tol_eq
+
+ @property
+ def alpha_min(self):
+ """Minimal step size for globalization MERIT_BACKTRACKING, default: 0.05."""
+ return self.__alpha_min
+
+ @property
+ def alpha_reduction(self):
+ """Step size reduction factor for globalization MERIT_BACKTRACKING, default: 0.7."""
+ return self.__alpha_reduction
+
+ @property
+ def nlp_solver_tol_ineq(self):
+ """NLP solver inequality tolerance"""
+ return self.__nlp_solver_tol_ineq
+
+ @property
+ def nlp_solver_tol_comp(self):
+ """NLP solver complementarity tolerance"""
+ return self.__nlp_solver_tol_comp
+
+ @property
+ def nlp_solver_max_iter(self):
+ """
+ NLP solver maximum number of iterations.
+ Type: int > 0
+ Default: 100
+ """
+ return self.__nlp_solver_max_iter
+
+ @property
+ def time_steps(self):
+ """
+ Vector with time steps between the shooting nodes. Set automatically to uniform discretization if :py:attr:`N` and :py:attr:`tf` are provided.
+ Default: :code:`None`
+ """
+ return self.__time_steps
+
+ @property
+ def shooting_nodes(self):
+ """
+ Vector with the shooting nodes, time_steps will be computed from it automatically.
+ Default: :code:`None`
+ """
+ return self.__shooting_nodes
+
+ @property
+ def tf(self):
+ """
+ Prediction horizon
+ Type: float > 0
+ Default: :code:`None`
+ """
+ return self.__tf
+
+ @property
+ def Tsim(self):
+ """
+ Time horizon for one integrator step. Automatically calculated as :py:attr:`tf`/:py:attr:`N`.
+ Default: :code:`None`
+ """
+ return self.__Tsim
+
+ @property
+ def print_level(self):
+ """
+ Verbosity of printing.
+ Type: int >= 0
+ Default: 0
+ """
+ return self.__print_level
+
+ @property
+ def model_external_shared_lib_dir(self):
+ """Path to the .so lib"""
+ return self.__model_external_shared_lib_dir
+
+ @property
+ def model_external_shared_lib_name(self):
+ """Name of the .so lib"""
+ return self.__model_external_shared_lib_name
+
+ @property
+ def exact_hess_constr(self):
+ """
+ Used in case of hessian_approx == 'EXACT'.\n
+ Can be used to turn off exact hessian contributions from the constraints module.
+ """
+ return self.__exact_hess_constr
+
+ @property
+ def exact_hess_cost(self):
+ """
+ Used in case of hessian_approx == 'EXACT'.\n
+ Can be used to turn off exact hessian contributions from the cost module.
+ """
+ return self.__exact_hess_cost
+
+ @property
+ def exact_hess_dyn(self):
+ """
+ Used in case of hessian_approx == 'EXACT'.\n
+ Can be used to turn off exact hessian contributions from the dynamics module.
+ """
+ return self.__exact_hess_dyn
+
+ @property
+ def ext_cost_num_hess(self):
+ """
+ Determines if custom hessian approximation for cost contribution is used (> 0).\n
+ Or if hessian contribution is evaluated exactly using CasADi external function (=0 - default).
+ """
+ return self.__ext_cost_num_hess
+
+ @qp_solver.setter
+ def qp_solver(self, qp_solver):
+ qp_solvers = ('PARTIAL_CONDENSING_HPIPM', \
+ 'FULL_CONDENSING_QPOASES', 'FULL_CONDENSING_HPIPM', \
+ 'PARTIAL_CONDENSING_QPDUNES', 'PARTIAL_CONDENSING_OSQP')
+ if qp_solver in qp_solvers:
+ self.__qp_solver = qp_solver
+ else:
+ raise Exception('Invalid qp_solver value. Possible values are:\n\n' \
+ + ',\n'.join(qp_solvers) + '.\n\nYou have: ' + qp_solver + '.\n\nExiting.')
+
+ @regularize_method.setter
+ def regularize_method(self, regularize_method):
+ regularize_methods = ('NO_REGULARIZE', 'MIRROR', 'PROJECT', \
+ 'PROJECT_REDUC_HESS', 'CONVEXIFY')
+ if regularize_method in regularize_methods:
+ self.__regularize_method = regularize_method
+ else:
+ raise Exception('Invalid regularize_method value. Possible values are:\n\n' \
+ + ',\n'.join(regularize_methods) + '.\n\nYou have: ' + regularize_method + '.\n\nExiting.')
+
+ @hessian_approx.setter
+ def hessian_approx(self, hessian_approx):
+ hessian_approxs = ('GAUSS_NEWTON', 'EXACT')
+ if hessian_approx in hessian_approxs:
+ self.__hessian_approx = hessian_approx
+ else:
+ raise Exception('Invalid hessian_approx value. Possible values are:\n\n' \
+ + ',\n'.join(hessian_approxs) + '.\n\nYou have: ' + hessian_approx + '.\n\nExiting.')
+
+ @integrator_type.setter
+ def integrator_type(self, integrator_type):
+ integrator_types = ('ERK', 'IRK', 'GNSF', 'DISCRETE', 'LIFTED_IRK')
+ if integrator_type in integrator_types:
+ self.__integrator_type = integrator_type
+ else:
+ raise Exception('Invalid integrator_type value. Possible values are:\n\n' \
+ + ',\n'.join(integrator_types) + '.\n\nYou have: ' + integrator_type + '.\n\nExiting.')
+
+ @tf.setter
+ def tf(self, tf):
+ self.__tf = tf
+
+ @time_steps.setter
+ def time_steps(self, time_steps):
+ self.__time_steps = time_steps
+
+ @shooting_nodes.setter
+ def shooting_nodes(self, shooting_nodes):
+ self.__shooting_nodes = shooting_nodes
+
+
+ @Tsim.setter
+ def Tsim(self, Tsim):
+ self.__Tsim = Tsim
+
+ @globalization.setter
+ def globalization(self, globalization):
+ self.__globalization = globalization
+
+ @alpha_min.setter
+ def alpha_min(self, alpha_min):
+ self.__alpha_min = alpha_min
+
+ @alpha_reduction.setter
+ def alpha_reduction(self, alpha_reduction):
+ self.__alpha_reduction = alpha_reduction
+
+ @sim_method_num_stages.setter
+ def sim_method_num_stages(self, sim_method_num_stages):
+
+ # if type(sim_method_num_stages) == int:
+ # self.__sim_method_num_stages = sim_method_num_stages
+ # else:
+ # raise Exception('Invalid sim_method_num_stages value. sim_method_num_stages must be an integer. Exiting.')
+
+ self.__sim_method_num_stages = sim_method_num_stages
+
+ @sim_method_num_steps.setter
+ def sim_method_num_steps(self, sim_method_num_steps):
+
+ # if type(sim_method_num_steps) == int:
+ # self.__sim_method_num_steps = sim_method_num_steps
+ # else:
+ # raise Exception('Invalid sim_method_num_steps value. sim_method_num_steps must be an integer. Exiting.')
+ self.__sim_method_num_steps = sim_method_num_steps
+
+
+ @sim_method_newton_iter.setter
+ def sim_method_newton_iter(self, sim_method_newton_iter):
+
+ if type(sim_method_newton_iter) == int:
+ self.__sim_method_newton_iter = sim_method_newton_iter
+ else:
+ raise Exception('Invalid sim_method_newton_iter value. sim_method_newton_iter must be an integer. Exiting.')
+
+ @sim_method_jac_reuse.setter
+ def sim_method_jac_reuse(self, sim_method_jac_reuse):
+ # if sim_method_jac_reuse in (True, False):
+ self.__sim_method_jac_reuse = sim_method_jac_reuse
+ # else:
+ # raise Exception('Invalid sim_method_jac_reuse value. sim_method_jac_reuse must be a Boolean.')
+
+ @nlp_solver_type.setter
+ def nlp_solver_type(self, nlp_solver_type):
+ nlp_solver_types = ('SQP', 'SQP_RTI')
+ if nlp_solver_type in nlp_solver_types:
+ self.__nlp_solver_type = nlp_solver_type
+ else:
+ raise Exception('Invalid nlp_solver_type value. Possible values are:\n\n' \
+ + ',\n'.join(nlp_solver_types) + '.\n\nYou have: ' + nlp_solver_type + '.\n\nExiting.')
+
+ @nlp_solver_step_length.setter
+ def nlp_solver_step_length(self, nlp_solver_step_length):
+ if type(nlp_solver_step_length) == float and nlp_solver_step_length > 0:
+ self.__nlp_solver_step_length = nlp_solver_step_length
+ else:
+ raise Exception('Invalid nlp_solver_step_length value. nlp_solver_step_length must be a positive float. Exiting')
+
+ @levenberg_marquardt.setter
+ def levenberg_marquardt(self, levenberg_marquardt):
+ if isinstance(levenberg_marquardt, float) and levenberg_marquardt >= 0:
+ self.__levenberg_marquardt = levenberg_marquardt
+ else:
+ raise Exception('Invalid levenberg_marquardt value. levenberg_marquardt must be a positive float. Exiting')
+
+ @qp_solver_iter_max.setter
+ def qp_solver_iter_max(self, qp_solver_iter_max):
+ if isinstance(qp_solver_iter_max, int) and qp_solver_iter_max > 0:
+ self.__qp_solver_iter_max = qp_solver_iter_max
+ else:
+ raise Exception('Invalid qp_solver_iter_max value. qp_solver_iter_max must be a positive int. Exiting')
+
+ @qp_solver_cond_N.setter
+ def qp_solver_cond_N(self, qp_solver_cond_N):
+ if isinstance(qp_solver_cond_N, int) and qp_solver_cond_N > 0:
+ self.__qp_solver_cond_N = qp_solver_cond_N
+ else:
+ raise Exception('Invalid qp_solver_cond_N value. qp_solver_cond_N must be a positive int. Exiting')
+
+ @qp_solver_warm_start.setter
+ def qp_solver_warm_start(self, qp_solver_warm_start):
+ if qp_solver_warm_start in [0, 1, 2]:
+ self.__qp_solver_warm_start = qp_solver_warm_start
+ else:
+ raise Exception('Invalid qp_solver_warm_start value. qp_solver_warm_start must be 0 or 1 or 2. Exiting')
+
+ @qp_tol.setter
+ def qp_tol(self, qp_tol):
+ if isinstance(qp_tol, float) and qp_tol > 0:
+ self.__qp_solver_tol_eq = qp_tol
+ self.__qp_solver_tol_ineq = qp_tol
+ self.__qp_solver_tol_stat = qp_tol
+ self.__qp_solver_tol_comp = qp_tol
+ else:
+ raise Exception('Invalid qp_tol value. qp_tol must be a positive float. Exiting')
+
+ @qp_solver_tol_stat.setter
+ def qp_solver_tol_stat(self, qp_solver_tol_stat):
+ if isinstance(qp_solver_tol_stat, float) and qp_solver_tol_stat > 0:
+ self.__qp_solver_tol_stat = qp_solver_tol_stat
+ else:
+ raise Exception('Invalid qp_solver_tol_stat value. qp_solver_tol_stat must be a positive float. Exiting')
+
+ @qp_solver_tol_eq.setter
+ def qp_solver_tol_eq(self, qp_solver_tol_eq):
+ if isinstance(qp_solver_tol_eq, float) and qp_solver_tol_eq > 0:
+ self.__qp_solver_tol_eq = qp_solver_tol_eq
+ else:
+ raise Exception('Invalid qp_solver_tol_eq value. qp_solver_tol_eq must be a positive float. Exiting')
+
+ @qp_solver_tol_ineq.setter
+ def qp_solver_tol_ineq(self, qp_solver_tol_ineq):
+ if isinstance(qp_solver_tol_ineq, float) and qp_solver_tol_ineq > 0:
+ self.__qp_solver_tol_ineq = qp_solver_tol_ineq
+ else:
+ raise Exception('Invalid qp_solver_tol_ineq value. qp_solver_tol_ineq must be a positive float. Exiting')
+
+ @qp_solver_tol_comp.setter
+ def qp_solver_tol_comp(self, qp_solver_tol_comp):
+ if isinstance(qp_solver_tol_comp, float) and qp_solver_tol_comp > 0:
+ self.__qp_solver_tol_comp = qp_solver_tol_comp
+ else:
+ raise Exception('Invalid qp_solver_tol_comp value. qp_solver_tol_comp must be a positive float. Exiting')
+
+ @tol.setter
+ def tol(self, tol):
+ if isinstance(tol, float) and tol > 0:
+ self.__nlp_solver_tol_eq = tol
+ self.__nlp_solver_tol_ineq = tol
+ self.__nlp_solver_tol_stat = tol
+ self.__nlp_solver_tol_comp = tol
+ else:
+ raise Exception('Invalid tol value. tol must be a positive float. Exiting')
+
+ @nlp_solver_tol_stat.setter
+ def nlp_solver_tol_stat(self, nlp_solver_tol_stat):
+ if isinstance(nlp_solver_tol_stat, float) and nlp_solver_tol_stat > 0:
+ self.__nlp_solver_tol_stat = nlp_solver_tol_stat
+ else:
+ raise Exception('Invalid nlp_solver_tol_stat value. nlp_solver_tol_stat must be a positive float. Exiting')
+
+ @nlp_solver_tol_eq.setter
+ def nlp_solver_tol_eq(self, nlp_solver_tol_eq):
+ if isinstance(nlp_solver_tol_eq, float) and nlp_solver_tol_eq > 0:
+ self.__nlp_solver_tol_eq = nlp_solver_tol_eq
+ else:
+ raise Exception('Invalid nlp_solver_tol_eq value. nlp_solver_tol_eq must be a positive float. Exiting')
+
+ @nlp_solver_tol_ineq.setter
+ def nlp_solver_tol_ineq(self, nlp_solver_tol_ineq):
+ if isinstance(nlp_solver_tol_ineq, float) and nlp_solver_tol_ineq > 0:
+ self.__nlp_solver_tol_ineq = nlp_solver_tol_ineq
+ else:
+ raise Exception('Invalid nlp_solver_tol_ineq value. nlp_solver_tol_ineq must be a positive float. Exiting')
+
+ @nlp_solver_tol_comp.setter
+ def nlp_solver_tol_comp(self, nlp_solver_tol_comp):
+ if isinstance(nlp_solver_tol_comp, float) and nlp_solver_tol_comp > 0:
+ self.__nlp_solver_tol_comp = nlp_solver_tol_comp
+ else:
+ raise Exception('Invalid nlp_solver_tol_comp value. nlp_solver_tol_comp must be a positive float. Exiting')
+
+ @nlp_solver_max_iter.setter
+ def nlp_solver_max_iter(self, nlp_solver_max_iter):
+
+ if type(nlp_solver_max_iter) == int and nlp_solver_max_iter > 0:
+ self.__nlp_solver_max_iter = nlp_solver_max_iter
+ else:
+ raise Exception('Invalid nlp_solver_max_iter value. nlp_solver_max_iter must be a positive int. Exiting')
+
+ @print_level.setter
+ def print_level(self, print_level):
+ if type(print_level) == int and print_level >= 0:
+ self.__print_level = print_level
+ else:
+ raise Exception('Invalid print_level value. print_level takes one of the values >=0. Exiting')
+
+ @model_external_shared_lib_dir.setter
+ def model_external_shared_lib_dir(self, model_external_shared_lib_dir):
+ if type(model_external_shared_lib_dir) == str :
+ self.__model_external_shared_lib_dir = model_external_shared_lib_dir
+ else:
+ raise Exception('Invalid model_external_shared_lib_dir value. Str expected.' \
+ + '.\n\nYou have: ' + type(model_external_shared_lib_dir) + '.\n\nExiting.')
+
+ @model_external_shared_lib_name.setter
+ def model_external_shared_lib_name(self, model_external_shared_lib_name):
+ if type(model_external_shared_lib_name) == str :
+ if model_external_shared_lib_name[-3:] == '.so' :
+ raise Exception('Invalid model_external_shared_lib_name value. Remove the .so extension.' \
+ + '.\n\nYou have: ' + type(model_external_shared_lib_name) + '.\n\nExiting.')
+ else :
+ self.__model_external_shared_lib_name = model_external_shared_lib_name
+ else:
+ raise Exception('Invalid model_external_shared_lib_name value. Str expected.' \
+ + '.\n\nYou have: ' + type(model_external_shared_lib_name) + '.\n\nExiting.')
+
+ @exact_hess_constr.setter
+ def exact_hess_constr(self, exact_hess_constr):
+ if exact_hess_constr in [0, 1]:
+ self.__exact_hess_constr = exact_hess_constr
+ else:
+ raise Exception('Invalid exact_hess_constr value. exact_hess_constr takes one of the values 0, 1. Exiting')
+
+ @exact_hess_cost.setter
+ def exact_hess_cost(self, exact_hess_cost):
+ if exact_hess_cost in [0, 1]:
+ self.__exact_hess_cost = exact_hess_cost
+ else:
+ raise Exception('Invalid exact_hess_cost value. exact_hess_cost takes one of the values 0, 1. Exiting')
+
+ @exact_hess_dyn.setter
+ def exact_hess_dyn(self, exact_hess_dyn):
+ if exact_hess_dyn in [0, 1]:
+ self.__exact_hess_dyn = exact_hess_dyn
+ else:
+ raise Exception('Invalid exact_hess_dyn value. exact_hess_dyn takes one of the values 0, 1. Exiting')
+
+ @ext_cost_num_hess.setter
+ def ext_cost_num_hess(self, ext_cost_num_hess):
+ if ext_cost_num_hess in [0, 1]:
+ self.__ext_cost_num_hess = ext_cost_num_hess
+ else:
+ raise Exception('Invalid ext_cost_num_hess value. ext_cost_num_hess takes one of the values 0, 1. Exiting')
+
+ def set(self, attr, value):
+ setattr(self, attr, value)
+
+
+class AcadosOcp:
+ """
+ Class containing the full description of the optimal control problem.
+ This object can be used to create an :py:class:`acados_template.acados_ocp_solver.AcadosOcpSolver`.
+
+ The class has the following properties that can be modified to formulate a specific OCP, see below:
+
+ - :py:attr:`dims` of type :py:class:`acados_template.acados_ocp.AcadosOcpDims`
+ - :py:attr:`model` of type :py:class:`acados_template.acados_model.AcadosModel`
+ - :py:attr:`cost` of type :py:class:`acados_template.acados_ocp.AcadosOcpCost`
+ - :py:attr:`constraints` of type :py:class:`acados_template.acados_ocp.AcadosOcpConstraints`
+ - :py:attr:`solver_options` of type :py:class:`acados_template.acados_ocp.AcadosOcpOptions`
+
+ - :py:attr:`acados_include_path` (set automatically)
+ - :py:attr:`acados_lib_path` (set automatically)
+ - :py:attr:`parameter_values` - used to initialize the parameters (can be changed)
+ """
+ def __init__(self, acados_path=''):
+ """
+ Keyword arguments:
+ acados_path -- path of your acados installation
+ """
+ if acados_path == '':
+ acados_path = get_acados_path()
+
+ self.dims = AcadosOcpDims()
+ """Dimension definitions, type :py:class:`acados_template.acados_ocp.AcadosOcpDims`"""
+ self.model = AcadosModel()
+ """Model definitions, type :py:class:`acados_template.acados_model.AcadosModel`"""
+ self.cost = AcadosOcpCost()
+ """Cost definitions, type :py:class:`acados_template.acados_ocp.AcadosOcpCost`"""
+ self.constraints = AcadosOcpConstraints()
+ """Constraints definitions, type :py:class:`acados_template.acados_ocp.AcadosOcpConstraints`"""
+ self.solver_options = AcadosOcpOptions()
+ """Solver Options, type :py:class:`acados_template.acados_ocp.AcadosOcpOptions`"""
+
+ self.acados_include_path = f'{acados_path}/include'
+ """Path to acados include directory, type: string"""
+ self.acados_lib_path = f'{acados_path}/lib'
+ """Path to where acados library is located, type: string"""
+
+ self.__parameter_values = np.array([])
+ self.__problem_class = 'OCP'
+
+ self.code_export_directory = 'c_generated_code'
+ """Path to where code will be exported. Default: `c_generated_code`."""
+
+ @property
+ def parameter_values(self):
+ """:math:`p` - initial values for parameter - can be updated stagewise"""
+ return self.__parameter_values
+
+ @parameter_values.setter
+ def parameter_values(self, parameter_values):
+ if isinstance(parameter_values, np.ndarray):
+ self.__parameter_values = parameter_values
+ else:
+ raise Exception('Invalid parameter_values value. ' +
+ f'Expected numpy array, got {type(parameter_values)}.')
+
+ def set(self, attr, value):
+ # tokenize string
+ tokens = attr.split('_', 1)
+ if len(tokens) > 1:
+ setter_to_call = getattr(getattr(self, tokens[0]), 'set')
+ else:
+ setter_to_call = getattr(self, 'set')
+
+ setter_to_call(tokens[1], value)
+
+ return
diff --git a/pyextra/acados_template/acados_ocp_solver.py b/pyextra/acados_template/acados_ocp_solver.py
new file mode 100644
index 000000000..4e80e1205
--- /dev/null
+++ b/pyextra/acados_template/acados_ocp_solver.py
@@ -0,0 +1,1388 @@
+# -*- coding: future_fstrings -*-
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import sys
+import os
+import json
+import numpy as np
+from datetime import datetime
+import ctypes
+from ctypes import POINTER, cast, CDLL, c_void_p, c_char_p, c_double, c_int, c_int64, byref
+
+from copy import deepcopy
+
+from .generate_c_code_explicit_ode import generate_c_code_explicit_ode
+from .generate_c_code_implicit_ode import generate_c_code_implicit_ode
+from .generate_c_code_gnsf import generate_c_code_gnsf
+from .generate_c_code_discrete_dynamics import generate_c_code_discrete_dynamics
+from .generate_c_code_constraint import generate_c_code_constraint
+from .generate_c_code_nls_cost import generate_c_code_nls_cost
+from .generate_c_code_external_cost import generate_c_code_external_cost
+from .acados_ocp import AcadosOcp
+from .acados_model import acados_model_strip_casadi_symbolics
+from .utils import is_column, is_empty, casadi_length, render_template, acados_class2dict,\
+ format_class_dict, ocp_check_against_layout, np_array_to_list, make_model_consistent,\
+ set_up_imported_gnsf_model, get_acados_path
+
+
+def make_ocp_dims_consistent(acados_ocp):
+ dims = acados_ocp.dims
+ cost = acados_ocp.cost
+ constraints = acados_ocp.constraints
+ model = acados_ocp.model
+ opts = acados_ocp.solver_options
+
+ # nx
+ if is_column(model.x):
+ dims.nx = casadi_length(model.x)
+ else:
+ raise Exception('model.x should be column vector!')
+
+ # nu
+ if is_empty(model.u):
+ dims.nu = 0
+ else:
+ dims.nu = casadi_length(model.u)
+
+ # nz
+ if is_empty(model.z):
+ dims.nz = 0
+ else:
+ dims.nz = casadi_length(model.z)
+
+ # np
+ if is_empty(model.p):
+ dims.np = 0
+ else:
+ dims.np = casadi_length(model.p)
+ if acados_ocp.parameter_values.shape[0] != dims.np:
+ raise Exception('inconsistent dimension np, regarding model.p and parameter_values.' + \
+ f'\nGot np = {dims.np}, acados_ocp.parameter_values.shape = {acados_ocp.parameter_values.shape[0]}\n')
+
+ # cost
+ # initial stage - if not set, copy fields from path constraints
+ if cost.cost_type_0 is None:
+ cost.cost_type_0 = cost.cost_type
+ cost.W_0 = cost.W
+ cost.Vx_0 = cost.Vx
+ cost.Vu_0 = cost.Vu
+ cost.Vz_0 = cost.Vz
+ cost.yref_0 = cost.yref
+ cost.cost_ext_fun_type_0 = cost.cost_ext_fun_type
+ model.cost_y_expr_0 = model.cost_y_expr
+ model.cost_expr_ext_cost_0 = model.cost_expr_ext_cost
+
+ if cost.cost_type_0 == 'LINEAR_LS':
+ ny_0 = cost.W_0.shape[0]
+ if cost.Vx_0.shape[0] != ny_0 or cost.Vu_0.shape[0] != ny_0:
+ raise Exception('inconsistent dimension ny_0, regarding W_0, Vx_0, Vu_0.' + \
+ f'\nGot W_0[{cost.W_0.shape}], Vx_0[{cost.Vx_0.shape}], Vu_0[{cost.Vu_0.shape}]\n')
+ if dims.nz != 0 and cost.Vz_0.shape[0] != ny_0:
+ raise Exception('inconsistent dimension ny_0, regarding W_0, Vx_0, Vu_0, Vz_0.' + \
+ f'\nGot W_0[{cost.W_0.shape}], Vx_0[{cost.Vx_0.shape}], Vu_0[{cost.Vu_0.shape}], Vz_0[{cost.Vz_0.shape}]\n')
+ if cost.Vx_0.shape[1] != dims.nx and ny_0 != 0:
+ raise Exception('inconsistent dimension: Vx_0 should have nx columns.')
+ if cost.Vu_0.shape[1] != dims.nu and ny_0 != 0:
+ raise Exception('inconsistent dimension: Vu_0 should have nu columns.')
+ if cost.yref_0.shape[0] != ny_0:
+ raise Exception('inconsistent dimension: regarding W_0, yref_0.' + \
+ f'\nGot W_0[{cost.W_0.shape}], yref_0[{cost.yref_0.shape}]\n')
+ dims.ny_0 = ny_0
+
+ elif cost.cost_type_0 == 'NONLINEAR_LS':
+ ny_0 = cost.W_0.shape[0]
+ if is_empty(model.cost_y_expr_0) and ny_0 != 0:
+ raise Exception('inconsistent dimension ny_0: regarding W_0, cost_y_expr.')
+ elif casadi_length(model.cost_y_expr_0) != ny_0:
+ raise Exception('inconsistent dimension ny_0: regarding W_0, cost_y_expr.')
+ if cost.yref_0.shape[0] != ny_0:
+ raise Exception('inconsistent dimension: regarding W_0, yref_0.' + \
+ f'\nGot W_0[{cost.W.shape}], yref_0[{cost.yref_0.shape}]\n')
+ dims.ny_0 = ny_0
+
+ # path
+ if cost.cost_type == 'LINEAR_LS':
+ ny = cost.W.shape[0]
+ if cost.Vx.shape[0] != ny or cost.Vu.shape[0] != ny:
+ raise Exception('inconsistent dimension ny, regarding W, Vx, Vu.' + \
+ f'\nGot W[{cost.W.shape}], Vx[{cost.Vx.shape}], Vu[{cost.Vu.shape}]\n')
+ if dims.nz != 0 and cost.Vz.shape[0] != ny:
+ raise Exception('inconsistent dimension ny, regarding W, Vx, Vu, Vz.' + \
+ f'\nGot W[{cost.W.shape}], Vx[{cost.Vx.shape}], Vu[{cost.Vu.shape}], Vz[{cost.Vz.shape}]\n')
+ if cost.Vx.shape[1] != dims.nx and ny != 0:
+ raise Exception('inconsistent dimension: Vx should have nx columns.')
+ if cost.Vu.shape[1] != dims.nu and ny != 0:
+ raise Exception('inconsistent dimension: Vu should have nu columns.')
+ if cost.yref.shape[0] != ny:
+ raise Exception('inconsistent dimension: regarding W, yref.' + \
+ f'\nGot W[{cost.W.shape}], yref[{cost.yref.shape}]\n')
+ dims.ny = ny
+
+ elif cost.cost_type == 'NONLINEAR_LS':
+ ny = cost.W.shape[0]
+ if is_empty(model.cost_y_expr) and ny != 0:
+ raise Exception('inconsistent dimension ny: regarding W, cost_y_expr.')
+ elif casadi_length(model.cost_y_expr) != ny:
+ raise Exception('inconsistent dimension ny: regarding W, cost_y_expr.')
+ if cost.yref.shape[0] != ny:
+ raise Exception('inconsistent dimension: regarding W, yref.' + \
+ f'\nGot W[{cost.W.shape}], yref[{cost.yref.shape}]\n')
+ dims.ny = ny
+
+ # terminal
+ if cost.cost_type_e == 'LINEAR_LS':
+ ny_e = cost.W_e.shape[0]
+ if cost.Vx_e.shape[0] != ny_e:
+ raise Exception('inconsistent dimension ny_e: regarding W_e, cost_y_expr_e.' + \
+ f'\nGot W_e[{cost.W_e.shape}], Vx_e[{cost.Vx_e.shape}]')
+ if cost.Vx_e.shape[1] != dims.nx and ny_e != 0:
+ raise Exception('inconsistent dimension: Vx_e should have nx columns.')
+ if cost.yref_e.shape[0] != ny_e:
+ raise Exception('inconsistent dimension: regarding W_e, yref_e.')
+ dims.ny_e = ny_e
+
+ elif cost.cost_type_e == 'NONLINEAR_LS':
+ ny_e = cost.W_e.shape[0]
+ if is_empty(model.cost_y_expr_e) and ny_e != 0:
+ raise Exception('inconsistent dimension ny_e: regarding W_e, cost_y_expr_e.')
+ elif casadi_length(model.cost_y_expr_e) != ny_e:
+ raise Exception('inconsistent dimension ny_e: regarding W_e, cost_y_expr_e.')
+ if cost.yref_e.shape[0] != ny_e:
+ raise Exception('inconsistent dimension: regarding W_e, yref_e.')
+ dims.ny_e = ny_e
+
+
+ ## constraints
+ # initial
+ if (constraints.lbx_0 == [] and constraints.ubx_0 == []):
+ dims.nbx_0 = 0
+ else:
+ this_shape = constraints.lbx_0.shape
+ other_shape = constraints.ubx_0.shape
+ if not this_shape == other_shape:
+ raise Exception('lbx_0, ubx_0 have different shapes!')
+ if not is_column(constraints.lbx_0):
+ raise Exception('lbx_0, ubx_0 must be column vectors!')
+ dims.nbx_0 = constraints.lbx_0.size
+
+ if all(constraints.lbx_0 == constraints.ubx_0) and dims.nbx_0 == dims.nx \
+ and dims.nbxe_0 is None \
+ and (constraints.idxbxe_0.shape == constraints.idxbx_0.shape)\
+ and all(constraints.idxbxe_0 == constraints.idxbx_0):
+ # case: x0 was set: nbx0 are all equlities.
+ dims.nbxe_0 = dims.nbx_0
+ elif dims.nbxe_0 is None:
+ # case: x0 was not set -> dont assume nbx0 to be equality constraints.
+ dims.nbxe_0 = 0
+
+ # path
+ nbx = constraints.idxbx.shape[0]
+ if constraints.ubx.shape[0] != nbx or constraints.lbx.shape[0] != nbx:
+ raise Exception('inconsistent dimension nbx, regarding idxbx, ubx, lbx.')
+ else:
+ dims.nbx = nbx
+
+ nbu = constraints.idxbu.shape[0]
+ if constraints.ubu.shape[0] != nbu or constraints.lbu.shape[0] != nbu:
+ raise Exception('inconsistent dimension nbu, regarding idxbu, ubu, lbu.')
+ else:
+ dims.nbu = nbu
+
+ ng = constraints.lg.shape[0]
+ if constraints.ug.shape[0] != ng or constraints.C.shape[0] != ng \
+ or constraints.D.shape[0] != ng:
+ raise Exception('inconsistent dimension ng, regarding lg, ug, C, D.')
+ else:
+ dims.ng = ng
+
+ if not is_empty(model.con_h_expr):
+ nh = casadi_length(model.con_h_expr)
+ else:
+ nh = 0
+
+ if constraints.uh.shape[0] != nh or constraints.lh.shape[0] != nh:
+ raise Exception('inconsistent dimension nh, regarding lh, uh, con_h_expr.')
+ else:
+ dims.nh = nh
+
+ if is_empty(model.con_phi_expr):
+ dims.nphi = 0
+ dims.nr = 0
+ else:
+ dims.nphi = casadi_length(model.con_phi_expr)
+ if is_empty(model.con_r_expr):
+ raise Exception('convex over nonlinear constraints: con_r_expr but con_phi_expr is nonempty')
+ else:
+ dims.nr = casadi_length(model.con_r_expr)
+
+ # terminal
+ nbx_e = constraints.idxbx_e.shape[0]
+ if constraints.ubx_e.shape[0] != nbx_e or constraints.lbx_e.shape[0] != nbx_e:
+ raise Exception('inconsistent dimension nbx_e, regarding idxbx_e, ubx_e, lbx_e.')
+ else:
+ dims.nbx_e = nbx_e
+
+ ng_e = constraints.lg_e.shape[0]
+ if constraints.ug_e.shape[0] != ng_e or constraints.C_e.shape[0] != ng_e:
+ raise Exception('inconsistent dimension ng_e, regarding_e lg_e, ug_e, C_e.')
+ else:
+ dims.ng_e = ng_e
+
+ if not is_empty(model.con_h_expr_e):
+ nh_e = casadi_length(model.con_h_expr_e)
+ else:
+ nh_e = 0
+
+ if constraints.uh_e.shape[0] != nh_e or constraints.lh_e.shape[0] != nh_e:
+ raise Exception('inconsistent dimension nh_e, regarding lh_e, uh_e, con_h_expr_e.')
+ else:
+ dims.nh_e = nh_e
+
+ if is_empty(model.con_phi_expr_e):
+ dims.nphi_e = 0
+ dims.nr_e = 0
+ else:
+ dims.nphi_e = casadi_length(model.con_phi_expr_e)
+ if is_empty(model.con_r_expr_e):
+ raise Exception('convex over nonlinear constraints: con_r_expr_e but con_phi_expr_e is nonempty')
+ else:
+ dims.nr_e = casadi_length(model.con_r_expr_e)
+
+ # Slack dimensions
+ nsbx = constraints.idxsbx.shape[0]
+ if is_empty(constraints.lsbx):
+ constraints.lsbx = np.zeros((nsbx,))
+ elif constraints.lsbx.shape[0] != nsbx:
+ raise Exception('inconsistent dimension nsbx, regarding idxsbx, lsbx.')
+ if is_empty(constraints.usbx):
+ constraints.usbx = np.zeros((nsbx,))
+ elif constraints.usbx.shape[0] != nsbx:
+ raise Exception('inconsistent dimension nsbx, regarding idxsbx, usbx.')
+ dims.nsbx = nsbx
+
+ nsbu = constraints.idxsbu.shape[0]
+ if is_empty(constraints.lsbu):
+ constraints.lsbu = np.zeros((nsbu,))
+ elif constraints.lsbu.shape[0] != nsbu:
+ raise Exception('inconsistent dimension nsbu, regarding idxsbu, lsbu.')
+ if is_empty(constraints.usbu):
+ constraints.usbu = np.zeros((nsbu,))
+ elif constraints.usbu.shape[0] != nsbu:
+ raise Exception('inconsistent dimension nsbu, regarding idxsbu, usbu.')
+ dims.nsbu = nsbu
+
+ nsh = constraints.idxsh.shape[0]
+ if is_empty(constraints.lsh):
+ constraints.lsh = np.zeros((nsh,))
+ elif constraints.lsh.shape[0] != nsh:
+ raise Exception('inconsistent dimension nsh, regarding idxsh, lsh.')
+ if is_empty(constraints.ush):
+ constraints.ush = np.zeros((nsh,))
+ elif constraints.ush.shape[0] != nsh:
+ raise Exception('inconsistent dimension nsh, regarding idxsh, ush.')
+ dims.nsh = nsh
+
+ nsphi = constraints.idxsphi.shape[0]
+ if is_empty(constraints.lsphi):
+ constraints.lsphi = np.zeros((nsphi,))
+ elif constraints.lsphi.shape[0] != nsphi:
+ raise Exception('inconsistent dimension nsphi, regarding idxsphi, lsphi.')
+ if is_empty(constraints.usphi):
+ constraints.usphi = np.zeros((nsphi,))
+ elif constraints.usphi.shape[0] != nsphi:
+ raise Exception('inconsistent dimension nsphi, regarding idxsphi, usphi.')
+ dims.nsphi = nsphi
+
+ nsg = constraints.idxsg.shape[0]
+ if is_empty(constraints.lsg):
+ constraints.lsg = np.zeros((nsg,))
+ elif constraints.lsg.shape[0] != nsg:
+ raise Exception('inconsistent dimension nsg, regarding idxsg, lsg.')
+ if is_empty(constraints.usg):
+ constraints.usg = np.zeros((nsg,))
+ elif constraints.usg.shape[0] != nsg:
+ raise Exception('inconsistent dimension nsg, regarding idxsg, usg.')
+ dims.nsg = nsg
+
+ ns = nsbx + nsbu + nsh + nsg + nsphi
+ wrong_field = ""
+ if cost.Zl.shape[0] != ns:
+ wrong_field = "Zl"
+ dim = cost.Zl.shape[0]
+ elif cost.Zu.shape[0] != ns:
+ wrong_field = "Zu"
+ dim = cost.Zu.shape[0]
+ elif cost.zl.shape[0] != ns:
+ wrong_field = "zl"
+ dim = cost.zl.shape[0]
+ elif cost.zu.shape[0] != ns:
+ wrong_field = "zu"
+ dim = cost.zu.shape[0]
+
+ if wrong_field != "":
+ raise Exception(f'Inconsistent size for field {wrong_field}, with dimension {dim}, \n\t'\
+ + f'Detected ns = {ns} = nsbx + nsbu + nsg + nsh + nsphi.\n\t'\
+ + f'With nsbx = {nsbx}, nsbu = {nsbu}, nsg = {nsg}, nsh = {nsh}, nsphi = {nsphi}')
+
+ dims.ns = ns
+
+ nsbx_e = constraints.idxsbx_e.shape[0]
+ if is_empty(constraints.lsbx_e):
+ constraints.lsbx_e = np.zeros((nsbx_e,))
+ elif constraints.lsbx_e.shape[0] != nsbx_e:
+ raise Exception('inconsistent dimension nsbx_e, regarding idxsbx_e, lsbx_e.')
+ if is_empty(constraints.usbx_e):
+ constraints.usbx_e = np.zeros((nsbx_e,))
+ elif constraints.usbx_e.shape[0] != nsbx_e:
+ raise Exception('inconsistent dimension nsbx_e, regarding idxsbx_e, usbx_e.')
+ dims.nsbx_e = nsbx_e
+
+ nsh_e = constraints.idxsh_e.shape[0]
+ if is_empty(constraints.lsh_e):
+ constraints.lsh_e = np.zeros((nsh_e,))
+ elif constraints.lsh_e.shape[0] != nsh_e:
+ raise Exception('inconsistent dimension nsh_e, regarding idxsh_e, lsh_e.')
+ if is_empty(constraints.ush_e):
+ constraints.ush_e = np.zeros((nsh_e,))
+ elif constraints.ush_e.shape[0] != nsh_e:
+ raise Exception('inconsistent dimension nsh_e, regarding idxsh_e, ush_e.')
+ dims.nsh_e = nsh_e
+
+ nsg_e = constraints.idxsg_e.shape[0]
+ if is_empty(constraints.lsg_e):
+ constraints.lsg_e = np.zeros((nsg_e,))
+ elif constraints.lsg_e.shape[0] != nsg_e:
+ raise Exception('inconsistent dimension nsg_e, regarding idxsg_e, lsg_e.')
+ if is_empty(constraints.usg_e):
+ constraints.usg_e = np.zeros((nsg_e,))
+ elif constraints.usg_e.shape[0] != nsg_e:
+ raise Exception('inconsistent dimension nsg_e, regarding idxsg_e, usg_e.')
+ dims.nsg_e = nsg_e
+
+ nsphi_e = constraints.idxsphi_e.shape[0]
+ if is_empty(constraints.lsphi_e):
+ constraints.lsphi_e = np.zeros((nsphi_e,))
+ elif constraints.lsphi_e.shape[0] != nsphi_e:
+ raise Exception('inconsistent dimension nsphi_e, regarding idxsphi_e, lsphi_e.')
+ if is_empty(constraints.usphi_e):
+ constraints.usphi_e = np.zeros((nsphi_e,))
+ elif constraints.usphi_e.shape[0] != nsphi_e:
+ raise Exception('inconsistent dimension nsphi_e, regarding idxsphi_e, usphi_e.')
+ dims.nsphi_e = nsphi_e
+
+ # terminal
+ ns_e = nsbx_e + nsh_e + nsg_e + nsphi_e
+ wrong_field = ""
+ if cost.Zl_e.shape[0] != ns_e:
+ wrong_field = "Zl_e"
+ dim = cost.Zl_e.shape[0]
+ elif cost.Zu_e.shape[0] != ns_e:
+ wrong_field = "Zu_e"
+ dim = cost.Zu_e.shape[0]
+ elif cost.zl_e.shape[0] != ns_e:
+ wrong_field = "zl_e"
+ dim = cost.zl_e.shape[0]
+ elif cost.zu_e.shape[0] != ns_e:
+ wrong_field = "zu_e"
+ dim = cost.zu_e.shape[0]
+
+ if wrong_field != "":
+ raise Exception(f'Inconsistent size for field {wrong_field}, with dimension {dim}, \n\t'\
+ + f'Detected ns_e = {ns_e} = nsbx_e + nsg_e + nsh_e + nsphi_e.\n\t'\
+ + f'With nsbx_e = {nsbx_e}, nsg_e = {nsg_e}, nsh_e = {nsh_e}, nsphi_e = {nsphi_e}')
+
+ dims.ns_e = ns_e
+
+ # discretization
+ if is_empty(opts.time_steps) and is_empty(opts.shooting_nodes):
+ # uniform discretization
+ opts.time_steps = opts.tf / dims.N * np.ones((dims.N,))
+
+ elif not is_empty(opts.shooting_nodes):
+ if np.shape(opts.shooting_nodes)[0] != dims.N+1:
+ raise Exception('inconsistent dimension N, regarding shooting_nodes.')
+
+ time_steps = np.zeros((dims.N,))
+ for i in range(dims.N):
+ time_steps[i] = opts.shooting_nodes[i+1] - opts.shooting_nodes[i]
+ opts.time_steps = time_steps
+
+ elif (not is_empty(opts.time_steps)) and (not is_empty(opts.shooting_nodes)):
+ Exception('Please provide either time_steps or shooting_nodes for nonuniform discretization')
+
+ tf = np.sum(opts.time_steps)
+ if (tf - opts.tf) / tf > 1e-15:
+ raise Exception(f'Inconsistent discretization: {opts.tf}'\
+ f' = tf != sum(opts.time_steps) = {tf}.')
+
+ # num_steps
+ if isinstance(opts.sim_method_num_steps, np.ndarray) and opts.sim_method_num_steps.size == 1:
+ opts.sim_method_num_steps = opts.sim_method_num_steps.item()
+
+ if isinstance(opts.sim_method_num_steps, (int, float)) and opts.sim_method_num_steps % 1 == 0:
+ opts.sim_method_num_steps = opts.sim_method_num_steps * np.ones((dims.N,), dtype=np.int64)
+ elif isinstance(opts.sim_method_num_steps, np.ndarray) and opts.sim_method_num_steps.size == dims.N \
+ and np.all(np.equal(np.mod(opts.sim_method_num_steps, 1), 0)):
+ opts.sim_method_num_steps = np.reshape(opts.sim_method_num_steps, (dims.N,)).astype(np.int64)
+ else:
+ raise Exception("Wrong value for sim_method_num_steps. Should be either int or array of ints of shape (N,).")
+
+ # num_stages
+ if isinstance(opts.sim_method_num_stages, np.ndarray) and opts.sim_method_num_stages.size == 1:
+ opts.sim_method_num_stages = opts.sim_method_num_stages.item()
+
+ if isinstance(opts.sim_method_num_stages, (int, float)) and opts.sim_method_num_stages % 1 == 0:
+ opts.sim_method_num_stages = opts.sim_method_num_stages * np.ones((dims.N,), dtype=np.int64)
+ elif isinstance(opts.sim_method_num_stages, np.ndarray) and opts.sim_method_num_stages.size == dims.N \
+ and np.all(np.equal(np.mod(opts.sim_method_num_stages, 1), 0)):
+ opts.sim_method_num_stages = np.reshape(opts.sim_method_num_stages, (dims.N,)).astype(np.int64)
+ else:
+ raise Exception("Wrong value for sim_method_num_stages. Should be either int or array of ints of shape (N,).")
+
+ # jac_reuse
+ if isinstance(opts.sim_method_jac_reuse, np.ndarray) and opts.sim_method_jac_reuse.size == 1:
+ opts.sim_method_jac_reuse = opts.sim_method_jac_reuse.item()
+
+ if isinstance(opts.sim_method_jac_reuse, (int, float)) and opts.sim_method_jac_reuse % 1 == 0:
+ opts.sim_method_jac_reuse = opts.sim_method_jac_reuse * np.ones((dims.N,), dtype=np.int64)
+ elif isinstance(opts.sim_method_jac_reuse, np.ndarray) and opts.sim_method_jac_reuse.size == dims.N \
+ and np.all(np.equal(np.mod(opts.sim_method_jac_reuse, 1), 0)):
+ opts.sim_method_jac_reuse = np.reshape(opts.sim_method_jac_reuse, (dims.N,)).astype(np.int64)
+ else:
+ raise Exception("Wrong value for sim_method_jac_reuse. Should be either int or array of ints of shape (N,).")
+
+
+
+def get_ocp_nlp_layout():
+ current_module = sys.modules[__name__]
+ acados_path = os.path.dirname(current_module.__file__)
+ with open(acados_path + '/acados_layout.json', 'r') as f:
+ ocp_nlp_layout = json.load(f)
+ return ocp_nlp_layout
+
+
+def ocp_formulation_json_dump(acados_ocp, simulink_opts, json_file='acados_ocp_nlp.json'):
+ # Load acados_ocp_nlp structure description
+ ocp_layout = get_ocp_nlp_layout()
+
+ # Copy input ocp object dictionary
+ ocp_nlp_dict = dict(deepcopy(acados_ocp).__dict__)
+ # TODO: maybe make one function with formatting
+
+ for acados_struct, v in ocp_layout.items():
+ # skip non dict attributes
+ if not isinstance(v, dict):
+ continue
+ # setattr(ocp_nlp, acados_struct, dict(getattr(acados_ocp, acados_struct).__dict__))
+ # Copy ocp object attributes dictionaries
+ ocp_nlp_dict[acados_struct]=dict(getattr(acados_ocp, acados_struct).__dict__)
+
+ ocp_nlp_dict = format_class_dict(ocp_nlp_dict)
+
+ # strip symbolics
+ ocp_nlp_dict['model'] = acados_model_strip_casadi_symbolics(ocp_nlp_dict['model'])
+
+ # strip shooting_nodes
+ ocp_nlp_dict['solver_options'].pop('shooting_nodes', None)
+
+ dims_dict = acados_class2dict(acados_ocp.dims)
+
+ ocp_check_against_layout(ocp_nlp_dict, dims_dict)
+
+ # add simulink options
+ ocp_nlp_dict['simulink_opts'] = simulink_opts
+
+ with open(json_file, 'w') as f:
+ json.dump(ocp_nlp_dict, f, default=np_array_to_list, indent=4, sort_keys=True)
+
+
+
+def ocp_formulation_json_load(json_file='acados_ocp_nlp.json'):
+ # Load acados_ocp_nlp structure description
+ ocp_layout = get_ocp_nlp_layout()
+
+ with open(json_file, 'r') as f:
+ ocp_nlp_json = json.load(f)
+
+ ocp_nlp_dict = json2dict(ocp_nlp_json, ocp_nlp_json['dims'])
+
+ # Instantiate AcadosOcp object
+ acados_ocp = AcadosOcp()
+
+ # load class dict
+ acados_ocp.__dict__ = ocp_nlp_dict
+
+ # load class attributes dict, dims, constraints, etc
+ for acados_struct, v in ocp_layout.items():
+ # skip non dict attributes
+ if not isinstance(v, dict):
+ continue
+ acados_attribute = getattr(acados_ocp, acados_struct)
+ acados_attribute.__dict__ = ocp_nlp_dict[acados_struct]
+ setattr(acados_ocp, acados_struct, acados_attribute)
+
+ return acados_ocp
+
+
+def ocp_generate_external_functions(acados_ocp, model):
+
+ model = make_model_consistent(model)
+
+ if acados_ocp.solver_options.hessian_approx == 'EXACT':
+ opts = dict(generate_hess=1)
+ else:
+ opts = dict(generate_hess=0)
+ code_export_dir = acados_ocp.code_export_directory
+ opts['code_export_directory'] = code_export_dir
+
+ if acados_ocp.model.dyn_ext_fun_type != 'casadi':
+ raise Exception("ocp_generate_external_functions: dyn_ext_fun_type only supports 'casadi' for now.\
+ Extending the Python interface with generic function support is welcome.")
+
+ if acados_ocp.solver_options.integrator_type == 'ERK':
+ # explicit model -- generate C code
+ generate_c_code_explicit_ode(model, opts)
+ elif acados_ocp.solver_options.integrator_type == 'IRK':
+ # implicit model -- generate C code
+ generate_c_code_implicit_ode(model, opts)
+ elif acados_ocp.solver_options.integrator_type == 'LIFTED_IRK':
+ generate_c_code_implicit_ode(model, opts)
+ elif acados_ocp.solver_options.integrator_type == 'GNSF':
+ generate_c_code_gnsf(model, opts)
+ elif acados_ocp.solver_options.integrator_type == 'DISCRETE':
+ generate_c_code_discrete_dynamics(model, opts)
+ else:
+ raise Exception("ocp_generate_external_functions: unknown integrator type.")
+
+ if acados_ocp.dims.nphi > 0 or acados_ocp.dims.nh > 0:
+ generate_c_code_constraint(model, model.name, False, opts)
+
+ if acados_ocp.dims.nphi_e > 0 or acados_ocp.dims.nh_e > 0:
+ generate_c_code_constraint(model, model.name, True, opts)
+
+ # dummy matrices
+ if not acados_ocp.cost.cost_type_0 == 'LINEAR_LS':
+ acados_ocp.cost.Vx_0 = np.zeros((acados_ocp.dims.ny_0, acados_ocp.dims.nx))
+ acados_ocp.cost.Vu_0 = np.zeros((acados_ocp.dims.ny_0, acados_ocp.dims.nu))
+ if not acados_ocp.cost.cost_type == 'LINEAR_LS':
+ acados_ocp.cost.Vx = np.zeros((acados_ocp.dims.ny, acados_ocp.dims.nx))
+ acados_ocp.cost.Vu = np.zeros((acados_ocp.dims.ny, acados_ocp.dims.nu))
+ if not acados_ocp.cost.cost_type_e == 'LINEAR_LS':
+ acados_ocp.cost.Vx_e = np.zeros((acados_ocp.dims.ny_e, acados_ocp.dims.nx))
+
+ if acados_ocp.cost.cost_type_0 == 'NONLINEAR_LS':
+ generate_c_code_nls_cost(model, model.name, 'initial', opts)
+ elif acados_ocp.cost.cost_type_0 == 'EXTERNAL':
+ generate_c_code_external_cost(model, 'initial', opts)
+
+ if acados_ocp.cost.cost_type == 'NONLINEAR_LS':
+ generate_c_code_nls_cost(model, model.name, 'path', opts)
+ elif acados_ocp.cost.cost_type == 'EXTERNAL':
+ generate_c_code_external_cost(model, 'path', opts)
+
+ if acados_ocp.cost.cost_type_e == 'NONLINEAR_LS':
+ generate_c_code_nls_cost(model, model.name, 'terminal', opts)
+ elif acados_ocp.cost.cost_type_e == 'EXTERNAL':
+ generate_c_code_external_cost(model, 'terminal', opts)
+
+
+def ocp_render_templates(acados_ocp, json_file):
+
+ name = acados_ocp.model.name
+
+ # setting up loader and environment
+ json_path = '{cwd}/{json_file}'.format(
+ cwd=os.getcwd(),
+ json_file=json_file)
+
+ if not os.path.exists(json_path):
+ raise Exception('{} not found!'.format(json_path))
+
+ code_export_dir = acados_ocp.code_export_directory
+ template_dir = code_export_dir
+
+ ## Render templates
+ in_file = 'main.in.c'
+ out_file = f'main_{name}.c'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'acados_solver.in.c'
+ out_file = f'acados_solver_{name}.c'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'acados_solver.in.h'
+ out_file = f'acados_solver_{name}.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'Makefile.in'
+ out_file = 'Makefile'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'acados_solver_sfun.in.c'
+ out_file = f'acados_solver_sfunction_{name}.c'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'make_sfun.in.m'
+ out_file = f'make_sfun_{name}.m'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # sim
+ in_file = 'acados_sim_solver.in.c'
+ out_file = f'acados_sim_solver_{name}.c'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'acados_sim_solver.in.h'
+ out_file = f'acados_sim_solver_{name}.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'main_sim.in.c'
+ out_file = f'main_sim_{name}.c'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ ## folder model
+ template_dir = f'{code_export_dir}/{name}_model/'
+
+ in_file = 'model.in.h'
+ out_file = f'{name}_model.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # constraints on convex over nonlinear function
+ if acados_ocp.constraints.constr_type == 'BGP' and acados_ocp.dims.nphi > 0:
+ # constraints on outer function
+ template_dir = f'{code_export_dir}/{name}_constraints/'
+ in_file = 'phi_constraint.in.h'
+ out_file = f'{name}_phi_constraint.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # terminal constraints on convex over nonlinear function
+ if acados_ocp.constraints.constr_type_e == 'BGP' and acados_ocp.dims.nphi_e > 0:
+ # terminal constraints on outer function
+ template_dir = f'{code_export_dir}/{name}_constraints/'
+ in_file = 'phi_e_constraint.in.h'
+ out_file = f'{name}_phi_e_constraint.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # nonlinear constraints
+ if acados_ocp.constraints.constr_type == 'BGH' and acados_ocp.dims.nh > 0:
+ template_dir = f'{code_export_dir}/{name}_constraints/'
+ in_file = 'h_constraint.in.h'
+ out_file = f'{name}_h_constraint.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # terminal nonlinear constraints
+ if acados_ocp.constraints.constr_type_e == 'BGH' and acados_ocp.dims.nh_e > 0:
+ template_dir = f'{code_export_dir}/{name}_constraints/'
+ in_file = 'h_e_constraint.in.h'
+ out_file = f'{name}_h_e_constraint.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # initial stage Nonlinear LS cost function
+ if acados_ocp.cost.cost_type_0 == 'NONLINEAR_LS':
+ template_dir = f'{code_export_dir}/{name}_cost/'
+ in_file = 'cost_y_0_fun.in.h'
+ out_file = f'{name}_cost_y_0_fun.h'
+ render_template(in_file, out_file, template_dir, json_path)
+ # external cost - terminal
+ elif acados_ocp.cost.cost_type_0 == 'EXTERNAL':
+ template_dir = f'{code_export_dir}/{name}_cost/'
+ in_file = 'external_cost_0.in.h'
+ out_file = f'{name}_external_cost_0.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # path Nonlinear LS cost function
+ if acados_ocp.cost.cost_type == 'NONLINEAR_LS':
+ template_dir = f'{code_export_dir}/{name}_cost/'
+ in_file = 'cost_y_fun.in.h'
+ out_file = f'{name}_cost_y_fun.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # terminal Nonlinear LS cost function
+ if acados_ocp.cost.cost_type_e == 'NONLINEAR_LS':
+ template_dir = f'{code_export_dir}/{name}_cost/'
+ in_file = 'cost_y_e_fun.in.h'
+ out_file = f'{name}_cost_y_e_fun.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # external cost
+ if acados_ocp.cost.cost_type == 'EXTERNAL':
+ template_dir = f'{code_export_dir}/{name}_cost/'
+ in_file = 'external_cost.in.h'
+ out_file = f'{name}_external_cost.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ # external cost - terminal
+ if acados_ocp.cost.cost_type_e == 'EXTERNAL':
+ template_dir = f'{code_export_dir}/{name}_cost/'
+ in_file = 'external_cost_e.in.h'
+ out_file = f'{name}_external_cost_e.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+
+def remove_x0_elimination(acados_ocp):
+ acados_ocp.constraints.idxbxe_0 = np.zeros((0,))
+ acados_ocp.dims.nbxe_0 = 0
+
+
+class AcadosOcpSolver:
+ """
+ Class to interact with the acados ocp solver C object.
+
+ :param acados_ocp: type AcadosOcp - description of the OCP for acados
+ :param json_file: name for the json file used to render the templated code - default: acados_ocp_nlp.json
+ :param simulink_opts: Options to configure Simulink S-function blocks, mainly to activate possible Inputs and Outputs
+ """
+ if sys.platform=="win32":
+ from ctypes import wintypes
+ dlclose = ctypes.WinDLL('kernel32', use_last_error=True).FreeLibrary
+ dlclose.argtypes = [wintypes.HMODULE]
+ else:
+ dlclose = CDLL(None).dlclose
+ dlclose.argtypes = [c_void_p]
+
+ @classmethod
+ def generate(cls, acados_ocp, json_file='acados_ocp_nlp.json', simulink_opts=None, build=True):
+ model = acados_ocp.model
+
+ if simulink_opts is None:
+ json_path = os.path.dirname(os.path.realpath(__file__))
+ with open(json_path + '/simulink_default_opts.json', 'r') as f:
+ simulink_opts = json.load(f)
+
+ # make dims consistent
+ make_ocp_dims_consistent(acados_ocp)
+
+ # module dependent post processing
+ if acados_ocp.solver_options.integrator_type == 'GNSF':
+ set_up_imported_gnsf_model(acados_ocp)
+
+ if acados_ocp.solver_options.qp_solver == 'PARTIAL_CONDENSING_QPDUNES':
+ remove_x0_elimination(acados_ocp)
+
+ # set integrator time automatically
+ acados_ocp.solver_options.Tsim = acados_ocp.solver_options.time_steps[0]
+
+ # generate external functions
+ ocp_generate_external_functions(acados_ocp, model)
+
+ # dump to json
+ ocp_formulation_json_dump(acados_ocp, simulink_opts, json_file)
+
+ code_export_dir = acados_ocp.code_export_directory
+ # render templates
+ ocp_render_templates(acados_ocp, json_file)
+
+ if build:
+ ## Compile solver
+ cwd=os.getcwd()
+ os.chdir(code_export_dir)
+ os.system('make clean_ocp_shared_lib')
+ os.system('make ocp_shared_lib')
+ os.chdir(cwd)
+
+ def __init__(self, model_name, N, code_export_dir):
+ self.model_name = model_name
+ self.N = N
+
+ self.solver_created = False
+ self.shared_lib_name = f'{code_export_dir}/libacados_ocp_solver_{self.model_name}.so'
+
+ # get shared_lib
+ self.shared_lib = CDLL(self.shared_lib_name)
+
+ # create capsule
+ getattr(self.shared_lib, f"{self.model_name}_acados_create_capsule").restype = c_void_p
+ self.capsule = getattr(self.shared_lib, f"{self.model_name}_acados_create_capsule")()
+
+ # create solver
+ getattr(self.shared_lib, f"{self.model_name}_acados_create").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_create").restype = c_int
+ assert getattr(self.shared_lib, f"{self.model_name}_acados_create")(self.capsule)==0
+ self.solver_created = True
+
+ # get pointers solver
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_opts").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_opts").restype = c_void_p
+ self.nlp_opts = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_opts")(self.capsule)
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_dims").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_dims").restype = c_void_p
+ self.nlp_dims = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_dims")(self.capsule)
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_config").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_config").restype = c_void_p
+ self.nlp_config = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_config")(self.capsule)
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_out").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_out").restype = c_void_p
+ self.nlp_out = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_out")(self.capsule)
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_in").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_in").restype = c_void_p
+ self.nlp_in = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_in")(self.capsule)
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_solver").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_solver").restype = c_void_p
+ self.nlp_solver = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_solver")(self.capsule)
+
+ # treat parameters separately
+ getattr(self.shared_lib, f"{self.model_name}_acados_update_params").argtypes = [c_void_p, c_int, POINTER(c_double)]
+ getattr(self.shared_lib, f"{self.model_name}_acados_update_params").restype = c_int
+ self._set_param = getattr(self.shared_lib, f"{self.model_name}_acados_update_params")
+
+ self.shared_lib.ocp_nlp_constraint_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)]
+ self.shared_lib.ocp_nlp_constraint_dims_get_from_attr.restype = c_int
+ self.shared_lib.ocp_nlp_constraints_model_set_slice.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_int, c_char_p, c_void_p, c_int]
+
+ self.shared_lib.ocp_nlp_cost_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)]
+ self.shared_lib.ocp_nlp_cost_dims_get_from_attr.restype = c_int
+ self.shared_lib.ocp_nlp_cost_model_set_slice.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_int, c_char_p, c_void_p, c_int]
+
+ self.shared_lib.ocp_nlp_constraints_model_set.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_cost_model_set.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_out_set.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_set.argtypes = \
+ [c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+
+ self.shared_lib.ocp_nlp_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p]
+ self.shared_lib.ocp_nlp_dims_get_from_attr.restype = c_int
+ self.shared_lib.ocp_nlp_out_get_slice.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_get_at_stage.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+
+
+ def solve(self):
+ """
+ Solve the ocp with current input.
+ """
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_solve").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_solve").restype = c_int
+ status = getattr(self.shared_lib, f"{self.model_name}_acados_solve")(self.capsule)
+ return status
+
+
+ def get_slice(self, start_stage_, end_stage_, field_):
+ dims = self.shared_lib.ocp_nlp_dims_get_from_attr(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, start_stage_, field_)
+ out = np.ascontiguousarray(np.zeros((end_stage_ - start_stage_, dims)), dtype=np.float64)
+ self.fill_in_slice(start_stage_, end_stage_, field_, out)
+ return out
+
+ def fill_in_slice(self, start_stage_, end_stage_, field_, arr):
+ out_fields = ['x', 'u', 'z', 'pi', 'lam', 't']
+ mem_fields = ['sl', 'su']
+ field = field_
+ field = field.encode('utf-8')
+
+ if (field_ not in out_fields + mem_fields):
+ raise Exception('AcadosOcpSolver.get_slice(): {} is an invalid argument.\
+ \n Possible values are {}. Exiting.'.format(field_, out_fields))
+
+ if not isinstance(start_stage_, int):
+ raise Exception('AcadosOcpSolver.get_slice(): stage index must be Integer.')
+
+ if not isinstance(end_stage_, int):
+ raise Exception('AcadosOcpSolver.get_slice(): stage index must be Integer.')
+
+ if start_stage_ >= end_stage_:
+ raise Exception('AcadosOcpSolver.get_slice(): end stage index must be larger than start stage index')
+
+ if start_stage_ < 0 or end_stage_ > self.N + 1:
+ raise Exception('AcadosOcpSolver.get_slice(): stage index must be in [0, N], got: {}.'.format(self.N))
+
+ out_data = cast(arr.ctypes.data, POINTER(c_double))
+
+ if (field_ in out_fields):
+ self.shared_lib.ocp_nlp_out_get_slice(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, start_stage_, end_stage_, field, out_data)
+ elif field_ in mem_fields:
+ self.shared_lib.ocp_nlp_get_at_stage(self.nlp_config, \
+ self.nlp_dims, self.nlp_solver, start_stage_, end_stage_, field, out_data)
+
+ def get(self, stage_, field_):
+ return self.get_slice(stage_, stage_ + 1, field_)[0]
+
+
+ def print_statistics(self):
+ """
+ prints statistics of previous solver run as a table:
+ - iter: iteration number
+ - res_stat: stationarity residual
+ - res_eq: residual wrt equality constraints (dynamics)
+ - res_ineq: residual wrt inequality constraints (constraints)
+ - res_comp: residual wrt complementarity conditions
+ - qp_stat: status of QP solver
+ - qp_iter: number of QP iterations
+ - qp_res_stat: stationarity residual of the last QP solution
+ - qp_res_eq: residual wrt equality constraints (dynamics) of the last QP solution
+ - qp_res_ineq: residual wrt inequality constraints (constraints) of the last QP solution
+ - qp_res_comp: residual wrt complementarity conditions of the last QP solution
+ """
+ stat = self.get_stats("statistics")
+
+ if self.acados_ocp.solver_options.nlp_solver_type == 'SQP':
+ print('\niter\tres_stat\tres_eq\t\tres_ineq\tres_comp\tqp_stat\tqp_iter')
+ if stat.shape[0]>7:
+ print('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp')
+ for jj in range(stat.shape[1]):
+ print('{:d}\t{:e}\t{:e}\t{:e}\t{:e}\t{:d}\t{:d}'.format( \
+ int(stat[0][jj]), stat[1][jj], stat[2][jj], \
+ stat[3][jj], stat[4][jj], int(stat[5][jj]), int(stat[6][jj])))
+ if stat.shape[0]>7:
+ print('\t{:e}\t{:e}\t{:e}\t{:e}'.format( \
+ stat[7][jj], stat[8][jj], stat[9][jj], stat[10][jj]))
+ print('\n')
+ elif self.acados_ocp.solver_options.nlp_solver_type == 'SQP_RTI':
+ print('\niter\tqp_stat\tqp_iter')
+ if stat.shape[0]>3:
+ print('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp')
+ for jj in range(stat.shape[1]):
+ print('{:d}\t{:d}\t{:d}'.format( int(stat[0][jj]), int(stat[1][jj]), int(stat[2][jj])))
+ if stat.shape[0]>3:
+ print('\t{:e}\t{:e}\t{:e}\t{:e}'.format( \
+ stat[3][jj], stat[4][jj], stat[5][jj], stat[6][jj]))
+ print('\n')
+
+ return
+
+
+ def store_iterate(self, filename='', overwrite=False):
+ """
+ Stores the current iterate of the ocp solver in a json file.
+
+ :param filename: if not set, use model_name + timestamp + '.json'
+ :param overwrite: if false and filename exists add timestamp to filename
+ """
+ if filename == '':
+ filename += self.model_name + '_' + 'iterate' + '.json'
+
+ if not overwrite:
+ # append timestamp
+ if os.path.isfile(filename):
+ filename = filename[:-5]
+ filename += datetime.utcnow().strftime('%Y-%m-%d-%H:%M:%S.%f') + '.json'
+
+ # get iterate:
+ solution = dict()
+
+ for i in range(self.N+1):
+ solution['x_'+str(i)] = self.get(i,'x')
+ solution['u_'+str(i)] = self.get(i,'u')
+ solution['z_'+str(i)] = self.get(i,'z')
+ solution['lam_'+str(i)] = self.get(i,'lam')
+ solution['t_'+str(i)] = self.get(i, 't')
+ solution['sl_'+str(i)] = self.get(i, 'sl')
+ solution['su_'+str(i)] = self.get(i, 'su')
+ for i in range(self.N):
+ solution['pi_'+str(i)] = self.get(i,'pi')
+
+ # save
+ with open(filename, 'w') as f:
+ json.dump(solution, f, default=np_array_to_list, indent=4, sort_keys=True)
+ print("stored current iterate in ", os.path.join(os.getcwd(), filename))
+
+
+ def load_iterate(self, filename):
+ """
+ Loads the iterate stored in json file with filename into the ocp solver.
+ """
+ if not os.path.isfile(filename):
+ raise Exception('load_iterate: failed, file does not exist: ' + os.path.join(os.getcwd(), filename))
+
+ with open(filename, 'r') as f:
+ solution = json.load(f)
+
+ for key in solution.keys():
+ (field, stage) = key.split('_')
+ self.set(int(stage), field, np.array(solution[key]))
+
+
+ def get_stats(self, field_):
+ """
+ Get the information of the last solver call.
+
+ :param field: string in ['statistics', 'time_tot', 'time_lin', 'time_sim', 'time_sim_ad', 'time_sim_la', 'time_qp', 'time_qp_solver_call', 'time_reg', 'sqp_iter']
+ """
+
+ fields = ['time_tot', # total cpu time previous call
+ 'time_lin', # cpu time for linearization
+ 'time_sim', # cpu time for integrator
+ 'time_sim_ad', # cpu time for integrator contribution of external function calls
+ 'time_sim_la', # cpu time for integrator contribution of linear algebra
+ 'time_qp', # cpu time qp solution
+ 'time_qp_solver_call', # cpu time inside qp solver (without converting the QP)
+ 'time_qp_xcond',
+ 'time_glob', # cpu time globalization
+ 'time_reg', # cpu time regularization
+ 'sqp_iter', # number of SQP iterations
+ 'qp_iter', # vector of QP iterations for last SQP call
+ 'statistics', # table with info about last iteration
+ 'stat_m',
+ 'stat_n',]
+
+ field = field_
+ field = field.encode('utf-8')
+ if (field_ not in fields):
+ raise Exception('AcadosOcpSolver.get_stats(): {} is not a valid argument.\
+ \n Possible values are {}. Exiting.'.format(fields, fields))
+
+ if field_ in ['sqp_iter', 'stat_m', 'stat_n']:
+ out = np.ascontiguousarray(np.zeros((1,)), dtype=np.int64)
+ out_data = cast(out.ctypes.data, POINTER(c_int64))
+
+ elif field_ == 'statistics':
+ sqp_iter = self.get_stats("sqp_iter")
+ stat_m = self.get_stats("stat_m")
+ stat_n = self.get_stats("stat_n")
+
+ min_size = min([stat_m, sqp_iter+1])
+
+ out = np.ascontiguousarray(
+ np.zeros((stat_n[0]+1, min_size[0])), dtype=np.float64)
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+
+ elif field_ == 'qp_iter':
+ full_stats = self.get_stats('statistics')
+ if self.acados_ocp.solver_options.nlp_solver_type == 'SQP':
+ out = full_stats[6, :]
+ elif self.acados_ocp.solver_options.nlp_solver_type == 'SQP_RTI':
+ out = full_stats[2, :]
+
+ else:
+ out = np.ascontiguousarray(np.zeros((1,)), dtype=np.float64)
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+
+ if not field_ == 'qp_iter':
+ self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data)
+
+ return out
+
+
+ def get_cost(self):
+ """
+ Returns the cost value of the current solution.
+ """
+ # compute cost internally
+ self.shared_lib.ocp_nlp_eval_cost.argtypes = [c_void_p, c_void_p, c_void_p]
+ self.shared_lib.ocp_nlp_eval_cost(self.nlp_solver, self.nlp_in, self.nlp_out)
+
+ # create output array
+ out = np.ascontiguousarray(np.zeros((1,)), dtype=np.float64)
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+
+ # call getter
+ self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p]
+
+ field = "cost_value".encode('utf-8')
+ self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data)
+
+ return out[0]
+
+
+ def get_residuals(self):
+ """
+ Returns an array of the form [res_stat, res_eq, res_ineq, res_comp].
+ """
+ # compute residuals if RTI
+ if self.acados_ocp.solver_options.nlp_solver_type == 'SQP_RTI':
+ self.shared_lib.ocp_nlp_eval_residuals.argtypes = [c_void_p, c_void_p, c_void_p]
+ self.shared_lib.ocp_nlp_eval_residuals(self.nlp_solver, self.nlp_in, self.nlp_out)
+
+ # create output array
+ out = np.ascontiguousarray(np.zeros((4, 1)), dtype=np.float64)
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+
+ # call getters
+ self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p]
+
+ field = "res_stat".encode('utf-8')
+ self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data)
+
+ out_data = cast(out[1].ctypes.data, POINTER(c_double))
+ field = "res_eq".encode('utf-8')
+ self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data)
+
+ out_data = cast(out[2].ctypes.data, POINTER(c_double))
+ field = "res_ineq".encode('utf-8')
+ self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data)
+
+ out_data = cast(out[3].ctypes.data, POINTER(c_double))
+ field = "res_comp".encode('utf-8')
+ self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data)
+ return out.flatten()
+
+
+ # Note: this function should not be used anymore, better use cost_set, constraints_set
+
+ def set(self, stage_, field_, value_):
+
+ """
+ Set numerical data inside the solver.
+
+ :param stage: integer corresponding to shooting node
+ :param field: string in ['x', 'u', 'pi', 'lam', 't', 'p']
+
+ .. note:: regarding lam, t: \n
+ the inequalities are internally organized in the following order: \n
+ [ lbu lbx lg lh lphi ubu ubx ug uh uphi; \n
+ lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi]
+
+ .. note:: pi: multipliers for dynamics equality constraints \n
+ lam: multipliers for inequalities \n
+ t: slack variables corresponding to evaluation of all inequalities (at the solution) \n
+ sl: slack variables of soft lower inequality constraints \n
+ su: slack variables of soft upper inequality constraints \n
+ """
+ cost_fields = ['y_ref', 'yref']
+ constraints_fields = ['lbx', 'ubx', 'lbu', 'ubu']
+ out_fields = ['x', 'u', 'pi', 'lam', 't', 'z']
+ mem_fields = ['sl', 'su']
+
+ # cast value_ to avoid conversion issues
+ if isinstance(value_, (float, int)):
+ value_ = np.array([value_])
+ value_ = value_.astype(float)
+
+ field = field_
+ field = field.encode('utf-8')
+
+ stage = c_int(stage_)
+
+ if field_ not in constraints_fields + cost_fields + out_fields + mem_fields:
+ raise Exception("AcadosOcpSolver.set(): {} is not a valid argument.\
+ \nPossible values are {}. Exiting.".format(field, \
+ constraints_fields + cost_fields + out_fields + ['p']))
+
+ self.shared_lib.ocp_nlp_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p]
+ self.shared_lib.ocp_nlp_dims_get_from_attr.restype = c_int
+
+ dims = self.shared_lib.ocp_nlp_dims_get_from_attr(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, stage_, field)
+
+ if value_.shape[0] != dims:
+ msg = 'AcadosOcpSolver.set(): mismatching dimension for field "{}" '.format(field_)
+ msg += 'with dimension {} (you have {})'.format(dims, value_.shape)
+ raise Exception(msg)
+
+ value_data_p = cast(value_.ctypes.data, c_void_p)
+ if field_ in constraints_fields:
+ self.shared_lib.ocp_nlp_constraints_model_set(self.nlp_config, \
+ self.nlp_dims, self.nlp_in, stage, field, value_data_p)
+ elif field_ in cost_fields:
+ self.shared_lib.ocp_nlp_cost_model_set(self.nlp_config, \
+ self.nlp_dims, self.nlp_in, stage, field, value_data_p)
+ elif field_ in out_fields:
+ self.shared_lib.ocp_nlp_out_set(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, stage, field, value_data_p)
+ elif field_ in mem_fields:
+ self.shared_lib.ocp_nlp_set(self.nlp_config, \
+ self.nlp_solver, stage, field, value_data_p)
+ return
+
+
+ def set_param(self, stage_, value_):
+ value_data = cast(value_.ctypes.data, POINTER(c_double))
+ self._set_param(self.capsule, stage_, value_data, value_.shape[0])
+
+ def cost_set(self, start_stage_, field_, value_, api='warn'):
+ self.cost_set_slice(start_stage_, start_stage_+1, field_, value_[None], api='warn')
+
+ def cost_set_slice(self, start_stage_, end_stage_, field_, value_, api='warn'):
+ """
+ Set numerical data in the cost module of the solver.
+
+ :param stage: integer corresponding to shooting node
+ :param field: string, e.g. 'yref', 'W', 'ext_cost_num_hess'
+ :param value: of appropriate size
+ """
+ # cast value_ to avoid conversion issues
+ field = field_.encode('utf-8')
+ if len(value_.shape) > 2:
+ dim = value_.shape[1]*value_.shape[2]
+ else:
+ dim = value_.shape[1]
+
+ self.shared_lib.ocp_nlp_cost_model_set_slice(self.nlp_config, \
+ self.nlp_dims, self.nlp_in, start_stage_, end_stage_, field,
+ cast(value_.ctypes.data, c_void_p), dim)
+
+
+ def constraints_set(self, start_stage_, field_, value_, api='warn'):
+ self.constraints_set_slice(start_stage_, start_stage_+1, field_, value_[None], api='warn')
+
+
+ def constraints_set_slice(self, start_stage_, end_stage_, field_, value_, api='warn'):
+ """
+ Set numerical data in the constraint module of the solver.
+
+ :param stage: integer corresponding to shooting node
+ :param field: string in ['lbx', 'ubx', 'lbu', 'ubu', 'lg', 'ug', 'lh', 'uh', 'uphi']
+ :param value: of appropriate size
+ """
+
+ field = field_.encode('utf-8')
+ if len(value_.shape) > 2:
+ dim = value_.shape[1]*value_.shape[2]
+ else:
+ dim = value_.shape[1]
+
+ self.shared_lib.ocp_nlp_constraints_model_set_slice(self.nlp_config, \
+ self.nlp_dims, self.nlp_in, start_stage_, end_stage_, field,
+ cast(value_.ctypes.data, c_void_p), dim)
+
+
+ def dynamics_get(self, stage_, field_):
+ """
+ Get numerical data from the dynamics module of the solver:
+
+ :param stage: integer corresponding to shooting node
+ :param field: string, e.g. 'A'
+ """
+
+ field = field_
+ field = field.encode('utf-8')
+ stage = c_int(stage_)
+
+ # get dims
+ self.shared_lib.ocp_nlp_dynamics_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)]
+ self.shared_lib.ocp_nlp_dynamics_dims_get_from_attr.restype = c_int
+
+ dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc)
+ dims_data = cast(dims.ctypes.data, POINTER(c_int))
+
+ self.shared_lib.ocp_nlp_dynamics_dims_get_from_attr(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, stage_, field, dims_data)
+
+ # create output data
+ out = np.ascontiguousarray(np.zeros((np.prod(dims),)), dtype=np.float64)
+ out = out.reshape(dims[0], dims[1], order='F')
+
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+ out_data_p = cast((out_data), c_void_p)
+
+ # call getter
+ self.shared_lib.ocp_nlp_get_at_stage.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_get_at_stage(self.nlp_config, \
+ self.nlp_dims, self.nlp_solver, stage, field, out_data_p)
+
+ return out
+
+
+ def options_set(self, field_, value_):
+ """
+ Set options of the solver.
+
+ :param field: string, e.g. 'print_level', 'rti_phase', 'initialize_t_slacks', 'step_length', 'alpha_min', 'alpha_reduction'
+ :param value: of type int, float
+ """
+ int_fields = ['print_level', 'rti_phase', 'initialize_t_slacks']
+ double_fields = ['step_length', 'tol_eq', 'tol_stat', 'tol_ineq', 'tol_comp', 'alpha_min', 'alpha_reduction']
+ string_fields = ['globalization']
+
+ # check field availability and type
+ if field_ in int_fields:
+ if not isinstance(value_, int):
+ raise Exception('solver option {} must be of type int. You have {}.'.format(field_, type(value_)))
+ else:
+ value_ctypes = c_int(value_)
+
+ elif field_ in double_fields:
+ if not isinstance(value_, float):
+ raise Exception('solver option {} must be of type float. You have {}.'.format(field_, type(value_)))
+ else:
+ value_ctypes = c_double(value_)
+
+ elif field_ in string_fields:
+ if not isinstance(value_, str):
+ raise Exception('solver option {} must be of type str. You have {}.'.format(field_, type(value_)))
+ else:
+ value_ctypes = value_.encode('utf-8')
+ else:
+ raise Exception('AcadosOcpSolver.options_set() does not support field {}.'\
+ '\n Possible values are {}.'.format(field_, ', '.join(int_fields + double_fields + string_fields)))
+
+
+ if field_ == 'rti_phase':
+ if value_ < 0 or value_ > 2:
+ raise Exception('AcadosOcpSolver.solve(): argument \'rti_phase\' can '
+ 'take only values 0, 1, 2 for SQP-RTI-type solvers')
+ if self.acados_ocp.solver_options.nlp_solver_type != 'SQP_RTI' and value_ > 0:
+ raise Exception('AcadosOcpSolver.solve(): argument \'rti_phase\' can '
+ 'take only value 0 for SQP-type solvers')
+
+ # encode
+ field = field_
+ field = field.encode('utf-8')
+
+ # call C interface
+ if field_ in string_fields:
+ self.shared_lib.ocp_nlp_solver_opts_set.argtypes = \
+ [c_void_p, c_void_p, c_char_p, c_char_p]
+ self.shared_lib.ocp_nlp_solver_opts_set(self.nlp_config, \
+ self.nlp_opts, field, value_ctypes)
+ else:
+ self.shared_lib.ocp_nlp_solver_opts_set.argtypes = \
+ [c_void_p, c_void_p, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_solver_opts_set(self.nlp_config, \
+ self.nlp_opts, field, byref(value_ctypes))
+ return
+
+
+ def __del__(self):
+ if self.solver_created:
+ getattr(self.shared_lib, f"{self.model_name}_acados_free").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_free").restype = c_int
+ getattr(self.shared_lib, f"{self.model_name}_acados_free")(self.capsule)
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_free_capsule").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_free_capsule").restype = c_int
+ getattr(self.shared_lib, f"{self.model_name}_acados_free_capsule")(self.capsule)
+
+ try:
+ self.dlclose(self.shared_lib._handle)
+ except:
+ pass
diff --git a/pyextra/acados_template/acados_ocp_solver_fast.py b/pyextra/acados_template/acados_ocp_solver_fast.py
new file mode 100644
index 000000000..656d288f1
--- /dev/null
+++ b/pyextra/acados_template/acados_ocp_solver_fast.py
@@ -0,0 +1,402 @@
+import sys
+import os
+import json
+import numpy as np
+from datetime import datetime
+
+from ctypes import POINTER, CDLL, c_void_p, c_int, cast, c_double, c_char_p
+
+from copy import deepcopy
+
+from .generate_c_code_explicit_ode import generate_c_code_explicit_ode
+from .generate_c_code_implicit_ode import generate_c_code_implicit_ode
+from .generate_c_code_gnsf import generate_c_code_gnsf
+from .generate_c_code_discrete_dynamics import generate_c_code_discrete_dynamics
+from .generate_c_code_constraint import generate_c_code_constraint
+from .generate_c_code_nls_cost import generate_c_code_nls_cost
+from .generate_c_code_external_cost import generate_c_code_external_cost
+from .acados_ocp import AcadosOcp
+from .acados_model import acados_model_strip_casadi_symbolics
+from .utils import is_column, is_empty, casadi_length, render_template, acados_class2dict,\
+ format_class_dict, ocp_check_against_layout, np_array_to_list, make_model_consistent,\
+ set_up_imported_gnsf_model, get_acados_path
+
+
+class AcadosOcpSolverFast:
+ dlclose = CDLL(None).dlclose
+ dlclose.argtypes = [c_void_p]
+
+ def __init__(self, model_name, N, code_export_dir):
+
+ self.solver_created = False
+ self.N = N
+ self.model_name = model_name
+
+ self.shared_lib_name = f'{code_export_dir}/libacados_ocp_solver_{model_name}.so'
+
+ # get shared_lib
+ self.shared_lib = CDLL(self.shared_lib_name)
+
+ # create capsule
+ getattr(self.shared_lib, f"{model_name}_acados_create_capsule").restype = c_void_p
+ self.capsule = getattr(self.shared_lib, f"{model_name}_acados_create_capsule")()
+
+ # create solver
+ getattr(self.shared_lib, f"{model_name}_acados_create").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_create").restype = c_int
+ assert getattr(self.shared_lib, f"{model_name}_acados_create")(self.capsule)==0
+ self.solver_created = True
+
+ # get pointers solver
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_opts").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_opts").restype = c_void_p
+ self.nlp_opts = getattr(self.shared_lib, f"{model_name}_acados_get_nlp_opts")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_dims").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_dims").restype = c_void_p
+ self.nlp_dims = getattr(self.shared_lib, f"{model_name}_acados_get_nlp_dims")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_config").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_config").restype = c_void_p
+ self.nlp_config = getattr(self.shared_lib, f"{model_name}_acados_get_nlp_config")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_out").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_out").restype = c_void_p
+ self.nlp_out = getattr(self.shared_lib, f"{model_name}_acados_get_nlp_out")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_in").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_in").restype = c_void_p
+ self.nlp_in = getattr(self.shared_lib, f"{model_name}_acados_get_nlp_in")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_solver").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_nlp_solver").restype = c_void_p
+ self.nlp_solver = getattr(self.shared_lib, f"{model_name}_acados_get_nlp_solver")(self.capsule)
+
+
+ def solve(self):
+ """
+ Solve the ocp with current input.
+ """
+ model_name = self.model_name
+
+ getattr(self.shared_lib, f"{model_name}_acados_solve").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_solve").restype = c_int
+ status = getattr(self.shared_lib, f"{model_name}_acados_solve")(self.capsule)
+ return status
+
+ def cost_set(self, start_stage_, field_, value_, api='warn'):
+ self.cost_set_slice(start_stage_, start_stage_+1, field_, value_[None], api='warn')
+ return
+
+ def cost_set_slice(self, start_stage_, end_stage_, field_, value_, api='warn'):
+ """
+ Set numerical data in the cost module of the solver.
+
+ :param stage: integer corresponding to shooting node
+ :param field: string, e.g. 'yref', 'W', 'ext_cost_num_hess'
+ :param value: of appropriate size
+ """
+ # cast value_ to avoid conversion issues
+ if isinstance(value_, (float, int)):
+ value_ = np.array([value_])
+ value_ = np.ascontiguousarray(np.copy(value_), dtype=np.float64)
+ field = field_
+ field = field.encode('utf-8')
+ dim = np.product(value_.shape[1:])
+
+ start_stage = c_int(start_stage_)
+ end_stage = c_int(end_stage_)
+ self.shared_lib.ocp_nlp_cost_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)]
+ self.shared_lib.ocp_nlp_cost_dims_get_from_attr.restype = c_int
+
+ dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc)
+ dims_data = cast(dims.ctypes.data, POINTER(c_int))
+
+ self.shared_lib.ocp_nlp_cost_dims_get_from_attr(self.nlp_config,
+ self.nlp_dims, self.nlp_out, start_stage_, field, dims_data)
+
+ value_shape = value_.shape
+ expected_shape = tuple(np.concatenate([np.array([end_stage_ - start_stage_]), dims]))
+ if len(value_shape) == 2:
+ value_shape = (value_shape[0], value_shape[1], 0)
+
+ elif len(value_shape) == 3:
+ if api=='old':
+ pass
+ elif api=='warn':
+ if not np.all(np.ravel(value_, order='F')==np.ravel(value_, order='K')):
+ raise Exception("Ambiguity in API detected.\n"
+ "Are you making an acados model from scrach? Add api='new' to cost_set and carry on.\n"
+ "Are you seeing this error suddenly in previously running code? Read on.\n"
+ " You are relying on a now-fixed bug in cost_set for field '{}'.\n".format(field_) +
+ " acados_template now correctly passes on any matrices to acados in column major format.\n" +
+ " Two options to fix this error: \n" +
+ " * Add api='old' to cost_set to restore old incorrect behaviour\n" +
+ " * Add api='new' to cost_set and remove any unnatural manipulation of the value argument " +
+ "such as non-mathematical transposes, reshaping, casting to fortran order, etc... " +
+ "If there is no such manipulation, then you have probably been getting an incorrect solution before.")
+ # Get elements in column major order
+ value_ = np.ravel(value_, order='F')
+ elif api=='new':
+ # Get elements in column major order
+ value_ = np.ravel(value_, order='F')
+ else:
+ raise Exception("Unknown api: '{}'".format(api))
+
+ if value_shape != expected_shape:
+ raise Exception('AcadosOcpSolver.cost_set(): mismatching dimension',
+ ' for field "{}" with dimension {} (you have {})'.format(
+ field_, expected_shape, value_shape))
+
+
+ value_data = cast(value_.ctypes.data, POINTER(c_double))
+ value_data_p = cast((value_data), c_void_p)
+
+ self.shared_lib.ocp_nlp_cost_model_set_slice.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_int, c_char_p, c_void_p, c_int]
+ self.shared_lib.ocp_nlp_cost_model_set_slice(self.nlp_config,
+ self.nlp_dims, self.nlp_in, start_stage, end_stage, field, value_data_p, dim)
+ return
+
+ def constraints_set(self, start_stage_, field_, value_, api='warn'):
+ self.constraints_set_slice(start_stage_, start_stage_+1, field_, value_[None], api='warn')
+ return
+
+ def constraints_set_slice(self, start_stage_, end_stage_, field_, value_, api='warn'):
+ """
+ Set numerical data in the constraint module of the solver.
+
+ :param stage: integer corresponding to shooting node
+ :param field: string in ['lbx', 'ubx', 'lbu', 'ubu', 'lg', 'ug', 'lh', 'uh', 'uphi']
+ :param value: of appropriate size
+ """
+ # cast value_ to avoid conversion issues
+ if isinstance(value_, (float, int)):
+ value_ = np.array([value_])
+ value_ = value_.astype(float)
+
+ field = field_
+ field = field.encode('utf-8')
+ dim = np.product(value_.shape[1:])
+
+ start_stage = c_int(start_stage_)
+ end_stage = c_int(end_stage_)
+ self.shared_lib.ocp_nlp_constraint_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)]
+ self.shared_lib.ocp_nlp_constraint_dims_get_from_attr.restype = c_int
+
+ dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc)
+ dims_data = cast(dims.ctypes.data, POINTER(c_int))
+
+ self.shared_lib.ocp_nlp_constraint_dims_get_from_attr(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, start_stage_, field, dims_data)
+
+ value_shape = value_.shape
+ expected_shape = tuple(np.concatenate([np.array([end_stage_ - start_stage_]), dims]))
+ if len(value_shape) == 2:
+ value_shape = (value_shape[0], value_shape[1], 0)
+ elif len(value_shape) == 3:
+ if api=='old':
+ pass
+ elif api=='warn':
+ if not np.all(np.ravel(value_, order='F')==np.ravel(value_, order='K')):
+ raise Exception("Ambiguity in API detected.\n"
+ "Are you making an acados model from scrach? Add api='new' to constraints_set and carry on.\n"
+ "Are you seeing this error suddenly in previously running code? Read on.\n"
+ " You are relying on a now-fixed bug in constraints_set for field '{}'.\n".format(field_) +
+ " acados_template now correctly passes on any matrices to acados in column major format.\n" +
+ " Two options to fix this error: \n" +
+ " * Add api='old' to constraints_set to restore old incorrect behaviour\n" +
+ " * Add api='new' to constraints_set and remove any unnatural manipulation of the value argument " +
+ "such as non-mathematical transposes, reshaping, casting to fortran order, etc... " +
+ "If there is no such manipulation, then you have probably been getting an incorrect solution before.")
+ # Get elements in column major order
+ value_ = np.ravel(value_, order='F')
+ elif api=='new':
+ # Get elements in column major order
+ value_ = np.ravel(value_, order='F')
+ else:
+ raise Exception("Unknown api: '{}'".format(api))
+ if value_shape != expected_shape:
+ raise Exception('AcadosOcpSolver.constraints_set(): mismatching dimension' \
+ ' for field "{}" with dimension {} (you have {})'.format(field_, expected_shape, value_shape))
+
+ value_data = cast(value_.ctypes.data, POINTER(c_double))
+ value_data_p = cast((value_data), c_void_p)
+
+ self.shared_lib.ocp_nlp_constraints_model_set_slice.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_int, c_char_p, c_void_p, c_int]
+ self.shared_lib.ocp_nlp_constraints_model_set_slice(self.nlp_config, \
+ self.nlp_dims, self.nlp_in, start_stage, end_stage, field, value_data_p, dim)
+ return
+
+ # Note: this function should not be used anymore, better use cost_set, constraints_set
+ def set(self, stage_, field_, value_):
+ """
+ Set numerical data inside the solver.
+
+ :param stage: integer corresponding to shooting node
+ :param field: string in ['x', 'u', 'pi', 'lam', 't', 'p']
+
+ .. note:: regarding lam, t: \n
+ the inequalities are internally organized in the following order: \n
+ [ lbu lbx lg lh lphi ubu ubx ug uh uphi; \n
+ lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi]
+
+ .. note:: pi: multipliers for dynamics equality constraints \n
+ lam: multipliers for inequalities \n
+ t: slack variables corresponding to evaluation of all inequalities (at the solution) \n
+ sl: slack variables of soft lower inequality constraints \n
+ su: slack variables of soft upper inequality constraints \n
+ """
+ cost_fields = ['y_ref', 'yref']
+ constraints_fields = ['lbx', 'ubx', 'lbu', 'ubu']
+ out_fields = ['x', 'u', 'pi', 'lam', 't', 'z']
+ mem_fields = ['sl', 'su']
+
+ # cast value_ to avoid conversion issues
+ if isinstance(value_, (float, int)):
+ value_ = np.array([value_])
+ value_ = value_.astype(float)
+
+ model_name = self.model_name
+
+ field = field_
+ field = field.encode('utf-8')
+
+ stage = c_int(stage_)
+
+ # treat parameters separately
+ if field_ == 'p':
+ getattr(self.shared_lib, f"{model_name}_acados_update_params").argtypes = [c_void_p, c_int, POINTER(c_double)]
+ getattr(self.shared_lib, f"{model_name}_acados_update_params").restype = c_int
+
+ value_data = cast(value_.ctypes.data, POINTER(c_double))
+
+ assert getattr(self.shared_lib, f"{model_name}_acados_update_params")(self.capsule, stage, value_data, value_.shape[0])==0
+ else:
+ if field_ not in constraints_fields + cost_fields + out_fields + mem_fields:
+ raise Exception("AcadosOcpSolver.set(): {} is not a valid argument.\
+ \nPossible values are {}. Exiting.".format(field, \
+ constraints_fields + cost_fields + out_fields + ['p']))
+
+ self.shared_lib.ocp_nlp_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p]
+ self.shared_lib.ocp_nlp_dims_get_from_attr.restype = c_int
+
+ dims = self.shared_lib.ocp_nlp_dims_get_from_attr(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, stage_, field)
+
+ if value_.shape[0] != dims:
+ msg = 'AcadosOcpSolver.set(): mismatching dimension for field "{}" '.format(field_)
+ msg += 'with dimension {} (you have {})'.format(dims, value_.shape)
+ raise Exception(msg)
+
+ value_data = cast(value_.ctypes.data, POINTER(c_double))
+ value_data_p = cast((value_data), c_void_p)
+
+ if field_ in constraints_fields:
+ self.shared_lib.ocp_nlp_constraints_model_set.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_constraints_model_set(self.nlp_config, \
+ self.nlp_dims, self.nlp_in, stage, field, value_data_p)
+ elif field_ in cost_fields:
+ self.shared_lib.ocp_nlp_cost_model_set.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_cost_model_set(self.nlp_config, \
+ self.nlp_dims, self.nlp_in, stage, field, value_data_p)
+ elif field_ in out_fields:
+ self.shared_lib.ocp_nlp_out_set.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_out_set(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, stage, field, value_data_p)
+ elif field_ in mem_fields:
+ self.shared_lib.ocp_nlp_set.argtypes = \
+ [c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_set(self.nlp_config, \
+ self.nlp_solver, stage, field, value_data_p)
+ return
+
+
+ def get_slice(self, start_stage_, end_stage_, field_):
+ """
+ Get the last solution of the solver:
+
+ :param start_stage: integer corresponding to shooting node that indicates start of slice
+ :param end_stage: integer corresponding to shooting node that indicates end of slice
+ :param field: string in ['x', 'u', 'z', 'pi', 'lam', 't', 'sl', 'su',]
+
+ .. note:: regarding lam, t: \n
+ the inequalities are internally organized in the following order: \n
+ [ lbu lbx lg lh lphi ubu ubx ug uh uphi; \n
+ lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi]
+
+ .. note:: pi: multipliers for dynamics equality constraints \n
+ lam: multipliers for inequalities \n
+ t: slack variables corresponding to evaluation of all inequalities (at the solution) \n
+ sl: slack variables of soft lower inequality constraints \n
+ su: slack variables of soft upper inequality constraints \n
+ """
+ out_fields = ['x', 'u', 'z', 'pi', 'lam', 't']
+ mem_fields = ['sl', 'su']
+ field = field_
+ field = field.encode('utf-8')
+
+ if (field_ not in out_fields + mem_fields):
+ raise Exception('AcadosOcpSolver.get_slice(): {} is an invalid argument.\
+ \n Possible values are {}. Exiting.'.format(field_, out_fields))
+
+ if not isinstance(start_stage_, int):
+ raise Exception('AcadosOcpSolver.get_slice(): stage index must be Integer.')
+
+ if not isinstance(end_stage_, int):
+ raise Exception('AcadosOcpSolver.get_slice(): stage index must be Integer.')
+
+ if start_stage_ >= end_stage_:
+ raise Exception('AcadosOcpSolver.get_slice(): end stage index must be larger than start stage index')
+
+ if start_stage_ < 0 or end_stage_ > self.N + 1:
+ raise Exception('AcadosOcpSolver.get_slice(): stage index must be in [0, N], got: {}.'.format(self.N))
+ self.shared_lib.ocp_nlp_dims_get_from_attr.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p]
+ self.shared_lib.ocp_nlp_dims_get_from_attr.restype = c_int
+
+ dims = self.shared_lib.ocp_nlp_dims_get_from_attr(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, start_stage_, field)
+
+ out = np.ascontiguousarray(np.zeros((end_stage_ - start_stage_, dims)), dtype=np.float64)
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+
+ if (field_ in out_fields):
+ self.shared_lib.ocp_nlp_out_get_slice.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_out_get_slice(self.nlp_config, \
+ self.nlp_dims, self.nlp_out, start_stage_, end_stage_, field, out_data)
+ elif field_ in mem_fields:
+ self.shared_lib.ocp_nlp_get_at_stage.argtypes = \
+ [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p]
+ self.shared_lib.ocp_nlp_get_at_stage(self.nlp_config, \
+ self.nlp_dims, self.nlp_solver, start_stage_, end_stage_, field, out_data)
+
+ return out
+
+ def get_cost(self):
+ """
+ Returns the cost value of the current solution.
+ """
+ # compute cost internally
+ self.shared_lib.ocp_nlp_eval_cost.argtypes = [c_void_p, c_void_p, c_void_p]
+ self.shared_lib.ocp_nlp_eval_cost(self.nlp_solver, self.nlp_in, self.nlp_out)
+
+ # create output array
+ out = np.ascontiguousarray(np.zeros((1,)), dtype=np.float64)
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+
+ # call getter
+ self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p]
+
+ field = "cost_value".encode('utf-8')
+ self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data)
+
+ return out[0]
diff --git a/pyextra/acados_template/acados_sim.py b/pyextra/acados_template/acados_sim.py
new file mode 100644
index 000000000..3ae198865
--- /dev/null
+++ b/pyextra/acados_template/acados_sim.py
@@ -0,0 +1,294 @@
+# -*- coding: future_fstrings -*-
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import numpy as np
+import casadi as ca
+import os
+from .acados_model import AcadosModel
+from .utils import get_acados_path
+
+class AcadosSimDims:
+ """
+ Class containing the dimensions of the model to be simulated.
+ """
+ def __init__(self):
+ self.__nx = None
+ self.__nu = None
+ self.__nz = 0
+ self.__np = 0
+
+ @property
+ def nx(self):
+ """:math:`n_x` - number of states. Type: int > 0"""
+ return self.__nx
+
+ @property
+ def nz(self):
+ """:math:`n_z` - number of algebraic variables. Type: int >= 0"""
+ return self.__nz
+
+ @property
+ def nu(self):
+ """:math:`n_u` - number of inputs. Type: int >= 0"""
+ return self.__nu
+
+ @property
+ def np(self):
+ """:math:`n_p` - number of parameters. Type: int >= 0"""
+ return self.__np
+
+ @nx.setter
+ def nx(self, nx):
+ if type(nx) == int and nx > 0:
+ self.__nx = nx
+ else:
+ raise Exception('Invalid nx value, expected positive integer. Exiting.')
+
+ @nz.setter
+ def nz(self, nz):
+ if type(nz) == int and nz > -1:
+ self.__nz = nz
+ else:
+ raise Exception('Invalid nz value, expected nonnegative integer. Exiting.')
+
+ @nu.setter
+ def nu(self, nu):
+ if type(nu) == int and nu > -1:
+ self.__nu = nu
+ else:
+ raise Exception('Invalid nu value, expected nonnegative integer. Exiting.')
+
+ @np.setter
+ def np(self, np):
+ if type(np) == int and np > -1:
+ self.__np = np
+ else:
+ raise Exception('Invalid np value, expected nonnegative integer. Exiting.')
+
+ def set(self, attr, value):
+ setattr(self, attr, value)
+
+
+class AcadosSimOpts:
+ """
+ class containing the solver options
+ """
+ def __init__(self):
+ self.__integrator_type = 'ERK'
+ self.__tf = None
+ # ints
+ self.__sim_method_num_stages = 1
+ self.__sim_method_num_steps = 1
+ self.__sim_method_newton_iter = 3
+ # bools
+ self.__sens_forw = True
+ self.__sens_adj = False
+ self.__sens_algebraic = False
+ self.__sens_hess = False
+ self.__output_z = False
+ self.__sim_method_jac_reuse = 0
+
+ @property
+ def integrator_type(self):
+ """Integrator type. Default: 'ERK'."""
+ return self.__integrator_type
+
+ @property
+ def num_stages(self):
+ """Number of stages in the integrator. Default: 1"""
+ return self.__sim_method_num_stages
+
+ @property
+ def num_steps(self):
+ """Number of steps in the integrator. Default: 1"""
+ return self.__sim_method_num_steps
+
+ @property
+ def newton_iter(self):
+ """Number of Newton iterations in simulation method. Default: 3"""
+ return self.__sim_method_newton_iter
+
+ @property
+ def sens_forw(self):
+ """Boolean determining if forward sensitivities are computed. Default: True"""
+ return self.__sens_forw
+
+ @property
+ def sens_adj(self):
+ """Boolean determining if adjoint sensitivities are computed. Default: False"""
+ return self.__sens_adj
+
+ @property
+ def sens_algebraic(self):
+ """Boolean determining if sensitivities wrt algebraic variables are computed. Default: False"""
+ return self.__sens_algebraic
+
+ @property
+ def sens_hess(self):
+ """Boolean determining if hessians are computed. Default: False"""
+ return self.__sens_hess
+
+ @property
+ def output_z(self):
+ """Boolean determining if values for algebraic variables (corresponding to start of simulation interval) are computed. Default: False"""
+ return self.__output_z
+
+ @property
+ def sim_method_jac_reuse(self):
+ """Integer determining if jacobians are reused (0 or 1). Default: 0"""
+ return self.__sim_method_jac_reuse
+
+ @property
+ def T(self):
+ """Time horizon"""
+ return self.__Tsim
+
+ @integrator_type.setter
+ def integrator_type(self, integrator_type):
+ integrator_types = ('ERK', 'IRK', 'GNSF')
+ if integrator_type in integrator_types:
+ self.__integrator_type = integrator_type
+ else:
+ raise Exception('Invalid integrator_type value. Possible values are:\n\n' \
+ + ',\n'.join(integrator_types) + '.\n\nYou have: ' + integrator_type + '.\n\nExiting.')
+
+ @T.setter
+ def T(self, T):
+ self.__Tsim = T
+
+ @num_stages.setter
+ def num_stages(self, num_stages):
+ if isinstance(num_stages, int):
+ self.__sim_method_num_stages = num_stages
+ else:
+ raise Exception('Invalid num_stages value. num_stages must be an integer.')
+
+ @num_steps.setter
+ def num_steps(self, num_steps):
+ if isinstance(num_steps, int):
+ self.__sim_method_num_steps = num_steps
+ else:
+ raise Exception('Invalid num_steps value. num_steps must be an integer.')
+
+ @newton_iter.setter
+ def newton_iter(self, newton_iter):
+ if isinstance(newton_iter, int):
+ self.__sim_method_newton_iter = newton_iter
+ else:
+ raise Exception('Invalid newton_iter value. newton_iter must be an integer.')
+
+ @sens_forw.setter
+ def sens_forw(self, sens_forw):
+ if sens_forw in (True, False):
+ self.__sens_forw = sens_forw
+ else:
+ raise Exception('Invalid sens_forw value. sens_forw must be a Boolean.')
+
+ @sens_adj.setter
+ def sens_adj(self, sens_adj):
+ if sens_adj in (True, False):
+ self.__sens_adj = sens_adj
+ else:
+ raise Exception('Invalid sens_adj value. sens_adj must be a Boolean.')
+
+ @sens_hess.setter
+ def sens_hess(self, sens_hess):
+ if sens_hess in (True, False):
+ self.__sens_hess = sens_hess
+ else:
+ raise Exception('Invalid sens_hess value. sens_hess must be a Boolean.')
+
+ @sens_algebraic.setter
+ def sens_algebraic(self, sens_algebraic):
+ if sens_algebraic in (True, False):
+ self.__sens_algebraic = sens_algebraic
+ else:
+ raise Exception('Invalid sens_algebraic value. sens_algebraic must be a Boolean.')
+
+ @output_z.setter
+ def output_z(self, output_z):
+ if output_z in (True, False):
+ self.__output_z = output_z
+ else:
+ raise Exception('Invalid output_z value. output_z must be a Boolean.')
+
+ @sim_method_jac_reuse.setter
+ def sim_method_jac_reuse(self, sim_method_jac_reuse):
+ if sim_method_jac_reuse in (0, 1):
+ self.__sim_method_jac_reuse = sim_method_jac_reuse
+ else:
+ raise Exception('Invalid sim_method_jac_reuse value. sim_method_jac_reuse must be 0 or 1.')
+
+class AcadosSim:
+ """
+ The class has the following properties that can be modified to formulate a specific simulation problem, see below:
+
+ :param acados_path: string with the path to acados. It is used to generate the include and lib paths.
+
+ - :py:attr:`dims` of type :py:class:`acados_template.acados_ocp.AcadosSimDims` - are automatically detected from model
+ - :py:attr:`model` of type :py:class:`acados_template.acados_model.AcadosModel`
+ - :py:attr:`solver_options` of type :py:class:`acados_template.acados_sim.AcadosSimOpts`
+
+ - :py:attr:`acados_include_path` (set automatically)
+ - :py:attr:`acados_lib_path` (set automatically)
+ """
+ def __init__(self, acados_path=''):
+ if acados_path == '':
+ acados_path = get_acados_path()
+ self.dims = AcadosSimDims()
+ """Dimension definitions, automatically detected from :py:attr:`model`. Type :py:class:`acados_template.acados_sim.AcadosSimDims`"""
+ self.model = AcadosModel()
+ """Model definitions, type :py:class:`acados_template.acados_model.AcadosModel`"""
+ self.solver_options = AcadosSimOpts()
+ """Solver Options, type :py:class:`acados_template.acados_sim.AcadosSimOpts`"""
+
+ self.acados_include_path = f'{acados_path}/include'
+ """Path to acados include directors (set automatically), type: `string`"""
+ self.acados_lib_path = f'{acados_path}/lib'
+ """Path to where acados library is located (set automatically), type: `string`"""
+
+ self.code_export_directory = 'c_generated_code'
+ """Path to where code will be exported. Default: `c_generated_code`."""
+
+ def set(self, attr, value):
+ # tokenize string
+ tokens = attr.split('_', 1)
+ if len(tokens) > 1:
+ setter_to_call = getattr(getattr(self, tokens[0]), 'set')
+ else:
+ setter_to_call = getattr(self, 'set')
+
+ setter_to_call(tokens[1], value)
+
+ return
diff --git a/pyextra/acados_template/acados_sim_layout.json b/pyextra/acados_template/acados_sim_layout.json
new file mode 100644
index 000000000..c8f4280b8
--- /dev/null
+++ b/pyextra/acados_template/acados_sim_layout.json
@@ -0,0 +1,44 @@
+{
+ "acados_include_path": [
+ "str"
+ ],
+ "model": {
+ "name" : [
+ "str"
+ ]
+ },
+ "acados_lib_path": [
+ "str"
+ ],
+ "dims": {
+ "np": [
+ "int"
+ ],
+ "nu": [
+ "int"
+ ],
+ "nx": [
+ "int"
+ ],
+ "nz": [
+ "int"
+ ]
+ },
+ "solver_options": {
+ "integrator_type": [
+ "str"
+ ],
+ "Tsim": [
+ "float"
+ ],
+ "sim_method_num_stages": [
+ "int"
+ ],
+ "sim_method_num_steps": [
+ "int"
+ ],
+ "sim_method_newton_iter": [
+ "int"
+ ]
+ }
+}
diff --git a/pyextra/acados_template/acados_sim_solver.py b/pyextra/acados_template/acados_sim_solver.py
new file mode 100644
index 000000000..a5447907b
--- /dev/null
+++ b/pyextra/acados_template/acados_sim_solver.py
@@ -0,0 +1,407 @@
+# -*- coding: future_fstrings -*-
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import sys, os, json
+
+import numpy as np
+
+from ctypes import *
+from copy import deepcopy
+
+from .generate_c_code_explicit_ode import generate_c_code_explicit_ode
+from .generate_c_code_implicit_ode import generate_c_code_implicit_ode
+from .generate_c_code_gnsf import generate_c_code_gnsf
+from .acados_sim import AcadosSim
+from .acados_ocp import AcadosOcp
+from .acados_model import acados_model_strip_casadi_symbolics
+from .utils import is_column, render_template, format_class_dict, np_array_to_list,\
+ make_model_consistent, set_up_imported_gnsf_model
+
+
+def make_sim_dims_consistent(acados_sim):
+ dims = acados_sim.dims
+ model = acados_sim.model
+ # nx
+ if is_column(model.x):
+ dims.nx = model.x.shape[0]
+ else:
+ raise Exception("model.x should be column vector!")
+
+ # nu
+ if is_column(model.u):
+ dims.nu = model.u.shape[0]
+ elif model.u == None or model.u == []:
+ dims.nu = 0
+ else:
+ raise Exception("model.u should be column vector or None!")
+
+ # nz
+ if is_column(model.z):
+ dims.nz = model.z.shape[0]
+ elif model.z == None or model.z == []:
+ dims.nz = 0
+ else:
+ raise Exception("model.z should be column vector or None!")
+
+ # np
+ if is_column(model.p):
+ dims.np = model.p.shape[0]
+ elif model.p == None or model.p == []:
+ dims.np = 0
+ else:
+ raise Exception("model.p should be column vector or None!")
+
+
+def get_sim_layout():
+ current_module = sys.modules[__name__]
+ acados_path = os.path.dirname(current_module.__file__)
+ with open(acados_path + '/acados_sim_layout.json', 'r') as f:
+ sim_layout = json.load(f)
+ return sim_layout
+
+
+
+def sim_formulation_json_dump(acados_sim, json_file='acados_sim.json'):
+ # Load acados_sim structure description
+ sim_layout = get_sim_layout()
+
+ # Copy input sim object dictionary
+ sim_dict = dict(deepcopy(acados_sim).__dict__)
+
+ for key, v in sim_layout.items():
+ # skip non dict attributes
+ if not isinstance(v, dict): continue
+ # Copy sim object attributes dictionaries
+ sim_dict[key]=dict(getattr(acados_sim, key).__dict__)
+
+ sim_dict['model'] = acados_model_strip_casadi_symbolics(sim_dict['model'])
+ sim_json = format_class_dict(sim_dict)
+
+ with open(json_file, 'w') as f:
+ json.dump(sim_json, f, default=np_array_to_list, indent=4, sort_keys=True)
+
+
+def sim_render_templates(json_file, model_name, code_export_dir):
+ # setting up loader and environment
+ json_path = '{cwd}/{json_file}'.format(
+ cwd=os.getcwd(),
+ json_file=json_file)
+
+ if not os.path.exists(json_path):
+ raise Exception(f"{json_path} not found!")
+
+ template_dir = code_export_dir
+
+ ## Render templates
+ in_file = 'acados_sim_solver.in.c'
+ out_file = f'acados_sim_solver_{model_name}.c'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'acados_sim_solver.in.h'
+ out_file = f'acados_sim_solver_{model_name}.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'Makefile.in'
+ out_file = f'Makefile'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ in_file = 'main_sim.in.c'
+ out_file = f'main_sim_{model_name}.c'
+ render_template(in_file, out_file, template_dir, json_path)
+
+ ## folder model
+ template_dir = f'{code_export_dir}/{model_name}_model/'
+
+ in_file = 'model.in.h'
+ out_file = f'{model_name}_model.h'
+ render_template(in_file, out_file, template_dir, json_path)
+
+
+def sim_generate_casadi_functions(acados_sim):
+ model = acados_sim.model
+ model = make_model_consistent(model)
+
+ integrator_type = acados_sim.solver_options.integrator_type
+
+ opts = dict(generate_hess = acados_sim.solver_options.sens_hess,
+ code_export_directory = acados_sim.code_export_directory)
+ # generate external functions
+ if integrator_type == 'ERK':
+ generate_c_code_explicit_ode(model, opts)
+ elif integrator_type == 'IRK':
+ generate_c_code_implicit_ode(model, opts)
+ elif integrator_type == 'GNSF':
+ generate_c_code_gnsf(model, opts)
+
+class AcadosSimSolver:
+ """
+ Class to interact with the acados integrator C object.
+
+ :param acados_sim: type :py:class:`acados_template.acados_ocp.AcadosOcp` (takes values to generate an instance :py:class:`acados_template.acados_sim.AcadosSim`) or :py:class:`acados_template.acados_sim.AcadosSim`
+ :param json_file: Default: 'acados_sim.json'
+ :param build: Default: True
+ """
+ def __init__(self, acados_sim_, json_file='acados_sim.json', build=True):
+
+ self.solver_created = False
+
+ if isinstance(acados_sim_, AcadosOcp):
+ # set up acados_sim_
+ acados_sim = AcadosSim()
+ acados_sim.model = acados_sim_.model
+ acados_sim.dims.nx = acados_sim_.dims.nx
+ acados_sim.dims.nu = acados_sim_.dims.nu
+ acados_sim.dims.nz = acados_sim_.dims.nz
+ acados_sim.dims.np = acados_sim_.dims.np
+ acados_sim.solver_options.integrator_type = acados_sim_.solver_options.integrator_type
+ acados_sim.code_export_directory = acados_sim_.code_export_directory
+
+ elif isinstance(acados_sim_, AcadosSim):
+ acados_sim = acados_sim_
+
+ acados_sim.__problem_class = 'SIM'
+
+ model_name = acados_sim.model.name
+ make_sim_dims_consistent(acados_sim)
+
+ # reuse existing json and casadi functions, when creating integrator from ocp
+ if isinstance(acados_sim_, AcadosSim):
+ if acados_sim.solver_options.integrator_type == 'GNSF':
+ set_up_imported_gnsf_model(acados_sim)
+
+ sim_generate_casadi_functions(acados_sim)
+ sim_formulation_json_dump(acados_sim, json_file)
+
+ code_export_dir = acados_sim.code_export_directory
+ if build:
+ # render templates
+ sim_render_templates(json_file, model_name, code_export_dir)
+
+ ## Compile solver
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ os.system('make sim_shared_lib')
+ os.chdir(cwd)
+
+ self.sim_struct = acados_sim
+ model_name = self.sim_struct.model.name
+ self.model_name = model_name
+
+ # Ctypes
+ shared_lib = f'{code_export_dir}/libacados_sim_solver_{model_name}.so'
+ self.shared_lib = CDLL(shared_lib)
+
+
+ # create capsule
+ getattr(self.shared_lib, f"{model_name}_acados_sim_solver_create_capsule").restype = c_void_p
+ self.capsule = getattr(self.shared_lib, f"{model_name}_acados_sim_solver_create_capsule")()
+
+ # create solver
+ getattr(self.shared_lib, f"{model_name}_acados_sim_create").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_sim_create").restype = c_int
+ assert getattr(self.shared_lib, f"{model_name}_acados_sim_create")(self.capsule)==0
+ self.solver_created = True
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_opts").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_opts").restype = c_void_p
+ self.sim_opts = getattr(self.shared_lib, f"{model_name}_acados_get_sim_opts")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_dims").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_dims").restype = c_void_p
+ self.sim_dims = getattr(self.shared_lib, f"{model_name}_acados_get_sim_dims")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_config").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_config").restype = c_void_p
+ self.sim_config = getattr(self.shared_lib, f"{model_name}_acados_get_sim_config")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_out").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_out").restype = c_void_p
+ self.sim_out = getattr(self.shared_lib, f"{model_name}_acados_get_sim_out")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_in").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_in").restype = c_void_p
+ self.sim_in = getattr(self.shared_lib, f"{model_name}_acados_get_sim_in")(self.capsule)
+
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_solver").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{model_name}_acados_get_sim_solver").restype = c_void_p
+ self.sim_solver = getattr(self.shared_lib, f"{model_name}_acados_get_sim_solver")(self.capsule)
+
+ nu = self.sim_struct.dims.nu
+ nx = self.sim_struct.dims.nx
+ nz = self.sim_struct.dims.nz
+ self.gettable = {
+ 'x': nx,
+ 'xn': nx,
+ 'u': nu,
+ 'z': nz,
+ 'S_forw': nx*(nx+nu),
+ 'Sx': nx*nx,
+ 'Su': nx*nu,
+ 'S_adj': nx+nu,
+ 'S_hess': (nx+nu)*(nx+nu),
+ 'S_algebraic': (nz)*(nx+nu),
+ }
+
+ self.settable = ['S_adj', 'T', 'x', 'u', 'xdot', 'z', 'p'] # S_forw
+
+
+ def solve(self):
+ """
+ Solve the simulation problem with current input.
+ """
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_solve").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_solve").restype = c_int
+
+ status = getattr(self.shared_lib, f"{self.model_name}_acados_sim_solve")(self.capsule)
+ return status
+
+
+ def get(self, field_):
+ """
+ Get the last solution of the solver.
+
+ :param str field: string in ['x', 'u', 'z', 'S_forw', 'Sx', 'Su', 'S_adj', 'S_hess', 'S_algebraic']
+ """
+ field = field_
+ field = field.encode('utf-8')
+
+ if field_ in self.gettable.keys():
+
+ # allocate array
+ dims = self.gettable[field_]
+ out = np.ascontiguousarray(np.zeros((dims,)), dtype=np.float64)
+ out_data = cast(out.ctypes.data, POINTER(c_double))
+
+ self.shared_lib.sim_out_get.argtypes = [c_void_p, c_void_p, c_void_p, c_char_p, c_void_p]
+ self.shared_lib.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, out_data)
+
+ if field_ == 'S_forw':
+ nu = self.sim_struct.dims.nu
+ nx = self.sim_struct.dims.nx
+ out = out.reshape(nx, nx+nu, order='F')
+ elif field_ == 'Sx':
+ nx = self.sim_struct.dims.nx
+ out = out.reshape(nx, nx, order='F')
+ elif field_ == 'Su':
+ nx = self.sim_struct.dims.nx
+ nu = self.sim_struct.dims.nu
+ out = out.reshape(nx, nu, order='F')
+ elif field_ == 'S_hess':
+ nx = self.sim_struct.dims.nx
+ nu = self.sim_struct.dims.nu
+ out = out.reshape(nx+nu, nx+nu, order='F')
+ elif field_ == 'S_algebraic':
+ nx = self.sim_struct.dims.nx
+ nu = self.sim_struct.dims.nu
+ nz = self.sim_struct.dims.nz
+ out = out.reshape(nz, nx+nu, order='F')
+ else:
+ raise Exception(f'AcadosSimSolver.get(): Unknown field {field_},' \
+ f' available fields are {", ".join(self.gettable.keys())}')
+
+ return out
+
+
+ def set(self, field_, value_):
+ """
+ Set numerical data inside the solver.
+
+ :param field: string in ['p', 'S_adj', 'T', 'x', 'u', 'xdot', 'z']
+ :param value: the value with appropriate size.
+ """
+ # cast value_ to avoid conversion issues
+ if isinstance(value_, (float, int)):
+ value_ = np.array([value_])
+
+ value_ = value_.astype(float)
+ value_data = cast(value_.ctypes.data, POINTER(c_double))
+ value_data_p = cast((value_data), c_void_p)
+
+ field = field_
+ field = field.encode('utf-8')
+
+ # treat parameters separately
+ if field_ == 'p':
+ model_name = self.sim_struct.model.name
+ getattr(self.shared_lib, f"{model_name}_acados_sim_update_params").argtypes = [c_void_p, POINTER(c_double), c_int]
+ value_data = cast(value_.ctypes.data, POINTER(c_double))
+ getattr(self.shared_lib, f"{model_name}_acados_sim_update_params")(self.capsule, value_data, value_.shape[0])
+ return
+ else:
+ # dimension check
+ dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc)
+ dims_data = cast(dims.ctypes.data, POINTER(c_int))
+
+ self.shared_lib.sim_dims_get_from_attr.argtypes = [c_void_p, c_void_p, c_char_p, POINTER(c_int)]
+ self.shared_lib.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, dims_data)
+
+ value_ = np.ravel(value_, order='F')
+
+ value_shape = value_.shape
+ if len(value_shape) == 1:
+ value_shape = (value_shape[0], 0)
+
+ if value_shape != tuple(dims):
+ raise Exception('AcadosSimSolver.set(): mismatching dimension' \
+ ' for field "{}" with dimension {} (you have {})'.format(field_, tuple(dims), value_shape))
+
+ # set
+ if field_ in ['xdot', 'z']:
+ self.shared_lib.sim_solver_set.argtypes = [c_void_p, c_char_p, c_void_p]
+ self.shared_lib.sim_solver_set(self.sim_solver, field, value_data_p)
+ elif field_ in self.settable:
+ self.shared_lib.sim_in_set.argtypes = [c_void_p, c_void_p, c_void_p, c_char_p, c_void_p]
+ self.shared_lib.sim_in_set(self.sim_config, self.sim_dims, self.sim_in, field, value_data_p)
+ else:
+ raise Exception(f'AcadosSimSolver.set(): Unknown field {field_},' \
+ f' available fields are {", ".join(self.settable)}')
+
+ return
+
+
+ def __del__(self):
+
+ if self.solver_created:
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_free").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_free").restype = c_int
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_free")(self.capsule)
+
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_solver_free_capsule").argtypes = [c_void_p]
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_solver_free_capsule").restype = c_int
+ getattr(self.shared_lib, f"{self.model_name}_acados_sim_solver_free_capsule")(self.capsule)
+
+ try:
+ self.dlclose(self.shared_lib._handle)
+ except:
+ pass
diff --git a/pyextra/acados_template/c_templates_tera/CPPLINT.cfg b/pyextra/acados_template/c_templates_tera/CPPLINT.cfg
new file mode 100644
index 000000000..bbd1caf05
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/CPPLINT.cfg
@@ -0,0 +1 @@
+exclude_files=[main, acados_solver, acados_solver_sfun, Makefile, model].*\.?
diff --git a/pyextra/acados_template/c_templates_tera/Makefile.in b/pyextra/acados_template/c_templates_tera/Makefile.in
new file mode 100644
index 000000000..330a5aba1
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/Makefile.in
@@ -0,0 +1,499 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+{%- if solver_options.qp_solver %}
+ {%- set qp_solver = solver_options.qp_solver %}
+{%- else %}
+ {%- set qp_solver = "FULL_CONDENSING_HPIPM" %}
+{%- endif %}
+
+{%- if solver_options.hessian_approx %}
+ {%- set hessian_approx = solver_options.hessian_approx %}
+{%- elif solver_options.sens_hess %}
+ {%- set hessian_approx = "EXACT" %}
+{%- else %}
+ {%- set hessian_approx = "GAUSS_NEWTON" %}
+{%- endif %}
+
+{%- if constraints.constr_type %}
+ {%- set constr_type = constraints.constr_type %}
+{%- else %}
+ {%- set constr_type = "NONE" %}
+{%- endif %}
+
+{%- if constraints.constr_type_e %}
+ {%- set constr_type_e = constraints.constr_type_e %}
+{%- else %}
+ {%- set constr_type_e = "NONE" %}
+{%- endif %}
+
+{%- if cost.cost_type %}
+ {%- set cost_type = cost.cost_type %}
+{%- else %}
+ {%- set cost_type = "NONE" %}
+{%- endif %}
+
+{%- if cost.cost_type_e %}
+ {%- set cost_type_e = cost.cost_type_e %}
+{%- else %}
+ {%- set cost_type_e = "NONE" %}
+{%- endif %}
+
+{%- if cost.cost_type_0 %}
+ {%- set cost_type_0 = cost.cost_type_0 %}
+{%- else %}
+ {%- set cost_type_0 = "NONE" %}
+{%- endif %}
+
+{%- if dims.nh %}
+ {%- set dims_nh = dims.nh %}
+{%- else %}
+ {%- set dims_nh = 0 %}
+{%- endif %}
+
+{%- if dims.nphi %}
+ {%- set dims_nphi = dims.nphi %}
+{%- else %}
+ {%- set dims_nphi = 0 %}
+{%- endif %}
+
+{%- if dims.nh_e %}
+ {%- set dims_nh_e = dims.nh_e %}
+{%- else %}
+ {%- set dims_nh_e = 0 %}
+{%- endif %}
+
+{%- if dims.nphi_e %}
+ {%- set dims_nphi_e = dims.nphi_e %}
+{%- else %}
+ {%- set dims_nphi_e = 0 %}
+{%- endif %}
+{%- if solver_options.model_external_shared_lib_dir %}
+ {%- set model_external_shared_lib_dir = solver_options.model_external_shared_lib_dir %}
+{%- endif %}
+{%- if solver_options.model_external_shared_lib_name %}
+ {%- set model_external_shared_lib_name = solver_options.model_external_shared_lib_name %}
+{%- endif %}
+
+{# control operator #}
+{%- if os and os == "pc" %}
+ {%- set control = "&" %}
+{%- else %}
+ {%- set control = ";" %}
+{%- endif %}
+
+{# acados linking libraries and flags #}
+{%- if acados_link_libs and os and os == "pc" %}
+ {%- set link_libs = acados_link_libs.qpoases ~ " " ~ acados_link_libs.hpmpc ~ " " ~ acados_link_libs.osqp -%}
+ {%- set openmp_flag = acados_link_libs.openmp %}
+{%- else %}
+ {%- set openmp_flag = " " %}
+ {%- if qp_solver == "FULL_CONDENSING_QPOASES" %}
+ {%- set link_libs = "-lqpOASES_e" %}
+ {%- else %}
+ {%- set link_libs = "" %}
+ {%- endif %}
+{%- endif %}
+
+{# acados flags #}
+ACADOS_FLAGS = -fPIC -std=c99 {{ openmp_flag }} #-fno-diagnostics-show-line-numbers -g
+{%- if qp_solver == "FULL_CONDENSING_QPOASES" %}
+ACADOS_FLAGS += -DACADOS_WITH_QPOASES
+{%- endif %}
+{%- if qp_solver == "PARTIAL_CONDENSING_OSQP" %}
+ACADOS_FLAGS += -DACADOS_WITH_OSQP
+{%- endif %}
+{%- if qp_solver == "PARTIAL_CONDENSING_QPDUNES" %}
+ACADOS_FLAGS += -DACADOS_WITH_QPDUNES
+{%- endif %}
+# # Debugging
+# ACADOS_FLAGS += -g3
+
+MODEL_OBJ=
+{%- if solver_options.integrator_type == "ERK" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_expl_ode_fun.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_expl_vde_forw.o
+{%- if hessian_approx == "EXACT" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_expl_ode_hess.o
+{%- endif %}
+{%- elif solver_options.integrator_type == "IRK" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_z.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_impl_dae_jac_x_xdot_u_z.o
+{%- if hessian_approx == "EXACT" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_impl_dae_hess.o
+{%- endif %}
+{%- elif solver_options.integrator_type == "LIFTED_IRK" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_u.o
+{%- if hessian_approx == "EXACT" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_impl_dae_hess.o
+{%- endif %}
+{%- elif solver_options.integrator_type == "GNSF" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_gnsf_phi_fun.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_gnsf_phi_fun_jac_y.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_gnsf_phi_jac_y_uhat.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_gnsf_get_matrices_fun.o
+{%- elif solver_options.integrator_type == "DISCRETE" %}
+{%- if model.dyn_ext_fun_type == "casadi" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun.o
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac.o
+{%- if hessian_approx == "EXACT" %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac_hess.o
+{%- endif %}
+{%- else %}
+MODEL_OBJ+= {{ model.name }}_model/{{ model.dyn_source_discrete }}
+{%- endif %}
+{%- endif %}
+
+
+OCP_OBJ=
+{%- if constr_type == "BGP" and dims_nphi > 0 %}
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_phi_constraint.o
+{%- endif %}
+{%- if constr_type_e == "BGP" and dims_nphi_e > 0 %}
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_phi_e_constraint.o
+{%- endif %}
+
+{%- if constr_type == "BGH" and dims_nh > 0 %}
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt.o
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_constr_h_fun.o
+{%- if hessian_approx == "EXACT" %}
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt_hess.o
+{%- endif %}
+{%- endif %}
+
+{%- if constr_type_e == "BGH" and dims_nh_e > 0 %}
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt.o
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun.o
+{%- if hessian_approx == "EXACT" %}
+OCP_OBJ+= {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess.o
+{%- endif %}
+{%- endif %}
+
+{%- if cost_type_0 == "NONLINEAR_LS" %}
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_0_fun.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_0_fun_jac_ut_xt.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_0_hess.c
+{%- elif cost_type_0 == "EXTERNAL" %}
+{% if cost.cost_ext_fun_type_0 == "casadi" %}
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac_hess.c
+{% else %}
+OCP_OBJ+= {{ model.name }}_cost/{{ cost.cost_source_ext_cost_0 }}
+{% endif %}
+{%- endif %}
+{%- if cost_type == "NONLINEAR_LS" %}
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_fun.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_fun_jac_ut_xt.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_hess.c
+{%- elif cost_type == "EXTERNAL" %}
+{% if cost.cost_ext_fun_type == "casadi" %}
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac_hess.c
+{% elif cost.cost_source_ext_cost != cost.cost_source_ext_cost_0 %}
+OCP_OBJ+= {{ model.name }}_cost/{{ cost.cost_source_ext_cost }}
+{% endif %}
+{%- endif %}
+{%- if cost_type_e == "NONLINEAR_LS" %}
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_e_fun.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_e_fun_jac_ut_xt.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_y_e_hess.c
+{%- elif cost_type_e == "EXTERNAL" %}
+{% if cost.cost_ext_fun_type_e == "casadi" %}
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac.c
+OCP_OBJ+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac_hess.c
+{% elif cost.cost_source_ext_cost_e != cost.cost_source_ext_cost_0 %}
+OCP_OBJ+= {{ model.name }}_cost/{{ cost.cost_source_ext_cost_e }}
+{% endif %}
+{%- endif %}
+OCP_OBJ+= acados_solver_{{ model.name }}.o
+
+
+SIM_OBJ=
+SIM_OBJ+= acados_sim_solver_{{ model.name }}.o
+
+EX_OBJ=
+EX_OBJ+= main_{{ model.name }}.o
+
+EX_SIM_OBJ=
+EX_SIM_OBJ+= main_sim_{{ model.name }}.o
+
+OBJ=
+OBJ+= $(MODEL_OBJ)
+{%- if solver_options.integrator_type != "DISCRETE" %}
+OBJ+= $(SIM_OBJ)
+{%- endif %}
+OBJ+= $(OCP_OBJ)
+
+EXTERNAL_DIR=
+EXTERNAL_LIB=
+
+{%- if model_external_shared_lib_dir and model_external_shared_lib_name %}
+EXTERNAL_DIR+= {{ model_external_shared_lib_dir }}
+EXTERNAL_LIB+= {{ model_external_shared_lib_name }}
+{%- endif %}
+
+INCLUDE_PATH = {{ acados_include_path }}
+LIB_PATH = {{ acados_lib_path }}
+
+{%- if solver_options.integrator_type == "DISCRETE" %}
+all: clean casadi_fun example
+shared_lib: ocp_shared_lib
+{%- else %}
+all: clean casadi_fun example_sim example
+shared_lib: bundled_shared_lib ocp_shared_lib sim_shared_lib
+{%- endif %}
+
+CASADI_MODEL_SOURCE=
+{%- if solver_options.integrator_type == "ERK" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_expl_ode_fun.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_expl_vde_forw.c
+{%- if hessian_approx == "EXACT" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_expl_ode_hess.c
+{%- endif %}
+{%- elif solver_options.integrator_type == "IRK" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_fun.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_fun_jac_x_xdot_z.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_jac_x_xdot_u_z.c
+{%- if hessian_approx == "EXACT" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_hess.c
+{%- endif %}
+{%- elif solver_options.integrator_type == "LIFTED_IRK" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_fun.c
+# CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_fun_jac_x_xdot_z.c
+# CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_jac_x_xdot_u_z.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_fun_jac_x_xdot_u.c
+{%- if hessian_approx == "EXACT" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_impl_dae_hess.c
+{%- endif %}
+{%- elif solver_options.integrator_type == "GNSF" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_gnsf_phi_fun.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_gnsf_phi_fun_jac_y.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_gnsf_phi_jac_y_uhat.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_gnsf_get_matrices_fun.c
+{%- elif solver_options.integrator_type == "DISCRETE" and model.dyn_ext_fun_type == "casadi" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_dyn_disc_phi_fun.c
+CASADI_MODEL_SOURCE+= {{ model.name }}_dyn_disc_phi_fun_jac.c
+{%- if hessian_approx == "EXACT" %}
+CASADI_MODEL_SOURCE+= {{ model.name }}_dyn_disc_phi_fun_jac_hess.c
+{%- endif %}
+{%- endif %}
+{%- if constr_type == "BGP" and dims_nphi > 0 %}
+CASADI_CON_PHI_SOURCE=
+CASADI_CON_PHI_SOURCE+= {{ model.name }}_phi_constraint.c
+{%- endif %}
+{%- if constr_type_e == "BGP" and dims_nphi_e > 0 %}
+CASADI_CON_PHI_E_SOURCE=
+CASADI_CON_PHI_E_SOURCE+= {{ model.name }}_phi_e_constraint.c
+{%- endif %}
+{%- if constr_type == "BGH" and dims_nh > 0 %}
+CASADI_CON_H_SOURCE=
+CASADI_CON_H_SOURCE+= {{ model.name }}_constr_h_fun_jac_uxt_zt.c
+CASADI_CON_H_SOURCE+= {{ model.name }}_constr_h_fun.c
+{%- if hessian_approx == "EXACT" %}
+CASADI_CON_H_SOURCE+= {{ model.name }}_constr_h_fun_jac_uxt_zt_hess.c
+{%- endif %}
+{%- endif %}
+
+{%- if dims_nh_e > 0 %}
+CASADI_CON_H_E_SOURCE=
+CASADI_CON_H_E_SOURCE+= {{ model.name }}_constr_h_e_fun_jac_uxt_zt.c
+CASADI_CON_H_E_SOURCE+= {{ model.name }}_constr_h_e_fun.c
+{%- if hessian_approx == "EXACT" %}
+CASADI_CON_H_E_SOURCE+= {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess.c
+{%- endif %}
+{%- endif %}
+
+{%- if cost_type == "NONLINEAR_LS" %}
+CASADI_COST_Y_SOURCE=
+CASADI_COST_Y_SOURCE+= {{ model.name }}_cost_y_fun.c
+CASADI_COST_Y_SOURCE+= {{ model.name }}_cost_y_fun_jac_ut_xt.c
+CASADI_COST_Y_SOURCE+= {{ model.name }}_cost_y_hess.c
+{%- endif %}
+{%- if cost_type_e == "NONLINEAR_LS" %}
+CASADI_COST_Y_E_SOURCE=
+CASADI_COST_Y_E_SOURCE+= {{ model.name }}_cost_y_e_fun.c
+CASADI_COST_Y_E_SOURCE+= {{ model.name }}_cost_y_e_fun_jac_ut_xt.c
+CASADI_COST_Y_E_SOURCE+= {{ model.name }}_cost_y_e_hess.c
+{%- endif %}
+{%- if cost_type_0 == "NONLINEAR_LS" %}
+CASADI_COST_Y_0_SOURCE=
+CASADI_COST_Y_0_SOURCE+= {{ model.name }}_cost_y_0_fun.c
+CASADI_COST_Y_0_SOURCE+= {{ model.name }}_cost_y_0_fun_jac_ut_xt.c
+CASADI_COST_Y_0_SOURCE+= {{ model.name }}_cost_y_0_hess.c
+{%- endif %}
+
+casadi_fun:
+ {%- if model.dyn_ext_fun_type == "casadi" %}
+ ( cd {{ model.name }}_model {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_MODEL_SOURCE))
+ {%- endif %}
+ {%- if constr_type == "BGP" and dims_nphi > 0 %}
+ ( cd {{ model.name }}_constraints {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_CON_PHI_SOURCE))
+ {%- endif %}
+ {%- if constr_type_e == "BGP" and dims_nphi_e > 0 %}
+ ( cd {{ model.name }}_constraints {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_CON_PHI_E_SOURCE))
+ {%- endif %}
+ {%- if constr_type == "BGH" and dims_nh > 0 %}
+ ( cd {{ model.name }}_constraints {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_CON_H_SOURCE))
+ {%- endif %}
+ {%- if constr_type_e == "BGH" and dims_nh_e > 0 %}
+ ( cd {{ model.name }}_constraints {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_CON_H_E_SOURCE))
+ {%- endif %}
+ {%- if cost_type == "NONLINEAR_LS" %}
+ ( cd {{ model.name }}_cost {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_COST_Y_SOURCE))
+ {%- endif %}
+ {%- if cost_type_e == "NONLINEAR_LS" %}
+ ( cd {{ model.name }}_cost {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_COST_Y_E_SOURCE))
+ {%- endif %}
+ {%- if cost_type_0 == "NONLINEAR_LS" %}
+ ( cd {{ model.name }}_cost {{ control }} gcc $(ACADOS_FLAGS) -c $(CASADI_COST_Y_0_SOURCE))
+ {%- endif %}
+
+main:
+ gcc $(ACADOS_FLAGS) -c main_{{ model.name }}.c -I $(INCLUDE_PATH)/blasfeo/include/ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) -I $(INCLUDE_PATH)/acados/ \
+ {%- if qp_solver == "FULL_CONDENSING_QPOASES" %}
+ -I $(INCLUDE_PATH)/qpOASES_e/
+ {%- endif %}
+
+main_sim:
+ gcc $(ACADOS_FLAGS) -c main_sim_{{ model.name }}.c -I $(INCLUDE_PATH)/blasfeo/include/ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) -I $(INCLUDE_PATH)/acados/
+
+ocp_solver:
+ gcc $(ACADOS_FLAGS) -c acados_solver_{{ model.name }}.c -I $(INCLUDE_PATH)/blasfeo/include/ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) -I $(INCLUDE_PATH)/acados/ \
+ {%- if qp_solver == "FULL_CONDENSING_QPOASES" %}
+ -I $(INCLUDE_PATH)/qpOASES_e/
+ {%- endif %}
+
+sim_solver:
+ gcc $(ACADOS_FLAGS) -c acados_sim_solver_{{ model.name }}.c -I $(INCLUDE_PATH)/blasfeo/include/ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) -I $(INCLUDE_PATH)/acados/ \
+ {%- if qp_solver == "FULL_CONDENSING_QPOASES" %}
+ -I $(INCLUDE_PATH)/qpOASES_e/
+ {%- endif %}
+
+example: ocp_solver main
+ gcc $(ACADOS_FLAGS) -o main_{{ model.name }} $(EX_OBJ) $(OBJ) -L $(LIB_PATH) \
+ -lacados -lhpipm -lblasfeo \
+ {{ link_libs }} \
+ -lm \
+ -I $(INCLUDE_PATH)/blasfeo/include/ \
+ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) \
+ -I $(INCLUDE_PATH)/acados/ \
+ {%- if qp_solver == "FULL_CONDENSING_QPOASES" %}
+ -I $(INCLUDE_PATH)/qpOASES_e/
+ {%- endif %}
+
+
+example_sim: sim_solver main_sim
+ gcc $(ACADOS_FLAGS) -o main_sim_{{ model.name }} $(EX_SIM_OBJ) $(MODEL_OBJ) $(SIM_OBJ) -L $(LIB_PATH) \
+ -lacados -lhpipm -lblasfeo \
+ {{ link_libs }} \
+ -lm \
+ -I $(INCLUDE_PATH)/blasfeo/include/ \
+ -I $(INCLUDE_PATH)/acados/ \
+
+{%- if solver_options.integrator_type != "DISCRETE" %}
+
+bundled_shared_lib: casadi_fun ocp_solver sim_solver
+ gcc $(ACADOS_FLAGS) -shared -o libacados_solver_{{ model.name }}.so $(OBJ) \
+ -I $(INCLUDE_PATH)/blasfeo/include/ \
+ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) \
+ -L $(LIB_PATH) \
+ -lacados -lhpipm -lblasfeo \
+ {{ link_libs }} \
+ -lm \
+
+ocp_shared_lib: casadi_fun ocp_solver
+ gcc $(ACADOS_FLAGS) -shared -o libacados_ocp_solver_{{ model.name }}.so $(OCP_OBJ) $(MODEL_OBJ) \
+ -I $(INCLUDE_PATH)/blasfeo/include/ \
+ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) \
+ -L$(EXTERNAL_DIR) -l$(EXTERNAL_LIB) \
+ -L $(LIB_PATH) -lacados -lhpipm -lblasfeo \
+ {{ link_libs }} \
+ -lm \
+
+{%- else %}
+
+ocp_shared_lib: casadi_fun ocp_solver
+ gcc $(ACADOS_FLAGS) -shared -o libacados_ocp_solver_{{ model.name }}.so $(OCP_OBJ) $(MODEL_OBJ) \
+ -I $(INCLUDE_PATH)/blasfeo/include/ \
+ -I $(INCLUDE_PATH)/hpipm/include/ \
+ -I $(INCLUDE_PATH) \
+ -L$(EXTERNAL_DIR) -l$(EXTERNAL_LIB) \
+ -L $(LIB_PATH) -lacados -lhpipm -lblasfeo \
+ {{ link_libs }} \
+ -lm \
+
+{%- endif %}
+
+sim_shared_lib: casadi_fun sim_solver
+ gcc $(ACADOS_FLAGS) -shared -o libacados_sim_solver_{{ model.name }}.so $(SIM_OBJ) $(MODEL_OBJ) -L$(EXTERNAL_DIR) -l$(EXTERNAL_LIB) \
+ -L $(LIB_PATH) -lacados -lhpipm -lblasfeo \
+ {{ link_libs }} \
+ -lm \
+
+{%- if os and os == "pc" %}
+
+clean:
+ del \Q *.o 2>nul
+ del \Q *.so 2>nul
+ del \Q main_{{ model.name }} 2>nul
+
+clean_ocp_shared_lib:
+ del \Q libacados_ocp_solver_{{ model.name }}.so 2>nul
+ del \Q acados_solver_{{ model.name }}.o 2>nul
+
+{%- else %}
+
+clean:
+ rm -f *.o
+ rm -f *.so
+ rm -f main_{{ model.name }}
+
+clean_ocp_shared_lib:
+ rm -f libacados_ocp_solver_{{ model.name }}.so
+ rm -f acados_solver_{{ model.name }}.o
+
+{%- endif %}
diff --git a/pyextra/acados_template/c_templates_tera/acados_mex_create.in.c b/pyextra/acados_template/c_templates_tera/acados_mex_create.in.c
new file mode 100644
index 000000000..7fa08d8f7
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_mex_create.in.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+// standard
+#include
+#include
+#include
+
+// acados
+#include "acados/utils/print.h"
+#include "acados_c/ocp_nlp_interface.h"
+#include "acados_solver_{{ model.name }}.h"
+
+// mex
+#include "mex.h"
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ long long *l_ptr;
+ int status = 0;
+
+ // create solver
+ nlp_solver_capsule *acados_ocp_capsule = {{ model.name }}_acados_create_capsule();
+
+ status = {{ model.name }}_acados_create(acados_ocp_capsule);
+
+ if (status)
+ {
+ mexPrintf("{{ model.name }}_acados_create() returned status %d.\n", status);
+ }
+ mexPrintf("{{ model.name }}_acados_create() -> success!\n");
+
+ // get pointers to nlp solver related objects
+ ocp_nlp_plan *nlp_plan = {{ model.name }}_acados_get_nlp_plan(acados_ocp_capsule);
+ ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(acados_ocp_capsule);
+ ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(acados_ocp_capsule);
+ ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(acados_ocp_capsule);
+ ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(acados_ocp_capsule);
+ ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(acados_ocp_capsule);
+ void *nlp_opts = {{ model.name }}_acados_get_nlp_opts(acados_ocp_capsule);
+
+ // mexPrintf("acados: got pointer to objectes!\n");
+
+ // field names of output struct
+ #define FIELDS_OCP 9
+ #define FIELDS_EXT_FUN 25
+ #define MAX_FIELDS 25
+ char *fieldnames[MAX_FIELDS];
+
+ for (int i = 0; i < MAX_FIELDS; i++)
+ {
+ fieldnames[i] = (char*) mxMalloc(50);
+ }
+
+ memcpy(fieldnames[0],"config",sizeof("config"));
+ memcpy(fieldnames[1],"dims",sizeof("dims"));
+ memcpy(fieldnames[2],"opts",sizeof("opts"));
+ memcpy(fieldnames[3],"in",sizeof("in"));
+ memcpy(fieldnames[4],"out",sizeof("out"));
+ memcpy(fieldnames[5],"solver",sizeof("solver"));
+ memcpy(fieldnames[6],"sens_out",sizeof("sens_out"));
+ memcpy(fieldnames[7],"plan",sizeof("plan"));
+ memcpy(fieldnames[8],"capsule",sizeof("capsule"));
+
+ // create output struct - C_ocp
+ plhs[0] = mxCreateStructMatrix(1, 1, 9, (const char **) fieldnames);
+
+ // MEX: config, dims, opts, in, out, solver, sens_out, plan
+ // plan
+ mxArray *plan_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(plan_mat);
+ l_ptr[0] = (long long) nlp_plan;
+ mxSetField(plhs[0], 0, "plan", plan_mat);
+
+ // config
+ mxArray *config_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(config_mat);
+ l_ptr[0] = (long long) nlp_config;
+ mxSetField(plhs[0], 0, "config", config_mat);
+
+ // dims
+ mxArray *dims_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(dims_mat);
+ l_ptr[0] = (long long) nlp_dims;
+ mxSetField(plhs[0], 0, "dims", dims_mat);
+
+ // opts
+ mxArray *opts_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(opts_mat);
+ l_ptr[0] = (long long) nlp_opts;
+ mxSetField(plhs[0], 0, "opts", opts_mat);
+
+ // in
+ mxArray *in_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(in_mat);
+ l_ptr[0] = (long long) nlp_in;
+ mxSetField(plhs[0], 0, "in", in_mat);
+
+ // out
+ mxArray *out_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(out_mat);
+ l_ptr[0] = (long long) nlp_out;
+ mxSetField(plhs[0], 0, "out", out_mat);
+
+ // solver
+ mxArray *solver_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(solver_mat);
+ l_ptr[0] = (long long) nlp_solver;
+ mxSetField(plhs[0], 0, "solver", solver_mat);
+
+ // TODO: sens_out not actually implemented in templates..
+ // sens_out
+ mxArray *sens_out_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(sens_out_mat);
+ l_ptr[0] = (long long) 1;
+ mxSetField(plhs[0], 0, "sens_out", sens_out_mat);
+
+ // capsule
+ mxArray *capsule_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(capsule_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule;
+ mxSetField(plhs[0], 0, "capsule", capsule_mat);
+
+ /* store external function pointers */
+ // dyn
+ memcpy(fieldnames[0],"expl_ode_fun",sizeof("expl_ode_fun"));
+ memcpy(fieldnames[1],"forw_vde",sizeof("forw_vde"));
+ memcpy(fieldnames[2],"hess_vde",sizeof("hess_vde"));
+ memcpy(fieldnames[3],"impl_dae_fun",sizeof("impl_dae_fun"));
+ memcpy(fieldnames[4],"impl_dae_fun_jac_x_xdot_z",sizeof("impl_dae_fun_jac_x_xdot_z"));
+ memcpy(fieldnames[5],"impl_dae_jac_x_xdot_u_z",sizeof("impl_dae_jac_x_xdot_u_z"));
+ memcpy(fieldnames[6],"impl_dae_hess",sizeof("impl_dae_hess"));
+
+ memcpy(fieldnames[7],"gnsf_phi_fun",sizeof("gnsf_phi_fun"));
+ memcpy(fieldnames[8],"gnsf_phi_fun_jac_y",sizeof("gnsf_phi_fun_jac_y"));
+ memcpy(fieldnames[9],"gnsf_phi_jac_y_uhat",sizeof("gnsf_phi_jac_y_uhat"));
+ memcpy(fieldnames[10],"gnsf_f_lo_jac_x1_x1dot_u_z",sizeof("gnsf_f_lo_jac_x1_x1dot_u_z"));
+ memcpy(fieldnames[11],"gnsf_get_matrices_fun",sizeof("gnsf_get_matrices_fun"));
+
+ memcpy(fieldnames[12],"disc_phi_fun",sizeof("disc_phi_fun"));
+ memcpy(fieldnames[13],"disc_phi_fun_jac",sizeof("disc_phi_fun_jac"));
+ memcpy(fieldnames[14],"disc_phi_fun_jac_hess",sizeof("disc_phi_fun_jac_hess"));
+
+ // cost
+ memcpy(fieldnames[15],"cost_y_fun",sizeof("cost_y_fun"));
+ memcpy(fieldnames[16],"cost_y_fun_jac_ut_xt",sizeof("cost_y_fun_jac_ut_xt"));
+ memcpy(fieldnames[17],"cost_y_hess",sizeof("cost_y_hess"));
+ memcpy(fieldnames[18],"ext_cost_fun",sizeof("ext_cost_fun"));
+ memcpy(fieldnames[19],"ext_cost_fun_jac",sizeof("ext_cost_fun_jac"));
+ memcpy(fieldnames[20],"ext_cost_fun_jac_hess",sizeof("ext_cost_fun_jac_hess"));
+
+ // constraints
+ memcpy(fieldnames[21],"phi_constraint",sizeof("phi_constraint"));
+ memcpy(fieldnames[22],"nl_constr_h_fun_jac",sizeof("nl_constr_h_fun_jac"));
+ memcpy(fieldnames[23],"nl_constr_h_fun",sizeof("nl_constr_h_fun"));
+ memcpy(fieldnames[24],"nl_constr_h_fun_jac_hess",sizeof("nl_constr_h_fun_jac_hess"));
+
+
+ // create output struct - C_ocp_ext_fun
+ plhs[1] = mxCreateStructMatrix(1, 1, FIELDS_EXT_FUN, (const char **) fieldnames);
+
+
+ for (int i = 0; i < FIELDS_EXT_FUN; i++)
+ {
+ mxFree( fieldnames[i] );
+ }
+
+/* dynamics */
+ mxArray *expl_ode_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *forw_vde_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *hess_vde_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *impl_dae_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *impl_dae_fun_jac_x_xdot_z_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *impl_dae_jac_x_xdot_u_z_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *impl_dae_hess_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+
+ mxArray *gnsf_phi_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *gnsf_phi_fun_jac_y_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *gnsf_phi_jac_y_uhat_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *gnsf_f_lo_jac_x1_x1dot_u_z_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *gnsf_get_matrices_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+
+ mxArray *disc_phi_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *disc_phi_fun_jac_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+ mxArray *disc_phi_fun_jac_hess_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL);
+
+{% if solver_options.integrator_type == "ERK" %}
+ {# TODO: remove _casadi from these names.. #}
+ l_ptr = mxGetData(forw_vde_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->forw_vde_casadi;
+ l_ptr = mxGetData(expl_ode_fun_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->expl_ode_fun;
+{% if solver_options.hessian_approx == "EXACT" %}
+ l_ptr = mxGetData(hess_vde_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->hess_vde_casadi;
+{%- endif %}
+{% elif solver_options.integrator_type == "IRK" %}
+ l_ptr = mxGetData(impl_dae_fun_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_fun;
+ l_ptr = mxGetData(impl_dae_fun_jac_x_xdot_z_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_fun_jac_x_xdot_z;
+ l_ptr = mxGetData(impl_dae_jac_x_xdot_u_z_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_jac_x_xdot_u_z;
+{% if solver_options.hessian_approx == "EXACT" %}
+ l_ptr = mxGetData(impl_dae_hess_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_hess;
+{%- endif %}
+{% elif solver_options.integrator_type == "GNSF" %}
+ l_ptr = mxGetData(gnsf_phi_fun_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->gnsf_phi_fun;
+ l_ptr = mxGetData(gnsf_phi_fun_jac_y_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->gnsf_phi_fun_jac_y;
+ l_ptr = mxGetData(gnsf_phi_jac_y_uhat_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->gnsf_phi_jac_y_uhat;
+ l_ptr = mxGetData(gnsf_f_lo_jac_x1_x1dot_u_z_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->gnsf_f_lo_jac_x1_x1dot_u_z;
+ l_ptr = mxGetData(gnsf_get_matrices_fun_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->gnsf_get_matrices_fun;
+{% elif solver_options.integrator_type == "DISCRETE" %}
+ l_ptr = mxGetData(disc_phi_fun_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->discr_dyn_phi_fun;
+ l_ptr = mxGetData(disc_phi_fun_jac_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->discr_dyn_phi_fun_jac_ut_xt;
+{% if solver_options.hessian_approx == "EXACT" %}
+ l_ptr = mxGetData(disc_phi_fun_jac_hess_mat);
+ l_ptr[0] = (long long) acados_ocp_capsule->discr_dyn_phi_fun_jac_ut_xt_hess;
+{%- endif %}
+{%- endif %}
+ mxSetField(plhs[1], 0, "expl_ode_fun", expl_ode_fun_mat);
+ mxSetField(plhs[1], 0, "forw_vde", forw_vde_mat);
+ mxSetField(plhs[1], 0, "hess_vde", hess_vde_mat);
+
+ mxSetField(plhs[1], 0, "gnsf_phi_fun", gnsf_phi_fun_mat);
+ mxSetField(plhs[1], 0, "gnsf_phi_fun_jac_y", gnsf_phi_fun_jac_y_mat);
+ mxSetField(plhs[1], 0, "gnsf_phi_jac_y_uhat", gnsf_phi_jac_y_uhat_mat);
+ mxSetField(plhs[1], 0, "gnsf_f_lo_jac_x1_x1dot_u_z", gnsf_f_lo_jac_x1_x1dot_u_z_mat);
+ mxSetField(plhs[1], 0, "gnsf_get_matrices_fun", gnsf_get_matrices_fun_mat);
+
+ mxSetField(plhs[1], 0, "impl_dae_fun", impl_dae_fun_mat);
+ mxSetField(plhs[1], 0, "impl_dae_fun_jac_x_xdot_z", impl_dae_fun_jac_x_xdot_z_mat);
+ mxSetField(plhs[1], 0, "impl_dae_jac_x_xdot_u_z", impl_dae_jac_x_xdot_u_z_mat);
+ mxSetField(plhs[1], 0, "impl_dae_hess", impl_dae_hess_mat);
+
+ mxSetField(plhs[1], 0, "disc_phi_fun", disc_phi_fun_mat);
+ mxSetField(plhs[1], 0, "disc_phi_fun_jac", disc_phi_fun_jac_mat);
+ mxSetField(plhs[1], 0, "disc_phi_fun_jac_hess", disc_phi_fun_jac_hess_mat);
+/* constaints */
+ mxArray *phi_constraint_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(phi_constraint_mat);
+{%- if constraints.constr_type == "BGP" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->phi_constraint;
+{% endif %}
+{% if constraints.constr_type_e == "BGP" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->phi_e_constraint;
+{% endif %}
+ mxSetField(plhs[1], 0, "phi_constraint", phi_constraint_mat);
+
+ mxArray *nl_constr_h_fun_jac_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(nl_constr_h_fun_jac_mat);
+{% if constraints.constr_type == "BGH" and dims.nh > 0 %}
+ l_ptr[0] = (long long) acados_ocp_capsule->nl_constr_h_fun_jac;
+{% endif %}
+{% if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->nl_constr_h_e_fun_jac;
+{%- endif %}
+ mxSetField(plhs[1], 0, "nl_constr_h_fun_jac", nl_constr_h_fun_jac_mat);
+
+ mxArray *nl_constr_h_fun_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(nl_constr_h_fun_mat);
+{% if constraints.constr_type == "BGH" and dims.nh > 0 %}
+ l_ptr[0] = (long long) acados_ocp_capsule->nl_constr_h_fun;
+{% endif %}
+{% if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->nl_constr_h_e_fun;
+{%- endif %}
+ mxSetField(plhs[1], 0, "nl_constr_h_fun", nl_constr_h_fun_mat);
+
+ mxArray *nl_constr_h_fun_jac_hess_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(nl_constr_h_fun_jac_hess_mat);
+{% if constraints.constr_type == "BGH" and dims.nh > 0 and solver_options.hessian_approx == "EXACT" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->nl_constr_h_fun_jac_hess;
+{% endif %}
+{% if constraints.constr_type_e == "BGH" and dims.nh_e > 0 and solver_options.hessian_approx == "EXACT" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->nl_constr_h_e_fun_jac_hess;
+{%- endif %}
+ mxSetField(plhs[1], 0, "nl_constr_h_fun_jac_hess", nl_constr_h_fun_jac_hess_mat);
+
+/* cost */
+ mxArray *cost_y_fun_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(cost_y_fun_mat);
+{% if cost.cost_type == "NONLINEAR_LS" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->cost_y_fun;
+{% endif %}
+{% if cost.cost_type_e == "NONLINEAR_LS" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->cost_y_e_fun;
+{%- endif %}
+ mxSetField(plhs[1], 0, "cost_y_fun", cost_y_fun_mat);
+
+ mxArray *cost_y_fun_jac_ut_xt_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(cost_y_fun_jac_ut_xt_mat);
+{% if cost.cost_type == "NONLINEAR_LS" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->cost_y_fun_jac_ut_xt;
+{% endif %}
+{% if cost.cost_type_e == "NONLINEAR_LS" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->cost_y_e_fun_jac_ut_xt;
+{%- endif %}
+ mxSetField(plhs[1], 0, "cost_y_fun_jac_ut_xt", cost_y_fun_jac_ut_xt_mat);
+
+ mxArray *cost_y_hess_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(cost_y_hess_mat);
+{% if cost.cost_type == "NONLINEAR_LS" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->cost_y_hess;
+{% endif %}
+{% if cost.cost_type_e == "NONLINEAR_LS" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->cost_y_e_hess;
+{%- endif %}
+ mxSetField(plhs[1], 0, "cost_y_hess", cost_y_hess_mat);
+
+ mxArray *ext_cost_fun_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(ext_cost_fun_mat);
+{% if cost.cost_type == "EXTERNAL" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->ext_cost_fun;
+{% endif -%}
+{% if cost.cost_type_e == "EXTERNAL" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->ext_cost_e_fun;
+{%- endif %}
+ mxSetField(plhs[1], 0, "ext_cost_fun", ext_cost_fun_mat);
+
+ mxArray *ext_cost_fun_jac_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(ext_cost_fun_jac_mat);
+{% if cost.cost_type == "EXTERNAL" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->ext_cost_fun_jac;
+{% endif -%}
+{% if cost.cost_type_e == "EXTERNAL" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->ext_cost_e_fun_jac;
+{%- endif %}
+ mxSetField(plhs[1], 0, "ext_cost_fun_jac", ext_cost_fun_jac_mat);
+
+ mxArray *ext_cost_fun_jac_hess_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL);
+ l_ptr = mxGetData(ext_cost_fun_jac_hess_mat);
+{% if cost.cost_type == "EXTERNAL" %}
+ l_ptr[0] = (long long) acados_ocp_capsule->ext_cost_fun_jac_hess;
+{% endif -%}
+{% if cost.cost_type_e == "EXTERNAL" %}
+ l_ptr[1] = (long long) &acados_ocp_capsule->ext_cost_e_fun_jac_hess;
+{%- endif %}
+ mxSetField(plhs[1], 0, "ext_cost_fun_jac_hess", ext_cost_fun_jac_hess_mat);
+
+
+ return;
+}
diff --git a/pyextra/acados_template/c_templates_tera/acados_mex_free.in.c b/pyextra/acados_template/c_templates_tera/acados_mex_free.in.c
new file mode 100644
index 000000000..843440297
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_mex_free.in.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+// system
+#include
+#include
+#include
+// acados
+#include "acados_solver_{{ model.name }}.h"
+
+// mex
+#include "mex.h"
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ int status = 0;
+ long long *ptr;
+
+ // mexPrintf("\nin mex_acados_free\n");
+ const mxArray *C_ocp = prhs[0];
+ // capsule
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "capsule" ) );
+ nlp_solver_capsule *capsule = (nlp_solver_capsule *) ptr[0];
+
+ status = {{ model.name }}_acados_free(capsule);
+ if (status)
+ {
+ mexPrintf("{{ model.name }}_acados_free() returned status %d.\n", status);
+ }
+
+ status = {{ model.name }}_acados_free_capsule(capsule);
+ if (status)
+ {
+ mexPrintf("{{ model.name }}_acados_free_capsule() returned status %d.\n", status);
+ }
+
+ return;
+}
+
diff --git a/pyextra/acados_template/c_templates_tera/acados_mex_set.in.c b/pyextra/acados_template/c_templates_tera/acados_mex_set.in.c
new file mode 100644
index 000000000..ee86a3116
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_mex_set.in.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+// standard
+#include
+#include
+#include
+
+// acados
+#include "acados/utils/print.h"
+#include "acados_c/ocp_nlp_interface.h"
+#include "acados_solver_{{ model.name }}.h"
+
+// mex
+#include "mex.h"
+#include "mex_macros.h"
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+
+ long long *ptr;
+ int acados_size;
+ mxArray *mex_field;
+ char fun_name[20] = "ocp_set";
+ char buffer [500]; // for error messages
+
+ /* RHS */
+ int min_nrhs = 6;
+
+ char *ext_fun_type = mxArrayToString( prhs[0] );
+ char *ext_fun_type_e = mxArrayToString( prhs[1] );
+
+ // C ocp
+ const mxArray *C_ocp = prhs[2];
+ // capsule
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "capsule" ) );
+ nlp_solver_capsule *capsule = (nlp_solver_capsule *) ptr[0];
+ // plan
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "plan" ) );
+ ocp_nlp_plan *plan = (ocp_nlp_plan *) ptr[0];
+ // config
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "config" ) );
+ ocp_nlp_config *config = (ocp_nlp_config *) ptr[0];
+ // dims
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "dims" ) );
+ ocp_nlp_dims *dims = (ocp_nlp_dims *) ptr[0];
+ // opts
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "opts" ) );
+ void *opts = (void *) ptr[0];
+ // in
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "in" ) );
+ ocp_nlp_in *in = (ocp_nlp_in *) ptr[0];
+ // out
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "out" ) );
+ ocp_nlp_out *out = (ocp_nlp_out *) ptr[0];
+ // solver
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "solver" ) );
+ ocp_nlp_solver *solver = (ocp_nlp_solver *) ptr[0];
+
+ const mxArray *C_ext_fun_pointers = prhs[3];
+ // field
+ char *field = mxArrayToString( prhs[4] );
+ // value
+ double *value = mxGetPr( prhs[5] );
+
+ // for checks
+ int matlab_size = (int) mxGetNumberOfElements( prhs[5] );
+ int nrow = (int) mxGetM( prhs[5] );
+ int ncol = (int) mxGetN( prhs[5] );
+
+ int N = dims->N;
+ int nu = dims->nu[0];
+ int nx = dims->nx[0];
+
+ // stage
+ int s0, se;
+ if (nrhs==min_nrhs)
+ {
+ s0 = 0;
+ se = N;
+ }
+ else if (nrhs==min_nrhs+1)
+ {
+ s0 = mxGetScalar( prhs[6] );
+ if (s0 > N)
+ {
+ sprintf(buffer, "ocp_set: N < specified stage = %d\n", s0);
+ mexErrMsgTxt(buffer);
+ }
+ se = s0 + 1;
+ }
+ else
+ {
+ sprintf(buffer, "ocp_set: wrong nrhs: %d\n", nrhs);
+ mexErrMsgTxt(buffer);
+ }
+
+ /* Set value */
+ // constraints
+ if (!strcmp(field, "constr_x0"))
+ {
+ acados_size = nx;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ ocp_nlp_constraints_model_set(config, dims, in, 0, "lbx", value);
+ ocp_nlp_constraints_model_set(config, dims, in, 0, "ubx", value);
+ }
+ else if (!strcmp(field, "constr_C"))
+ {
+ for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS))
+ {
+ acados_size = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "y_ref");
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ ocp_nlp_cost_model_set(config, dims, in, ii, "y_ref", value);
+ }
+ else
+ {
+ MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii);
+ }
+ }
+ }
+ else if (!strcmp(field, "cost_y_ref_e"))
+ {
+ acados_size = ocp_nlp_dims_get_from_attr(config, dims, out, N, "y_ref");
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ ocp_nlp_cost_model_set(config, dims, in, N, "y_ref", value);
+ }
+ else if (!strcmp(field, "cost_Vu"))
+ {
+ for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS))
+ {
+ int ny = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "y_ref");
+ int nu = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "u");
+ acados_size = ny * nu;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ ocp_nlp_cost_model_set(config, dims, in, ii, "Vu", value);
+ }
+ else
+ {
+ MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii);
+ }
+ }
+ }
+ else if (!strcmp(field, "cost_Vx"))
+ {
+ for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS))
+ {
+ int ny = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "y_ref");
+ int nx = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "x");
+ acados_size = ny * nx;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ ocp_nlp_cost_model_set(config, dims, in, ii, "Vx", value);
+ }
+ else
+ {
+ MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii);
+ }
+ }
+ }
+ else if (!strcmp(field, "cost_W"))
+ {
+ for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS))
+ {
+ int ny = ocp_nlp_dims_get_from_attr(config, dims, out, s0, "y_ref");
+ acados_size = ny * ny;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ ocp_nlp_cost_model_set(config, dims, in, ii, "W", value);
+ }
+ else
+ {
+ MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii);
+ }
+ }
+ }
+ else if (!strcmp(field, "cost_Z"))
+ {
+ acados_size = ocp_nlp_dims_get_from_attr(config, dims, out, s0, "cost_Z");
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ for (int ii=s0; iisim_solver_plan[0];
+ sim_solver_t type = sim_plan.sim_solver;
+ if (type == IRK)
+ {
+ int nz = ocp_nlp_dims_get_from_attr(config, dims, out, 0, "z");
+ if (nrhs!=min_nrhs)
+ MEX_SETTER_NO_STAGE_SUPPORT(fun_name, field)
+
+ acados_size = N*nz;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ for (int ii=0; iisim_solver_plan[0];
+ sim_solver_t type = sim_plan.sim_solver;
+ if (type == IRK)
+ {
+ int nx = ocp_nlp_dims_get_from_attr(config, dims, out, 0, "x");
+ if (nrhs!=min_nrhs)
+ MEX_SETTER_NO_STAGE_SUPPORT(fun_name, field)
+
+ acados_size = N*nx;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ for (int ii=0; iisim_solver_plan[0];
+ sim_solver_t type = sim_plan.sim_solver;
+ if (type == GNSF)
+ {
+ int nout = ocp_nlp_dims_get_from_attr(config, dims, out, 0, "init_gnsf_phi");
+
+ if (nrhs!=min_nrhs)
+ MEX_SETTER_NO_STAGE_SUPPORT(fun_name, field)
+
+ acados_size = N*nout;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ for (int ii=0; iinlp_solver == SQP && rti_phase != 0)
+ {
+ MEX_FIELD_ONLY_SUPPORTED_FOR_SOLVER(fun_name, field, "sqp_rti")
+ }
+ ocp_nlp_solver_opts_set(config, opts, "rti_phase", &rti_phase);
+ }
+ else if (!strcmp(field, "qp_warm_start"))
+ {
+ acados_size = 1;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ int qp_warm_start = (int) value[0];
+ ocp_nlp_solver_opts_set(config, opts, "qp_warm_start", &qp_warm_start);
+ }
+ else if (!strcmp(field, "warm_start_first_qp"))
+ {
+ acados_size = 1;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ int warm_start_first_qp = (int) value[0];
+ ocp_nlp_solver_opts_set(config, opts, "warm_start_first_qp", &warm_start_first_qp);
+ }
+ else if (!strcmp(field, "print_level"))
+ {
+ acados_size = 1;
+ MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size);
+ int print_level = (int) value[0];
+ ocp_nlp_solver_opts_set(config, opts, "print_level", &print_level);
+ }
+ else
+ {
+ MEX_FIELD_NOT_SUPPORTED_SUGGEST(fun_name, field, "p, constr_x0,\
+ constr_lbx, constr_ubx, constr_C, constr_D, constr_lg, constr_ug, constr_lh, constr_uh\
+ constr_lbu, constr_ubu, cost_y_ref[_e],\
+ cost_Vu, cost_Vx, cost_Vz, cost_W, cost_Z, cost_Zl, cost_Zu, cost_z,\
+ cost_zl, cost_zu, init_x, init_u, init_z, init_xdot, init_gnsf_phi,\
+ init_pi, nlp_solver_max_iter, qp_warm_start, warm_start_first_qp, print_level");
+ }
+
+ return;
+}
+
diff --git a/pyextra/acados_template/c_templates_tera/acados_mex_solve.in.c b/pyextra/acados_template/c_templates_tera/acados_mex_solve.in.c
new file mode 100644
index 000000000..9fd4feab2
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_mex_solve.in.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+// system
+#include
+#include
+#include
+// acados
+#include "acados_solver_{{ model.name }}.h"
+
+// mex
+#include "mex.h"
+
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+ // C_ocp
+ long long *ptr;
+ const mxArray *C_ocp = prhs[0];
+
+ // capsule
+ ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "capsule" ) );
+ nlp_solver_capsule *capsule = (nlp_solver_capsule *) ptr[0];
+
+ // solve
+ {{ model.name }}_acados_solve(capsule);
+
+}
diff --git a/pyextra/acados_template/c_templates_tera/acados_sim_solver.in.c b/pyextra/acados_template/c_templates_tera/acados_sim_solver.in.c
new file mode 100644
index 000000000..390506420
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_sim_solver.in.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+{%- if solver_options.hessian_approx %}
+ {%- set hessian_approx = solver_options.hessian_approx %}
+{%- elif solver_options.sens_hess %}
+ {%- set hessian_approx = "EXACT" %}
+{%- else %}
+ {%- set hessian_approx = "GAUSS_NEWTON" %}
+{%- endif %}
+// standard
+#include
+#include
+
+// acados
+#include "acados_c/external_function_interface.h"
+#include "acados_c/sim_interface.h"
+#include "acados_c/external_function_interface.h"
+
+#include "acados/sim/sim_common.h"
+#include "acados/utils/external_function_generic.h"
+#include "acados/utils/print.h"
+
+
+// example specific
+#include "{{ model.name }}_model/{{ model.name }}_model.h"
+#include "acados_sim_solver_{{ model.name }}.h"
+
+
+// ** solver data **
+
+sim_solver_capsule * {{ model.name }}_acados_sim_solver_create_capsule()
+{
+ void* capsule_mem = malloc(sizeof(sim_solver_capsule));
+ sim_solver_capsule *capsule = (sim_solver_capsule *) capsule_mem;
+
+ return capsule;
+}
+
+
+int {{ model.name }}_acados_sim_solver_free_capsule(sim_solver_capsule * capsule)
+{
+ free(capsule);
+ return 0;
+}
+
+
+int {{ model.name }}_acados_sim_create(sim_solver_capsule * capsule)
+{
+ // initialize
+ int nx = {{ dims.nx }};
+ int nu = {{ dims.nu }};
+ int nz = {{ dims.nz }};
+ bool tmp_bool;
+
+ {#// double Tsim = {{ solver_options.tf / dims.N }};#}
+ double Tsim = {{ solver_options.Tsim }};
+
+ {% if solver_options.integrator_type == "IRK" %}
+ capsule->sim_impl_dae_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ capsule->sim_impl_dae_fun_jac_x_xdot_z = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ capsule->sim_impl_dae_jac_x_xdot_u_z = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+
+ // external functions (implicit model)
+ capsule->sim_impl_dae_fun->casadi_fun = &{{ model.name }}_impl_dae_fun;
+ capsule->sim_impl_dae_fun->casadi_work = &{{ model.name }}_impl_dae_fun_work;
+ capsule->sim_impl_dae_fun->casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_sparsity_in;
+ capsule->sim_impl_dae_fun->casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_sparsity_out;
+ capsule->sim_impl_dae_fun->casadi_n_in = &{{ model.name }}_impl_dae_fun_n_in;
+ capsule->sim_impl_dae_fun->casadi_n_out = &{{ model.name }}_impl_dae_fun_n_out;
+ external_function_param_casadi_create(capsule->sim_impl_dae_fun, {{ dims.np }});
+
+ capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_fun = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z;
+ capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_work = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_work;
+ capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_in;
+ capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_out;
+ capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_n_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_in;
+ capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_n_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_out;
+ external_function_param_casadi_create(capsule->sim_impl_dae_fun_jac_x_xdot_z, {{ dims.np }});
+
+ // external_function_param_casadi impl_dae_jac_x_xdot_u_z;
+ capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_fun = &{{ model.name }}_impl_dae_jac_x_xdot_u_z;
+ capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_work = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_work;
+ capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_sparsity_in = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_in;
+ capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_sparsity_out = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_out;
+ capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_n_in = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_n_in;
+ capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_n_out = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_n_out;
+ external_function_param_casadi_create(capsule->sim_impl_dae_jac_x_xdot_u_z, {{ dims.np }});
+
+{%- if hessian_approx == "EXACT" %}
+ capsule->sim_impl_dae_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ // external_function_param_casadi impl_dae_jac_x_xdot_u_z;
+ capsule->sim_impl_dae_hess->casadi_fun = &{{ model.name }}_impl_dae_hess;
+ capsule->sim_impl_dae_hess->casadi_work = &{{ model.name }}_impl_dae_hess_work;
+ capsule->sim_impl_dae_hess->casadi_sparsity_in = &{{ model.name }}_impl_dae_hess_sparsity_in;
+ capsule->sim_impl_dae_hess->casadi_sparsity_out = &{{ model.name }}_impl_dae_hess_sparsity_out;
+ capsule->sim_impl_dae_hess->casadi_n_in = &{{ model.name }}_impl_dae_hess_n_in;
+ capsule->sim_impl_dae_hess->casadi_n_out = &{{ model.name }}_impl_dae_hess_n_out;
+ external_function_param_casadi_create(capsule->sim_impl_dae_hess, {{ dims.np }});
+{%- endif %}
+
+ {% elif solver_options.integrator_type == "ERK" %}
+ // explicit ode
+ capsule->sim_forw_vde_casadi = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ capsule->sim_expl_ode_fun_casadi = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+
+ capsule->sim_forw_vde_casadi->casadi_fun = &{{ model.name }}_expl_vde_forw;
+ capsule->sim_forw_vde_casadi->casadi_n_in = &{{ model.name }}_expl_vde_forw_n_in;
+ capsule->sim_forw_vde_casadi->casadi_n_out = &{{ model.name }}_expl_vde_forw_n_out;
+ capsule->sim_forw_vde_casadi->casadi_sparsity_in = &{{ model.name }}_expl_vde_forw_sparsity_in;
+ capsule->sim_forw_vde_casadi->casadi_sparsity_out = &{{ model.name }}_expl_vde_forw_sparsity_out;
+ capsule->sim_forw_vde_casadi->casadi_work = &{{ model.name }}_expl_vde_forw_work;
+ external_function_param_casadi_create(capsule->sim_forw_vde_casadi, {{ dims.np }});
+
+ capsule->sim_expl_ode_fun_casadi->casadi_fun = &{{ model.name }}_expl_ode_fun;
+ capsule->sim_expl_ode_fun_casadi->casadi_n_in = &{{ model.name }}_expl_ode_fun_n_in;
+ capsule->sim_expl_ode_fun_casadi->casadi_n_out = &{{ model.name }}_expl_ode_fun_n_out;
+ capsule->sim_expl_ode_fun_casadi->casadi_sparsity_in = &{{ model.name }}_expl_ode_fun_sparsity_in;
+ capsule->sim_expl_ode_fun_casadi->casadi_sparsity_out = &{{ model.name }}_expl_ode_fun_sparsity_out;
+ capsule->sim_expl_ode_fun_casadi->casadi_work = &{{ model.name }}_expl_ode_fun_work;
+ external_function_param_casadi_create(capsule->sim_expl_ode_fun_casadi, {{ dims.np }});
+
+{%- if hessian_approx == "EXACT" %}
+ capsule->sim_expl_ode_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ // external_function_param_casadi impl_dae_jac_x_xdot_u_z;
+ capsule->sim_expl_ode_hess->casadi_fun = &{{ model.name }}_expl_ode_hess;
+ capsule->sim_expl_ode_hess->casadi_work = &{{ model.name }}_expl_ode_hess_work;
+ capsule->sim_expl_ode_hess->casadi_sparsity_in = &{{ model.name }}_expl_ode_hess_sparsity_in;
+ capsule->sim_expl_ode_hess->casadi_sparsity_out = &{{ model.name }}_expl_ode_hess_sparsity_out;
+ capsule->sim_expl_ode_hess->casadi_n_in = &{{ model.name }}_expl_ode_hess_n_in;
+ capsule->sim_expl_ode_hess->casadi_n_out = &{{ model.name }}_expl_ode_hess_n_out;
+ external_function_param_casadi_create(capsule->sim_expl_ode_hess, {{ dims.np }});
+{%- endif %}
+
+ {% elif solver_options.integrator_type == "GNSF" -%}
+ capsule->sim_gnsf_phi_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ capsule->sim_gnsf_phi_fun_jac_y = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ capsule->sim_gnsf_phi_jac_y_uhat = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+ capsule->sim_gnsf_get_matrices_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi));
+
+ capsule->sim_gnsf_phi_fun->casadi_fun = &{{ model.name }}_gnsf_phi_fun;
+ capsule->sim_gnsf_phi_fun->casadi_n_in = &{{ model.name }}_gnsf_phi_fun_n_in;
+ capsule->sim_gnsf_phi_fun->casadi_n_out = &{{ model.name }}_gnsf_phi_fun_n_out;
+ capsule->sim_gnsf_phi_fun->casadi_sparsity_in = &{{ model.name }}_gnsf_phi_fun_sparsity_in;
+ capsule->sim_gnsf_phi_fun->casadi_sparsity_out = &{{ model.name }}_gnsf_phi_fun_sparsity_out;
+ capsule->sim_gnsf_phi_fun->casadi_work = &{{ model.name }}_gnsf_phi_fun_work;
+ external_function_param_casadi_create(capsule->sim_gnsf_phi_fun, {{ dims.np }});
+
+ capsule->sim_gnsf_phi_fun_jac_y->casadi_fun = &{{ model.name }}_gnsf_phi_fun_jac_y;
+ capsule->sim_gnsf_phi_fun_jac_y->casadi_n_in = &{{ model.name }}_gnsf_phi_fun_jac_y_n_in;
+ capsule->sim_gnsf_phi_fun_jac_y->casadi_n_out = &{{ model.name }}_gnsf_phi_fun_jac_y_n_out;
+ capsule->sim_gnsf_phi_fun_jac_y->casadi_sparsity_in = &{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_in;
+ capsule->sim_gnsf_phi_fun_jac_y->casadi_sparsity_out = &{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_out;
+ capsule->sim_gnsf_phi_fun_jac_y->casadi_work = &{{ model.name }}_gnsf_phi_fun_jac_y_work;
+ external_function_param_casadi_create(capsule->sim_gnsf_phi_fun_jac_y, {{ dims.np }});
+
+ capsule->sim_gnsf_phi_jac_y_uhat->casadi_fun = &{{ model.name }}_gnsf_phi_jac_y_uhat;
+ capsule->sim_gnsf_phi_jac_y_uhat->casadi_n_in = &{{ model.name }}_gnsf_phi_jac_y_uhat_n_in;
+ capsule->sim_gnsf_phi_jac_y_uhat->casadi_n_out = &{{ model.name }}_gnsf_phi_jac_y_uhat_n_out;
+ capsule->sim_gnsf_phi_jac_y_uhat->casadi_sparsity_in = &{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_in;
+ capsule->sim_gnsf_phi_jac_y_uhat->casadi_sparsity_out = &{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_out;
+ capsule->sim_gnsf_phi_jac_y_uhat->casadi_work = &{{ model.name }}_gnsf_phi_jac_y_uhat_work;
+ external_function_param_casadi_create(capsule->sim_gnsf_phi_jac_y_uhat, {{ dims.np }});
+
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_fun = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz;
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_n_in = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_in;
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_n_out = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_out;
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_sparsity_in = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_in;
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_sparsity_out = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_out;
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_work = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_work;
+ external_function_param_casadi_create(capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z, {{ dims.np }});
+
+ capsule->sim_gnsf_get_matrices_fun->casadi_fun = &{{ model.name }}_gnsf_get_matrices_fun;
+ capsule->sim_gnsf_get_matrices_fun->casadi_n_in = &{{ model.name }}_gnsf_get_matrices_fun_n_in;
+ capsule->sim_gnsf_get_matrices_fun->casadi_n_out = &{{ model.name }}_gnsf_get_matrices_fun_n_out;
+ capsule->sim_gnsf_get_matrices_fun->casadi_sparsity_in = &{{ model.name }}_gnsf_get_matrices_fun_sparsity_in;
+ capsule->sim_gnsf_get_matrices_fun->casadi_sparsity_out = &{{ model.name }}_gnsf_get_matrices_fun_sparsity_out;
+ capsule->sim_gnsf_get_matrices_fun->casadi_work = &{{ model.name }}_gnsf_get_matrices_fun_work;
+ external_function_param_casadi_create(capsule->sim_gnsf_get_matrices_fun, {{ dims.np }});
+ {% endif %}
+
+ // sim plan & config
+ sim_solver_plan plan;
+ plan.sim_solver = {{ solver_options.integrator_type }};
+
+ // create correct config based on plan
+ sim_config * {{ model.name }}_sim_config = sim_config_create(plan);
+ capsule->acados_sim_config = {{ model.name }}_sim_config;
+
+ // sim dims
+ void *{{ model.name }}_sim_dims = sim_dims_create({{ model.name }}_sim_config);
+ capsule->acados_sim_dims = {{ model.name }}_sim_dims;
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nx", &nx);
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nu", &nu);
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nz", &nz);
+{% if solver_options.integrator_type == "GNSF" %}
+ int gnsf_nx1 = {{ dims.gnsf_nx1 }};
+ int gnsf_nz1 = {{ dims.gnsf_nz1 }};
+ int gnsf_nout = {{ dims.gnsf_nout }};
+ int gnsf_ny = {{ dims.gnsf_ny }};
+ int gnsf_nuhat = {{ dims.gnsf_nuhat }};
+
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nx1", &gnsf_nx1);
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nz1", &gnsf_nz1);
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nout", &gnsf_nout);
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "ny", &gnsf_ny);
+ sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nuhat", &gnsf_nuhat);
+{% endif %}
+
+ // sim opts
+ sim_opts *{{ model.name }}_sim_opts = sim_opts_create({{ model.name }}_sim_config, {{ model.name }}_sim_dims);
+ capsule->acados_sim_opts = {{ model.name }}_sim_opts;
+ int tmp_int = {{ solver_options.sim_method_newton_iter }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "newton_iter", &tmp_int);
+
+{% if problem_class == "SIM" %}
+ tmp_int = {{ solver_options.sim_method_num_stages }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_stages", &tmp_int);
+ tmp_int = {{ solver_options.sim_method_num_steps }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_steps", &tmp_int);
+
+ // options that are not available to AcadosOcpSolver
+ // (in OCP they will be determined by other options, like exact_hessian)
+ tmp_bool = {{ solver_options.sens_forw }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_forw", &tmp_bool);
+ tmp_bool = {{ solver_options.sens_adj }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_adj", &tmp_bool);
+ tmp_bool = {{ solver_options.sens_algebraic }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_algebraic", &tmp_bool);
+ tmp_bool = {{ solver_options.sens_hess }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_hess", &tmp_bool);
+ tmp_bool = {{ solver_options.output_z }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "output_z", &tmp_bool);
+
+{% else %} {# num_stages and num_steps of first shooting interval are used #}
+ tmp_int = {{ solver_options.sim_method_num_stages[0] }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_stages", &tmp_int);
+ tmp_int = {{ solver_options.sim_method_num_steps[0] }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_steps", &tmp_int);
+ tmp_bool = {{ solver_options.sim_method_jac_reuse[0] }};
+ sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "jac_reuse", &tmp_bool);
+{% endif %}
+
+ // sim in / out
+ sim_in *{{ model.name }}_sim_in = sim_in_create({{ model.name }}_sim_config, {{ model.name }}_sim_dims);
+ capsule->acados_sim_in = {{ model.name }}_sim_in;
+ sim_out *{{ model.name }}_sim_out = sim_out_create({{ model.name }}_sim_config, {{ model.name }}_sim_dims);
+ capsule->acados_sim_out = {{ model.name }}_sim_out;
+
+ sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims,
+ {{ model.name }}_sim_in, "T", &Tsim);
+
+ // model functions
+{%- if solver_options.integrator_type == "IRK" %}
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "impl_ode_fun", capsule->sim_impl_dae_fun);
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "impl_ode_fun_jac_x_xdot", capsule->sim_impl_dae_fun_jac_x_xdot_z);
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "impl_ode_jac_x_xdot_u", capsule->sim_impl_dae_jac_x_xdot_u_z);
+{%- if hessian_approx == "EXACT" %}
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "impl_dae_hess", capsule->sim_impl_dae_hess);
+{%- endif %}
+
+{%- elif solver_options.integrator_type == "ERK" %}
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "expl_vde_for", capsule->sim_forw_vde_casadi);
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "expl_ode_fun", capsule->sim_expl_ode_fun_casadi);
+{%- if hessian_approx == "EXACT" %}
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "expl_ode_hess", capsule->sim_expl_ode_hess);
+{%- endif %}
+{%- elif solver_options.integrator_type == "GNSF" %}
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "phi_fun", capsule->sim_gnsf_phi_fun);
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "phi_fun_jac_y", capsule->sim_gnsf_phi_fun_jac_y);
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "phi_jac_y_uhat", capsule->sim_gnsf_phi_jac_y_uhat);
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "f_lo_jac_x1_x1dot_u_z", capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z);
+ {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model,
+ "gnsf_get_matrices_fun", capsule->sim_gnsf_get_matrices_fun);
+{%- endif %}
+
+ // sim solver
+ sim_solver *{{ model.name }}_sim_solver = sim_solver_create({{ model.name }}_sim_config,
+ {{ model.name }}_sim_dims, {{ model.name }}_sim_opts);
+ capsule->acados_sim_solver = {{ model.name }}_sim_solver;
+
+ /* initialize parameter values */
+ {% if dims.np > 0 %}
+ // initialize parameters to nominal value
+ double p[{{ dims.np }}];
+ {% for i in range(end=dims.np) %}
+ p[{{ i }}] = {{ parameter_values[i] }};
+ {%- endfor %}
+
+{%- if solver_options.integrator_type == "ERK" %}
+ capsule->sim_forw_vde_casadi[0].set_param(capsule->sim_forw_vde_casadi, p);
+ capsule->sim_expl_ode_fun_casadi[0].set_param(capsule->sim_expl_ode_fun_casadi, p);
+{%- if hessian_approx == "EXACT" %}
+ capsule->sim_expl_ode_hess[0].set_param(capsule->sim_expl_ode_hess, p);
+{%- endif %}
+{%- elif solver_options.integrator_type == "IRK" %}
+ capsule->sim_impl_dae_fun[0].set_param(capsule->sim_impl_dae_fun, p);
+ capsule->sim_impl_dae_fun_jac_x_xdot_z[0].set_param(capsule->sim_impl_dae_fun_jac_x_xdot_z, p);
+ capsule->sim_impl_dae_jac_x_xdot_u_z[0].set_param(capsule->sim_impl_dae_jac_x_xdot_u_z, p);
+{%- if hessian_approx == "EXACT" %}
+ capsule->sim_impl_dae_hess[0].set_param(capsule->sim_impl_dae_hess, p);
+{%- endif %}
+{%- elif solver_options.integrator_type == "GNSF" %}
+ capsule->sim_gnsf_phi_fun[0].set_param(capsule->sim_gnsf_phi_fun, p);
+ capsule->sim_gnsf_phi_fun_jac_y[0].set_param(capsule->sim_gnsf_phi_fun_jac_y, p);
+ capsule->sim_gnsf_phi_jac_y_uhat[0].set_param(capsule->sim_gnsf_phi_jac_y_uhat, p);
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z[0].set_param(capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z, p);
+ capsule->sim_gnsf_get_matrices_fun[0].set_param(capsule->sim_gnsf_get_matrices_fun, p);
+{% endif %}
+ {% endif %}{# if dims.np #}
+
+ /* initialize input */
+ // x
+ double x0[{{ dims.nx }}];
+ for (int ii = 0; ii < {{ dims.nx }}; ii++)
+ x0[ii] = 0.0;
+
+ sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims,
+ {{ model.name }}_sim_in, "x", x0);
+
+
+ // u
+ double u0[{{ dims.nu }}];
+ for (int ii = 0; ii < {{ dims.nu }}; ii++)
+ u0[ii] = 0.0;
+
+ sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims,
+ {{ model.name }}_sim_in, "u", u0);
+
+ // S_forw
+ double S_forw[{{ dims.nx * (dims.nx + dims.nu) }}];
+ for (int ii = 0; ii < {{ dims.nx * (dims.nx + dims.nu) }}; ii++)
+ S_forw[ii] = 0.0;
+ for (int ii = 0; ii < {{ dims.nx }}; ii++)
+ S_forw[ii + ii * {{ dims.nx }} ] = 1.0;
+
+
+ sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims,
+ {{ model.name }}_sim_in, "S_forw", S_forw);
+
+ int status = sim_precompute({{ model.name }}_sim_solver, {{ model.name }}_sim_in, {{ model.name }}_sim_out);
+
+ return status;
+}
+
+
+int {{ model.name }}_acados_sim_solve(sim_solver_capsule *capsule)
+{
+ // integrate dynamics using acados sim_solver
+ int status = sim_solve(capsule->acados_sim_solver,
+ capsule->acados_sim_in, capsule->acados_sim_out);
+ if (status != 0)
+ printf("error in {{ model.name }}_acados_sim_solve()! Exiting.\n");
+
+ return status;
+}
+
+
+int {{ model.name }}_acados_sim_free(sim_solver_capsule *capsule)
+{
+ // free memory
+ sim_solver_destroy(capsule->acados_sim_solver);
+ sim_in_destroy(capsule->acados_sim_in);
+ sim_out_destroy(capsule->acados_sim_out);
+ sim_opts_destroy(capsule->acados_sim_opts);
+ sim_dims_destroy(capsule->acados_sim_dims);
+ sim_config_destroy(capsule->acados_sim_config);
+
+ // free external function
+{%- if solver_options.integrator_type == "IRK" %}
+ external_function_param_casadi_free(capsule->sim_impl_dae_fun);
+ external_function_param_casadi_free(capsule->sim_impl_dae_fun_jac_x_xdot_z);
+ external_function_param_casadi_free(capsule->sim_impl_dae_jac_x_xdot_u_z);
+{%- if hessian_approx == "EXACT" %}
+ external_function_param_casadi_free(capsule->sim_impl_dae_hess);
+{%- endif %}
+{%- elif solver_options.integrator_type == "ERK" %}
+ external_function_param_casadi_free(capsule->sim_forw_vde_casadi);
+ external_function_param_casadi_free(capsule->sim_expl_ode_fun_casadi);
+{%- if hessian_approx == "EXACT" %}
+ external_function_param_casadi_free(capsule->sim_expl_ode_hess);
+{%- endif %}
+{%- elif solver_options.integrator_type == "GNSF" %}
+ external_function_param_casadi_free(capsule->sim_gnsf_phi_fun);
+ external_function_param_casadi_free(capsule->sim_gnsf_phi_fun_jac_y);
+ external_function_param_casadi_free(capsule->sim_gnsf_phi_jac_y_uhat);
+ external_function_param_casadi_free(capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z);
+ external_function_param_casadi_free(capsule->sim_gnsf_get_matrices_fun);
+{% endif %}
+
+ return 0;
+}
+
+
+int {{ model.name }}_acados_sim_update_params(sim_solver_capsule *capsule, double *p, int np)
+{
+ int status = 0;
+ int casadi_np = {{ dims.np }};
+
+ if (casadi_np != np) {
+ printf("{{ model.name }}_acados_sim_update_params: trying to set %i parameters for external functions."
+ " External function has %i parameters. Exiting.\n", np, casadi_np);
+ exit(1);
+ }
+
+{%- if solver_options.integrator_type == "ERK" %}
+ capsule->sim_forw_vde_casadi[0].set_param(capsule->sim_forw_vde_casadi, p);
+ capsule->sim_expl_ode_fun_casadi[0].set_param(capsule->sim_expl_ode_fun_casadi, p);
+{%- if hessian_approx == "EXACT" %}
+ capsule->sim_expl_ode_hess[0].set_param(capsule->sim_expl_ode_hess, p);
+{%- endif %}
+{%- elif solver_options.integrator_type == "IRK" %}
+ capsule->sim_impl_dae_fun[0].set_param(capsule->sim_impl_dae_fun, p);
+ capsule->sim_impl_dae_fun_jac_x_xdot_z[0].set_param(capsule->sim_impl_dae_fun_jac_x_xdot_z, p);
+ capsule->sim_impl_dae_jac_x_xdot_u_z[0].set_param(capsule->sim_impl_dae_jac_x_xdot_u_z, p);
+{%- if hessian_approx == "EXACT" %}
+ capsule->sim_impl_dae_hess[0].set_param(capsule->sim_impl_dae_hess, p);
+{%- endif %}
+{%- elif solver_options.integrator_type == "GNSF" %}
+ capsule->sim_gnsf_phi_fun[0].set_param(capsule->sim_gnsf_phi_fun, p);
+ capsule->sim_gnsf_phi_fun_jac_y[0].set_param(capsule->sim_gnsf_phi_fun_jac_y, p);
+ capsule->sim_gnsf_phi_jac_y_uhat[0].set_param(capsule->sim_gnsf_phi_jac_y_uhat, p);
+ capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z[0].set_param(capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z, p);
+ capsule->sim_gnsf_get_matrices_fun[0].set_param(capsule->sim_gnsf_get_matrices_fun, p);
+{% endif %}
+
+ return status;
+}
+
+/* getters pointers to C objects*/
+sim_config * {{ model.name }}_acados_get_sim_config(sim_solver_capsule *capsule)
+{
+ return capsule->acados_sim_config;
+};
+
+sim_in * {{ model.name }}_acados_get_sim_in(sim_solver_capsule *capsule)
+{
+ return capsule->acados_sim_in;
+};
+
+sim_out * {{ model.name }}_acados_get_sim_out(sim_solver_capsule *capsule)
+{
+ return capsule->acados_sim_out;
+};
+
+void * {{ model.name }}_acados_get_sim_dims(sim_solver_capsule *capsule)
+{
+ return capsule->acados_sim_dims;
+};
+
+sim_opts * {{ model.name }}_acados_get_sim_opts(sim_solver_capsule *capsule)
+{
+ return capsule->acados_sim_opts;
+};
+
+sim_solver * {{ model.name }}_acados_get_sim_solver(sim_solver_capsule *capsule)
+{
+ return capsule->acados_sim_solver;
+};
+
diff --git a/pyextra/acados_template/c_templates_tera/acados_sim_solver.in.h b/pyextra/acados_template/c_templates_tera/acados_sim_solver.in.h
new file mode 100644
index 000000000..de332e835
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_sim_solver.in.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+#ifndef ACADOS_SIM_{{ model.name }}_H_
+#define ACADOS_SIM_{{ model.name }}_H_
+
+#include "acados_c/sim_interface.h"
+#include "acados_c/external_function_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// ** capsule for solver data **
+typedef struct sim_solver_capsule
+{
+ // acados objects
+ sim_in *acados_sim_in;
+ sim_out *acados_sim_out;
+ sim_solver *acados_sim_solver;
+ sim_opts *acados_sim_opts;
+ sim_config *acados_sim_config;
+ void *acados_sim_dims;
+
+ /* external functions */
+ // ERK
+ external_function_param_casadi * sim_forw_vde_casadi;
+ external_function_param_casadi * sim_expl_ode_fun_casadi;
+ external_function_param_casadi * sim_expl_ode_hess;
+
+ // IRK
+ external_function_param_casadi * sim_impl_dae_fun;
+ external_function_param_casadi * sim_impl_dae_fun_jac_x_xdot_z;
+ external_function_param_casadi * sim_impl_dae_jac_x_xdot_u_z;
+ external_function_param_casadi * sim_impl_dae_hess;
+
+ // GNSF
+ external_function_param_casadi * sim_gnsf_phi_fun;
+ external_function_param_casadi * sim_gnsf_phi_fun_jac_y;
+ external_function_param_casadi * sim_gnsf_phi_jac_y_uhat;
+ external_function_param_casadi * sim_gnsf_f_lo_jac_x1_x1dot_u_z;
+ external_function_param_casadi * sim_gnsf_get_matrices_fun;
+
+} sim_solver_capsule;
+
+
+int {{ model.name }}_acados_sim_create(sim_solver_capsule *capsule);
+int {{ model.name }}_acados_sim_solve(sim_solver_capsule *capsule);
+int {{ model.name }}_acados_sim_free(sim_solver_capsule *capsule);
+int {{ model.name }}_acados_sim_update_params(sim_solver_capsule *capsule, double *value, int np);
+
+sim_config * {{ model.name }}_acados_get_sim_config(sim_solver_capsule *capsule);
+sim_in * {{ model.name }}_acados_get_sim_in(sim_solver_capsule *capsule);
+sim_out * {{ model.name }}_acados_get_sim_out(sim_solver_capsule *capsule);
+void * {{ model.name }}_acados_get_sim_dims(sim_solver_capsule *capsule);
+sim_opts * {{ model.name }}_acados_get_sim_opts(sim_solver_capsule *capsule);
+sim_solver * {{ model.name }}_acados_get_sim_solver(sim_solver_capsule *capsule);
+
+
+sim_solver_capsule * {{ model.name }}_acados_sim_solver_create_capsule(void);
+int {{ model.name }}_acados_sim_solver_free_capsule(sim_solver_capsule *capsule);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ACADOS_SIM_{{ model.name }}_H_
diff --git a/pyextra/acados_template/c_templates_tera/acados_sim_solver_sfun.in.c b/pyextra/acados_template/c_templates_tera/acados_sim_solver_sfun.in.c
new file mode 100644
index 000000000..234295fa2
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_sim_solver_sfun.in.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+#define S_FUNCTION_NAME acados_sim_solver_sfunction_{{ model.name }}
+#define S_FUNCTION_LEVEL 2
+
+#define MDL_START
+
+// acados
+#include "acados/utils/print.h"
+#include "acados_c/ocp_nlp_interface.h"
+#include "acados_c/external_function_interface.h"
+
+// example specific
+#include "{{ model.name }}_model/{{ model.name }}_model.h"
+#include "acados_sim_solver_{{ model.name }}.h"
+
+#include "simstruc.h"
+
+#define SAMPLINGTIME {{ solver_options.Tsim }}
+
+
+static void mdlInitializeSizes (SimStruct *S)
+{
+ // specify the number of continuous and discrete states
+ ssSetNumContStates(S, 0);
+ ssSetNumDiscStates(S, 0);
+
+ {# compute number of input ports #}
+ {%- set n_inputs = 1 %} {# x0 #}
+ {%- if dims.nu > 0 %} {# u0 -#}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif %}
+ {%- if dims.np > 0 %} {# parameters #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif %}
+
+ // specify the number of input ports
+ if ( !ssSetNumInputPorts(S, {{ n_inputs }}) )
+ return;
+
+ // specify the number of output ports
+ if ( !ssSetNumOutputPorts(S, 1) )
+ return;
+
+ // specify dimension information for the input ports
+ {%- set i_input = 0 %}
+ // x0
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nx }});
+
+ {%- if dims.nu > 0 %}
+ {%- set i_input = i_input + 1 %}
+ // u0
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nu }});
+ {%- endif %}
+
+ {%- if dims.np > 0 %}
+ {%- set i_input = i_input + 1 %}
+ // parameters
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.np }});
+ {%- endif %}
+
+ // specify dimension information for the output ports
+ ssSetOutputPortVectorDimension(S, 0, {{ dims.nx }} ); // xnext
+
+ // specify the direct feedthrough status
+ // should be set to 1 for all inputs used in mdlOutputs
+ {%- for i in range(end=n_inputs) %}
+ ssSetInputPortDirectFeedThrough(S, {{ i }}, 1);
+ {%- endfor %}
+
+ // one sample time
+ ssSetNumSampleTimes(S, 1);
+}
+
+
+#if defined(MATLAB_MEX_FILE)
+
+#define MDL_SET_INPUT_PORT_DIMENSION_INFO
+#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
+
+static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
+{
+ if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) )
+ return;
+}
+
+static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
+{
+ if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) )
+ return;
+}
+
+#endif /* MATLAB_MEX_FILE */
+
+
+static void mdlInitializeSampleTimes(SimStruct *S)
+{
+ ssSetSampleTime(S, 0, SAMPLINGTIME);
+ ssSetOffsetTime(S, 0, 0.0);
+}
+
+
+static void mdlStart(SimStruct *S)
+{
+ sim_solver_capsule *capsule = {{ model.name }}_acados_sim_solver_create_capsule();
+ {{ model.name }}_acados_sim_create(capsule);
+
+ ssSetUserData(S, (void*)capsule);
+}
+
+static void mdlOutputs(SimStruct *S, int_T tid)
+{
+ sim_solver_capsule *capsule = ssGetUserData(S);
+
+ sim_config *acados_sim_config = {{ model.name }}_acados_get_sim_config(capsule);
+ sim_in *acados_sim_in = {{ model.name }}_acados_get_sim_in(capsule);
+ sim_out *acados_sim_out = {{ model.name }}_acados_get_sim_out(capsule);
+ void *acados_sim_dims = {{ model.name }}_acados_get_sim_dims(capsule);
+ // sim_opts * {{ model.name }}_acados_get_sim_opts(capsule);
+ // sim_solver * {{ model.name }}_acados_get_sim_solver(capsule);
+
+ InputRealPtrsType in_sign;
+ {% set input_sizes = [dims.nx, dims.nu, dims.np] %}
+
+ // local buffer
+ {%- set buffer_size = input_sizes | sort | last %}
+ real_t buffer[{{ buffer_size }}];
+
+
+ /* go through inputs */
+ {%- set i_input = 0 %}
+ // initial condition
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int i = 0; i < {{ dims.nx }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ sim_in_set(acados_sim_config, acados_sim_dims,
+ acados_sim_in, "x", buffer);
+
+
+ // ssPrintf("\nin acados sim:\n");
+ // for (int i = 0; i < {{ dims.nx }}; i++) ssPrintf("x0[%d] = %f\n", i, buffer[i]);
+ // ssPrintf("\n");
+
+{% if dims.nu > 0 %}
+ // control input - u
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.nu }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ sim_in_set(acados_sim_config, acados_sim_dims,
+ acados_sim_in, "u", buffer);
+{%- endif %}
+
+
+{% if dims.np > 0 %}
+ // parameters
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.np }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ // update value of parameters
+ {{ model.name }}_acados_sim_update_params(capsule, buffer, {{ dims.np }});
+{%- endif %}
+
+
+ /* call solver */
+ int acados_status = {{ model.name }}_acados_sim_solve(capsule);
+
+
+ /* set outputs */
+ real_t *out_x = ssGetOutputPortRealSignal(S, 0);
+
+ // get simulated state
+ sim_out_get(acados_sim_config, acados_sim_dims, acados_sim_out,
+ "xn", (void *) out_x);
+
+ // ssPrintf("\nacados sim solve: returned %d\n", acados_status);
+ // for (int i = 0; i < {{ dims.nx }}; i++) ssPrintf("x_sim[%d] = %f\n", i, out_x[i]);
+ // ssPrintf("\n");
+
+}
+
+
+static void mdlTerminate(SimStruct *S)
+{
+ sim_solver_capsule *capsule = ssGetUserData(S);
+
+ {{ model.name }}_acados_sim_free(capsule);
+ {{ model.name }}_acados_sim_solver_free_capsule(capsule);
+}
+
+
+#ifdef MATLAB_MEX_FILE
+#include "simulink.c"
+#else
+#include "cg_sfun.h"
+#endif
diff --git a/pyextra/acados_template/c_templates_tera/acados_solver.in.c b/pyextra/acados_template/c_templates_tera/acados_solver.in.c
new file mode 100644
index 000000000..da73f6e29
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_solver.in.c
@@ -0,0 +1,2446 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+// standard
+#include
+#include
+// acados
+#include "acados/utils/print.h"
+#include "acados_c/ocp_nlp_interface.h"
+#include "acados_c/external_function_interface.h"
+
+// example specific
+#include "{{ model.name }}_model/{{ model.name }}_model.h"
+{% if constraints.constr_type == "BGP" and dims.nphi %}
+#include "{{ model.name }}_constraints/{{ model.name }}_phi_constraint.h"
+{% endif %}
+{% if constraints.constr_type_e == "BGP" and dims.nphi_e > 0 %}
+#include "{{ model.name }}_constraints/{{ model.name }}_phi_e_constraint.h"
+{% endif %}
+{% if constraints.constr_type == "BGH" and dims.nh > 0 %}
+#include "{{ model.name }}_constraints/{{ model.name }}_h_constraint.h"
+{% endif %}
+{% if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %}
+#include "{{ model.name }}_constraints/{{ model.name }}_h_e_constraint.h"
+{% endif %}
+{%- if cost.cost_type == "NONLINEAR_LS" %}
+#include "{{ model.name }}_cost/{{ model.name }}_cost_y_fun.h"
+{%- elif cost.cost_type == "EXTERNAL" %}
+#include "{{ model.name }}_cost/{{ model.name }}_external_cost.h"
+{%- endif %}
+{%- if cost.cost_type_0 == "NONLINEAR_LS" %}
+#include "{{ model.name }}_cost/{{ model.name }}_cost_y_0_fun.h"
+{%- elif cost.cost_type_0 == "EXTERNAL" %}
+#include "{{ model.name }}_cost/{{ model.name }}_external_cost_0.h"
+{%- endif %}
+{%- if cost.cost_type_e == "NONLINEAR_LS" %}
+#include "{{ model.name }}_cost/{{ model.name }}_cost_y_e_fun.h"
+{%- elif cost.cost_type_e == "EXTERNAL" %}
+#include "{{ model.name }}_cost/{{ model.name }}_external_cost_e.h"
+{%- endif %}
+
+#include "acados_solver_{{ model.name }}.h"
+
+#define NX {{ dims.nx }}
+#define NZ {{ dims.nz }}
+#define NU {{ dims.nu }}
+#define NP {{ dims.np }}
+#define NBX {{ dims.nbx }}
+#define NBX0 {{ dims.nbx_0 }}
+#define NBU {{ dims.nbu }}
+#define NSBX {{ dims.nsbx }}
+#define NSBU {{ dims.nsbu }}
+#define NSH {{ dims.nsh }}
+#define NSG {{ dims.nsg }}
+#define NSPHI {{ dims.nsphi }}
+#define NSHN {{ dims.nsh_e }}
+#define NSGN {{ dims.nsg_e }}
+#define NSPHIN {{ dims.nsphi_e }}
+#define NSBXN {{ dims.nsbx_e }}
+#define NS {{ dims.ns }}
+#define NSN {{ dims.ns_e }}
+#define NG {{ dims.ng }}
+#define NBXN {{ dims.nbx_e }}
+#define NGN {{ dims.ng_e }}
+#define NY0 {{ dims.ny_0 }}
+#define NY {{ dims.ny }}
+#define NYN {{ dims.ny_e }}
+#define N {{ dims.N }}
+#define NH {{ dims.nh }}
+#define NPHI {{ dims.nphi }}
+#define NHN {{ dims.nh_e }}
+#define NPHIN {{ dims.nphi_e }}
+#define NR {{ dims.nr }}
+
+
+// ** solver data **
+
+nlp_solver_capsule * {{ model.name }}_acados_create_capsule()
+{
+ void* capsule_mem = malloc(sizeof(nlp_solver_capsule));
+ nlp_solver_capsule *capsule = (nlp_solver_capsule *) capsule_mem;
+
+ return capsule;
+}
+
+
+int {{ model.name }}_acados_free_capsule(nlp_solver_capsule *capsule)
+{
+ free(capsule);
+ return 0;
+}
+
+
+int {{ model.name }}_acados_create(nlp_solver_capsule * capsule)
+{
+ int status = 0;
+
+ // number of expected runtime parameters
+ capsule->nlp_np = NP;
+
+ /************************************************
+ * plan & config
+ ************************************************/
+ ocp_nlp_plan * nlp_solver_plan = ocp_nlp_plan_create(N);
+ capsule->nlp_solver_plan = nlp_solver_plan;
+
+ {%- if solver_options.nlp_solver_type == "SQP" %}
+ nlp_solver_plan->nlp_solver = SQP;
+ {% else %}
+ nlp_solver_plan->nlp_solver = SQP_RTI;
+ {%- endif %}
+
+ nlp_solver_plan->ocp_qp_solver_plan.qp_solver = {{ solver_options.qp_solver }};
+
+ nlp_solver_plan->nlp_cost[0] = {{ cost.cost_type_0 }};
+ for (int i = 1; i < N; i++)
+ nlp_solver_plan->nlp_cost[i] = {{ cost.cost_type }};
+
+ nlp_solver_plan->nlp_cost[N] = {{ cost.cost_type_e }};
+
+ for (int i = 0; i < N; i++)
+ {
+ {% if solver_options.integrator_type == "DISCRETE" %}
+ nlp_solver_plan->nlp_dynamics[i] = DISCRETE_MODEL;
+ // discrete dynamics does not need sim solver option, this field is ignored
+ nlp_solver_plan->sim_solver_plan[i].sim_solver = INVALID_SIM_SOLVER;
+ {% else %}
+ nlp_solver_plan->nlp_dynamics[i] = CONTINUOUS_MODEL;
+ nlp_solver_plan->sim_solver_plan[i].sim_solver = {{ solver_options.integrator_type }};
+ {%- endif %}
+ }
+
+ for (int i = 0; i < N; i++)
+ {
+ {% if constraints.constr_type == "BGP" %}
+ nlp_solver_plan->nlp_constraints[i] = BGP;
+ {%- else -%}
+ nlp_solver_plan->nlp_constraints[i] = BGH;
+ {%- endif %}
+ }
+
+ {%- if constraints.constr_type_e == "BGP" %}
+ nlp_solver_plan->nlp_constraints[N] = BGP;
+ {% else %}
+ nlp_solver_plan->nlp_constraints[N] = BGH;
+ {%- endif %}
+
+{%- if solver_options.hessian_approx == "EXACT" %}
+ {%- if solver_options.regularize_method == "NO_REGULARIZE" %}
+ nlp_solver_plan->regularization = NO_REGULARIZE;
+ {%- elif solver_options.regularize_method == "MIRROR" %}
+ nlp_solver_plan->regularization = MIRROR;
+ {%- elif solver_options.regularize_method == "PROJECT" %}
+ nlp_solver_plan->regularization = PROJECT;
+ {%- elif solver_options.regularize_method == "PROJECT_REDUC_HESS" %}
+ nlp_solver_plan->regularization = PROJECT_REDUC_HESS;
+ {%- elif solver_options.regularize_method == "CONVEXIFY" %}
+ nlp_solver_plan->regularization = CONVEXIFY;
+ {%- endif %}
+{%- endif %}
+ ocp_nlp_config * nlp_config = ocp_nlp_config_create(*nlp_solver_plan);
+ capsule->nlp_config = nlp_config;
+
+
+ /************************************************
+ * dimensions
+ ************************************************/
+ #define NINTNP1MEMS 17
+ int* intNp1mem = (int*)malloc( (N+1)*sizeof(int)*NINTNP1MEMS );
+
+ int* nx = intNp1mem + (N+1)*0;
+ int* nu = intNp1mem + (N+1)*1;
+ int* nbx = intNp1mem + (N+1)*2;
+ int* nbu = intNp1mem + (N+1)*3;
+ int* nsbx = intNp1mem + (N+1)*4;
+ int* nsbu = intNp1mem + (N+1)*5;
+ int* nsg = intNp1mem + (N+1)*6;
+ int* nsh = intNp1mem + (N+1)*7;
+ int* nsphi = intNp1mem + (N+1)*8;
+ int* ns = intNp1mem + (N+1)*9;
+ int* ng = intNp1mem + (N+1)*10;
+ int* nh = intNp1mem + (N+1)*11;
+ int* nphi = intNp1mem + (N+1)*12;
+ int* nz = intNp1mem + (N+1)*13;
+ int* ny = intNp1mem + (N+1)*14;
+ int* nr = intNp1mem + (N+1)*15;
+ int* nbxe = intNp1mem + (N+1)*16;
+
+ for (int i = 0; i < N+1; i++)
+ {
+ // common
+ nx[i] = NX;
+ nu[i] = NU;
+ nz[i] = NZ;
+ ns[i] = NS;
+ // cost
+ ny[i] = NY;
+ // constraints
+ nbx[i] = NBX;
+ nbu[i] = NBU;
+ nsbx[i] = NSBX;
+ nsbu[i] = NSBU;
+ nsg[i] = NSG;
+ nsh[i] = NSH;
+ nsphi[i] = NSPHI;
+ ng[i] = NG;
+ nh[i] = NH;
+ nphi[i] = NPHI;
+ nr[i] = NR;
+ nbxe[i] = 0;
+ }
+
+ // for initial state
+ nbx[0] = NBX0;
+ nsbx[0] = 0;
+ ns[0] = NS - NSBX;
+ nbxe[0] = {{ dims.nbxe_0 }};
+ ny[0] = NY0;
+
+ // terminal - common
+ nu[N] = 0;
+ nz[N] = 0;
+ ns[N] = NSN;
+ // cost
+ ny[N] = NYN;
+ // constraint
+ nbx[N] = NBXN;
+ nbu[N] = 0;
+ ng[N] = NGN;
+ nh[N] = NHN;
+ nphi[N] = NPHIN;
+ nr[N] = {{ dims.nr_e }};
+
+ nsbx[N] = NSBXN;
+ nsbu[N] = 0;
+ nsg[N] = NSGN;
+ nsh[N] = NSHN;
+ nsphi[N] = NSPHIN;
+
+ /* create and set ocp_nlp_dims */
+ ocp_nlp_dims * nlp_dims = ocp_nlp_dims_create(nlp_config);
+ capsule->nlp_dims = nlp_dims;
+
+ ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "nx", nx);
+ ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "nu", nu);
+ ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "nz", nz);
+ ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "ns", ns);
+
+ for (int i = 0; i <= N; i++)
+ {
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nbx", &nbx[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nbu", &nbu[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsbx", &nsbx[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsbu", &nsbu[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "ng", &ng[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsg", &nsg[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nbxe", &nbxe[i]);
+ }
+
+ {%- if cost.cost_type_0 == "NONLINEAR_LS" or cost.cost_type_0 == "LINEAR_LS" %}
+ ocp_nlp_dims_set_cost(nlp_config, nlp_dims, 0, "ny", &ny[0]);
+ {%- endif %}
+
+ {%- if cost.cost_type == "NONLINEAR_LS" or cost.cost_type == "LINEAR_LS" %}
+ for (int i = 1; i < N; i++)
+ ocp_nlp_dims_set_cost(nlp_config, nlp_dims, i, "ny", &ny[i]);
+ {%- endif %}
+
+ for (int i = 0; i < N; i++)
+ {
+ {%- if constraints.constr_type == "BGH" and dims.nh > 0 %}
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nh", &nh[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsh", &nsh[i]);
+ {%- elif constraints.constr_type == "BGP" and dims.nphi > 0 %}
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nr", &nr[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nphi", &nphi[i]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsphi", &nsphi[i]);
+ {%- endif %}
+ }
+
+ {%- if constraints.constr_type_e == "BGH" %}
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nh", &nh[N]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nsh", &nsh[N]);
+ {%- elif constraints.constr_type_e == "BGP" %}
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nr", &nr[N]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nphi", &nphi[N]);
+ ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nsphi", &nsphi[N]);
+ {%- endif %}
+ {%- if cost.cost_type_e == "NONLINEAR_LS" or cost.cost_type_e == "LINEAR_LS" %}
+ ocp_nlp_dims_set_cost(nlp_config, nlp_dims, N, "ny", &ny[N]);
+ {%- endif %}
+
+ free(intNp1mem);
+
+{% if solver_options.integrator_type == "GNSF" -%}
+ // GNSF specific dimensions
+ int gnsf_nx1 = {{ dims.gnsf_nx1 }};
+ int gnsf_nz1 = {{ dims.gnsf_nz1 }};
+ int gnsf_nout = {{ dims.gnsf_nout }};
+ int gnsf_ny = {{ dims.gnsf_ny }};
+ int gnsf_nuhat = {{ dims.gnsf_nuhat }};
+
+ for (int i = 0; i < N; i++)
+ {
+ if (nlp_solver_plan->sim_solver_plan[i].sim_solver == GNSF)
+ {
+ ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nx1", &gnsf_nx1);
+ ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nz1", &gnsf_nz1);
+ ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nout", &gnsf_nout);
+ ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_ny", &gnsf_ny);
+ ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nuhat", &gnsf_nuhat);
+ }
+ }
+{%- endif %}
+
+ /************************************************
+ * external functions
+ ************************************************/
+ {%- if constraints.constr_type == "BGP" %}
+ capsule->phi_constraint = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++)
+ {
+ // nonlinear part of convex-composite constraint
+ capsule->phi_constraint[i].casadi_fun = &{{ model.name }}_phi_constraint;
+ capsule->phi_constraint[i].casadi_n_in = &{{ model.name }}_phi_constraint_n_in;
+ capsule->phi_constraint[i].casadi_n_out = &{{ model.name }}_phi_constraint_n_out;
+ capsule->phi_constraint[i].casadi_sparsity_in = &{{ model.name }}_phi_constraint_sparsity_in;
+ capsule->phi_constraint[i].casadi_sparsity_out = &{{ model.name }}_phi_constraint_sparsity_out;
+ capsule->phi_constraint[i].casadi_work = &{{ model.name }}_phi_constraint_work;
+
+ external_function_param_casadi_create(&capsule->phi_constraint[i], {{ dims.np }});
+ }
+ {%- endif %}
+
+ {%- if constraints.constr_type_e == "BGP" %}
+ // nonlinear part of convex-composite constraint
+ capsule->phi_e_constraint.casadi_fun = &{{ model.name }}_phi_e_constraint;
+ capsule->phi_e_constraint.casadi_n_in = &{{ model.name }}_phi_e_constraint_n_in;
+ capsule->phi_e_constraint.casadi_n_out = &{{ model.name }}_phi_e_constraint_n_out;
+ capsule->phi_e_constraint.casadi_sparsity_in = &{{ model.name }}_phi_e_constraint_sparsity_in;
+ capsule->phi_e_constraint.casadi_sparsity_out = &{{ model.name }}_phi_e_constraint_sparsity_out;
+ capsule->phi_e_constraint.casadi_work = &{{ model.name }}_phi_e_constraint_work;
+
+ external_function_param_casadi_create(&capsule->phi_e_constraint, {{ dims.np }});
+ {% endif %}
+
+ {%- if constraints.constr_type == "BGH" and dims.nh > 0 %}
+ capsule->nl_constr_h_fun_jac = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->nl_constr_h_fun_jac[i].casadi_fun = &{{ model.name }}_constr_h_fun_jac_uxt_zt;
+ capsule->nl_constr_h_fun_jac[i].casadi_n_in = &{{ model.name }}_constr_h_fun_jac_uxt_zt_n_in;
+ capsule->nl_constr_h_fun_jac[i].casadi_n_out = &{{ model.name }}_constr_h_fun_jac_uxt_zt_n_out;
+ capsule->nl_constr_h_fun_jac[i].casadi_sparsity_in = &{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_in;
+ capsule->nl_constr_h_fun_jac[i].casadi_sparsity_out = &{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_out;
+ capsule->nl_constr_h_fun_jac[i].casadi_work = &{{ model.name }}_constr_h_fun_jac_uxt_zt_work;
+ external_function_param_casadi_create(&capsule->nl_constr_h_fun_jac[i], {{ dims.np }});
+ }
+ capsule->nl_constr_h_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->nl_constr_h_fun[i].casadi_fun = &{{ model.name }}_constr_h_fun;
+ capsule->nl_constr_h_fun[i].casadi_n_in = &{{ model.name }}_constr_h_fun_n_in;
+ capsule->nl_constr_h_fun[i].casadi_n_out = &{{ model.name }}_constr_h_fun_n_out;
+ capsule->nl_constr_h_fun[i].casadi_sparsity_in = &{{ model.name }}_constr_h_fun_sparsity_in;
+ capsule->nl_constr_h_fun[i].casadi_sparsity_out = &{{ model.name }}_constr_h_fun_sparsity_out;
+ capsule->nl_constr_h_fun[i].casadi_work = &{{ model.name }}_constr_h_fun_work;
+ external_function_param_casadi_create(&capsule->nl_constr_h_fun[i], {{ dims.np }});
+ }
+ {% if solver_options.hessian_approx == "EXACT" %}
+ capsule->nl_constr_h_fun_jac_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->nl_constr_h_fun_jac_hess[i].casadi_fun = &{{ model.name }}_constr_h_fun_jac_uxt_zt_hess;
+ capsule->nl_constr_h_fun_jac_hess[i].casadi_n_in = &{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_in;
+ capsule->nl_constr_h_fun_jac_hess[i].casadi_n_out = &{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_out;
+ capsule->nl_constr_h_fun_jac_hess[i].casadi_sparsity_in = &{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_in;
+ capsule->nl_constr_h_fun_jac_hess[i].casadi_sparsity_out = &{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_out;
+ capsule->nl_constr_h_fun_jac_hess[i].casadi_work = &{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_work;
+
+ external_function_param_casadi_create(&capsule->nl_constr_h_fun_jac_hess[i], {{ dims.np }});
+ }
+ {% endif %}
+ {% endif %}
+
+ {%- if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %}
+ capsule->nl_constr_h_e_fun_jac.casadi_fun = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt;
+ capsule->nl_constr_h_e_fun_jac.casadi_n_in = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_n_in;
+ capsule->nl_constr_h_e_fun_jac.casadi_n_out = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_n_out;
+ capsule->nl_constr_h_e_fun_jac.casadi_sparsity_in = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_sparsity_in;
+ capsule->nl_constr_h_e_fun_jac.casadi_sparsity_out = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_sparsity_out;
+ capsule->nl_constr_h_e_fun_jac.casadi_work = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_work;
+ external_function_param_casadi_create(&capsule->nl_constr_h_e_fun_jac, {{ dims.np }});
+
+ capsule->nl_constr_h_e_fun.casadi_fun = &{{ model.name }}_constr_h_e_fun;
+ capsule->nl_constr_h_e_fun.casadi_n_in = &{{ model.name }}_constr_h_e_fun_n_in;
+ capsule->nl_constr_h_e_fun.casadi_n_out = &{{ model.name }}_constr_h_e_fun_n_out;
+ capsule->nl_constr_h_e_fun.casadi_sparsity_in = &{{ model.name }}_constr_h_e_fun_sparsity_in;
+ capsule->nl_constr_h_e_fun.casadi_sparsity_out = &{{ model.name }}_constr_h_e_fun_sparsity_out;
+ capsule->nl_constr_h_e_fun.casadi_work = &{{ model.name }}_constr_h_e_fun_work;
+ external_function_param_casadi_create(&capsule->nl_constr_h_e_fun, {{ dims.np }});
+
+ {% if solver_options.hessian_approx == "EXACT" %}
+ capsule->nl_constr_h_e_fun_jac_hess.casadi_fun = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess;
+ capsule->nl_constr_h_e_fun_jac_hess.casadi_n_in = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_n_in;
+ capsule->nl_constr_h_e_fun_jac_hess.casadi_n_out = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_n_out;
+ capsule->nl_constr_h_e_fun_jac_hess.casadi_sparsity_in = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_sparsity_in;
+ capsule->nl_constr_h_e_fun_jac_hess.casadi_sparsity_out = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_sparsity_out;
+ capsule->nl_constr_h_e_fun_jac_hess.casadi_work = &{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_work;
+ external_function_param_casadi_create(&capsule->nl_constr_h_e_fun_jac_hess, {{ dims.np }});
+ {% endif %}
+ {%- endif %}
+
+{% if solver_options.integrator_type == "ERK" %}
+ // explicit ode
+ capsule->forw_vde_casadi = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->forw_vde_casadi[i].casadi_fun = &{{ model.name }}_expl_vde_forw;
+ capsule->forw_vde_casadi[i].casadi_n_in = &{{ model.name }}_expl_vde_forw_n_in;
+ capsule->forw_vde_casadi[i].casadi_n_out = &{{ model.name }}_expl_vde_forw_n_out;
+ capsule->forw_vde_casadi[i].casadi_sparsity_in = &{{ model.name }}_expl_vde_forw_sparsity_in;
+ capsule->forw_vde_casadi[i].casadi_sparsity_out = &{{ model.name }}_expl_vde_forw_sparsity_out;
+ capsule->forw_vde_casadi[i].casadi_work = &{{ model.name }}_expl_vde_forw_work;
+ external_function_param_casadi_create(&capsule->forw_vde_casadi[i], {{ dims.np }});
+ }
+
+ capsule->expl_ode_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->expl_ode_fun[i].casadi_fun = &{{ model.name }}_expl_ode_fun;
+ capsule->expl_ode_fun[i].casadi_n_in = &{{ model.name }}_expl_ode_fun_n_in;
+ capsule->expl_ode_fun[i].casadi_n_out = &{{ model.name }}_expl_ode_fun_n_out;
+ capsule->expl_ode_fun[i].casadi_sparsity_in = &{{ model.name }}_expl_ode_fun_sparsity_in;
+ capsule->expl_ode_fun[i].casadi_sparsity_out = &{{ model.name }}_expl_ode_fun_sparsity_out;
+ capsule->expl_ode_fun[i].casadi_work = &{{ model.name }}_expl_ode_fun_work;
+ external_function_param_casadi_create(&capsule->expl_ode_fun[i], {{ dims.np }});
+ }
+
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->hess_vde_casadi = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->hess_vde_casadi[i].casadi_fun = &{{ model.name }}_expl_ode_hess;
+ capsule->hess_vde_casadi[i].casadi_n_in = &{{ model.name }}_expl_ode_hess_n_in;
+ capsule->hess_vde_casadi[i].casadi_n_out = &{{ model.name }}_expl_ode_hess_n_out;
+ capsule->hess_vde_casadi[i].casadi_sparsity_in = &{{ model.name }}_expl_ode_hess_sparsity_in;
+ capsule->hess_vde_casadi[i].casadi_sparsity_out = &{{ model.name }}_expl_ode_hess_sparsity_out;
+ capsule->hess_vde_casadi[i].casadi_work = &{{ model.name }}_expl_ode_hess_work;
+ external_function_param_casadi_create(&capsule->hess_vde_casadi[i], {{ dims.np }});
+ }
+ {%- endif %}
+
+{% elif solver_options.integrator_type == "IRK" %}
+ // implicit dae
+ capsule->impl_dae_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->impl_dae_fun[i].casadi_fun = &{{ model.name }}_impl_dae_fun;
+ capsule->impl_dae_fun[i].casadi_work = &{{ model.name }}_impl_dae_fun_work;
+ capsule->impl_dae_fun[i].casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_sparsity_in;
+ capsule->impl_dae_fun[i].casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_sparsity_out;
+ capsule->impl_dae_fun[i].casadi_n_in = &{{ model.name }}_impl_dae_fun_n_in;
+ capsule->impl_dae_fun[i].casadi_n_out = &{{ model.name }}_impl_dae_fun_n_out;
+ external_function_param_casadi_create(&capsule->impl_dae_fun[i], {{ dims.np }});
+ }
+
+ capsule->impl_dae_fun_jac_x_xdot_z = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->impl_dae_fun_jac_x_xdot_z[i].casadi_fun = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z;
+ capsule->impl_dae_fun_jac_x_xdot_z[i].casadi_work = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_work;
+ capsule->impl_dae_fun_jac_x_xdot_z[i].casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_in;
+ capsule->impl_dae_fun_jac_x_xdot_z[i].casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_out;
+ capsule->impl_dae_fun_jac_x_xdot_z[i].casadi_n_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_in;
+ capsule->impl_dae_fun_jac_x_xdot_z[i].casadi_n_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_out;
+ external_function_param_casadi_create(&capsule->impl_dae_fun_jac_x_xdot_z[i], {{ dims.np }});
+ }
+
+ capsule->impl_dae_jac_x_xdot_u_z = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->impl_dae_jac_x_xdot_u_z[i].casadi_fun = &{{ model.name }}_impl_dae_jac_x_xdot_u_z;
+ capsule->impl_dae_jac_x_xdot_u_z[i].casadi_work = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_work;
+ capsule->impl_dae_jac_x_xdot_u_z[i].casadi_sparsity_in = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_in;
+ capsule->impl_dae_jac_x_xdot_u_z[i].casadi_sparsity_out = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_out;
+ capsule->impl_dae_jac_x_xdot_u_z[i].casadi_n_in = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_n_in;
+ capsule->impl_dae_jac_x_xdot_u_z[i].casadi_n_out = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_n_out;
+ external_function_param_casadi_create(&capsule->impl_dae_jac_x_xdot_u_z[i], {{ dims.np }});
+ }
+
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->impl_dae_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->impl_dae_hess[i].casadi_fun = &{{ model.name }}_impl_dae_hess;
+ capsule->impl_dae_hess[i].casadi_work = &{{ model.name }}_impl_dae_hess_work;
+ capsule->impl_dae_hess[i].casadi_sparsity_in = &{{ model.name }}_impl_dae_hess_sparsity_in;
+ capsule->impl_dae_hess[i].casadi_sparsity_out = &{{ model.name }}_impl_dae_hess_sparsity_out;
+ capsule->impl_dae_hess[i].casadi_n_in = &{{ model.name }}_impl_dae_hess_n_in;
+ capsule->impl_dae_hess[i].casadi_n_out = &{{ model.name }}_impl_dae_hess_n_out;
+ external_function_param_casadi_create(&capsule->impl_dae_hess[i], {{ dims.np }});
+ }
+ {%- endif %}
+{% elif solver_options.integrator_type == "LIFTED_IRK" %}
+ // external functions (implicit model)
+ capsule->impl_dae_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->impl_dae_fun[i].casadi_fun = &{{ model.name }}_impl_dae_fun;
+ capsule->impl_dae_fun[i].casadi_work = &{{ model.name }}_impl_dae_fun_work;
+ capsule->impl_dae_fun[i].casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_sparsity_in;
+ capsule->impl_dae_fun[i].casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_sparsity_out;
+ capsule->impl_dae_fun[i].casadi_n_in = &{{ model.name }}_impl_dae_fun_n_in;
+ capsule->impl_dae_fun[i].casadi_n_out = &{{ model.name }}_impl_dae_fun_n_out;
+ external_function_param_casadi_create(&capsule->impl_dae_fun[i], {{ dims.np }});
+ }
+
+ capsule->impl_dae_fun_jac_x_xdot_u = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); for (int i = 0; i < N; i++) {
+ capsule->impl_dae_fun_jac_x_xdot_u[i].casadi_fun = &{{ model.name }}_impl_dae_fun_jac_x_xdot_u;
+ capsule->impl_dae_fun_jac_x_xdot_u[i].casadi_work = &{{ model.name }}_impl_dae_fun_jac_x_xdot_u_work;
+ capsule->impl_dae_fun_jac_x_xdot_u[i].casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_u_sparsity_in;
+ capsule->impl_dae_fun_jac_x_xdot_u[i].casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_u_sparsity_out;
+ capsule->impl_dae_fun_jac_x_xdot_u[i].casadi_n_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_u_n_in;
+ capsule->impl_dae_fun_jac_x_xdot_u[i].casadi_n_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_u_n_out;
+ external_function_param_casadi_create(&capsule->impl_dae_fun_jac_x_xdot_u[i], {{ dims.np }});
+ }
+
+{% elif solver_options.integrator_type == "GNSF" %}
+ capsule->gnsf_phi_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->gnsf_phi_fun[i].casadi_fun = &{{ model.name }}_gnsf_phi_fun;
+ capsule->gnsf_phi_fun[i].casadi_work = &{{ model.name }}_gnsf_phi_fun_work;
+ capsule->gnsf_phi_fun[i].casadi_sparsity_in = &{{ model.name }}_gnsf_phi_fun_sparsity_in;
+ capsule->gnsf_phi_fun[i].casadi_sparsity_out = &{{ model.name }}_gnsf_phi_fun_sparsity_out;
+ capsule->gnsf_phi_fun[i].casadi_n_in = &{{ model.name }}_gnsf_phi_fun_n_in;
+ capsule->gnsf_phi_fun[i].casadi_n_out = &{{ model.name }}_gnsf_phi_fun_n_out;
+ external_function_param_casadi_create(&capsule->gnsf_phi_fun[i], {{ dims.np }});
+ }
+
+ capsule->gnsf_phi_fun_jac_y = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->gnsf_phi_fun_jac_y[i].casadi_fun = &{{ model.name }}_gnsf_phi_fun_jac_y;
+ capsule->gnsf_phi_fun_jac_y[i].casadi_work = &{{ model.name }}_gnsf_phi_fun_jac_y_work;
+ capsule->gnsf_phi_fun_jac_y[i].casadi_sparsity_in = &{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_in;
+ capsule->gnsf_phi_fun_jac_y[i].casadi_sparsity_out = &{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_out;
+ capsule->gnsf_phi_fun_jac_y[i].casadi_n_in = &{{ model.name }}_gnsf_phi_fun_jac_y_n_in;
+ capsule->gnsf_phi_fun_jac_y[i].casadi_n_out = &{{ model.name }}_gnsf_phi_fun_jac_y_n_out;
+ external_function_param_casadi_create(&capsule->gnsf_phi_fun_jac_y[i], {{ dims.np }});
+ }
+
+ capsule->gnsf_phi_jac_y_uhat = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->gnsf_phi_jac_y_uhat[i].casadi_fun = &{{ model.name }}_gnsf_phi_jac_y_uhat;
+ capsule->gnsf_phi_jac_y_uhat[i].casadi_work = &{{ model.name }}_gnsf_phi_jac_y_uhat_work;
+ capsule->gnsf_phi_jac_y_uhat[i].casadi_sparsity_in = &{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_in;
+ capsule->gnsf_phi_jac_y_uhat[i].casadi_sparsity_out = &{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_out;
+ capsule->gnsf_phi_jac_y_uhat[i].casadi_n_in = &{{ model.name }}_gnsf_phi_jac_y_uhat_n_in;
+ capsule->gnsf_phi_jac_y_uhat[i].casadi_n_out = &{{ model.name }}_gnsf_phi_jac_y_uhat_n_out;
+ external_function_param_casadi_create(&capsule->gnsf_phi_jac_y_uhat[i], {{ dims.np }});
+ }
+
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i].casadi_fun = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz;
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i].casadi_work = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_work;
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i].casadi_sparsity_in = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_in;
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i].casadi_sparsity_out = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_out;
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i].casadi_n_in = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_in;
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i].casadi_n_out = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_out;
+ external_function_param_casadi_create(&capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i], {{ dims.np }});
+ }
+
+ capsule->gnsf_get_matrices_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N; i++) {
+ capsule->gnsf_get_matrices_fun[i].casadi_fun = &{{ model.name }}_gnsf_get_matrices_fun;
+ capsule->gnsf_get_matrices_fun[i].casadi_work = &{{ model.name }}_gnsf_get_matrices_fun_work;
+ capsule->gnsf_get_matrices_fun[i].casadi_sparsity_in = &{{ model.name }}_gnsf_get_matrices_fun_sparsity_in;
+ capsule->gnsf_get_matrices_fun[i].casadi_sparsity_out = &{{ model.name }}_gnsf_get_matrices_fun_sparsity_out;
+ capsule->gnsf_get_matrices_fun[i].casadi_n_in = &{{ model.name }}_gnsf_get_matrices_fun_n_in;
+ capsule->gnsf_get_matrices_fun[i].casadi_n_out = &{{ model.name }}_gnsf_get_matrices_fun_n_out;
+ external_function_param_casadi_create(&capsule->gnsf_get_matrices_fun[i], {{ dims.np }});
+ }
+{% elif solver_options.integrator_type == "DISCRETE" %}
+ // discrete dynamics
+ capsule->discr_dyn_phi_fun = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N);
+ for (int i = 0; i < N; i++)
+ {
+ {%- if model.dyn_ext_fun_type == "casadi" %}
+ capsule->discr_dyn_phi_fun[i].casadi_fun = &{{ model.name }}_dyn_disc_phi_fun;
+ capsule->discr_dyn_phi_fun[i].casadi_n_in = &{{ model.name }}_dyn_disc_phi_fun_n_in;
+ capsule->discr_dyn_phi_fun[i].casadi_n_out = &{{ model.name }}_dyn_disc_phi_fun_n_out;
+ capsule->discr_dyn_phi_fun[i].casadi_sparsity_in = &{{ model.name }}_dyn_disc_phi_fun_sparsity_in;
+ capsule->discr_dyn_phi_fun[i].casadi_sparsity_out = &{{ model.name }}_dyn_disc_phi_fun_sparsity_out;
+ capsule->discr_dyn_phi_fun[i].casadi_work = &{{ model.name }}_dyn_disc_phi_fun_work;
+ {%- else %}
+ capsule->discr_dyn_phi_fun[i].fun = &{{ model.dyn_disc_fun }};
+ {%- endif %}
+ external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->discr_dyn_phi_fun[i], {{ dims.np }});
+ }
+
+ capsule->discr_dyn_phi_fun_jac_ut_xt = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N);
+ for (int i = 0; i < N; i++)
+ {
+ {%- if model.dyn_ext_fun_type == "casadi" %}
+ capsule->discr_dyn_phi_fun_jac_ut_xt[i].casadi_fun = &{{ model.name }}_dyn_disc_phi_fun_jac;
+ capsule->discr_dyn_phi_fun_jac_ut_xt[i].casadi_n_in = &{{ model.name }}_dyn_disc_phi_fun_jac_n_in;
+ capsule->discr_dyn_phi_fun_jac_ut_xt[i].casadi_n_out = &{{ model.name }}_dyn_disc_phi_fun_jac_n_out;
+ capsule->discr_dyn_phi_fun_jac_ut_xt[i].casadi_sparsity_in = &{{ model.name }}_dyn_disc_phi_fun_jac_sparsity_in;
+ capsule->discr_dyn_phi_fun_jac_ut_xt[i].casadi_sparsity_out = &{{ model.name }}_dyn_disc_phi_fun_jac_sparsity_out;
+ capsule->discr_dyn_phi_fun_jac_ut_xt[i].casadi_work = &{{ model.name }}_dyn_disc_phi_fun_jac_work;
+ {%- else %}
+ capsule->discr_dyn_phi_fun_jac_ut_xt[i].fun = &{{ model.dyn_disc_fun_jac }};
+ {%- endif %}
+ external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->discr_dyn_phi_fun_jac_ut_xt[i], {{ dims.np }});
+ }
+
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N);
+ for (int i = 0; i < N; i++)
+ {
+ {%- if model.dyn_ext_fun_type == "casadi" %}
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].casadi_fun = &{{ model.name }}_dyn_disc_phi_fun_jac_hess;
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].casadi_n_in = &{{ model.name }}_dyn_disc_phi_fun_jac_hess_n_in;
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].casadi_n_out = &{{ model.name }}_dyn_disc_phi_fun_jac_hess_n_out;
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].casadi_sparsity_in = &{{ model.name }}_dyn_disc_phi_fun_jac_hess_sparsity_in;
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].casadi_sparsity_out = &{{ model.name }}_dyn_disc_phi_fun_jac_hess_sparsity_out;
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].casadi_work = &{{ model.name }}_dyn_disc_phi_fun_jac_hess_work;
+ {%- else %}
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].fun = &{{ model.dyn_disc_fun_jac_hess }};
+ {%- endif %}
+ external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i], {{ dims.np }});
+ }
+ {%- endif %}
+{%- endif %}
+
+
+{%- if cost.cost_type_0 == "NONLINEAR_LS" %}
+ // nonlinear least square function
+ capsule->cost_y_0_fun.casadi_fun = &{{ model.name }}_cost_y_0_fun;
+ capsule->cost_y_0_fun.casadi_n_in = &{{ model.name }}_cost_y_0_fun_n_in;
+ capsule->cost_y_0_fun.casadi_n_out = &{{ model.name }}_cost_y_0_fun_n_out;
+ capsule->cost_y_0_fun.casadi_sparsity_in = &{{ model.name }}_cost_y_0_fun_sparsity_in;
+ capsule->cost_y_0_fun.casadi_sparsity_out = &{{ model.name }}_cost_y_0_fun_sparsity_out;
+ capsule->cost_y_0_fun.casadi_work = &{{ model.name }}_cost_y_0_fun_work;
+ external_function_param_casadi_create(&capsule->cost_y_0_fun, {{ dims.np }});
+
+ capsule->cost_y_0_fun_jac_ut_xt.casadi_fun = &{{ model.name }}_cost_y_0_fun_jac_ut_xt;
+ capsule->cost_y_0_fun_jac_ut_xt.casadi_n_in = &{{ model.name }}_cost_y_0_fun_jac_ut_xt_n_in;
+ capsule->cost_y_0_fun_jac_ut_xt.casadi_n_out = &{{ model.name }}_cost_y_0_fun_jac_ut_xt_n_out;
+ capsule->cost_y_0_fun_jac_ut_xt.casadi_sparsity_in = &{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_in;
+ capsule->cost_y_0_fun_jac_ut_xt.casadi_sparsity_out = &{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_out;
+ capsule->cost_y_0_fun_jac_ut_xt.casadi_work = &{{ model.name }}_cost_y_0_fun_jac_ut_xt_work;
+ external_function_param_casadi_create(&capsule->cost_y_0_fun_jac_ut_xt, {{ dims.np }});
+
+ capsule->cost_y_0_hess.casadi_fun = &{{ model.name }}_cost_y_0_hess;
+ capsule->cost_y_0_hess.casadi_n_in = &{{ model.name }}_cost_y_0_hess_n_in;
+ capsule->cost_y_0_hess.casadi_n_out = &{{ model.name }}_cost_y_0_hess_n_out;
+ capsule->cost_y_0_hess.casadi_sparsity_in = &{{ model.name }}_cost_y_0_hess_sparsity_in;
+ capsule->cost_y_0_hess.casadi_sparsity_out = &{{ model.name }}_cost_y_0_hess_sparsity_out;
+ capsule->cost_y_0_hess.casadi_work = &{{ model.name }}_cost_y_0_hess_work;
+ external_function_param_casadi_create(&capsule->cost_y_0_hess, {{ dims.np }});
+
+{%- elif cost.cost_type_0 == "EXTERNAL" %}
+ // external cost
+ {% if cost.cost_ext_fun_type_0 == "casadi" %}
+ capsule->ext_cost_0_fun.casadi_fun = &{{ model.name }}_cost_ext_cost_0_fun;
+ capsule->ext_cost_0_fun.casadi_n_in = &{{ model.name }}_cost_ext_cost_0_fun_n_in;
+ capsule->ext_cost_0_fun.casadi_n_out = &{{ model.name }}_cost_ext_cost_0_fun_n_out;
+ capsule->ext_cost_0_fun.casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_0_fun_sparsity_in;
+ capsule->ext_cost_0_fun.casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_0_fun_sparsity_out;
+ capsule->ext_cost_0_fun.casadi_work = &{{ model.name }}_cost_ext_cost_0_fun_work;
+ {% else %}
+ capsule->ext_cost_0_fun.fun = &{{ cost.cost_function_ext_cost_0 }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type_0 }}_create(&capsule->ext_cost_0_fun, {{ dims.np }});
+
+ // external cost
+ {% if cost.cost_ext_fun_type_0 == "casadi" %}
+ capsule->ext_cost_0_fun_jac.casadi_fun = &{{ model.name }}_cost_ext_cost_0_fun_jac;
+ capsule->ext_cost_0_fun_jac.casadi_n_in = &{{ model.name }}_cost_ext_cost_0_fun_jac_n_in;
+ capsule->ext_cost_0_fun_jac.casadi_n_out = &{{ model.name }}_cost_ext_cost_0_fun_jac_n_out;
+ capsule->ext_cost_0_fun_jac.casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_in;
+ capsule->ext_cost_0_fun_jac.casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_out;
+ capsule->ext_cost_0_fun_jac.casadi_work = &{{ model.name }}_cost_ext_cost_0_fun_jac_work;
+ {% else %}
+ capsule->ext_cost_0_fun_jac.fun = &{{ cost.cost_function_ext_cost_0 }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type_0 }}_create(&capsule->ext_cost_0_fun_jac, {{ dims.np }});
+
+ // external cost
+ {% if cost.cost_ext_fun_type_0 == "casadi" %}
+ capsule->ext_cost_0_fun_jac_hess.casadi_fun = &{{ model.name }}_cost_ext_cost_0_fun_jac_hess;
+ capsule->ext_cost_0_fun_jac_hess.casadi_n_in = &{{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_in;
+ capsule->ext_cost_0_fun_jac_hess.casadi_n_out = &{{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_out;
+ capsule->ext_cost_0_fun_jac_hess.casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_in;
+ capsule->ext_cost_0_fun_jac_hess.casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_out;
+ capsule->ext_cost_0_fun_jac_hess.casadi_work = &{{ model.name }}_cost_ext_cost_0_fun_jac_hess_work;
+ {% else %}
+ capsule->ext_cost_0_fun_jac_hess.fun = &{{ cost.cost_function_ext_cost_0 }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type_0 }}_create(&capsule->ext_cost_0_fun_jac_hess, {{ dims.np }});
+{%- endif %}
+
+{%- if cost.cost_type == "NONLINEAR_LS" %}
+ // nonlinear least squares cost
+ capsule->cost_y_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N-1; i++)
+ {
+ capsule->cost_y_fun[i].casadi_fun = &{{ model.name }}_cost_y_fun;
+ capsule->cost_y_fun[i].casadi_n_in = &{{ model.name }}_cost_y_fun_n_in;
+ capsule->cost_y_fun[i].casadi_n_out = &{{ model.name }}_cost_y_fun_n_out;
+ capsule->cost_y_fun[i].casadi_sparsity_in = &{{ model.name }}_cost_y_fun_sparsity_in;
+ capsule->cost_y_fun[i].casadi_sparsity_out = &{{ model.name }}_cost_y_fun_sparsity_out;
+ capsule->cost_y_fun[i].casadi_work = &{{ model.name }}_cost_y_fun_work;
+
+ external_function_param_casadi_create(&capsule->cost_y_fun[i], {{ dims.np }});
+ }
+
+ capsule->cost_y_fun_jac_ut_xt = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N-1; i++)
+ {
+ capsule->cost_y_fun_jac_ut_xt[i].casadi_fun = &{{ model.name }}_cost_y_fun_jac_ut_xt;
+ capsule->cost_y_fun_jac_ut_xt[i].casadi_n_in = &{{ model.name }}_cost_y_fun_jac_ut_xt_n_in;
+ capsule->cost_y_fun_jac_ut_xt[i].casadi_n_out = &{{ model.name }}_cost_y_fun_jac_ut_xt_n_out;
+ capsule->cost_y_fun_jac_ut_xt[i].casadi_sparsity_in = &{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_in;
+ capsule->cost_y_fun_jac_ut_xt[i].casadi_sparsity_out = &{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_out;
+ capsule->cost_y_fun_jac_ut_xt[i].casadi_work = &{{ model.name }}_cost_y_fun_jac_ut_xt_work;
+
+ external_function_param_casadi_create(&capsule->cost_y_fun_jac_ut_xt[i], {{ dims.np }});
+ }
+
+ capsule->cost_y_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N);
+ for (int i = 0; i < N-1; i++)
+ {
+ capsule->cost_y_hess[i].casadi_fun = &{{ model.name }}_cost_y_hess;
+ capsule->cost_y_hess[i].casadi_n_in = &{{ model.name }}_cost_y_hess_n_in;
+ capsule->cost_y_hess[i].casadi_n_out = &{{ model.name }}_cost_y_hess_n_out;
+ capsule->cost_y_hess[i].casadi_sparsity_in = &{{ model.name }}_cost_y_hess_sparsity_in;
+ capsule->cost_y_hess[i].casadi_sparsity_out = &{{ model.name }}_cost_y_hess_sparsity_out;
+ capsule->cost_y_hess[i].casadi_work = &{{ model.name }}_cost_y_hess_work;
+
+ external_function_param_casadi_create(&capsule->cost_y_hess[i], {{ dims.np }});
+ }
+{%- elif cost.cost_type == "EXTERNAL" %}
+ // external cost
+ capsule->ext_cost_fun = (external_function_param_{{ cost.cost_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ cost.cost_ext_fun_type }})*N);
+ for (int i = 0; i < N-1; i++)
+ {
+ {% if cost.cost_ext_fun_type == "casadi" %}
+ capsule->ext_cost_fun[i].casadi_fun = &{{ model.name }}_cost_ext_cost_fun;
+ capsule->ext_cost_fun[i].casadi_n_in = &{{ model.name }}_cost_ext_cost_fun_n_in;
+ capsule->ext_cost_fun[i].casadi_n_out = &{{ model.name }}_cost_ext_cost_fun_n_out;
+ capsule->ext_cost_fun[i].casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_fun_sparsity_in;
+ capsule->ext_cost_fun[i].casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_fun_sparsity_out;
+ capsule->ext_cost_fun[i].casadi_work = &{{ model.name }}_cost_ext_cost_fun_work;
+ {% else %}
+ capsule->ext_cost_fun[i].fun = &{{ cost.cost_function_ext_cost }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type }}_create(&capsule->ext_cost_fun[i], {{ dims.np }});
+ }
+
+ capsule->ext_cost_fun_jac = (external_function_param_{{ cost.cost_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ cost.cost_ext_fun_type }})*N);
+ for (int i = 0; i < N-1; i++)
+ {
+ {% if cost.cost_ext_fun_type == "casadi" %}
+ capsule->ext_cost_fun_jac[i].casadi_fun = &{{ model.name }}_cost_ext_cost_fun_jac;
+ capsule->ext_cost_fun_jac[i].casadi_n_in = &{{ model.name }}_cost_ext_cost_fun_jac_n_in;
+ capsule->ext_cost_fun_jac[i].casadi_n_out = &{{ model.name }}_cost_ext_cost_fun_jac_n_out;
+ capsule->ext_cost_fun_jac[i].casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_fun_jac_sparsity_in;
+ capsule->ext_cost_fun_jac[i].casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_fun_jac_sparsity_out;
+ capsule->ext_cost_fun_jac[i].casadi_work = &{{ model.name }}_cost_ext_cost_fun_jac_work;
+ {% else %}
+ capsule->ext_cost_fun_jac[i].fun = &{{ cost.cost_function_ext_cost }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type }}_create(&capsule->ext_cost_fun_jac[i], {{ dims.np }});
+ }
+
+ capsule->ext_cost_fun_jac_hess = (external_function_param_{{ cost.cost_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ cost.cost_ext_fun_type }})*N);
+ for (int i = 0; i < N-1; i++)
+ {
+ {% if cost.cost_ext_fun_type == "casadi" %}
+ capsule->ext_cost_fun_jac_hess[i].casadi_fun = &{{ model.name }}_cost_ext_cost_fun_jac_hess;
+ capsule->ext_cost_fun_jac_hess[i].casadi_n_in = &{{ model.name }}_cost_ext_cost_fun_jac_hess_n_in;
+ capsule->ext_cost_fun_jac_hess[i].casadi_n_out = &{{ model.name }}_cost_ext_cost_fun_jac_hess_n_out;
+ capsule->ext_cost_fun_jac_hess[i].casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_in;
+ capsule->ext_cost_fun_jac_hess[i].casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_out;
+ capsule->ext_cost_fun_jac_hess[i].casadi_work = &{{ model.name }}_cost_ext_cost_fun_jac_hess_work;
+ {% else %}
+ capsule->ext_cost_fun_jac_hess[i].fun = &{{ cost.cost_function_ext_cost }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type }}_create(&capsule->ext_cost_fun_jac_hess[i], {{ dims.np }});
+ }
+{%- endif %}
+
+{%- if cost.cost_type_e == "NONLINEAR_LS" %}
+ // nonlinear least square function
+ capsule->cost_y_e_fun.casadi_fun = &{{ model.name }}_cost_y_e_fun;
+ capsule->cost_y_e_fun.casadi_n_in = &{{ model.name }}_cost_y_e_fun_n_in;
+ capsule->cost_y_e_fun.casadi_n_out = &{{ model.name }}_cost_y_e_fun_n_out;
+ capsule->cost_y_e_fun.casadi_sparsity_in = &{{ model.name }}_cost_y_e_fun_sparsity_in;
+ capsule->cost_y_e_fun.casadi_sparsity_out = &{{ model.name }}_cost_y_e_fun_sparsity_out;
+ capsule->cost_y_e_fun.casadi_work = &{{ model.name }}_cost_y_e_fun_work;
+ external_function_param_casadi_create(&capsule->cost_y_e_fun, {{ dims.np }});
+
+ capsule->cost_y_e_fun_jac_ut_xt.casadi_fun = &{{ model.name }}_cost_y_e_fun_jac_ut_xt;
+ capsule->cost_y_e_fun_jac_ut_xt.casadi_n_in = &{{ model.name }}_cost_y_e_fun_jac_ut_xt_n_in;
+ capsule->cost_y_e_fun_jac_ut_xt.casadi_n_out = &{{ model.name }}_cost_y_e_fun_jac_ut_xt_n_out;
+ capsule->cost_y_e_fun_jac_ut_xt.casadi_sparsity_in = &{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_in;
+ capsule->cost_y_e_fun_jac_ut_xt.casadi_sparsity_out = &{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_out;
+ capsule->cost_y_e_fun_jac_ut_xt.casadi_work = &{{ model.name }}_cost_y_e_fun_jac_ut_xt_work;
+ external_function_param_casadi_create(&capsule->cost_y_e_fun_jac_ut_xt, {{ dims.np }});
+
+ capsule->cost_y_e_hess.casadi_fun = &{{ model.name }}_cost_y_e_hess;
+ capsule->cost_y_e_hess.casadi_n_in = &{{ model.name }}_cost_y_e_hess_n_in;
+ capsule->cost_y_e_hess.casadi_n_out = &{{ model.name }}_cost_y_e_hess_n_out;
+ capsule->cost_y_e_hess.casadi_sparsity_in = &{{ model.name }}_cost_y_e_hess_sparsity_in;
+ capsule->cost_y_e_hess.casadi_sparsity_out = &{{ model.name }}_cost_y_e_hess_sparsity_out;
+ capsule->cost_y_e_hess.casadi_work = &{{ model.name }}_cost_y_e_hess_work;
+ external_function_param_casadi_create(&capsule->cost_y_e_hess, {{ dims.np }});
+
+{%- elif cost.cost_type_e == "EXTERNAL" %}
+ // external cost
+ {% if cost.cost_ext_fun_type_e == "casadi" %}
+ capsule->ext_cost_e_fun.casadi_fun = &{{ model.name }}_cost_ext_cost_e_fun;
+ capsule->ext_cost_e_fun.casadi_n_in = &{{ model.name }}_cost_ext_cost_e_fun_n_in;
+ capsule->ext_cost_e_fun.casadi_n_out = &{{ model.name }}_cost_ext_cost_e_fun_n_out;
+ capsule->ext_cost_e_fun.casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_e_fun_sparsity_in;
+ capsule->ext_cost_e_fun.casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_e_fun_sparsity_out;
+ capsule->ext_cost_e_fun.casadi_work = &{{ model.name }}_cost_ext_cost_e_fun_work;
+ {% else %}
+ capsule->ext_cost_e_fun.fun = &{{ cost.cost_function_ext_cost_e }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type_e }}_create(&capsule->ext_cost_e_fun, {{ dims.np }});
+
+ // external cost
+ {% if cost.cost_ext_fun_type_e == "casadi" %}
+ capsule->ext_cost_e_fun_jac.casadi_fun = &{{ model.name }}_cost_ext_cost_e_fun_jac;
+ capsule->ext_cost_e_fun_jac.casadi_n_in = &{{ model.name }}_cost_ext_cost_e_fun_jac_n_in;
+ capsule->ext_cost_e_fun_jac.casadi_n_out = &{{ model.name }}_cost_ext_cost_e_fun_jac_n_out;
+ capsule->ext_cost_e_fun_jac.casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_in;
+ capsule->ext_cost_e_fun_jac.casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_out;
+ capsule->ext_cost_e_fun_jac.casadi_work = &{{ model.name }}_cost_ext_cost_e_fun_jac_work;
+ {% else %}
+ capsule->ext_cost_e_fun_jac.fun = &{{ cost.cost_function_ext_cost_e }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type_e }}_create(&capsule->ext_cost_e_fun_jac, {{ dims.np }});
+
+ // external cost
+ {% if cost.cost_ext_fun_type_e == "casadi" %}
+ capsule->ext_cost_e_fun_jac_hess.casadi_fun = &{{ model.name }}_cost_ext_cost_e_fun_jac_hess;
+ capsule->ext_cost_e_fun_jac_hess.casadi_n_in = &{{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_in;
+ capsule->ext_cost_e_fun_jac_hess.casadi_n_out = &{{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_out;
+ capsule->ext_cost_e_fun_jac_hess.casadi_sparsity_in = &{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_in;
+ capsule->ext_cost_e_fun_jac_hess.casadi_sparsity_out = &{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_out;
+ capsule->ext_cost_e_fun_jac_hess.casadi_work = &{{ model.name }}_cost_ext_cost_e_fun_jac_hess_work;
+ {% else %}
+ capsule->ext_cost_e_fun_jac_hess.fun = &{{ cost.cost_function_ext_cost_e }};
+ {% endif %}
+ external_function_param_{{ cost.cost_ext_fun_type_e }}_create(&capsule->ext_cost_e_fun_jac_hess, {{ dims.np }});
+{%- endif %}
+
+ /************************************************
+ * nlp_in
+ ************************************************/
+ ocp_nlp_in * nlp_in = ocp_nlp_in_create(nlp_config, nlp_dims);
+ capsule->nlp_in = nlp_in;
+
+ // set up time_steps
+ {% set all_equal = true -%}
+ {%- set val = solver_options.time_steps[0] %}
+ {%- for j in range(start=1, end=dims.N) %}
+ {%- if val != solver_options.time_steps[j] %}
+ {%- set_global all_equal = false %}
+ {%- break %}
+ {%- endif %}
+ {%- endfor %}
+
+ {%- if all_equal == true -%}
+ // all time_steps are identical
+ double time_step = {{ solver_options.time_steps[0] }};
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_in_set(nlp_config, nlp_dims, nlp_in, i, "Ts", &time_step);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "scaling", &time_step);
+ }
+ {%- else -%}
+ // time_steps are different
+ double* time_steps = malloc(N*sizeof(double));
+ {%- for j in range(end=dims.N) %}
+ time_steps[{{ j }}] = {{ solver_options.time_steps[j] }};
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_in_set(nlp_config, nlp_dims, nlp_in, i, "Ts", &time_steps[i]);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "scaling", &time_steps[i]);
+ }
+ free(time_steps);
+ {%- endif %}
+
+ /**** Dynamics ****/
+ for (int i = 0; i < N; i++)
+ {
+ {%- if solver_options.integrator_type == "ERK" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "expl_vde_forw", &capsule->forw_vde_casadi[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "expl_ode_fun", &capsule->expl_ode_fun[i]);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "expl_ode_hess", &capsule->hess_vde_casadi[i]);
+ {%- endif %}
+ {% elif solver_options.integrator_type == "IRK" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "impl_dae_fun", &capsule->impl_dae_fun[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i,
+ "impl_dae_fun_jac_x_xdot_z", &capsule->impl_dae_fun_jac_x_xdot_z[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i,
+ "impl_dae_jac_x_xdot_u", &capsule->impl_dae_jac_x_xdot_u_z[i]);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "impl_dae_hess", &capsule->impl_dae_hess[i]);
+ {%- endif %}
+ {% elif solver_options.integrator_type == "LIFTED_IRK" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "impl_dae_fun", &capsule->impl_dae_fun[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i,
+ "impl_dae_fun_jac_x_xdot_u", &capsule->impl_dae_fun_jac_x_xdot_u[i]);
+ {% elif solver_options.integrator_type == "GNSF" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "phi_fun", &capsule->gnsf_phi_fun[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "phi_fun_jac_y", &capsule->gnsf_phi_fun_jac_y[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "phi_jac_y_uhat", &capsule->gnsf_phi_jac_y_uhat[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "f_lo_jac_x1_x1dot_u_z",
+ &capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "gnsf_get_matrices_fun",
+ &capsule->gnsf_get_matrices_fun[i]);
+ {% elif solver_options.integrator_type == "DISCRETE" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "disc_dyn_fun", &capsule->discr_dyn_phi_fun[i]);
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "disc_dyn_fun_jac",
+ &capsule->discr_dyn_phi_fun_jac_ut_xt[i]);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "disc_dyn_fun_jac_hess",
+ &capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i]);
+ {%- endif %}
+ {%- endif %}
+ }
+
+
+ /**** Cost ****/
+{%- if cost.cost_type_0 == "NONLINEAR_LS" or cost.cost_type_0 == "LINEAR_LS" %}
+{% if dims.ny_0 > 0 %}
+ double* W_0 = calloc(NY0*NY0, sizeof(double));
+ // change only the non-zero elements:
+ {%- for j in range(end=dims.ny_0) %}
+ {%- for k in range(end=dims.ny_0) %}
+ {%- if cost.W_0[j][k] != 0 %}
+ W_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.W_0[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "W", W_0);
+ free(W_0);
+
+ double* yref_0 = calloc(NY0, sizeof(double));
+ // change only the non-zero elements:
+ {%- for j in range(end=dims.ny_0) %}
+ {%- if cost.yref_0[j] != 0 %}
+ yref_0[{{ j }}] = {{ cost.yref_0[j] }};
+ {%- endif %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "yref", yref_0);
+ free(yref_0);
+{% endif %}
+{% endif %}
+
+{%- if cost.cost_type == "NONLINEAR_LS" or cost.cost_type == "LINEAR_LS" %}
+{% if dims.ny > 0 %}
+ double* W = calloc(NY*NY, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny) %}
+ {%- for k in range(end=dims.ny) %}
+ {%- if cost.W[j][k] != 0 %}
+ W[{{ j }}+(NY) * {{ k }}] = {{ cost.W[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+
+ double* yref = calloc(NY, sizeof(double));
+ // change only the non-zero elements:
+ {%- for j in range(end=dims.ny) %}
+ {%- if cost.yref[j] != 0 %}
+ yref[{{ j }}] = {{ cost.yref[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "W", W);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "yref", yref);
+ }
+ free(W);
+ free(yref);
+{% endif %}
+{% endif %}
+
+{%- if cost.cost_type_0 == "LINEAR_LS" %}
+ double* Vx_0 = calloc(NY0*NX, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny_0) %}
+ {%- for k in range(end=dims.nx) %}
+ {%- if cost.Vx_0[j][k] != 0 %}
+ Vx_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.Vx_0[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "Vx", Vx_0);
+ free(Vx_0);
+
+{% if dims.ny_0 > 0 and dims.nu > 0 %}
+ double* Vu_0 = calloc(NY0*NU, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny_0) %}
+ {%- for k in range(end=dims.nu) %}
+ {%- if cost.Vu_0[j][k] != 0 %}
+ Vu_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.Vu_0[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "Vu", Vu_0);
+ free(Vu_0);
+{% endif %}
+{% if dims.ny_0 > 0 and dims.nz > 0 %}
+ double* Vz_0 = calloc(NY0*NZ, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny_0) %}
+ {%- for k in range(end=dims.nz) %}
+ {%- if cost.Vz_0[j][k] != 0 %}
+ Vz_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.Vz_0[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "Vz", Vz_0);
+ free(Vz_0);
+{%- endif %}
+{%- endif %}{# LINEAR LS #}
+
+
+{%- if cost.cost_type == "LINEAR_LS" %}
+ double* Vx = calloc(NY*NX, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny) %}
+ {%- for k in range(end=dims.nx) %}
+ {%- if cost.Vx[j][k] != 0 %}
+ Vx[{{ j }}+(NY) * {{ k }}] = {{ cost.Vx[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Vx", Vx);
+ }
+ free(Vx);
+
+{% if dims.ny > 0 and dims.nu > 0 %}
+ double* Vu = calloc(NY*NU, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny) %}
+ {%- for k in range(end=dims.nu) %}
+ {%- if cost.Vu[j][k] != 0 %}
+ Vu[{{ j }}+(NY) * {{ k }}] = {{ cost.Vu[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Vu", Vu);
+ }
+ free(Vu);
+{% endif %}
+
+{% if dims.ny > 0 and dims.nz > 0 %}
+ double* Vz = calloc(NY*NZ, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny) %}
+ {%- for k in range(end=dims.nz) %}
+ {%- if cost.Vz[j][k] != 0 %}
+ Vz[{{ j }}+(NY) * {{ k }}] = {{ cost.Vz[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Vz", Vz);
+ }
+ free(Vz);
+{%- endif %}
+{%- endif %}{# LINEAR LS #}
+
+
+{%- if cost.cost_type_0 == "NONLINEAR_LS" %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "nls_y_fun", &capsule->cost_y_0_fun);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "nls_y_fun_jac", &capsule->cost_y_0_fun_jac_ut_xt);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "nls_y_hess", &capsule->cost_y_0_hess);
+{%- elif cost.cost_type_0 == "EXTERNAL" %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "ext_cost_fun", &capsule->ext_cost_0_fun);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "ext_cost_fun_jac", &capsule->ext_cost_0_fun_jac);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "ext_cost_fun_jac_hess", &capsule->ext_cost_0_fun_jac_hess);
+{%- endif %}
+
+{%- if cost.cost_type == "NONLINEAR_LS" %}
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "nls_y_fun", &capsule->cost_y_fun[i-1]);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "nls_y_fun_jac", &capsule->cost_y_fun_jac_ut_xt[i-1]);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "nls_y_hess", &capsule->cost_y_hess[i-1]);
+ }
+{%- elif cost.cost_type == "EXTERNAL" %}
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "ext_cost_fun", &capsule->ext_cost_fun[i-1]);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "ext_cost_fun_jac", &capsule->ext_cost_fun_jac[i-1]);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "ext_cost_fun_jac_hess", &capsule->ext_cost_fun_jac_hess[i-1]);
+ }
+{%- endif %}
+
+
+{% if dims.ns > 0 %}
+ double* zlumem = calloc(4*NS, sizeof(double));
+ double* Zl = zlumem+NS*0;
+ double* Zu = zlumem+NS*1;
+ double* zl = zlumem+NS*2;
+ double* zu = zlumem+NS*3;
+ // change only the non-zero elements:
+ {%- for j in range(end=dims.ns) %}
+ {%- if cost.Zl[j] != 0 %}
+ Zl[{{ j }}] = {{ cost.Zl[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {%- for j in range(end=dims.ns) %}
+ {%- if cost.Zu[j] != 0 %}
+ Zu[{{ j }}] = {{ cost.Zu[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {%- for j in range(end=dims.ns) %}
+ {%- if cost.zl[j] != 0 %}
+ zl[{{ j }}] = {{ cost.zl[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {%- for j in range(end=dims.ns) %}
+ {%- if cost.zu[j] != 0 %}
+ zu[{{ j }}] = {{ cost.zu[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Zl", Zl);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Zu", Zu);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "zl", zl);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "zu", zu);
+ }
+ free(zlumem);
+{% endif %}
+
+ // terminal cost
+{% if cost.cost_type_e == "LINEAR_LS" or cost.cost_type_e == "NONLINEAR_LS" %}
+{% if dims.ny_e > 0 %}
+ double* yref_e = calloc(NYN, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny_e) %}
+ {%- if cost.yref_e[j] != 0 %}
+ yref_e[{{ j }}] = {{ cost.yref_e[j] }};
+ {%- endif %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "yref", yref_e);
+ free(yref_e);
+
+ double* W_e = calloc(NYN*NYN, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny_e) %}
+ {%- for k in range(end=dims.ny_e) %}
+ {%- if cost.W_e[j][k] != 0 %}
+ W_e[{{ j }}+(NYN) * {{ k }}] = {{ cost.W_e[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "W", W_e);
+ free(W_e);
+
+ {%- if cost.cost_type_e == "LINEAR_LS" %}
+ double* Vx_e = calloc(NYN*NX, sizeof(double));
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ny_e) %}
+ {%- for k in range(end=dims.nx) %}
+ {%- if cost.Vx_e[j][k] != 0 %}
+ Vx_e[{{ j }}+(NYN) * {{ k }}] = {{ cost.Vx_e[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "Vx", Vx_e);
+ free(Vx_e);
+ {%- endif %}
+
+ {%- if cost.cost_type_e == "NONLINEAR_LS" %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "nls_y_fun", &capsule->cost_y_e_fun);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "nls_y_fun_jac", &capsule->cost_y_e_fun_jac_ut_xt);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "nls_y_hess", &capsule->cost_y_e_hess);
+ {%- endif %}
+{%- endif %}{# ny_e > 0 #}
+
+{%- elif cost.cost_type_e == "EXTERNAL" %}
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "ext_cost_fun", &capsule->ext_cost_e_fun);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "ext_cost_fun_jac", &capsule->ext_cost_e_fun_jac);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "ext_cost_fun_jac_hess", &capsule->ext_cost_e_fun_jac_hess);
+{%- endif %}
+
+{% if dims.ns_e > 0 %}
+ double* zluemem = calloc(4*NSN, sizeof(double));
+ double* Zl_e = zluemem+NSN*0;
+ double* Zu_e = zluemem+NSN*1;
+ double* zl_e = zluemem+NSN*2;
+ double* zu_e = zluemem+NSN*3;
+
+ // change only the non-zero elements:
+ {% for j in range(end=dims.ns_e) %}
+ {%- if cost.Zl_e[j] != 0 %}
+ Zl_e[{{ j }}] = {{ cost.Zl_e[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {% for j in range(end=dims.ns_e) %}
+ {%- if cost.Zu_e[j] != 0 %}
+ Zu_e[{{ j }}] = {{ cost.Zu_e[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {% for j in range(end=dims.ns_e) %}
+ {%- if cost.zl_e[j] != 0 %}
+ zl_e[{{ j }}] = {{ cost.zl_e[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {% for j in range(end=dims.ns_e) %}
+ {%- if cost.zu_e[j] != 0 %}
+ zu_e[{{ j }}] = {{ cost.zu_e[j] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "Zl", Zl_e);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "Zu", Zu_e);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "zl", zl_e);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "zu", zu_e);
+ free(zluemem);
+{%- endif %}
+
+ /**** Constraints ****/
+
+ // bounds for initial stage
+{% if dims.nbx_0 > 0 %}
+ // x0
+ int* idxbx0 = malloc(NBX0 * sizeof(int));
+ {%- for i in range(end=dims.nbx_0) %}
+ idxbx0[{{ i }}] = {{ constraints.idxbx_0[i] }};
+ {%- endfor %}
+
+ double* lubx0 = calloc(2*NBX0, sizeof(double));
+ double* lbx0 = lubx0;
+ double* ubx0 = lubx0 + NBX0;
+ // change only the non-zero elements:
+ {%- for i in range(end=dims.nbx_0) %}
+ {%- if constraints.lbx_0[i] != 0 %}
+ lbx0[{{ i }}] = {{ constraints.lbx_0[i] }};
+ {%- endif %}
+ {%- if constraints.ubx_0[i] != 0 %}
+ ubx0[{{ i }}] = {{ constraints.ubx_0[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxbx", idxbx0);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbx", lbx0);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubx", ubx0);
+ free(idxbx0);
+ free(lubx0);
+{% endif %}
+{% if dims.nbxe_0 > 0 %}
+ // idxbxe_0
+ int* idxbxe_0 = malloc({{ dims.nbxe_0 }} * sizeof(int));
+ {% for i in range(end=dims.nbxe_0) %}
+ idxbxe_0[{{ i }}] = {{ constraints.idxbxe_0[i] }};
+ {%- endfor %}
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxbxe", idxbxe_0);
+ free(idxbxe_0);
+{% endif %}
+
+ /* constraints that are the same for initial and intermediate */
+{%- if dims.nsbx > 0 %}
+{# TODO: introduce nsbx0 & move this block down!! #}
+ // ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxsbx", idxsbx);
+ // ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lsbx", lsbx);
+ // ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "usbx", usbx);
+
+ // soft bounds on x
+ int* idxsbx = malloc(NSBX * sizeof(int));
+ {% for i in range(end=dims.nsbx) %}
+ idxsbx[{{ i }}] = {{ constraints.idxsbx[i] }};
+ {%- endfor %}
+
+ double* lusbx = calloc(2*NSBX, sizeof(double));
+ double* lsbx = lusbx;
+ double* usbx = lusbx + NSBX;
+ {% for i in range(end=dims.nsbx) %}
+ {%- if constraints.lsbx[i] != 0 %}
+ lsbx[{{ i }}] = {{ constraints.lsbx[i] }};
+ {%- endif %}
+ {%- if constraints.usbx[i] != 0 %}
+ usbx[{{ i }}] = {{ constraints.usbx[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsbx", idxsbx);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsbx", lsbx);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usbx", usbx);
+ }
+ free(idxsbx);
+ free(lusbx);
+{%- endif %}
+
+
+{% if dims.nbu > 0 %}
+ // u
+ int* idxbu = malloc(NBU * sizeof(int));
+ {% for i in range(end=dims.nbu) %}
+ idxbu[{{ i }}] = {{ constraints.idxbu[i] }};
+ {%- endfor %}
+ double* lubu = calloc(2*NBU, sizeof(double));
+ double* lbu = lubu;
+ double* ubu = lubu + NBU;
+ {% for i in range(end=dims.nbu) %}
+ {%- if constraints.lbu[i] != 0 %}
+ lbu[{{ i }}] = {{ constraints.lbu[i] }};
+ {%- endif %}
+ {%- if constraints.ubu[i] != 0 %}
+ ubu[{{ i }}] = {{ constraints.ubu[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxbu", idxbu);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lbu", lbu);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ubu", ubu);
+ }
+ free(idxbu);
+ free(lubu);
+{% endif %}
+
+{% if dims.nsbu > 0 %}
+ // set up soft bounds for u
+ int* idxsbu = malloc(NSBU * sizeof(int));
+ {% for i in range(end=dims.nsbu) %}
+ idxsbu[{{ i }}] = {{ constraints.idxsbu[i] }};
+ {%- endfor %}
+ double* lusbu = calloc(2*NSBU, sizeof(double));
+ double* lsbu = lusbu;
+ double* usbu = lusbu + NSBU;
+ {% for i in range(end=dims.nsbu) %}
+ {%- if constraints.lsbu[i] != 0 %}
+ lsbu[{{ i }}] = {{ constraints.lsbu[i] }};
+ {%- endif %}
+ {%- if constraints.usbu[i] != 0 %}
+ usbu[{{ i }}] = {{ constraints.usbu[i] }};
+ {%- endif %}
+ {%- endfor %}
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsbu", idxsbu);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsbu", lsbu);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usbu", usbu);
+ }
+ free(idxsbu);
+ free(lusbu);
+{% endif %}
+
+{% if dims.nsg > 0 %}
+ // set up soft bounds for general linear constraints
+ int* idxsg = malloc(NSG * sizeof(int));
+ {% for i in range(end=dims.nsg) %}
+ idxsg[{{ i }}] = {{ constraints.idxsg[i] }};
+ {%- endfor %}
+ double* lusg = calloc(2*NSG, sizeof(double));
+ double* lsg = lusg;
+ double* usg = lusg + NSG;
+ {% for i in range(end=dims.nsg) %}
+ {%- if constraints.lsg[i] != 0 %}
+ lsg[{{ i }}] = {{ constraints.lsg[i] }};
+ {%- endif %}
+ {%- if constraints.usg[i] != 0 %}
+ usg[{{ i }}] = {{ constraints.usg[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsg", idxsg);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsg", lsg);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usg", usg);
+ }
+ free(idxsg);
+ free(lusg);
+{% endif %}
+
+{% if dims.nsh > 0 %}
+ // set up soft bounds for nonlinear constraints
+ int* idxsh = malloc(NSH * sizeof(int));
+ {% for i in range(end=dims.nsh) %}
+ idxsh[{{ i }}] = {{ constraints.idxsh[i] }};
+ {%- endfor %}
+ double* lush = calloc(2*NSH, sizeof(double));
+ double* lsh = lush;
+ double* ush = lush + NSH;
+ {% for i in range(end=dims.nsh) %}
+ {%- if constraints.lsh[i] != 0 %}
+ lsh[{{ i }}] = {{ constraints.lsh[i] }};
+ {%- endif %}
+ {%- if constraints.ush[i] != 0 %}
+ ush[{{ i }}] = {{ constraints.ush[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsh", idxsh);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsh", lsh);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ush", ush);
+ }
+ free(idxsh);
+ free(lush);
+{% endif %}
+
+{% if dims.nsphi > 0 %}
+ // set up soft bounds for convex-over-nonlinear constraints
+ int* idxsphi = malloc(NSPHI * sizeof(int));
+ {% for i in range(end=dims.nsphi) %}
+ idxsphi[{{ i }}] = {{ constraints.idxsphi[i] }};
+ {%- endfor %}
+ double* lusphi = calloc(2*NSPHI, sizeof(double));
+ double* lsphi = lusphi;
+ double* usphi = lusphi + NSPHI;
+ {% for i in range(end=dims.nsphi) %}
+ {%- if constraints.lsphi[i] != 0 %}
+ lsphi[{{ i }}] = {{ constraints.lsphi[i] }};
+ {%- endif %}
+ {%- if constraints.usphi[i] != 0 %}
+ usphi[{{ i }}] = {{ constraints.usphi[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsphi", idxsphi);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsphi", lsphi);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usphi", usphi);
+ }
+ free(idxsphi);
+ free(lusphi);
+{% endif %}
+
+{% if dims.nbx > 0 %}
+ // x
+ int* idxbx = malloc(NBX * sizeof(int));
+ {% for i in range(end=dims.nbx) %}
+ idxbx[{{ i }}] = {{ constraints.idxbx[i] }};
+ {%- endfor %}
+ double* lubx = calloc(2*NBX, sizeof(double));
+ double* lbx = lubx;
+ double* ubx = lubx + NBX;
+ {% for i in range(end=dims.nbx) %}
+ {%- if constraints.lbx[i] != 0 %}
+ lbx[{{ i }}] = {{ constraints.lbx[i] }};
+ {%- endif %}
+ {%- if constraints.ubx[i] != 0 %}
+ ubx[{{ i }}] = {{ constraints.ubx[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 1; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxbx", idxbx);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lbx", lbx);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ubx", ubx);
+ }
+ free(idxbx);
+ free(lubx);
+{% endif %}
+
+{% if dims.ng > 0 %}
+ // set up general constraints for stage 0 to N-1
+ double* D = calloc(NG*NU, sizeof(double));
+ double* C = calloc(NG*NX, sizeof(double));
+ double* lug = calloc(2*NG, sizeof(double));
+ double* lg = lug;
+ double* ug = lug + NG;
+
+ {% for j in range(end=dims.ng) -%}
+ {% for k in range(end=dims.nu) %}
+ {%- if constraints.D[j][k] != 0 %}
+ D[{{ j }}+NG * {{ k }}] = {{ constraints.D[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+
+ {% for j in range(end=dims.ng) -%}
+ {% for k in range(end=dims.nx) %}
+ {%- if constraints.C[j][k] != 0 %}
+ C[{{ j }}+NG * {{ k }}] = {{ constraints.C[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+
+ {% for i in range(end=dims.ng) %}
+ {%- if constraints.lg[i] != 0 %}
+ lg[{{ i }}] = {{ constraints.lg[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {% for i in range(end=dims.ng) %}
+ {%- if constraints.ug[i] != 0 %}
+ ug[{{ i }}] = {{ constraints.ug[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "D", D);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "C", C);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lg", lg);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ug", ug);
+ }
+ free(D);
+ free(C);
+ free(lug);
+{% endif %}
+
+{% if dims.nh > 0 %}
+ // set up nonlinear constraints for stage 0 to N-1
+ double* luh = calloc(2*NH, sizeof(double));
+ double* lh = luh;
+ double* uh = luh + NH;
+
+ {% for i in range(end=dims.nh) %}
+ {%- if constraints.lh[i] != 0 %}
+ lh[{{ i }}] = {{ constraints.lh[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {% for i in range(end=dims.nh) %}
+ {%- if constraints.uh[i] != 0 %}
+ uh[{{ i }}] = {{ constraints.uh[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ // nonlinear constraints for stages 0 to N-1
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "nl_constr_h_fun_jac",
+ &capsule->nl_constr_h_fun_jac[i]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "nl_constr_h_fun",
+ &capsule->nl_constr_h_fun[i]);
+ {% if solver_options.hessian_approx == "EXACT" %}
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i,
+ "nl_constr_h_fun_jac_hess", &capsule->nl_constr_h_fun_jac_hess[i]);
+ {% endif %}
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lh", lh);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "uh", uh);
+ }
+ free(luh);
+{% endif %}
+
+{% if dims.nphi > 0 and constraints.constr_type == "BGP" %}
+ // set up convex-over-nonlinear constraints for stage 0 to N-1
+ double* luphi = calloc(2*NPHI, sizeof(double));
+ double* lphi = luphi;
+ double* uphi = luphi + NPHI;
+ {% for i in range(end=dims.nphi) %}
+ {%- if constraints.lphi[i] != 0 %}
+ lphi[{{ i }}] = {{ constraints.lphi[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {% for i in range(end=dims.nphi) %}
+ {%- if constraints.uphi[i] != 0 %}
+ uphi[{{ i }}] = {{ constraints.uphi[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i,
+ "nl_constr_phi_o_r_fun_phi_jac_ux_z_phi_hess_r_jac_ux", &capsule->phi_constraint[i]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lphi", lphi);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "uphi", uphi);
+ }
+ free(luphi);
+{% endif %}
+
+ /* terminal constraints */
+{% if dims.nbx_e > 0 %}
+ // set up bounds for last stage
+ // x
+ int* idxbx_e = malloc(NBXN * sizeof(int));
+ {% for i in range(end=dims.nbx_e) %}
+ idxbx_e[{{ i }}] = {{ constraints.idxbx_e[i] }};
+ {%- endfor %}
+ double* lubx_e = calloc(2*NBXN, sizeof(double));
+ double* lbx_e = lubx_e;
+ double* ubx_e = lubx_e + NBXN;
+ {% for i in range(end=dims.nbx_e) %}
+ {%- if constraints.lbx_e[i] != 0 %}
+ lbx_e[{{ i }}] = {{ constraints.lbx_e[i] }};
+ {%- endif %}
+ {%- if constraints.ubx_e[i] != 0 %}
+ ubx_e[{{ i }}] = {{ constraints.ubx_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxbx", idxbx_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lbx", lbx_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ubx", ubx_e);
+ free(idxbx_e);
+ free(lubx_e);
+{%- endif %}
+
+{% if dims.nsg_e > 0 %}
+ // set up soft bounds for general linear constraints
+ int* idxsg_e = calloc(NSGN, sizeof(int));
+ {% for i in range(end=dims.nsg_e) %}
+ idxsg_e[{{ i }}] = {{ constraints.idxsg_e[i] }};
+ {%- endfor %}
+ double* lusg_e = calloc(2*NSGN, sizeof(double));
+ double* lsg_e = lusg_e;
+ double* usg_e = lusg_e + NSGN;
+ {% for i in range(end=dims.nsg_e) %}
+ {%- if constraints.lsg_e[i] != 0 %}
+ lsg_e[{{ i }}] = {{ constraints.lsg_e[i] }};
+ {%- endif %}
+ {%- if constraints.usg_e[i] != 0 %}
+ usg_e[{{ i }}] = {{ constraints.usg_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsg", idxsg_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsg", lsg_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "usg", usg_e);
+ free(idxsg_e);
+ free(lusg_e);
+{%- endif %}
+
+{% if dims.nsh_e > 0 %}
+ // set up soft bounds for nonlinear constraints
+ int* idxsh_e = malloc(NSHN * sizeof(int));
+ {% for i in range(end=dims.nsh_e) %}
+ idxsh_e[{{ i }}] = {{ constraints.idxsh_e[i] }};
+ {%- endfor %}
+ double* lush_e = calloc(2*NSHN, sizeof(double));
+ double* lsh_e = lush_e;
+ double* ush_e = lush_e + NSHN;
+ {% for i in range(end=dims.nsh_e) %}
+ {%- if constraints.lsh_e[i] != 0 %}
+ lsh_e[{{ i }}] = {{ constraints.lsh_e[i] }};
+ {%- endif %}
+ {%- if constraints.ush_e[i] != 0 %}
+ ush_e[{{ i }}] = {{ constraints.ush_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsh", idxsh_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsh", lsh_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ush", ush_e);
+ free(idxsh_e);
+ free(lush_e);
+{%- endif %}
+
+{% if dims.nsphi_e > 0 %}
+ // set up soft bounds for convex-over-nonlinear constraints
+ int* idxsphi_e = malloc(NSPHIN * sizeof(int));
+ {% for i in range(end=dims.nsphi_e) %}
+ idxsphi_e[{{ i }}] = {{ constraints.idxsphi_e[i] }};
+ {%- endfor %}
+ double* lusphi_e = calloc(2*NSPHIN, sizeof(double));
+ double* lsphi_e = lusphi_e;
+ double* usphi_e = lusphi_e + NSPHIN;
+ {% for i in range(end=dims.nsphi_e) %}
+ {%- if constraints.lsphi_e[i] != 0 %}
+ lsphi_e[{{ i }}] = {{ constraints.lsphi_e[i] }};
+ {%- endif %}
+ {%- if constraints.usphi_e[i] != 0 %}
+ usphi_e[{{ i }}] = {{ constraints.usphi_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsphi", idxsphi_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsphi", lsphi_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "usphi", usphi_e);
+ free(idxsphi_e);
+ free(lusphi_e);
+{%- endif %}
+
+{% if dims.nsbx_e > 0 %}
+ // soft bounds on x
+ int* idxsbx_e = malloc(NSBXN * sizeof(int));
+ {% for i in range(end=dims.nsbx_e) %}
+ idxsbx_e[{{ i }}] = {{ constraints.idxsbx_e[i] }};
+ {%- endfor %}
+ double* lusbx_e = calloc(2*NSBXN, sizeof(double));
+ double* lsbx_e = lusbx_e;
+ double* usbx_e = lusbx_e + NSBXN;
+ {% for i in range(end=dims.nsbx_e) %}
+ {%- if constraints.lsbx_e[i] != 0 %}
+ lsbx_e[{{ i }}] = {{ constraints.lsbx_e[i] }};
+ {%- endif %}
+ {%- if constraints.usbx_e[i] != 0 %}
+ usbx_e[{{ i }}] = {{ constraints.usbx_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsbx", idxsbx_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsbx", lsbx_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "usbx", usbx_e);
+ free(idxsbx_e);
+ free(lusbx_e);
+{% endif %}
+
+{% if dims.ng_e > 0 %}
+ // set up general constraints for last stage
+ double* C_e = calloc(NGN*NX, sizeof(double));
+ double* lug_e = calloc(2*NGN, sizeof(double));
+ double* lg_e = lug_e;
+ double* ug_e = lug_e + NGN;
+
+ {% for j in range(end=dims.ng) %}
+ {%- for k in range(end=dims.nx) %}
+ {%- if constraints.C_e[j][k] != 0 %}
+ C_e[{{ j }}+NG * {{ k }}] = {{ constraints.C_e[j][k] }};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+
+ {% for i in range(end=dims.ng_e) %}
+ {%- if constraints.lg_e[i] != 0 %}
+ lg_e[{{ i }}] = {{ constraints.lg_e[i] }};
+ {%- endif %}
+ {%- if constraints.ug_e[i] != 0 %}
+ ug_e[{{ i }}] = {{ constraints.ug_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "C", C_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lg", lg_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ug", ug_e);
+ free(C_e);
+ free(lug_e);
+{%- endif %}
+
+{% if dims.nh_e > 0 %}
+ // set up nonlinear constraints for last stage
+ double* luh_e = calloc(2*NHN, sizeof(double));
+ double* lh_e = luh_e;
+ double* uh_e = luh_e + NHN;
+ {% for i in range(end=dims.nh_e) %}
+ {%- if constraints.lh_e[i] != 0 %}
+ lh_e[{{ i }}] = {{ constraints.lh_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ {% for i in range(end=dims.nh_e) %}
+ {%- if constraints.uh_e[i] != 0 %}
+ uh_e[{{ i }}] = {{ constraints.uh_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "nl_constr_h_fun_jac", &capsule->nl_constr_h_e_fun_jac);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "nl_constr_h_fun", &capsule->nl_constr_h_e_fun);
+ {% if solver_options.hessian_approx == "EXACT" %}
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "nl_constr_h_fun_jac_hess",
+ &capsule->nl_constr_h_e_fun_jac_hess);
+ {% endif %}
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lh", lh_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "uh", uh_e);
+ free(luh_e);
+{%- endif %}
+
+{% if dims.nphi_e > 0 and constraints.constr_type_e == "BGP" %}
+ // set up convex-over-nonlinear constraints for last stage
+ double* luphi_e = calloc(2*NPHIN, sizeof(double));
+ double* lphi_e = luphi_e;
+ double* uphi_e = luphi_e + NPHIN;
+ {% for i in range(end=dims.nphi_e) %}
+ {%- if constraints.lphi_e[i] != 0 %}
+ lphi_e[{{ i }}] = {{ constraints.lphi_e[i] }};
+ {%- endif %}
+ {%- if constraints.uphi_e[i] != 0 %}
+ uphi_e[{{ i }}] = {{ constraints.uphi_e[i] }};
+ {%- endif %}
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lphi", lphi_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "uphi", uphi_e);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N,
+ "nl_constr_phi_o_r_fun_phi_jac_ux_z_phi_hess_r_jac_ux", &capsule->phi_e_constraint);
+ free(luphi_e);
+{% endif %}
+
+
+ /************************************************
+ * opts
+ ************************************************/
+
+ capsule->nlp_opts = ocp_nlp_solver_opts_create(nlp_config, nlp_dims);
+
+{% if solver_options.hessian_approx == "EXACT" %}
+ bool nlp_solver_exact_hessian = true;
+ // TODO: this if should not be needed! however, calling the setter with false leads to weird behavior. Investigate!
+ if (nlp_solver_exact_hessian)
+ {
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "exact_hess", &nlp_solver_exact_hessian);
+ }
+ int exact_hess_dyn = {{ solver_options.exact_hess_dyn }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "exact_hess_dyn", &exact_hess_dyn);
+
+ int exact_hess_cost = {{ solver_options.exact_hess_cost }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "exact_hess_cost", &exact_hess_cost);
+
+ int exact_hess_constr = {{ solver_options.exact_hess_constr }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "exact_hess_constr", &exact_hess_constr);
+{%- endif -%}
+
+{%- if solver_options.globalization == "FIXED_STEP" %}
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "globalization", "fixed_step");
+{%- elif solver_options.globalization == "MERIT_BACKTRACKING" %}
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "globalization", "merit_backtracking");
+
+ double alpha_min = {{ solver_options.alpha_min }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "alpha_min", &alpha_min);
+
+ double alpha_reduction = {{ solver_options.alpha_reduction }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "alpha_reduction", &alpha_reduction);
+{%- endif -%}
+
+{%- if dims.nz > 0 %}
+ // TODO: these options are lower level -> should be encapsulated! maybe through hessian approx option.
+ bool output_z_val = true;
+ bool sens_algebraic_val = true;
+
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_output_z", &output_z_val);
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_sens_algebraic", &sens_algebraic_val);
+{%- endif %}
+
+{%- if solver_options.integrator_type != "DISCRETE" %}
+
+ // set up sim_method_num_steps
+ {%- set all_equal = true %}
+ {%- set val = solver_options.sim_method_num_steps[0] %}
+ {%- for j in range(start=1, end=dims.N) %}
+ {%- if val != solver_options.sim_method_num_steps[j] %}
+ {%- set_global all_equal = false %}
+ {%- break %}
+ {%- endif %}
+ {%- endfor %}
+
+ {%- if all_equal == true %}
+ // all sim_method_num_steps are identical
+ int sim_method_num_steps = {{ solver_options.sim_method_num_steps[0] }};
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_num_steps", &sim_method_num_steps);
+ {%- else %}
+ // sim_method_num_steps are different
+ int* sim_method_num_steps = malloc(N*sizeof(int));
+ {%- for j in range(end=dims.N) %}
+ sim_method_num_steps[{{ j }}] = {{ solver_options.sim_method_num_steps[j] }};
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_num_steps", &sim_method_num_steps[i]);
+ free(sim_method_num_steps);
+ {%- endif %}
+
+ // set up sim_method_num_stages
+ {%- set all_equal = true %}
+ {%- set val = solver_options.sim_method_num_stages[0] %}
+ {%- for j in range(start=1, end=dims.N) %}
+ {%- if val != solver_options.sim_method_num_stages[j] %}
+ {%- set_global all_equal = false %}
+ {%- break %}
+ {%- endif %}
+ {%- endfor %}
+
+ {%- if all_equal == true %}
+ // all sim_method_num_stages are identical
+ int sim_method_num_stages = {{ solver_options.sim_method_num_stages[0] }};
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_num_stages", &sim_method_num_stages);
+ {%- else %}
+ int* sim_method_num_stages = malloc(N*sizeof(int));
+ {%- for j in range(end=dims.N) %}
+ sim_method_num_stages[{{ j }}] = {{ solver_options.sim_method_num_stages[j] }};
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_num_stages", &sim_method_num_stages[i]);
+ free(sim_method_num_stages);
+ {%- endif %}
+
+ int newton_iter_val = {{ solver_options.sim_method_newton_iter }};
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_newton_iter", &newton_iter_val);
+
+
+ // set up sim_method_jac_reuse
+ {%- set all_equal = true %}
+ {%- set val = solver_options.sim_method_jac_reuse[0] %}
+ {%- for j in range(start=1, end=dims.N) %}
+ {%- if val != solver_options.sim_method_jac_reuse[j] %}
+ {%- set_global all_equal = false %}
+ {%- break %}
+ {%- endif %}
+ {%- endfor %}
+ {%- if all_equal == true %}
+ bool tmp_bool = (bool) {{ solver_options.sim_method_jac_reuse[0] }};
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_jac_reuse", &tmp_bool);
+ {%- else %}
+ bool* sim_method_jac_reuse = malloc(N*sizeof(bool));
+ {%- for j in range(end=dims.N) %}
+ sim_method_jac_reuse[{{ j }}] = (bool){{ solver_options.sim_method_jac_reuse[j] }};
+ {%- endfor %}
+
+ for (int i = 0; i < N; i++)
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "dynamics_jac_reuse", &sim_method_jac_reuse[i]);
+ free(sim_method_jac_reuse);
+ {%- endif %}
+
+{%- endif %}
+
+ double nlp_solver_step_length = {{ solver_options.nlp_solver_step_length }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "step_length", &nlp_solver_step_length);
+
+ {%- if solver_options.nlp_solver_warm_start_first_qp %}
+ int nlp_solver_warm_start_first_qp = {{ solver_options.nlp_solver_warm_start_first_qp }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "warm_start_first_qp", &nlp_solver_warm_start_first_qp);
+ {%- endif %}
+
+ double levenberg_marquardt = {{ solver_options.levenberg_marquardt }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "levenberg_marquardt", &levenberg_marquardt);
+
+ /* options QP solver */
+{%- if solver_options.qp_solver is starting_with("PARTIAL_CONDENSING") %}
+ int qp_solver_cond_N;
+
+ {%- if solver_options.qp_solver_cond_N %}
+ qp_solver_cond_N = {{ solver_options.qp_solver_cond_N }};
+ {% else %}
+ // NOTE: there is no condensing happening here!
+ qp_solver_cond_N = N;
+ {%- endif %}
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "qp_cond_N", &qp_solver_cond_N);
+{% endif %}
+
+ int qp_solver_iter_max = {{ solver_options.qp_solver_iter_max }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "qp_iter_max", &qp_solver_iter_max);
+
+ {%- if solver_options.qp_solver_tol_stat %}
+ double qp_solver_tol_stat = {{ solver_options.qp_solver_tol_stat }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "qp_tol_stat", &qp_solver_tol_stat);
+ {%- endif -%}
+
+ {%- if solver_options.qp_solver_tol_eq %}
+ double qp_solver_tol_eq = {{ solver_options.qp_solver_tol_eq }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "qp_tol_eq", &qp_solver_tol_eq);
+ {%- endif -%}
+
+ {%- if solver_options.qp_solver_tol_ineq %}
+ double qp_solver_tol_ineq = {{ solver_options.qp_solver_tol_ineq }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "qp_tol_ineq", &qp_solver_tol_ineq);
+ {%- endif -%}
+
+ {%- if solver_options.qp_solver_tol_comp %}
+ double qp_solver_tol_comp = {{ solver_options.qp_solver_tol_comp }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "qp_tol_comp", &qp_solver_tol_comp);
+ {%- endif -%}
+
+ {%- if solver_options.qp_solver_warm_start %}
+ int qp_solver_warm_start = {{ solver_options.qp_solver_warm_start }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "qp_warm_start", &qp_solver_warm_start);
+ {%- endif -%}
+
+{% if solver_options.nlp_solver_type == "SQP" %}
+ // set SQP specific options
+ double nlp_solver_tol_stat = {{ solver_options.nlp_solver_tol_stat }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "tol_stat", &nlp_solver_tol_stat);
+
+ double nlp_solver_tol_eq = {{ solver_options.nlp_solver_tol_eq }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "tol_eq", &nlp_solver_tol_eq);
+
+ double nlp_solver_tol_ineq = {{ solver_options.nlp_solver_tol_ineq }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "tol_ineq", &nlp_solver_tol_ineq);
+
+ double nlp_solver_tol_comp = {{ solver_options.nlp_solver_tol_comp }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "tol_comp", &nlp_solver_tol_comp);
+
+ int nlp_solver_max_iter = {{ solver_options.nlp_solver_max_iter }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "max_iter", &nlp_solver_max_iter);
+
+ int initialize_t_slacks = {{ solver_options.initialize_t_slacks }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "initialize_t_slacks", &initialize_t_slacks);
+{%- endif %}
+
+ int print_level = {{ solver_options.print_level }};
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "print_level", &print_level);
+
+
+ int ext_cost_num_hess = {{ solver_options.ext_cost_num_hess }};
+{%- if cost.cost_type == "EXTERNAL" %}
+ for (int i = 0; i < N; i++)
+ {
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, i, "cost_numerical_hessian", &ext_cost_num_hess);
+ }
+{%- endif %}
+{%- if cost.cost_type_e == "EXTERNAL" %}
+ ocp_nlp_solver_opts_set_at_stage(nlp_config, capsule->nlp_opts, N, "cost_numerical_hessian", &ext_cost_num_hess);
+{%- endif %}
+
+
+ /* out */
+ ocp_nlp_out * nlp_out = ocp_nlp_out_create(nlp_config, nlp_dims);
+ capsule->nlp_out = nlp_out;
+
+ // initialize primal solution
+ double* xu0 = calloc(NX+NU, sizeof(double));
+ double* x0 = xu0;
+{% if dims.nbx_0 == dims.nx %}
+ // initialize with x0
+ {% for item in constraints.lbx_0 %}
+ {%- if item != 0 %}
+ x0[{{ loop.index0 }}] = {{ item }};
+ {%- endif %}
+ {%- endfor %}
+{% else %}
+ // initialize with zeros
+{%- endif %}
+
+ double* u0 = xu0 + NX;
+
+ for (int i = 0; i < N; i++)
+ {
+ // x0
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "x", x0);
+ // u0
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "u", u0);
+ }
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, N, "x", x0);
+ free(xu0);
+
+ capsule->nlp_solver = ocp_nlp_solver_create(nlp_config, nlp_dims, capsule->nlp_opts);
+
+
+{% if dims.np > 0 %}
+ // initialize parameters to nominal value
+ double* p = calloc(NP, sizeof(double));
+ {% for item in parameter_values %}
+ {%- if item != 0 %}
+ p[{{ loop.index0 }}] = {{ item }};
+ {%- endif %}
+ {%- endfor %}
+
+ for (int i = 0; i <= N; i++)
+ {
+ {{ model.name }}_acados_update_params(capsule, i, p, NP);
+ }
+ free(p);
+{%- endif %}{# if dims.np #}
+
+ status = ocp_nlp_precompute(capsule->nlp_solver, nlp_in, nlp_out);
+
+ if (status != ACADOS_SUCCESS)
+ {
+ printf("\nocp_precompute failed!\n\n");
+ exit(1);
+ }
+
+ return status;
+}
+
+
+int {{ model.name }}_acados_update_params(nlp_solver_capsule * capsule, int stage, double *p, int np)
+{
+ int solver_status = 0;
+
+ int casadi_np = {{ dims.np }};
+ if (casadi_np != np) {
+ printf("acados_update_params: trying to set %i parameters for external functions."
+ " External function has %i parameters. Exiting.\n", np, casadi_np);
+ exit(1);
+ }
+
+{%- if dims.np > 0 %}
+ if (stage < {{ dims.N }} && stage >= 0)
+ {
+ {%- if solver_options.integrator_type == "IRK" %}
+ capsule->impl_dae_fun[stage].set_param(capsule->impl_dae_fun+stage, p);
+ capsule->impl_dae_fun_jac_x_xdot_z[stage].set_param(capsule->impl_dae_fun_jac_x_xdot_z+stage, p);
+ capsule->impl_dae_jac_x_xdot_u_z[stage].set_param(capsule->impl_dae_jac_x_xdot_u_z+stage, p);
+
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->impl_dae_hess[stage].set_param(capsule->impl_dae_hess+stage, p);
+ {%- endif %}
+ {% elif solver_options.integrator_type == "LIFTED_IRK" %}
+ capsule->impl_dae_fun[stage].set_param(capsule->impl_dae_fun+stage, p);
+ capsule->impl_dae_fun_jac_x_xdot_z[stage].set_param(capsule->impl_dae_fun_jac_x_xdot_z+stage, p);
+ {% elif solver_options.integrator_type == "ERK" %}
+ capsule->forw_vde_casadi[stage].set_param(capsule->forw_vde_casadi+stage, p);
+ capsule->expl_ode_fun[stage].set_param(capsule->expl_ode_fun+stage, p);
+
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->hess_vde_casadi[stage].set_param(capsule->hess_vde_casadi+stage, p);
+ {%- endif %}
+ {% elif solver_options.integrator_type == "GNSF" %}
+ capsule->gnsf_phi_fun[stage].set_param(capsule->gnsf_phi_fun+stage, p);
+ capsule->gnsf_phi_fun_jac_y[stage].set_param(capsule->gnsf_phi_fun_jac_y+stage, p);
+ capsule->gnsf_phi_jac_y_uhat[stage].set_param(capsule->gnsf_phi_jac_y_uhat+stage, p);
+
+ capsule->gnsf_f_lo_jac_x1_x1dot_u_z[stage].set_param(capsule->gnsf_f_lo_jac_x1_x1dot_u_z+stage, p);
+ {% elif solver_options.integrator_type == "DISCRETE" %}
+ capsule->discr_dyn_phi_fun[stage].set_param(capsule->discr_dyn_phi_fun+stage, p);
+ capsule->discr_dyn_phi_fun_jac_ut_xt[stage].set_param(capsule->discr_dyn_phi_fun_jac_ut_xt+stage, p);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->discr_dyn_phi_fun_jac_ut_xt_hess[stage].set_param(capsule->discr_dyn_phi_fun_jac_ut_xt_hess+stage, p);
+ {% endif %}
+ {%- endif %}{# integrator_type #}
+
+ // constraints
+ {% if constraints.constr_type == "BGP" %}
+ capsule->phi_constraint[stage].set_param(capsule->phi_constraint+stage, p);
+ {% elif constraints.constr_type == "BGH" and dims.nh > 0 %}
+ capsule->nl_constr_h_fun_jac[stage].set_param(capsule->nl_constr_h_fun_jac+stage, p);
+ capsule->nl_constr_h_fun[stage].set_param(capsule->nl_constr_h_fun+stage, p);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->nl_constr_h_fun_jac_hess[stage].set_param(capsule->nl_constr_h_fun_jac_hess+stage, p);
+ {%- endif %}
+ {%- endif %}
+
+ // cost
+ if (stage == 0)
+ {
+ {%- if cost.cost_type_0 == "NONLINEAR_LS" %}
+ capsule->cost_y_0_fun.set_param(&capsule->cost_y_0_fun, p);
+ capsule->cost_y_0_fun_jac_ut_xt.set_param(&capsule->cost_y_0_fun_jac_ut_xt, p);
+ capsule->cost_y_0_hess.set_param(&capsule->cost_y_0_hess, p);
+ {%- elif cost.cost_type_0 == "EXTERNAL" %}
+ capsule->ext_cost_0_fun.set_param(&capsule->ext_cost_0_fun, p);
+ capsule->ext_cost_0_fun_jac.set_param(&capsule->ext_cost_0_fun_jac, p);
+ capsule->ext_cost_0_fun_jac_hess.set_param(&capsule->ext_cost_0_fun_jac_hess, p);
+ {% endif %}
+ }
+ else // 0 < stage < N
+ {
+ {%- if cost.cost_type == "NONLINEAR_LS" %}
+ capsule->cost_y_fun[stage-1].set_param(capsule->cost_y_fun+stage-1, p);
+ capsule->cost_y_fun_jac_ut_xt[stage-1].set_param(capsule->cost_y_fun_jac_ut_xt+stage-1, p);
+ capsule->cost_y_hess[stage-1].set_param(capsule->cost_y_hess+stage-1, p);
+ {%- elif cost.cost_type == "EXTERNAL" %}
+ capsule->ext_cost_fun[stage-1].set_param(capsule->ext_cost_fun+stage-1, p);
+ capsule->ext_cost_fun_jac[stage-1].set_param(capsule->ext_cost_fun_jac+stage-1, p);
+ capsule->ext_cost_fun_jac_hess[stage-1].set_param(capsule->ext_cost_fun_jac_hess+stage-1, p);
+ {%- endif %}
+ }
+ }
+
+ else // stage == N
+ {
+ // terminal shooting node has no dynamics
+ // cost
+ {%- if cost.cost_type_e == "NONLINEAR_LS" %}
+ capsule->cost_y_e_fun.set_param(&capsule->cost_y_e_fun, p);
+ capsule->cost_y_e_fun_jac_ut_xt.set_param(&capsule->cost_y_e_fun_jac_ut_xt, p);
+ capsule->cost_y_e_hess.set_param(&capsule->cost_y_e_hess, p);
+ {%- elif cost.cost_type_e == "EXTERNAL" %}
+ capsule->ext_cost_e_fun.set_param(&capsule->ext_cost_e_fun, p);
+ capsule->ext_cost_e_fun_jac.set_param(&capsule->ext_cost_e_fun_jac, p);
+ capsule->ext_cost_e_fun_jac_hess.set_param(&capsule->ext_cost_e_fun_jac_hess, p);
+ {% endif %}
+ // constraints
+ {% if constraints.constr_type_e == "BGP" %}
+ capsule->phi_e_constraint.set_param(&capsule->phi_e_constraint, p);
+ {% elif constraints.constr_type_e == "BGH" and dims.nh_e > 0 %}
+ capsule->nl_constr_h_e_fun_jac.set_param(&capsule->nl_constr_h_e_fun_jac, p);
+ capsule->nl_constr_h_e_fun.set_param(&capsule->nl_constr_h_e_fun, p);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ capsule->nl_constr_h_e_fun_jac_hess.set_param(&capsule->nl_constr_h_e_fun_jac_hess, p);
+ {%- endif %}
+ {% endif %}
+ }
+{% endif %}{# if dims.np #}
+
+ return solver_status;
+}
+
+
+
+int {{ model.name }}_acados_solve(nlp_solver_capsule * capsule)
+{
+ // solve NLP
+ int solver_status = ocp_nlp_solve(capsule->nlp_solver, capsule->nlp_in, capsule->nlp_out);
+
+ return solver_status;
+}
+
+
+int {{ model.name }}_acados_free(nlp_solver_capsule * capsule)
+{
+ // free memory
+ ocp_nlp_solver_opts_destroy(capsule->nlp_opts);
+ ocp_nlp_in_destroy(capsule->nlp_in);
+ ocp_nlp_out_destroy(capsule->nlp_out);
+ ocp_nlp_solver_destroy(capsule->nlp_solver);
+ ocp_nlp_dims_destroy(capsule->nlp_dims);
+ ocp_nlp_config_destroy(capsule->nlp_config);
+ ocp_nlp_plan_destroy(capsule->nlp_solver_plan);
+
+ /* free external function */
+ // dynamics
+{%- if solver_options.integrator_type == "IRK" %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_casadi_free(&capsule->impl_dae_fun[i]);
+ external_function_param_casadi_free(&capsule->impl_dae_fun_jac_x_xdot_z[i]);
+ external_function_param_casadi_free(&capsule->impl_dae_jac_x_xdot_u_z[i]);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ external_function_param_casadi_free(&capsule->impl_dae_hess[i]);
+ {%- endif %}
+ }
+ free(capsule->impl_dae_fun);
+ free(capsule->impl_dae_fun_jac_x_xdot_z);
+ free(capsule->impl_dae_jac_x_xdot_u_z);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ free(capsule->impl_dae_hess);
+ {%- endif %}
+
+{%- elif solver_options.integrator_type == "LIFTED_IRK" %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_casadi_free(&capsule->impl_dae_fun[i]);
+ external_function_param_casadi_free(&capsule->impl_dae_fun_jac_x_xdot_u[i]);
+ }
+ free(capsule->impl_dae_fun);
+ free(capsule->impl_dae_fun_jac_x_xdot_u);
+
+{%- elif solver_options.integrator_type == "ERK" %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_casadi_free(&capsule->forw_vde_casadi[i]);
+ external_function_param_casadi_free(&capsule->expl_ode_fun[i]);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ external_function_param_casadi_free(&capsule->hess_vde_casadi[i]);
+ {%- endif %}
+ }
+ free(capsule->forw_vde_casadi);
+ free(capsule->expl_ode_fun);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ free(capsule->hess_vde_casadi);
+ {%- endif %}
+
+{%- elif solver_options.integrator_type == "GNSF" %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_casadi_free(&capsule->gnsf_phi_fun[i]);
+ external_function_param_casadi_free(&capsule->gnsf_phi_fun_jac_y[i]);
+ external_function_param_casadi_free(&capsule->gnsf_phi_jac_y_uhat[i]);
+ external_function_param_casadi_free(&capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i]);
+ external_function_param_casadi_free(&capsule->gnsf_get_matrices_fun[i]);
+ }
+ free(capsule->gnsf_phi_fun);
+ free(capsule->gnsf_phi_fun_jac_y);
+ free(capsule->gnsf_phi_jac_y_uhat);
+ free(capsule->gnsf_f_lo_jac_x1_x1dot_u_z);
+ free(capsule->gnsf_get_matrices_fun);
+{%- elif solver_options.integrator_type == "DISCRETE" %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->discr_dyn_phi_fun[i]);
+ external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->discr_dyn_phi_fun_jac_ut_xt[i]);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i]);
+ {%- endif %}
+ }
+ free(capsule->discr_dyn_phi_fun);
+ free(capsule->discr_dyn_phi_fun_jac_ut_xt);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ free(capsule->discr_dyn_phi_fun_jac_ut_xt_hess);
+ {%- endif %}
+
+{%- endif %}
+
+ // cost
+{%- if cost.cost_type_0 == "NONLINEAR_LS" %}
+ external_function_param_casadi_free(&capsule->cost_y_0_fun);
+ external_function_param_casadi_free(&capsule->cost_y_0_fun_jac_ut_xt);
+ external_function_param_casadi_free(&capsule->cost_y_0_hess);
+{%- elif cost.cost_type_0 == "EXTERNAL" %}
+ external_function_param_{{ cost.cost_ext_fun_type_0 }}_free(&capsule->ext_cost_0_fun);
+ external_function_param_{{ cost.cost_ext_fun_type_0 }}_free(&capsule->ext_cost_0_fun_jac);
+ external_function_param_{{ cost.cost_ext_fun_type_0 }}_free(&capsule->ext_cost_0_fun_jac_hess);
+{%- endif %}
+{%- if cost.cost_type == "NONLINEAR_LS" %}
+ for (int i = 0; i < {{ dims.N }} - 1; i++)
+ {
+ external_function_param_casadi_free(&capsule->cost_y_fun[i]);
+ external_function_param_casadi_free(&capsule->cost_y_fun_jac_ut_xt[i]);
+ external_function_param_casadi_free(&capsule->cost_y_hess[i]);
+ }
+ free(capsule->cost_y_fun);
+ free(capsule->cost_y_fun_jac_ut_xt);
+ free(capsule->cost_y_hess);
+{%- elif cost.cost_type == "EXTERNAL" %}
+ for (int i = 0; i < {{ dims.N }} - 1; i++)
+ {
+ external_function_param_{{ cost.cost_ext_fun_type }}_free(&capsule->ext_cost_fun[i]);
+ external_function_param_{{ cost.cost_ext_fun_type }}_free(&capsule->ext_cost_fun_jac[i]);
+ external_function_param_{{ cost.cost_ext_fun_type }}_free(&capsule->ext_cost_fun_jac_hess[i]);
+ }
+ free(capsule->ext_cost_fun);
+ free(capsule->ext_cost_fun_jac);
+ free(capsule->ext_cost_fun_jac_hess);
+{%- endif %}
+{%- if cost.cost_type_e == "NONLINEAR_LS" %}
+ external_function_param_casadi_free(&capsule->cost_y_e_fun);
+ external_function_param_casadi_free(&capsule->cost_y_e_fun_jac_ut_xt);
+ external_function_param_casadi_free(&capsule->cost_y_e_hess);
+{%- elif cost.cost_type_e == "EXTERNAL" %}
+ external_function_param_{{ cost.cost_ext_fun_type_e }}_free(&capsule->ext_cost_e_fun);
+ external_function_param_{{ cost.cost_ext_fun_type_e }}_free(&capsule->ext_cost_e_fun_jac);
+ external_function_param_{{ cost.cost_ext_fun_type_e }}_free(&capsule->ext_cost_e_fun_jac_hess);
+{%- endif %}
+
+ // constraints
+{%- if constraints.constr_type == "BGH" and dims.nh > 0 %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_casadi_free(&capsule->nl_constr_h_fun_jac[i]);
+ external_function_param_casadi_free(&capsule->nl_constr_h_fun[i]);
+ }
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_casadi_free(&capsule->nl_constr_h_fun_jac_hess[i]);
+ }
+ {%- endif %}
+ free(capsule->nl_constr_h_fun_jac);
+ free(capsule->nl_constr_h_fun);
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ free(capsule->nl_constr_h_fun_jac_hess);
+ {%- endif %}
+
+{%- elif constraints.constr_type == "BGP" and dims.nphi > 0 %}
+ for (int i = 0; i < {{ dims.N }}; i++)
+ {
+ external_function_param_casadi_free(&capsule->phi_constraint[i]);
+ }
+ free(capsule->phi_constraint);
+{%- endif %}
+
+{%- if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %}
+ external_function_param_casadi_free(&capsule->nl_constr_h_e_fun_jac);
+ external_function_param_casadi_free(&capsule->nl_constr_h_e_fun);
+{%- if solver_options.hessian_approx == "EXACT" %}
+ external_function_param_casadi_free(&capsule->nl_constr_h_e_fun_jac_hess);
+{%- endif %}
+{%- elif constraints.constr_type_e == "BGP" and dims.nphi_e > 0 %}
+ external_function_param_casadi_free(&capsule->phi_e_constraint);
+{%- endif %}
+
+ return 0;
+}
+
+ocp_nlp_in *{{ model.name }}_acados_get_nlp_in(nlp_solver_capsule * capsule) { return capsule->nlp_in; }
+ocp_nlp_out *{{ model.name }}_acados_get_nlp_out(nlp_solver_capsule * capsule) { return capsule->nlp_out; }
+ocp_nlp_solver *{{ model.name }}_acados_get_nlp_solver(nlp_solver_capsule * capsule) { return capsule->nlp_solver; }
+ocp_nlp_config *{{ model.name }}_acados_get_nlp_config(nlp_solver_capsule * capsule) { return capsule->nlp_config; }
+void *{{ model.name }}_acados_get_nlp_opts(nlp_solver_capsule * capsule) { return capsule->nlp_opts; }
+ocp_nlp_dims *{{ model.name }}_acados_get_nlp_dims(nlp_solver_capsule * capsule) { return capsule->nlp_dims; }
+ocp_nlp_plan *{{ model.name }}_acados_get_nlp_plan(nlp_solver_capsule * capsule) { return capsule->nlp_solver_plan; }
+
+
+void {{ model.name }}_acados_print_stats(nlp_solver_capsule * capsule)
+{
+ int sqp_iter, stat_m, stat_n, tmp_int;
+ ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "sqp_iter", &sqp_iter);
+ ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "stat_n", &stat_n);
+ ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "stat_m", &stat_m);
+
+ {% set stat_n_max = 10 %}
+ double stat[{{ solver_options.nlp_solver_max_iter * stat_n_max }}];
+ ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "statistics", stat);
+
+ int nrow = sqp_iter+1 < stat_m ? sqp_iter+1 : stat_m;
+
+ printf("iter\tres_stat\tres_eq\t\tres_ineq\tres_comp\tqp_stat\tqp_iter\n");
+ for (int i = 0; i < nrow; i++)
+ {
+ for (int j = 0; j < stat_n + 1; j++)
+ {
+ if (j == 0 || j > 4)
+ {
+ tmp_int = (int) stat[i + j * nrow];
+ printf("%d\t", tmp_int);
+ }
+ else
+ {
+ printf("%e\t", stat[i + j * nrow]);
+ }
+ }
+ printf("\n");
+ }
+}
+
diff --git a/pyextra/acados_template/c_templates_tera/acados_solver.in.h b/pyextra/acados_template/c_templates_tera/acados_solver.in.h
new file mode 100644
index 000000000..e8966c254
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_solver.in.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+#ifndef ACADOS_SOLVER_{{ model.name }}_H_
+#define ACADOS_SOLVER_{{ model.name }}_H_
+
+#include "acados_c/ocp_nlp_interface.h"
+#include "acados_c/external_function_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ** capsule for solver data **
+typedef struct nlp_solver_capsule
+{
+ // acados objects
+ ocp_nlp_in *nlp_in;
+ ocp_nlp_out *nlp_out;
+ ocp_nlp_solver *nlp_solver;
+ void *nlp_opts;
+ ocp_nlp_plan *nlp_solver_plan;
+ ocp_nlp_config *nlp_config;
+ ocp_nlp_dims *nlp_dims;
+
+ // number of expected runtime parameters
+ unsigned int nlp_np;
+
+ /* external functions */
+ // dynamics
+ external_function_param_casadi *forw_vde_casadi;
+ external_function_param_casadi *expl_ode_fun;
+ external_function_param_casadi *hess_vde_casadi;
+ external_function_param_casadi *impl_dae_fun;
+ external_function_param_casadi *impl_dae_fun_jac_x_xdot_z;
+ external_function_param_casadi *impl_dae_jac_x_xdot_u_z;
+ external_function_param_casadi *impl_dae_fun_jac_x_xdot_u;
+ external_function_param_casadi *impl_dae_hess;
+ external_function_param_casadi *gnsf_phi_fun;
+ external_function_param_casadi *gnsf_phi_fun_jac_y;
+ external_function_param_casadi *gnsf_phi_jac_y_uhat;
+ external_function_param_casadi *gnsf_f_lo_jac_x1_x1dot_u_z;
+ external_function_param_casadi *gnsf_get_matrices_fun;
+ external_function_param_{{ model.dyn_ext_fun_type }} *discr_dyn_phi_fun;
+ external_function_param_{{ model.dyn_ext_fun_type }} *discr_dyn_phi_fun_jac_ut_xt;
+ external_function_param_{{ model.dyn_ext_fun_type }} *discr_dyn_phi_fun_jac_ut_xt_hess;
+
+ // cost
+ external_function_param_casadi *cost_y_fun;
+ external_function_param_casadi *cost_y_fun_jac_ut_xt;
+ external_function_param_casadi *cost_y_hess;
+ external_function_param_{{ cost.cost_ext_fun_type }} *ext_cost_fun;
+ external_function_param_{{ cost.cost_ext_fun_type }} *ext_cost_fun_jac;
+ external_function_param_{{ cost.cost_ext_fun_type }} *ext_cost_fun_jac_hess;
+
+ external_function_param_casadi cost_y_0_fun;
+ external_function_param_casadi cost_y_0_fun_jac_ut_xt;
+ external_function_param_casadi cost_y_0_hess;
+ external_function_param_{{ cost.cost_ext_fun_type_0 }} ext_cost_0_fun;
+ external_function_param_{{ cost.cost_ext_fun_type_0 }} ext_cost_0_fun_jac;
+ external_function_param_{{ cost.cost_ext_fun_type_0 }} ext_cost_0_fun_jac_hess;
+
+ external_function_param_casadi cost_y_e_fun;
+ external_function_param_casadi cost_y_e_fun_jac_ut_xt;
+ external_function_param_casadi cost_y_e_hess;
+ external_function_param_{{ cost.cost_ext_fun_type_e }} ext_cost_e_fun;
+ external_function_param_{{ cost.cost_ext_fun_type_e }} ext_cost_e_fun_jac;
+ external_function_param_{{ cost.cost_ext_fun_type_e }} ext_cost_e_fun_jac_hess;
+
+ // constraints
+ external_function_param_casadi *phi_constraint;
+ external_function_param_casadi *nl_constr_h_fun_jac;
+ external_function_param_casadi *nl_constr_h_fun;
+ external_function_param_casadi *nl_constr_h_fun_jac_hess;
+
+ external_function_param_casadi phi_e_constraint;
+ external_function_param_casadi nl_constr_h_e_fun_jac;
+ external_function_param_casadi nl_constr_h_e_fun;
+ external_function_param_casadi nl_constr_h_e_fun_jac_hess;
+} nlp_solver_capsule;
+
+nlp_solver_capsule * {{ model.name }}_acados_create_capsule(void);
+int {{ model.name }}_acados_free_capsule(nlp_solver_capsule *capsule);
+
+int {{ model.name }}_acados_create(nlp_solver_capsule * capsule);
+int {{ model.name }}_acados_update_params(nlp_solver_capsule * capsule, int stage, double *value, int np);
+int {{ model.name }}_acados_solve(nlp_solver_capsule * capsule);
+int {{ model.name }}_acados_free(nlp_solver_capsule * capsule);
+void {{ model.name }}_acados_print_stats(nlp_solver_capsule * capsule);
+
+ocp_nlp_in *{{ model.name }}_acados_get_nlp_in(nlp_solver_capsule * capsule);
+ocp_nlp_out *{{ model.name }}_acados_get_nlp_out(nlp_solver_capsule * capsule);
+ocp_nlp_solver *{{ model.name }}_acados_get_nlp_solver(nlp_solver_capsule * capsule);
+ocp_nlp_config *{{ model.name }}_acados_get_nlp_config(nlp_solver_capsule * capsule);
+void *{{ model.name }}_acados_get_nlp_opts(nlp_solver_capsule * capsule);
+ocp_nlp_dims *{{ model.name }}_acados_get_nlp_dims(nlp_solver_capsule * capsule);
+ocp_nlp_plan *{{ model.name }}_acados_get_nlp_plan(nlp_solver_capsule * capsule);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // ACADOS_SOLVER_{{ model.name }}_H_
diff --git a/pyextra/acados_template/c_templates_tera/acados_solver_sfun.in.c b/pyextra/acados_template/c_templates_tera/acados_solver_sfun.in.c
new file mode 100644
index 000000000..e70c5cafe
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/acados_solver_sfun.in.c
@@ -0,0 +1,761 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+#define S_FUNCTION_NAME acados_solver_sfunction_{{ model.name }}
+#define S_FUNCTION_LEVEL 2
+
+#define MDL_START
+
+// acados
+#include "acados/utils/print.h"
+#include "acados_c/sim_interface.h"
+#include "acados_c/external_function_interface.h"
+
+// example specific
+#include "{{ model.name }}_model/{{ model.name }}_model.h"
+#include "acados_solver_{{ model.name }}.h"
+
+#include "simstruc.h"
+
+{% if simulink_opts.samplingtime == "t0" -%}
+#define SAMPLINGTIME {{ solver_options.time_steps[0] }}
+{%- elif simulink_opts.samplingtime == "-1" -%}
+#define SAMPLINGTIME -1
+{%- else -%}
+ {{ throw(message = "simulink_opts.samplingtime must be '-1' or 't0', got val") }}
+{%- endif %}
+
+static void mdlInitializeSizes (SimStruct *S)
+{
+ // specify the number of continuous and discrete states
+ ssSetNumContStates(S, 0);
+ ssSetNumDiscStates(S, 0);
+
+ {%- for key, val in simulink_opts.inputs -%}
+ {%- if val != 0 and val != 1 -%}
+ {{ throw(message = "simulink_opts.inputs must be 0 or 1, got val") }}
+ {%- endif -%}
+ {%- endfor -%}
+
+ {#- compute number of input ports #}
+ {%- set n_inputs = 0 -%}
+ {%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 -%} {#- y_ref_0 -#}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref -%} {#- y_ref -#}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e -%} {#- y_ref_e #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+ {%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+
+ {%- for key, val in simulink_opts.inputs -%}
+ {%- if val != 0 and val != 1 -%}
+ {{ throw(message = "simulink_opts.inputs must be 0 or 1, got val") }}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #}
+ {%- set n_inputs = n_inputs + 1 %}
+ {%- endif -%}
+ {%- if dims.ny > 0 and simulink_opts.inputs.cost_W -%} {#- cost_W #}
+ {%- set n_inputs = n_inputs + 1 %}
+ {%- endif -%}
+ {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e -%} {#- cost_W_e #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+
+ {%- if simulink_opts.inputs.x_init -%} {#- x_init #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+
+ {%- if simulink_opts.inputs.u_init -%} {#- u_init #}
+ {%- set n_inputs = n_inputs + 1 -%}
+ {%- endif -%}
+
+ // specify the number of input ports
+ if ( !ssSetNumInputPorts(S, {{ n_inputs }}) )
+ return;
+
+ // specify the number of output ports
+ {%- set_global n_outputs = 0 %}
+ {%- for key, val in simulink_opts.outputs %}
+ {%- if val == 1 %}
+ {%- set_global n_outputs = n_outputs + val %}
+ {%- elif val != 0 %}
+ {{ throw(message = "simulink_opts.outputs must be 0 or 1, got val") }}
+ {%- endif %}
+ {%- endfor %}
+ if ( !ssSetNumOutputPorts(S, {{ n_outputs }}) )
+ return;
+
+ // specify dimension information for the input ports
+ {%- set i_input = -1 %}{# note here i_input is 0-based #}
+ {%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #}
+ {%- set i_input = i_input + 1 %}
+ // lbx_0
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_0 }});
+ {%- endif %}
+ {%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #}
+ {%- set i_input = i_input + 1 %}
+ // ubx_0
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_0 }});
+ {%- endif %}
+
+ {%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #}
+ {%- set i_input = i_input + 1 %}
+ // parameters
+ ssSetInputPortVectorDimension(S, {{ i_input }}, ({{ dims.N }}+1) * {{ dims.np }});
+ {%- endif %}
+
+ {%- if dims.ny > 0 and simulink_opts.inputs.y_ref_0 %}
+ {%- set i_input = i_input + 1 %}
+ // y_ref_0
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_0 }});
+ {%- endif %}
+
+ {%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %}
+ {%- set i_input = i_input + 1 %}
+ // y_ref
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ (dims.N-1) * dims.ny }});
+ {%- endif %}
+
+ {%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %}
+ {%- set i_input = i_input + 1 %}
+ // y_ref_e
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_e }});
+ {%- endif %}
+
+ {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #}
+ {%- set i_input = i_input + 1 %}
+ // lbx
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ (dims.N-1) * dims.nbx }});
+ {%- endif %}
+ {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #}
+ {%- set i_input = i_input + 1 %}
+ // ubx
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ (dims.N-1) * dims.nbx }});
+ {%- endif %}
+
+ {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #}
+ {%- set i_input = i_input + 1 %}
+ // lbx_e
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_e }});
+ {%- endif %}
+ {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #}
+ {%- set i_input = i_input + 1 %}
+ // ubx_e
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_e }});
+ {%- endif %}
+
+ {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #}
+ {%- set i_input = i_input + 1 %}
+ // lbu
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.nbu }});
+ {%- endif -%}
+ {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #}
+ {%- set i_input = i_input + 1 %}
+ // ubu
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.nbu }});
+ {%- endif -%}
+
+
+ {%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #}
+ {%- set i_input = i_input + 1 %}
+ // lg
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ng }});
+ {%- endif -%}
+ {%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #}
+ {%- set i_input = i_input + 1 %}
+ // ug
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ng }});
+ {%- endif -%}
+
+ {%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #}
+ {%- set i_input = i_input + 1 %}
+ // lh
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nh }});
+ {%- endif -%}
+ {%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #}
+ {%- set i_input = i_input + 1 %}
+ // uh
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nh }});
+ {%- endif -%}
+
+ {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #}
+ {%- set i_input = i_input + 1 %}
+ // cost_W_0
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_0 * dims.ny_0 }});
+ {%- endif %}
+
+ {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W %} {#- cost_W #}
+ {%- set i_input = i_input + 1 %}
+ // cost_W
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny * dims.ny }});
+ {%- endif %}
+
+ {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #}
+ {%- set i_input = i_input + 1 %}
+ // cost_W_e
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_e * dims.ny_e }});
+ {%- endif %}
+
+ {%- if simulink_opts.inputs.x_init -%} {#- x_init #}
+ {%- set i_input = i_input + 1 %}
+ // x_init
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nx * (dims.N+1) }});
+ {%- endif -%}
+
+ {%- if simulink_opts.inputs.u_init -%} {#- u_init #}
+ {%- set i_input = i_input + 1 %}
+ // u_init
+ ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nu * (dims.N) }});
+ {%- endif -%}
+
+ /* specify dimension information for the OUTPUT ports */
+ {%- set i_output = -1 %}{# note here i_output is 0-based #}
+ {%- if dims.nu > 0 and simulink_opts.outputs.u0 == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nu }} );
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.utraj == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nu * dims.N }} );
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.xtraj == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nx * (dims.N+1) }} );
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.solver_status == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, 1 );
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.KKT_residual == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, 1 );
+ {%- endif %}
+
+ {%- if dims.N > 0 and simulink_opts.outputs.x1 == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nx }} ); // state at shooting node 1
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.CPU_time == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, 1);
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.CPU_time_sim == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, 1);
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.CPU_time_qp == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, 1);
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.CPU_time_lin == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, 1);
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.sqp_iter == 1 %}
+ {%- set i_output = i_output + 1 %}
+ ssSetOutputPortVectorDimension(S, {{ i_output }}, 1 );
+ {%- endif %}
+
+ // specify the direct feedthrough status
+ // should be set to 1 for all inputs used in mdlOutputs
+ {%- for i in range(end=n_inputs) %}
+ ssSetInputPortDirectFeedThrough(S, {{ i }}, 1);
+ {%- endfor %}
+
+ // one sample time
+ ssSetNumSampleTimes(S, 1);
+}
+
+
+#if defined(MATLAB_MEX_FILE)
+
+#define MDL_SET_INPUT_PORT_DIMENSION_INFO
+#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
+
+static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
+{
+ if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) )
+ return;
+}
+
+static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
+{
+ if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) )
+ return;
+}
+
+#endif /* MATLAB_MEX_FILE */
+
+
+static void mdlInitializeSampleTimes(SimStruct *S)
+{
+ ssSetSampleTime(S, 0, SAMPLINGTIME);
+ ssSetOffsetTime(S, 0, 0.0);
+}
+
+
+static void mdlStart(SimStruct *S)
+{
+ nlp_solver_capsule *capsule = {{ model.name }}_acados_create_capsule();
+ {{ model.name }}_acados_create(capsule);
+
+ ssSetUserData(S, (void*)capsule);
+}
+
+
+static void mdlOutputs(SimStruct *S, int_T tid)
+{
+ nlp_solver_capsule *capsule = ssGetUserData(S);
+ ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(capsule);
+ ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule);
+ ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(capsule);
+ ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(capsule);
+
+ InputRealPtrsType in_sign;
+
+ {%- set buffer_sizes = [dims.nbx_0, dims.np, dims.nbx, dims.nbu, dims.ng, dims.nh, dims.nx] -%}
+
+ {%- if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 %} {# y_ref_0 #}
+ {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_0)) %}
+ {%- endif %}
+ {%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %} {# y_ref #}
+ {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny)) %}
+ {%- endif %}
+ {%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %} {# y_ref_e #}
+ {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_e)) %}
+ {%- endif %}
+
+ {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {# cost_W_0 #}
+ {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_0 * dims.ny_0)) %}
+ {%- endif %}
+ {%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {# cost_W #}
+ {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny * dims.ny)) %}
+ {%- endif %}
+ {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {# cost_W_e #}
+ {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_e * dims.ny_e)) %}
+ {%- endif %}
+
+ // local buffer
+ {%- set buffer_size = buffer_sizes | sort | last %}
+ real_t buffer[{{ buffer_size }}];
+
+ /* go through inputs */
+ {%- set i_input = -1 %}
+ {%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #}
+ // lbx_0
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int i = 0; i < {{ dims.nbx_0 }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbx", buffer);
+ {%- endif %}
+
+ {%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #}
+ // ubx_0
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int i = 0; i < {{ dims.nbx_0 }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubx", buffer);
+ {%- endif %}
+
+ {%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #}
+ // parameters - stage-variant !!!
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ // update value of parameters
+ for (int ii = 0; ii <= {{ dims.N }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.np }}; jj++)
+ buffer[jj] = (double)(*in_sign[ii*{{dims.np}}+jj]);
+ {{ model.name }}_acados_update_params(capsule, ii, buffer, {{ dims.np }});
+ }
+ {%- endif %}
+
+ {% if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 %}
+ // y_ref_0
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.ny_0 }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "yref", (void *) buffer);
+ {%- endif %}
+
+ {% if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %}
+ // y_ref - for stages 1 to N-1
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int ii = 1; ii < {{ dims.N }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.ny }}; jj++)
+ buffer[jj] = (double)(*in_sign[(ii-1)*{{ dims.ny }}+jj]);
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, ii, "yref", (void *) buffer);
+ }
+ {%- endif %}
+
+ {% if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %}
+ // y_ref_e
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.ny_e }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, {{ dims.N }}, "yref", (void *) buffer);
+ {%- endif %}
+
+ {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #}
+ // lbx
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int ii = 1; ii < {{ dims.N }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.nbx }}; jj++)
+ buffer[jj] = (double)(*in_sign[(ii-1)*{{ dims.nbx }}+jj]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lbx", (void *) buffer);
+ }
+ {%- endif %}
+ {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #}
+ // ubx
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int ii = 1; ii < {{ dims.N }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.nbx }}; jj++)
+ buffer[jj] = (double)(*in_sign[(ii-1)*{{ dims.nbx }}+jj]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "ubx", (void *) buffer);
+ }
+ {%- endif %}
+
+
+ {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #}
+ // lbx_e
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.nbx_e }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, {{ dims.N }}, "lbx", buffer);
+ {%- endif %}
+ {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #}
+ // ubx_e
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.nbx_e }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, {{ dims.N }}, "ubx", buffer);
+ {%- endif %}
+
+
+ {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #}
+ // lbu
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.nbu }}; jj++)
+ buffer[jj] = (double)(*in_sign[ii*{{ dims.nbu }}+jj]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lbu", (void *) buffer);
+ }
+ {%- endif -%}
+ {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #}
+ // ubu
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.nbu }}; jj++)
+ buffer[jj] = (double)(*in_sign[ii*{{ dims.nbu }}+jj]);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "ubu", (void *) buffer);
+ }
+ {%- endif -%}
+
+ {%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #}
+ // lg
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.ng }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lg", buffer);
+ {%- endif -%}
+ {%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #}
+ // ug
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.ng }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "ug", buffer);
+ {%- endif -%}
+ {%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #}
+ // lh
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.nh }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lh", buffer);
+ {%- endif -%}
+ {%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #}
+ // uh
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+
+ for (int i = 0; i < {{ dims.nh }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "uh", buffer);
+ {%- endif -%}
+
+ {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {# cost_W_0 #}
+ // cost_W_0
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int i = 0; i < {{ dims.ny_0 * dims.ny_0 }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "W", buffer);
+ {%- endif %}
+
+ {%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {# cost_W #}
+ // cost_W
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int i = 0; i < {{ dims.ny * dims.ny }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ for (int ii = 1; ii < {{ dims.N }}; ii++)
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, ii, "W", buffer);
+ {%- endif %}
+
+ {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #}
+ // cost_W_e
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int i = 0; i < {{ dims.ny_e * dims.ny_e }}; i++)
+ buffer[i] = (double)(*in_sign[i]);
+
+ ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, {{ dims.N }}, "W", buffer);
+ {%- endif %}
+
+ {%- if simulink_opts.inputs.x_init %} {#- x_init #}
+ // x_init
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int ii = 0; ii < {{ dims.N + 1 }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.nx }}; jj++)
+ buffer[jj] = (double)(*in_sign[(ii)*{{ dims.nx }}+jj]);
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, ii, "x", (void *) buffer);
+ }
+ {%- endif %}
+
+ {%- if simulink_opts.inputs.u_init %} {#- u_init #}
+ // u_init
+ {%- set i_input = i_input + 1 %}
+ in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }});
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ {
+ for (int jj = 0; jj < {{ dims.nu }}; jj++)
+ buffer[jj] = (double)(*in_sign[(ii)*{{ dims.nu }}+jj]);
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, ii, "u", (void *) buffer);
+ }
+ {%- endif %}
+
+ /* call solver */
+ int rti_phase = 0;
+ ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "rti_phase", &rti_phase);
+ int acados_status = {{ model.name }}_acados_solve(capsule);
+
+
+ /* set outputs */
+ // assign pointers to output signals
+ real_t *out_u0, *out_utraj, *out_xtraj, *out_status, *out_sqp_iter, *out_KKT_res, *out_x1, *out_cpu_time, *out_cpu_time_sim, *out_cpu_time_qp, *out_cpu_time_lin;
+ int tmp_int;
+
+ {%- set i_output = -1 -%}{# note here i_output is 0-based #}
+ {%- if dims.nu > 0 and simulink_opts.outputs.u0 == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_u0 = ssGetOutputPortRealSignal(S, {{ i_output }});
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 0, "u", (void *) out_u0);
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.utraj == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_utraj = ssGetOutputPortRealSignal(S, {{ i_output }});
+ for (int ii = 0; ii < {{ dims.N }}; ii++)
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii,
+ "u", (void *) (out_utraj + ii * {{ dims.nu }}));
+ {%- endif %}
+
+ {% if simulink_opts.outputs.xtraj == 1 %}
+ {%- set i_output = i_output + 1 %}
+
+ out_xtraj = ssGetOutputPortRealSignal(S, {{ i_output }});
+ for (int ii = 0; ii < {{ dims.N + 1 }}; ii++)
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii,
+ "x", (void *) (out_xtraj + ii * {{ dims.nx }}));
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.solver_status == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_status = ssGetOutputPortRealSignal(S, {{ i_output }});
+ *out_status = (real_t) acados_status;
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.KKT_residual == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_KKT_res = ssGetOutputPortRealSignal(S, {{ i_output }});
+ *out_KKT_res = (real_t) nlp_out->inf_norm_res;
+ {%- endif %}
+
+ {%- if dims.N > 0 and simulink_opts.outputs.x1 == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_x1 = ssGetOutputPortRealSignal(S, {{ i_output }});
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 1, "x", (void *) out_x1);
+ {%- endif %}
+
+ {%- if simulink_opts.outputs.CPU_time == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_cpu_time = ssGetOutputPortRealSignal(S, {{ i_output }});
+ // get solution time
+ ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_tot", (void *) out_cpu_time);
+ {%- endif -%}
+
+ {%- if simulink_opts.outputs.CPU_time_sim == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_cpu_time_sim = ssGetOutputPortRealSignal(S, {{ i_output }});
+ ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_sim", (void *) out_cpu_time_sim);
+ {%- endif -%}
+
+ {%- if simulink_opts.outputs.CPU_time_qp == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_cpu_time_qp = ssGetOutputPortRealSignal(S, {{ i_output }});
+ ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_qp", (void *) out_cpu_time_qp);
+ {%- endif -%}
+
+ {%- if simulink_opts.outputs.CPU_time_lin == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_cpu_time_lin = ssGetOutputPortRealSignal(S, {{ i_output }});
+ ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_lin", (void *) out_cpu_time_lin);
+ {%- endif -%}
+
+ {%- if simulink_opts.outputs.sqp_iter == 1 %}
+ {%- set i_output = i_output + 1 %}
+ out_sqp_iter = ssGetOutputPortRealSignal(S, {{ i_output }});
+ // get sqp iter
+ ocp_nlp_get(nlp_config, capsule->nlp_solver, "sqp_iter", (void *) &tmp_int);
+ *out_sqp_iter = (real_t) tmp_int;
+ {%- endif %}
+
+}
+
+static void mdlTerminate(SimStruct *S)
+{
+ nlp_solver_capsule *capsule = ssGetUserData(S);
+
+ {{ model.name }}_acados_free(capsule);
+ {{ model.name }}_acados_free_capsule(capsule);
+}
+
+
+#ifdef MATLAB_MEX_FILE
+#include "simulink.c"
+#else
+#include "cg_sfun.h"
+#endif
diff --git a/pyextra/acados_template/c_templates_tera/cost_y_0_fun.in.h b/pyextra/acados_template/c_templates_tera/cost_y_0_fun.in.h
new file mode 100644
index 000000000..347446e3f
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/cost_y_0_fun.in.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+#ifndef {{ model.name }}_Y_0_COST
+#define {{ model.name }}_Y_0_COST
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if cost.cost_type_0 == "NONLINEAR_LS" %}
+int {{ model.name }}_cost_y_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_0_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_0_fun_sparsity_in(int);
+const int *{{ model.name }}_cost_y_0_fun_sparsity_out(int);
+int {{ model.name }}_cost_y_0_fun_n_in(void);
+int {{ model.name }}_cost_y_0_fun_n_out(void);
+
+int {{ model.name }}_cost_y_0_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_0_fun_jac_ut_xt_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_in(int);
+const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_out(int);
+int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_in(void);
+int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_out(void);
+
+int {{ model.name }}_cost_y_0_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_0_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_0_hess_sparsity_in(int);
+const int *{{ model.name }}_cost_y_0_hess_sparsity_out(int);
+int {{ model.name }}_cost_y_0_hess_n_in(void);
+int {{ model.name }}_cost_y_0_hess_n_out(void);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_Y_0_COST
diff --git a/pyextra/acados_template/c_templates_tera/cost_y_e_fun.in.h b/pyextra/acados_template/c_templates_tera/cost_y_e_fun.in.h
new file mode 100644
index 000000000..acc99009f
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/cost_y_e_fun.in.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+#ifndef {{ model.name }}_Y_E_COST
+#define {{ model.name }}_Y_E_COST
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if cost.cost_type_e == "NONLINEAR_LS" %}
+int {{ model.name }}_cost_y_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_e_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_e_fun_sparsity_in(int);
+const int *{{ model.name }}_cost_y_e_fun_sparsity_out(int);
+int {{ model.name }}_cost_y_e_fun_n_in(void);
+int {{ model.name }}_cost_y_e_fun_n_out(void);
+
+int {{ model.name }}_cost_y_e_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_e_fun_jac_ut_xt_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_in(int);
+const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_out(int);
+int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_in(void);
+int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_out(void);
+
+int {{ model.name }}_cost_y_e_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_e_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_e_hess_sparsity_in(int);
+const int *{{ model.name }}_cost_y_e_hess_sparsity_out(int);
+int {{ model.name }}_cost_y_e_hess_n_in(void);
+int {{ model.name }}_cost_y_e_hess_n_out(void);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_Y_E_COST
diff --git a/pyextra/acados_template/c_templates_tera/cost_y_fun.in.h b/pyextra/acados_template/c_templates_tera/cost_y_fun.in.h
new file mode 100644
index 000000000..1e03780cc
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/cost_y_fun.in.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+#ifndef {{ model.name }}_Y_COST
+#define {{ model.name }}_Y_COST
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if cost.cost_type == "NONLINEAR_LS" %}
+int {{ model.name }}_cost_y_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_fun_sparsity_in(int);
+const int *{{ model.name }}_cost_y_fun_sparsity_out(int);
+int {{ model.name }}_cost_y_fun_n_in(void);
+int {{ model.name }}_cost_y_fun_n_out(void);
+
+int {{ model.name }}_cost_y_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_fun_jac_ut_xt_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_in(int);
+const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_out(int);
+int {{ model.name }}_cost_y_fun_jac_ut_xt_n_in(void);
+int {{ model.name }}_cost_y_fun_jac_ut_xt_n_out(void);
+
+int {{ model.name }}_cost_y_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_y_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_y_hess_sparsity_in(int);
+const int *{{ model.name }}_cost_y_hess_sparsity_out(int);
+int {{ model.name }}_cost_y_hess_n_in(void);
+int {{ model.name }}_cost_y_hess_n_out(void);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_Y_COST
diff --git a/pyextra/acados_template/c_templates_tera/external_cost.in.h b/pyextra/acados_template/c_templates_tera/external_cost.in.h
new file mode 100644
index 000000000..d200dba45
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/external_cost.in.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+#ifndef {{ model.name }}_EXT_COST
+#define {{ model.name }}_EXT_COST
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if cost.cost_ext_fun_type == "casadi" %}
+{% if cost.cost_type == "EXTERNAL" %}
+int {{ model.name }}_cost_ext_cost_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_fun_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_fun_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_fun_n_in(void);
+int {{ model.name }}_cost_ext_cost_fun_n_out(void);
+
+int {{ model.name }}_cost_ext_cost_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_fun_jac_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_in(void);
+int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_out(void);
+
+int {{ model.name }}_cost_ext_cost_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_fun_jac_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_fun_jac_n_in(void);
+int {{ model.name }}_cost_ext_cost_fun_jac_n_out(void);
+{% endif %}
+
+{% else %}
+int {{ cost.cost_function_ext_cost }}(void **, void **, void *);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_EXT_COST
diff --git a/pyextra/acados_template/c_templates_tera/external_cost_0.in.h b/pyextra/acados_template/c_templates_tera/external_cost_0.in.h
new file mode 100644
index 000000000..8152447e5
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/external_cost_0.in.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+#ifndef {{ model.name }}_EXT_COST_0
+#define {{ model.name }}_EXT_COST_0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if cost.cost_ext_fun_type_0 == "casadi" %}
+
+{% if cost.cost_type_0 == "EXTERNAL" %}
+int {{ model.name }}_cost_ext_cost_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_0_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_0_fun_n_in(void);
+int {{ model.name }}_cost_ext_cost_0_fun_n_out(void);
+
+int {{ model.name }}_cost_ext_cost_0_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_in(void);
+int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_out(void);
+
+int {{ model.name }}_cost_ext_cost_0_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_0_fun_jac_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_0_fun_jac_n_in(void);
+int {{ model.name }}_cost_ext_cost_0_fun_jac_n_out(void);
+{% endif %}
+
+{% else %}
+int {{ cost.cost_function_ext_cost_0 }}(void **, void **, void *);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_EXT_COST_0
diff --git a/pyextra/acados_template/c_templates_tera/external_cost_e.in.h b/pyextra/acados_template/c_templates_tera/external_cost_e.in.h
new file mode 100644
index 000000000..56485db4c
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/external_cost_e.in.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+#ifndef {{ model.name }}_EXT_COST_E
+#define {{ model.name }}_EXT_COST_E
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if cost.cost_ext_fun_type_e == "casadi" %}
+{% if cost.cost_type_e == "EXTERNAL" %}
+int {{ model.name }}_cost_ext_cost_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_e_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_e_fun_n_in(void);
+int {{ model.name }}_cost_ext_cost_e_fun_n_out(void);
+
+int {{ model.name }}_cost_ext_cost_e_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_in(void);
+int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_out(void);
+
+int {{ model.name }}_cost_ext_cost_e_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_cost_ext_cost_e_fun_jac_work(int *, int *, int *, int *);
+const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_in(int);
+const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_out(int);
+int {{ model.name }}_cost_ext_cost_e_fun_jac_n_in(void);
+int {{ model.name }}_cost_ext_cost_e_fun_jac_n_out(void);
+{% endif %}
+
+{% else %}
+int {{ cost.cost_function_ext_cost_e }}(void **, void **, void *);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_EXT_COST_E
diff --git a/pyextra/acados_template/c_templates_tera/h_constraint.in.h b/pyextra/acados_template/c_templates_tera/h_constraint.in.h
new file mode 100644
index 000000000..e49176c6e
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/h_constraint.in.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+#ifndef {{ model.name }}_H_CONSTRAINT
+#define {{ model.name }}_H_CONSTRAINT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if dims.nh > 0 %}
+int {{ model.name }}_constr_h_fun_jac_uxt_zt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_constr_h_fun_jac_uxt_zt_work(int *, int *, int *, int *);
+const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_in(int);
+const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_out(int);
+int {{ model.name }}_constr_h_fun_jac_uxt_zt_n_in(void);
+int {{ model.name }}_constr_h_fun_jac_uxt_zt_n_out(void);
+
+int {{ model.name }}_constr_h_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_constr_h_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_constr_h_fun_sparsity_in(int);
+const int *{{ model.name }}_constr_h_fun_sparsity_out(int);
+int {{ model.name }}_constr_h_fun_n_in(void);
+int {{ model.name }}_constr_h_fun_n_out(void);
+
+{% if solver_options.hessian_approx == "EXACT" -%}
+int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_in(int);
+const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_out(int);
+int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_in(void);
+int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_out(void);
+{% endif %}
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_H_CONSTRAINT
diff --git a/pyextra/acados_template/c_templates_tera/h_e_constraint.in.h b/pyextra/acados_template/c_templates_tera/h_e_constraint.in.h
new file mode 100644
index 000000000..a5dd71164
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/h_e_constraint.in.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+#ifndef {{ model.name }}_H_E_CONSTRAINT
+#define {{ model.name }}_H_E_CONSTRAINT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if dims.nh_e > 0 %}
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_work(int *, int *, int *, int *);
+const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_sparsity_in(int);
+const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_sparsity_out(int);
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_n_in(void);
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_n_out(void);
+
+int {{ model.name }}_constr_h_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_constr_h_e_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_constr_h_e_fun_sparsity_in(int);
+const int *{{ model.name }}_constr_h_e_fun_sparsity_out(int);
+int {{ model.name }}_constr_h_e_fun_n_in(void);
+int {{ model.name }}_constr_h_e_fun_n_out(void);
+
+{% if solver_options.hessian_approx == "EXACT" -%}
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_sparsity_in(int);
+const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_sparsity_out(int);
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_n_in(void);
+int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_n_out(void);
+{% endif %}
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_H_E_CONSTRAINT
diff --git a/pyextra/acados_template/c_templates_tera/main.in.c b/pyextra/acados_template/c_templates_tera/main.in.c
new file mode 100644
index 000000000..1cae69aea
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/main.in.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+// standard
+#include
+#include
+// acados
+#include "acados/utils/print.h"
+#include "acados/utils/math.h"
+#include "acados_c/ocp_nlp_interface.h"
+#include "acados_c/external_function_interface.h"
+#include "acados_solver_{{ model.name }}.h"
+
+
+int main()
+{
+
+ nlp_solver_capsule *acados_ocp_capsule = {{ model.name }}_acados_create_capsule();
+ int status = {{ model.name }}_acados_create(acados_ocp_capsule);
+
+ if (status)
+ {
+ printf("{{ model.name }}_acados_create() returned status %d. Exiting.\n", status);
+ exit(1);
+ }
+
+ ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(acados_ocp_capsule);
+ ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(acados_ocp_capsule);
+ ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(acados_ocp_capsule);
+ ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(acados_ocp_capsule);
+ ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(acados_ocp_capsule);
+ void *nlp_opts = {{ model.name }}_acados_get_nlp_opts(acados_ocp_capsule);
+
+ // initial condition
+ int idxbx0[{{ dims.nbx_0 }}];
+ {%- for i in range(end=dims.nbx_0) %}
+ idxbx0[{{ i }}] = {{ constraints.idxbx_0[i] }};
+ {%- endfor %}
+
+ double lbx0[{{ dims.nbx_0 }}];
+ double ubx0[{{ dims.nbx_0 }}];
+ {%- for i in range(end=dims.nbx_0) %}
+ lbx0[{{ i }}] = {{ constraints.lbx_0[i] }};
+ ubx0[{{ i }}] = {{ constraints.ubx_0[i] }};
+ {%- endfor %}
+
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxbx", idxbx0);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbx", lbx0);
+ ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubx", ubx0);
+
+ // initialization for state values
+ double x_init[{{ dims.nx }}];
+ {%- for i in range(end=dims.nx) %}
+ x_init[{{ i }}] = 0.0;
+ {%- endfor %}
+
+ // initial value for control input
+ double u0[{{ dims.nu }}];
+ {%- for i in range(end=dims.nu) %}
+ u0[{{ i }}] = 0.0;
+ {%- endfor %}
+
+
+ {%- if dims.np > 0 %}
+ // set parameters
+ double p[{{ dims.np }}];
+ {% for item in parameter_values %}
+ p[{{ loop.index0 }}] = {{ item }};
+ {% endfor %}
+
+ for (int ii = 0; ii <= {{ dims.N }}; ii++)
+ {
+ {{ model.name }}_acados_update_params(acados_ocp_capsule, ii, p, {{ dims.np }});
+ }
+ {% endif %}{# if np > 0 #}
+
+ // prepare evaluation
+ int NTIMINGS = 1;
+ double min_time = 1e12;
+ double kkt_norm_inf;
+ double elapsed_time;
+ int sqp_iter;
+
+ double xtraj[{{ dims.nx }} * ({{ dims.N }}+1)];
+ double utraj[{{ dims.nu }} * ({{ dims.N }})];
+
+
+ // solve ocp in loop
+ int rti_phase = 0;
+
+ for (int ii = 0; ii < NTIMINGS; ii++)
+ {
+ // initialize solution
+ for (int i = 0; i <= nlp_dims->N; i++)
+ {
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "x", x_init);
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "u", u0);
+ }
+ ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "rti_phase", &rti_phase);
+ status = {{ model.name }}_acados_solve(acados_ocp_capsule);
+ ocp_nlp_get(nlp_config, nlp_solver, "time_tot", &elapsed_time);
+ min_time = MIN(elapsed_time, min_time);
+ }
+
+ /* print solution and statistics */
+ for (int ii = 0; ii <= nlp_dims->N; ii++)
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "x", &xtraj[ii*{{ dims.nx }}]);
+ for (int ii = 0; ii < nlp_dims->N; ii++)
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "u", &utraj[ii*{{ dims.nu }}]);
+
+ printf("\n--- xtraj ---\n");
+ d_print_exp_tran_mat( {{ dims.nx }}, {{ dims.N }}+1, xtraj, {{ dims.nx }} );
+ printf("\n--- utraj ---\n");
+ d_print_exp_tran_mat( {{ dims.nu }}, {{ dims.N }}, utraj, {{ dims.nu }} );
+ // ocp_nlp_out_print(nlp_solver->dims, nlp_out);
+
+ printf("\nsolved ocp %d times, solution printed above\n\n", NTIMINGS);
+
+ if (status == ACADOS_SUCCESS)
+ {
+ printf("{{ model.name }}_acados_solve(): SUCCESS!\n");
+ }
+ else
+ {
+ printf("{{ model.name }}_acados_solve() failed with status %d.\n", status);
+ }
+
+ // get solution
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 0, "kkt_norm_inf", &kkt_norm_inf);
+ ocp_nlp_get(nlp_config, nlp_solver, "sqp_iter", &sqp_iter);
+
+ {{ model.name }}_acados_print_stats(acados_ocp_capsule);
+
+ printf("\nSolver info:\n");
+ printf(" SQP iterations %2d\n minimum time for %d solve %f [ms]\n KKT %e\n",
+ sqp_iter, NTIMINGS, min_time*1000, kkt_norm_inf);
+
+ // free solver
+ status = {{ model.name }}_acados_free(acados_ocp_capsule);
+ if (status) {
+ printf("{{ model.name }}_acados_free() returned status %d. \n", status);
+ }
+ // free solver capsule
+ status = {{ model.name }}_acados_free_capsule(acados_ocp_capsule);
+ if (status) {
+ printf("{{ model.name }}_acados_free_capsule() returned status %d. \n", status);
+ }
+
+ return status;
+}
diff --git a/pyextra/acados_template/c_templates_tera/main_mex.in.c b/pyextra/acados_template/c_templates_tera/main_mex.in.c
new file mode 100644
index 000000000..8da5db29a
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/main_mex.in.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+// standard
+#include
+#include
+// acados
+#include "acados/utils/print.h"
+#include "acados/utils/math.h"
+#include "acados_c/ocp_nlp_interface.h"
+#include "acados_solver_{{ model.name }}.h"
+// mex
+#include "mex.h"
+
+/* auxilary mex */
+// prints a matrix in column-major format (exponential notation)
+void MEX_print_exp_mat(int m, int n, double *A, int lda)
+{
+ for (int i=0; iN; i++)
+ {
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "x", x_init);
+ ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "u", u0);
+ }
+ status = {{ model.name }}_acados_solve();
+ ocp_nlp_get(nlp_config, nlp_solver, "time_tot", &elapsed_time);
+ min_time = MIN(elapsed_time, min_time);
+ }
+
+ /* print solution and statistics */
+ for (int ii = 0; ii <= nlp_dims->N; ii++)
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "x", &xtraj[ii*{{ dims.nx }}]);
+ for (int ii = 0; ii < nlp_dims->N; ii++)
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "u", &utraj[ii*{{ dims.nu }}]);
+
+ mexPrintf("\n--- xtraj ---\n");
+ MEX_print_exp_tran_mat( {{ dims.nx }}, {{ dims.N }}+1, xtraj, {{ dims.nx }} );
+ mexPrintf("\n--- utraj ---\n");
+ MEX_print_exp_tran_mat( {{ dims.nu }}, {{ dims.N }}, utraj, {{ dims.nu }} );
+
+ mexPrintf("\nsolved ocp %d times, solution printed above\n\n", NTIMINGS);
+
+ if (status == ACADOS_SUCCESS)
+ mexPrintf("{{ model.name }}_acados_solve(): SUCCESS!\n");
+ else
+ mexPrintf("{{ model.name }}_acados_solve() failed with status %d.\n", status);
+
+ // get solution
+ ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 0, "kkt_norm_inf", &kkt_norm_inf);
+ ocp_nlp_get(nlp_config, nlp_solver, "sqp_iter", &sqp_iter);
+
+ mexPrintf("\nSolver info:\n");
+ mexPrintf(" SQP iterations %2d\n minimum time for 1 solve %f [ms]\n KKT %e\n",
+ sqp_iter, min_time*1000, kkt_norm_inf);
+
+ // free solver
+ status = {{ model.name }}_acados_free();
+ if (status)
+ {
+ mexPrintf("{{ model.name }}_acados_free() returned status %d.\n", status);
+ }
+
+ return;
+}
diff --git a/pyextra/acados_template/c_templates_tera/main_sim.in.c b/pyextra/acados_template/c_templates_tera/main_sim.in.c
new file mode 100644
index 000000000..b62bf8f7f
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/main_sim.in.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+
+// standard
+#include
+#include
+// acados
+#include "acados/utils/print.h"
+#include "acados/utils/math.h"
+#include "acados_c/sim_interface.h"
+#include "acados_sim_solver_{{ model.name }}.h"
+
+
+int main()
+{
+ int status = 0;
+ sim_solver_capsule *capsule = {{ model.name }}_acados_sim_solver_create_capsule();
+ status = {{ model.name }}_acados_sim_create(capsule);
+
+ if (status)
+ {
+ printf("acados_create() returned status %d. Exiting.\n", status);
+ exit(1);
+ }
+
+ sim_config *acados_sim_config = {{ model.name }}_acados_get_sim_config(capsule);
+ sim_in *acados_sim_in = {{ model.name }}_acados_get_sim_in(capsule);
+ sim_out *acados_sim_out = {{ model.name }}_acados_get_sim_out(capsule);
+ void *acados_sim_dims = {{ model.name }}_acados_get_sim_dims(capsule);
+
+ // initial condition
+ double x_current[{{ dims.nx }}];
+ {%- for i in range(end=dims.nx) %}
+ x_current[{{ i }}] = 0.0;
+ {%- endfor %}
+
+ {% if constraints.lbx_0 %}
+ {%- for i in range(end=dims.nbx_0) %}
+ x_current[{{ constraints.idxbx_0[i] }}] = {{ constraints.lbx_0[i] }};
+ {%- endfor %}
+ {% if dims.nbx_0 != dims.nx %}
+ printf("main_sim: NOTE: initial state not fully defined via lbx_0, using 0.0 for indices that are not in idxbx_0.");
+ {%- endif %}
+ {% else %}
+ printf("main_sim: initial state not defined, should be in lbx_0, using zero vector.");
+ {%- endif %}
+
+
+ // initial value for control input
+ double u0[{{ dims.nu }}];
+ {%- for i in range(end=dims.nu) %}
+ u0[{{ i }}] = 0.0;
+ {%- endfor %}
+
+ {%- if dims.np > 0 %}
+ // set parameters
+ double p[{{ dims.np }}];
+ {% for item in parameter_values %}
+ p[{{ loop.index0 }}] = {{ item }};
+ {% endfor %}
+
+ {{ model.name }}_acados_sim_update_params(capsule, p, {{ dims.np }});
+ {% endif %}{# if np > 0 #}
+
+ int n_sim_steps = 3;
+ // solve ocp in loop
+ for (int ii = 0; ii < n_sim_steps; ii++)
+ {
+ sim_in_set(acados_sim_config, acados_sim_dims,
+ acados_sim_in, "x", x_current);
+ status = {{ model.name }}_acados_sim_solve(capsule);
+
+ if (status != ACADOS_SUCCESS)
+ {
+ printf("acados_solve() failed with status %d.\n", status);
+ }
+
+ sim_out_get(acados_sim_config, acados_sim_dims,
+ acados_sim_out, "x", x_current);
+
+ printf("\nx_current, %d\n", ii);
+ for (int jj = 0; jj < {{ dims.nx }}; jj++)
+ {
+ printf("%e\n", x_current[jj]);
+ }
+ }
+
+ printf("\nPerformed %d simulation steps with acados integrator successfully.\n\n", n_sim_steps);
+
+ // free solver
+ status = {{ model.name }}_acados_sim_free(capsule);
+ if (status) {
+ printf("{{ model.name }}_acados_sim_free() returned status %d. \n", status);
+ }
+
+ {{ model.name }}_acados_sim_solver_free_capsule(capsule);
+
+ return status;
+}
diff --git a/pyextra/acados_template/c_templates_tera/make_main_mex.in.m b/pyextra/acados_template/c_templates_tera/make_main_mex.in.m
new file mode 100644
index 000000000..9188686a0
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/make_main_mex.in.m
@@ -0,0 +1,105 @@
+%
+% Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+% Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+% Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+% Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+%
+% This file is part of acados.
+%
+% The 2-Clause BSD License
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+%
+% 1. Redistributions of source code must retain the above copyright notice,
+% this list of conditions and the following disclaimer.
+%
+% 2. Redistributions in binary form must reproduce the above copyright notice,
+% this list of conditions and the following disclaimer in the documentation
+% and/or other materials provided with the distribution.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.;
+%
+
+function make_main_mex_{{ model.name }}()
+
+ opts.output_dir = pwd;
+
+ % get acados folder
+ acados_folder = getenv('ACADOS_INSTALL_DIR');
+
+ % set paths
+ acados_include = ['-I' fullfile(acados_folder, 'include')];
+ template_lib_include = ['-l' 'acados_solver_{{ model.name }}'];
+ template_lib_path = ['-L' fullfile(pwd)];
+
+ acados_lib_path = ['-L' fullfile(acados_folder, 'lib')];
+ external_include = ['-I', fullfile(acados_folder, 'external')];
+ blasfeo_include = ['-I', fullfile(acados_folder, 'external', 'blasfeo', 'include')];
+ hpipm_include = ['-I', fullfile(acados_folder, 'external', 'hpipm', 'include')];
+
+ mex_names = { ...
+ 'main_mex_{{ model.name }}' ...
+ };
+
+ mex_files = cell(length(mex_names), 1);
+ for k=1:length(mex_names)
+ mex_files{k} = fullfile([mex_names{k}, '.c']);
+ end
+
+ %% octave C flags
+ if is_octave()
+ if ~exist(fullfile(opts.output_dir, 'cflags_octave.txt'), 'file')
+ diary(fullfile(opts.output_dir, 'cflags_octave.txt'));
+ diary on
+ mkoctfile -p CFLAGS
+ diary off
+ input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r');
+ cflags_tmp = fscanf(input_file, '%[^\n]s');
+ fclose(input_file);
+ if ~ismac()
+ cflags_tmp = [cflags_tmp, ' -std=c99 -fopenmp'];
+ else
+ cflags_tmp = [cflags_tmp, ' -std=c99'];
+ end
+ input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'w');
+ fprintf(input_file, '%s', cflags_tmp);
+ fclose(input_file);
+ end
+ % read cflags from file
+ input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r');
+ cflags_tmp = fscanf(input_file, '%[^\n]s');
+ fclose(input_file);
+ setenv('CFLAGS', cflags_tmp);
+ end
+
+ %% compile mex
+ for ii=1:length(mex_files)
+ disp(['compiling ', mex_files{ii}])
+ if is_octave()
+ % mkoctfile -p CFLAGS
+ mex(acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,...
+ acados_lib_path, template_lib_path, '-lacados', '-lhpipm', '-lblasfeo', mex_files{ii})
+ else
+ if ismac()
+ FLAGS = 'CFLAGS=$CFLAGS -std=c99';
+ else
+ FLAGS = 'CFLAGS=$CFLAGS -std=c99 -fopenmp';
+ end
+ mex(FLAGS, acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,...
+ acados_lib_path, template_lib_path, '-lacados', '-lhpipm', '-lblasfeo', mex_files{ii})
+ end
+ end
+
+
+end
\ No newline at end of file
diff --git a/pyextra/acados_template/c_templates_tera/make_mex.in.m b/pyextra/acados_template/c_templates_tera/make_mex.in.m
new file mode 100644
index 000000000..cde30f6f4
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/make_mex.in.m
@@ -0,0 +1,110 @@
+%
+% Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+% Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+% Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+% Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+%
+% This file is part of acados.
+%
+% The 2-Clause BSD License
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+%
+% 1. Redistributions of source code must retain the above copyright notice,
+% this list of conditions and the following disclaimer.
+%
+% 2. Redistributions in binary form must reproduce the above copyright notice,
+% this list of conditions and the following disclaimer in the documentation
+% and/or other materials provided with the distribution.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.;
+%
+
+function make_mex_{{ model.name }}()
+
+ opts.output_dir = pwd;
+
+ % get acados folder
+ acados_folder = getenv('ACADOS_INSTALL_DIR');
+
+ % set paths
+ acados_include = ['-I' fullfile(acados_folder, 'include')];
+ template_lib_include = ['-l' 'acados_ocp_solver_{{ model.name }}'];
+ template_lib_path = ['-L' fullfile(pwd)];
+
+ acados_lib_path = ['-L' fullfile(acados_folder, 'lib')];
+ external_include = ['-I', fullfile(acados_folder, 'external')];
+ blasfeo_include = ['-I', fullfile(acados_folder, 'external', 'blasfeo', 'include')];
+ hpipm_include = ['-I', fullfile(acados_folder, 'external', 'hpipm', 'include')];
+
+ mex_include = ['-I', fullfile(acados_folder, 'interfaces', 'acados_matlab_octave')];
+
+ mex_names = { ...
+ 'acados_mex_create_{{ model.name }}' ...
+ 'acados_mex_free_{{ model.name }}' ...
+ 'acados_mex_solve_{{ model.name }}' ...
+ 'acados_mex_set_{{ model.name }}' ...
+ };
+
+ mex_files = cell(length(mex_names), 1);
+ for k=1:length(mex_names)
+ mex_files{k} = fullfile([mex_names{k}, '.c']);
+ end
+
+ %% octave C flags
+ if is_octave()
+ if ~exist(fullfile(opts.output_dir, 'cflags_octave.txt'), 'file')
+ diary(fullfile(opts.output_dir, 'cflags_octave.txt'));
+ diary on
+ mkoctfile -p CFLAGS
+ diary off
+ input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r');
+ cflags_tmp = fscanf(input_file, '%[^\n]s');
+ fclose(input_file);
+ if ~ismac()
+ cflags_tmp = [cflags_tmp, ' -std=c99 -fopenmp'];
+ else
+ cflags_tmp = [cflags_tmp, ' -std=c99'];
+ end
+ input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'w');
+ fprintf(input_file, '%s', cflags_tmp);
+ fclose(input_file);
+ end
+ % read cflags from file
+ input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r');
+ cflags_tmp = fscanf(input_file, '%[^\n]s');
+ fclose(input_file);
+ setenv('CFLAGS', cflags_tmp);
+ end
+
+ %% compile mex
+ for ii=1:length(mex_files)
+ disp(['compiling ', mex_files{ii}])
+ if is_octave()
+ % mkoctfile -p CFLAGS
+ mex(acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,...
+ acados_lib_path, template_lib_path, mex_include, '-lacados', '-lhpipm', '-lblasfeo', mex_files{ii})
+ else
+ if ismac()
+ FLAGS = 'CFLAGS=$CFLAGS -std=c99';
+ else
+ FLAGS = 'CFLAGS=$CFLAGS -std=c99 -fopenmp';
+ end
+ mex(FLAGS, acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,...
+ acados_lib_path, template_lib_path, mex_include, '-lacados', '-lhpipm', '-lblasfeo', mex_files{ii})
+ end
+ end
+
+
+end
\ No newline at end of file
diff --git a/pyextra/acados_template/c_templates_tera/make_sfun.in.m b/pyextra/acados_template/c_templates_tera/make_sfun.in.m
new file mode 100644
index 000000000..172da654e
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/make_sfun.in.m
@@ -0,0 +1,335 @@
+%
+% Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+% Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+% Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+% Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+%
+% This file is part of acados.
+%
+% The 2-Clause BSD License
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+%
+% 1. Redistributions of source code must retain the above copyright notice,
+% this list of conditions and the following disclaimer.
+%
+% 2. Redistributions in binary form must reproduce the above copyright notice,
+% this list of conditions and the following disclaimer in the documentation
+% and/or other materials provided with the distribution.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.;
+%
+
+SOURCES = { ...
+ {%- if solver_options.integrator_type == 'ERK' %}
+ '{{ model.name }}_model/{{ model.name }}_expl_ode_fun.c', ...
+ '{{ model.name }}_model/{{ model.name }}_expl_vde_forw.c',...
+ {%- if solver_options.hessian_approx == 'EXACT' %}
+ '{{ model.name }}_model/{{ model.name }}_expl_ode_hess.c',...
+ {%- endif %}
+ {%- elif solver_options.integrator_type == "IRK" %}
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_fun.c', ...
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_z.c', ...
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_jac_x_xdot_u_z.c', ...
+ {%- if solver_options.hessian_approx == 'EXACT' %}
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_hess.c',...
+ {%- endif %}
+ {%- elif solver_options.integrator_type == "GNSF" %}
+ '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun.c',...
+ '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun_jac_y.c',...
+ '{{ model.name }}_model/{{ model.name }}_gnsf_phi_jac_y_uhat.c',...
+ '{{ model.name }}_model/{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.c',...
+ '{{ model.name }}_model/{{ model.name }}_gnsf_get_matrices_fun.c',...
+ {%- elif solver_options.integrator_type == "DISCRETE" %}
+ '{{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun.c',...
+ '{{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac.c',...
+ {%- if solver_options.hessian_approx == "EXACT" %}
+ '{{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac_hess.c',...
+ {%- endif %}
+ {%- endif %}
+ {%- if cost.cost_type_0 == "NONLINEAR_LS" %}
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_0_fun.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_0_fun_jac_ut_xt.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_0_hess.c',...
+ {%- elif cost.cost_type_0 == "EXTERNAL" %}
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac_hess.c',...
+ {%- endif %}
+
+ {%- if cost.cost_type == "NONLINEAR_LS" %}
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_fun.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_fun_jac_ut_xt.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_hess.c',...
+ {%- elif cost.cost_type == "EXTERNAL" %}
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac_hess.c',...
+ {%- endif %}
+ {%- if cost.cost_type_e == "NONLINEAR_LS" %}
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_e_fun.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_e_fun_jac_ut_xt.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_y_e_hess.c',...
+ {%- elif cost.cost_type_e == "EXTERNAL" %}
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac.c',...
+ '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac_hess.c',...
+ {%- endif %}
+ {%- if constraints.constr_type == "BGH" and dims.nh > 0 %}
+ '{{ model.name }}_constraints/{{ model.name }}_constr_h_fun.c', ...
+ '{{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt_hess.c', ...
+ '{{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt.c', ...
+ {%- elif constraints.constr_type == "BGP" and dims.nphi > 0 %}
+ '{{ model.name }}_constraints/{{ model.name }}_phi_constraint.c', ...
+ {%- endif %}
+ {%- if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %}
+ '{{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun.c', ...
+ '{{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess.c', ...
+ '{{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt.c', ...
+ {%- elif constraints.constr_type_e == "BGP" and dims.nphi_e > 0 %}
+ '{{ model.name }}_constraints/{{ model.name }}_phi_e_constraint.c', ...
+ {%- endif %}
+ 'acados_solver_sfunction_{{ model.name }}.c', ...
+ 'acados_solver_{{ model.name }}.c'
+ };
+
+INC_PATH = '{{ acados_include_path }}';
+
+INCS = {['-I', fullfile(INC_PATH, 'blasfeo', 'include')], ...
+ ['-I', fullfile(INC_PATH, 'hpipm', 'include')], ...
+ ['-I', fullfile(INC_PATH, 'acados')], ...
+ ['-I', fullfile(INC_PATH)]};
+
+{% if solver_options.qp_solver is containing("QPOASES") %}
+INCS{end+1} = ['-I', fullfile(INC_PATH, 'qpOASES_e')];
+{% endif %}
+
+CFLAGS = 'CFLAGS=$CFLAGS';
+LDFLAGS = 'LDFLAGS=$LDFLAGS';
+COMPFLAGS = 'COMPFLAGS=$COMPFLAGS';
+COMPDEFINES = 'COMPDEFINES=$COMPDEFINES';
+
+{% if solver_options.qp_solver is containing("QPOASES") %}
+CFLAGS = [ CFLAGS, ' -DACADOS_WITH_QPOASES ' ];
+COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_QPOASES ' ];
+{%- elif solver_options.qp_solver is containing("OSQP") %}
+CFLAGS = [ CFLAGS, ' -DACADOS_WITH_OSQP ' ];
+COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_OSQP ' ];
+{%- elif solver_options.qp_solver is containing("QPDUNES") %}
+CFLAGS = [ CFLAGS, ' -DACADOS_WITH_QPDUNES ' ];
+COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_QPDUNES ' ];
+{%- elif solver_options.qp_solver is containing("HPMPC") %}
+CFLAGS = [ CFLAGS, ' -DACADOS_WITH_HPMPC ' ];
+COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_HPMPC ' ];
+{% endif %}
+
+LIB_PATH = ['-L', fullfile('{{ acados_lib_path }}')];
+
+LIBS = {'-lacados', '-lhpipm', '-lblasfeo'};
+
+% acados linking libraries and flags
+{%- if acados_link_libs and os and os == "pc" %}
+LDFLAGS = [LDFLAGS ' {{ acados_link_libs.openmp }}'];
+COMPFLAGS = [COMPFLAGS ' {{ acados_link_libs.openmp }}'];
+LIBS{end+1} = '{{ acados_link_libs.qpoases }}';
+LIBS{end+1} = '{{ acados_link_libs.hpmpc }}';
+LIBS{end+1} = '{{ acados_link_libs.osqp }}';
+{%- else %}
+ {% if solver_options.qp_solver is containing("QPOASES") %}
+LIBS{end+1} = '-lqpOASES_e';
+ {% endif %}
+{%- endif %}
+
+mex('-v', '-O', CFLAGS, LDFLAGS, COMPFLAGS, COMPDEFINES, INCS{:}, ...
+ LIB_PATH, LIBS{:}, SOURCES{:}, ...
+ '-output', 'acados_solver_sfunction_{{ model.name }}' );
+
+fprintf( [ '\n\nSuccessfully created sfunction:\nacados_solver_sfunction_{{ model.name }}', '.', ...
+ eval('mexext')] );
+
+
+%% print note on usage of s-function
+fprintf('\n\nNote: Usage of Sfunction is as follows:\n')
+input_note = 'Inputs are:\n';
+i_in = 1;
+
+
+{%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #}
+input_note = strcat(input_note, num2str(i_in), ') lbx_0 - lower bound on x for stage 0,',...
+ ' size [{{ dims.nbx_0 }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #}
+input_note = strcat(input_note, num2str(i_in), ') ubx_0 - upper bound on x for stage 0,',...
+ ' size [{{ dims.nbx_0 }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #}
+input_note = strcat(input_note, num2str(i_in), ') parameters - concatenated for all shooting nodes 0 to N+1,',...
+ ' size [{{ (dims.N+1)*dims.np }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 %}
+input_note = strcat(input_note, num2str(i_in), ') y_ref_0, size [{{ dims.ny_0 }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %}
+input_note = strcat(input_note, num2str(i_in), ') y_ref - concatenated for shooting nodes 1 to N-1,',...
+ ' size [{{ (dims.N-1) * dims.ny }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %}
+input_note = strcat(input_note, num2str(i_in), ') y_ref_e, size [{{ dims.ny_e }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #}
+input_note = strcat(input_note, num2str(i_in), ') lbx for shooting nodes 1 to N-1, size [{{ (dims.N-1) * dims.nbx }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+{%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #}
+input_note = strcat(input_note, num2str(i_in), ') ubx for shooting nodes 1 to N-1, size [{{ (dims.N-1) * dims.nbx }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+
+{%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #}
+input_note = strcat(input_note, num2str(i_in), ') lbx_e (lbx at shooting node N), size [{{ dims.nbx_e }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+{%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #}
+input_note = strcat(input_note, num2str(i_in), ') ubx_e (ubx at shooting node N), size [{{ dims.nbx_e }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #}
+input_note = strcat(input_note, num2str(i_in), ') lbu for shooting nodes 0 to N-1, size [{{ dims.N*dims.nbu }}]\n ');
+i_in = i_in + 1;
+{%- endif -%}
+{%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #}
+input_note = strcat(input_note, num2str(i_in), ') ubu for shooting nodes 0 to N-1, size [{{ dims.N*dims.nbu }}]\n ');
+i_in = i_in + 1;
+{%- endif -%}
+
+{%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #}
+input_note = strcat(input_note, num2str(i_in), ') lg, size [{{ dims.ng }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+{%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #}
+input_note = strcat(input_note, num2str(i_in), ') ug, size [{{ dims.ng }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #}
+input_note = strcat(input_note, num2str(i_in), ') lh, size [{{ dims.nh }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+{%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #}
+input_note = strcat(input_note, num2str(i_in), ') uh, size [{{ dims.nh }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #}
+input_note = strcat(input_note, num2str(i_in), ') cost_W_0 in column-major format, size [{{ dims.ny_0 * dims.ny_0 }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {#- cost_W #}
+input_note = strcat(input_note, num2str(i_in), ') cost_W in column-major format, that is set for all intermediate shooting nodes: 1 to N-1, size [{{ dims.ny * dims.ny }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #}
+input_note = strcat(input_note, num2str(i_in), ') cost_W_e in column-major format, size [{{ dims.ny_e * dims.ny_e }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if simulink_opts.inputs.x_init %} {#- x_init #}
+input_note = strcat(input_note, num2str(i_in), ') initialization of x for all shooting nodes, size [{{ dims.nx * (dims.N+1) }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if simulink_opts.inputs.u_init %} {#- u_init #}
+input_note = strcat(input_note, num2str(i_in), ') initialization of u for shooting nodes 0 to N-1, size [{{ dims.nu * (dims.N) }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+fprintf(input_note)
+
+disp(' ')
+
+output_note = 'Outputs are:\n';
+i_out = 0;
+
+{%- if dims.nu > 0 and simulink_opts.outputs.u0 == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') u0, control input at node 0, size [{{ dims.nu }}]\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.utraj == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') utraj, control input concatenated for nodes 0 to N-1, size [{{ dims.nu * dims.N }}]\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.xtraj == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') xtraj, state concatenated for nodes 0 to N, size [{{ dims.nx * (dims.N + 1) }}]\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.solver_status == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') acados solver status (0 = SUCCESS)\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.KKT_residual == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') KKT residual\n ');
+{%- endif %}
+
+{%- if dims.N > 0 and simulink_opts.outputs.x1 == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') x1, state at node 1\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.CPU_time == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') CPU time\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.CPU_time_sim == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') CPU time integrator\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.CPU_time_qp == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') CPU time QP solution\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.CPU_time_lin == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') CPU time linearization (including integrator)\n ');
+{%- endif %}
+
+{%- if simulink_opts.outputs.sqp_iter == 1 %}
+i_out = i_out + 1;
+output_note = strcat(output_note, num2str(i_out), ') SQP iterations\n ');
+{%- endif %}
+
+fprintf(output_note)
diff --git a/pyextra/acados_template/c_templates_tera/make_sfun_sim.in.m b/pyextra/acados_template/c_templates_tera/make_sfun_sim.in.m
new file mode 100644
index 000000000..1c5cf0b12
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/make_sfun_sim.in.m
@@ -0,0 +1,99 @@
+%
+% Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+% Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+% Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+% Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+%
+% This file is part of acados.
+%
+% The 2-Clause BSD License
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+%
+% 1. Redistributions of source code must retain the above copyright notice,
+% this list of conditions and the following disclaimer.
+%
+% 2. Redistributions in binary form must reproduce the above copyright notice,
+% this list of conditions and the following disclaimer in the documentation
+% and/or other materials provided with the distribution.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.;
+%
+
+SOURCES = [ 'acados_sim_solver_sfunction_{{ model.name }}.c ', ...
+ 'acados_sim_solver_{{ model.name }}.c ', ...
+ {%- if solver_options.integrator_type == 'ERK' %}
+ '{{ model.name }}_model/{{ model.name }}_expl_ode_fun.c ', ...
+ '{{ model.name }}_model/{{ model.name }}_expl_vde_forw.c ',...
+ {%- if solver_options.hessian_approx == 'EXACT' %}
+ '{{ model.name }}_model/{{ model.name }}_expl_ode_hess.c ',...
+ {%- endif %}
+ {%- elif solver_options.integrator_type == "IRK" %}
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_fun.c ', ...
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_z.c ', ...
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_jac_x_xdot_u_z.c ', ...
+ {%- if solver_options.hessian_approx == 'EXACT' %}
+ '{{ model.name }}_model/{{ model.name }}_impl_dae_hess.c ',...
+ {%- endif %}
+ {%- elif solver_options.integrator_type == "GNSF" %}
+ '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun.c '
+ '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun_jac_y.c '
+ '{{ model.name }}_model/{{ model.name }}_gnsf_phi_jac_y_uhat.c '
+ '{{ model.name }}_model/{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.c '
+ '{{ model.name }}_model/{{ model.name }}_gnsf_get_matrices_fun.c '
+ {%- endif %}
+ ];
+
+INC_PATH = '{{ acados_include_path }}';
+
+INCS = [ ' -I', fullfile(INC_PATH, 'blasfeo', 'include'), ...
+ ' -I', fullfile(INC_PATH, 'hpipm', 'include'), ...
+ ' -I', INC_PATH, ' -I', fullfile(INC_PATH, 'acados'), ' '];
+
+CFLAGS = ' -O';
+
+LIB_PATH = '{{ acados_lib_path }}';
+
+LIBS = '-lacados -lblasfeo -lhpipm';
+
+eval( [ 'mex -v -output acados_sim_solver_sfunction_{{ model.name }} ', ...
+ CFLAGS, INCS, ' ', SOURCES, ' -L', LIB_PATH, ' ', LIBS ]);
+
+fprintf( [ '\n\nSuccessfully created sfunction:\nacados_sim_solver_sfunction_{{ model.name }}', '.', ...
+ eval('mexext')] );
+
+
+%% print note on usage of s-function
+fprintf('\n\nNote: Usage of Sfunction is as follows:\n')
+input_note = 'Inputs are:\n1) x0, initial state, size [{{ dims.nx }}]\n ';
+i_in = 2;
+{%- if dims.nu > 0 %}
+input_note = strcat(input_note, num2str(i_in), ') u, size [{{ dims.nu }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+{%- if dims.np > 0 %}
+input_note = strcat(input_note, num2str(i_in), ') parameters, size [{{ dims.np }}]\n ');
+i_in = i_in + 1;
+{%- endif %}
+
+
+fprintf(input_note)
+
+disp(' ')
+
+output_note = strcat('Outputs are:\n', ...
+ '1) x1 - simulated state, size [{{ dims.nx }}]\n');
+
+fprintf(output_note)
diff --git a/pyextra/acados_template/c_templates_tera/mex_solver.in.m b/pyextra/acados_template/c_templates_tera/mex_solver.in.m
new file mode 100644
index 000000000..728741a46
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/mex_solver.in.m
@@ -0,0 +1,166 @@
+%
+% Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+% Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+% Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+% Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+%
+% This file is part of acados.
+%
+% The 2-Clause BSD License
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions are met:
+%
+% 1. Redistributions of source code must retain the above copyright notice,
+% this list of conditions and the following disclaimer.
+%
+% 2. Redistributions in binary form must reproduce the above copyright notice,
+% this list of conditions and the following disclaimer in the documentation
+% and/or other materials provided with the distribution.
+%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+% POSSIBILITY OF SUCH DAMAGE.;
+%
+
+classdef {{ model.name }}_mex_solver < handle
+
+ properties
+ C_ocp
+ C_ocp_ext_fun
+ cost_ext_fun_type
+ cost_ext_fun_type_e
+ end % properties
+
+
+
+ methods
+
+ % constructor
+ function obj = {{ model.name }}_mex_solver()
+ make_mex_{{ model.name }}();
+ [obj.C_ocp, obj.C_ocp_ext_fun] = acados_mex_create_{{ model.name }}();
+ % to have path to destructor when changing directory
+ addpath('.')
+ obj.cost_ext_fun_type = '{{ cost.cost_ext_fun_type }}';
+ obj.cost_ext_fun_type_e = '{{ cost.cost_ext_fun_type_e }}';
+ end
+
+ % destructor
+ function delete(obj)
+ if ~isempty(obj.C_ocp)
+ acados_mex_free_{{ model.name }}(obj.C_ocp);
+ end
+ end
+
+ % solve
+ function solve(obj)
+ acados_mex_solve_{{ model.name }}(obj.C_ocp);
+ end
+
+ % set -- borrowed from MEX interface
+ function set(varargin)
+ obj = varargin{1};
+ field = varargin{2};
+ value = varargin{3};
+ if ~isa(field, 'char')
+ error('field must be a char vector, use '' ''');
+ end
+ if nargin==3
+ acados_mex_set_{{ model.name }}(obj.cost_ext_fun_type, obj.cost_ext_fun_type_e, obj.C_ocp, obj.C_ocp_ext_fun, field, value);
+ elseif nargin==4
+ stage = varargin{4};
+ acados_mex_set_{{ model.name }}(obj.cost_ext_fun_type, obj.cost_ext_fun_type_e, obj.C_ocp, obj.C_ocp_ext_fun, field, value, stage);
+ else
+ disp('acados_ocp.set: wrong number of input arguments (2 or 3 allowed)');
+ end
+ end
+
+ function value = get_cost(obj)
+ value = ocp_get_cost(obj.C_ocp);
+ end
+
+ % get -- borrowed from MEX interface
+ function value = get(varargin)
+ % usage:
+ % obj.get(field, value, [stage])
+ obj = varargin{1};
+ field = varargin{2};
+ if any(strfind('sens', field))
+ error('field sens* (sensitivities of optimal solution) not yet supported for templated MEX.')
+ end
+ if ~isa(field, 'char')
+ error('field must be a char vector, use '' ''');
+ end
+
+ if nargin==2
+ value = ocp_get(obj.C_ocp, field);
+ elseif nargin==3
+ stage = varargin{3};
+ value = ocp_get(obj.C_ocp, field, stage);
+ else
+ disp('acados_ocp.get: wrong number of input arguments (1 or 2 allowed)');
+ end
+ end
+
+
+ % print
+ function print(varargin)
+ if nargin < 2
+ field = 'stat';
+ else
+ field = varargin{2};
+ end
+
+ obj = varargin{1};
+
+ if strcmp(field, 'stat')
+ stat = obj.get('stat');
+ {%- if solver_options.nlp_solver_type == "SQP" %}
+ fprintf('\niter\tres_stat\tres_eq\t\tres_ineq\tres_comp\tqp_stat\tqp_iter');
+ if size(stat,2)>7
+ fprintf('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp');
+ end
+ fprintf('\n');
+ for jj=1:size(stat,1)
+ fprintf('%d\t%e\t%e\t%e\t%e\t%d\t%d', stat(jj,1), stat(jj,2), stat(jj,3), stat(jj,4), stat(jj,5), stat(jj,6), stat(jj,7));
+ if size(stat,2)>7
+ fprintf('\t%e\t%e\t%e\t%e', stat(jj,8), stat(jj,9), stat(jj,10), stat(jj,11));
+ end
+ fprintf('\n');
+ end
+ fprintf('\n');
+ {%- else %}
+ fprintf('\niter\tqp_status\tqp_iter');
+ if size(stat,2)>3
+ fprintf('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp');
+ end
+ fprintf('\n');
+ for jj=1:size(stat,1)
+ fprintf('%d\t%d\t\t%d', stat(jj,1), stat(jj,2), stat(jj,3));
+ if size(stat,2)>3
+ fprintf('\t%e\t%e\t%e\t%e', stat(jj,4), stat(jj,5), stat(jj,6), stat(jj,7));
+ end
+ fprintf('\n');
+ end
+ {% endif %}
+
+ else
+ fprintf('unsupported field in function print of acados_ocp.print, got %s', field);
+ keyboard
+ end
+
+ end
+
+ end % methods
+
+end % class
+
diff --git a/pyextra/acados_template/c_templates_tera/model.in.h b/pyextra/acados_template/c_templates_tera/model.in.h
new file mode 100644
index 000000000..661811232
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/model.in.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+#ifndef {{ model.name }}_MODEL
+#define {{ model.name }}_MODEL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{%- if solver_options.hessian_approx %}
+ {%- set hessian_approx = solver_options.hessian_approx %}
+{%- elif solver_options.sens_hess %}
+ {%- set hessian_approx = "EXACT" %}
+{%- else %}
+ {%- set hessian_approx = "GAUSS_NEWTON" %}
+{%- endif %}
+
+{% if solver_options.integrator_type == "IRK" or solver_options.integrator_type == "LIFTED_IRK" %}
+// implicit ODE
+int {{ model.name }}_impl_dae_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_impl_dae_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_impl_dae_fun_sparsity_in(int);
+const int *{{ model.name }}_impl_dae_fun_sparsity_out(int);
+int {{ model.name }}_impl_dae_fun_n_in(void);
+int {{ model.name }}_impl_dae_fun_n_out(void);
+
+// implicit ODE
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_z(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_z_work(int *, int *, int *, int *);
+const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_in(int);
+const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_out(int);
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_in(void);
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_out(void);
+
+// implicit ODE
+int {{ model.name }}_impl_dae_jac_x_xdot_u_z(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_impl_dae_jac_x_xdot_u_z_work(int *, int *, int *, int *);
+const int *{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_in(int);
+const int *{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_out(int);
+int {{ model.name }}_impl_dae_jac_x_xdot_u_z_n_in(void);
+int {{ model.name }}_impl_dae_jac_x_xdot_u_z_n_out(void);
+
+// implicit ODE - for lifted_irk
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_u(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_u_work(int *, int *, int *, int *);
+const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_u_sparsity_in(int);
+const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_u_sparsity_out(int);
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_u_n_in(void);
+int {{ model.name }}_impl_dae_fun_jac_x_xdot_u_n_out(void);
+
+{%- if hessian_approx == "EXACT" %}
+int {{ model.name }}_impl_dae_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_impl_dae_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_impl_dae_hess_sparsity_in(int);
+const int *{{ model.name }}_impl_dae_hess_sparsity_out(int);
+int {{ model.name }}_impl_dae_hess_n_in(void);
+int {{ model.name }}_impl_dae_hess_n_out(void);
+{%- endif %}
+
+{% elif solver_options.integrator_type == "GNSF" %}
+/* GNSF Functions */
+// used to import model matrices
+int {{ model.name }}_gnsf_get_matrices_fun(const double** arg, double** res, int* iw, double* w, void *mem);
+int {{ model.name }}_gnsf_get_matrices_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_gnsf_get_matrices_fun_sparsity_in(int);
+const int *{{ model.name }}_gnsf_get_matrices_fun_sparsity_out(int);
+int {{ model.name }}_gnsf_get_matrices_fun_n_in(void);
+int {{ model.name }}_gnsf_get_matrices_fun_n_out(void);
+
+// phi_fun
+int {{ model.name }}_gnsf_phi_fun(const double** arg, double** res, int* iw, double* w, void *mem);
+int {{ model.name }}_gnsf_phi_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_gnsf_phi_fun_sparsity_in(int);
+const int *{{ model.name }}_gnsf_phi_fun_sparsity_out(int);
+int {{ model.name }}_gnsf_phi_fun_n_in(void);
+int {{ model.name }}_gnsf_phi_fun_n_out(void);
+
+// phi_fun_jac_y
+int {{ model.name }}_gnsf_phi_fun_jac_y(const double** arg, double** res, int* iw, double* w, void *mem);
+int {{ model.name }}_gnsf_phi_fun_jac_y_work(int *, int *, int *, int *);
+const int *{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_in(int);
+const int *{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_out(int);
+int {{ model.name }}_gnsf_phi_fun_jac_y_n_in(void);
+int {{ model.name }}_gnsf_phi_fun_jac_y_n_out(void);
+
+// phi_jac_y_uhat
+int {{ model.name }}_gnsf_phi_jac_y_uhat(const double** arg, double** res, int* iw, double* w, void *mem);
+int {{ model.name }}_gnsf_phi_jac_y_uhat_work(int *, int *, int *, int *);
+const int *{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_in(int);
+const int *{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_out(int);
+int {{ model.name }}_gnsf_phi_jac_y_uhat_n_in(void);
+int {{ model.name }}_gnsf_phi_jac_y_uhat_n_out(void);
+
+// f_lo_fun_jac_x1k1uz
+int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz(const double** arg, double** res, int* iw, double* w, void *mem);
+int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_work(int *, int *, int *, int *);
+const int *{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_in(int);
+const int *{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_out(int);
+int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_in(void);
+int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_out(void);
+
+{% elif solver_options.integrator_type == "ERK" %}
+/* explicit ODE */
+
+// explicit ODE
+int {{ model.name }}_expl_ode_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_expl_ode_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_expl_ode_fun_sparsity_in(int);
+const int *{{ model.name }}_expl_ode_fun_sparsity_out(int);
+int {{ model.name }}_expl_ode_fun_n_in(void);
+int {{ model.name }}_expl_ode_fun_n_out(void);
+
+// explicit forward VDE
+int {{ model.name }}_expl_vde_forw(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_expl_vde_forw_work(int *, int *, int *, int *);
+const int *{{ model.name }}_expl_vde_forw_sparsity_in(int);
+const int *{{ model.name }}_expl_vde_forw_sparsity_out(int);
+int {{ model.name }}_expl_vde_forw_n_in(void);
+int {{ model.name }}_expl_vde_forw_n_out(void);
+
+// explicit adjoint VDE
+int {{ model.name }}_expl_vde_adj(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_expl_vde_adj_work(int *, int *, int *, int *);
+const int *{{ model.name }}_expl_vde_adj_sparsity_in(int);
+const int *{{ model.name }}_expl_vde_adj_sparsity_out(int);
+int {{ model.name }}_expl_vde_adj_n_in(void);
+int {{ model.name }}_expl_vde_adj_n_out(void);
+
+{%- if hessian_approx == "EXACT" %}
+int {{ model.name }}_expl_ode_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_expl_ode_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_expl_ode_hess_sparsity_in(int);
+const int *{{ model.name }}_expl_ode_hess_sparsity_out(int);
+int {{ model.name }}_expl_ode_hess_n_in(void);
+int {{ model.name }}_expl_ode_hess_n_out(void);
+{%- endif %}
+
+{% elif solver_options.integrator_type == "DISCRETE" %}
+
+{% if model.dyn_ext_fun_type == "casadi" %}
+int {{ model.name }}_dyn_disc_phi_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_dyn_disc_phi_fun_work(int *, int *, int *, int *);
+const int *{{ model.name }}_dyn_disc_phi_fun_sparsity_in(int);
+const int *{{ model.name }}_dyn_disc_phi_fun_sparsity_out(int);
+int {{ model.name }}_dyn_disc_phi_fun_n_in(void);
+int {{ model.name }}_dyn_disc_phi_fun_n_out(void);
+
+int {{ model.name }}_dyn_disc_phi_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_dyn_disc_phi_fun_jac_work(int *, int *, int *, int *);
+const int *{{ model.name }}_dyn_disc_phi_fun_jac_sparsity_in(int);
+const int *{{ model.name }}_dyn_disc_phi_fun_jac_sparsity_out(int);
+int {{ model.name }}_dyn_disc_phi_fun_jac_n_in(void);
+int {{ model.name }}_dyn_disc_phi_fun_jac_n_out(void);
+
+{%- if hessian_approx == "EXACT" %}
+int {{ model.name }}_dyn_disc_phi_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_dyn_disc_phi_fun_jac_hess_work(int *, int *, int *, int *);
+const int *{{ model.name }}_dyn_disc_phi_fun_jac_hess_sparsity_in(int);
+const int *{{ model.name }}_dyn_disc_phi_fun_jac_hess_sparsity_out(int);
+int {{ model.name }}_dyn_disc_phi_fun_jac_hess_n_in(void);
+int {{ model.name }}_dyn_disc_phi_fun_jac_hess_n_out(void);
+{%- endif %}
+{% else %}
+ {%- if hessian_approx == "EXACT" %}
+int {{ model.dyn_disc_fun_jac_hess }}(void **, void **, void *);
+ {% endif %}
+int {{ model.dyn_disc_fun_jac }}(void **, void **, void *);
+int {{ model.dyn_disc_fun }}(void **, void **, void *);
+{% endif %}
+
+
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_MODEL
diff --git a/pyextra/acados_template/c_templates_tera/phi_constraint.in.h b/pyextra/acados_template/c_templates_tera/phi_constraint.in.h
new file mode 100644
index 000000000..283ed7f88
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/phi_constraint.in.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+ * Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+ * Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+ * Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+ *
+ * This file is part of acados.
+ *
+ * The 2-Clause BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.;
+ */
+
+#ifndef {{ model.name }}_PHI_CONSTRAINT
+#define {{ model.name }}_PHI_CONSTRAINT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if dims.nphi > 0 %}
+// implicit ODE
+int {{ model.name }}_phi_constraint(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_phi_constraint_work(int *, int *, int *, int *);
+const int *{{ model.name }}_phi_constraint_sparsity_in(int);
+const int *{{ model.name }}_phi_constraint_sparsity_out(int);
+int {{ model.name }}_phi_constraint_n_in(void);
+int {{ model.name }}_phi_constraint_n_out(void);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_PHI_CONSTRAINT
diff --git a/pyextra/acados_template/c_templates_tera/phi_e_constraint.in.h b/pyextra/acados_template/c_templates_tera/phi_e_constraint.in.h
new file mode 100644
index 000000000..dc8e293ad
--- /dev/null
+++ b/pyextra/acados_template/c_templates_tera/phi_e_constraint.in.h
@@ -0,0 +1,21 @@
+#ifndef {{ model.name }}_PHI_E_CONSTRAINT
+#define {{ model.name }}_PHI_E_CONSTRAINT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+{% if dims.nphi_e > 0 %}
+int {{ model.name }}_phi_e_constraint(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem);
+int {{ model.name }}_phi_e_constraint_work(int *, int *, int *, int *);
+const int *{{ model.name }}_phi_e_constraint_sparsity_in(int);
+const int *{{ model.name }}_phi_e_constraint_sparsity_out(int);
+int {{ model.name }}_phi_e_constraint_n_in(void);
+int {{ model.name }}_phi_e_constraint_n_out(void);
+{% endif %}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // {{ model.name }}_PHI_E_CONSTRAINT
diff --git a/pyextra/acados_template/generate_c_code_constraint.py b/pyextra/acados_template/generate_c_code_constraint.py
new file mode 100644
index 000000000..93e919c56
--- /dev/null
+++ b/pyextra/acados_template/generate_c_code_constraint.py
@@ -0,0 +1,180 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import os
+from casadi import *
+from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_length, casadi_version_warning
+
+def generate_c_code_constraint( model, con_name, is_terminal, opts ):
+
+ casadi_version = CasadiMeta.version()
+ casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double')
+
+ if casadi_version not in (ALLOWED_CASADI_VERSIONS):
+ casadi_version_warning(casadi_version)
+
+ # load constraint variables and expression
+ x = model.x
+ p = model.p
+
+ if isinstance(x, casadi.MX):
+ symbol = MX.sym
+ else:
+ symbol = SX.sym
+
+ if is_terminal:
+ con_h_expr = model.con_h_expr_e
+ con_phi_expr = model.con_phi_expr_e
+ # create dummy u, z
+ u = symbol('u', 0, 0)
+ z = symbol('z', 0, 0)
+ else:
+ con_h_expr = model.con_h_expr
+ con_phi_expr = model.con_phi_expr
+ u = model.u
+ z = model.z
+
+ if (not is_empty(con_h_expr)) and (not is_empty(con_phi_expr)):
+ raise Exception("acados: you can either have constraint_h, or constraint_phi, not both.")
+
+ if not (is_empty(con_h_expr) and is_empty(con_phi_expr)):
+ if is_empty(con_h_expr):
+ constr_type = 'BGP'
+ else:
+ constr_type = 'BGH'
+
+ if is_empty(p):
+ p = symbol('p', 0, 0)
+
+ if is_empty(z):
+ z = symbol('z', 0, 0)
+
+ if not (is_empty(con_h_expr)) and opts['generate_hess']:
+ # multipliers for hessian
+ nh = casadi_length(con_h_expr)
+ lam_h = symbol('lam_h', nh, 1)
+
+ # set up & change directory
+ code_export_dir = opts["code_export_directory"]
+ if not os.path.exists(code_export_dir):
+ os.makedirs(code_export_dir)
+
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ gen_dir = con_name + '_constraints'
+ if not os.path.exists(gen_dir):
+ os.mkdir(gen_dir)
+ gen_dir_location = './' + gen_dir
+ os.chdir(gen_dir_location)
+
+ # export casadi functions
+ if constr_type == 'BGH':
+ if is_terminal:
+ fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt'
+ else:
+ fun_name = con_name + '_constr_h_fun_jac_uxt_zt'
+
+ jac_ux_t = transpose(jacobian(con_h_expr, vertcat(u,x)))
+ jac_z_t = jacobian(con_h_expr, z)
+ constraint_fun_jac_tran = Function(fun_name, [x, u, z, p], \
+ [con_h_expr, jac_ux_t, jac_z_t])
+
+ constraint_fun_jac_tran.generate(fun_name, casadi_opts)
+ if opts['generate_hess']:
+
+ if is_terminal:
+ fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt_hess'
+ else:
+ fun_name = con_name + '_constr_h_fun_jac_uxt_zt_hess'
+
+ # adjoint
+ adj_ux = jtimes(con_h_expr, vertcat(u, x), lam_h, True)
+ # hessian
+ hess_ux = jacobian(adj_ux, vertcat(u, x))
+
+ adj_z = jtimes(con_h_expr, z, lam_h, True)
+ hess_z = jacobian(adj_z, z)
+
+ # set up functions
+ constraint_fun_jac_tran_hess = \
+ Function(fun_name, [x, u, lam_h, z, p], \
+ [con_h_expr, jac_ux_t, hess_ux, jac_z_t, hess_z])
+
+ # generate C code
+ constraint_fun_jac_tran_hess.generate(fun_name, casadi_opts)
+
+ if is_terminal:
+ fun_name = con_name + '_constr_h_e_fun'
+ else:
+ fun_name = con_name + '_constr_h_fun'
+ h_fun = Function(fun_name, [x, u, z, p], [con_h_expr])
+ h_fun.generate(fun_name, casadi_opts)
+
+ else: # BGP constraint
+ if is_terminal:
+ fun_name = con_name + '_phi_e_constraint'
+ r = model.con_r_in_phi_e
+ con_r_expr = model.con_r_expr_e
+ else:
+ fun_name = con_name + '_phi_constraint'
+ r = model.con_r_in_phi
+ con_r_expr = model.con_r_expr
+
+ nphi = casadi_length(con_phi_expr)
+ con_phi_expr_x_u_z = substitute(con_phi_expr, r, con_r_expr)
+ phi_jac_u = jacobian(con_phi_expr_x_u_z, u)
+ phi_jac_x = jacobian(con_phi_expr_x_u_z, x)
+ phi_jac_z = jacobian(con_phi_expr_x_u_z, z)
+
+ hess = hessian(con_phi_expr[0], r)[0]
+ for i in range(1, nphi):
+ hess = vertcat(hess, hessian(con_phi_expr[i], r)[0])
+
+ r_jac_u = jacobian(con_r_expr, u)
+ r_jac_x = jacobian(con_r_expr, x)
+
+ constraint_phi = \
+ Function(fun_name, [x, u, z, p], \
+ [con_phi_expr_x_u_z, \
+ vertcat(transpose(phi_jac_u), \
+ transpose(phi_jac_x)), \
+ transpose(phi_jac_z), \
+ hess, vertcat(transpose(r_jac_u), \
+ transpose(r_jac_x))])
+
+ constraint_phi.generate(fun_name, casadi_opts)
+
+ # change directory back
+ os.chdir(cwd)
+
+ return
diff --git a/pyextra/acados_template/generate_c_code_discrete_dynamics.py b/pyextra/acados_template/generate_c_code_discrete_dynamics.py
new file mode 100644
index 000000000..531b5ed9d
--- /dev/null
+++ b/pyextra/acados_template/generate_c_code_discrete_dynamics.py
@@ -0,0 +1,99 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+import os
+from casadi import *
+from .utils import ALLOWED_CASADI_VERSIONS, casadi_length, casadi_version_warning
+
+def generate_c_code_discrete_dynamics( model, opts ):
+
+ casadi_version = CasadiMeta.version()
+ casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double')
+
+ if casadi_version not in (ALLOWED_CASADI_VERSIONS):
+ casadi_version_warning(casadi_version)
+
+ # load model
+ x = model.x
+ u = model.u
+ p = model.p
+ phi = model.disc_dyn_expr
+ model_name = model.name
+ nx = x.size()[0]
+
+
+ if isinstance(phi, casadi.MX):
+ symbol = MX.sym
+ elif isinstance(phi, casadi.SX):
+ symbol = SX.sym
+ else:
+ Exception("generate_c_code_disc_dyn: disc_dyn_expr must be a CasADi expression, you have type: {}".format(type(phi)))
+
+ # assume nx1 = nx !!!
+ lam = symbol('lam', nx, 1)
+
+ # generate jacobians
+ ux = vertcat(u,x)
+ jac_ux = jacobian(phi, ux)
+ # generate adjoint
+ adj_ux = jtimes(phi, ux, lam, True)
+ # generate hessian
+ hess_ux = jacobian(adj_ux, ux)
+
+ ## change directory
+ code_export_dir = opts["code_export_directory"]
+ if not os.path.exists(code_export_dir):
+ os.makedirs(code_export_dir)
+
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ model_dir = model_name + '_model'
+ if not os.path.exists(model_dir):
+ os.mkdir(model_dir)
+ model_dir_location = './' + model_dir
+ os.chdir(model_dir_location)
+
+ # set up & generate Functions
+ fun_name = model_name + '_dyn_disc_phi_fun'
+ phi_fun = Function(fun_name, [x, u, p], [phi])
+ phi_fun.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_dyn_disc_phi_fun_jac'
+ phi_fun_jac_ut_xt = Function(fun_name, [x, u, p], [phi, jac_ux.T])
+ phi_fun_jac_ut_xt.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_dyn_disc_phi_fun_jac_hess'
+ phi_fun_jac_ut_xt_hess = Function(fun_name, [x, u, lam, p], [phi, jac_ux.T, hess_ux])
+ phi_fun_jac_ut_xt_hess.generate(fun_name, casadi_opts)
+
+ os.chdir(cwd)
diff --git a/pyextra/acados_template/generate_c_code_explicit_ode.py b/pyextra/acados_template/generate_c_code_explicit_ode.py
new file mode 100644
index 000000000..fb0c020b0
--- /dev/null
+++ b/pyextra/acados_template/generate_c_code_explicit_ode.py
@@ -0,0 +1,124 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import os
+from casadi import *
+from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_version_warning
+
+def generate_c_code_explicit_ode( model, opts ):
+
+ casadi_version = CasadiMeta.version()
+ casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double')
+ if casadi_version not in (ALLOWED_CASADI_VERSIONS):
+ casadi_version_warning(casadi_version)
+
+
+ generate_hess = opts["generate_hess"]
+ code_export_dir = opts["code_export_directory"]
+
+ # load model
+ x = model.x
+ u = model.u
+ p = model.p
+ f_expl = model.f_expl_expr
+ model_name = model.name
+
+ ## get model dimensions
+ nx = x.size()[0]
+ nu = u.size()[0]
+
+ if isinstance(f_expl, casadi.MX):
+ symbol = MX.sym
+ elif isinstance(f_expl, casadi.SX):
+ symbol = SX.sym
+ else:
+ raise Exception("Invalid type for f_expl! Possible types are 'SX' and 'MX'. Exiting.")
+ ## set up functions to be exported
+ Sx = symbol('Sx', nx, nx)
+ Sp = symbol('Sp', nx, nu)
+ lambdaX = symbol('lambdaX', nx, 1)
+
+ fun_name = model_name + '_expl_ode_fun'
+
+ ## Set up functions
+ expl_ode_fun = Function(fun_name, [x, u, p], [f_expl])
+
+ vdeX = jtimes(f_expl,x,Sx)
+ vdeP = jacobian(f_expl,u) + jtimes(f_expl,x,Sp)
+
+ fun_name = model_name + '_expl_vde_forw'
+
+ expl_vde_forw = Function(fun_name, [x, Sx, Sp, u, p], [f_expl, vdeX, vdeP])
+
+ adj = jtimes(f_expl, vertcat(x, u), lambdaX, True)
+
+ fun_name = model_name + '_expl_vde_adj'
+ expl_vde_adj = Function(fun_name, [x, lambdaX, u, p], [adj])
+
+ if generate_hess:
+ S_forw = vertcat(horzcat(Sx, Sp), horzcat(DM.zeros(nu,nx), DM.eye(nu)))
+ hess = mtimes(transpose(S_forw),jtimes(adj, vertcat(x,u), S_forw))
+ hess2 = []
+ for j in range(nx+nu):
+ for i in range(j,nx+nu):
+ hess2 = vertcat(hess2, hess[i,j])
+
+ fun_name = model_name + '_expl_ode_hess'
+ expl_ode_hess = Function(fun_name, [x, Sx, Sp, lambdaX, u, p], [adj, hess2])
+
+ ## generate C code
+ if not os.path.exists(code_export_dir):
+ os.makedirs(code_export_dir)
+
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ model_dir = model_name + '_model'
+ if not os.path.exists(model_dir):
+ os.mkdir(model_dir)
+ model_dir_location = './' + model_dir
+ os.chdir(model_dir_location)
+ fun_name = model_name + '_expl_ode_fun'
+ expl_ode_fun.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_expl_vde_forw'
+ expl_vde_forw.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_expl_vde_adj'
+ expl_vde_adj.generate(fun_name, casadi_opts)
+
+ if generate_hess:
+ fun_name = model_name + '_expl_ode_hess'
+ expl_ode_hess.generate(fun_name, casadi_opts)
+ os.chdir(cwd)
+
+ return
diff --git a/pyextra/acados_template/generate_c_code_external_cost.py b/pyextra/acados_template/generate_c_code_external_cost.py
new file mode 100644
index 000000000..bc21f85f7
--- /dev/null
+++ b/pyextra/acados_template/generate_c_code_external_cost.py
@@ -0,0 +1,110 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import os
+from casadi import SX, MX, Function, transpose, vertcat, horzcat, hessian, CasadiMeta
+from .utils import ALLOWED_CASADI_VERSIONS, casadi_version_warning
+
+
+def generate_c_code_external_cost(model, stage_type, opts):
+
+ casadi_version = CasadiMeta.version()
+ casadi_opts = dict(mex=False, casadi_int="int", casadi_real="double")
+
+ if casadi_version not in (ALLOWED_CASADI_VERSIONS):
+ casadi_version_warning(casadi_version)
+
+ x = model.x
+ p = model.p
+
+ if isinstance(x, MX):
+ symbol = MX.sym
+ else:
+ symbol = SX.sym
+
+ if stage_type == 'terminal':
+ suffix_name = "_cost_ext_cost_e_fun"
+ suffix_name_hess = "_cost_ext_cost_e_fun_jac_hess"
+ suffix_name_jac = "_cost_ext_cost_e_fun_jac"
+ u = symbol("u", 0, 0)
+ ext_cost = model.cost_expr_ext_cost_e
+
+ elif stage_type == 'path':
+ suffix_name = "_cost_ext_cost_fun"
+ suffix_name_hess = "_cost_ext_cost_fun_jac_hess"
+ suffix_name_jac = "_cost_ext_cost_fun_jac"
+ u = model.u
+ ext_cost = model.cost_expr_ext_cost
+
+ elif stage_type == 'initial':
+ suffix_name = "_cost_ext_cost_0_fun"
+ suffix_name_hess = "_cost_ext_cost_0_fun_jac_hess"
+ suffix_name_jac = "_cost_ext_cost_0_fun_jac"
+ u = model.u
+ ext_cost = model.cost_expr_ext_cost_0
+
+ # set up functions to be exported
+ fun_name = model.name + suffix_name
+ fun_name_hess = model.name + suffix_name_hess
+ fun_name_jac = model.name + suffix_name_jac
+
+ # generate expression for full gradient and Hessian
+ full_hess, grad = hessian(ext_cost, vertcat(u, x))
+
+ ext_cost_fun = Function(fun_name, [x, u, p], [ext_cost])
+ ext_cost_fun_jac_hess = Function(
+ fun_name_hess, [x, u, p], [ext_cost, grad, full_hess]
+ )
+ ext_cost_fun_jac = Function(
+ fun_name_jac, [x, u, p], [ext_cost, grad]
+ )
+
+ # generate C code
+ code_export_dir = opts["code_export_directory"]
+ if not os.path.exists(code_export_dir):
+ os.makedirs(code_export_dir)
+
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ gen_dir = model.name + '_cost'
+ if not os.path.exists(gen_dir):
+ os.mkdir(gen_dir)
+ gen_dir_location = "./" + gen_dir
+ os.chdir(gen_dir_location)
+
+ ext_cost_fun.generate(fun_name, casadi_opts)
+ ext_cost_fun_jac_hess.generate(fun_name_hess, casadi_opts)
+ ext_cost_fun_jac.generate(fun_name_jac, casadi_opts)
+
+ os.chdir(cwd)
+ return
diff --git a/pyextra/acados_template/generate_c_code_gnsf.py b/pyextra/acados_template/generate_c_code_gnsf.py
new file mode 100644
index 000000000..3203cbbcc
--- /dev/null
+++ b/pyextra/acados_template/generate_c_code_gnsf.py
@@ -0,0 +1,131 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import os
+from casadi import *
+from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_version_warning
+
+def generate_c_code_gnsf( model, opts ):
+
+ casadi_version = CasadiMeta.version()
+ casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double')
+ if casadi_version not in (ALLOWED_CASADI_VERSIONS):
+ casadi_version_warning(casadi_version)
+
+ model_name = model.name
+ code_export_dir = opts["code_export_directory"]
+
+ # set up directory
+ if not os.path.exists(code_export_dir):
+ os.makedirs(code_export_dir)
+
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ model_dir = model_name + '_model'
+ if not os.path.exists(model_dir):
+ os.mkdir(model_dir)
+ model_dir_location = './' + model_dir
+ os.chdir(model_dir_location)
+
+ # obtain gnsf dimensions
+ get_matrices_fun = model.get_matrices_fun
+ phi_fun = model.phi_fun
+
+ size_gnsf_A = get_matrices_fun.size_out(0)
+ gnsf_nx1 = size_gnsf_A[1]
+ gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1]
+ gnsf_nuhat = max(phi_fun.size_in(1))
+ gnsf_ny = max(phi_fun.size_in(0))
+ gnsf_nout = max(phi_fun.size_out(0))
+
+ # set up expressions
+ # if the model uses MX because of cost/constraints
+ # the DAE can be exported as SX -> detect GNSF in Matlab
+ # -> evaluated SX GNSF functions with MX.
+ u = model.u
+
+ if isinstance(u, casadi.MX):
+ symbol = MX.sym
+ else:
+ symbol = SX.sym
+
+ y = symbol("y", gnsf_ny, 1)
+ uhat = symbol("uhat", gnsf_nuhat, 1)
+ p = model.p
+ x1 = symbol("gnsf_x1", gnsf_nx1, 1)
+ x1dot = symbol("gnsf_x1dot", gnsf_nx1, 1)
+ z1 = symbol("gnsf_z1", gnsf_nz1, 1)
+ dummy = symbol("gnsf_dummy", 1, 1)
+ empty_var = symbol("gnsf_empty_var", 0, 0)
+
+ ## generate C code
+ fun_name = model_name + '_gnsf_phi_fun'
+ phi_fun_ = Function(fun_name, [y, uhat, p], [phi_fun(y, uhat, p)])
+ phi_fun_.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_gnsf_phi_fun_jac_y'
+ phi_fun_jac_y = model.phi_fun_jac_y
+ phi_fun_jac_y_ = Function(fun_name, [y, uhat, p], phi_fun_jac_y(y, uhat, p))
+ phi_fun_jac_y_.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_gnsf_phi_jac_y_uhat'
+ phi_jac_y_uhat = model.phi_jac_y_uhat
+ phi_jac_y_uhat_ = Function(fun_name, [y, uhat, p], phi_jac_y_uhat(y, uhat, p))
+ phi_jac_y_uhat_.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_gnsf_f_lo_fun_jac_x1k1uz'
+ f_lo_fun_jac_x1k1uz = model.f_lo_fun_jac_x1k1uz
+ f_lo_fun_jac_x1k1uz_eval = f_lo_fun_jac_x1k1uz(x1, x1dot, z1, u, p)
+
+ # avoid codegeneration issue
+ if not isinstance(f_lo_fun_jac_x1k1uz_eval, tuple) and is_empty(f_lo_fun_jac_x1k1uz_eval):
+ f_lo_fun_jac_x1k1uz_eval = [empty_var]
+
+ f_lo_fun_jac_x1k1uz_ = Function(fun_name, [x1, x1dot, z1, u, p],
+ f_lo_fun_jac_x1k1uz_eval)
+ f_lo_fun_jac_x1k1uz_.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_gnsf_get_matrices_fun'
+ get_matrices_fun_ = Function(fun_name, [dummy], get_matrices_fun(1))
+ get_matrices_fun_.generate(fun_name, casadi_opts)
+
+ # remove fields for json dump
+ del model.phi_fun
+ del model.phi_fun_jac_y
+ del model.phi_jac_y_uhat
+ del model.f_lo_fun_jac_x1k1uz
+ del model.get_matrices_fun
+
+ os.chdir(cwd)
+
+ return
diff --git a/pyextra/acados_template/generate_c_code_implicit_ode.py b/pyextra/acados_template/generate_c_code_implicit_ode.py
new file mode 100644
index 000000000..e0138c69f
--- /dev/null
+++ b/pyextra/acados_template/generate_c_code_implicit_ode.py
@@ -0,0 +1,139 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import os
+from casadi import *
+from .utils import ALLOWED_CASADI_VERSIONS, is_empty, casadi_length, casadi_version_warning
+
+def generate_c_code_implicit_ode( model, opts ):
+
+ casadi_version = CasadiMeta.version()
+ casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double')
+ if casadi_version not in (ALLOWED_CASADI_VERSIONS):
+ casadi_version_warning(casadi_version)
+
+ generate_hess = opts["generate_hess"]
+ code_export_dir = opts["code_export_directory"]
+
+ ## load model
+ x = model.x
+ xdot = model.xdot
+ u = model.u
+ z = model.z
+ p = model.p
+ f_impl = model.f_impl_expr
+ model_name = model.name
+
+ ## get model dimensions
+ nx = casadi_length(x)
+ nu = casadi_length(u)
+ nz = casadi_length(z)
+
+ ## generate jacobians
+ jac_x = jacobian(f_impl, x)
+ jac_xdot = jacobian(f_impl, xdot)
+ jac_u = jacobian(f_impl, u)
+ jac_z = jacobian(f_impl, z)
+
+ ## generate hessian
+ x_xdot_z_u = vertcat(x, xdot, z, u)
+
+ if isinstance(x, casadi.MX):
+ symbol = MX.sym
+ else:
+ symbol = SX.sym
+
+ multiplier = symbol('multiplier', nx + nz)
+
+ ADJ = jtimes(f_impl, x_xdot_z_u, multiplier, True)
+ HESS = jacobian(ADJ, x_xdot_z_u)
+
+ ## Set up functions
+ p = model.p
+ fun_name = model_name + '_impl_dae_fun'
+ impl_dae_fun = Function(fun_name, [x, xdot, u, z, p], [f_impl])
+
+ fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z'
+ impl_dae_fun_jac_x_xdot_z = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_z])
+
+ # fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z'
+ # impl_dae_fun_jac_x_xdot = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_z])
+
+ # fun_name = model_name + '_impl_dae_jac_x_xdot_u'
+ # impl_dae_jac_x_xdot_u = Function(fun_name, [x, xdot, u, z, p], [jac_x, jac_xdot, jac_u, jac_z])
+
+ fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z'
+ impl_dae_fun_jac_x_xdot_u_z = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u, jac_z])
+
+ fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u'
+ impl_dae_fun_jac_x_xdot_u = Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u])
+
+ fun_name = model_name + '_impl_dae_jac_x_xdot_u_z'
+ impl_dae_jac_x_xdot_u_z = Function(fun_name, [x, xdot, u, z, p], [jac_x, jac_xdot, jac_u, jac_z])
+
+
+ fun_name = model_name + '_impl_dae_hess'
+ impl_dae_hess = Function(fun_name, [x, xdot, u, z, multiplier, p], [HESS])
+
+ # generate C code
+ if not os.path.exists(code_export_dir):
+ os.makedirs(code_export_dir)
+
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ model_dir = model_name + '_model'
+ if not os.path.exists(model_dir):
+ os.mkdir(model_dir)
+ model_dir_location = './' + model_dir
+ os.chdir(model_dir_location)
+
+ fun_name = model_name + '_impl_dae_fun'
+ impl_dae_fun.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z'
+ impl_dae_fun_jac_x_xdot_z.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_impl_dae_jac_x_xdot_u_z'
+ impl_dae_jac_x_xdot_u_z.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z'
+ impl_dae_fun_jac_x_xdot_u_z.generate(fun_name, casadi_opts)
+
+ fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u'
+ impl_dae_fun_jac_x_xdot_u.generate(fun_name, casadi_opts)
+
+ if generate_hess:
+ fun_name = model_name + '_impl_dae_hess'
+ impl_dae_hess.generate(fun_name, casadi_opts)
+
+ os.chdir(cwd)
diff --git a/pyextra/acados_template/generate_c_code_nls_cost.py b/pyextra/acados_template/generate_c_code_nls_cost.py
new file mode 100644
index 000000000..cdb0bf001
--- /dev/null
+++ b/pyextra/acados_template/generate_c_code_nls_cost.py
@@ -0,0 +1,113 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import os
+from casadi import *
+from .utils import ALLOWED_CASADI_VERSIONS, casadi_length, casadi_version_warning
+
+def generate_c_code_nls_cost( model, cost_name, stage_type, opts ):
+
+ casadi_version = CasadiMeta.version()
+ casadi_opts = dict(mex=False, casadi_int='int', casadi_real='double')
+
+ if casadi_version not in (ALLOWED_CASADI_VERSIONS):
+ casadi_version_warning(casadi_version)
+
+ x = model.x
+ p = model.p
+
+ if isinstance(x, casadi.MX):
+ symbol = MX.sym
+ else:
+ symbol = SX.sym
+
+ if stage_type == 'terminal':
+ middle_name = '_cost_y_e'
+ u = symbol('u', 0, 0)
+ cost_expr = model.cost_y_expr_e
+
+ elif stage_type == 'initial':
+ middle_name = '_cost_y_0'
+ u = model.u
+ cost_expr = model.cost_y_expr_0
+
+ elif stage_type == 'path':
+ middle_name = '_cost_y'
+ u = model.u
+ cost_expr = model.cost_y_expr
+
+ # set up directory
+ code_export_dir = opts["code_export_directory"]
+ if not os.path.exists(code_export_dir):
+ os.makedirs(code_export_dir)
+
+ cwd = os.getcwd()
+ os.chdir(code_export_dir)
+ gen_dir = cost_name + '_cost'
+ if not os.path.exists(gen_dir):
+ os.mkdir(gen_dir)
+ gen_dir_location = './' + gen_dir
+ os.chdir(gen_dir_location)
+
+ # set up expressions
+ cost_jac_expr = transpose(jacobian(cost_expr, vertcat(u, x)))
+
+ ny = casadi_length(cost_expr)
+
+ y = symbol('y', ny, 1)
+
+ y_adj = jtimes(cost_expr, vertcat(u, x), y, True)
+ y_hess = jacobian(y_adj, vertcat(u, x))
+
+ ## generate C code
+ suffix_name = '_fun'
+ fun_name = cost_name + middle_name + suffix_name
+ y_fun = Function( fun_name, [x, u, p], \
+ [ cost_expr ])
+ y_fun.generate( fun_name, casadi_opts )
+
+ suffix_name = '_fun_jac_ut_xt'
+ fun_name = cost_name + middle_name + suffix_name
+ y_fun_jac_ut_xt = Function(fun_name, [x, u, p], \
+ [ cost_expr, cost_jac_expr ])
+ y_fun_jac_ut_xt.generate( fun_name, casadi_opts )
+
+ suffix_name = '_hess'
+ fun_name = cost_name + middle_name + suffix_name
+ y_hess = Function(fun_name, [x, u, y, p], [ y_hess ])
+ y_hess.generate( fun_name, casadi_opts )
+
+ os.chdir(cwd)
+
+ return
+
diff --git a/pyextra/acados_template/simulink_default_opts.json b/pyextra/acados_template/simulink_default_opts.json
new file mode 100644
index 000000000..258a224cb
--- /dev/null
+++ b/pyextra/acados_template/simulink_default_opts.json
@@ -0,0 +1,39 @@
+{
+ "outputs": {
+ "u0": 1,
+ "utraj": 0,
+ "xtraj": 0,
+ "solver_status": 1,
+ "KKT_residual": 1,
+ "x1": 1,
+ "CPU_time": 1,
+ "CPU_time_sim": 0,
+ "CPU_time_qp": 0,
+ "CPU_time_lin": 0,
+ "sqp_iter": 1
+ },
+ "inputs": {
+ "lbx_0": 1,
+ "ubx_0": 1,
+ "parameter_traj": 1,
+ "y_ref_0": 1,
+ "y_ref": 1,
+ "y_ref_e": 1,
+ "lbx": 1,
+ "ubx": 1,
+ "lbx_e": 1,
+ "ubx_e": 1,
+ "lbu": 1,
+ "ubu": 1,
+ "lg": 1,
+ "ug": 1,
+ "lh": 1,
+ "uh": 1,
+ "cost_W_0": 0,
+ "cost_W": 0,
+ "cost_W_e": 0,
+ "x_init": 0,
+ "u_init": 0
+ },
+ "samplingtime": "t0"
+}
diff --git a/pyextra/acados_template/utils.py b/pyextra/acados_template/utils.py
new file mode 100644
index 000000000..3f002b98c
--- /dev/null
+++ b/pyextra/acados_template/utils.py
@@ -0,0 +1,440 @@
+#
+# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren,
+# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor,
+# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan,
+# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl
+#
+# This file is part of acados.
+#
+# The 2-Clause BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.;
+#
+
+import os, sys, json
+import urllib.request
+import shutil
+import numpy as np
+from casadi import SX, MX, DM, Function, CasadiMeta
+
+ALLOWED_CASADI_VERSIONS = ('3.5.5', '3.5.4', '3.5.3', '3.5.2', '3.5.1', '3.4.5', '3.4.0')
+
+TERA_VERSION = "0.0.34"
+
+def get_acados_path():
+ ACADOS_PATH = os.environ.get('ACADOS_SOURCE_DIR')
+ if not ACADOS_PATH:
+ acados_template_path = os.path.dirname(os.path.abspath(__file__))
+ acados_path = os.path.join(acados_template_path, '../../../')
+ ACADOS_PATH = os.path.realpath(acados_path)
+ msg = 'Warning: Did not find environment variable ACADOS_SOURCE_DIR, '
+ msg += 'guessed ACADOS_PATH to be {}.\n'.format(ACADOS_PATH)
+ msg += 'Please export ACADOS_SOURCE_DIR to not avoid this warning.'
+ print(msg)
+ return ACADOS_PATH
+
+
+def get_tera_exec_path():
+ TERA_PATH = os.environ.get('TERA_PATH')
+ if not TERA_PATH:
+ TERA_PATH = os.path.join(get_acados_path(), 'bin/t_renderer')
+ return TERA_PATH
+
+
+platform2tera = {
+ "linux": "linux",
+ "darwin": "osx",
+ "win32": "window.exe"
+}
+
+
+def casadi_version_warning(casadi_version):
+ msg = 'Warning: Please note that the following versions of CasADi are '
+ msg += 'officially supported: {}.\n '.format(" or ".join(ALLOWED_CASADI_VERSIONS))
+ msg += 'If there is an incompatibility with the CasADi generated code, '
+ msg += 'please consider changing your CasADi version.\n'
+ msg += 'Version {} currently in use.'.format(casadi_version)
+ print(msg)
+
+
+def is_column(x):
+ if isinstance(x, np.ndarray):
+ if x.ndim == 1:
+ return True
+ elif x.ndim == 2 and x.shape[1] == 1:
+ return True
+ else:
+ return False
+ elif isinstance(x, (MX, SX, DM)):
+ if x.shape[1] == 1:
+ return True
+ elif x.shape[0] == 0 and x.shape[1] == 0:
+ return True
+ else:
+ return False
+ elif x == None or x == []:
+ return False
+ else:
+ raise Exception("is_column expects one of the following types: np.ndarray, casadi.MX, casadi.SX."
+ + " Got: " + str(type(x)))
+
+
+def is_empty(x):
+ if isinstance(x, (MX, SX, DM)):
+ return x.is_empty()
+ elif isinstance(x, np.ndarray):
+ if np.prod(x.shape) == 0:
+ return True
+ else:
+ return False
+ elif x == None or x == []:
+ return True
+ else:
+ raise Exception("is_empty expects one of the following types: casadi.MX, casadi.SX, "
+ + "None, numpy array empty list. Got: " + str(type(x)))
+
+
+def casadi_length(x):
+ if isinstance(x, (MX, SX, DM)):
+ return int(np.prod(x.shape))
+ else:
+ raise Exception("casadi_length expects one of the following types: casadi.MX, casadi.SX."
+ + " Got: " + str(type(x)))
+
+
+def make_model_consistent(model):
+ x = model.x
+ xdot = model.xdot
+ u = model.u
+ z = model.z
+ p = model.p
+
+ if isinstance(x, MX):
+ symbol = MX.sym
+ elif isinstance(x, SX):
+ symbol = SX.sym
+ else:
+ raise Exception("model.x must be casadi.SX or casadi.MX, got {}".format(type(x)))
+
+ if is_empty(p):
+ model.p = symbol('p', 0, 0)
+
+ if is_empty(z):
+ model.z = symbol('z', 0, 0)
+
+ return model
+
+
+def get_tera():
+ tera_path = get_tera_exec_path()
+ acados_path = get_acados_path()
+
+ if os.path.exists(tera_path) and os.access(tera_path, os.X_OK):
+ return tera_path
+
+ repo_url = "https://github.com/acados/tera_renderer/releases"
+ url = "{}/download/v{}/t_renderer-v{}-{}".format(
+ repo_url, TERA_VERSION, TERA_VERSION, platform2tera[sys.platform])
+
+ manual_install = 'For manual installation follow these instructions:\n'
+ manual_install += '1 Download binaries from {}\n'.format(url)
+ manual_install += '2 Copy them in {}/bin\n'.format(acados_path)
+ manual_install += '3 Strip the version and platform from the binaries: '
+ manual_install += 'as t_renderer-v0.0.34-X -> t_renderer)\n'
+ manual_install += '4 Enable execution privilege on the file "t_renderer" with:\n'
+ manual_install += '"chmod +x {}"\n\n'.format(tera_path)
+
+ msg = "\n"
+ msg += 'Tera template render executable not found, '
+ msg += 'while looking in path:\n{}\n'.format(tera_path)
+ msg += 'In order to be able to render the templates, '
+ msg += 'you need to download the tera renderer binaries from:\n'
+ msg += '{}\n\n'.format(repo_url)
+ msg += 'Do you wish to set up Tera renderer automatically?\n'
+ msg += 'y/N? (press y to download tera or any key for manual installation)\n'
+
+ if input(msg) == 'y':
+ print("Dowloading {}".format(url))
+ with urllib.request.urlopen(url) as response, open(tera_path, 'wb') as out_file:
+ shutil.copyfileobj(response, out_file)
+ print("Successfully downloaded t_renderer.")
+ os.chmod(tera_path, 0o755)
+ return tera_path
+
+ msg_cancel = "\nYou cancelled automatic download.\n\n"
+ msg_cancel += manual_install
+ msg_cancel += "Once installed re-run your script.\n\n"
+ print(msg_cancel)
+
+ sys.exit(1)
+
+
+def render_template(in_file, out_file, template_dir, json_path):
+ cwd = os.getcwd()
+ if not os.path.exists(template_dir):
+ os.mkdir(template_dir)
+ os.chdir(template_dir)
+
+ tera_path = get_tera()
+
+ # setting up loader and environment
+ acados_path = os.path.dirname(os.path.abspath(__file__))
+
+ template_glob = acados_path + '/c_templates_tera/*'
+ acados_template_path = acados_path + '/c_templates_tera'
+
+ # call tera as system cmd
+ os_cmd = "{tera_path} '{template_glob}' '{in_file}' '{json_path}' '{out_file}'".format(
+ tera_path=tera_path,
+ template_glob=template_glob,
+ json_path=json_path,
+ in_file=in_file,
+ out_file=out_file
+ )
+ status = os.system(os_cmd)
+ if (status != 0):
+ raise Exception('Rendering of {} failed! Exiting.\n'.format(in_file))
+
+ os.chdir(cwd)
+
+
+## Conversion functions
+def np_array_to_list(np_array):
+ if isinstance(np_array, (np.ndarray)):
+ return np_array.tolist()
+ elif isinstance(np_array, (SX)):
+ return DM(np_array).full()
+ elif isinstance(np_array, (DM)):
+ return np_array.full()
+ else:
+ raise(Exception(
+ "Cannot convert to list type {}".format(type(np_array))
+ ))
+
+
+def format_class_dict(d):
+ """
+ removes the __ artifact from class to dict conversion
+ """
+ out = {}
+ for k, v in d.items():
+ if isinstance(v, dict):
+ v = format_class_dict(v)
+
+ out_key = k.split('__', 1)[-1]
+ out[k.replace(k, out_key)] = v
+ return out
+
+
+def acados_class2dict(class_instance):
+ """
+ removes the __ artifact from class to dict conversion
+ """
+
+ d = dict(class_instance.__dict__)
+ out = {}
+ for k, v in d.items():
+ if isinstance(v, dict):
+ v = format_class_dict(v)
+
+ out_key = k.split('__', 1)[-1]
+ out[k.replace(k, out_key)] = v
+ return out
+
+
+def ocp_check_against_layout(ocp_nlp, ocp_dims):
+ """
+ Check dimensions against layout
+ Parameters
+ ---------
+ ocp_nlp : dict
+ dictionary loaded from JSON to be post-processed.
+
+ ocp_dims : instance of AcadosOcpDims
+ """
+
+ # load JSON layout
+ current_module = sys.modules[__name__]
+ acados_path = os.path.dirname(current_module.__file__)
+ with open(acados_path + '/acados_layout.json', 'r') as f:
+ ocp_nlp_layout = json.load(f)
+
+ ocp_check_against_layout_recursion(ocp_nlp, ocp_dims, ocp_nlp_layout)
+ return
+
+
+def ocp_check_against_layout_recursion(ocp_nlp, ocp_dims, layout):
+
+ for key, item in ocp_nlp.items():
+
+ try:
+ layout_of_key = layout[key]
+ except KeyError:
+ raise Exception("ocp_check_against_layout_recursion: field" \
+ " '{0}' is not in layout but in OCP description.".format(key))
+
+ if isinstance(item, dict):
+ ocp_check_against_layout_recursion(item, ocp_dims, layout_of_key)
+
+ if 'ndarray' in layout_of_key:
+ if isinstance(item, int) or isinstance(item, float):
+ item = np.array([item])
+ if isinstance(item, (list, np.ndarray)) and (layout_of_key[0] != 'str'):
+ dim_layout = []
+ dim_names = layout_of_key[1]
+
+ for dim_name in dim_names:
+ dim_layout.append(ocp_dims[dim_name])
+
+ dims = tuple(dim_layout)
+
+ item = np.array(item)
+ item_dims = item.shape
+ if len(item_dims) != len(dims):
+ raise Exception('Mismatching dimensions for field {0}. ' \
+ 'Expected {1} dimensional array, got {2} dimensional array.' \
+ .format(key, len(dims), len(item_dims)))
+
+ if np.prod(item_dims) != 0 or np.prod(dims) != 0:
+ if dims != item_dims:
+ raise Exception('acados -- mismatching dimensions for field {0}. ' \
+ 'Provided data has dimensions {1}, ' \
+ 'while associated dimensions {2} are {3}' \
+ .format(key, item_dims, dim_names, dims))
+ return
+
+
+def J_to_idx(J):
+ nrows = J.shape[0]
+ idx = np.zeros((nrows, ))
+ for i in range(nrows):
+ this_idx = np.nonzero(J[i,:])[0]
+ if len(this_idx) != 1:
+ raise Exception('Invalid J matrix structure detected, ' \
+ 'must contain one nonzero element per row. Exiting.')
+ if this_idx.size > 0 and J[i,this_idx[0]] != 1:
+ raise Exception('J matrices can only contain 1s. Exiting.')
+ idx[i] = this_idx[0]
+ return idx
+
+
+def J_to_idx_slack(J):
+ nrows = J.shape[0]
+ ncol = J.shape[1]
+ idx = np.zeros((ncol, ))
+ i_idx = 0
+ for i in range(nrows):
+ this_idx = np.nonzero(J[i,:])[0]
+ if len(this_idx) == 1:
+ idx[i_idx] = i
+ i_idx = i_idx + 1
+ elif len(this_idx) > 1:
+ raise Exception('J_to_idx_slack: Invalid J matrix. Exiting. ' \
+ 'Found more than one nonzero in row ' + str(i))
+ if this_idx.size > 0 and J[i,this_idx[0]] != 1:
+ raise Exception('J_to_idx_slack: J matrices can only contain 1s, ' \
+ 'got J(' + str(i) + ', ' + str(this_idx[0]) + ') = ' + str(J[i,this_idx[0]]) )
+ if not i_idx == ncol:
+ raise Exception('J_to_idx_slack: J must contain a 1 in every column!')
+ return idx
+
+
+def acados_dae_model_json_dump(model):
+
+ # load model
+ x = model.x
+ xdot = model.xdot
+ u = model.u
+ z = model.z
+ p = model.p
+
+ f_impl = model.f_impl_expr
+ model_name = model.name
+
+ # create struct with impl_dae_fun, casadi_version
+ fun_name = model_name + '_impl_dae_fun'
+ impl_dae_fun = Function(fun_name, [x, xdot, u, z, p], [f_impl])
+
+ casadi_version = CasadiMeta.version()
+ str_impl_dae_fun = impl_dae_fun.serialize()
+
+ dae_dict = {"str_impl_dae_fun": str_impl_dae_fun, "casadi_version": casadi_version}
+
+ # dump
+ json_file = model_name + '_acados_dae.json'
+ with open(json_file, 'w') as f:
+ json.dump(dae_dict, f, default=np_array_to_list, indent=4, sort_keys=True)
+ print("dumped ", model_name, " dae to file:", json_file, "\n")
+
+
+def set_up_imported_gnsf_model(acados_formulation):
+
+ gnsf = acados_formulation.gnsf_model
+
+ # check CasADi version
+ # dump_casadi_version = gnsf['casadi_version']
+ # casadi_version = CasadiMeta.version()
+
+ # if not casadi_version == dump_casadi_version:
+ # print("WARNING: GNSF model was dumped with another CasADi version.\n"
+ # + "This might yield errors. Please use the same version for compatibility, serialize version: "
+ # + dump_casadi_version + " current Python CasADi verison: " + casadi_version)
+ # input("Press any key to attempt to continue...")
+
+ # load model
+ phi_fun = Function.deserialize(gnsf['phi_fun'])
+ phi_fun_jac_y = Function.deserialize(gnsf['phi_fun_jac_y'])
+ phi_jac_y_uhat = Function.deserialize(gnsf['phi_jac_y_uhat'])
+ get_matrices_fun = Function.deserialize(gnsf['get_matrices_fun'])
+
+ # obtain gnsf dimensions
+ size_gnsf_A = get_matrices_fun.size_out(0)
+ acados_formulation.dims.gnsf_nx1 = size_gnsf_A[1]
+ acados_formulation.dims.gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1]
+ acados_formulation.dims.gnsf_nuhat = max(phi_fun.size_in(1))
+ acados_formulation.dims.gnsf_ny = max(phi_fun.size_in(0))
+ acados_formulation.dims.gnsf_nout = max(phi_fun.size_out(0))
+
+ # save gnsf functions in model
+ acados_formulation.model.phi_fun = phi_fun
+ acados_formulation.model.phi_fun_jac_y = phi_fun_jac_y
+ acados_formulation.model.phi_jac_y_uhat = phi_jac_y_uhat
+ acados_formulation.model.get_matrices_fun = get_matrices_fun
+
+ if "f_lo_fun_jac_x1k1uz" in gnsf:
+ f_lo_fun_jac_x1k1uz = Function.deserialize(gnsf['f_lo_fun_jac_x1k1uz'])
+ acados_formulation.model.f_lo_fun_jac_x1k1uz = f_lo_fun_jac_x1k1uz
+ else:
+ dummy_var_x1 = SX.sym('dummy_var_x1', acados_formulation.dims.gnsf_nx1)
+ dummy_var_x1dot = SX.sym('dummy_var_x1dot', acados_formulation.dims.gnsf_nx1)
+ dummy_var_z1 = SX.sym('dummy_var_z1', acados_formulation.dims.gnsf_nz1)
+ dummy_var_u = SX.sym('dummy_var_z1', acados_formulation.dims.nu)
+ dummy_var_p = SX.sym('dummy_var_z1', acados_formulation.dims.np)
+ empty_var = SX.sym('empty_var', 0, 0)
+
+ empty_fun = Function('empty_fun', \
+ [dummy_var_x1, dummy_var_x1dot, dummy_var_z1, dummy_var_u, dummy_var_p],
+ [empty_var])
+ acados_formulation.model.f_lo_fun_jac_x1k1uz = empty_fun
+
+ del acados_formulation.gnsf_model
diff --git a/rednose/SConscript b/rednose/SConscript
index 36daf2cd7..ca1b28423 100644
--- a/rednose/SConscript
+++ b/rednose/SConscript
@@ -1,4 +1,4 @@
-Import('env', 'envCython', 'arch', 'rednose_config')
+Import('env', 'envCython', 'arch', 'rednose_config', 'common')
generated_folder = rednose_config['generated_folder']
@@ -34,6 +34,7 @@ libkf = env.SharedLibrary(f'{generated_folder}/libkf', lib_target)
lenv = envCython.Clone()
lenv["LINKFLAGS"] += [libkf[0].get_labspath()]
+lenv["LIBS"] = ['zmq', common] + lenv["LIBS"]
ekf_sym_so = lenv.Program('#rednose/helpers/ekf_sym_pyx.so', [ekf_sym_pyx, ekf_sym_cc, common_ekf])
lenv.Depends(ekf_sym_so, libkf)
diff --git a/rednose/helpers/ekf_sym.cc b/rednose/helpers/ekf_sym.cc
index 365a6f989..be3f51609 100644
--- a/rednose/helpers/ekf_sym.cc
+++ b/rednose/helpers/ekf_sym.cc
@@ -1,4 +1,5 @@
#include "ekf_sym.h"
+#include "logger/logger.h"
using namespace EKFS;
using namespace Eigen;
@@ -88,7 +89,7 @@ std::optional EKFSym::predict_and_update_batch(double t, int kind, std
std::deque rewound;
if (!std::isnan(this->filter_time) && t < this->filter_time) {
if (this->rewind_t.empty() || t < this->rewind_t.front() || t < this->rewind_t.back() - this->max_rewind_age) {
- std::cout << "observation too old at " << t << " with filter at " << this->filter_time << ", ignoring" << std::endl;
+ LOGD("observation too old at %d with filter at %d, ignoring!", t, this->filter_time);
return std::nullopt;
}
rewound = this->rewind(t);
diff --git a/rednose/logger/logger.h b/rednose/logger/logger.h
new file mode 100644
index 000000000..e21509352
--- /dev/null
+++ b/rednose/logger/logger.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#ifdef SWAGLOG
+#include "selfdrive/common/swaglog.h"
+#else
+
+#define CLOUDLOG_DEBUG 10
+#define CLOUDLOG_INFO 20
+#define CLOUDLOG_WARNING 30
+#define CLOUDLOG_ERROR 40
+#define CLOUDLOG_CRITICAL 50
+
+#define cloudlog(lvl, fmt, ...) printf(fmt "\n", ## __VA_ARGS__)
+
+#define LOGD(fmt, ...) cloudlog(CLOUDLOG_DEBUG, fmt, ## __VA_ARGS__)
+#define LOG(fmt, ...) cloudlog(CLOUDLOG_INFO, fmt, ## __VA_ARGS__)
+#define LOGW(fmt, ...) cloudlog(CLOUDLOG_WARNING, fmt, ## __VA_ARGS__)
+#define LOGE(fmt, ...) cloudlog(CLOUDLOG_ERROR, fmt, ## __VA_ARGS__)
+
+#endif
diff --git a/release/build_release3.sh b/release/build_release.sh
similarity index 65%
rename from release/build_release3.sh
rename to release/build_release.sh
index 37cea5204..95fcfea1a 100755
--- a/release/build_release3.sh
+++ b/release/build_release.sh
@@ -9,7 +9,17 @@ cd $DIR
BUILD_DIR=/data/openpilot
SOURCE_DIR="$(git rev-parse --show-toplevel)"
-BRANCH=release3-staging
+if [ -f /TICI ]; then
+ FILES_SRC="release/files_tici"
+ RELEASE_BRANCH=release3-staging
+ DASHCAM_BRANCH=dashcam3-staging
+elif [ -f /EON ]; then
+ FILES_SRC="release/files_eon"
+ RELEASE_BRANCH=release2-staging
+ DASHCAM_BRANCH=dashcam-staging
+else
+ exit 0
+fi
# set git identity
source $DIR/identity.sh
@@ -20,13 +30,14 @@ mkdir -p $BUILD_DIR
cd $BUILD_DIR
git init
git remote add origin git@github.com:commaai/openpilot.git
-git checkout -f -B $BRANCH
+git fetch origin $RELEASE_BRANCH
+git checkout --orphan $RELEASE_BRANCH
# do the files copy
echo "[-] copying files T=$SECONDS"
cd $SOURCE_DIR
cp -pR --parents $(cat release/files_common) $BUILD_DIR/
-cp -pR --parents $(cat release/files_tici) $BUILD_DIR/
+cp -pR --parents $(cat $FILES_SRC) $BUILD_DIR/
# in the directory
cd $BUILD_DIR
@@ -39,6 +50,7 @@ echo "#define COMMA_VERSION \"$VERSION-release\"" > selfdrive/common/version.h
echo "[-] committing version $VERSION T=$SECONDS"
git add -f .
git commit -a -m "openpilot v$VERSION release"
+git branch --set-upstream-to=origin/$RELEASE_BRANCH
# Build panda firmware
pushd panda/
@@ -50,15 +62,20 @@ popd
export PYTHONPATH="$BUILD_DIR"
scons -j$(nproc)
-# Run tests
-#python selfdrive/manager/test/test_manager.py
-selfdrive/car/tests/test_car_interfaces.py
+# Ensure no submodules in release
+if test "$(git submodule--helper list | wc -l)" -gt "0"; then
+ echo "submodules found:"
+ git submodule--helper list
+ exit 1
+fi
+git submodule status
# Cleanup
find . -name '*.a' -delete
find . -name '*.o' -delete
find . -name '*.os' -delete
find . -name '*.pyc' -delete
+find . -name 'moc_*' -delete
find . -name '__pycache__' -delete
rm -rf panda/board panda/certs panda/crypto
rm -rf .sconsign.dblite Jenkinsfile release/
@@ -68,8 +85,8 @@ rm models/supercombo.dlc
mkdir -p panda/board/obj
mv /tmp/panda.bin.signed panda/board/obj/panda.bin.signed
-# Restore phonelibs
-git checkout phonelibs/
+# Restore third_party
+git checkout third_party/
# Mark as prebuilt release
touch prebuilt
@@ -78,15 +95,24 @@ touch prebuilt
git add -f .
git commit --amend -m "openpilot v$VERSION"
+# Run tests
+TEST_FILES="tools/"
+cd $SOURCE_DIR
+cp -pR -n --parents $TEST_FILES $BUILD_DIR/
+cd $BUILD_DIR
+RELEASE=1 selfdrive/test/test_onroad.py
+#selfdrive/manager/test/test_manager.py
+selfdrive/car/tests/test_car_interfaces.py
+rm -rf $TEST_FILES
+
if [ ! -z "$PUSH" ]; then
echo "[-] pushing T=$SECONDS"
- git remote set-url origin git@github.com:commaai/openpilot.git
- git push -f origin $BRANCH
+ git push -f origin $RELEASE_BRANCH
# Create dashcam
git rm selfdrive/car/*/carcontroller.py
git commit -m "create dashcam release from release"
- git push -f origin $BRANCH:dashcam3-staging
+ git push -f origin $RELEASE_BRANCH:$DASHCAM_BRANCH
fi
echo "[-] done T=$SECONDS"
diff --git a/release/build_release2.sh b/release/build_release2.sh
deleted file mode 100755
index c607aa820..000000000
--- a/release/build_release2.sh
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-export GIT_COMMITTER_NAME="Vehicle Researcher"
-export GIT_COMMITTER_EMAIL="user@comma.ai"
-export GIT_AUTHOR_NAME="Vehicle Researcher"
-export GIT_AUTHOR_EMAIL="user@comma.ai"
-
-export GIT_SSH_COMMAND="ssh -i /data/gitkey"
-
-# set CLEAN to build outside of CI
-if [ ! -z "$CLEAN" ]; then
- # Create folders
- rm -rf /data/openpilot
- mkdir -p /data/openpilot
- cd /data/openpilot
-
- # Create git repo
- git init
- git remote add origin git@github.com:commaai/openpilot.git
- git fetch origin devel-staging
-else
- cd /data/openpilot
- git clean -xdf
- git branch -D release2-staging || true
-fi
-
-git fetch origin release2-staging
-git fetch origin dashcam-staging
-
-# Create release2 with no history
-if [ ! -z "$CLEAN" ]; then
- git checkout --orphan release2-staging origin/devel-staging
-else
- git checkout --orphan release2-staging
-fi
-
-VERSION=$(cat selfdrive/common/version.h | awk -F[\"-] '{print $2}')
-echo "#define COMMA_VERSION \"$VERSION-release\"" > selfdrive/common/version.h
-
-git commit -m "openpilot v$VERSION"
-
-# Build signed panda firmware
-pushd panda/
-CERT=/tmp/pandaextra/certs/release RELEASE=1 scons -u .
-mv board/obj/panda.bin.signed /tmp/panda.bin.signed
-popd
-
-# Build stuff
-ln -sfn /data/openpilot /data/pythonpath
-export PYTHONPATH="/data/openpilot:/data/openpilot/pyextra"
-scons -j3
-
-# Run tests
-python selfdrive/manager/test/test_manager.py
-selfdrive/car/tests/test_car_interfaces.py
-
-# Ensure no submodules in release
-if test "$(git submodule--helper list | wc -l)" -gt "0"; then
- echo "submodules found:"
- git submodule--helper list
- exit 1
-fi
-git submodule status
-
-# Cleanup
-find . -name '*.a' -delete
-find . -name '*.o' -delete
-find . -name '*.os' -delete
-find . -name '*.pyc' -delete
-find . -name '__pycache__' -delete
-rm -rf panda/board panda/certs panda/crypto
-rm -rf .sconsign.dblite Jenkinsfile release/
-rm models/supercombo.dlc
-
-# Move back signed panda fw
-mkdir -p panda/board/obj
-mv /tmp/panda.bin.signed panda/board/obj/panda.bin.signed
-
-# Restore phonelibs
-git checkout phonelibs/
-
-# Mark as prebuilt release
-touch prebuilt
-
-# Add built files to git
-git add -f .
-git commit --amend -m "openpilot v$VERSION"
-
-# Print committed files that are normally gitignored
-#git status --ignored
-
-if [ ! -z "$PUSH" ]; then
- git remote set-url origin git@github.com:commaai/openpilot.git
-
- # Push to release2-staging
- git push -f origin release2-staging
-
- # Create dashcam release
- git rm selfdrive/car/*/carcontroller.py
-
- git commit -m "create dashcam release from release2"
- git push -f origin release2-staging:dashcam-staging
-fi
diff --git a/release/files_common b/release/files_common
index a025e661b..68c2600c2 100644
--- a/release/files_common
+++ b/release/files_common
@@ -7,10 +7,9 @@ launch_openpilot.sh
Jenkinsfile
SConstruct
-CONTRIBUTING.md
README.md
RELEASES.md
-SAFETY.md
+docs/*
site_scons/site_tools/cython.py
common/.gitignore
@@ -61,6 +60,8 @@ models/dmonitoring_model_q.dlc
release/*
+installer/updater/updater
+
selfdrive/version.py
selfdrive/__init__.py
@@ -96,6 +97,7 @@ selfdrive/car/car_helpers.py
selfdrive/car/fingerprints.py
selfdrive/car/interfaces.py
selfdrive/car/vin.py
+selfdrive/car/disable_ecu.py
selfdrive/car/fw_versions.py
selfdrive/car/isotp_parallel_query.py
selfdrive/car/tests/__init__.py
@@ -188,11 +190,6 @@ selfdrive/debug/*.py
selfdrive/common/SConscript
selfdrive/common/version.h
-selfdrive/common/framebuffer.h
-selfdrive/common/framebuffer.cc
-selfdrive/common/glutil.cc
-selfdrive/common/glutil.h
-selfdrive/common/touch.[c,h]
selfdrive/common/swaglog.h
selfdrive/common/swaglog.cc
selfdrive/common/util.cc
@@ -238,44 +235,25 @@ selfdrive/controls/lib/pid.py
selfdrive/controls/lib/longitudinal_planner.py
selfdrive/controls/lib/radar_helpers.py
selfdrive/controls/lib/vehicle_model.py
-selfdrive/controls/lib/fcw.py
-selfdrive/controls/lib/long_mpc.py
-selfdrive/controls/lib/lead_mpc.py
selfdrive/controls/lib/cluster/*
-selfdrive/controls/lib/lateral_mpc/lib_mpc_export/*
-selfdrive/controls/lib/lateral_mpc/.gitignore
-selfdrive/controls/lib/lateral_mpc/SConscript
-selfdrive/controls/lib/lateral_mpc/__init__.py
-selfdrive/controls/lib/lateral_mpc/generator.cpp
-selfdrive/controls/lib/lateral_mpc/libmpc_py.py
-selfdrive/controls/lib/lateral_mpc/lateral_mpc.c
-
-selfdrive/controls/lib/lead_mpc_lib/lib_mpc_export/*
-selfdrive/controls/lib/lead_mpc_lib/.gitignore
-selfdrive/controls/lib/lead_mpc_lib/SConscript
-selfdrive/controls/lib/lead_mpc_lib/__init__.py
-selfdrive/controls/lib/lead_mpc_lib/generator.cpp
-selfdrive/controls/lib/lead_mpc_lib/libmpc_py.py
-selfdrive/controls/lib/lead_mpc_lib/longitudinal_mpc.c
-
-selfdrive/controls/lib/longitudinal_mpc_lib/lib_mpc_export/*
+selfdrive/controls/lib/lateral_mpc_lib/.gitignore
selfdrive/controls/lib/longitudinal_mpc_lib/.gitignore
-selfdrive/controls/lib/longitudinal_mpc_lib/SConscript
-selfdrive/controls/lib/longitudinal_mpc_lib/__init__.py
-selfdrive/controls/lib/longitudinal_mpc_lib/generator.cpp
-selfdrive/controls/lib/longitudinal_mpc_lib/libmpc_py.py
-selfdrive/controls/lib/longitudinal_mpc_lib/longitudinal_mpc.c
+selfdrive/controls/lib/lateral_mpc_lib/*
+selfdrive/controls/lib/longitudinal_mpc_lib/*
selfdrive/hardware/__init__.py
selfdrive/hardware/base.h
selfdrive/hardware/base.py
selfdrive/hardware/hw.h
selfdrive/hardware/eon/__init__.py
+selfdrive/hardware/eon/androidd.py
selfdrive/hardware/eon/hardware.h
selfdrive/hardware/eon/hardware.py
-selfdrive/hardware/eon/androidd.py
+selfdrive/hardware/eon/neos.py
+selfdrive/hardware/eon/neos.json
+selfdrive/hardware/eon/updater
selfdrive/hardware/tici/__init__.py
selfdrive/hardware/tici/hardware.py
selfdrive/hardware/tici/amplifier.py
@@ -369,6 +347,9 @@ selfdrive/ui/qt/widgets/*.h
selfdrive/ui/qt/spinner_aarch64
selfdrive/ui/qt/text_aarch64
+selfdrive/ui/replay/framereader.cc
+selfdrive/ui/replay/framereader.h
+
selfdrive/camerad/SConscript
selfdrive/camerad/main.cc
@@ -380,6 +361,8 @@ selfdrive/camerad/cameras/camera_frame_stream.cc
selfdrive/camerad/cameras/camera_frame_stream.h
selfdrive/camerad/cameras/camera_qcom.cc
selfdrive/camerad/cameras/camera_qcom.h
+selfdrive/camerad/cameras/camera_replay.cc
+selfdrive/camerad/cameras/camera_replay.h
selfdrive/camerad/cameras/debayer.cl
selfdrive/camerad/cameras/sensor_i2c.h
selfdrive/camerad/cameras/sensor2_i2c.h
@@ -444,56 +427,56 @@ selfdrive/assets/assets.qrc
selfdrive/assets/*.png
selfdrive/assets/*.svg
selfdrive/assets/fonts/*.ttf
+selfdrive/assets/icons/*
selfdrive/assets/images/*
selfdrive/assets/offroad/*
selfdrive/assets/sounds/*
selfdrive/assets/training/*
-phonelibs/SConscript
+third_party/SConscript
-phonelibs/nanovg/*.c
-phonelibs/nanovg/*.h
+third_party/nanovg/*.c
+third_party/nanovg/*.h
-phonelibs/libgralloc/**
-phonelibs/linux/**
-phonelibs/opencl/**
-phonelibs/zlib/*
-phonelibs/bzip2/*
-phonelibs/openmax/**
+third_party/libgralloc/**
+third_party/linux/**
+third_party/opencl/**
+third_party/zlib/*
+third_party/bzip2/*
+third_party/openmax/**
-phonelibs/json11/json11.cpp
-phonelibs/json11/json11.hpp
+third_party/json11/json11.cpp
+third_party/json11/json11.hpp
-phonelibs/qpoases/**
+third_party/qrcode/*.cc
+third_party/qrcode/*.hpp
-phonelibs/qrcode/*.cc
-phonelibs/qrcode/*.hpp
+third_party/kaitai/*.h
+third_party/kaitai/*.cpp
-phonelibs/kaitai/*.h
-phonelibs/kaitai/*.cpp
+third_party/libyuv/include/**
+third_party/libyuv/lib/**
+third_party/libyuv/larch64/**
-phonelibs/libyuv/include/**
-phonelibs/libyuv/lib/**
-phonelibs/libyuv/larch64/**
+third_party/snpe/include/**
+third_party/snpe/aarch64**
+third_party/snpe/larch64**
+third_party/snpe/dsp**
-phonelibs/snpe/include/**
-phonelibs/snpe/aarch64**
-phonelibs/snpe/larch64**
-phonelibs/snpe/dsp**
+third_party/acados/x86_64/**
+third_party/acados/aarch64/**
+third_party/acados/larch64/**
+third_party/acados/include/**
-phonelibs/android_frameworks_native/**
-phonelibs/android_hardware_libhardware/**
-phonelibs/android_system_core/**
-
-installer/updater/updater
-installer/updater/updater.cc
-installer/updater/update.json
-installer/updater/Makefile
+third_party/android_frameworks_native/**
+third_party/android_hardware_libhardware/**
+third_party/android_system_core/**
scripts/update_now.sh
scripts/stop_updater.sh
pyextra/.gitignore
+pyextra/acados_template/**
rednose/**
@@ -588,6 +571,7 @@ opendbc/honda_insight_ex_2019_can_generated.dbc
opendbc/acura_ilx_2016_nidec.dbc
opendbc/hyundai_kia_generic.dbc
+opendbc/hyundai_kia_mando_front_radar.dbc
opendbc/mazda_2017.dbc
diff --git a/release/files_eon b/release/files_eon
new file mode 100644
index 000000000..b43bf86b5
--- /dev/null
+++ b/release/files_eon
@@ -0,0 +1 @@
+README.md
diff --git a/release/files_pc b/release/files_pc
index 1b57f97a7..2f55599c2 100644
--- a/release/files_pc
+++ b/release/files_pc
@@ -1,3 +1,3 @@
-phonelibs/mapbox-gl-native-qt/x86_64/**
+third_party/mapbox-gl-native-qt/x86_64/**
-phonelibs/qt-plugins/x86_64/**
+third_party/qt-plugins/x86_64/**
diff --git a/release/files_tici b/release/files_tici
index cf5184a58..b5a2e5b7a 100644
--- a/release/files_tici
+++ b/release/files_tici
@@ -1,4 +1,4 @@
-phonelibs/mapbox-gl-native-qt/include/*
+third_party/mapbox-gl-native-qt/include/*
selfdrive/timezoned.py
diff --git a/selfdrive/assets/assets.qrc b/selfdrive/assets/assets.qrc
index 1fc6d3591..39be41aa6 100644
--- a/selfdrive/assets/assets.qrc
+++ b/selfdrive/assets/assets.qrc
@@ -5,8 +5,10 @@
img_circled_slash.svg
img_eye_open.svg
img_eye_closed.svg
+ icons/close.svg
offroad/icon_lock_closed.svg
offroad/icon_checkmark.svg
+ offroad/icon_warning.png
offroad/icon_wifi_strength_low.svg
offroad/icon_wifi_strength_medium.svg
offroad/icon_wifi_strength_high.svg
diff --git a/selfdrive/assets/fonts/courbd.ttf b/selfdrive/assets/fonts/courbd.ttf
deleted file mode 100644
index a4f26b4b5..000000000
Binary files a/selfdrive/assets/fonts/courbd.ttf and /dev/null differ
diff --git a/selfdrive/assets/icons/close.svg b/selfdrive/assets/icons/close.svg
new file mode 100644
index 000000000..b1e6d3b86
--- /dev/null
+++ b/selfdrive/assets/icons/close.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/selfdrive/assets/images/battery.png b/selfdrive/assets/images/battery.png
deleted file mode 100644
index cac3b9096..000000000
Binary files a/selfdrive/assets/images/battery.png and /dev/null differ
diff --git a/selfdrive/assets/images/battery_charging.png b/selfdrive/assets/images/battery_charging.png
deleted file mode 100644
index 4c25566d0..000000000
Binary files a/selfdrive/assets/images/battery_charging.png and /dev/null differ
diff --git a/selfdrive/assets/img_trafficLight_green.png b/selfdrive/assets/img_trafficLight_green.png
deleted file mode 100644
index b2e07dab0..000000000
Binary files a/selfdrive/assets/img_trafficLight_green.png and /dev/null differ
diff --git a/selfdrive/assets/img_trafficLight_none.png b/selfdrive/assets/img_trafficLight_none.png
deleted file mode 100644
index 01deb5a00..000000000
Binary files a/selfdrive/assets/img_trafficLight_none.png and /dev/null differ
diff --git a/selfdrive/assets/img_trafficLight_red.png b/selfdrive/assets/img_trafficLight_red.png
deleted file mode 100644
index 4c440250e..000000000
Binary files a/selfdrive/assets/img_trafficLight_red.png and /dev/null differ
diff --git a/selfdrive/assets/img_trafficLight_yellow.png b/selfdrive/assets/img_trafficLight_yellow.png
deleted file mode 100644
index 8dd5bd42c..000000000
Binary files a/selfdrive/assets/img_trafficLight_yellow.png and /dev/null differ
diff --git a/selfdrive/assets/img_trafficSign_stop.png b/selfdrive/assets/img_trafficSign_stop.png
deleted file mode 100644
index 9261c4747..000000000
Binary files a/selfdrive/assets/img_trafficSign_stop.png and /dev/null differ
diff --git a/selfdrive/assets/img_trafficSign_turn.png b/selfdrive/assets/img_trafficSign_turn.png
deleted file mode 100644
index c304d1bf2..000000000
Binary files a/selfdrive/assets/img_trafficSign_turn.png and /dev/null differ
diff --git a/selfdrive/assets/offroad/icon_app_store.png b/selfdrive/assets/offroad/icon_app_store.png
deleted file mode 100644
index ae0dd95ce..000000000
Binary files a/selfdrive/assets/offroad/icon_app_store.png and /dev/null differ
diff --git a/selfdrive/assets/offroad/icon_connect_app.png b/selfdrive/assets/offroad/icon_connect_app.png
deleted file mode 100644
index cd216d3e6..000000000
Binary files a/selfdrive/assets/offroad/icon_connect_app.png and /dev/null differ
diff --git a/selfdrive/assets/offroad/icon_eon.png b/selfdrive/assets/offroad/icon_eon.png
deleted file mode 100644
index 72856c4e6..000000000
Binary files a/selfdrive/assets/offroad/icon_eon.png and /dev/null differ
diff --git a/selfdrive/assets/offroad/icon_play_store.png b/selfdrive/assets/offroad/icon_play_store.png
deleted file mode 100644
index 1eca9d589..000000000
Binary files a/selfdrive/assets/offroad/icon_play_store.png and /dev/null differ
diff --git a/selfdrive/assets/offroad/icon_user.png b/selfdrive/assets/offroad/icon_user.png
deleted file mode 100644
index 9b653cc4b..000000000
Binary files a/selfdrive/assets/offroad/icon_user.png and /dev/null differ
diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py
index 4c656756b..fadbad0bf 100755
--- a/selfdrive/athena/athenad.py
+++ b/selfdrive/athena/athenad.py
@@ -253,7 +253,7 @@ def uploadFileToUrl(fn, url, headers):
@dispatcher.add_method
def listUploadQueue():
items = list(upload_queue.queue) + list(cur_upload_items.values())
- return [i._asdict() for i in items if i is not None]
+ return [i._asdict() for i in items if (i is not None) and (i.id not in cancelled_uploads)]
@dispatcher.add_method
diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc
index 3f09ec949..edf5e5e8e 100644
--- a/selfdrive/boardd/boardd.cc
+++ b/selfdrive/boardd/boardd.cc
@@ -9,9 +9,11 @@
#include
#include
#include
+#include
#include
#include
#include
+#include