From 7717f4913fb407f8e4a69203aace0a2b47799956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Tue, 28 Dec 2021 18:26:59 +0100 Subject: [PATCH] Add GaussMarkovProcess pybind11 interface and examples (#315) Signed-off-by: ahcorde Signed-off-by: Louise Poubel Co-authored-by: Louise Poubel --- examples/gauss_markov_process_example.py | 44 +++++++++++ examples/gauss_markov_process_example.rb | 42 +++++++++++ src/python/CMakeLists.txt | 1 - src/python_pybind11/CMakeLists.txt | 2 + src/python_pybind11/src/GaussMarkovProcess.cc | 73 +++++++++++++++++++ src/python_pybind11/src/GaussMarkovProcess.hh | 43 +++++++++++ .../src/_ignition_math_pybind11.cc | 4 + .../test}/GaussMarkovProcess_TEST.py | 0 8 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 examples/gauss_markov_process_example.py create mode 100644 examples/gauss_markov_process_example.rb create mode 100644 src/python_pybind11/src/GaussMarkovProcess.cc create mode 100644 src/python_pybind11/src/GaussMarkovProcess.hh rename src/{python => python_pybind11/test}/GaussMarkovProcess_TEST.py (100%) diff --git a/examples/gauss_markov_process_example.py b/examples/gauss_markov_process_example.py new file mode 100644 index 000000000..1e9e93ec0 --- /dev/null +++ b/examples/gauss_markov_process_example.py @@ -0,0 +1,44 @@ +# Copyright (C) 2021 Open Source Robotics Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License") +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Modify the PYTHONPATH environment variable to include the ignition math +# library install path. For example, if you install to /usr: +# +# $ export PYTHONPATH=/usr/lib/python:$PYTHONPATH +# +# You can plot the data generated by this program by following these +# steps. +# +# 1. Run this program and save the output to a file: +# python3 gauss_markov_process_example.py > plot.data +# +# 2. Use gnuplot to create a plot: +# gnuplot -e 'set terminal jpeg; plot "plot.data" with lines' > out.jpg +import datetime +from ignition.math import GaussMarkovProcess + +# Create the process with: +# * Start value of 20.2 +# * Theta (rate at which the process should approach the mean) of 0.1 +# * Mu (mean value) 0. +# * Sigma (volatility) of 0.5. +gmp = GaussMarkovProcess(20.2, 0.1, 0, 0.5); + +dt = datetime.timedelta(milliseconds=100) + +# This process should decrease toward the mean value of 0. +# With noise of 0.5, the process will walk a bit. +for i in range(1000): + value = gmp.update(dt); + print(value); diff --git a/examples/gauss_markov_process_example.rb b/examples/gauss_markov_process_example.rb new file mode 100644 index 000000000..b6944dc8c --- /dev/null +++ b/examples/gauss_markov_process_example.rb @@ -0,0 +1,42 @@ +# Copyright (C) 2021 Open Source Robotics Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License") +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Modify the RUBYLIB environment variable to include the ignition math +# library install path. For example, if you install to /user: +# +# $ export RUBYLIB=/usr/lib/ruby:$RUBYLIB +# +# You can plot the data generated by this program by following these +# steps. +# +# 1. Run this program and save the output to a file: +# ruby gauss_markov_process_example.rb > plot.data +# +# 2. Use gnuplot to create a plot: +# gnuplot -e 'set terminal jpeg; plot "plot.data" with lines' > out.jpg +require 'ignition/math' + +# Create the process with: +# * Start value of 20.2 +# * Theta (rate at which the process should approach the mean) of 0.1 +# * Mu (mean value) 0. +# * Sigma (volatility) of 0.5. +gmp = Ignition::Math::GaussMarkovProcess.new(20.2, 0.1, 0, 0.5); + +# This process should decrease toward the mean value of 0. +# With noise of 0.5, the process will walk a bit. +for i in 0..1000 do + value = gmp.Update(0.1); + puts(value); +end diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 85f9a3a19..7d6835a99 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -92,7 +92,6 @@ if (PYTHONLIBS_FOUND) Cylinder_TEST DiffDriveOdometry_TEST Frustum_TEST - GaussMarkovProcess_TEST Inertial_TEST MassMatrix3_TEST Matrix4_TEST diff --git a/src/python_pybind11/CMakeLists.txt b/src/python_pybind11/CMakeLists.txt index e0c42e8b9..51e598a88 100644 --- a/src/python_pybind11/CMakeLists.txt +++ b/src/python_pybind11/CMakeLists.txt @@ -16,6 +16,7 @@ if (${pybind11_FOUND}) src/_ignition_math_pybind11.cc src/Angle.cc src/Color.cc + src/GaussMarkovProcess.cc src/Helpers.cc src/Kmeans.cc src/Material.cc @@ -80,6 +81,7 @@ if (${pybind11_FOUND}) Angle_TEST Color_TEST Filter_TEST + GaussMarkovProcess_TEST Helpers_TEST Kmeans_TEST Line2_TEST diff --git a/src/python_pybind11/src/GaussMarkovProcess.cc b/src/python_pybind11/src/GaussMarkovProcess.cc new file mode 100644 index 000000000..928744409 --- /dev/null +++ b/src/python_pybind11/src/GaussMarkovProcess.cc @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +#include +#include + +#include +#include +#include + +#include + +#include "GaussMarkovProcess.hh" + +namespace py = pybind11; + +namespace ignition +{ +namespace math +{ +namespace python +{ +void defineMathGaussMarkovProcess( + py::module &m, const std::string &typestr) +{ + using Class = ignition::math::GaussMarkovProcess; + std::string pyclass_name = typestr; + py::class_(m, + pyclass_name.c_str(), + py::buffer_protocol(), + py::dynamic_attr()) + .def(py::init<>()) + .def(py::init()) + .def("set", + &Class::Set, + "Set the process parameters. This will also call Reset().") + .def("start", &Class::Start, + "Get the start value.") + .def("value", + &Class::Value, + "Get the current process value.") + .def("theta", &Class::Theta, "Get the theta value.") + .def("mu", &Class::Mu, "Get the mu value.") + .def("sigma", &Class::Sigma, "Get the sigma value.") + .def("reset", + &Class::Reset, + "Reset the process. This will set the current process value") + .def("update", + py::overload_cast< + const std::chrono::steady_clock::duration&>( + &Class::Update), + "Update the process and get the new value.") + .def("update", + py::overload_cast(&Class::Update), + "Update the process and get the new value."); +} +} // namespace python +} // namespace math +} // namespace ignition diff --git a/src/python_pybind11/src/GaussMarkovProcess.hh b/src/python_pybind11/src/GaussMarkovProcess.hh new file mode 100644 index 000000000..c100c684f --- /dev/null +++ b/src/python_pybind11/src/GaussMarkovProcess.hh @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +#ifndef IGNITION_MATH_PYTHON__GAUSSMARKOVPROCESS_HH_ +#define IGNITION_MATH_PYTHON__GAUSSMARKOVPROCESS_HH_ + +#include + +#include + +namespace py = pybind11; + +namespace ignition +{ +namespace math +{ +namespace python +{ +/// Define a pybind11 wrapper for an ignition::math::GaussMarkovProcess +/** + * \param[in] module a pybind11 module to add the definition to + * \param[in] typestr name of the type used by Python + */ +void defineMathGaussMarkovProcess(py::module &m, const std::string &typestr); +} // namespace python +} // namespace math +} // namespace ignition + +#endif // IGNITION_MATH_PYTHON__GAUSSMARKOVPROCESS_HH_ diff --git a/src/python_pybind11/src/_ignition_math_pybind11.cc b/src/python_pybind11/src/_ignition_math_pybind11.cc index 6288d9c5a..aa1ca093c 100644 --- a/src/python_pybind11/src/_ignition_math_pybind11.cc +++ b/src/python_pybind11/src/_ignition_math_pybind11.cc @@ -17,6 +17,7 @@ #include "Angle.hh" #include "Color.hh" #include "Filter.hh" +#include "GaussMarkovProcess.hh" #include "Helpers.hh" #include "Kmeans.hh" #include "Line2.hh" @@ -48,6 +49,9 @@ PYBIND11_MODULE(math, m) ignition::math::python::defineMathColor(m, "Color"); + ignition::math::python::defineMathGaussMarkovProcess( + m, "GaussMarkovProcess"); + ignition::math::python::defineMathHelpers(m); ignition::math::python::defineMathKmeans(m, "Kmeans"); diff --git a/src/python/GaussMarkovProcess_TEST.py b/src/python_pybind11/test/GaussMarkovProcess_TEST.py similarity index 100% rename from src/python/GaussMarkovProcess_TEST.py rename to src/python_pybind11/test/GaussMarkovProcess_TEST.py