Noxious
Noxious

Reputation: 87

Embedding Python into C++ calling two functions and passing array around

I'm trying to embedding python functions into my c++ code for doing some symbolic and algebraic operations.

My idea: I want to create a matrix with symbolic variables depending on some input variables. This matrix I want to use afterwards in another function. This function is generating some coordinates out of the symbolic matrix. And i want then to pass this results to my c++ code back.

My problem: I have a problem to get this matrix out of python to my c++ code and back to the other function as input. Because i want to pass the symbolic matrix via c++ to the other python function which should generate out of this matrix the results. Just to try my python code and the integration into c++ i wrote the code below.

Edit: To make my question more specific I wrote the whole work I want to do with this functions in Python. To clarify I need one function which is generating the symbolic matrix and the other has to calculate the values. And for the calculation the values are coming from the inside of my C++ code.

Here the example written in Python:

from sympy import *
import numpy as np


def main():
    start_pos = [1,2,3]
    end_pos = [4,5,6]

    generic_function = generate_symbolic_transformation(start_pos,end_pos)
    calculate_symbolic_transformation(generic_function,90,0.5);

# Calculation of the symbolic transformation depending on the input
def calculate_symbolic_transformation(generic_function,thetay_value,k_value):
    thetay = symbols('thetay')
    k = symbols('k')
    transf_matrix = MatrixSymbol('tm',4,4)
    transf_matrix = Matrix(transf_matrix)
    transf_matrix = sympify(generic_function)
    transf_matrix = transf_matrix.subs([(thetay,thetay_value),(k,k_value)])
    print transf_matrix
    return 1

# Generation of the symbolic transformation depending on the input
def generate_symbolic_transformation(Start_pos_coords,End_pos_coords):

    # Symbolic startposition
    Start_pos = MatrixSymbol('S',3,1)
    Start_pos = Matrix(Start_pos)
    Start_pos[0] = Start_pos_coords[0]
    Start_pos[1] = Start_pos_coords[1]
    Start_pos[2] = Start_pos_coords[2]

    print Start_pos

    # Symbolic endposition
    End_pos = MatrixSymbol('E',3,1)
    End_pos = Matrix(End_pos)
    End_pos[0] = End_pos_coords[0]
    End_pos[1] = End_pos_coords[1]
    End_pos[2] = End_pos_coords[2]

    print End_pos

    # Symbolic rotation matric
    R = MatrixSymbol('R',3,3)

    # Symbolic transformation matric
    T = MatrixSymbol('T',4,4)

    # Necessary symbolic variabls
    k = symbols('k')
    thetax = symbols('thetax')
    thetay = symbols('thetay')
    thetaz = symbols('thetaz')

    # For rotation of EulerAngles RzRyRx:
    Rx = MatrixSymbol('Rx',3,3)
    Ry = MatrixSymbol('Ry',3,3)
    Rz = MatrixSymbol('Rz',3,3)

    # Filling Rx rotation matric
    #   |   1           0                   0         |
    #   |   0       -cos(thetax)      sin(thetax)     |
    #   |   0        sin(thetax)      cos(thetax)     |

    Rx = Matrix(Rx)
    Rx[0,0] = 1
    Rx[0,1] = 0
    Rx[0,2] = 0
    Rx[1,0] = 0
    Rx[1,1] = cos(thetax)
    Rx[1,2] = -sin(thetax)
    Rx[2,0] = 0
    Rx[2,1] = sin(thetax)
    Rx[2,2] = cos(thetax)

    # Filling Ry rotation matric
    #   |    cos(thetay)        0      sin(thetay)     |
    #   |          0            1           0          |
    #   |   -sin(thetay)        0      cos(thetay)     |

    Ry = Matrix(Ry)
    Ry[0,0] = cos(thetay)
    Ry[0,1] = 0
    Ry[0,2] = sin(thetay)
    Ry[1,0] = 0
    Ry[1,1] = 1
    Ry[1,2] = 0
    Ry[2,0] = -sin(thetay)
    Ry[2,1] = 0
    Ry[2,2] = cos(thetay)

    # Filling Rz rotation matric
    #   |    cos(thetaz)   -sin(thetaz)      0     |
    #   |    sin(thetaz)    cos(thetaz)      0     |
    #   |          0            0            1     |

    Rz = Matrix(Rz)
    Rz[0,0] = cos(thetaz)
    Rz[0,1] = -sin(thetaz)
    Rz[0,2] = 0
    Rz[1,0] = sin(thetaz)
    Rz[1,1] = cos(thetaz)
    Rz[1,2] = 0
    Rz[2,0] = 0
    Rz[2,1] = 0
    Rz[2,2] = 1

    # Generating the rotation matric
    R = Rz*Ry*Rx

    # Generating the linear translation
    # Symbolic 3D line function
    Translation = MatrixSymbol('Tl',3,1)
    Translation = Start_pos + k * (End_pos-Start_pos)

    # Integrate it into the transformation matric
    #   |    R      T    |
    #   |   000     1    |
    T = Matrix(T)

    i=0
    for r in range(4):
        for c in range(4):
            if (c < 3 and r < 3):
                T[r,c] = R[r,c]
            elif (c == 3 and r < 3):
                T[r,c] = Translation[i]
                ++i
            elif (c < 3 and r == 3):
                T[r,c] = 0
            else:
                T[r,c] = 1

    ## Save the created matrics with symbolic variables into global object
    T = T.subs([(thetax,0),(thetaz,0)])
    return T

if __name__ == "__main__":
    main()

Upvotes: 1

Views: 199

Answers (1)

sterin
sterin

Reputation: 1968

There are several errors here:

  1. The Python function generate_symbolic_transformation throws an exception, which makes resultObj be NULL. This propagates further and leads to the crash.

  2. Even if resultObj was not NULL, it would not have been returned properly to its caller, as the last two lines of CallPlugIn_generate_symbolic_transformation make sure that a value is only returned it it is NULL.

But these are specific problems. I would also make a few general suggestion that might help you catch problems early, saving time and effort:

  1. Handle Python errors. At the bare minimum, if a Python C/API function returns NULL, print the error. For example:

if (!resultObj) { PyErr_Print(); }

This would have resulted in an error message similar to:

Traceback (most recent call last): File "/home/sterin/ClionProjects/numpy1/numpy_test.py", line 15, in generate_symbolic_transformation T = T.subs([(thetax,0),(thetaz,0)]) NameError: global name 'thetax' is not defined

Helping you to catch the error much earlier.

  1. Make sure no NULL values are provided as PyObject* arguments to Python C/API calls (unless specifically allowed). This would have caught the place where the NULL result have been used.

Upvotes: 1

Related Questions