VisibleSim BlockCode Generator

How to use this BlockCode generator

This application generates a template for your VisibleSim applications (named BlockCodes), which can downloaded as a zip archive. This generator proposes to prepare a template for your VisibleSim application, including usual functions and associating methods to messages. First of all, fill in the Settings tab with:

  1. The name of your application,
  2. The desired modular robot architecture,
  3. The functions you want included in your code (pre-loading, event, ...),
  4. A list of messages you want to manage (associated to their C++ types, e.g., int, CustomType, ...)

Click on the Update and Generate button to update the form, and generate the codes.

Four files are generated according to your parameters, you can inspect them using their respective tabs and download a zip archive with all files using the Download Zip files button from the settings tab.
This archive contains a directory and the four files, you just have to copy the directory in your applicationsSrc directory of your VisibleSim installation.

Then add the name of your application in the applicationsSrc/Makefile, to add it to the list of compiled applications, and run make from the root directory of VisibleSim.

Finally, the compilation will create a new directory (with the same name of your application) in the applicationsBin directory. You must add a config.xml file before running your code.

Application name:
Robot type: Blinky Block   Smart Block   Sliding Cube   Hexanodes
2D catom   3D catom   Datom
Events parseUserElements(...)  ? Provides the user with a pointer to the configuration file parser, which can be used to read additional user information from it.parseUserBlockElements()  ? Provides the user with a pointer to the configuration file parser, which can be used to read additional user information from each block config. Has to be overridden in the child class.onBlockSelected()  ? User-implemented debug function that gets called when a module is selected in the GUI.
processLocalEvent(...)  ? Handler for all events received by the host block.onMotionEnd()  ? Callback function executed whenever the module finishes a motion.onAssertTriggered()  ? User-implemented debug function that gets called when a VS_ASSERT is triggered.
onUserKeyPressed(...)  ? User-implemented keyboard handler function.onGlDraw()  ? Call during GL drawing phase, can be used by a user to draw custom Gl content into the simulated world.onTap(...)  ? This function is called when a module is tapped by the user. Prints a message to the console by default. Can be overloaded in the user blockCode.
parseUserCommandLineArgument(...)  ? User-implemented keyboard handler function that gets called when a key press event could not be caught by openglViewer.onInterfaceDraw()  ? Called during interface drawing phase, can be used by a user to draw a custom GL string onto the bottom-left corner of the GUI.
New message void

Main file: myApp.cpp

#include <iostream>
#include "myAppCode.hpp"

using namespace std;
using namespace BlinkyBlocks;

int main(int argc, char **argv) {
    try {
        createSimulator(argc, argv, MyAppCode::buildNewBlockCode);
        getSimulator()->printInfo();
        BaseSimulator::getWorld()->printInfo();
        deleteSimulator();
    } catch(std::exception const& e) {
        cerr << "Uncaught exception: " << e.what();
    }

    return 0;
}                

File: myAppCode.cpp

#include "myAppCode.hpp"

MyAppCode::MyAppCode(BlinkyBlocksBlock *host):BlinkyBlocksBlockCode(host),module(host) {
    // @warning Do not remove block below, as a blockcode with a NULL host might be created
    //  for command line parsing
    if (not host) return;

}

void MyAppCode::startup() {
    console << "start " << module->blockId << "\n";
    if (module->blockId == 1) { // Master id is 1
        module->setColor(RED);
	}
}

Makefile


# Get current directory's name
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
APPDIR = ../../applicationsBin/$(current_dir)

#####################################################################
#
# --- Sample User Makefile ---
#
# GLOBAL_LIBS, GLOBAL_INCLUDES and GLOBAL_CFLAGS are set by parent Makefile
# HOWEVER: If calling make from the codeBlock directory (for more convenience to the user),
#	these variables will be empty. Hence we test their value and if undefined,
#	set them to predefined values.
#
# You will find instructions below on how to edit the Makefile to fit your needs.
#
# SRCS contains all the sources of your codeBlocks
SRCS = myApp.cpp myAppCode.cpp
#
# OUT is the output binary, where APPDIR is its enclosing directory
OUT = $(APPDIR)/myApp
#
# MODULELIB is the library for your target module type: -lsimBlinkyBlocks
MODULELIB = -lsimBlinkyBlocks
# TESTS contains the commands that will be executed when `make test` is called
TESTS = ../../utilities/blockCodeTest.sh myApp $(OUT)
#
# CUSTOM_LIBS are the external dependencies of your blockcode, empty by default
CUSTOM_LIBS =
#
# End of Makefile section requiring input by user
#####################################################################

OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.depends)

OS = $(shell uname -s)
SIMULATORLIB = $(MODULELIB:-l%=../../simulatorCore/lib/lib%.a)

