show1.py sample code

The show1.py script is a PyQt5 application for live performance of a set of stepper-motor driven sculptures. This iteration features an example scripting interface for running a performance sequencer as separate thread. It can also use simulated or physical MIDI input as events to drive an Arduino-based stepper system connected via a serial port. It includes a basic interface to a four-channel DMX controller. It includes hooks for MIDI and OSC output for extending the performance across the network.

The script and libraries are packaged as show1.zip.

The assumption is that each set piece will use a separate, customized instance of this script, so each script is configured to drive one set of four motors.

The example user interface allows driving the motors in either an incremental or impulsive mode. Knobs 1 and 2 are still frequency and damping; knobs 3 to 6 adjust the ramp speed on each axis.

Design Documentation

The specific implementation is an attempt to satisfy a number of design constraints:

  1. support offline simulated operation for code debugging

  2. support scripting commands over OSC networking

  3. provide hooks for state machine motion generators

  4. provide hooks for procedural motion primitives

  5. provide hooks for data-driven choreography

A few features of note:

  1. The script.primitives module provides a prototype for state-machine generators; it is instantiated in MainApp as self.primitives.

  2. The script.script1 module provides a prototype for procedural scripting; the script is instantiated in MainApp as self.script. Please note that the parent class rcp.script.Script provides some blocking primitives which monitor the event queue.

  3. The script.midi module separates out the customizable user interface.

Motion Primitives

The movement notation is encoded as operator messages expressed as Python tuples in which the first value is a keyword. These are essentially function calls with no return values (i.e purely for side-effects) which may be passed in message queues or over network messages. The status messages are similar but passed back to the script via the input queue.

Motion primitives

(‘pose’, name)

Move to named pose.

(‘random’, boolean)

Enable or disable the random movement generator.

Parametric primitives

(‘gains’, freq, damping)

Set all channels to the given parameters.

(‘tempo’, bpm)

Set the global tempo in beats per minute.

(‘magnitude’, factor)

Set the global scaling factor.

Status messages

(‘status’, ‘moving’)

Issued when any motor starts to move.

(‘status’, ‘stopped’)

Issued when all motors have come to rest.

(‘console’, ‘stop’)

User has clicked on the Stop button.

(‘console’, ‘reset’)

User has clicked on the Reset button.

(‘console’, ‘play’)

User has clicked on the Play button.

(‘console’, string)

User has entered a command string in the text box.

(‘script’, ‘start’)

Start message received from show controller via OSC network.

Code Documentation

show1.py

A show control system with GUI.

class show1.AppWindow(main)[source]

A custom main window which provides all GUI controls. This generally follows a model-view-controller convention in which this window provides the views, passing events to the application controller via callbacks.

apply_user_configuration(config)[source]

Apply the persistent configuration values from a configparser section proxy object.

closeEvent(event)[source]

Qt callback received before windows closes.

connect_callbacks()[source]

Finish initializing the GUI by connecting all callbacks from GUI elements to application controller methods. This allows the log window to be set up early to capture any messages from the initialization of other object.

gather_configuration(config)[source]

Update the persistent configuration values in a configparser section proxy object.

scriptButtonPressed(command)[source]

Callback invoked whenever a script pushbutton is pressed.

scriptCommandEntered()[source]

Callback invoked whenever command line text is entered on the script tab.

set_status(string)[source]

Update the status bar at the bottom of the display to show the provided string.

sliderMoved(slider, value)[source]
writeScriptConsole(string)[source]

Write output to the console text area.

class show1.MainApp[source]

Main application controller object holding any non-GUI related state.

app_has_started()[source]

Callback to be invoked right after the main event loop begins. This may be extended in child classes to implement startup behaviors which require a running event loop.

app_is_exiting()[source]

Callback invoked right before the program ends, either from a keyboard interrupt window close. This may be extended in child classes to clean up external resources, e.g., close any serial ports to remove associated lock files.

apply_configuration()[source]
dmx_slider_change(channel, value)[source]

Callback invoked when a DMX channel strip slider is moved.

frame_timer_tick()[source]
initialize_default_configuration()[source]

Method to add default configuration values. This is intended to be extended in child classes. It is called during object initialization.

poll_script_queues()[source]
save_configuration(path=None)[source]

Method to save the current configuration file. This is not called by default, it must be invoked explicitly by child classes.

script/primitives.py

class script.primitives.MotionPrimitives(main, pose_csv_path='script/poses')[source]

Class to encapsulate the set of motion primitives available for this performance. This also abstracts the basic interface to both motor and simulation and supports periodic execution.

increment_reference(winch_index, steps)[source]

Map a given winch index to the particular winch set.

increment_target(winch_index, steps)[source]

Map a given winch index to the particular winch set.

process_cue(args)[source]
set_damping(d)[source]
set_freq_damping()[source]
set_frequency(f)[source]
set_pose(name)[source]
set_speed(winch_index, steps)[source]

Map a given winch index to the particular winch set.

set_target(winch_index, steps)[source]

Map a given winch index to the particular winch set.

simulator_velocity()[source]

Extract the current velocity vector from the simulator, which is not currently reported by the serial winches.

update_for_interval(interval)[source]
user_parameter_change(parameter, value)[source]

Hook for user-controlled sliders, useful for debugging and tuning.

script/midi.py

class script.midi.WinchMIDILogic(main)[source]

Core performance logic for processing MIDI input into winch commands.

channel_pressure(channel, pressure)[source]

Process a MIDI Channel Pressure event.

control_change(channel, cc, value)[source]

Process a MIDI Control Change event.

note_off(channel, key, velocity)[source]

Process a MIDI Note Off event.

note_on(channel, key, velocity)[source]

Process a MIDI Note On event.

script/script1.py

Demonstration script class for show1.py showing a self-contained process for sequencing events over time. The inputs and outputs are deliberately constrained to message queues to preclude synchronization problems and maintain compatibility with network communication.

class script.script1.Script[source]
script_task()[source]

Entry point for the script to run on a background thread.

send_cue(*args)[source]
send_pose(name)[source]
send_reset_cue()[source]
send_show(*args)[source]
sequence()[source]

Demonstration sequence. This could be decomposed further into subroutines.