/**
 * Enables to register observation model and store it
 * @param {String} name
 * @callback fn the function corresponding to the desired model
 */
declare function registerObservation(name: string, fn: any): void;
/**
 * Enables to register dynamic model and store it
 * @param {String} name
 * @callback fn the function corresponding to the desired model
 */
declare function registerDynamic(name: string, fn: any): void;
/**
 * Build a model given an observation configuration
 * @param {ObservationConfig} observation
 * @returns {ObservationConfig} the configuration with respect to the model
 */
declare function buildObservation(observation: any): any;
/**
 * Build a model given dynamic and observation configurations
 * @param {DynamicConfig} dynamic
 * @param {ObservationConfig} observation
 * @returns {DynamicConfig} the dynamic configuration with respect to the model
 */
declare function buildDynamic(dynamic: any, observation: any): any;

/**
* Creates a dynamic model, following constant position model with respect with the dimensions provided in the observation parameters
* @param {DynamicConfig} dynamic
* @param {ObservationConfig} observation
* @returns {DynamicConfig}
*/
declare function constantPosition(dynamic: any, observation: any): any;

/**
*Creates a dynamic model, following constant position model with respect with the dimensions provided in the observation parameters
* @param {DynamicConfig} dynamic
* @param {ObservationConfig} observation
* @returns {DynamicConfig}
*/
declare function constantSpeed(dynamic: any, observation: any): any;

/**
* Creates a dynamic model, following constant acceleration model with respect with the dimensions provided in the observation parameters
* @param {DynamicConfig} dynamic
* @param {ObservationConfig} observation
* @returns {DynamicConfig}
*/
declare function constantAcceleration(dynamic: any, observation: any): any;

/**
* @typedef {Object.<DynamicName, DynamicConfig>} PerNameConfigs
*/
/**
* @typedef {Object} DynamicConfig
* @param {Array.<Number>} obsIndexes
* @param {Covariance} staticCovariance
*/
/**
* Creates a dynamic model, considering the null in order to make the predictions
* @param {Object} main
* @param {Object.<String, DynamicConfig>} main.perName
* @param {ObservationConfig} observation
* @param {Array.<Array.<Number>>} opts.observedProjection
* @returns {DynamicConfig}
*/
declare function composition({ perName }: {
    perName: any;
}, observation: any): {
    dimension: any;
    init: {
        index: number;
        mean: any[];
        covariance: any[][];
    };
    transition(options: any): any[][];
    covariance(options: any): any[][];
};

/**
* Creates a dynamic model, considering the null in order to make the predictions
* @param {Array.<Array.<Number>>} staticCovariance generated with moving average
* @param {Number} observationDimension
* @returns {DynamicConfig}
*/
declare function constantPositionWithNull({ staticCovariance, obsDynaIndexes, init }: {
    staticCovariance: any;
    obsDynaIndexes: any;
    init: any;
}): {
    dimension: any;
    transition(): number[][];
    covariance({ previousCorrected, index }: {
        previousCorrected: any;
        index: any;
    }): any;
    init: any;
};

interface StateLT {
    mean: number[][];
    covariance: number[][];
    index?: number;
}

interface Observation {
    name: string;
}
type PreviousCorrectedCallback = (opts: {
    index: number;
    previousCorrected?: StateLT;
    predicted: StateLT;
    variance?: number[];
}) => number[][];
type PredictedCallback = (opts: {
    index: number;
    previousCorrected?: StateLT;
    predicted: StateLT;
    observation?: Observation;
}) => number[][];
interface WinstonLogger {
    info: (...args: any[]) => void;
    debug: (...args: any[]) => void;
    warn: (...args: any[]) => void;
    error: (...args: any[]) => void;
}
interface DynamicConfig {
    /**
     * named this config.
     */
    name?: string;
    dimension?: number;
    /**
     * a function that returns the control parameter B_k*u_k of the kalman filter
     */
    constant?: PreviousCorrectedCallback;
    /**
     * for extended kalman filter only, the non-linear state-transition model
     */
    fn?: PreviousCorrectedCallback;
    /**
     * the state-transition model (or for EKF the jacobian of the fn)
     */
    transition: number[][] | PredictedCallback;
    /**
     * covariance the covariance of the process noise
     */
    covariance: number[] | number[][] | PredictedCallback;
    /**
     *
     */
    init: StateLT;
    timeStep?: number;
}
interface CoreConfig {
    /**
     * dynamic the system's dynamic model
     */
    dynamic: DynamicConfig;
    /**
     *  the system's observation model
     */
    observation: ObservationConfig;
    /**
     * a Winston-like logger
     */
    logger?: WinstonLogger;
}
interface ObservationConfig {
    sensorDimension?: number;
    dimension: number;
    nSensors?: number;
    observedProjection?: any;
    fn?: PredictedCallback;
    /**
     * stateProjection the matrix to transform state to observation (for EKF, the jacobian of the fn)
     */
    stateProjection?: number | number[] | number[][] | PreviousCorrectedCallback;
    /**
     * covariance the covariance of the observation noise
     */
    covariance: number[] | number[][] | PreviousCorrectedCallback;
    sensorCovariance?: number[];
    name?: 'sensor' | string;
}

