Skip to content

How to send more data to python

evanrex edited this page Jun 7, 2021 · 11 revisions
  • To see these techniques in use view Strategy.cc. the pyFunction.
  • the first command that must be run before using or calling python Scripts or PyObjects is Py_Initialize(). this function basically creates a python interpreter to run python commands and files
  • to run a python command use the following command PyRun_SimpleString("import os"). in this example here we are importing the os library to interpreter.
  • this is an example on how you can call on a python file. to check if it has imported you can put pModule in an if statement
//calling on myFile.py 
PyObject *  pName = PyUnicode_FromString("myFile");
PyObject * pModule = PyImport_Import(pName);

if(pModule)
{
	// running the method myFunc in myFile.py
	PyObject * pFunc = PyObject_GetAttrString(pModule, "myFunc"); 
       
	if(pFunc && PyCallable_Check(pFunc))
	{
           //here we call on the python function and store the output in a PyObject in this example we are sending in a list so we attach an O before world_data
           PyObject * pReturn = PyObject_CallFunction(pFunc,"O",world_data);
	   //here we convert the pyobject to the relevent c++ format
           int x = (int) PyLong_AsLong(pReturn);
	   return x;
	}
	else
	{
            
	    cout << "ERROR: function selectSkill()\n"<<endl;
            return -1;
	}

	}
	else
	{
        
		cout << "ERROR: Module not imported"<<endl;
        return -2;
	}

for info on how to convert c++ to PyObject look here and how to convert from PyObject to c++ you can look here

  • an example of converting a c++ data type to a python Object
//converting an integer to a PyObject
int x = 5
PyObject * temp;
temp = Py_BuildValue("i",x);
  • an example of extracting data from a PyObject
PyObject * objectPy;
//update objectPy
int x = (int) PyLong_AsLong(objectPy);

Handling Python Lists

  • how to define a python list
int n = 5;
PyObject* pyList = PyList_New(n);
  • how to get an item from the pyList (get the item at index 0)
PyObject* item = PyList_GetItem(pyList, 0);
  • how to set an item in a python list
int value = 5;
PyObject * item = Py_BuildValue("i",value);
PyList_SetItem(PyList,0,item);

Using the world data object:

In strategy.cc, there is a method: worldData(), which takes in a series of PyObjects, and returns them as a list. It is this list, world_data, that is passed through to python.

Passing the world_data list through to python:

C++ side:

PyObject * world_data = worldData(playerNumPy,playModePy,sidePy,posPy,ballPy, teamPositionsPy, oppPositionsPy ,teamDistToBallPy,OppDistToBallPy);
n = pyFunction(world_data,pos);

Python side:

import Robocup as RC
def selectSkill(world_data): #see how selectSkill() takes in world_data as a parameter
    robocup = RC.Robocup(world_data) #see how the Robocup constructor takes in world_data as a parameter

Comparing the worldData() method to the constructor for the Robocup class in python:

worldData()

PyObject * worldData(PyObject *  _playerNumber,PyObject * _playMode,PyObject * _side,PyObject * posPy,PyObject * ballPy,PyObject *  teamPositionsPy,PyObject *  oppPositionsPy,PyObject * teamDistToBallPy,PyObject * OppDistToBallPy){
    
    //this mirrors constructor for Robocup class on python side
    
    PyObject * pyList;
    pyList = PyList_New(9);
    PyList_SetItem(pyList,0,_playerNumber);
    PyList_SetItem(pyList,1,_playMode);
    PyList_SetItem(pyList,2,_side);
    PyList_SetItem(pyList,3,posPy);    
    PyList_SetItem(pyList,4,ballPy);
    PyList_SetItem(pyList,5,teamPositionsPy);
    PyList_SetItem(pyList,6,oppPositionsPy);

    PyList_SetItem(pyList,7,teamDistToBallPy);
    PyList_SetItem(pyList,8,OppDistToBallPy);



    return pyList;

Robocup constructor:

class Robocup():
    //...
    def __init__(self, world_data):
        """
        Parameters
        ----------
        world data passed through to selectSkill() - ALTERATION IS NOT RECOMMENDED
        This mirrors worldDate object on C++ side
        """

        #World Model Data:
        self.__player_number=world_data[0]
        self.__play_mode=world_data[1]
        self.__side = world_data[2]
        self.__player_pos = world_data[3]        
        self.__ball_pos = world_data[4]
        self.__team_positions = world_data[5]
        self.__opponent_positions = world_data[6]

        #Wrapped C++ Functions:
        self.__team_dist_ball = world_data[7]
        self.__opp_dist_ball = world_data[8]

As you can see, the constructor for the Robocup class in python clearly mirrors the method for worldData in C++.

Clone this wiki locally