Commit e35b20d0 authored by Giuseppe Carboni's avatar Giuseppe Carboni
Browse files

Fix #646, wrote a Python wrapper for the `SRTMinorServoCommandLibrary` (#650)

* Fix #646, wrote a Python wrapper for the `SRTMinorServoCommandLibrary`

* Fix #646, Added a python module that uses the wrapper library

It has been commented in order to replicate the behavior in any future python wrapped C++ library

* Fix #646, fixed a few small things regarding some include and the Makefile

* Fix #646, added documentation about the Python wrapper

Also, fixed some small inconsistencies with the new C++ implementation

* Issue #637, removed an unneeded include statement
parent b3bbae00
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
#ifndef _PYSRTMINORSERVOCOMMANDLIBRARY_H
#define _PYSRTMINORSERVOCOMMANDLIBRARY_H

/**
 * PySRTMinorServoCommandLibrary.h
 * 2021/12/13
 * Giuseppe Carboni (giuseppe.carboni@inaf.it)
 */

#include <boost/python.hpp>
#include "SRTMinorServoCommandLibrary.h"


/**
 * SRT Minor Servo Command Library Python Wrapper
 *
 * This class wraps the SRTMinorServoCommandLibrary with boost_python in order to grant access to its static functions via Python
 */
class PySRTMinorServoCommandLibrary : public SRTMinorServoCommandLibrary
{
public:
    /*
     * Builds the command used to move a single servo to a given set of coordinates
     * This is an overload of the original SRTMinorServoCommandLibrary::preset function
     * An overload was needed in order to handle the coordinates parameter as a Python list instead of a C++ std::vector
     * @param servo_id the ID of the single servo to be moved
     * @param coordinates a Python list containing the N coordinates to be sent to the servo
     * @return the composed message
     */
    static std::string preset(std::string servo_id, boost::python::list& coordinates);

    /*
     * Builds the command used to provide a single tracking set of coordinates to a single servo
     * This is an overload of the original SRTMinorServoCommandLibrary::programTrack function
     * An overload was needed in order to handle the coordinates parameter as a Python list instead of a C++ std::vector
     * @param servo_id the ID of the single servo to send the command to
     * @param trajectory_id the ID number of the trajectory the given set of coordinates belongs to
     * @param point_id the ID number of the given set of coordinates inside the trajectory
     * @param coordinates a Python list containing the N coordinates the servo have to move to at the given time
     * @param start_time only mandatory for the first point in the trajectory, a double representing the UNIX epoch of the starting instant of the trajectory
     * @return the composed message
     */
    static std::string programTrack(std::string servo_id, unsigned int trajectory_id, unsigned int point_id, boost::python::list& coordinates, double start_time=-1);

    /*
     * Builds the command used to provide a set of offsets to a given servo
     * This is an overload of the original SRTMinorServoCommandLibrary::offset function
     * An overload was needed in order to handle the coordinates parameter as a Python list instead of a C++ std::vector
     * @param servo_id the ID of the single servo to be moved
     * @param coordinates a Python list containing the N coordinates to be sent to the servo
     * @return the composed message
     */
    static std::string offset(std::string servo_id, boost::python::list& coordinates);

private:
    /*
     * Converts the given Python list into a C++ std::vector object
     * @param py_list the given Python list to be converted
     * @return the composed C++ std::vector containing doubles
     */
    static std::vector<double> pylist2cppvector(boost::python::list& py_list);
};

/*
 * The following 3 lines of code allow the overloaded functions to ignore the optional parameter and use the default one defined in the original SRTMinorServoCommandLibrary header file
 */
BOOST_PYTHON_FUNCTION_OVERLOADS(status, PySRTMinorServoCommandLibrary::status, 0, 1)
BOOST_PYTHON_FUNCTION_OVERLOADS(stow, PySRTMinorServoCommandLibrary::stow, 1, 2)
BOOST_PYTHON_FUNCTION_OVERLOADS(programTrack, PySRTMinorServoCommandLibrary::programTrack, 4, 5)

/*
 * Python module definition. Since the original SRTMinorServoCommandLibrary only contains static functions, we write the Python module with static functions only, omitting the class
 */
BOOST_PYTHON_MODULE(libPySRTMinorServoCommandLibrary)
{
    using namespace boost::python;
    def("status", &PySRTMinorServoCommandLibrary::status, status(arg("servo_id") = ""));
    def("setup", &PySRTMinorServoCommandLibrary::setup);
    def("stow", &PySRTMinorServoCommandLibrary::stow, stow(arg("stow_position") = 1));
    def("stop", &PySRTMinorServoCommandLibrary::stop);
    def("preset", &PySRTMinorServoCommandLibrary::preset);
    def("programTrack", &PySRTMinorServoCommandLibrary::programTrack, programTrack(arg("start_time") = -1));
    def("offset", &PySRTMinorServoCommandLibrary::offset);
}
#endif
+1 −3
Original line number Diff line number Diff line
@@ -9,8 +9,6 @@

