hku-ect / gazebosc

3 stars 6 forks source link

OSX/Linux: Build Status

GazebOSC

Gazebosc is a high level actor model programming environment. You can visually create actors and author them using a nodal UI. Actors are running concurrently and can be programmed sequentially using C, C++ or Python. Actors communicate using the OSC serialisation format.

screenshot

Prebuilt binaries

CI tested binaries with bundled Python are available from:

https://pong.hku.nl/~buildbot/gazebosc/

Sort on date to find the latest build.

Creating Actors

Easiest method of adding a new actor is using Python. You'll need to have a Gazebosc build with Python. Otherwise you can create Actors in C or C++.

Python Actor

class MyActor(object):
    def handleSocket(self, addr, msg, type, name, uuid, *args, **kwargs):
        print("received OSC message {} {}".format(addr, msg))
        return ("/MyActorMsg", [ "hello", "world", 42] )

This is just the most basic actor which responds to incoming messages. A template you can use for a full feature actor is as follows:


class MyActor(object):
    def __init__(self, *args, **kwargs):
        self.timeout = 1000         # Use this timeout value for when you need recurring handleTimer events
                                    # Set to -1 to wait infinite (default)

    def handleApi(self, command, *args, **kwargs):
        print("The API command is {} and its arguments is {}".format(command, args))
        return None

    def handleSocket(self, address, data, *args, **kwargs):
        print("The osc address is {} and its data is {}".format(address, data))
        return ("/myreturnaddress", ["hello", 3, 2, 1])

    def handleTimer(self, *args, **kwargs):
        # This is a timed event, use it as you need
        print("My timed event with type: {}, name: {}, uuid: {}".format(args[0], args[1], args[2]))
        return ("/mytimedreturn", ["hello", 1, 2, 3])

    def handleCustomSocket(self, *args, **kwargs):
        # We'll explain this in the future
        return ("/myreturnaddress", ["hello", "world"])

    def handleStop(self, *args, **kwargs):
        # We are shutting down
        print("Bye bye from {}".format(args[1]))

Save this file as MyActor.py as the filename needs to equal the class name!

C++ Actor

To create an actor in C++ you'll need to build GazebOSC from source as you will add the actor to the source. You can use the following example code as an example:

class MyActor : public Sphactor
{
public:
    MyActor() : Sphactor() {}

    static const char *capabilities; // this string is used to describe the capacilitites of the actor

    zmsg_t *handleInit(sphactor_event_t *ev) // this method is called when the actor is started (added to the stage)
    {   // you will receive an event (ev) with an message (ev->msg) which you will need to cleanup
        if ( ev->msg )
            zmsg_destroy(&ev->msg);
        return nullptr; // you can return a message (zmsg) or nothing (nullptr)
    }

    zmsg_t *handleAPI(sphactor_event_t *ev) // this method is called when the actor's is edited from the UI
    { if ( ev->msg ) zmsg_destroy(&ev->msg); return nullptr; }

    zmsg_t *handleSocket(sphactor_event_t *ev) // this method is called when the actor receives a message (usually OSC)
    {
        if ( ev->msg )
            zmsg_destroy(&ev->msg);
        return nullptr;
    }

    zmsg_t *handleStop(sphactor_event_t *ev) // this method is called when the actor is stopped (actor removed)
    { if ( ev->msg ) zmsg_destroy(&ev->msg); return nullptr; }
}

Once created an actor needs to be registered by calling:

sphactor_register<MyActor>( "My Actor", MyActor::capabilities );

This is usually done in GazebOSC's main.cpp

C Actor

An actor in C only constists of a function receiving an event and a string describing its capabilities:

const char * countCapabilities = "inputs\n"
                                "    input\n"
                                "        type = \"OSC\"\n"
                                "outputs\n"
                                "    output\n"
                                "        type = \"OSC\"\n";

zmsg_t *
my_count_actor( sphactor_event_t *ev, void* args )
{
    static int my_count_actor_count = 0;
    if ( streq(ev->type, "INIT")) {   // at INIT we load the capability string
        sphactor_actor_set_capability((sphactor_actor_t*)ev->actor, zconfig_str_load(countCapabilities));
    }
    else
    if ( streq(ev->type, "SOCK")) {   // SOCK is when we receive a message (usually OSC)
        my_count_actor_count++; // increment counter

        // set a custom report (used in the UI)
        zosc_t * msg = zosc_create("/report", "si",
                                   "counter", (int32_t)my_count_actor_count);

        sphactor_actor_set_custom_report_data( (sphactor_actor_t*)ev->actor, msg );
    }
    return ev->msg;
}

Register the actor as follows:

sphactor_register( "My Count Actor", &my_count_actor, zconfig_str_load(countCapabilities), NULL, NULL );

Actor Life cycle

Once an actor has been created, it has the following states:

See libsphactor for details on the actor API.

Build from source

Most dependencies are bundled in the repository. There is one main external ZeroMQ dependency you need to have available:

Dependencies for the build process / dependencies are:

If you want Python support you'll need to have a recent Python >3.7 installed!

OSX

Building Dependencies

Once the above dependencies are installed, you are ready to build Gazebosc.

Build with XCode

To create an XCode project, perform the following commands from the root gazebosc git folder:

mkdir xcodeproj
cd xcodeproj
cmake -G Xcode ..

This should generate a valid Xcode project that can run and pass tests.

Build using make

In the root gazebosc git folder:

mkdir build
cd build
cmake ..
make

The gazebosc executable will be in the bin folder!

(Debian/Ubuntu) Linux

sudo apt-get update
sudo apt-get install -y \
    build-essential libtool-bin cmake libasound2-dev \
    pkg-config autotools-dev autoconf automake \
    uuid-dev libpcre3-dev libsodium-dev python3-dev

Clone and build libzmq

git clone https://github.com/zeromq/libzmq.git
cd libzmq
./autogen.sh && ./configure --without-documentation
make
sudo make install

Building Gazebosc

Once the above dependencies are installed, you are ready to build Gazebosc:

You'll find the Gazebosc binary in the bin directory, to run:

cd bin
./gazebosc

If you want to work on Gazebosc it's easiest to use the QtCreator IDE. Just load the CMakeLists.txt as a project in QtCreator and run from there.

Raspberry Pi (Raspberry Pi OS)

Use the following script:

sudo apt install git libtool-bin libdrm-dev libgbm-dev build-essential libtool-bin cmake \
    pkg-config autotools-dev autoconf automake libevdev2 libgles2-mesa-dev \
    uuid-dev libpcre3-dev libsodium-dev python3-dev libasound2-dev libxext-dev
git clone https://github.com/zeromq/libzmq.git
cd libzmq
./autogen.sh && ./configure --without-documentation
make
sudo make install
cd ..
git clone --recurse-submodules http://github.com/hku-ect/gazebosc.git
mkdir gazebosc/build
cd gazebosc/build
cmake .. -DWITH_OPENVR=OFF 
CFLAGS=-mfpu=neon make

Windows

git clone --recurse-submodules http://github.com/hku-ect/gazebosc.git

You are now ready to code/debug as normal!

Related research