Python Dynamics Simulations: Part 4 — Sockets with C and Python

About integrating the simulations in your applications

Juan Sandubete
Dec 30, 2020 · 7 min read
Atlantic Ocean from Tarifa seafloor (Spain) | Photo by Juan Sandubete

In the previous chapters of this tutorial we have learnt how to make simulations of dynamics models. The way we have made them until now is useful for offline analysis, but, for online simulations with hardware in the loop or with other software, we may add a little piece of software in order to establish the data transmission.

We will assume that the hardware in the loop has some link which supports sockets (like ESP32 or ESP8266 through WiFi or whatever). If you are interested in serial connections, let me know in the comments!

As always, I assume that you have read the previous parts of this tutorial. If you have any doubt about how does this simulator work, please, check it out. Here you have the index of the tutorial.

The content of this chapter is divided in four sections. This is the content of the this tutorial part:

  • Sockets in a nutshell
  • Socket programming with Python
  • Socket programming with C / C++
  • JSON message encoding/decoding (Python and C)

1. Sockets in a nutshell

The bibliography about sockets is extensive. Really. So I will not create another post talking about this thing. Instead, I’m going to show you a little bit about them for the case you don’t know them and, for further learning, you will have additional links at the end of this post.

The goal of this sockets section is to show an easy method for communicating our process, even if one was written with Python and the other with C running in a micro-controller.

Sockets are software structures which allows the exchange of data across different processes, within one unique machine or among several connected ones. A socket can be like the gate of your process with the rest of the world.

They can work using different underlying protocols, but the most used are TCP and UDP. You can choose what of them is more useful for your application considering this:

  • UDP: Big data stream and not a big deal to loss one data package. Also useful if you don’t have big computation capacity. For instance, real time video stream.
  • TCP: Big computational effort to ensure that every bit you send is delivered. For instance, high level commands sent to a robot.

The main parameters of the sockets are the address family, the protocol (if TCP: SOCK_STREAM, if UDP: SOCK_DGRAM), the host address and the port. Check the references for more information [1][2][3][5]. Specially the third reference is a very good one.

2. Socket programming with Python

In the socket connections (basic case) there is a pair of processes communicating. One acts passively, waiting for a request, and the other acts actively, reaching out the server for initiating the data exchange. The first is called server and the second, client.

The code shown below corresponds, respectively, to the TCP Client, UDP Client, TCP Server, UDP Server. It is almost the same code for all of them, but I believe that I can help you to understand the differences if I give you the code for all the cases.

Some observations:

  • The configuration of the socket is, obviously, different for UDP and TCP.
  • The UDP client does not need to establish a connection with the server prior to the delivery of the messages. With TCP it is necessary.
  • The TCP server detects whenever the client is down and, in this case, it can wait or switch off. The UDP server per se will not notice the status of the client.
  • In order to connect the client with an external host, change the address (‘0.0.0.0’ = localhost) by the desired host address.

The rest of the code is pretty similar for both cases. Should you have any question, let me know in the comments.

3. Socket programming with C

Although the use of sockets is somehow more complicated/tricky with C, the socket programming is essentially the same in these three languages, thus we are going to see only how to program TCP sockets with C. Take a look to [1] or [2] for UDP sockets and other configurations.

Note. You can use this C code also inside your C++ programs but, if you want something more modern, check how to program sockets with boost [5].

In the creation C socket, several functions are used. This is a fast resume of them:

  • socket(int domain, int type, int protocol) creates the socket itself. Domain will usually be AF_INET or AF_INET6 (IPv4, IPv6). Type serves for choosing UDP, TCP or whatever. Protocol is usually ‘0’. You specify More info, here.
  • setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len) is used to apply some configuration (through binary mask) to the socket, for instance, to broadcast messages to all connected clients. For further setting options and more information, check it here.
  • bind() binds the socket to some address/port. More info.
  • listen() makes the socket capable of accepting connections from clients. More info here.
  • accept() turns the socket into a “waiting for connections” status until some client reaches it.

Notice that, in this example, the buffer size matches the size of the input message so that the server stops waiting as soon as the message is received. This has been made in order to avoid an endless delay on the recv() or read().