#include <sstream>
#include <vector>
#include <acstimeEpochHelper.h>
#include <IRA>

/**
 * SRT Minor Servo Command Library
@@ -40,7 +38,7 @@ public:
     * @param stow_position the position to which the servo have to stow to
     * @return the composed message
     */
    static std::string stow(std::string servo_id, unsigned int stow_position = 0);
    static std::string stow(std::string servo_id, unsigned int stow_position = 1);

    /*
     * Builds the command used to stop a single servo system
+6 −4
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ USER_CFLAGS = -Wall
#
# additional include and library search paths
# USER_INC = /usr/local/include
USER_LIB =
# USER_LIB =

#
# MODULE CODE DESCRIPTION:
@@ -59,12 +59,14 @@ INCLUDES = hexlib.h SRTMinorServoCommandLibrary.h
#
# Libraries (public and local)
# ----------------------------
LIBRARIES       = SRTMinorServoLibrary SRTMinorServoCommandLibrary
LIBRARIES       = SRTMinorServoLibrary SRTMinorServoCommandLibrary PySRTMinorServoCommandLibrary
LIBRARIES_L     =
SRTMinorServoLibrary_OBJECTS = hexlib
SRTMinorServoLibrary_LIBS = gsl gslcblas m
SRTMinorServoCommandLibrary_OBJECTS = SRTMinorServoCommandLibrary
SRTMinorServoCommandLibrary_LIBS = IRALibrary
SRTMinorServoCommandLibrary_LIBS =
PySRTMinorServoCommandLibrary_OBJECTS = PySRTMinorServoCommandLibrary
PySRTMinorServoCommandLibrary_LIBS = SRTMinorServoCommandLibrary boost_python

#
# <brief description of lllll library>
@@ -91,7 +93,7 @@ PY_SCRIPTS_L =
PY_MODULES         =
PY_MODULES_L       =

PY_PACKAGES        =
PY_PACKAGES        = SRTMinorServoCommandLibrary
PY_PACKAGES_L      =
pppppp_MODULES	   =

+26 −0
Original line number Diff line number Diff line
#include "PySRTMinorServoCommandLibrary.h"

std::string PySRTMinorServoCommandLibrary::preset(std::string servo_id, boost::python::list& coordinates)
{
    return SRTMinorServoCommandLibrary::preset(servo_id, PySRTMinorServoCommandLibrary::pylist2cppvector(coordinates));
}

std::string PySRTMinorServoCommandLibrary::programTrack(std::string servo_id, unsigned int trajectory_id, unsigned int point_id, boost::python::list& coordinates, double start_time)
{
    return SRTMinorServoCommandLibrary::programTrack(servo_id, trajectory_id, point_id, PySRTMinorServoCommandLibrary::pylist2cppvector(coordinates), start_time);
}

std::string PySRTMinorServoCommandLibrary::offset(std::string servo_id, boost::python::list& coordinates)
{
    return SRTMinorServoCommandLibrary::offset(servo_id, PySRTMinorServoCommandLibrary::pylist2cppvector(coordinates));
}

std::vector<double> PySRTMinorServoCommandLibrary::pylist2cppvector(boost::python::list& py_list)
{
    std::vector<double> cpp_vector;
    for(unsigned int i = 0; i < len(py_list); i++)
    {
        cpp_vector.push_back(boost::python::extract<double>(py_list[i]));
    }
    return cpp_vector;
}
+18 −0
Original line number Diff line number Diff line
# SRTMinorServoCommandLibrary Python wrapper

In order to use the SRTMinorServoCommandLibrary python wrapper, it is sufficient to import the SRTCommandLibrary package like this:

`import SRTMinorServoCommandLibrary`

The all the functions of the library can be used in the following fashion:

`SRTMinorServoCommandLibrary.status()`
`SRTMinorServoCommandLibrary.status('PFP')`
`SRTMinorServoCommandLibrary.setup('KKG')`
`SRTMinorServoCommandLibrary.stow('PFP')`
`SRTMinorServoCommandLibrary.stow('PFP', 2)`
`SRTMinorServoCommandLibrary.stop('SRP')`
`SRTMinorServoCommandLibrary.preset('SRP', [0, 1, 2, 3, 4, 5])`
`SRTMinorServoCommandLibrary.programTrack('PFP', 0, 0, [0, 1, 2, 3, 4, 5], <start_time>)`
`SRTMinorServoCommandLibrary.programTrack('PFP', 0, 1, [0, 1, 2, 3, 4, 5])`
`SRTMinorServoCommandLibrary.offset('SRP', [6, 7, 8, 9, 10, 11])`
Loading