2011-10-14 02:41:56 +08:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
|
2019-02-11 22:39:48 +08:00
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
2011-10-14 02:41:56 +08:00
|
|
|
* Atlanta, Georgia 30332-0415
|
|
|
|
* All Rights Reserved
|
|
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
|
|
|
|
* See LICENSE for the license information
|
|
|
|
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
2011-10-14 11:23:14 +08:00
|
|
|
* @file Argument.h
|
|
|
|
* @brief arguments to constructors and methods
|
|
|
|
* @author Frank Dellaert
|
2012-06-27 02:52:27 +08:00
|
|
|
* @author Andrew Melim
|
2012-07-13 06:28:28 +08:00
|
|
|
* @author Richard Roberts
|
2011-10-14 02:41:56 +08:00
|
|
|
**/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2014-11-14 00:28:05 +08:00
|
|
|
#include "TemplateSubstitution.h"
|
2014-05-26 01:29:06 +08:00
|
|
|
#include "FileWriter.h"
|
2014-05-26 02:35:07 +08:00
|
|
|
#include "ReturnValue.h"
|
2014-05-26 01:29:06 +08:00
|
|
|
|
2011-12-03 00:43:15 +08:00
|
|
|
namespace wrap {
|
|
|
|
|
2011-10-14 12:43:06 +08:00
|
|
|
/// Argument class
|
2011-10-14 02:41:56 +08:00
|
|
|
struct Argument {
|
2014-11-12 09:49:23 +08:00
|
|
|
Qualified type;
|
2012-10-02 22:40:07 +08:00
|
|
|
std::string name;
|
2014-11-30 23:08:42 +08:00
|
|
|
bool is_const, is_ref, is_ptr;
|
2012-01-10 13:06:46 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
Argument() :
|
|
|
|
is_const(false), is_ref(false), is_ptr(false) {
|
|
|
|
}
|
2011-10-14 12:43:06 +08:00
|
|
|
|
2014-11-30 23:08:42 +08:00
|
|
|
Argument(const Qualified& t, const std::string& n) :
|
|
|
|
type(t), name(n), is_const(false), is_ref(false), is_ptr(false) {
|
|
|
|
}
|
|
|
|
|
2016-11-23 01:13:33 +08:00
|
|
|
bool isSameSignature(const Argument& other) const {
|
2016-09-14 05:11:23 +08:00
|
|
|
return type == other.type
|
|
|
|
&& is_const == other.is_const && is_ref == other.is_ref
|
|
|
|
&& is_ptr == other.is_ptr;
|
|
|
|
}
|
|
|
|
|
2014-11-30 23:08:42 +08:00
|
|
|
bool operator==(const Argument& other) const {
|
|
|
|
return type == other.type && name == other.name
|
|
|
|
&& is_const == other.is_const && is_ref == other.is_ref
|
|
|
|
&& is_ptr == other.is_ptr;
|
|
|
|
}
|
|
|
|
|
2014-11-14 00:28:05 +08:00
|
|
|
Argument expandTemplate(const TemplateSubstitution& ts) const;
|
2014-11-13 19:52:41 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
/// return MATLAB class for use in isa(x,class)
|
|
|
|
std::string matlabClass(const std::string& delim = "") const;
|
2012-01-10 13:06:46 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
/// MATLAB code generation, MATLAB to C++
|
|
|
|
void matlab_unwrap(FileWriter& file, const std::string& matlabName) const;
|
2014-11-14 04:11:29 +08:00
|
|
|
|
2014-11-30 04:11:13 +08:00
|
|
|
/**
|
|
|
|
* emit checking argument to MATLAB proxy
|
|
|
|
* @param proxyFile output stream
|
|
|
|
*/
|
2014-11-30 04:43:48 +08:00
|
|
|
void proxy_check(FileWriter& proxyFile, const std::string& s) const;
|
2014-11-30 04:11:13 +08:00
|
|
|
|
2016-09-09 01:33:32 +08:00
|
|
|
/**
|
|
|
|
* emit arguments for cython pxd
|
|
|
|
* @param file output stream
|
|
|
|
*/
|
2016-12-16 13:23:45 +08:00
|
|
|
void emit_cython_pxd(FileWriter& file, const std::string& className,
|
|
|
|
const std::vector<std::string>& templateArgs) const;
|
2016-09-10 03:52:44 +08:00
|
|
|
void emit_cython_pyx(FileWriter& file) const;
|
2016-11-20 22:24:43 +08:00
|
|
|
std::string pyx_asParam() const;
|
convert numpy input params to dtype float and order 'F' automatically
using numpy.astype(...). No copy if the params are already in the correct dtype and storage order.
For a function
f(Matrix A, Matrix B),
simply wrapping it to pyx as
f(A.astype(float, order='F', copy=False), B.astype(float, order='F', copy=False))
won't work.
It produces a strange side-effect that the content of A is overwritten by B and the two inputs are the same (data address) inside the function!
This is because Cython decreases the ref count for the temporary variable resulted from A.astype(...) before generates the wrap for B.astype(...).
Hence, the A.astype temp var is probably reused for B.astype, and they were pointing to the same data address.
For that reason, we have to go a longer route and wrap it as:
A = A.astype(float, order='F', copy=False)
B = B.astype(float, order='F', copy=False)
f(A, B)
For future ref., here is a sample of the wrongly generated code that wraps the JacobianFactor constructor:
Jacobian(Key i1, Matrix A1, Key i2, Matrix A2, Vector b, noiseModel::Diagonal model)
Wrongly wrapped pyx code:
self.shared_CJacobianFactor_ = shared_ptr[CJacobianFactor](new CJacobianFactor(i1, <MatrixXd>(Map[MatrixXd](A1.astype(float, order='F',copy=False)), i2, <MatrixXd>(Map[MatrixXd](A2.astype(float, order='F', copy=False)), <VectorXd>(Map[VectorXd](b.astype(float, order='F', copy=False))), model.shared_CnoiseModel_Diagonal_))
The problematic Cython generated CPP code with a comment on the problematic line:
/////////////////////////////////////////
// WRONG VERSION
/////////////////////////////////////////
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A1), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_14 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
///////////////////////////////////////////////
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; //<------- Problematic line!!! Killing this will result in the correct result!
///////////////////////////////////////////////
__pyx_t_13 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A2), __pyx_n_s_astype); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_13, __pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_15 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_12));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_b), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_16 = eigency::Map<Eigen::VectorXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
try {
__pyx_t_17 = new gtsam::JacobianFactor(__pyx_v_i1, ((Eigen::MatrixXd)__pyx_t_14), __pyx_v_i2, ((Eigen::MatrixXd)__pyx_t_15), ((Eigen::VectorXd)__pyx_t_16), __pyx_v_model->shared_CnoiseModel_Diagonal_);
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__pyx_v_self->shared_CJacobianFactor_ = boost::shared_ptr<gtsam::JacobianFactor> (__pyx_t_17);
2017-03-16 01:47:11 +08:00
|
|
|
std::string pyx_convertEigenTypeAndStorageOrder() const;
|
2016-09-09 01:33:32 +08:00
|
|
|
|
2014-11-14 04:11:29 +08:00
|
|
|
friend std::ostream& operator<<(std::ostream& os, const Argument& arg) {
|
|
|
|
os << (arg.is_const ? "const " : "") << arg.type << (arg.is_ptr ? "*" : "")
|
|
|
|
<< (arg.is_ref ? "&" : "");
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2011-10-14 02:41:56 +08:00
|
|
|
};
|
|
|
|
|
2012-01-10 13:06:46 +08:00
|
|
|
/// Argument list is just a container with Arguments
|
2011-12-09 04:51:15 +08:00
|
|
|
struct ArgumentList: public std::vector<Argument> {
|
2012-01-10 13:06:46 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
/// create a comma-separated string listing all argument types (not used)
|
|
|
|
std::string types() const;
|
2012-01-10 13:06:46 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
/// create a short "signature" string
|
|
|
|
std::string signature() const;
|
2012-01-10 13:06:46 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
/// create a comma-separated string listing all argument names, used in m-files
|
|
|
|
std::string names() const;
|
2011-10-14 12:43:06 +08:00
|
|
|
|
2014-05-26 03:21:13 +08:00
|
|
|
/// Check if all arguments scalar
|
|
|
|
bool allScalar() const;
|
|
|
|
|
2014-11-14 00:28:05 +08:00
|
|
|
ArgumentList expandTemplate(const TemplateSubstitution& ts) const;
|
2014-11-13 19:52:41 +08:00
|
|
|
|
2016-11-23 01:13:33 +08:00
|
|
|
bool isSameSignature(const ArgumentList& other) const {
|
2019-02-11 22:39:48 +08:00
|
|
|
for(size_t i = 0; i<size(); ++i)
|
2016-11-23 01:13:33 +08:00
|
|
|
if (!at(i).isSameSignature(other[i])) return false;
|
2016-09-14 05:11:23 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
// MATLAB code generation:
|
2011-10-14 12:43:06 +08:00
|
|
|
|
2012-10-02 22:40:07 +08:00
|
|
|
/**
|
|
|
|
* emit code to unwrap arguments
|
|
|
|
* @param file output stream
|
|
|
|
* @param start initial index for input array, set to 1 for method
|
|
|
|
*/
|
|
|
|
void matlab_unwrap(FileWriter& file, int start = 0) const; // MATLAB to C++
|
2012-06-27 02:52:27 +08:00
|
|
|
|
2014-05-26 01:01:36 +08:00
|
|
|
/**
|
|
|
|
* emit MATLAB prototype
|
|
|
|
* @param file output stream
|
|
|
|
* @param name of method or function
|
|
|
|
*/
|
|
|
|
void emit_prototype(FileWriter& file, const std::string& name) const;
|
|
|
|
|
2016-09-09 01:33:32 +08:00
|
|
|
/**
|
|
|
|
* emit arguments for cython pxd
|
|
|
|
* @param file output stream
|
|
|
|
*/
|
2016-12-16 13:23:45 +08:00
|
|
|
void emit_cython_pxd(FileWriter& file, const std::string& className,
|
|
|
|
const std::vector<std::string>& templateArgs) const;
|
2016-09-10 03:52:44 +08:00
|
|
|
void emit_cython_pyx(FileWriter& file) const;
|
2016-11-20 22:24:43 +08:00
|
|
|
std::string pyx_asParams() const;
|
|
|
|
std::string pyx_paramsList() const;
|
2017-08-07 02:07:13 +08:00
|
|
|
std::string pyx_castParamsToPythonType(const std::string& indent) const;
|
convert numpy input params to dtype float and order 'F' automatically
using numpy.astype(...). No copy if the params are already in the correct dtype and storage order.
For a function
f(Matrix A, Matrix B),
simply wrapping it to pyx as
f(A.astype(float, order='F', copy=False), B.astype(float, order='F', copy=False))
won't work.
It produces a strange side-effect that the content of A is overwritten by B and the two inputs are the same (data address) inside the function!
This is because Cython decreases the ref count for the temporary variable resulted from A.astype(...) before generates the wrap for B.astype(...).
Hence, the A.astype temp var is probably reused for B.astype, and they were pointing to the same data address.
For that reason, we have to go a longer route and wrap it as:
A = A.astype(float, order='F', copy=False)
B = B.astype(float, order='F', copy=False)
f(A, B)
For future ref., here is a sample of the wrongly generated code that wraps the JacobianFactor constructor:
Jacobian(Key i1, Matrix A1, Key i2, Matrix A2, Vector b, noiseModel::Diagonal model)
Wrongly wrapped pyx code:
self.shared_CJacobianFactor_ = shared_ptr[CJacobianFactor](new CJacobianFactor(i1, <MatrixXd>(Map[MatrixXd](A1.astype(float, order='F',copy=False)), i2, <MatrixXd>(Map[MatrixXd](A2.astype(float, order='F', copy=False)), <VectorXd>(Map[VectorXd](b.astype(float, order='F', copy=False))), model.shared_CnoiseModel_Diagonal_))
The problematic Cython generated CPP code with a comment on the problematic line:
/////////////////////////////////////////
// WRONG VERSION
/////////////////////////////////////////
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A1), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_14 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
///////////////////////////////////////////////
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; //<------- Problematic line!!! Killing this will result in the correct result!
///////////////////////////////////////////////
__pyx_t_13 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A2), __pyx_n_s_astype); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_13, __pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_15 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_12));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_b), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_16 = eigency::Map<Eigen::VectorXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
try {
__pyx_t_17 = new gtsam::JacobianFactor(__pyx_v_i1, ((Eigen::MatrixXd)__pyx_t_14), __pyx_v_i2, ((Eigen::MatrixXd)__pyx_t_15), ((Eigen::VectorXd)__pyx_t_16), __pyx_v_model->shared_CnoiseModel_Diagonal_);
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__pyx_v_self->shared_CJacobianFactor_ = boost::shared_ptr<gtsam::JacobianFactor> (__pyx_t_17);
2017-03-16 01:47:11 +08:00
|
|
|
std::string pyx_convertEigenTypeAndStorageOrder(const std::string& indent) const;
|
2016-09-09 01:33:32 +08:00
|
|
|
|
2014-05-26 02:35:07 +08:00
|
|
|
/**
|
2014-11-30 03:53:38 +08:00
|
|
|
* emit checking arguments to MATLAB proxy
|
2014-11-13 03:51:47 +08:00
|
|
|
* @param proxyFile output stream
|
2014-05-26 02:59:20 +08:00
|
|
|
*/
|
2014-11-30 04:11:13 +08:00
|
|
|
void proxy_check(FileWriter& proxyFile) const;
|
2014-11-14 04:11:29 +08:00
|
|
|
|
2014-11-30 03:53:38 +08:00
|
|
|
/// Output stream operator
|
2014-11-14 04:11:29 +08:00
|
|
|
friend std::ostream& operator<<(std::ostream& os,
|
|
|
|
const ArgumentList& argList) {
|
|
|
|
os << "(";
|
|
|
|
if (argList.size() > 0)
|
|
|
|
os << argList.front();
|
|
|
|
if (argList.size() > 1)
|
|
|
|
for (size_t i = 1; i < argList.size(); i++)
|
|
|
|
os << ", " << argList[i];
|
|
|
|
os << ")";
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2011-10-14 02:41:56 +08:00
|
|
|
};
|
|
|
|
|
2014-12-01 03:25:26 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html
|
|
|
|
struct ArgumentGrammar: public classic::grammar<ArgumentGrammar> {
|
|
|
|
|
|
|
|
wrap::Argument& result_; ///< successful parse will be placed in here
|
2014-12-02 03:03:26 +08:00
|
|
|
TypeGrammar argument_type_g; ///< Type parser for Argument::type
|
2014-12-01 03:25:26 +08:00
|
|
|
|
|
|
|
/// Construct type grammar and specify where result is placed
|
|
|
|
ArgumentGrammar(wrap::Argument& result) :
|
|
|
|
result_(result), argument_type_g(result.type) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Definition of type grammar
|
|
|
|
template<typename ScannerT>
|
2014-12-02 03:03:26 +08:00
|
|
|
struct definition: BasicRules<ScannerT> {
|
2014-12-01 03:25:26 +08:00
|
|
|
|
|
|
|
typedef classic::rule<ScannerT> Rule;
|
|
|
|
|
2014-12-02 03:03:26 +08:00
|
|
|
Rule argument_p;
|
2014-12-01 03:25:26 +08:00
|
|
|
|
|
|
|
definition(ArgumentGrammar const& self) {
|
|
|
|
using namespace classic;
|
|
|
|
|
|
|
|
// NOTE: allows for pointers to all types
|
|
|
|
// Slightly more permissive than before on basis/eigen type qualification
|
|
|
|
// Also, currently parses Point2*&, can't make it work otherwise :-(
|
|
|
|
argument_p = !str_p("const")[assign_a(self.result_.is_const, T)] //
|
|
|
|
>> self.argument_type_g //
|
|
|
|
>> !ch_p('*')[assign_a(self.result_.is_ptr, T)]
|
|
|
|
>> !ch_p('&')[assign_a(self.result_.is_ref, T)]
|
2014-12-02 03:03:26 +08:00
|
|
|
>> BasicRules<ScannerT>::name_p[assign_a(self.result_.name)];
|
2014-12-01 03:25:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Rule const& start() const {
|
|
|
|
return argument_p;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
// ArgumentGrammar
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html
|
|
|
|
struct ArgumentListGrammar: public classic::grammar<ArgumentListGrammar> {
|
|
|
|
|
|
|
|
wrap::ArgumentList& result_; ///< successful parse will be placed in here
|
|
|
|
|
|
|
|
/// Construct type grammar and specify where result is placed
|
|
|
|
ArgumentListGrammar(wrap::ArgumentList& result) :
|
2014-12-02 18:24:53 +08:00
|
|
|
result_(result) {
|
2014-12-01 03:25:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Definition of type grammar
|
|
|
|
template<typename ScannerT>
|
2014-12-02 03:03:26 +08:00
|
|
|
struct definition {
|
2014-12-01 03:25:26 +08:00
|
|
|
|
2014-12-02 18:24:53 +08:00
|
|
|
const Argument arg0; ///< used to reset arg
|
|
|
|
Argument arg; ///< temporary argument for use during parsing
|
|
|
|
ArgumentGrammar argument_g; ///< single Argument parser
|
|
|
|
|
2014-12-02 03:03:26 +08:00
|
|
|
classic::rule<ScannerT> argument_p, argumentList_p;
|
2014-12-01 03:25:26 +08:00
|
|
|
|
2014-12-02 18:24:53 +08:00
|
|
|
definition(ArgumentListGrammar const& self) :
|
|
|
|
argument_g(arg) {
|
2014-12-01 03:25:26 +08:00
|
|
|
using namespace classic;
|
2014-12-02 03:03:26 +08:00
|
|
|
|
2014-12-02 18:24:53 +08:00
|
|
|
argument_p = argument_g //
|
|
|
|
[classic::push_back_a(self.result_, arg)] //
|
|
|
|
[assign_a(arg, arg0)];
|
2014-12-02 03:03:26 +08:00
|
|
|
|
2014-12-01 03:25:26 +08:00
|
|
|
argumentList_p = '(' >> !argument_p >> *(',' >> argument_p) >> ')';
|
|
|
|
}
|
|
|
|
|
2014-12-02 03:03:26 +08:00
|
|
|
classic::rule<ScannerT> const& start() const {
|
2014-12-01 03:25:26 +08:00
|
|
|
return argumentList_p;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
// ArgumentListGrammar
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
|
|
|
|
}// \namespace wrap
|
2011-12-03 00:43:15 +08:00
|
|
|
|