ifeq ($(GLOBAL_INCLUDES), )
INCLUDES = -I. -I../../simulatorCore/src -I/usr/local/include -I/opt/local/include -I/usr/X11/include
else
INCLUDES = -I. -I../../simulatorCore/src $(GLOBAL_INCLUDES)
endif

ifeq ($(GLOBAL_LIBS), )
ifeq ($(OS),Darwin)
LIBS = -L./ -L../../simulatorCore/lib -L/usr/local/lib -lGLEW -lglut -framework GLUT -framework OpenGL -L/usr/X11/lib /usr/local/lib/libglut.dylib /usr/local/lib/libmuparser.dylib $(MODULELIB)
else
LIBS = -L./ -L../../simulatorCore/lib -L/usr/local/lib -L/opt/local/lib -L/usr/X11/lib -lglut -lGL -lGLU -lGLEW -lpthread -lm -ldl -lmuparser $(MODULELIB)
endif				#OS
else
LIBS = $(GLOBAL_LIBS) -L../../simulatorCore/lib
endif				#GLOBAL_LIBS

LIBS += $(CUSTOM_LIBS)

ifeq ($(GLOBAL_CCFLAGS),)
CCFLAGS = -g -Wall -std=c++17 -Wsuggest-override -fno-stack-protector
ifeq ($(OS), Darwin)
CCFLAGS += -DGL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED -Wno-deprecated-declarations -Wno-overloaded-virtual
endif
else
CCFLAGS = $(GLOBAL_CCFLAGS)
endif

CC = g++

.PHONY: clean all test

.cpp.o:
	$(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $@

%.depends: %.cpp
	$(CC) -M $(CCFLAGS) $(INCLUDES) $< > $@

all: $(OUT)
	@:

test:
	@$(TESTS)

autoinstall: $(OUT)
	cp $(OUT)  $(APPDIR)

$(APPDIR)/$(OUT): $(OUT)

$(OUT): $(SIMULATORLIB) $(OBJS)
	$(CC) -o $(OUT) $(OBJS) $(LIBS)

ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif

clean:
	rm -f *~ $(OBJS) $(OUT) $(DEPS)                    
File name:
Lattice size:(,,)
Description method
Robot's ID order Manual
Ordered
Random
Camera Camera auto
Target position: (,,)
Theta: , phi, distance
Light Camera auto
Light position: (,,)
Theta: , phi, distance
Visuals Shadows: off on
Background color:
Gradient 2nd color:

The Config file proposes a set of XML commands to describe the scene rendered in VisibleSim. To use your own myconfig.xml files, add the file as a -c parameter of your executable program in the /applicationBin/myApp directory.

~VS/myApp > ./myApp -c myconfig.xml                    

If no parameters are precised, VisibleSim try to open the config.xml files in the current directory.

It manages 3 mains elements:

  • The lattice size.
  • The initial configuration of modules, and eventually the goal shape.
  • The camera and light configuration.

The lattice

The initial configuration

Many solutions are available to describe the initial configuration shown in VisibleSim. The simplest consists in enumerate the list of modules precising they position and color. A more powerful solution is to use a vectorial description of the scene (CSG model), which allow to change the size and the position of the model.

For both methods we must create a tag <blockList color="R,G,B" blockSize="lx,ly,lz">, where (R,G,B) is the default color of the modules and (lx,ly,lz) the size of the module in the grid (the current generator will give automatically the good values for the current robots.

Each module will receive an ID, it is possible hear to choose how IDs are distributed to modules:

  • Case 1:
  • Case 2:
  • Case 3:

Modules enumeration

The simplest way to create a small configuration is to enumerate the list of modules. For each module we must precise its position in the grid (px,py,pz), if you add a color it will be used instead of the default color for the current module. <block position="px,py,pz" color="R,G,B">

For Catoms and Datoms, it is possible to add the orientation parameter...

CSG model

The CSG Config Format is very similar to the model presented by the openscad software, the model valid in VisibleSim are valid in OpenScad, but OpenScan proposes many possible syntax to create the same object.
Then the following lines presents VisibleSim capabilities:

  • We do not precise the name of parameter, only expression may be precise. Then be careful to respect the order of the parameters.
  • The list of available geometry is (with the good usage format):
    • cube([lx,ly,lz],center);
    • cylinder(height,base_radius,top_radius,center);
    • sphere(radius);
  • Transformation operators are:
    • translate([tx,ty,tz])
    • scale([hx,hy,hz])
    • rotate([rx,ry,rz])
  • Color parameters:
    • color([r,g,b])
  • Combination operators:
    • union() {…}, be careful: the union() operator must be precised for every lists of objects (not implicit).
    • intersection() {…}
    • difference() {…}
  • Only global variables are available.
  • Functions (modules) with parameters (but without recursivity).
    • Declaration of a function: module name(param1, param2) { instructions }
    • Call of a function: name(v1,v2)