Tutorial T2 – Sliders

Sometimes, it is very useful to interact with the simulation. Sliders can be used for numerous reasons, from controlling coefficients to displaying values in real-time.

```// Tutorial 2 - Sliders

// TUTORIALS ARE DESIGNED TO BE READ AND STEPPED THROUGH IN THE
// APRON SIMULATOR. THEY WILL NOT DO INTERESTING THINGS IF RAN!
// (c) David R W Barr 2011

// This tutorial introduces "sliders". Sliders are horizontal scroll
// bars that can be used to fluidly set parameters inside running
// algorithms.

!include('apron.aps')

// Create and display a register
!create('a', REGISTER, 128, 128)
sim.display(r[a])

// Create a slider - a variable is used as a handle to the slider
// so it can be identified later
handle_to_slider = sim.addSlider('Value', -100, 100, 0, 1.0, 0.1)

// The parameters for slider creation are as follows
// Name
// Minimum Value
// Maximum Value
// Default Value
// Scaling Value
// Accuracy (Minimum Step Size)

// The accuracy value determines how precisely a slider value can be set, a value of 1.0 will
// limit the slider to selecting whole numbers only. A value of 0.5 will limit the selection to
// whole numbers and half fractions, and so on etc... Here it is set to 0.1, which will limit
// the slider value to the nearest 10th.

handle_to_slider2 = sim.addSlider('Weird', -100, 100, 0, 1.0, 0.1)

t = 0 // Define a variable to store the value of a slider

// Try running now in the simulator, and move the value slider

#start
// To read a slider we use the "sim.get" function, passing along the handle
sim.get(handle_to_slider, t)
r[a] = t
sim.show(r[a])

t = t * -1

// We can also set slider positions to visualise a variable
sim.set(handle_to_slider2, t)

jump(#start)

//
// You will have noticed that the handles for the slider get classified as variables,
// which you may not want to appear in your regular variable list. To overcome this
// you could create a type derived from SIM_VARIABLE:
//
// !object('GUI', 'h', 700, 'SIM_VARIABLE')
// !create('value', 'GUI')
// !create('weird', 'GUI')
//
//
//
// In fact, this exact construct is already done for you by the APRON subsystem

end

```

Tutorial T1 – Registers

This tutorial introduces the concept of registers.

```// Tutorial 1 - Registers

// TUTORIALS ARE DESIGNED TO BE READ AND STEPPED THROUGH IN THE
// APRON SIMULATOR. THEY WILL NOT DO INTERESTING THINGS IF RAN!
// (c) David R W Barr 2011

// This tutorial shows how to construct 2D arrays, which in APRON
// are considered registers. Registers should have a multiple of 4
// elements in them. For example, an 8x8 register has 64 elements,
// which is valid. A 7x10 register is not evenly divisible by 4, and
// consequently many operations may produce unusual artifacts. Why?
// APRON uses SSE for almost all computation, which performs operations
// on 4 elements in parallel.

// However, it is OK to use odd-sized registers if you do not perform
// array operations upon them.

// For the best performance, it is recommended that registers with
// dimensions that are a power of 2 are used.

!include('apron.aps')

// Create a register labelled 'a' with dimensions 128x64. The type REGISTER
// is already defined by the APRON subsystem. The "create" function creates
// an object of type REGISTER called "a", which is 128 elements wide by 64
// elements high.
!create('a', REGISTER, 128, 64)

// We can use the "!define" preprocessor command to create some constants
// which make it easier to scale the algorithm
!define(WIDTH, 128)
!define(HEIGHT, 64)

// Create some more registers
!create('b', REGISTER, WIDTH, HEIGHT)
!create('c', REGISTER, WIDTH, HEIGHT)
!create('d', REGISTER, WIDTH, HEIGHT)
!create('e', REGISTER, WIDTH, HEIGHT)
!create('f', REGISTER, WIDTH, HEIGHT)

// All elements in a register are operated upon simultaneously. An object of type
// REGISTER can be accessed with the prefix "r".

r[a] = 35 // Set entire register to the value 35

r[b] = 55

// Basic numeric operators have already been defined in "apron.aps".
r[c] = r[a] + r[b]
r[d] = r[a] * r[b]
r[e] = r[a] / r[b]
r[f] = r[a] - r[b]

// Note that the default palette in APRON is configured to show -128 -> 0 as red, and
// 0 -> +128 as green. Palettes can be assigned algorithmically and individually. The
// global palette can be set using the "!default_palette()" preprocessor function.

// Palettes must exist in the APRON palette database. You can see this by hitting CTRL+4 in
// Crimson Editor.

r[a] = reg.setPalette('Raw', 0) // 0 -> 255 greyscale. The '0' is currently unused.

// Often it is convenient to configure the APRON Simulator via the algorithm, instead
// of manually each time you change something.

sim.display(r[a]) // Sends the register r[a] to the workspace (same as clicking on thumbnail)
sim.display(r[b])
sim.display(r[c])

sim.tile // Positions registers (same as clicking on tile button)

// Registers are mainly used to store spatial data, such as images. APRON is fast
// enough to perform many operations on video data. However, for performance reasons,
// when the simulation is "RUN" it is too slow to update the contents of all registers
// on screen. When in "RUN" mode we can use a special call to only update a selected register.

// HIT "RUN" NOW!
counter = 0
#loop
r[a] = counter
counter = counter + 1
if(counter, ==, 255)
counter = 0
endif
sim.show(r[a]) // Force an update in r[a] when running
jump(#loop)

end

```

