1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! # CasADi Rust interface
//!
//! This is a Rust interface to C functions generated by Rust
//!
//! This is a `no-std` library (however, mind that the CasADi-generated code
//! requires `libm` to call functions such as `sqrt`, `sin`, etc...)

#![no_std]

// Get the CasADi problem size and parameter size and re-export them, this is necessary to have
// them available as compile time constants
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

/// Number of static parameters
pub use CASADI_NP as NUM_STATIC_PARAMETERS;

/// Number of decision variables
pub use CASADI_NU as NUM_DECISION_VARIABLES;

use libc::{c_double, c_int};

extern "C" {
    fn icasadi_cost_(
        u: *const c_double,
        casadi_static_params: *const c_double,
        cost_value: *mut c_double,
    ) -> c_int;

    fn icasadi_grad_(
        u: *const c_double,
        casadi_static_params: *const c_double,
        cost_jacobian: *mut c_double,
    ) -> c_int;

    fn icasadi_constraints_as_penalty_(
        u: *const c_double,
        casadi_static_params: *const c_double,
        constraints_as_penalty: *mut c_double,
    ) -> c_int;

}

///
/// Consume the cost function written in C
///
/// # Example
/// ```
/// fn tst_call_casadi_cost() {
///     let u = [1.0, 2.0, 3.0, -5.0, 1.0, 10.0, 14.0, 17.0, 3.0, 5.0];
///     let p = [1.0, -1.0];
///     let mut cost_value = 0.0;
///     icasadi::icasadi_cost(&u, &p, &mut cost_value);
/// }
/// ```
///
/// # Panics
/// This method does not panic (on purpose). However, users need to be
/// careful when providing the arguments `u` and `casadi_static_params`
/// as they must be arrays of appropriate size.
///
/// As a safety measure, you may check whether
///
/// - `u.len() >= NUM_DECISION_VARIABLES`
/// - `casadi_static_params.len() >= NUM_STATIC_PARAMETERS`
///
pub fn icasadi_cost(u: &[f64], casadi_static_params: &[f64], cost_value: &mut f64) -> c_int {
    unsafe { icasadi_cost_(u.as_ptr(), casadi_static_params.as_ptr(), cost_value) }
}

///
/// Consume the Jacobian function written in C
///
/// # Example
/// ```
/// fn tst_call_casadi_cost() {
///     let u = [1.0, 2.0, 3.0, -5.0, 1.0, 10.0, 14.0, 17.0, 3.0, 5.0];
///     let p = [1.0, -1.0];
///     let mut jac = [0.0; 10];
///     icasadi::icasadi_grad(&u, &p, &mut jac);
/// }
/// ```
///
/// # Panics
/// This method does not panic (on purpose). However, users need to be
/// careful when providing the arguments `u` and `casadi_static_params`
/// as they must be arrays of appropriate size.
///
/// As a safety measure, you may check whether
///
/// - `u.len() >= icasadi::num_decision_variables()`
/// - `casadi_static_params.len() >= icasadi::num_static_parameters()`
/// - `cost_jacobian.len() >= icasadi::num_decision_variables()`
///
pub fn icasadi_grad(u: &[f64], casadi_static_params: &[f64], cost_jacobian: &mut [f64]) -> c_int {
    unsafe {
        icasadi_grad_(
            u.as_ptr(),
            casadi_static_params.as_ptr(),
            cost_jacobian.as_mut_ptr(),
        )
    }
}

pub fn icasadi_constraints_as_penalty(u: &[f64], casadi_static_params: &[f64], constraints_as_penalty: &mut [f64]) -> c_int {
    unsafe {
        icasadi_constraints_as_penalty_(
            u.as_ptr(),
            casadi_static_params.as_ptr(),
            constraints_as_penalty.as_mut_ptr(),
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn tst_num_static() {
        let _np = NUM_STATIC_PARAMETERS;
    }

    #[test]
    fn tst_num_decision_var() {
        let _nu = NUM_DECISION_VARIABLES;
    }

}