declare class CoreKalmanFilter {
    dynamic: DynamicConfig;
    observation: ObservationConfig;
    logger: WinstonLogger;
    constructor(options: CoreConfig);
    getValue(fn: number[][] | PreviousCorrectedCallback | PredictedCallback, options: any): number[][];
    getInitState(): State;
    /**
    This will return the predicted covariance of a given previousCorrected State, this will help us to build the asymptoticState.
    * @param {State} previousCorrected
    * @returns{Array.<Array.<Number>>}
    */
    getPredictedCovariance(options?: {
        previousCorrected?: State;
        index?: number;
    }): number[][];
    predictMean(o: {
        opts: any;
        transition: number[][];
    }): number[][];
    predictMeanWithoutControl(args: {
        opts: any;
        transition: number[][];
    }): number[][];
    /**
    This will return the new prediction, relatively to the dynamic model chosen
    * @param {State} previousCorrected State relative to our dynamic model
    * @returns{State} predicted State
    */
    predict(options?: {
        previousCorrected?: State;
        index?: number;
        observation?: number[] | number[][];
    }): State;
    /**
     * This will return the new correction, taking into account the prediction made
     * and the observation of the sensor
     * param {State} predicted the previous State
     * @param options
     * @returns kalmanGain
     */
    getGain(options: {
        predicted: State;
        stateProjection?: number[][];
    }): number[][];
    /**
     * This will return the corrected covariance of a given predicted State, this will help us to build the asymptoticState.
     * @param {State} predicted the previous State
     * @returns{Array.<Array.<Number>>}
     */
    getCorrectedCovariance(options: {
        predicted: State;
        optimalKalmanGain?: any;
        stateProjection?: any;
    }): number[][];
    getPredictedObservation(args: {
        opts: any;
        stateProjection: number[][];
    }): number[][];
    /**
    This will return the new correction, taking into account the prediction made
    and the observation of the sensor
    * @param {State} predicted the previous State
    * @param {Array} observation the observation of the sensor
    * @returns{State} corrected State of the Kalman Filter
    */
    correct(options: {
        predicted: any;
        observation: any;
    }): State;
}

declare class KalmanFilter extends CoreKalmanFilter {
    /**
    * @typedef {Object} Config
    * @property {DynamicObjectConfig | DynamicNonObjectConfig} dynamic
    * @property {ObservationObjectConfig | ObservationNonObjectConfig} observation
    */
    /**
    * @param {Config} options
    */
    constructor(options?: {
        observation?: any | {
            name: string;
        };
        dynamic?: any | {
            name: string;
        };
        logger?: WinstonLogger;
    });
    correct(options: {
        predicted: State;
        observation: number[] | number[][];
    }): State;
    /**
    * Performs the prediction and the correction steps
    * @param {State} previousCorrected
    * @param {<Array.<Number>>} observation
    * @returns {Array.<Number>} the mean of the corrections
    */
    filter(options: {
        previousCorrected?: State;
        index?: number;
        observation: number[] | number[][];
    }): State;
    /**
     * Filters all the observations
     * @param {Array.<Array.<Number>>} observations
     * @returns {Array.<Array.<Number>>} the mean of the corrections
     */
    filterAll(observations: any): number[][];
    /**
    * Returns an estimation of the asymptotic state covariance as explained in https://en.wikipedia.org/wiki/Kalman_filter#Asymptotic_form
    * in practice this can be used as a init.covariance value but is very costful calculation (that's why this is not made by default)
    * @param {Number} [limitIterations=1e2] max number of iterations
    * @param {Number} [tolerance=1e-6] returns when the last values differences are less than tolerance
    * @return {Array.<Array.<Number>>} covariance
    */
    asymptoticStateCovariance({ limitIterations, tolerance }?: {
        limitIterations?: number;
        tolerance?: number;
    }): number[][];
    /**
    * Returns an estimation of the asymptotic gain, as explained in https://en.wikipedia.org/wiki/Kalman_filter#Asymptotic_form
    * @param {Number} [tolerance=1e-6] returns when the last values differences are less than tolerance
    * @return {Array.<Array.<Number>>} gain
    */
    asymptoticGain({ tolerance }?: {
        tolerance?: number;
    }): number[][];
}

