Getting started¶
Here you find two ways of getting started with the BayesOpt4ROS package. If you already have a catkin workspace and would like to directly integrate BayesOpt4ROS into your workflow, please see section Your own workspace. In case you just want to try out the package, follow Example workspace (Docker) to set up a workspace inside a Docker container.
Your own workspace¶
For the following steps, we’ll assume that ${WORKSPACE}
is the root of your catkin workspace.
Requirements¶
BayesOpt4ROS requires Python 3, which is the default version when you use ROS Noetic. If you are using ROS Melodic (or older) you first need to set up Python 3 for your workspace.
Installation¶
First, let’s clone BayesOpt4ROS as a package into your workspace:
cd ${WORKSPACE}
git clone https://github.com/lukasfro/bayesopt4ros.git src/bayesopt4ros
Our package is written in Python and requires some 3rd parties libraries to work. You can easily install them via pip:
python3 -m pip install -r src/bayesopt4ros/requirements.txt
Now we should be ready to build the workspace:
catkin_make
# Or
catkin_make_isolated
# Or
catkin build
# Don't forget to source the setup files
source devel(_isolated)/setup.bash
You should be good to go now. One way of quickly testing if the installation worked is by launching the server.
roslaunch bayesopt4ros bayesopt.launch
You should see the output of the server similar to this:
[INFO] [1616593243.400756]: [BayesOptServer] Iteration 0: Ready to receive requests.
Note
If roslaunch fails, make sure that the node script is executable.
chmod +x src/bayesopt4ros/nodes/bayesopt_node.py
The server node is now ready to receive requests from a client (your node). Continue with the tutorial to see what callback methods you need to implement.
Client implementation¶
The BayesOpt4ROS package uses the ActionServer/ActionClient communication pattern. On the official ROS homepage you can find tutorials for an exemplary implementation. Since BayesOpt4ROS already provides the server side, you just need to implement the client code. In the following, we show you what methods/callbacks you have to implement to communicate with the server (depending on the language of your choice).
First, we need to instantiate the respective client node and tell it to listen to the BayesOpt server.
C++:
#include "actionlib/client/simple_action_client.h"
#include "bayesopt4ros/BayesOptAction.h"
Client client_node_("BayesOpt");
client_node_.waitForServer();
Python:
import actionlib
from bayesopt4ros.msg import BayesOptAction, BayesOptGoal
self.client = actionlib.SimpleActionClient("BayesOpt", BayesOptAction)
self.client.wait_for_server()
Querying the server to get new parameters is done by sending a ‘goal’. Here is where you provide the server with your experiment’s outcome via y_new, i.e., the function value of the objective that you want to optimize.
C++:
BayesOptGoal goal;
goal.y_new = 42.0;
client_node_.sendGoal(goal, boost::bind(&ExampleClient::bayesOptCallback, this, _1, _2));
Python:
goal = BayesOptGoal(y_new=y_new)
self.client.send_goal(goal)
Whenever the server is done computing a new set of parameters, the respective callback method is called. For the sake of this example, we just store the result in a class variable x_new.
C++:
void bayesOptCallback(const actionlib::SimpleClientGoalState& state, const BayesOptResultConstPtr& result) {
x_new_ = result->x_new;
}
Python:
self.client.wait_for_result()
result = self.client.get_result()
x_new = result.x_new
Note
The above Python example waits the server do be done until it continues running. This behaviour is not always desired. You can also implement an asynchronous pattern via callback functions in Python. The official ROS documentation does not provide such an example, but this answer has everything that you should need.
That’s already it! By repeatively querying the server via the pattern above, you will receive new parameters that will optimize your objective. Full examples of exemplary clients can be found here for C++ and here for Python.
Example workspace (Docker)¶
In case you do not directly want to install BayesOpt4ROS into your own workspace, we provide a repository to test the package within a Docker container. If you do not have Docker installed, now would be a good time to do so.
Set up Docker¶
First, clone the workspace repository:
git clone https://github.com/lukasfro/bayesopt4ros_workspace.git
cd bayesopt4ros_workspace
Next, let’s create an image from the provided Dockerfile and run a container
# -t tags a docker image with a name, 'bayesopt4ros' in our case
docker build -t bayesopt4ros .
# -it runs the container in interactive mode
# -v mounts our current directory to the workspace in the container
docker run -it -v $(pwd):/root/ws/ bayesopt4ros
Note
If you are working on a MacBook M1 with ARM chip, you need to adapt the Dockerfile to pull the right ROS image. Just have a look here and change the base image:
# For all machines except MacBooks with M1 CPU
FROM osrf/ros:noetic-desktop-full
# Use this image when your are using a MacBook with M1 CPU
FROM arm64v8/ros:noetic
Running test client¶
The following commands will only work within the Docker container. Let’s build the workspace (choose any build system of your choice):
catkin_make_isolated
source devel_isolated/setup.bash
The easiest way to see the server in action is by executing one of the integration tests:
rostest bayesopt4ros test_client_python.test
If you want to look at the results, we provide a small visualization script. You can run the following command outside of the running Docker container if you want to directly show the results. We also save an image to disk to the logging directory (this also works within the Docker container since we mounted your local workspace to the container workspace).
python3 visualize.py --log-dir logs/forrester_ucb
The resulting image should look something like this