TUTORIAL: T0 – The Basics

The code below is a good starting point for looking at the basics of APRON syntax. APRON is an interpreted functional script, where all commands are of the form y = f(x1, x2, x3). Each line of APRON code directly translates to a “virtual” hardware instruction. The simulator provided in APRON emulates an ideal processor array, that is capable of many functions.

```// Tutorial 0 - The Basics

// TUTORIALS ARE DESIGNED TO BE READ AND STEPPED THROUGH IN THE
// APRON SIMULATOR. THEY WILL NOT DO INTERESTING THINGS IF RAN!
// (c) David R W Barr 2011

// Welcome to APRON! This tutorial explains the basics of algorithm structure,
// program flow and variables. Please read to the end of this source file, following
// the instructions

// <- These double slashes are a comment. APRON does not have block comments, although
// Crimson Editor can "pretend" by selecting the text and hitting CTRL+M to comment, and
// CTRL+SHIFT+M to uncomment. Try it!

// Nearly all APRON programs need to specify they are going to use the APRON core
// for compilation and simulation. This is defined in the headerfile 'apron.aps'.
// Header files are placed directly in the code, line for line, when the pre-processor
// command "!include" is used. Be careful not to include files twice, or in the wrong order.
// The APRON compiler will catch recursive inclusions.

// Include the main APRON system
!include('apron.aps')

// The above line is a pre-processor command. We know this because it begins with !
// pre-processor commands are executed at compile time and are used to help form
// the algorithm through code-reuse, encapsulation and readability.

// Character strings in APRON are surrounded by single quotes - 'like this'
// APRON Script files have the extension "aps". There is no distinction between
// source and header files, as headers are equally just source files.

// Variables in APRON are all 32-bit floating point numbers (even the integers!)
// They are implicitly defined when written to, but must have been defined when read.

a = 3 // Create a variable "a" and set it 3.

// APRON assumes variables implied this way are of type "VARIABLE"

// Basic mathematical operators are included in the APRON core.
// APRON is an interpreted assembly language. Therefore you cannot use long
// expressions.

b = a + 7 // is valid

// but "b = a + 7 + 6"  or "b = a + 2 * b" is not.

// Why? This makes an assumption that one line of APRON code performs more than one hardware
// level instruction. This will make more sense when you reach the advanced tutorials. For now,
// treat expressions in APRON as if you were using a simple calculator from the 70's.

// Frustratingly, "b = a + 7" is good, but "b = 7 + a" is not. APRON expressions should always be
// variable = constant,
// or variable = variable,
// or variable = variable + constant,
// or variable = variable + variable

// Again reasons for this will be explained when you start designing models of procesisng hardware

// As you step through the code in the simulator you will notice the variables are listed, and
// their values change accordingly. The simulator allows you to change the value of a variable
// by double-clicking on it. A single-click higlights the variable. This may be useful when your
// algorithms become larger.

counter = 0 // Create a variable called "counter"

// Labels are code locations. For example

#loop_one
// It is conventional to indent after declaring a label

counter = counter + 1 // Increment counter

// Conditionally jump back to the label if true
jumpif(counter, <, 5, #loop_one)

// Removing the indent helps segment the above code form the rest of the program. More often
// than not you will remove the indent after a jump, jumpif, or return statement

// This is skipped - come back here in a bit...
#sneaky_subroutine
counter = 500
return

#loop_two
// We can use if..else..endif and if..endif blocks to optionally execute code
if(counter, ==, 5)
// The counter is at the correct value!
counter = counter * counter
else
// The counter has been messed with!
counter = 25
endif

// A call jumps to the given location, and places the previous location
// on a stack. When a return statement is encountered, the current
// location is swapped with the previous location.
callif(counter, ==, 25, #sneaky_subroutine)
// Like jump, calls do not have to be conditional

// Now counter should be 500
if(counter, >, 499)
if(counter, <, 501)
call(#all_good)
else
endif
else
endif

// The "end" statement stops the simulation. Permenantly.
end

#all_good
// Excellent!
score = 100 // points
return

// Booo!
score = -100 // points
return

```
Posted in Documentation, Examples | 2 Comments

Demo: Object Tracking

The following demo video shows APRON (with the aid of a CUDA plug-in) learning and tracking an object selected by the user. The algorithm behind this is quite naive, but shows surprising robustness to rotation.

Example: Simple Camera

The “Hello World” of APRON examples is the simple act of grabbing an image from a webcam and displaying it in the simulator. The script below uses the apron.webcam plugin. First the camera is initialised to capture images at a specific width and height. The program then loops repeatedly grabbing an image, and then displaying it.

``````!include('apron.aps')
!include('apron.webcam.aps')

!define(CAM_W, 128)
!define(CAM_H, 128)

!create('camera', REGISTER, CAM_W, CAM_H)

webcam.init(CAMW, CAM_H)
sim.display(r[camera])
sim.tile

#start
r[camera] = webcam.getLuminance(0)
r[camera] = r[camera] / 2
sim.show(r[camera])
jump(#start)
``````