/**
 * Class representing a multi dimensionnal gaussian, with his mean and his covariance
 * @property {Number} [index=0] the index of the State in the process, this is not mandatory for simple Kalman Filter, but is needed for most of the use case of extended kalman filter
 * @property {Array.<Array.<Number>>} covariance square matrix of size dimension
 * @property {Array.<Array<Number>>} mean column matrix of size dimension x 1
 */
declare class State implements StateLT {
    mean: number[][];
    covariance: number[][];
    index: number | undefined;
    constructor(args: {
        mean: number[][];
        covariance: number[][];
        index?: number;
    });
    /**
    * Check the consistency of the State
    * @param {Object} options
    * @see check
    */
    check(options?: {
        dimension?: number | null;
        title?: string;
        eigen?: boolean;
    }): void;
    /**
    * Check the consistency of the State's attributes
    * @param {State} state
    * @param {Object} [options={}]
    * @param {Array} [options.dimension=null] if defined check the dimension of the state
    * @param {String} [options.title=null] used to log error mor explicitly
    * @param {Boolean} options.eigen
    * @returns {Null}
    */
    static check(state: State, args?: {
        dimension?: number | null;
        title?: string;
        eigen?: boolean;
    }): void;
    /**
    * Multiply state with matrix
    * @param {State} state
    * @param {Array.<Array.<Number>>} matrix
    * @returns {State}
    */
    static matMul(args: {
        state: State;
        matrix: number[][];
    }): State;
    /**
    * From a state in n-dimension create a state in a subspace
    * If you see the state as a N-dimension gaussian,
    * this can be viewed as the sub M-dimension gaussian (M < N)
    * @param {Array.<Number>} obsIndexes list of dimension to extract,  (M < N <=> obsIndexes.length < this.mean.length)
    * @returns {State} subState in subspace, with subState.mean.length === obsIndexes.length
    */
    subState(obsIndexes: number[]): State;
    /**
    * @typedef {Object} DetailedMahalanobis
    * @property {Array.<[Number]>} diff
    * @property {Array.<Array.<Number>>} covarianceInvert
    * @property {Number} value
    */
    /**
    * Simple Malahanobis distance between the distribution (this) and a point
    * @param {Array.<[Number]>} point a Nx1 matrix representing a point
    * @returns {DetailedMahalanobis}
    */
    rawDetailedMahalanobis(point: number[][]): {
        diff: number[][];
        covarianceInvert: number[][];
        value: number;
    };
    /**
    * Malahanobis distance is made against an observation, so the mean and covariance
    * are projected into the observation space
    * @param {KalmanFilter} kf kalman filter use to project the state in observation's space
    * @param {Observation} observation
    * @param {Array.<Number>} obsIndexes list of indexes of observation state to use for the mahalanobis distance
    * @returns {DetailedMahalanobis}
    */
    detailedMahalanobis(args: {
        kf: KalmanFilter;
        observation: number[][] | number[];
        obsIndexes?: number[];
    }): {
        diff: number[][];
        covarianceInvert: number[][];
        value: number;
    };
    /**
    * @param {Object} options @see detailedMahalanobis
    * @returns {Number}
    */
    mahalanobis(options: {
        kf: KalmanFilter;
        observation: number[][] | number[];
        obsIndexes?: number[];
    }): number;
    /**
    * Bhattacharyya distance is made against in the observation space
    * to do it in the normal space see state.bhattacharyya
    * @param {KalmanFilter} kf kalman filter use to project the state in observation's space
    * @param {State} state
    * @param {Array.<Number>} obsIndexes list of indexes of observation state to use for the bhattacharyya distance
    * @returns {Number}
    */
    obsBhattacharyya(options: {
        kf: KalmanFilter;
        state: State;
        obsIndexes: number[];
    }): number;
    /**
    * @param {State} otherState other state to compare with
    * @returns {Number}
    */
    bhattacharyya(otherState: State): number;
}

