Visual Servoing Platform
version 3.6.1 under development (2024-04-25)
|
Since ViSP 3.6.0, a 3rd party library was introduced to allow the seamless use of JSON (JavaScript Object Notation) in ViSP. The library that is used is JSON for modern C++. To install it on your system, look at JSON for modern C++ installation instructions for your system.
The main use case for using JSON in your programs is to save your experimental results. The main advantage of using JSON is that it is widely supported by default in other languages.
Thanks to this 3rd party, JSON serialization was introduced for vpCameraParameters, vpArray2D, vpColVector, vpPoseVector, vpHomogeneousMatrix, vpMe and vpMbGenericTracker.
In this tutorial, we will use JSON to:
First of all, it is necessary to understand the structure of JSON documents to better use them. For a detailed description, you may be interested in the Mozilla Developer Network documentation.
Much of this section is a repeat of the library's documentation, available here.
To use JSON in your code you should first include the relevant header:
This introduces a new type named json
which supports many types out of the box:
This snippet will print
{ "aVector": [1.0, 2.0, 3.0], "bool": false, "double": 3.14156, "string": "Hello World!" }
The library also allows to define explicit conversion between a custom type and JSON. This can be achieved by defining the two following functions:
These functions must be defined in the same scope namespace as YourType and must be accessible everywhere YourType is used. It is thus common to define it in the header where YourType is defined.
Once this conversion is defined you can convert to and from json with:
To better understand the requirements and caveats when writing custom conversions, we encourage you to read the documentation on arbitrary type conversion.
This example will demonstrate some basic usage of JSON to save the data generated by running an IBVS and exporting it to python to plot some figures. This example is a modification tutorial-ibvs-4pts.cpp and the full code is available at tutorial-ibvs-4pts-json.cpp.
This program can be run with:
$ cd $VISP_WS/visp-build/tutorial/visual-servo/ibvs $ ./tutorial-ibvs-4pts-json --settings ibvs_settings.json --output results.json
We first start by defining the program arguments:
This struct contains the control law gain, the desired and starting pose, as well as the visual error threshold and robot sampling time. Finally it contains a value of type vpInteractionMatrixTypeSubset
which is defined as
This value will be converted to a vpServo::vpServoIteractionMatrixType when defining the control law, by calling Arguments::getInteractionMatrixType()
.
Now that our arguments are defined we must now know to parse JSON to get them. We start by defining how to serialize our enumeration vpInteractionMatrixTypeSubset
:
Note that if the value is not in CURRENT
, DESIRED
or MEAN
, then the parsing result will default to the value vpInteractionMatrixTypeSubset::UNKNOWN
.
Next we define how to parse the full list of arguments:
Where the method from_json()
is used to parse JSON and, inversely, to_json()
is used to convert the arguments to JSON, which we will use afterwards.
The syntax
is used to fill in optional values from the JSON document. If the key is not found then x
will be left unchanged This syntax can also be used to set a default value, e.g.:
In the from_json()
method, we ensure that all the arguments are correctly set:
With this conversion defined, we can read the program settings from a file (ibvs_settings.json
), containing
Note that while the Arguments
class represents the desired and starting poses as vpHomogeneousMatrix elements, they are defined in the JSON as vpPoseVector representations. ViSP will automatically convert one representation to the other when parsing JSON.
To read from the ibvs_settings.json
file, we will define the following method:
Which we will call in the main()
, to finally obtain our program arguments:
We can now start servoing and acquiring data, that will be saved to another JSON file.
To save the data to a JSON file, we first define what we'll save
This includes:
Before starting the servoing loop we create a results
object:
We then start the visual servoing loop:
where at each iteration, we update our results
object with
Finally, to save the results to a file, we define a function to write to a file
and call it at the end of the program
Our data is now saved in a JSON file, and we can reuse it in other programs, as we demonstrate further below.
We will now reparse the JSON file saved in Collecting and saving visual servoing data section to generate high quality plots in Python with Matplotlib. The script, plot-ibvs-control-law.py
can be found in the script folder of the ViSP git repository. It has been tested with Python 3.7.9, matplotlib 3.3.2 and numpy 1.17.3.
If not already done, to use the script install the following:
pip3
and python3
are correctly installed $ python3 --version $ pip3 --version
$ pip3 install --upgrade pip
pip3
$ pip3 install numpy
pip3
$ pip3 install matplotlib
The script gives plot-ibvs-control-law.py
a reference on how to plot with JSON data coming from ViSP. You may wish to modify and extend it to fit your use case or control law.
To run the script, replace the json path that contains the data to plot and where you wish to save the plots in the following command:
$ cd VISP_WS/visp/script $ python3 plot-ibvs-control-law.py --data $VISP_WS/visp-build/tutorial/visual-servo/ibvs/results.json \ --plot_folder ./plots
The script should produce similar output:
Generating error norm plot... Generating velocity plot... Generating 2D and 3D trajectory plots... Generating features plot... Plots were saved to $VISP_WS/visp/script/plots
You can then view the generated plots in the folder where you saved them (in our case in ./plots/
corresponding to $VISP_WS/visp/script/plots
folder).
$ ls $VISP_WS/visp/script/plots cMo.pdf error.pdf velocity.pdf cMo_3d.pdf trajectories_2d.pdf
You should obtain plots similar to those below, but with a higher quality (generated in pdf):
You are now ready to see how to continue with Tutorial: Loading a model-based generic tracker from JSON.