This is something that you usually must address with these C sockets. Other options are to send a previous message communicating the size of the incoming message (some custom protocol), or set a timeout in the server side.

The previous code files can be compiled with the following sentences:

gcc -o tcp_server tcp_server.c
gcc -o tcp_client tcp_client.c

You can also check the reference [2] for further information about this topic programming in C language.

4. Encoding/Decoding messages with JSON

As you may noticed, to send a message through a socket, it must consist of ASCII characters; so, what happens when you want to send floating point numbers? (For instance, you may need to send the accelerometer signals).

There are many possible solutions. The one that I like the most is to use JSON messages with which you can communicate two process written in different programming languages if they both have the corresponding library. Take a look in the chapter 3.3 if you don’t know yet what the JSON format is.

It is very easy to encode these numbers in a JSON message with Python. We can reuse the previous code of sockets adding/modifying some lines (which I have indicated with arrows):

Essentially, to encode the data, you must create a dictionary with as many labels and fields as you need (lists, floating point numbers and others are all allowed). Then, use json.dumps(data_dict) to transform the dictionary into a string which can be sent through the socket.

In the other side of the stream, the message string is transformed into a dict, using json.loads(message), from which you can extract the data using the labels.

I use the Frozen library to encode/decode JSON messages with C. The main advantage of this library is its very light weight (and it is also header-only), thus you can use it on any micro-controller program without storage space issues. Here I show how to write a JSON:

The result is written inside the char_buffer which is sent through the socket. Check the usage in the server example in the repository (c_sockets > ex2) using the same tcp_client code of the previous example.

To scan the value of a JSON from the socket with C, you must bring the variables in which you want to store the values and the expected JSON message structure, just like this:

int var1 = 0;
float var2 = 0.0;
json_scanf(str, strlen(str), "{c: %d, d: %f}", &var1, &var2);

You can read more about the Frozen Library usage on its readme, there on the Github repository.

5. Conclusions

Now that we can share data through sockets between processes, it is possible to launch the simulator in one terminal and the controller in another.

This controller will run independently with its own configuration and persistent data, something that we couldn’t do with the previous approach for the controller.

Indeed, this allows us to connect the simulator with any other application in case it is able of exchanging data through sockets. For instance, you can now use Octave scripts together with the Python simulator and C/C++ controllers easy way.

This serves, somehow, as standard communication channel between applications.

This is the last chapter about code tools which you should know in order to be able to understand the simulator code itself. From now on, we will learn lot of stuff of dynamic systems like transfer functions, multivariable correlation, nonlinear control and other things.

I hope you found this post useful and, please, consider to clap a little bit if it is the case! As always, you have all the code of the examples of this post in my Github repository.

Un abrazo y próspero año nuevo — Juan.

6. References

[1] Sockets for Java and C/linux(in Spanish): http://www.chuidiang.org/clinux/sockets/sockets_simp.php

[2] The C Sockets Vademecum: https://beej.us/guide/bgnet/

[3] Sockets programming with Python: https://realpython.com/python-sockets/

[4] Built-in python sockets methods: https://docs.python.org/3/library/socket.html

[5] Sockets with C++: https://www.codeproject.com/Articles/1264257/Socket-Programming-in-Cplusplus-using-boost-asio-T

Robotics Devs

Code and algorithms tutorials for roboticists

Juan Sandubete

Written by

Andalusian Robotics Engineer and SCUBA Diver who loves to learn stuff, to build artifacts and to experience nice things. https://www.instagram.com/jsandubete

Robotics Devs

Dynamic simulations with Python, navigation and control algorithms with C++, embedded systems, basic electronics and other useful topics for robotics developers. If you want to publish in Robotics Devs, send your draft to: roboticsdevs@gmail.com

Juan Sandubete

Written by

Andalusian Robotics Engineer and SCUBA Diver who loves to learn stuff, to build artifacts and to experience nice things. https://www.instagram.com/jsandubete

Robotics Devs

Dynamic simulations with Python, navigation and control algorithms with C++, embedded systems, basic electronics and other useful topics for robotics developers. If you want to publish in Robotics Devs, send your draft to: roboticsdevs@gmail.com

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store