/**
* Creates a dynamic model, considering the null in order to make the predictions
* @param {ObservationConfig} observation
* @returns {DynamicConfig}
*/
declare function constantSpeedDynamic(args: {
    staticCovariance: number[];
    avSpeed: number[];
    center: number[];
}, observation: any): {
    init: {
        mean: number[][];
        covariance: number[][];
        index: number;
    };
    dimension: number;
    transition: (args: {
        getTime: (index: number) => number;
        index: number;
        previousCorrected: State;
    }) => number[][];
    covariance: (args: {
        index: number;
        previousCorrected: State;
        getTime: (index: number) => number;
    }) => number[][];
};

/**
* This model is based on the constant speed model
* The constant speed model creates problems when dT >> fps (the track is lost)
* then the expected position can be very far from the center of the field
* to solve that, we use a model with 2 more hidden variable that are always center of the field
* When dT << typicalTime the model acts exactly as a constant speed model
* When dT >> typicalTime the model is a constant [x,y] = center model, sigma = defaultVariance
* @param {Object} options
* @param {ObservationConfig} observation
* @param {Number} [options.typicalTime=10]
* @returns {DynamicConfig}
*/
declare function shorttermConstantSpeed(options: any, observation: any): {
    dimension: number;
    init: {
        mean: number[][];
        covariance: number[][];
        index: number;
    };
    transition(options: {
        getTime: (index: number) => number;
        index: number;
        previousCorrected: State;
    }): number[][];
    covariance(options: {
        getTime: (index: number) => number;
        index: number;
        previousCorrected: State;
    }, observation: any): number[][];
};

declare function sensor(options: any): ObservationConfig;

/**
* @param {Object} options
* @param {Number} options.sensorDimension
* @param {CovarianceParam} options.sensorCovariance
* @param {Number} options.nSensors
* @returns {ObservationConfig}
*/
declare function nullableSensor(options: any): ObservationConfig;

/**
*Creates an observation model with a observedProjection corresponding to
* @param {DynamicConfig} dynamic
* @param {ObservationConfig} observation
* @returns {DynamicConfig}
*/
declare function sensorProjected({ selectedCovariance, totalDimension, obsIndexes, selectedStateProjection }: {
    selectedCovariance: any;
    totalDimension: any;
    obsIndexes: any;
    selectedStateProjection: any;
}): {
    dimension: any;
    observedProjection: number[][];
    covariance(o: any): any;
};

/**
* @param {Object} opts
* @param {Array.<Array.<Number>>} opts.measures a list of measure, size is LxN L the number of sample, N the dimension
* @param {Array.<Array.<Number>>} opts.averages a list of averages, size is LxN L the number of sample, N the dimension
* @returns {Array.<Array.<Number>>} covariance matrix size is NxN
*/
declare function getCovariance({ measures, averages }: {
    measures: any;
    averages: any;
}): number[][];

declare function checkCovariance(args: {
    covariance: number[][];
    eigen?: boolean;
}, _title?: string): void;

declare function correlationToCovariance({ correlation, variance }: {
    correlation: any;
    variance: any;
}): any;

declare function covarianceToCorrelation(covariance: any): {
    variance: any;
    correlation: any;
};

declare function projectObservation({ observation, obsIndexes, selectedStateProjection, invertSelectedStateProjection }: {
    observation: any;
    obsIndexes: any;
    selectedStateProjection: any;
    invertSelectedStateProjection: any;
}): number[];

export { KalmanFilter, State, buildDynamic, buildObservation, checkCovariance, composition, constantAcceleration, constantPosition, constantPositionWithNull, constantSpeed, constantSpeedDynamic, correlationToCovariance, covarianceToCorrelation, getCovariance, projectObservation, registerDynamic, registerObservation, sensor, nullableSensor as sensorLocalVariance, sensorProjected, shorttermConstantSpeed };
