From 151a84bcb789750555832a0c6cb2688512a57786 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 14 Oct 2020 15:00:37 +0100 Subject: [PATCH 01/54] Add bare bones of icub_vor environment --- c_code/Makefile | 2 +- c_code/icub_vor_env/Makefile | 17 + c_code/icub_vor_env/src/icub_vor_env.c | 292 ++++++++++++++++ examples/icub_vor_env/icub_vor_env_test.py | 71 ++++ spinn_gym/games/icub_vor_env/__init__.py | 0 spinn_gym/games/icub_vor_env/icub_vor_env.py | 321 ++++++++++++++++++ .../icub_vor_env_machine_vertex.py | 59 ++++ 7 files changed, 761 insertions(+), 1 deletion(-) create mode 100644 c_code/icub_vor_env/Makefile create mode 100644 c_code/icub_vor_env/src/icub_vor_env.c create mode 100644 examples/icub_vor_env/icub_vor_env_test.py create mode 100644 spinn_gym/games/icub_vor_env/__init__.py create mode 100644 spinn_gym/games/icub_vor_env/icub_vor_env.py create mode 100644 spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py diff --git a/c_code/Makefile b/c_code/Makefile index bb12b56d..3129da90 100644 --- a/c_code/Makefile +++ b/c_code/Makefile @@ -1,4 +1,4 @@ -DIRS = breakout inverted_pendulum double_inverted_pendulum multi_arm_bandit logic store_recall +DIRS = breakout inverted_pendulum double_inverted_pendulum multi_arm_bandit logic store_recall icub_vor_env #DIRS = breakout double_inverted_pendulum multi_arm_bandit logic store_recall diff --git a/c_code/icub_vor_env/Makefile b/c_code/icub_vor_env/Makefile new file mode 100644 index 00000000..6c4b926a --- /dev/null +++ b/c_code/icub_vor_env/Makefile @@ -0,0 +1,17 @@ +ifndef NEURAL_MODELLING_DIRS + $(error NEURAL_MODELLING_DIRS is not set. Please define + NEURAL_MODELLING_DIRS (possibly by running "source setup" in the + neural_modelling folder within the sPyNNaker source folder)) +endif + +APP := icub_vor_env +BUILD_DIR = $(abspath $(CURRENT_DIR)/../../build/$(APP))/ +SOURCES = icub_vor_env.c +MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +CURRENT_DIR := $(dir $(MAKEFILE_PATH)) +EXTRA_SRC_DIR := $(abspath $(CURRENT_DIR))/src +SOURCE_DIRS += $(EXTRA_SRC_DIR) +APP_OUTPUT_DIR := $(abspath $(CURRENT_DIR)../../spinn_gym/model_binaries/)/ +CFLAGS += -I$(NEURAL_MODELLING_DIRS)/src + +include $(SPINN_DIRS)/make/local.mk \ No newline at end of file diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c new file mode 100644 index 00000000..699f3435 --- /dev/null +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -0,0 +1,292 @@ +// +// icub_vor_env.c +// Environment to simulate ICub robot for particular network, see +// https://www.overleaf.com/project/5f1ee9467b6572000190b496 +// (replace with link to document in future) +// +// Copyright © 2020 Andrew Gait, Petrut Bogdan. All rights reserved. +// +// Standard includes +#include +#include +#include +#include + +// Spin 1 API includes +#include + +// Common includes +#include + +// Front end common includes +#include +#include +#include "random.h" + +#include + +//---------------------------------------------------------------------------- +// Enumerations +//---------------------------------------------------------------------------- +// Regions where information for the environment is written +typedef enum { + REGION_SYSTEM, + REGION_ICUB_VOR_ENV, + REGION_RECORDING, + REGION_ICUB_VOR_ENV_DATA, +} region_t; + +// we may need some of these at some point +//typedef enum { +// SPECIAL_EVENT_INPUT_1, +// SPECIAL_EVENT_INPUT_2, +// SPECIAL_EVENT_INPUT_3, +// SPECIAL_EVENT_INPUT_4, +// SPECIAL_EVENT_INPUT_5, +// SPECIAL_EVENT_INPUT_6, +// SPECIAL_EVENT_INPUT_7, +// SPECIAL_EVENT_INPUT_8, +//} special_event_t; + +// These are the keys to be received for left/right choice +typedef enum { + KEY_CHOICE_LEFT = 0x0, + KEY_CHOICE_RIGHT = 0x1 +} arm_key_t; + +//---------------------------------------------------------------------------- +// Globals +//---------------------------------------------------------------------------- + +static uint32_t _time; + +//! Should simulation run for ever? 0 if not +static uint32_t infinite_run; + +//! Set global variables up here +// - head position, head velocity (from array read in to start off with?) +// - error value(s) +uint32_t error_window_size; +uint32_t number_of_inputs; +accum *head_positions; +accum *head_velocities; +accum error_value; +// I'm sure there are more to be added to this list + +//! track the left and right values +uint32_t error_values[2] = {0}; + +//! The upper bits of the key value that model should transmit with +static uint32_t key; + +//! How many ticks until next window (default size 10ms) +static uint32_t tick_in_window = 0; + +//! the number of timer ticks that this model should run for before exiting. +uint32_t simulation_ticks = 0; + +//---------------------------------------------------------------------------- +// Inline functions +//---------------------------------------------------------------------------- + +// This is the function for sending a spike out from the environment, related +// to the error signal +static inline void send_spike(int input) +{ + spin1_send_mc_packet(key | (input), 0, NO_PAYLOAD); +// io_printf(IO_BUF, "sending spike to input %d\n", input); +} + +// Required if using auto-pause and resume +void resume_callback() { + recording_reset(); +} + +// Initialize environment with values sent from python DSG +static bool initialize(uint32_t *timer_period) +{ + io_printf(IO_BUF, "Initialise icub_vor_env: started\n"); + + // Get the address this core's DTCM data starts at from SRAM + data_specification_metadata_t *address = data_specification_get_data_address(); + + // Read the header + if (!data_specification_read_header(address)) { + return false; + } + + // Get the timing details and set up thse simulation interface + if (!simulation_initialise(data_specification_get_region(REGION_SYSTEM, address), + APPLICATION_NAME_HASH, timer_period, &simulation_ticks, + &infinite_run, &_time, 1, 0)) { + return false; + } + io_printf(IO_BUF, "simulation time = %u\n", simulation_ticks); + + + // Read icub_vor region, which for now contains the information about keys on received mc packets + address_t icub_vor_env_address_region = data_specification_get_region(REGION_ICUB_VOR_ENV, address); + key = icub_vor_env_address_region[0]; + io_printf(IO_BUF, "\tKey=%08x\n", key); + io_printf(IO_BUF, "\tTimer period=%d\n", *timer_period); + + // Get recording region + void *recording_region = data_specification_get_region( + REGION_RECORDING, address); + + // Setup recording + uint32_t recording_flags = 0; + if (!recording_initialize(&recording_region, &recording_flags)) { + rt_error(RTE_SWERR); + return false; + } + + // Now get the data associated with the environment + address_t icub_vor_env_data_region = data_specification_get_region(REGION_ICUB_VOR_ENV_DATA, address); + + // Ideally I guess this could be set up using a struct, but let's keep it simpler for now + error_window_size = icub_vor_env_data_region[0]; + error_value = icub_vor_env_data_region[1]; + number_of_inputs = icub_vor_env_data_region[2]; + head_positions = (accum *)&icub_vor_env_data_region[3]; + head_velocities = (accum *)&icub_vor_env_data_region[3 + number_of_inputs]; + + // Print values out to check + io_printf(IO_BUF, "error_window_size %u, error_value %u\n"); + for (uint32_t i=0; i error_values[1]) { + io_printf(IO_BUF, "error_values[0] %u > error_values[1] %u", + error_values[0], error_values[1]); + send_spike(0); + } + else { + send_spike(1); + } + } +} + +// when a packet is received, update the error +void mc_packet_received_callback(uint keyx, uint payload) +{ +// io_printf(IO_BUF, "mc_packet_received_callback"); +// io_printf(IO_BUF, "key = %x\n", keyx); +// io_printf(IO_BUF, "payload = %x\n", payload); + uint32_t compare; + compare = keyx & 0x1; +// io_printf(IO_BUF, "compare = %x\n", compare); + // If no payload has been set, make sure the loop will run + if (payload == 0) { payload = 1; } + + for (uint count = payload; count > 0; count--) { + if (compare == KEY_CHOICE_LEFT) { + // I think these are counts? + update_error(_time, 0); + } + else if (compare == KEY_CHOICE_RIGHT) { + update_error(_time, 1); + } + else { + io_printf(IO_BUF, "Unexpected key value %d\n", key); + } + } +} + +void timer_callback(uint unused, uint dummy) +{ + use(unused); + use(dummy); + + _time++; + + if (!infinite_run && _time >= simulation_ticks) { + //spin1_pause(); + recording_finalise(); + // go into pause and resume state to avoid another tick + simulation_handle_pause_resume(resume_callback); + // spin1_callback_off(MC_PACKET_RECEIVED); + + io_printf(IO_BUF, "infinite_run %d; time %d\n", infinite_run, _time); + io_printf(IO_BUF, "simulation_ticks %d\n", simulation_ticks); + // io_printf(IO_BUF, "key count Left %u\n", left_key_count); + // io_printf(IO_BUF, "key count Right %u\n", right_key_count); + + io_printf(IO_BUF, "Exiting on timer.\n"); +// simulation_handle_pause_resume(NULL); + simulation_ready_to_read(); + + _time -= 1; + return; + } + // Otherwise + else { + // Increment ticks in frame counter and if this has reached frame delay + tick_in_window++; + + // every 10ms (timesteps?) aggregate the values + if (tick_in_window == error_window_size) { + // Reset ticks in frame and update frame + tick_in_window = 0; + // Work out the error values + test_the_head(); + } + + // There is probably a point where the error values should be reset too? + + } +// io_printf(IO_BUF, "time %u\n", ticks); +// io_printf(IO_BUF, "time %u\n", _time); +} + +//---------------------------------------------------------------------------- +// Entry point +//---------------------------------------------------------------------------- +void c_main(void) +{ + // Load DTCM data + uint32_t timer_period; + if (!initialize(&timer_period)) { + io_printf(IO_BUF, "Error in initialisation - exiting!\n"); + rt_error(RTE_SWERR); + return; + } + + tick_in_window = 0; + + // Set timer tick (in microseconds) + io_printf(IO_BUF, "setting timer tick callback for %d microseconds\n", + timer_period); + spin1_set_timer_tick(timer_period); + + io_printf(IO_BUF, "simulation_ticks %d\n", simulation_ticks); + + // Register callback + spin1_callback_on(TIMER_TICK, timer_callback, 2); + spin1_callback_on(MC_PACKET_RECEIVED, mc_packet_received_callback, -1); + spin1_callback_on(MCPL_PACKET_RECEIVED, mc_packet_received_callback, -1); + + _time = UINT32_MAX; + + simulation_run(); + +} diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py new file mode 100644 index 00000000..9dde3fd1 --- /dev/null +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -0,0 +1,71 @@ +import spynnaker8 as p +import spinn_gym as gym + +from pyNN.utility.plotting import Figure, Panel +import matplotlib.pyplot as plt +import numpy as np +from spinn_front_end_common.utilities.globals_variables import get_simulator + +# Replace this with whatever is being used to get anything recorded from +# the ICubVorEnv vertex itself +def get_scores(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + scores = b_vertex.get_data( + 'score', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager, simulator.machine_time_step) + return scores.tolist() + + +p.setup(timestep=1.0) + +input_size = 2 +rate = 20 +input_pop = p.Population(input_size, p.SpikeSourcePoisson(rate=rate)) + +output_pop1 = p.Population(2, p.IF_cond_exp()) +output_pop2 = p.Population(2, p.IF_cond_exp()) + +# get head_positions and head_velocities from file +head_positions = [0, 1, 2, 3] +head_velocities = [3, 2, 1, 0] + +error_window_size = 10 +error_value = 0 +icub_vor_env_model = gym.ICubVorEnv( + head_positions, head_velocities, error_window_size, error_value) +icub_vor_env_pop = p.Population(input_size, icub_vor_env_model) + +input_pop.record('spikes') +# icub_vor_env_pop.record('spikes') +output_pop1.record('spikes') +output_pop2.record('spikes') + +i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) + +# test_rec = p.Projection(icub_vor_env_pop, icub_vor_env_pop, p.AllToAllConnector(), +# p.StaticSynapse(weight=0.1, delay=0.5)) +i2o1 = p.Projection(icub_vor_env_pop, output_pop1, p.AllToAllConnector(), + p.StaticSynapse(weight=0.1, delay=0.5)) +i2o2 = p.Projection(icub_vor_env_pop, output_pop2, p.OneToOneConnector(), + p.StaticSynapse(weight=0.1, delay=0.5)) + +simulator = get_simulator() + +runtime = 10000 +p.run(runtime) + +scores = get_scores(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) + +print(scores) + +spikes_in = input_pop.get_data('spikes').segments[0].spiketrains +spikes_out1 = output_pop1.get_data('spikes').segments[0].spiketrains +spikes_out2 = output_pop2.get_data('spikes').segments[0].spiketrains +Figure( + Panel(spikes_in, xlabel="Time (ms)", ylabel="nID", xticks=True), + Panel(spikes_out1, xlabel="Time (ms)", ylabel="nID", xticks=True), + Panel(spikes_out2, xlabel="Time (ms)", ylabel="nID", xticks=True) +) +plt.show() + +p.end() diff --git a/spinn_gym/games/icub_vor_env/__init__.py b/spinn_gym/games/icub_vor_env/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py new file mode 100644 index 00000000..dc6886ff --- /dev/null +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -0,0 +1,321 @@ +from spinn_utilities.overrides import overrides + +# PACMAN imports +from pacman.executor.injection_decorator import inject_items +from pacman.model.constraints.key_allocator_constraints import \ + ContiguousKeyRangeContraint +from pacman.model.graphs.application import ApplicationVertex +from pacman.model.resources.cpu_cycles_per_tick_resource import \ + CPUCyclesPerTickResource +from pacman.model.resources.dtcm_resource import DTCMResource +from pacman.model.resources.resource_container import ResourceContainer +from pacman.model.resources.variable_sdram import VariableSDRAM + +from data_specification.enums.data_type import DataType + +# SpinnFrontEndCommon imports +from spinn_front_end_common.abstract_models import AbstractChangableAfterRun +from spinn_front_end_common.interface.buffer_management \ + import recording_utilities +from spinn_front_end_common.abstract_models \ + .abstract_generates_data_specification \ + import AbstractGeneratesDataSpecification +from spinn_front_end_common.abstract_models. \ + abstract_provides_outgoing_partition_constraints import \ + AbstractProvidesOutgoingPartitionConstraints +from spinn_front_end_common.utilities import globals_variables +from spinn_front_end_common.interface.simulation import simulation_utilities +from spinn_front_end_common.utilities import constants as \ + front_end_common_constants +from spinn_front_end_common.utilities.exceptions import ConfigurationException + +# sPyNNaker imports +from spynnaker.pyNN.models.abstract_models import \ + AbstractAcceptsIncomingSynapses +from spynnaker.pyNN.models.common import AbstractNeuronRecordable +from spynnaker.pyNN.utilities import constants +from spynnaker.pyNN.models.common.simple_population_settable \ + import SimplePopulationSettable + +# ICubVorEnv imports +from spinn_gym.games.icub_vor_env.icub_vor_env_machine_vertex \ + import ICubVorEnvMachineVertex + +import numpy + +NUMPY_DATA_ELEMENT_TYPE = numpy.double + +# ---------------------------------------------------------------------------- +# ICubVorEnv +# ---------------------------------------------------------------------------- +class ICubVorEnv(ApplicationVertex, AbstractGeneratesDataSpecification, + AbstractProvidesOutgoingPartitionConstraints, + AbstractAcceptsIncomingSynapses, AbstractNeuronRecordable, + SimplePopulationSettable): + + @overrides(AbstractAcceptsIncomingSynapses.get_connections_from_machine) + def get_connections_from_machine( + self, transceiver, placement, edge, routing_infos, + synapse_information, machine_time_step, using_extra_monitor_cores, + placements=None, monitor_api=None, fixed_routes=None, + extra_monitor=None): + + # TODO: make this work properly (the following call does nothing) + + super(ICubVorEnv, self).get_connections_from_machine( + transceiver, placement, edge, routing_infos, + synapse_information, machine_time_step, using_extra_monitor_cores, + placements, monitor_api, fixed_routes, extra_monitor) + + def set_synapse_dynamics(self, synapse_dynamics): + pass + + @overrides(AbstractAcceptsIncomingSynapses.add_pre_run_connection_holder) + def add_pre_run_connection_holder( + self, connection_holder, projection_edge, synapse_information): + super(ICubVorEnv, self).add_pre_run_connection_holder( + connection_holder, projection_edge, synapse_information) + + def clear_connection_cache(self): + pass + + @overrides(AbstractAcceptsIncomingSynapses.get_synapse_id_by_target) + def get_synapse_id_by_target(self, target): + return 0 + + ICUB_VOR_ENV_REGION_BYTES = 4 + BASE_DATA_REGION_BYTES = 3 * 4 + MAX_SIM_DURATION = 1000 * 60 * 60 * 24 # 1 day + + # parameters expected by PyNN + default_parameters = { + 'error_window_size': 10, + 'error_value': 0.0, + 'constraints': None, + 'label': "ICubVorEnv", + 'incoming_spike_buffer_size': None, + 'duration': MAX_SIM_DURATION} + + def __init__(self, head_positions, head_velocities, + error_window_size=default_parameters['error_window_size'], + error_value=default_parameters['error_value'], + constraints=default_parameters['constraints'], + label=default_parameters['label'], + incoming_spike_buffer_size=default_parameters[ + 'incoming_spike_buffer_size'], + simulation_duration_ms=default_parameters['duration']): + # **NOTE** n_neurons currently ignored - width and height will be + # specified as additional parameters, forcing their product to be + # duplicated in n_neurons seems pointless + + self._label = label + + # Pass in variables + self._head_positions = head_positions + self._head_velocities = head_velocities + self._error_window_size = error_window_size + self._error_value = error_value + self._number_of_inputs = len(head_positions) + if self._number_of_inputs != len(head_velocities): + raise ConfigurationException( + "The length of head_positions {} is not the same as the " + "length of head_velocities {}".format( + self._number_of_inputs, len(head_velocities))) + + # n_neurons is the number of atoms in the network, which in this + # case only needs to be 2 (for receiving "left" and "right") + self._n_neurons = 2 + + # used to define size of recording region + self._recording_size = int((simulation_duration_ms / 1000.) * 4) + + # Superclasses + ApplicationVertex.__init__( + self, label, constraints, self.n_atoms) + AbstractProvidesOutgoingPartitionConstraints.__init__(self) + SimplePopulationSettable.__init__(self) + AbstractChangableAfterRun.__init__(self) + AbstractAcceptsIncomingSynapses.__init__(self) + self._change_requires_mapping = True + # get config from simulator + config = globals_variables.get_simulator().config + + if incoming_spike_buffer_size is None: + self._incoming_spike_buffer_size = config.getint( + "Simulation", "incoming_spike_buffer_size") + + def neurons(self): + return self._n_neurons + + def get_maximum_delay_supported_in_ms(self, machine_time_step): + # ICubVorEnv has no synapses so can simulate only one time step of delay + return machine_time_step / 1000.0 + + # ------------------------------------------------------------------------ + # ApplicationVertex overrides + # ------------------------------------------------------------------------ + @overrides(ApplicationVertex.get_resources_used_by_atoms) + def get_resources_used_by_atoms(self, vertex_slice): + # **HACK** only way to force no partitioning is to zero dtcm and cpu + container = ResourceContainer( + sdram=VariableSDRAM(fixed_sdram=0, per_timestep_sdram=4), + dtcm=DTCMResource(0), + cpu_cycles=CPUCyclesPerTickResource(0)) + + return container + + @overrides(ApplicationVertex.create_machine_vertex) + def create_machine_vertex(self, vertex_slice, resources_required, + label=None, constraints=None): + # Return suitable machine vertex + return ICubVorEnvMachineVertex( + resources_required, constraints, self._label, self, vertex_slice) + + @property + @overrides(ApplicationVertex.n_atoms) + def n_atoms(self): + return self._n_neurons + + # ------------------------------------------------------------------------ + # AbstractGeneratesDataSpecification overrides + # ------------------------------------------------------------------------ + @inject_items({"machine_time_step": "MachineTimeStep", + "time_scale_factor": "TimeScaleFactor", + "routing_info": "MemoryRoutingInfos", + "tags": "MemoryTags"}) + @overrides(AbstractGeneratesDataSpecification.generate_data_specification, + additional_arguments={"machine_time_step", "time_scale_factor", + "routing_info", "tags"} + ) + def generate_data_specification(self, spec, placement, machine_time_step, + time_scale_factor, routing_info, tags): + vertex = placement.vertex + + spec.comment("\n*** Spec for ICubVorEnv Instance ***\n\n") + spec.comment("\nReserving memory space for data regions:\n\n") + + # Reserve memory: + spec.reserve_memory_region( + region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.SYSTEM.value, + size=front_end_common_constants.SYSTEM_BYTES_REQUIREMENT, + label='setup') + spec.reserve_memory_region( + region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS + .ICUB_VOR_ENV.value, + size=self.ICUB_VOR_ENV_REGION_BYTES, label='ICubVorEnvParams') + # reserve recording region + spec.reserve_memory_region( + ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.RECORDING.value, + recording_utilities.get_recording_header_size(1)) + spec.reserve_memory_region( + region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value, + size=self.BASE_DATA_REGION_BYTES+(self._number_of_inputs*8), + label='ICubVorEnvArms') + + # Write setup region + spec.comment("\nWriting setup region:\n") + spec.switch_write_focus( + ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.SYSTEM.value) + spec.write_array(simulation_utilities.get_simulation_header_array( + vertex.get_binary_file_name(), machine_time_step, + time_scale_factor)) + + # Write icub_vor_env region containing routing key to transmit with + spec.comment("\nWriting icub_vor_env region:\n") + spec.switch_write_focus( + ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.ICUB_VOR_ENV.value) + spec.write_value(routing_info.get_first_key_from_pre_vertex( + vertex, constants.SPIKE_PARTITION_ID)) + + # Write recording region for score + spec.comment("\nWriting icub_vor_env recording region:\n") + spec.switch_write_focus( + ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.RECORDING.value) + ip_tags = tags.get_ip_tags_for_vertex(self) or [] + spec.write_array(recording_utilities.get_recording_header_array( + [self._recording_size], ip_tags=ip_tags)) + + # Write probabilites for arms + spec.comment("\nWriting icub_vor_env data region:\n") + spec.switch_write_focus( + ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value) + spec.write_value(self._error_window_size, data_type=DataType.UINT32) + spec.write_value(self._error_value, data_type=DataType.UINT32) + spec.write_value(self._number_of_inputs, data_type=DataType.UINT32) + # Write the data - Arrays must be 32-bit values, so convert + data = numpy.array(self._head_positions, dtype=numpy.uint32) + spec.write_array(data.view(numpy.uint32)) + data = numpy.array(self._head_velocities, dtype=numpy.uint32) + spec.write_array(data.view(numpy.uint32)) + + # End-of-Spec: + spec.end_specification() + + # ------------------------------------------------------------------------ + # AbstractProvidesOutgoingPartitionConstraints overrides + # ------------------------------------------------------------------------ + @overrides(AbstractProvidesOutgoingPartitionConstraints. + get_outgoing_partition_constraints) + def get_outgoing_partition_constraints(self, partition): + return [ContiguousKeyRangeContraint()] + + @property + @overrides(AbstractChangableAfterRun.requires_mapping) + def requires_mapping(self): + return self._change_requires_mapping + + @overrides(AbstractChangableAfterRun.mark_no_changes) + def mark_no_changes(self): + self._change_requires_mapping = False + + @overrides(SimplePopulationSettable.set_value) + def set_value(self, key, value): + SimplePopulationSettable.set_value(self, key, value) + self._change_requires_neuron_parameters_reload = True + + # ------------------------------------------------------------------------ + # Recording overrides + # ------------------------------------------------------------------------ + @overrides( + AbstractNeuronRecordable.clear_recording) + def clear_recording( + self, variable, buffer_manager, placements): + self._clear_recording_region(buffer_manager, placements, 0) + + @overrides(AbstractNeuronRecordable.get_recordable_variables) + def get_recordable_variables(self): + return 'score' # whatever this "records" will probably not be "score" + + @overrides(AbstractNeuronRecordable.is_recording) + def is_recording(self, variable): + return True + + @overrides(AbstractNeuronRecordable.set_recording) + def set_recording(self, variable, new_state=True, sampling_interval=None, + indexes=None): + pass + + @overrides(AbstractNeuronRecordable.get_neuron_sampling_interval) + def get_neuron_sampling_interval(self, variable): + return 10000 # 10 seconds hard coded in bkout.c + + @overrides(AbstractNeuronRecordable.get_data) + def get_data(self, variable, n_machine_time_steps, placements, + buffer_manager, machine_time_step): + vertex = self.machine_vertices.pop() + print('get_data from machine vertex ', vertex) + placement = placements.get_placement_of_vertex(vertex) + + # Read the data recorded + data_values, _ = buffer_manager.get_data_by_placement(placement, 0) + data = data_values + + numpy_format = list() + numpy_format.append(("Score", numpy.int32)) + + output_data = numpy.array(data, dtype=numpy.uint8).view(numpy_format) + + return output_data + + def reset_ring_buffer_shifts(self): + pass diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py new file mode 100644 index 00000000..3530b224 --- /dev/null +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -0,0 +1,59 @@ +from enum import Enum + +from spinn_utilities.overrides import overrides + +# PACMAN imports +from pacman.model.graphs.machine import MachineVertex + +# SpinnFrontEndCommon imports +from spinn_front_end_common.utilities import helpful_functions +from spinn_front_end_common.interface.buffer_management.buffer_models import \ + AbstractReceiveBuffersToHost +from spinn_front_end_common.abstract_models.abstract_has_associated_binary \ + import AbstractHasAssociatedBinary +from spinn_front_end_common.utilities.utility_objs import ExecutableType + + +# ---------------------------------------------------------------------------- +# ICubVorEnvMachineVertex +# ---------------------------------------------------------------------------- +class ICubVorEnvMachineVertex(MachineVertex, AbstractReceiveBuffersToHost, + AbstractHasAssociatedBinary): + _ICUB_VOR_ENV_REGIONS = Enum( + value="_ICUB_VOR_ENV_REGIONS", + names=[('SYSTEM', 0), + ('ICUB_VOR_ENV', 1), + ('RECORDING', 2), + ('DATA', 3)]) + + def __init__(self, resources_required, constraints=None, label=None, + app_vertex=None, vertex_slice=None): + # Superclasses + MachineVertex.__init__( + self, label, constraints, app_vertex, vertex_slice) + self._resource_required = resources_required + + @property + def resources_required(self): + return self._resource_required + + def get_minimum_buffer_sdram_usage(self): + return 0 # probably should make this a user input + + def get_recorded_region_ids(self): + return [0] + + def get_recording_region_base_address(self, txrx, placement): + return helpful_functions.locate_memory_region_for_placement( + placement, self._ICUB_VOR_ENV_REGIONS.RECORDING.value, txrx) + + def get_n_keys_for_partition(self, partition): + return 8 # for control IDs (CHECK: this should be 2, right?) + + @overrides(AbstractHasAssociatedBinary.get_binary_file_name) + def get_binary_file_name(self): + return "icub_vor_env.aplx" + + @overrides(AbstractHasAssociatedBinary.get_binary_start_type) + def get_binary_start_type(self): + return ExecutableType.USES_SIMULATION_INTERFACE From 526026c19a44834f2d7064b45b385d074a75ccfc Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 28 Oct 2020 14:35:51 +0000 Subject: [PATCH 02/54] First working (simplified) ICubVorEnv vertex and example test --- c_code/icub_vor_env/src/icub_vor_env.c | 187 +-- examples/icub_vor_env/icub_vor_env_test.py | 124 +- .../normalised_head_positions_1000.csv | 1000 +++++++++++++++++ .../normalised_head_velocities_1000.csv | 1000 +++++++++++++++++ spinn_gym/games/icub_vor_env/icub_vor_env.py | 110 +- .../icub_vor_env_machine_vertex.py | 8 +- 6 files changed, 2298 insertions(+), 131 deletions(-) create mode 100644 examples/icub_vor_env/normalised_head_positions_1000.csv create mode 100644 examples/icub_vor_env/normalised_head_velocities_1000.csv diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 699f3435..88536797 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -36,7 +36,7 @@ typedef enum { REGION_ICUB_VOR_ENV_DATA, } region_t; -// we may need some of these at some point +// we may need some of these at some point, so keeping them for now //typedef enum { // SPECIAL_EVENT_INPUT_1, // SPECIAL_EVENT_INPUT_2, @@ -52,7 +52,7 @@ typedef enum { typedef enum { KEY_CHOICE_LEFT = 0x0, KEY_CHOICE_RIGHT = 0x1 -} arm_key_t; +} lr_key_t; //---------------------------------------------------------------------------- // Globals @@ -63,24 +63,35 @@ static uint32_t _time; //! Should simulation run for ever? 0 if not static uint32_t infinite_run; -//! Set global variables up here -// - head position, head velocity (from array read in to start off with?) -// - error value(s) +//! Parameters set from Python code go here +// - error_window_size +// - number_of_inputs +// - head position, head velocity arrays +// - perfect eye position, perfect eye velocity arrays (unused at present) uint32_t error_window_size; uint32_t number_of_inputs; accum *head_positions; accum *head_velocities; -accum error_value; -// I'm sure there are more to be added to this list +accum *perfect_eye_pos; +accum *perfect_eye_vel; -//! track the left and right values -uint32_t error_values[2] = {0}; +//accum *eye_pos; +//accum *eye_vel; + +//! Global error value +accum error_value = 0.0k; + +//! count left and right spikes +uint32_t spike_counters[2] = {0}; //! The upper bits of the key value that model should transmit with static uint32_t key; -//! How many ticks until next window (default size 10ms) -static uint32_t tick_in_window = 0; +//! How many ticks until next error window (default size 10ms) +static uint32_t tick_in_error_window = 0; + +//! How many ticks until end of head loop +static uint32_t tick_in_head_loop = 0; //! the number of timer ticks that this model should run for before exiting. uint32_t simulation_ticks = 0; @@ -89,8 +100,8 @@ uint32_t simulation_ticks = 0; // Inline functions //---------------------------------------------------------------------------- -// This is the function for sending a spike out from the environment, related -// to the error signal +// This is the function for sending a spike out from the environment, currently +// related to the counts at the Left and Right atoms static inline void send_spike(int input) { spin1_send_mc_packet(key | (input), 0, NO_PAYLOAD); @@ -146,44 +157,33 @@ static bool initialize(uint32_t *timer_period) // Ideally I guess this could be set up using a struct, but let's keep it simpler for now error_window_size = icub_vor_env_data_region[0]; - error_value = icub_vor_env_data_region[1]; - number_of_inputs = icub_vor_env_data_region[2]; - head_positions = (accum *)&icub_vor_env_data_region[3]; - head_velocities = (accum *)&icub_vor_env_data_region[3 + number_of_inputs]; - - // Print values out to check - io_printf(IO_BUF, "error_window_size %u, error_value %u\n"); - for (uint32_t i=0; i error_values[1]) { - io_printf(IO_BUF, "error_values[0] %u > error_values[1] %u", - error_values[0], error_values[1]); - send_spike(0); - } - else { - send_spike(1); - } - } +void update_count(uint32_t index) { + // Update the count values in here when a mc packet is received +// io_printf(IO_BUF, "At time %u, update index %u \n", _time, index); + spike_counters[index] += 1; } // when a packet is received, update the error @@ -194,17 +194,17 @@ void mc_packet_received_callback(uint keyx, uint payload) // io_printf(IO_BUF, "payload = %x\n", payload); uint32_t compare; compare = keyx & 0x1; -// io_printf(IO_BUF, "compare = %x\n", compare); + // If no payload has been set, make sure the loop will run if (payload == 0) { payload = 1; } + // Update the spike counters based on the key value for (uint count = payload; count > 0; count--) { if (compare == KEY_CHOICE_LEFT) { - // I think these are counts? - update_error(_time, 0); + update_count(0); } else if (compare == KEY_CHOICE_RIGHT) { - update_error(_time, 1); + update_count(1); } else { io_printf(IO_BUF, "Unexpected key value %d\n", key); @@ -212,6 +212,41 @@ void mc_packet_received_callback(uint keyx, uint payload) } } +// Test the counters for the head after this loop +void test_the_head() { + // Here I am testing this is working by sending a spike out to + // wherever this vertex connects to, depending on which counter is higher. + if (spike_counters[0] > spike_counters[1]) { +// io_printf(IO_BUF, "spike_counters[0] %u > spike_counters[1] %u \n", +// spike_counters[0], spike_counters[1]); + send_spike(0); + // L > R so "move eye left" (blank for now while we decide how to do this) + + } + else { +// io_printf(IO_BUF, "spike_counters[0] %u <= spike_counters[1] %u \n", +// spike_counters[0], spike_counters[1]); + send_spike(1); + // L <= R so "move eye right" (blank for now while we decide how to do this) + + } + + // Here is where the error should be calculated: for now measure the error + // from the default eye position (middle = 0.5) and default velocity (0.0) + accum DEFAULT_EYE_POS = 0.5k; + accum DEFAULT_EYE_VEL = 0.0k; + + // I'm not sure whether this should be an absolute error or not... + accum error_pos = absk(head_positions[tick_in_head_loop] - DEFAULT_EYE_POS); + accum error_vel = absk(head_velocities[tick_in_head_loop] - DEFAULT_EYE_VEL); + error_value = error_pos + error_vel; + + // The above could easily be replaced by a comparison to the perfect eye + // position and velocity at the current value of tick_in_head_loop, once it has + // been worked out how the spike counters at L and R translate to head/eye movement + +} + void timer_callback(uint unused, uint dummy) { use(unused); @@ -219,20 +254,18 @@ void timer_callback(uint unused, uint dummy) _time++; + // If the time has run out if (!infinite_run && _time >= simulation_ticks) { //spin1_pause(); recording_finalise(); + // go into pause and resume state to avoid another tick simulation_handle_pause_resume(resume_callback); - // spin1_callback_off(MC_PACKET_RECEIVED); io_printf(IO_BUF, "infinite_run %d; time %d\n", infinite_run, _time); io_printf(IO_BUF, "simulation_ticks %d\n", simulation_ticks); - // io_printf(IO_BUF, "key count Left %u\n", left_key_count); - // io_printf(IO_BUF, "key count Right %u\n", right_key_count); io_printf(IO_BUF, "Exiting on timer.\n"); -// simulation_handle_pause_resume(NULL); simulation_ready_to_read(); _time -= 1; @@ -240,22 +273,38 @@ void timer_callback(uint unused, uint dummy) } // Otherwise else { - // Increment ticks in frame counter and if this has reached frame delay - tick_in_window++; - - // every 10ms (timesteps?) aggregate the values - if (tick_in_window == error_window_size) { - // Reset ticks in frame and update frame - tick_in_window = 0; - // Work out the error values - test_the_head(); + // Increment ticks for head loop and error window + tick_in_head_loop++; + tick_in_error_window++; + + // Test whether we have reached the end of the head inputs + if (tick_in_head_loop == number_of_inputs) { + // Reset back to zero if so + tick_in_head_loop = 0; } - // There is probably a point where the error values should be reset too? + // If ticks_in_error_window has reached error_window_size then compare + // the counters and calculate error + if (tick_in_error_window == error_window_size) { + // Check spike counters and calculate error value + test_the_head(); + + // Do recording + recording_record(0, &spike_counters[0], 4); + recording_record(1, &spike_counters[1], 4); + recording_record(2, &error_value, 4); + recording_record(3, &head_positions[tick_in_head_loop], 4); + recording_record(4, &head_velocities[tick_in_head_loop], 4); + + // Reset ticks in error window + tick_in_error_window = 0; + + // Reset the spike_counters + spike_counters[0] = 0; + spike_counters[1] = 0; + } } -// io_printf(IO_BUF, "time %u\n", ticks); -// io_printf(IO_BUF, "time %u\n", _time); } //---------------------------------------------------------------------------- @@ -271,7 +320,9 @@ void c_main(void) return; } - tick_in_window = 0; + // Initialise (probably unnecessary...) + tick_in_error_window = 0; + tick_in_head_loop = 0; // Set timer tick (in microseconds) io_printf(IO_BUF, "setting timer tick callback for %d microseconds\n", @@ -280,7 +331,7 @@ void c_main(void) io_printf(IO_BUF, "simulation_ticks %d\n", simulation_ticks); - // Register callback + // Register callbacks spin1_callback_on(TIMER_TICK, timer_callback, 2); spin1_callback_on(MC_PACKET_RECEIVED, mc_packet_received_callback, -1); spin1_callback_on(MCPL_PACKET_RECEIVED, mc_packet_received_callback, -1); diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 9dde3fd1..303ccb2a 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -4,68 +4,132 @@ from pyNN.utility.plotting import Figure, Panel import matplotlib.pyplot as plt import numpy as np +import os from spinn_front_end_common.utilities.globals_variables import get_simulator -# Replace this with whatever is being used to get anything recorded from -# the ICubVorEnv vertex itself -def get_scores(icub_vor_env_pop, simulator): +# Examples of get functions for variables +def get_error(icub_vor_env_pop, simulator): b_vertex = icub_vor_env_pop._vertex - scores = b_vertex.get_data( - 'score', simulator.no_machine_time_steps, simulator.placements, + error = b_vertex.get_data( + 'error', simulator.no_machine_time_steps, simulator.placements, simulator.buffer_manager, simulator.machine_time_step) - return scores.tolist() + return error.tolist() +def get_l_count(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + left_count = b_vertex.get_data( + 'L_count', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager, simulator.machine_time_step) + return left_count.tolist() + + +def get_r_count(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + right_count = b_vertex.get_data( + 'R_count', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager, simulator.machine_time_step) + return right_count.tolist() + + +def get_head_pos(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + head_positions = b_vertex.get_data( + 'head_pos', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager, simulator.machine_time_step) + return head_positions.tolist() + + +def get_head_vel(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + head_velocities = b_vertex.get_data( + 'head_vel', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager, simulator.machine_time_step) + return head_velocities.tolist() + + +# Setup p.setup(timestep=1.0) +# Build input SSP and output population input_size = 2 rate = 20 input_pop = p.Population(input_size, p.SpikeSourcePoisson(rate=rate)) -output_pop1 = p.Population(2, p.IF_cond_exp()) -output_pop2 = p.Population(2, p.IF_cond_exp()) +output_pop = p.Population(2, p.IF_cond_exp()) -# get head_positions and head_velocities from file -head_positions = [0, 1, 2, 3] -head_velocities = [3, 2, 1, 0] +# get head_positions and head_velocities from file (1000 samples) +base_dir = "./" +head_pos = np.loadtxt(os.path.join( + base_dir, "normalised_head_positions_1000.csv")) +head_vel = np.loadtxt(os.path.join( + base_dir, "normalised_head_velocities_1000.csv")) +# perfect eye positions and velocities are exactly out of phase with head +perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) +perfect_eye_vel = np.concatenate((head_vel[500:], head_vel[:500])) + +# build ICubVorEnv model pop error_window_size = 10 -error_value = 0 icub_vor_env_model = gym.ICubVorEnv( - head_positions, head_velocities, error_window_size, error_value) + head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size) icub_vor_env_pop = p.Population(input_size, icub_vor_env_model) +# Set recording for input and output pop (env pop records by default) input_pop.record('spikes') -# icub_vor_env_pop.record('spikes') -output_pop1.record('spikes') -output_pop2.record('spikes') +output_pop.record('spikes') +# Input -> ICubVorEnv projection i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) -# test_rec = p.Projection(icub_vor_env_pop, icub_vor_env_pop, p.AllToAllConnector(), -# p.StaticSynapse(weight=0.1, delay=0.5)) -i2o1 = p.Projection(icub_vor_env_pop, output_pop1, p.AllToAllConnector(), - p.StaticSynapse(weight=0.1, delay=0.5)) -i2o2 = p.Projection(icub_vor_env_pop, output_pop2, p.OneToOneConnector(), - p.StaticSynapse(weight=0.1, delay=0.5)) +# ICubVorEnv -> output projection +i2o2 = p.Projection(icub_vor_env_pop, output_pop, p.OneToOneConnector(), + p.StaticSynapse(weight=0.1, delay=1.0)) +# Store simulator and run simulator = get_simulator() - runtime = 10000 p.run(runtime) -scores = get_scores(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) - -print(scores) +# Get the data from the ICubVorEnv pop +errors = get_error(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) +l_counts = get_l_count(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) +r_counts = get_r_count(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) +rec_head_pos = get_head_pos( + icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) +rec_head_vel = get_head_vel( + icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) +# get the spike data from input and output and plot spikes_in = input_pop.get_data('spikes').segments[0].spiketrains -spikes_out1 = output_pop1.get_data('spikes').segments[0].spiketrains -spikes_out2 = output_pop2.get_data('spikes').segments[0].spiketrains +spikes_out = output_pop.get_data('spikes').segments[0].spiketrains Figure( Panel(spikes_in, xlabel="Time (ms)", ylabel="nID", xticks=True), - Panel(spikes_out1, xlabel="Time (ms)", ylabel="nID", xticks=True), - Panel(spikes_out2, xlabel="Time (ms)", ylabel="nID", xticks=True) + Panel(spikes_out, xlabel="Time (ms)", ylabel="nID", xticks=True) ) plt.show() +# plot the data from the ICubVorEnv pop +x_plot = [(n) for n in range(0, runtime, error_window_size)] +plt.figure(figsize=(10, 7)) +plt.subplot(3, 1, 1) +plt.plot(x_plot, rec_head_pos, label="head position") +plt.plot(x_plot, rec_head_vel, label="head velocity") +# plt.plot(perfect_eye_pos, label="eye position", ls='--') +# plt.plot(perfect_eye_vel, label="eye velocity", ls='--') +plt.legend(loc="best") +plt.xlim([0, runtime]) + +plt.subplot(3, 1, 2) +plt.plot(x_plot, errors, label="errors") +plt.legend(loc="best") +plt.xlim([0, runtime]) + +plt.subplot(3, 1, 3) +plt.plot(x_plot, l_counts, 'bo', label="l_counts") +plt.plot(x_plot, r_counts, 'ro', label="r_counts") +plt.legend(loc="best") +plt.xlim([0, runtime]) +plt.show() + p.end() diff --git a/examples/icub_vor_env/normalised_head_positions_1000.csv b/examples/icub_vor_env/normalised_head_positions_1000.csv new file mode 100644 index 00000000..a66f167a --- /dev/null +++ b/examples/icub_vor_env/normalised_head_positions_1000.csv @@ -0,0 +1,1000 @@ +5.000000000000000000e-01 +4.968584280172205769e-01 +4.937169800583237067e-01 +4.905757801422959141e-01 +4.874349522783312239e-01 +4.842946204609358540e-01 +4.811549086650327434e-01 +4.780159408410675770e-01 +4.748778409101152009e-01 +4.717407327589877020e-01 +4.686047402353433200e-01 +4.654699871427970814e-01 +4.623365972360336529e-01 +4.592046942159212497e-01 +4.560744017246283755e-01 +4.529458433407428375e-01 +4.498191425743925387e-01 +4.466944228623700996e-01 +4.435718075632591462e-01 +4.404514199525650930e-01 +4.373333832178478708e-01 +4.342178204538587050e-01 +4.311048546576810025e-01 +4.279946087238739594e-01 +4.248872054396214404e-01 +4.217827674798845239e-01 +4.186814174025581536e-01 +4.155832776436330644e-01 +4.124884705123619821e-01 +4.093971181864313191e-01 +4.063093427071376995e-01 +4.032252659745698686e-01 +4.001450097427964869e-01 +3.970686956150593638e-01 +3.939964450389726869e-01 +3.909283793017287456e-01 +3.878646195253094286e-01 +3.848052866617047152e-01 +3.817505014881376613e-01 +3.787003846022963249e-01 +3.756550564175726303e-01 +3.726146371583089478e-01 +3.695792468550515575e-01 +3.665490053398122172e-01 +3.635240322413374470e-01 +3.605044469803853624e-01 +3.574903687650119455e-01 +3.544819165858640875e-01 +3.514792092114825128e-01 +3.484823651836130298e-01 +3.454915028125263299e-01 +3.425067401723476124e-01 +3.395281950963952022e-01 +3.365559851725287155e-01 +3.335902277385066617e-01 +3.306310398773543158e-01 +3.276785384127414713e-01 +3.247328399043704628e-01 +3.217940606433745687e-01 +3.188623166477271287e-01 +3.159377236576610404e-01 +3.130203971310997479e-01 +3.101104522390994434e-01 +3.072080038613017594e-01 +3.043131665813987863e-01 +3.014260546826096898e-01 +2.985467821431686541e-01 +2.956754626318254808e-01 +2.928122095033579009e-01 +2.899571357940968763e-01 +2.871103542174636702e-01 +2.842719771595204614e-01 +2.814421166745335601e-01 +2.786208844805492801e-01 +2.758083919549839114e-01 +2.730047501302266255e-01 +2.702100696892560938e-01 +2.674244609612708157e-01 +2.646480339173337692e-01 +2.618808981660304402e-01 +2.591231629491423383e-01 +2.563749371373338914e-01 +2.536363292258542179e-01 +2.509074473302546071e-01 +2.481883991821196012e-01 +2.454792921248143411e-01 +2.427802331092467902e-01 +2.400913286896452226e-01 +2.374126850193521987e-01 +2.347444078466329742e-01 +2.320866025105016717e-01 +2.294393739365621077e-01 +2.268028266328654674e-01 +2.241770646857849103e-01 +2.215621917559060239e-01 +2.189583110739347360e-01 +2.163655254366217418e-01 +2.137839372027045548e-01 +2.112136482888661848e-01 +2.086547601657119666e-01 +2.061073738537634592e-01 +2.035715899194703860e-01 +2.010475084712405880e-01 +1.985352291554876580e-01 +1.960348511526972815e-01 +1.935464731735118127e-01 +1.910701934548328373e-01 +1.886061097559437183e-01 +1.861543193546497665e-01 +1.837149190434377577e-01 +1.812880051256551828e-01 +1.788736734117077898e-01 +1.764720192152779144e-01 +1.740831373495606293e-01 +1.717071221235217382e-01 +1.693440673381740869e-01 +1.669940662828741373e-01 +1.646572117316399964e-01 +1.623335959394877348e-01 +1.600233106387904114e-01 +1.577264470356556925e-01 +1.554430958063257595e-01 +1.531733470935975339e-01 +1.509172905032637180e-01 +1.486750151005754306e-01 +1.464466094067262691e-01 +1.442321613953573278e-01 +1.420317584890844753e-01 +1.398454875560465327e-01 +1.376734349064766827e-01 +1.355156862892942238e-01 +1.333723268887200553e-01 +1.312434413209130624e-01 +1.291291136306304266e-01 +1.270294272879089748e-01 +1.249444651847701759e-01 +1.228743096319481060e-01 +1.208190423556390614e-01 +1.187787444942760284e-01 +1.167534965953250653e-01 +1.147433786121053456e-01 +1.127484699006330721e-01 +1.107688492164882882e-01 +1.088045947117059764e-01 +1.068557839316905400e-01 +1.049224938121548489e-01 +1.030048006760823920e-01 +1.011027802307144785e-01 +9.921650756456172615e-02 +9.734605714443907154e-02 +9.549150281252624661e-02 +9.365291778345302687e-02 +9.183037464140800243e-02 +9.002394533727385573e-02 +8.823370118578630072e-02 +8.645971286271911249e-02 +8.470205040209372038e-02 +8.296078319341440577e-02 +8.123597997892917366e-02 +7.952770885091546560e-02 +7.783603724899244847e-02 +7.616103195745842214e-02 +7.450275910265410917e-02 +7.286128415035245109e-02 +7.123667190317387043e-02 +6.962898649802817808e-02 +6.803829140358236272e-02 +6.646464941775495627e-02 +6.490812266523718344e-02 +6.336877259503992388e-02 +6.184665997806815252e-02 +6.034184490472188633e-02 +5.885438678252336020e-02 +5.738434433377237465e-02 +5.593177559322773384e-02 +5.449673790581609223e-02 +5.307928792436814036e-02 +5.167948160738213004e-02 +5.029737421681453047e-02 +4.893302031589857881e-02 +4.758647376699023934e-02 +4.625778772944157125e-02 +4.494701465750219893e-02 +4.365420629824860732e-02 +4.237941368954126209e-02 +4.112268715800941610e-02 +3.988407631706485101e-02 +3.866363006494261123e-02 +3.746139658277095053e-02 +3.627742333266931185e-02 +3.511175705587434026e-02 +3.396444377089455346e-02 +3.283552877169401696e-02 +3.172505662590377473e-02 +3.063307117306297844e-02 +2.955961552288728644e-02 +2.850473205356779394e-02 +2.746846241009757994e-02 +2.645084750262781392e-02 +2.545192750485272826e-02 +2.447174185242324829e-02 +2.351032924139059843e-02 +2.256772762667849652e-02 +2.164397422058469966e-02 +2.073910549131210979e-02 +1.985315716152846743e-02 +1.898616420695706242e-02 +1.813816085499513064e-02 +1.730918058336305965e-02 +1.649925611878252929e-02 +1.570841943568448973e-02 +1.493670175494711538e-02 +1.418413354266304105e-02 +1.345074450893671281e-02 +1.273656360671143739e-02 +1.204161903062633820e-02 +1.136593821590328734e-02 +1.070954783726395243e-02 +1.007247380787654190e-02 +9.454741278332942644e-03 +8.856374635655694938e-03 +8.277397502335151480e-03 +7.717832735397306410e-03 +7.177702425500975814e-03 +6.657027896065995098e-03 +6.155829702431114825e-03 +5.674127631042982789e-03 +5.211940698674547012e-03 +4.769287151674406200e-03 +4.346184465246691331e-03 +3.942649342761062048e-03 +3.558697715093164793e-03 +3.194344739995830240e-03 +2.849604801500524309e-03 +2.524491509349885421e-03 +2.219017698460029608e-03 +1.933195428413733707e-03 +1.667035982985051734e-03 +1.420549869693005229e-03 +1.193746819387400682e-03 +9.866357858642066381e-04 +7.992249455125027824e-04 +6.315216969912662570e-04 +4.835326609376605633e-04 +3.552636797053698725e-04 +2.467198171342277480e-04 +1.579053583500300562e-04 +8.882380959550351118e-05 +3.947789809194413024e-05 +9.869571931456211367e-06 +0.000000000000000000e+00 +9.869571931456211367e-06 +3.947789809194413024e-05 +8.882380959550351118e-05 +1.579053583500300562e-04 +2.467198171342277480e-04 +3.552636797053698725e-04 +4.835326609376605633e-04 +6.315216969912662570e-04 +7.992249455125027824e-04 +9.866357858642066381e-04 +1.193746819387400682e-03 +1.420549869693005229e-03 +1.667035982985051734e-03 +1.933195428413733707e-03 +2.219017698460029608e-03 +2.524491509349885421e-03 +2.849604801500524309e-03 +3.194344739995830240e-03 +3.558697715093164793e-03 +3.942649342761131437e-03 +4.346184465246691331e-03 +4.769287151674406200e-03 +5.211940698674547012e-03 +5.674127631043052178e-03 +6.155829702431184214e-03 +6.657027896065995098e-03 +7.177702425500975814e-03 +7.717832735397306410e-03 +8.277397502335220869e-03 +8.856374635655694938e-03 +9.454741278332942644e-03 +1.007247380787654190e-02 +1.070954783726395243e-02 +1.136593821590328734e-02 +1.204161903062626882e-02 +1.273656360671143739e-02 +1.345074450893671281e-02 +1.418413354266304105e-02 +1.493670175494704599e-02 +1.570841943568442034e-02 +1.649925611878245990e-02 +1.730918058336299026e-02 +1.813816085499506126e-02 +1.898616420695706242e-02 +1.985315716152846743e-02 +2.073910549131204040e-02 +2.164397422058469966e-02 +2.256772762667849652e-02 +2.351032924139059843e-02 +2.447174185242317890e-02 +2.545192750485265887e-02 +2.645084750262781392e-02 +2.746846241009751055e-02 +2.850473205356772455e-02 +2.955961552288728644e-02 +3.063307117306290905e-02 +3.172505662590377473e-02 +3.283552877169394757e-02 +3.396444377089455346e-02 +3.511175705587434026e-02 +3.627742333266931185e-02 +3.746139658277095053e-02 +3.866363006494254184e-02 +3.988407631706478162e-02 +4.112268715800934671e-02 +4.237941368954119270e-02 +4.365420629824853793e-02 +4.494701465750219893e-02 +4.625778772944157125e-02 +4.758647376699023934e-02 +4.893302031589864820e-02 +5.029737421681439169e-02 +5.167948160738199126e-02 +5.307928792436807097e-02 +5.449673790581602284e-02 +5.593177559322773384e-02 +5.738434433377237465e-02 +5.885438678252336020e-02 +6.034184490472188633e-02 +6.184665997806829130e-02 +6.336877259503999327e-02 +6.490812266523718344e-02 +6.646464941775495627e-02 +6.803829140358229333e-02 +6.962898649802817808e-02 +7.123667190317387043e-02 +7.286128415035245109e-02 +7.450275910265410917e-02 +7.616103195745842214e-02 +7.783603724899251786e-02 +7.952770885091539621e-02 +8.123597997892910427e-02 +8.296078319341440577e-02 +8.470205040209365099e-02 +8.645971286271911249e-02 +8.823370118578630072e-02 +9.002394533727385573e-02 +9.183037464140807182e-02 +9.365291778345316565e-02 +9.549150281252624661e-02 +9.734605714443900215e-02 +9.921650756456158737e-02 +1.011027802307144091e-01 +1.030048006760822532e-01 +1.049224938121547102e-01 +1.068557839316904706e-01 +1.088045947117059070e-01 +1.107688492164882882e-01 +1.127484699006330721e-01 +1.147433786121053456e-01 +1.167534965953250653e-01 +1.187787444942759590e-01 +1.208190423556389920e-01 +1.228743096319480366e-01 +1.249444651847701759e-01 +1.270294272879088915e-01 +1.291291136306304266e-01 +1.312434413209130624e-01 +1.333723268887200553e-01 +1.355156862892942793e-01 +1.376734349064765439e-01 +1.398454875560464772e-01 +1.420317584890843365e-01 +1.442321613953572446e-01 +1.464466094067261859e-01 +1.486750151005754306e-01 +1.509172905032637180e-01 +1.531733470935975339e-01 +1.554430958063258150e-01 +1.577264470356556092e-01 +1.600233106387903559e-01 +1.623335959394877348e-01 +1.646572117316399131e-01 +1.669940662828741373e-01 +1.693440673381740869e-01 +1.717071221235218215e-01 +1.740831373495606849e-01 +1.764720192152779144e-01 +1.788736734117077343e-01 +1.812880051256550995e-01 +1.837149190434377577e-01 +1.861543193546497110e-01 +1.886061097559437183e-01 +1.910701934548328373e-01 +1.935464731735118127e-01 +1.960348511526973647e-01 +1.985352291554877413e-01 +2.010475084712406435e-01 +2.035715899194703304e-01 +2.061073738537633759e-01 +2.086547601657119666e-01 +2.112136482888661848e-01 +2.137839372027046381e-01 +2.163655254366217973e-01 +2.189583110739347638e-01 +2.215621917559060794e-01 +2.241770646857850491e-01 +2.268028266328653841e-01 +2.294393739365620521e-01 +2.320866025105016717e-01 +2.347444078466329742e-01 +2.374126850193521987e-01 +2.400913286896453336e-01 +2.427802331092468457e-01 +2.454792921248144522e-01 +2.481883991821197399e-01 +2.509074473302545516e-01 +2.536363292258542179e-01 +2.563749371373336694e-01 +2.591231629491422273e-01 +2.618808981660303292e-01 +2.646480339173336027e-01 +2.674244609612707047e-01 +2.702100696892560383e-01 +2.730047501302265700e-01 +2.758083919549838559e-01 +2.786208844805492246e-01 +2.814421166745335601e-01 +2.842719771595203504e-01 +2.871103542174635592e-01 +2.899571357940967653e-01 +2.928122095033578454e-01 +2.956754626318254253e-01 +2.985467821431686541e-01 +3.014260546826096898e-01 +3.043131665813987863e-01 +3.072080038613017594e-01 +3.101104522390993323e-01 +3.130203971310996369e-01 +3.159377236576608738e-01 +3.188623166477270732e-01 +3.217940606433745687e-01 +3.247328399043704628e-01 +3.276785384127414713e-01 +3.306310398773543158e-01 +3.335902277385067727e-01 +3.365559851725286045e-01 +3.395281950963952022e-01 +3.425067401723475013e-01 +3.454915028125262189e-01 +3.484823651836130298e-01 +3.514792092114825128e-01 +3.544819165858640875e-01 +3.574903687650120010e-01 +3.605044469803854179e-01 +3.635240322413375025e-01 +3.665490053398121617e-01 +3.695792468550514465e-01 +3.726146371583088923e-01 +3.756550564175725748e-01 +3.787003846022963249e-01 +3.817505014881376613e-01 +3.848052866617047707e-01 +3.878646195253094842e-01 +3.909283793017288566e-01 +3.939964450389725759e-01 +3.970686956150593083e-01 +4.001450097427964869e-01 +4.032252659745698686e-01 +4.063093427071376995e-01 +4.093971181864314302e-01 +4.124884705123620376e-01 +4.155832776436331755e-01 +4.186814174025583202e-01 +4.217827674798844684e-01 +4.248872054396214404e-01 +4.279946087238739594e-01 +4.311048546576810025e-01 +4.342178204538588160e-01 +4.373333832178477598e-01 +4.404514199525650375e-01 +4.435718075632590351e-01 +4.466944228623699331e-01 +4.498191425743925387e-01 +4.529458433407427820e-01 +4.560744017246284865e-01 +4.592046942159210277e-01 +4.623365972360335419e-01 +4.654699871427969704e-01 +4.686047402353432645e-01 +4.717407327589876465e-01 +4.748778409101152009e-01 +4.780159408410675215e-01 +4.811549086650327434e-01 +4.842946204609359095e-01 +4.874349522783311128e-01 +4.905757801422958031e-01 +4.937169800583235957e-01 +4.968584280172204104e-01 +4.999999999999999445e-01 +5.031415719827794231e-01 +5.062830199416762378e-01 +5.094242198577040304e-01 +5.125650477216687761e-01 +5.157053795390640349e-01 +5.188450913349671456e-01 +5.219840591589323120e-01 +5.251221590898846880e-01 +5.282592672410122425e-01 +5.313952597646567355e-01 +5.345300128572029186e-01 +5.376634027639664026e-01 +5.407953057840788613e-01 +5.439255982753714580e-01 +5.470541566592570515e-01 +5.501808574256074058e-01 +5.533055771376299559e-01 +5.564281924367407983e-01 +5.595485800474349070e-01 +5.626666167821521292e-01 +5.657821795461412950e-01 +5.688951453423191085e-01 +5.720053912761261516e-01 +5.751127945603784486e-01 +5.782172325201153651e-01 +5.813185825974417353e-01 +5.844167223563669911e-01 +5.875115294876379624e-01 +5.906028818135686809e-01 +5.936906572928624115e-01 +5.967747340254302424e-01 +5.998549902572036796e-01 +6.029313043849405807e-01 +6.060035549610273131e-01 +6.090716206982712544e-01 +6.121353804746906269e-01 +6.151947133382953403e-01 +6.182494985118623942e-01 +6.212996153977038416e-01 +6.243449435824275362e-01 +6.273853628416912187e-01 +6.304207531449484980e-01 +6.334509946601877273e-01 +6.364759677586625530e-01 +6.394955530196146931e-01 +6.425096312349881655e-01 +6.455180834141360791e-01 +6.485207907885176537e-01 +6.515176348163871367e-01 +6.545084971874738367e-01 +6.574932598276524987e-01 +6.604718049036047978e-01 +6.634440148274712845e-01 +6.664097722614933383e-01 +6.693689601226456842e-01 +6.723214615872585842e-01 +6.752671600956295928e-01 +6.782059393566255423e-01 +6.811376833522730934e-01 +6.840622763423390706e-01 +6.869796028689002521e-01 +6.898895477609005011e-01 +6.927919961386982406e-01 +6.956868334186012692e-01 +6.985739453173903657e-01 +7.014532178568314569e-01 +7.043245373681746857e-01 +7.071877904966422657e-01 +7.100428642059033457e-01 +7.128896457825363298e-01 +7.157280228404795386e-01 +7.185578833254665510e-01 +7.213791155194507754e-01 +7.241916080450162552e-01 +7.269952498697735965e-01 +7.297899303107441282e-01 +7.325755390387289623e-01 +7.353519660826660642e-01 +7.381191018339694487e-01 +7.408768370508574952e-01 +7.436250628626661641e-01 +7.463636707741456711e-01 +7.490925526697452819e-01 +7.518116008178801213e-01 +7.545207078751854368e-01 +7.572197668907529877e-01 +7.599086713103545554e-01 +7.625873149806478013e-01 +7.652555921533669148e-01 +7.679133974894982728e-01 +7.705606260634378923e-01 +7.731971733671345604e-01 +7.758229353142149787e-01 +7.784378082440938096e-01 +7.810416889260651807e-01 +7.836344745633780917e-01 +7.862160627972953897e-01 +7.887863517111337597e-01 +7.913452398342879501e-01 +7.938926261462365686e-01 +7.964284100805296696e-01 +7.989524915287593565e-01 +8.014647708445121754e-01 +8.039651488473026353e-01 +8.064535268264880763e-01 +8.089298065451669961e-01 +8.113938902440561707e-01 +8.138456806453501224e-01 +8.162850809565621590e-01 +8.187119948743448727e-01 +8.211263265882923212e-01 +8.235279807847220024e-01 +8.259168626504392874e-01 +8.282928778764780953e-01 +8.306559326618259131e-01 +8.330059337171258349e-01 +8.353427882683600592e-01 +8.376664040605121819e-01 +8.399766893612095053e-01 +8.422735529643443630e-01 +8.445569041936741295e-01 +8.468266529064023551e-01 +8.490827094967362543e-01 +8.513249848994244307e-01 +8.535533905932737309e-01 +8.557678386046426722e-01 +8.579682415109154414e-01 +8.601545124439535783e-01 +8.623265650935232340e-01 +8.644843137107056652e-01 +8.666276731112798615e-01 +8.687565586790868544e-01 +8.708708863693694902e-01 +8.729705727120909975e-01 +8.750555348152296853e-01 +8.771256903680518802e-01 +8.791809576443607721e-01 +8.812212555057239438e-01 +8.832465034046749208e-01 +8.852566213878946266e-01 +8.872515300993668586e-01 +8.892311507835117812e-01 +8.911954052882939958e-01 +8.931442160683092935e-01 +8.950775061878452066e-01 +8.969951993239174692e-01 +8.988972197692854937e-01 +9.007834924354382045e-01 +9.026539428555609978e-01 +9.045084971874736146e-01 +9.063470822165471397e-01 +9.081696253585920253e-01 +9.099760546627261304e-01 +9.117662988142136715e-01 +9.135402871372807487e-01 +9.152979495979064462e-01 +9.170392168065855110e-01 +9.187640200210709374e-01 +9.204722911490844650e-01 +9.221639627510076487e-01 +9.238389680425416195e-01 +9.254972408973460851e-01 +9.271387158496476877e-01 +9.287633280968260463e-01 +9.303710135019718219e-01 +9.319617085964176928e-01 +9.335353505822452380e-01 +9.350918773347628443e-01 +9.366312274049601871e-01 +9.381533400219318475e-01 +9.396581550952782802e-01 +9.411456132174766953e-01 +9.426156556662276254e-01 +9.440682244067722939e-01 +9.455032620941838939e-01 +9.469207120756319984e-01 +9.483205183926179949e-01 +9.497026257831855389e-01 +9.510669796841014767e-01 +9.524135262330098994e-01 +9.537422122705585537e-01 +9.550529853424978288e-01 +9.563457937017514343e-01 +9.576205863104587657e-01 +9.588773128419906255e-01 +9.601159236829351906e-01 +9.613363699350575553e-01 +9.625386034172290772e-01 +9.637225766673307437e-01 +9.648882429441257846e-01 +9.660355562291054188e-01 +9.671644712283061773e-01 +9.682749433740961420e-01 +9.693669288269370909e-01 +9.704403844771127829e-01 +9.714952679464323726e-01 +9.725315375899025172e-01 +9.735491524973722832e-01 +9.745480724951474105e-01 +9.755282581475768211e-01 +9.764896707586095959e-01 +9.774322723733215312e-01 +9.783560257794152726e-01 +9.792608945086878069e-01 +9.801468428384715326e-01 +9.810138357930427988e-01 +9.818618391450048000e-01 +9.826908194166369404e-01 +9.835007438812174430e-01 +9.842915805643155380e-01 +9.850632982450530095e-01 +9.858158664573369867e-01 +9.865492554910632039e-01 +9.872634363932886181e-01 +9.879583809693737173e-01 +9.886340617840967404e-01 +9.892904521627360337e-01 +9.899275261921234303e-01 +9.905452587216669880e-01 +9.911436253643443051e-01 +9.917226024976647514e-01 +9.922821672646027213e-01 +9.928222975744990242e-01 +9.933429721039339633e-01 +9.938441702975688852e-01 +9.943258723689569756e-01 +9.947880593013255224e-01 +9.952307128483256493e-01 +9.956538155347532948e-01 +9.960573506572389935e-01 +9.964413022849069046e-01 +9.968056552600041975e-01 +9.971503951984994618e-01 +9.974755084906501423e-01 +9.977809823015399981e-01 +9.980668045715862524e-01 +9.983329640170148789e-01 +9.985794501303070225e-01 +9.988062531806126687e-01 +9.990133642141357795e-01 +9.992007750544875666e-01 +9.993684783030087893e-01 +9.995164673390624088e-01 +9.996447363202946024e-01 +9.997532801828658000e-01 +9.998420946416499699e-01 +9.999111761904044826e-01 +9.999605221019081114e-01 +9.999901304280686132e-01 +1.000000000000000000e+00 +9.999901304280686132e-01 +9.999605221019081114e-01 +9.999111761904044826e-01 +9.998420946416499699e-01 +9.997532801828658000e-01 +9.996447363202946024e-01 +9.995164673390624088e-01 +9.993684783030087893e-01 +9.992007750544875666e-01 +9.990133642141357795e-01 +9.988062531806126687e-01 +9.985794501303070225e-01 +9.983329640170148789e-01 +9.980668045715862524e-01 +9.977809823015399981e-01 +9.974755084906501423e-01 +9.971503951984994618e-01 +9.968056552600041975e-01 +9.964413022849069046e-01 +9.960573506572389935e-01 +9.956538155347532948e-01 +9.952307128483256493e-01 +9.947880593013255224e-01 +9.943258723689569756e-01 +9.938441702975688852e-01 +9.933429721039340743e-01 +9.928222975744990242e-01 +9.922821672646027213e-01 +9.917226024976649734e-01 +9.911436253643443051e-01 +9.905452587216669880e-01 +9.899275261921234303e-01 +9.892904521627360337e-01 +9.886340617840967404e-01 +9.879583809693737173e-01 +9.872634363932886181e-01 +9.865492554910632039e-01 +9.858158664573369867e-01 +9.850632982450530095e-01 +9.842915805643155380e-01 +9.835007438812176650e-01 +9.826908194166369404e-01 +9.818618391450048000e-01 +9.810138357930429098e-01 +9.801468428384715326e-01 +9.792608945086879180e-01 +9.783560257794151616e-01 +9.774322723733215312e-01 +9.764896707586093738e-01 +9.755282581475768211e-01 +9.745480724951472995e-01 +9.735491524973721722e-01 +9.725315375899024062e-01 +9.714952679464322616e-01 +9.704403844771126719e-01 +9.693669288269370909e-01 +9.682749433740962530e-01 +9.671644712283059553e-01 +9.660355562291056408e-01 +9.648882429441255626e-01 +9.637225766673307437e-01 +9.625386034172289662e-01 +9.613363699350574443e-01 +9.601159236829350796e-01 +9.588773128419905145e-01 +9.576205863104588767e-01 +9.563457937017513233e-01 +9.550529853424979398e-01 +9.537422122705583316e-01 +9.524135262330097884e-01 +9.510669796841012547e-01 +9.497026257831855389e-01 +9.483205183926177728e-01 +9.469207120756318874e-01 +9.455032620941840049e-01 +9.440682244067721829e-01 +9.426156556662276254e-01 +9.411456132174764733e-01 +9.396581550952781692e-01 +9.381533400219317365e-01 +9.366312274049600761e-01 +9.350918773347627333e-01 +9.335353505822452380e-01 +9.319617085964176928e-01 +9.303710135019719329e-01 +9.287633280968261573e-01 +9.271387158496476877e-01 +9.254972408973461961e-01 +9.238389680425418415e-01 +9.221639627510077597e-01 +9.204722911490845760e-01 +9.187640200210711594e-01 +9.170392168065856220e-01 +9.152979495979064462e-01 +9.135402871372808598e-01 +9.117662988142138936e-01 +9.099760546627261304e-01 +9.081696253585921363e-01 +9.063470822165472507e-01 +9.045084971874737256e-01 +9.026539428555611089e-01 +9.007834924354383155e-01 +8.988972197692857158e-01 +8.969951993239175803e-01 +8.950775061878453176e-01 +8.931442160683095155e-01 +8.911954052882942179e-01 +8.892311507835118922e-01 +8.872515300993669696e-01 +8.852566213878948487e-01 +8.832465034046749208e-01 +8.812212555057241659e-01 +8.791809576443609942e-01 +8.771256903680521022e-01 +8.750555348152296853e-01 +8.729705727120912195e-01 +8.708708863693698232e-01 +8.687565586790870764e-01 +8.666276731112800835e-01 +8.644843137107057762e-01 +8.623265650935235671e-01 +8.601545124439533563e-01 +8.579682415109157745e-01 +8.557678386046426722e-01 +8.535533905932737309e-01 +8.513249848994247637e-01 +8.490827094967363653e-01 +8.468266529064027992e-01 +8.445569041936742405e-01 +8.422735529643444741e-01 +8.399766893612095053e-01 +8.376664040605122930e-01 +8.353427882683600592e-01 +8.330059337171258349e-01 +8.306559326618262462e-01 +8.282928778764783173e-01 +8.259168626504395094e-01 +8.235279807847221134e-01 +8.211263265882923212e-01 +8.187119948743448727e-01 +8.162850809565622701e-01 +8.138456806453500114e-01 +8.113938902440562817e-01 +8.089298065451674402e-01 +8.064535268264882983e-01 +8.039651488473028573e-01 +8.014647708445123975e-01 +7.989524915287595785e-01 +7.964284100805296696e-01 +7.938926261462366796e-01 +7.913452398342879501e-01 +7.887863517111338707e-01 +7.862160627972956117e-01 +7.836344745633783138e-01 +7.810416889260654028e-01 +7.784378082440940316e-01 +7.758229353142152007e-01 +7.731971733671344493e-01 +7.705606260634380034e-01 +7.679133974894981618e-01 +7.652555921533671368e-01 +7.625873149806478013e-01 +7.599086713103547774e-01 +7.572197668907534318e-01 +7.545207078751855478e-01 +7.518116008178805654e-01 +7.490925526697452819e-01 +7.463636707741457821e-01 +7.436250628626659420e-01 +7.408768370508576062e-01 +7.381191018339694487e-01 +7.353519660826662863e-01 +7.325755390387292953e-01 +7.297899303107437952e-01 +7.269952498697734855e-01 +7.241916080450159221e-01 +7.213791155194507754e-01 +7.185578833254663289e-01 +7.157280228404795386e-01 +7.128896457825362187e-01 +7.100428642059031237e-01 +7.071877904966422657e-01 +7.043245373681744637e-01 +7.014532178568313459e-01 +6.985739453173901437e-01 +6.956868334186012692e-01 +6.927919961386981296e-01 +6.898895477609005011e-01 +6.869796028688999190e-01 +6.840622763423389596e-01 +6.811376833522728713e-01 +6.782059393566253203e-01 +6.752671600956295928e-01 +6.723214615872583622e-01 +6.693689601226456842e-01 +6.664097722614931163e-01 +6.634440148274711735e-01 +6.604718049036045757e-01 +6.574932598276523876e-01 +6.545084971874738367e-01 +6.515176348163868036e-01 +6.485207907885174317e-01 +6.455180834141357460e-01 +6.425096312349881655e-01 +6.394955530196144711e-01 +6.364759677586625530e-01 +6.334509946601875052e-01 +6.304207531449484980e-01 +6.273853628416911077e-01 +6.243449435824276472e-01 +6.212996153977037306e-01 +6.182494985118626163e-01 +6.151947133382956734e-01 +6.121353804746907379e-01 +6.090716206982716985e-01 +6.060035549610274241e-01 +6.029313043849410247e-01 +5.998549902572035686e-01 +5.967747340254303534e-01 +5.936906572928624115e-01 +5.906028818135689029e-01 +5.875115294876379624e-01 +5.844167223563671021e-01 +5.813185825974421794e-01 +5.782172325201154761e-01 +5.751127945603787817e-01 +5.720053912761261516e-01 +5.688951453423193305e-01 +5.657821795461412950e-01 +5.626666167821523512e-01 +5.595485800474347959e-01 +5.564281924367410204e-01 +5.533055771376302889e-01 +5.501808574256075168e-01 +5.470541566592574956e-01 +5.439255982753715690e-01 +5.407953057840789723e-01 +5.376634027639662916e-01 +5.345300128572030296e-01 +5.313952597646566245e-01 +5.282592672410124646e-01 +5.251221590898850211e-01 +5.219840591589325340e-01 +5.188450913349675897e-01 +5.157053795390641460e-01 +5.125650477216689982e-01 +5.094242198577040304e-01 +5.062830199416764598e-01 +5.031415719827794231e-01 diff --git a/examples/icub_vor_env/normalised_head_velocities_1000.csv b/examples/icub_vor_env/normalised_head_velocities_1000.csv new file mode 100644 index 00000000..f215b6ad --- /dev/null +++ b/examples/icub_vor_env/normalised_head_velocities_1000.csv @@ -0,0 +1,1000 @@ +0.000000000000000000e+00 +9.869571931439562087e-06 +3.947789809190699632e-05 +8.882380959548627237e-05 +1.579053583499612364e-04 +2.467198171342090997e-04 +3.552636797053673788e-04 +4.835326609376300430e-04 +6.315216969912583423e-04 +7.992249455125140581e-04 +9.866357858641615353e-04 +1.193746819387333461e-03 +1.420549869692992653e-03 +1.667035982985024412e-03 +1.933195428413718962e-03 +2.219017698460000985e-03 +2.524491509349872410e-03 +2.849604801500486579e-03 +3.194344739995816362e-03 +3.558697715093159155e-03 +3.942649342761002200e-03 +4.346184465246665310e-03 +4.769287151674420945e-03 +5.211940698674534002e-03 +5.674127631042969779e-03 +6.155829702431123499e-03 +6.657027896065956935e-03 +7.177702425500961068e-03 +7.717832735397246562e-03 +8.277397502335116786e-03 +8.856374635655587385e-03 +9.454741278332920093e-03 +1.007247380787648638e-02 +1.070954783726390906e-02 +1.136593821590326132e-02 +1.204161903062620463e-02 +1.273656360671141137e-02 +1.345074450893671801e-02 +1.418413354266298380e-02 +1.493670175494710324e-02 +1.570841943568445503e-02 +1.649925611878251541e-02 +1.730918058336302495e-02 +1.813816085499507860e-02 +1.898616420695698956e-02 +1.985315716152841886e-02 +2.073910549131204387e-02 +2.164397422058470313e-02 +2.256772762667843060e-02 +2.351032924139054292e-02 +2.447174185242324135e-02 +2.545192750485270050e-02 +2.645084750262781739e-02 +2.746846241009755912e-02 +2.850473205356769679e-02 +2.955961552288726563e-02 +3.063307117306297844e-02 +3.172505662590380943e-02 +3.283552877169400308e-02 +3.396444377089454653e-02 +3.511175705587420148e-02 +3.627742333266925634e-02 +3.746139658277095746e-02 +3.866363006494259735e-02 +3.988407631706478162e-02 +4.112268715800936753e-02 +4.237941368954127597e-02 +4.365420629824853793e-02 +4.494701465750217118e-02 +4.625778772944151573e-02 +4.758647376699020465e-02 +4.893302031589858575e-02 +5.029737421681453047e-02 +5.167948160738201208e-02 +5.307928792436815424e-02 +5.449673790581603672e-02 +5.593177559322771303e-02 +5.738434433377238159e-02 +5.885438678252330469e-02 +6.034184490472183082e-02 +6.184665997806816640e-02 +6.336877259503986837e-02 +6.490812266523718344e-02 +6.646464941775491464e-02 +6.803829140358234884e-02 +6.962898649802816420e-02 +7.123667190317387043e-02 +7.286128415035239558e-02 +7.450275910265402590e-02 +7.616103195745833887e-02 +7.783603724899246235e-02 +7.952770885091538233e-02 +8.123597997892911815e-02 +8.296078319341440577e-02 +8.470205040209359548e-02 +8.645971286271908474e-02 +8.823370118578624521e-02 +9.002394533727378634e-02 +9.183037464140793305e-02 +9.365291778345298523e-02 +9.549150281252624661e-02 +9.734605714443907154e-02 +9.921650756456158737e-02 +1.011027802307144785e-01 +1.030048006760823781e-01 +1.049224938121547657e-01 +1.068557839316905261e-01 +1.088045947117059348e-01 +1.107688492164882604e-01 +1.127484699006330582e-01 +1.147433786121053179e-01 +1.167534965953250237e-01 +1.187787444942760007e-01 +1.208190423556390197e-01 +1.228743096319480643e-01 +1.249444651847701482e-01 +1.270294272879089470e-01 +1.291291136306304266e-01 +1.312434413209131179e-01 +1.333723268887199720e-01 +1.355156862892941960e-01 +1.376734349064766549e-01 +1.398454875560465327e-01 +1.420317584890843643e-01 +1.442321613953572168e-01 +1.464466094067261859e-01 +1.486750151005754306e-01 +1.509172905032636069e-01 +1.531733470935975061e-01 +1.554430958063257318e-01 +1.577264470356556925e-01 +1.600233106387903836e-01 +1.623335959394877070e-01 +1.646572117316399408e-01 +1.669940662828741373e-01 +1.693440673381740591e-01 +1.717071221235217937e-01 +1.740831373495606849e-01 +1.764720192152778033e-01 +1.788736734117078453e-01 +1.812880051256551550e-01 +1.837149190434377577e-01 +1.861543193546498220e-01 +1.886061097559437738e-01 +1.910701934548328096e-01 +1.935464731735117017e-01 +1.960348511526972537e-01 +1.985352291554875470e-01 +2.010475084712405602e-01 +2.035715899194703027e-01 +2.061073738537634592e-01 +2.086547601657119388e-01 +2.112136482888661571e-01 +2.137839372027044993e-01 +2.163655254366217140e-01 +2.189583110739346805e-01 +2.215621917559059684e-01 +2.241770646857848825e-01 +2.268028266328654674e-01 +2.294393739365620244e-01 +2.320866025105016994e-01 +2.347444078466328909e-01 +2.374126850193520877e-01 +2.400913286896452226e-01 +2.427802331092467902e-01 +2.454792921248143966e-01 +2.481883991821195179e-01 +2.509074473302545516e-01 +2.536363292258542179e-01 +2.563749371373338359e-01 +2.591231629491423938e-01 +2.618808981660304402e-01 +2.646480339173337137e-01 +2.674244609612708712e-01 +2.702100696892560938e-01 +2.730047501302265700e-01 +2.758083919549837448e-01 +2.786208844805491691e-01 +2.814421166745335046e-01 +2.842719771595204614e-01 +2.871103542174636702e-01 +2.899571357940967653e-01 +2.928122095033578454e-01 +2.956754626318254253e-01 +2.985467821431686541e-01 +3.014260546826096898e-01 +3.043131665813987308e-01 +3.072080038613017039e-01 +3.101104522390994434e-01 +3.130203971310998035e-01 +3.159377236576609294e-01 +3.188623166477270732e-01 +3.217940606433746242e-01 +3.247328399043705183e-01 +3.276785384127414713e-01 +3.306310398773542603e-01 +3.335902277385066617e-01 +3.365559851725287710e-01 +3.395281950963952577e-01 +3.425067401723476124e-01 +3.454915028125262189e-01 +3.484823651836129743e-01 +3.514792092114825683e-01 +3.544819165858641430e-01 +3.574903687650118900e-01 +3.605044469803853624e-01 +3.635240322413374470e-01 +3.665490053398122727e-01 +3.695792468550516130e-01 +3.726146371583089478e-01 +3.756550564175725193e-01 +3.787003846022962139e-01 +3.817505014881376058e-01 +3.848052866617046597e-01 +3.878646195253094286e-01 +3.909283793017286346e-01 +3.939964450389726314e-01 +3.970686956150593083e-01 +4.001450097427964869e-01 +4.032252659745698131e-01 +4.063093427071376440e-01 +4.093971181864312636e-01 +4.124884705123619821e-01 +4.155832776436331200e-01 +4.186814174025580981e-01 +4.217827674798845239e-01 +4.248872054396214959e-01 +4.279946087238739594e-01 +4.311048546576810025e-01 +4.342178204538587050e-01 +4.373333832178479263e-01 +4.404514199525651486e-01 +4.435718075632592017e-01 +4.466944228623699886e-01 +4.498191425743925942e-01 +4.529458433407428375e-01 +4.560744017246284310e-01 +4.592046942159213052e-01 +4.623365972360336529e-01 +4.654699871427971369e-01 +4.686047402353432645e-01 +4.717407327589876465e-01 +4.748778409101152009e-01 +4.780159408410675770e-01 +4.811549086650326323e-01 +4.842946204609357985e-01 +4.874349522783312239e-01 +4.905757801422959141e-01 +4.937169800583236512e-01 +4.968584280172204659e-01 +5.000000000000000000e-01 +5.031415719827794231e-01 +5.062830199416763488e-01 +5.094242198577040304e-01 +5.125650477216686651e-01 +5.157053795390641460e-01 +5.188450913349672566e-01 +5.219840591589324230e-01 +5.251221590898846880e-01 +5.282592672410122425e-01 +5.313952597646566245e-01 +5.345300128572029186e-01 +5.376634027639662916e-01 +5.407953057840787503e-01 +5.439255982753716800e-01 +5.470541566592571625e-01 +5.501808574256075168e-01 +5.533055771376299559e-01 +5.564281924367407983e-01 +5.595485800474349070e-01 +5.626666167821522402e-01 +5.657821795461412950e-01 +5.688951453423189975e-01 +5.720053912761261516e-01 +5.751127945603785596e-01 +5.782172325201154761e-01 +5.813185825974417353e-01 +5.844167223563669911e-01 +5.875115294876380734e-01 +5.906028818135686809e-01 +5.936906572928624115e-01 +5.967747340254301314e-01 +5.998549902572035686e-01 +6.029313043849406917e-01 +6.060035549610274241e-01 +6.090716206982713654e-01 +6.121353804746906269e-01 +6.151947133382953403e-01 +6.182494985118623942e-01 +6.212996153977036196e-01 +6.243449435824273142e-01 +6.273853628416909967e-01 +6.304207531449482760e-01 +6.334509946601877273e-01 +6.364759677586625530e-01 +6.394955530196145821e-01 +6.425096312349880545e-01 +6.455180834141358570e-01 +6.485207907885174317e-01 +6.515176348163869147e-01 +6.545084971874736146e-01 +6.574932598276522766e-01 +6.604718049036046867e-01 +6.634440148274711735e-01 +6.664097722614933383e-01 +6.693689601226456842e-01 +6.723214615872584732e-01 +6.752671600956294817e-01 +6.782059393566253203e-01 +6.811376833522728713e-01 +6.840622763423389596e-01 +6.869796028689001410e-01 +6.898895477609005011e-01 +6.927919961386982406e-01 +6.956868334186012692e-01 +6.985739453173902547e-01 +7.014532178568313459e-01 +7.043245373681745747e-01 +7.071877904966421546e-01 +7.100428642059032347e-01 +7.128896457825364408e-01 +7.157280228404795386e-01 +7.185578833254663289e-01 +7.213791155194506644e-01 +7.241916080450160331e-01 +7.269952498697733745e-01 +7.297899303107439062e-01 +7.325755390387291843e-01 +7.353519660826662863e-01 +7.381191018339696708e-01 +7.408768370508577172e-01 +7.436250628626662751e-01 +7.463636707741457821e-01 +7.490925526697452819e-01 +7.518116008178803433e-01 +7.545207078751857699e-01 +7.572197668907533208e-01 +7.599086713103547774e-01 +7.625873149806479123e-01 +7.652555921533671368e-01 +7.679133974894983838e-01 +7.705606260634378923e-01 +7.731971733671345604e-01 +7.758229353142150897e-01 +7.784378082440940316e-01 +7.810416889260654028e-01 +7.836344745633783138e-01 +7.862160627972955007e-01 +7.887863517111338707e-01 +7.913452398342881722e-01 +7.938926261462365686e-01 +7.964284100805295585e-01 +7.989524915287592455e-01 +8.014647708445122865e-01 +8.039651488473026353e-01 +8.064535268264880763e-01 +8.089298065451671071e-01 +8.113938902440561707e-01 +8.138456806453501224e-01 +8.162850809565621590e-01 +8.187119948743448727e-01 +8.211263265882922102e-01 +8.235279807847220024e-01 +8.259168626504391764e-01 +8.282928778764780953e-01 +8.306559326618259131e-01 +8.330059337171259459e-01 +8.353427882683600592e-01 +8.376664040605122930e-01 +8.399766893612096164e-01 +8.422735529643444741e-01 +8.445569041936742405e-01 +8.468266529064024661e-01 +8.490827094967362543e-01 +8.513249848994244307e-01 +8.535533905932737309e-01 +8.557678386046427832e-01 +8.579682415109156635e-01 +8.601545124439534673e-01 +8.623265650935233451e-01 +8.644843137107056652e-01 +8.666276731112799725e-01 +8.687565586790869654e-01 +8.708708863693694902e-01 +8.729705727120909975e-01 +8.750555348152299073e-01 +8.771256903680519912e-01 +8.791809576443608831e-01 +8.812212555057239438e-01 +8.832465034046749208e-01 +8.852566213878946266e-01 +8.872515300993668586e-01 +8.892311507835116702e-01 +8.911954052882941069e-01 +8.931442160683095155e-01 +8.950775061878453176e-01 +8.969951993239176913e-01 +8.988972197692854937e-01 +9.007834924354383155e-01 +9.026539428555608868e-01 +9.045084971874738367e-01 +9.063470822165470286e-01 +9.081696253585921363e-01 +9.099760546627261304e-01 +9.117662988142137825e-01 +9.135402871372810818e-01 +9.152979495979065572e-01 +9.170392168065857330e-01 +9.187640200210708263e-01 +9.204722911490845760e-01 +9.221639627510074266e-01 +9.238389680425416195e-01 +9.254972408973460851e-01 +9.271387158496476877e-01 +9.287633280968261573e-01 +9.303710135019719329e-01 +9.319617085964179148e-01 +9.335353505822450160e-01 +9.350918773347628443e-01 +9.366312274049599651e-01 +9.381533400219316254e-01 +9.396581550952780582e-01 +9.411456132174766953e-01 +9.426156556662275143e-01 +9.440682244067721829e-01 +9.455032620941840049e-01 +9.469207120756318874e-01 +9.483205183926179949e-01 +9.497026257831856499e-01 +9.510669796841013657e-01 +9.524135262330096774e-01 +9.537422122705585537e-01 +9.550529853424978288e-01 +9.563457937017514343e-01 +9.576205863104587657e-01 +9.588773128419906255e-01 +9.601159236829353016e-01 +9.613363699350575553e-01 +9.625386034172290772e-01 +9.637225766673305216e-01 +9.648882429441256736e-01 +9.660355562291054188e-01 +9.671644712283059553e-01 +9.682749433740961420e-01 +9.693669288269369799e-01 +9.704403844771127829e-01 +9.714952679464322616e-01 +9.725315375899022952e-01 +9.735491524973720612e-01 +9.745480724951472995e-01 +9.755282581475767101e-01 +9.764896707586095959e-01 +9.774322723733215312e-01 +9.783560257794153836e-01 +9.792608945086879180e-01 +9.801468428384716436e-01 +9.810138357930430208e-01 +9.818618391450050220e-01 +9.826908194166369404e-01 +9.835007438812174430e-01 +9.842915805643155380e-01 +9.850632982450528985e-01 +9.858158664573368757e-01 +9.865492554910632039e-01 +9.872634363932887291e-01 +9.879583809693738283e-01 +9.886340617840968514e-01 +9.892904521627360337e-01 +9.899275261921235414e-01 +9.905452587216669880e-01 +9.911436253643443051e-01 +9.917226024976648624e-01 +9.922821672646028324e-01 +9.928222975744990242e-01 +9.933429721039341853e-01 +9.938441702975688852e-01 +9.943258723689569756e-01 +9.947880593013254114e-01 +9.952307128483255383e-01 +9.956538155347532948e-01 +9.960573506572389935e-01 +9.964413022849067936e-01 +9.968056552600040865e-01 +9.971503951984994618e-01 +9.974755084906502534e-01 +9.977809823015399981e-01 +9.980668045715863634e-01 +9.983329640170149899e-01 +9.985794501303070225e-01 +9.988062531806126687e-01 +9.990133642141358905e-01 +9.992007750544874556e-01 +9.993684783030087893e-01 +9.995164673390624088e-01 +9.996447363202946024e-01 +9.997532801828656890e-01 +9.998420946416499699e-01 +9.999111761904043716e-01 +9.999605221019081114e-01 +9.999901304280686132e-01 +1.000000000000000000e+00 +9.999901304280686132e-01 +9.999605221019081114e-01 +9.999111761904043716e-01 +9.998420946416499699e-01 +9.997532801828656890e-01 +9.996447363202946024e-01 +9.995164673390624088e-01 +9.993684783030087893e-01 +9.992007750544874556e-01 +9.990133642141358905e-01 +9.988062531806126687e-01 +9.985794501303070225e-01 +9.983329640170149899e-01 +9.980668045715863634e-01 +9.977809823015399981e-01 +9.974755084906502534e-01 +9.971503951984994618e-01 +9.968056552600040865e-01 +9.964413022849067936e-01 +9.960573506572389935e-01 +9.956538155347532948e-01 +9.952307128483255383e-01 +9.947880593013254114e-01 +9.943258723689569756e-01 +9.938441702975688852e-01 +9.933429721039340743e-01 +9.928222975744990242e-01 +9.922821672646028324e-01 +9.917226024976648624e-01 +9.911436253643443051e-01 +9.905452587216669880e-01 +9.899275261921235414e-01 +9.892904521627361447e-01 +9.886340617840968514e-01 +9.879583809693738283e-01 +9.872634363932885071e-01 +9.865492554910632039e-01 +9.858158664573368757e-01 +9.850632982450528985e-01 +9.842915805643155380e-01 +9.835007438812174430e-01 +9.826908194166369404e-01 +9.818618391450050220e-01 +9.810138357930430208e-01 +9.801468428384716436e-01 +9.792608945086879180e-01 +9.783560257794153836e-01 +9.774322723733215312e-01 +9.764896707586095959e-01 +9.755282581475767101e-01 +9.745480724951472995e-01 +9.735491524973720612e-01 +9.725315375899024062e-01 +9.714952679464321506e-01 +9.704403844771127829e-01 +9.693669288269369799e-01 +9.682749433740961420e-01 +9.671644712283059553e-01 +9.660355562291054188e-01 +9.648882429441256736e-01 +9.637225766673305216e-01 +9.625386034172290772e-01 +9.613363699350574443e-01 +9.601159236829353016e-01 +9.588773128419906255e-01 +9.576205863104587657e-01 +9.563457937017514343e-01 +9.550529853424978288e-01 +9.537422122705584426e-01 +9.524135262330098994e-01 +9.510669796841013657e-01 +9.497026257831854279e-01 +9.483205183926177728e-01 +9.469207120756318874e-01 +9.455032620941838939e-01 +9.440682244067721829e-01 +9.426156556662278474e-01 +9.411456132174766953e-01 +9.396581550952782802e-01 +9.381533400219318475e-01 +9.366312274049601871e-01 +9.350918773347629553e-01 +9.335353505822450160e-01 +9.319617085964179148e-01 +9.303710135019720440e-01 +9.287633280968262683e-01 +9.271387158496476877e-01 +9.254972408973460851e-01 +9.238389680425416195e-01 +9.221639627510076487e-01 +9.204722911490845760e-01 +9.187640200210708263e-01 +9.170392168065857330e-01 +9.152979495979065572e-01 +9.135402871372810818e-01 +9.117662988142137825e-01 +9.099760546627261304e-01 +9.081696253585921363e-01 +9.063470822165471397e-01 +9.045084971874738367e-01 +9.026539428555611089e-01 +9.007834924354383155e-01 +8.988972197692854937e-01 +8.969951993239178023e-01 +8.950775061878453176e-01 +8.931442160683095155e-01 +8.911954052882941069e-01 +8.892311507835118922e-01 +8.872515300993670806e-01 +8.852566213878947377e-01 +8.832465034046749208e-01 +8.812212555057239438e-01 +8.791809576443611052e-01 +8.771256903680519912e-01 +8.750555348152299073e-01 +8.729705727120912195e-01 +8.708708863693697122e-01 +8.687565586790869654e-01 +8.666276731112800835e-01 +8.644843137107058872e-01 +8.623265650935234561e-01 +8.601545124439534673e-01 +8.579682415109156635e-01 +8.557678386046427832e-01 +8.535533905932739529e-01 +8.513249848994246527e-01 +8.490827094967364763e-01 +8.468266529064025772e-01 +8.445569041936743515e-01 +8.422735529643444741e-01 +8.399766893612096164e-01 +8.376664040605122930e-01 +8.353427882683600592e-01 +8.330059337171259459e-01 +8.306559326618259131e-01 +8.282928778764783173e-01 +8.259168626504396205e-01 +8.235279807847220024e-01 +8.211263265882924323e-01 +8.187119948743448727e-01 +8.162850809565623811e-01 +8.138456806453501224e-01 +8.113938902440562817e-01 +8.089298065451674402e-01 +8.064535268264882983e-01 +8.039651488473028573e-01 +8.014647708445122865e-01 +7.989524915287594675e-01 +7.964284100805295585e-01 +7.938926261462365686e-01 +7.913452398342879501e-01 +7.887863517111338707e-01 +7.862160627972956117e-01 +7.836344745633782027e-01 +7.810416889260655138e-01 +7.784378082440939206e-01 +7.758229353142153117e-01 +7.731971733671344493e-01 +7.705606260634378923e-01 +7.679133974894981618e-01 +7.652555921533670258e-01 +7.625873149806475793e-01 +7.599086713103547774e-01 +7.572197668907533208e-01 +7.545207078751855478e-01 +7.518116008178805654e-01 +7.490925526697452819e-01 +7.463636707741457821e-01 +7.436250628626660530e-01 +7.408768370508576062e-01 +7.381191018339693377e-01 +7.353519660826662863e-01 +7.325755390387292953e-01 +7.297899303107437952e-01 +7.269952498697733745e-01 +7.241916080450160331e-01 +7.213791155194507754e-01 +7.185578833254663289e-01 +7.157280228404795386e-01 +7.128896457825361077e-01 +7.100428642059030127e-01 +7.071877904966422657e-01 +7.043245373681743526e-01 +7.014532178568313459e-01 +6.985739453173901437e-01 +6.956868334186012692e-01 +6.927919961386980185e-01 +6.898895477609005011e-01 +6.869796028689000300e-01 +6.840622763423388486e-01 +6.811376833522728713e-01 +6.782059393566252092e-01 +6.752671600956294817e-01 +6.723214615872583622e-01 +6.693689601226456842e-01 +6.664097722614931163e-01 +6.634440148274711735e-01 +6.604718049036044647e-01 +6.574932598276523876e-01 +6.545084971874737256e-01 +6.515176348163868036e-01 +6.485207907885174317e-01 +6.455180834141357460e-01 +6.425096312349884986e-01 +6.394955530196148041e-01 +6.364759677586629971e-01 +6.334509946601878383e-01 +6.304207531449488311e-01 +6.273853628416912187e-01 +6.243449435824276472e-01 +6.212996153977037306e-01 +6.182494985118625053e-01 +6.151947133382956734e-01 +6.121353804746907379e-01 +6.090716206982716985e-01 +6.060035549610274241e-01 +6.029313043849410247e-01 +5.998549902572035686e-01 +5.967747340254304644e-01 +5.936906572928623005e-01 +5.906028818135689029e-01 +5.875115294876379624e-01 +5.844167223563671021e-01 +5.813185825974421794e-01 +5.782172325201154761e-01 +5.751127945603787817e-01 +5.720053912761261516e-01 +5.688951453423192195e-01 +5.657821795461412950e-01 +5.626666167821522402e-01 +5.595485800474347959e-01 +5.564281924367410204e-01 +5.533055771376302889e-01 +5.501808574256075168e-01 +5.470541566592573846e-01 +5.439255982753716800e-01 +5.407953057840789723e-01 +5.376634027639664026e-01 +5.345300128572030296e-01 +5.313952597646566245e-01 +5.282592672410123535e-01 +5.251221590898850211e-01 +5.219840591589325340e-01 +5.188450913349674787e-01 +5.157053795390641460e-01 +5.125650477216689982e-01 +5.094242198577040304e-01 +5.062830199416764598e-01 +5.031415719827793120e-01 +5.000000000000001110e-01 +4.968584280172208545e-01 +4.937169800583237622e-01 +4.905757801422960807e-01 +4.874349522783312239e-01 +4.842946204609360206e-01 +4.811549086650326323e-01 +4.780159408410676880e-01 +4.748778409101150899e-01 +4.717407327589878685e-01 +4.686047402353435976e-01 +4.654699871427971369e-01 +4.623365972360338194e-01 +4.592046942159211942e-01 +4.560744017246285420e-01 +4.529458433407427265e-01 +4.498191425743926497e-01 +4.466944228623699331e-01 +4.435718075632592017e-01 +4.404514199525653706e-01 +4.373333832178479263e-01 +4.342178204538589270e-01 +4.311048546576808915e-01 +4.279946087238740704e-01 +4.248872054396213849e-01 +4.217827674798846904e-01 +4.186814174025580426e-01 +4.155832776436331200e-01 +4.124884705123622042e-01 +4.093971181864312636e-01 +4.063093427071379216e-01 +4.032252659745698131e-01 +4.001450097427966535e-01 +3.970686956150591973e-01 +3.939964450389727424e-01 +3.909283793017285236e-01 +3.878646195253094286e-01 +3.848052866617044376e-01 +3.817505014881376613e-01 +3.787003846022964360e-01 +3.756550564175725193e-01 +3.726146371583090033e-01 +3.695792468550513910e-01 +3.665490053398122727e-01 +3.635240322413371694e-01 +3.605044469803854179e-01 +3.574903687650116679e-01 +3.544819165858640320e-01 +3.514792092114826794e-01 +3.484823651836129188e-01 +3.454915028125263854e-01 +3.425067401723474458e-01 +3.395281950963952577e-01 +3.365559851725286045e-01 +3.335902277385066617e-01 +3.306310398773540937e-01 +3.276785384127414158e-01 +3.247328399043706293e-01 +3.217940606433745132e-01 +3.188623166477272397e-01 +3.159377236576608183e-01 +3.130203971310998035e-01 +3.101104522390992213e-01 +3.072080038613017039e-01 +3.043131665813985087e-01 +3.014260546826096343e-01 +2.985467821431687652e-01 +2.956754626318253698e-01 +2.928122095033579564e-01 +2.899571357940966543e-01 +2.871103542174636702e-01 +2.842719771595202394e-01 +2.814421166745335046e-01 +2.786208844805489471e-01 +2.758083919549838003e-01 +2.730047501302266810e-01 +2.702100696892559273e-01 +2.674244609612708712e-01 +2.646480339173335472e-01 +2.618808981660304402e-01 +2.591231629491421162e-01 +2.563749371373337804e-01 +2.536363292258538849e-01 +2.509074473302548292e-01 +2.481883991821196567e-01 +2.454792921248145632e-01 +2.427802331092467902e-01 +2.400913286896454168e-01 +2.374126850193525040e-01 +2.347444078466331130e-01 +2.320866025105019770e-01 +2.294393739365621077e-01 +2.268028266328657172e-01 +2.241770646857848825e-01 +2.215621917559061904e-01 +2.189583110739346805e-01 +2.163655254366218805e-01 +2.137839372027044993e-01 +2.112136482888663236e-01 +2.086547601657122442e-01 +2.061073738537635425e-01 +2.035715899194706080e-01 +2.010475084712405602e-01 +1.985352291554878246e-01 +1.960348511526973092e-01 +1.935464731735118959e-01 +1.910701934548327818e-01 +1.886061097559438571e-01 +1.861543193546500441e-01 +1.837149190434377855e-01 +1.812880051256553771e-01 +1.788736734117078453e-01 +1.764720192152779976e-01 +1.740831373495606016e-01 +1.717071221235218770e-01 +1.693440673381740036e-01 +1.669940662828742761e-01 +1.646572117316401629e-01 +1.623335959394878181e-01 +1.600233106387906057e-01 +1.577264470356556925e-01 +1.554430958063259538e-01 +1.531733470935974506e-01 +1.509172905032638012e-01 +1.486750151005753473e-01 +1.464466094067263247e-01 +1.442321613953575221e-01 +1.420317584890844753e-01 +1.398454875560466992e-01 +1.376734349064766549e-01 +1.355156862892944181e-01 +1.333723268887199720e-01 +1.312434413209131179e-01 +1.291291136306303433e-01 +1.270294272879090025e-01 +1.249444651847704119e-01 +1.228743096319480643e-01 +1.208190423556391585e-01 +1.187787444942760007e-01 +1.167534965953251902e-01 +1.147433786121053179e-01 +1.127484699006330998e-01 +1.107688492164881772e-01 +1.088045947117059348e-01 +1.068557839316906510e-01 +1.049224938121548073e-01 +1.030048006760824197e-01 +1.011027802307144785e-01 +9.921650756456176778e-02 +9.734605714443890501e-02 +9.549150281252624661e-02 +9.365291778345290197e-02 +9.183037464140793305e-02 +9.002394533727396675e-02 +8.823370118578624521e-02 +8.645971286271916800e-02 +8.470205040209359548e-02 +8.296078319341440577e-02 +8.123597997892903488e-02 +7.952770885091546560e-02 +7.783603724899237908e-02 +7.616103195745833887e-02 +7.450275910265394264e-02 +7.286128415035239558e-02 +7.123667190317387043e-02 +6.962898649802808093e-02 +6.803829140358244598e-02 +6.646464941775491464e-02 +6.490812266523718344e-02 +6.336877259503978510e-02 +6.184665997806816640e-02 +6.034184490472174062e-02 +5.885438678252330469e-02 +5.738434433377247179e-02 +5.593177559322771303e-02 +5.449673790581603672e-02 +5.307928792436806403e-02 +5.167948160738210228e-02 +5.029737421681435700e-02 +4.893302031589858575e-02 +4.758647376699011444e-02 +4.625778772944143247e-02 +4.494701465750217118e-02 +4.365420629824853793e-02 +4.237941368954127597e-02 +4.112268715800928426e-02 +3.988407631706478162e-02 +3.866363006494242388e-02 +3.746139658277095746e-02 +3.627742333266925634e-02 +3.511175705587420148e-02 +3.396444377089454653e-02 +3.283552877169391288e-02 +3.172505662590380943e-02 +3.063307117306288824e-02 +2.955961552288726563e-02 +2.850473205356760659e-02 +2.746846241009755912e-02 +2.645084750262772719e-02 +2.545192750485270050e-02 +2.447174185242324135e-02 +2.351032924139054292e-02 +2.256772762667843060e-02 +2.164397422058470313e-02 +2.073910549131204387e-02 +1.985315716152832866e-02 +1.898616420695698956e-02 +1.813816085499507860e-02 +1.730918058336302495e-02 +1.649925611878251541e-02 +1.570841943568445503e-02 +1.493670175494710324e-02 +1.418413354266298380e-02 +1.345074450893671801e-02 +1.273656360671149984e-02 +1.204161903062637984e-02 +1.136593821590326132e-02 +1.070954783726399753e-02 +1.007247380787648638e-02 +9.454741278333008564e-03 +8.856374635655587385e-03 +8.277397502335205257e-03 +7.717832735397246562e-03 +7.177702425501049539e-03 +6.657027896066045405e-03 +6.155829702431123499e-03 +5.674127631043058249e-03 +5.211940698674534002e-03 +4.769287151674420945e-03 +4.346184465246665310e-03 +3.942649342761090671e-03 +3.558697715093159155e-03 +3.194344739995816362e-03 +2.849604801500574616e-03 +2.524491509349872410e-03 +2.219017698460000985e-03 +1.933195428413718962e-03 +1.667035982985024412e-03 +1.420549869692992653e-03 +1.193746819387333461e-03 +9.866357858641615353e-04 +7.992249455125140581e-04 +6.315216969912583423e-04 +4.835326609376300430e-04 +3.552636797053673788e-04 +2.467198171342090997e-04 +1.579053583499612364e-04 +8.882380959548627237e-05 +3.947789809190699632e-05 +9.869571931439562087e-06 diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 7c9dab72..91cae573 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -74,20 +74,24 @@ def get_synapse_id_by_target(self, target): ICUB_VOR_ENV_REGION_BYTES = 4 BASE_DATA_REGION_BYTES = 3 * 4 - MAX_SIM_DURATION = 1000 * 60 * 60 * 24 # 1 day + MAX_SIM_DURATION = 10000 +# RECORDABLE_VARIABLES = "error" + RECORDABLE_VARIABLES = [ + "L_count", "R_count", "error", "head_pos", "head_vel"] + RECORDABLE_DTYPES = [ + DataType.UINT32, DataType.UINT32, DataType.S1615, DataType.S1615, + DataType.S1615] # parameters expected by PyNN default_parameters = { 'error_window_size': 10, - 'error_value': 0.0, 'constraints': None, 'label': "ICubVorEnv", 'incoming_spike_buffer_size': None, 'duration': MAX_SIM_DURATION} - def __init__(self, head_positions, head_velocities, + def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size=default_parameters['error_window_size'], - error_value=default_parameters['error_value'], constraints=default_parameters['constraints'], label=default_parameters['label'], incoming_spike_buffer_size=default_parameters[ @@ -100,23 +104,39 @@ def __init__(self, head_positions, head_velocities, self._label = label # Pass in variables - self._head_positions = head_positions - self._head_velocities = head_velocities + self._head_pos = head_pos + self._head_vel = head_vel + self._perfect_eye_pos = perfect_eye_pos + self._perfect_eye_vel = perfect_eye_vel self._error_window_size = error_window_size - self._error_value = error_value - self._number_of_inputs = len(head_positions) - if self._number_of_inputs != len(head_velocities): + self._number_of_inputs = len(head_pos) + if self._number_of_inputs != len(head_vel): raise ConfigurationException( "The length of head_positions {} is not the same as the " "length of head_velocities {}".format( - self._number_of_inputs, len(head_velocities))) + self._number_of_inputs, len(head_vel))) # n_neurons is the number of atoms in the network, which in this # case only needs to be 2 (for receiving "left" and "right") self._n_neurons = 2 - # used to define size of recording region - self._recording_size = int((simulation_duration_ms / 1000.) * 4) + # used to define size of recording region: + # record variables every error_window_size ms (same size each time) + self._n_recordable_variables = len(self.RECORDABLE_VARIABLES) + + self._recording_size = int( + (simulation_duration_ms / error_window_size) * + front_end_common_constants.BYTES_PER_WORD) + + # set up recording region IDs and data types + self._region_ids = dict() + self._region_dtypes = dict() + for n in range(self._n_recordable_variables): + self._region_ids[self.RECORDABLE_VARIABLES[n]] = n + self._region_dtypes[ + self.RECORDABLE_VARIABLES[n]] = self.RECORDABLE_DTYPES[n] + + self._m_vertex = None # Superclasses ApplicationVertex.__init__( @@ -195,10 +215,11 @@ def generate_data_specification(self, spec, placement, machine_time_step, # reserve recording region spec.reserve_memory_region( ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.RECORDING.value, - recording_utilities.get_recording_header_size(1)) + recording_utilities.get_recording_header_size( + len(self.RECORDABLE_VARIABLES))) spec.reserve_memory_region( region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value, - size=self.BASE_DATA_REGION_BYTES+(self._number_of_inputs*8), + size=self.BASE_DATA_REGION_BYTES+(self._number_of_inputs*16), label='ICubVorEnvArms') # Write setup region @@ -221,20 +242,34 @@ def generate_data_specification(self, spec, placement, machine_time_step, spec.switch_write_focus( ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.RECORDING.value) ip_tags = tags.get_ip_tags_for_vertex(self) or [] + recording_sizes = [ + self._recording_size for _ in range(self._n_recordable_variables)] spec.write_array(recording_utilities.get_recording_header_array( - [self._recording_size], ip_tags=ip_tags)) + recording_sizes, ip_tags=ip_tags)) - # Write probabilites for arms + # Write parameters for ICubVorEnv data spec.comment("\nWriting icub_vor_env data region:\n") + float_scale = float(DataType.S1615.scale) spec.switch_write_focus( ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value) spec.write_value(self._error_window_size, data_type=DataType.UINT32) - spec.write_value(self._error_value, data_type=DataType.UINT32) spec.write_value(self._number_of_inputs, data_type=DataType.UINT32) # Write the data - Arrays must be 32-bit values, so convert - data = numpy.array(self._head_positions, dtype=numpy.uint32) + data = numpy.array( + [int(x * float_scale) for x in self._head_pos], + dtype=numpy.uint32) spec.write_array(data.view(numpy.uint32)) - data = numpy.array(self._head_velocities, dtype=numpy.uint32) + data = numpy.array( + [int(x * float_scale) for x in self._head_vel], + dtype=numpy.uint32) + spec.write_array(data.view(numpy.uint32)) + data = numpy.array( + [int(x * float_scale) for x in self._perfect_eye_pos], + dtype=numpy.uint32) + spec.write_array(data.view(numpy.uint32)) + data = numpy.array( + [int(x * float_scale) for x in self._perfect_eye_vel], + dtype=numpy.uint32) spec.write_array(data.view(numpy.uint32)) # End-of-Spec: @@ -269,11 +304,12 @@ def set_value(self, key, value): AbstractNeuronRecordable.clear_recording) def clear_recording( self, variable, buffer_manager, placements): - self._clear_recording_region(buffer_manager, placements, 0) + for n in range(len(self.RECORDABLE_VARIABLES)): + self._clear_recording_region(buffer_manager, placements, n) @overrides(AbstractNeuronRecordable.get_recordable_variables) def get_recordable_variables(self): - return 'score' # whatever this "records" will probably not be "score" + return self.RECORDABLE_VARIABLES @overrides(AbstractNeuronRecordable.is_recording) def is_recording(self, variable): @@ -286,25 +322,41 @@ def set_recording(self, variable, new_state=True, sampling_interval=None, @overrides(AbstractNeuronRecordable.get_neuron_sampling_interval) def get_neuron_sampling_interval(self, variable): - return 10000 # 10 seconds hard coded in bkout.c + return 10000 # 10 seconds hard coded in as sim duration... ? @overrides(AbstractNeuronRecordable.get_data) def get_data(self, variable, n_machine_time_steps, placements, buffer_manager, machine_time_step): - vertex = self.machine_vertices.pop() - print('get_data from machine vertex ', vertex) - placement = placements.get_placement_of_vertex(vertex) + if self._m_vertex is None: + self._m_vertex = self.machine_vertices.pop() + print('get_data from machine vertex ', self._m_vertex, + ' for variable ', variable) + placement = placements.get_placement_of_vertex(self._m_vertex) # Read the data recorded - data_values, _ = buffer_manager.get_data_by_placement(placement, 0) + data_values, _ = buffer_manager.get_data_by_placement( + placement, self._region_ids[variable]) data = data_values numpy_format = list() - numpy_format.append(("Score", numpy.int32)) + output_format = list() + if self._region_dtypes[variable] is DataType.S1615: + numpy_format.append((variable, numpy.int32)) + output_format.append((variable, numpy.float32)) + else: + numpy_format.append((variable, numpy.int32)) output_data = numpy.array(data, dtype=numpy.uint8).view(numpy_format) - - return output_data + if self._region_dtypes[variable] is DataType.S1615: + convert = numpy.zeros_like( + output_data, dtype=numpy.float32).view(output_format) + for i in range(output_data.size): + for j in range(len(numpy_format)): + convert[i][j] = float( + output_data[i][j]) / float(DataType.S1615.scale) + return convert + else: + return output_data def reset_ring_buffer_shifts(self): pass diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 3530b224..1f7960de 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -31,24 +31,24 @@ def __init__(self, resources_required, constraints=None, label=None, # Superclasses MachineVertex.__init__( self, label, constraints, app_vertex, vertex_slice) - self._resource_required = resources_required + self._resources_required = resources_required @property def resources_required(self): - return self._resource_required + return self._resources_required def get_minimum_buffer_sdram_usage(self): return 0 # probably should make this a user input def get_recorded_region_ids(self): - return [0] + return [0, 1, 2, 3, 4] def get_recording_region_base_address(self, txrx, placement): return helpful_functions.locate_memory_region_for_placement( placement, self._ICUB_VOR_ENV_REGIONS.RECORDING.value, txrx) def get_n_keys_for_partition(self, partition): - return 8 # for control IDs (CHECK: this should be 2, right?) + return 2 # for control IDs (CHECK: this should be 2, right?) @overrides(AbstractHasAssociatedBinary.get_binary_file_name) def get_binary_file_name(self): From 49ef436fa1fd1ab1bd15e98aad9f99226fb6831a Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 30 Oct 2020 11:16:58 +0000 Subject: [PATCH 03/54] Encode rates based on error and send to connected SpikeSourcePoisson --- c_code/icub_vor_env/src/icub_vor_env.c | 105 +++++++++++++----- examples/icub_vor_env/icub_vor_env_test.py | 66 +++++++---- spinn_gym/games/icub_vor_env/icub_vor_env.py | 11 +- .../icub_vor_env_machine_vertex.py | 7 +- 4 files changed, 138 insertions(+), 51 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 88536797..12dd8fdd 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -12,6 +12,8 @@ #include #include +#include + // Spin 1 API includes #include @@ -25,6 +27,7 @@ #include + //---------------------------------------------------------------------------- // Enumerations //---------------------------------------------------------------------------- @@ -69,6 +72,7 @@ static uint32_t infinite_run; // - head position, head velocity arrays // - perfect eye position, perfect eye velocity arrays (unused at present) uint32_t error_window_size; +uint32_t output_size; uint32_t number_of_inputs; accum *head_positions; accum *head_velocities; @@ -77,6 +81,7 @@ accum *perfect_eye_vel; //accum *eye_pos; //accum *eye_vel; +//accum *encoded_error_rates; //! Global error value accum error_value = 0.0k; @@ -102,9 +107,14 @@ uint32_t simulation_ticks = 0; // This is the function for sending a spike out from the environment, currently // related to the counts at the Left and Right atoms -static inline void send_spike(int input) +static inline void send_spike(int input, accum value) { - spin1_send_mc_packet(key | (input), 0, NO_PAYLOAD); +// uint32_t payload = bitsk(value); +// io_printf(IO_BUF, "payload %d value %k", payload, value); + // The rate value needs to be sent as a uint32_t, so convert and send + spin1_send_mc_packet(key | (input), bitsk(value), WITH_PAYLOAD); +// spin1_send_mc_packet(key | (input), value, WITH_PAYLOAD); +// spin1_send_mc_packet(key | (input), 0, NO_PAYLOAD); // io_printf(IO_BUF, "sending spike to input %d\n", input); } @@ -157,14 +167,15 @@ static bool initialize(uint32_t *timer_period) // Ideally I guess this could be set up using a struct, but let's keep it simpler for now error_window_size = icub_vor_env_data_region[0]; - number_of_inputs = icub_vor_env_data_region[1]; - head_positions = (accum *)&icub_vor_env_data_region[2]; - head_velocities = (accum *)&icub_vor_env_data_region[2 + number_of_inputs]; - perfect_eye_pos = (accum *)&icub_vor_env_data_region[2 + (2 * number_of_inputs)]; - perfect_eye_vel = (accum *)&icub_vor_env_data_region[2 + (3 * number_of_inputs)]; + output_size = icub_vor_env_data_region[1]; + number_of_inputs = icub_vor_env_data_region[2]; + head_positions = (accum *)&icub_vor_env_data_region[3]; + head_velocities = (accum *)&icub_vor_env_data_region[3 + number_of_inputs]; + perfect_eye_pos = (accum *)&icub_vor_env_data_region[3 + (2 * number_of_inputs)]; + perfect_eye_vel = (accum *)&icub_vor_env_data_region[3 + (3 * number_of_inputs)]; // Print some values out to check - io_printf(IO_BUF, "error_window_size %u\n", error_window_size); + io_printf(IO_BUF, "error_window_size %u output_size %u\n", error_window_size, output_size); io_printf(IO_BUF, "At 0: head pos %k, head vel %k, eye pos %k, eye vel %k\n", head_positions[0], head_velocities[0], perfect_eye_pos[0], perfect_eye_vel[0]); io_printf(IO_BUF, "At 250: head pos %k, head vel %k, eye pos %k, eye vel %k\n", @@ -216,35 +227,77 @@ void mc_packet_received_callback(uint keyx, uint payload) void test_the_head() { // Here I am testing this is working by sending a spike out to // wherever this vertex connects to, depending on which counter is higher. - if (spike_counters[0] > spike_counters[1]) { -// io_printf(IO_BUF, "spike_counters[0] %u > spike_counters[1] %u \n", -// spike_counters[0], spike_counters[1]); - send_spike(0); - // L > R so "move eye left" (blank for now while we decide how to do this) - - } - else { -// io_printf(IO_BUF, "spike_counters[0] %u <= spike_counters[1] %u \n", -// spike_counters[0], spike_counters[1]); - send_spike(1); - // L <= R so "move eye right" (blank for now while we decide how to do this) - - } +// if (spike_counters[0] > spike_counters[1]) { +//// io_printf(IO_BUF, "spike_counters[0] %u > spike_counters[1] %u \n", +//// spike_counters[0], spike_counters[1]); +// send_spike(0, 0); +// // L > R so "move eye left" (blank for now while we decide how to do this) +// +// } +// else { +//// io_printf(IO_BUF, "spike_counters[0] %u <= spike_counters[1] %u \n", +//// spike_counters[0], spike_counters[1]); +// send_spike(1, 0); +// // L <= R so "move eye right" (blank for now while we decide how to do this) +// +// } // Here is where the error should be calculated: for now measure the error - // from the default eye position (middle = 0.5) and default velocity (0.0) + // from the default eye position (middle = 0.5) and stationary velocity (0.0) accum DEFAULT_EYE_POS = 0.5k; accum DEFAULT_EYE_VEL = 0.0k; - // I'm not sure whether this should be an absolute error or not... - accum error_pos = absk(head_positions[tick_in_head_loop] - DEFAULT_EYE_POS); - accum error_vel = absk(head_velocities[tick_in_head_loop] - DEFAULT_EYE_VEL); + // Error is relative (in both cases) as the test is done based on > or < 0.0 + accum error_pos = head_positions[tick_in_head_loop] - DEFAULT_EYE_POS; + accum error_vel = head_velocities[tick_in_head_loop] - DEFAULT_EYE_VEL; error_value = error_pos + error_vel; // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has // been worked out how the spike counters at L and R translate to head/eye movement + // Encode the error into a series of rates which are then sent on + accum min_rate = 2.0k; + accum max_rate = 20.0k; + + accum mid_neuron = (accum) (output_size) * 0.5k; + accum low_threshold = absk(error_value) * mid_neuron; + accum up_threshold = low_threshold - mid_neuron; + + // The first 100 values in the connecting pop are agonist, then the next 100 are antagonist + uint32_t loop_size = output_size / 2; + for (uint32_t n=0; n < loop_size; n++) { + accum loop_value = (accum) n; + // Unless otherwise specified, rate values are min_rate + accum agonist_rate = min_rate; + accum antagonist_rate = min_rate; + if (loop_value < up_threshold) { + if (error_value >= 0.0k) { + // Antagonist is max_rate + antagonist_rate = max_rate; + } else { + // Agonist is max_rate + agonist_rate = max_rate; + } + } else if (loop_value < low_threshold) { + accum loop_to_up_value = loop_value - up_threshold; + accum low_to_up_value = low_threshold - up_threshold; +// threshold_calc = inter_value1 / inter_value2; + accum encoded_error_rate = max_rate - ((max_rate-min_rate) * (loop_to_up_value / low_to_up_value)); + if (error_value >= 0.0k) { + // Antagonist is encoded_error_rate + antagonist_rate = encoded_error_rate; + } else { + // Agonist is encoded_error_rate + agonist_rate = encoded_error_rate; + } + } + + // Now send the relevant spikes to the connected SSP population + send_spike(n, agonist_rate); + send_spike(n+loop_size, antagonist_rate); + } + } void timer_callback(uint unused, uint dummy) diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 303ccb2a..71c81c3d 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -53,10 +53,11 @@ def get_head_vel(icub_vor_env_pop, simulator): # Build input SSP and output population input_size = 2 -rate = 20 -input_pop = p.Population(input_size, p.SpikeSourcePoisson(rate=rate)) +output_size = 200 -output_pop = p.Population(2, p.IF_cond_exp()) +input_rate = 20 +input_pop = p.Population(input_size, p.SpikeSourcePoisson(rate=input_rate)) +output_pop = p.Population(output_size, p.SpikeSourcePoisson(rate=0)) # get head_positions and head_velocities from file (1000 samples) base_dir = "./" @@ -72,7 +73,8 @@ def get_head_vel(icub_vor_env_pop, simulator): # build ICubVorEnv model pop error_window_size = 10 icub_vor_env_model = gym.ICubVorEnv( - head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size) + head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, + output_size) icub_vor_env_pop = p.Population(input_size, icub_vor_env_model) # Set recording for input and output pop (env pop records by default) @@ -82,9 +84,9 @@ def get_head_vel(icub_vor_env_pop, simulator): # Input -> ICubVorEnv projection i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) -# ICubVorEnv -> output projection -i2o2 = p.Projection(icub_vor_env_pop, output_pop, p.OneToOneConnector(), - p.StaticSynapse(weight=0.1, delay=1.0)) +# ICubVorEnv -> output, setup live output to the SSP vertex +p.external_devices.activate_live_output_to( + icub_vor_env_pop, output_pop, "CONTROL") # Store simulator and run simulator = get_simulator() @@ -101,18 +103,39 @@ def get_head_vel(icub_vor_env_pop, simulator): icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) # get the spike data from input and output and plot -spikes_in = input_pop.get_data('spikes').segments[0].spiketrains -spikes_out = output_pop.get_data('spikes').segments[0].spiketrains -Figure( - Panel(spikes_in, xlabel="Time (ms)", ylabel="nID", xticks=True), - Panel(spikes_out, xlabel="Time (ms)", ylabel="nID", xticks=True) -) -plt.show() +# spikes_in = input_pop.get_data('spikes').segments[0].spiketrains +# spikes_out = output_pop.get_data('spikes').segments[0].spiketrains +# Figure( +# Panel(spikes_in, xlabel="Time (ms)", ylabel="nID", +# xticks=True, yticks=True), +# Panel(spikes_out, xlabel="Time (ms)", ylabel="nID", +# xticks=True, yticks=True) +# ) +# plt.show() + +spikes_in_spin = input_pop.spinnaker_get_data('spikes') +spikes_out_spin = output_pop.spinnaker_get_data('spikes') + +# end simulation +p.end() # plot the data from the ICubVorEnv pop x_plot = [(n) for n in range(0, runtime, error_window_size)] -plt.figure(figsize=(10, 7)) -plt.subplot(3, 1, 1) +plt.figure(figsize=(15, 11)) + +plt.subplot(5, 1, 1) +plt.scatter( + [i[1] for i in spikes_in_spin], [i[0] for i in spikes_in_spin], s=1) +plt.legend(loc="best") +plt.xlim([0, runtime]) + +plt.subplot(5, 1, 2) +plt.plot(x_plot, l_counts, 'bo', label="l_counts") +plt.plot(x_plot, r_counts, 'ro', label="r_counts") +plt.legend(loc="best") +plt.xlim([0, runtime]) + +plt.subplot(5, 1, 3) plt.plot(x_plot, rec_head_pos, label="head position") plt.plot(x_plot, rec_head_vel, label="head velocity") # plt.plot(perfect_eye_pos, label="eye position", ls='--') @@ -120,16 +143,15 @@ def get_head_vel(icub_vor_env_pop, simulator): plt.legend(loc="best") plt.xlim([0, runtime]) -plt.subplot(3, 1, 2) +plt.subplot(5, 1, 4) plt.plot(x_plot, errors, label="errors") plt.legend(loc="best") plt.xlim([0, runtime]) -plt.subplot(3, 1, 3) -plt.plot(x_plot, l_counts, 'bo', label="l_counts") -plt.plot(x_plot, r_counts, 'ro', label="r_counts") +plt.subplot(5, 1, 5) +plt.scatter( + [i[1] for i in spikes_out_spin], [i[0] for i in spikes_out_spin], s=1) plt.legend(loc="best") plt.xlim([0, runtime]) -plt.show() -p.end() +plt.show() diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 91cae573..ba330231 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -72,10 +72,13 @@ def clear_connection_cache(self): def get_synapse_id_by_target(self, target): return 0 + # key value ICUB_VOR_ENV_REGION_BYTES = 4 + # error_window_size, output_size, number_of_inputs BASE_DATA_REGION_BYTES = 3 * 4 + # not sure this is entirely necessary but keeping it for now MAX_SIM_DURATION = 10000 -# RECORDABLE_VARIABLES = "error" + # Probably better ways of doing this too, but keeping it for now RECORDABLE_VARIABLES = [ "L_count", "R_count", "error", "head_pos", "head_vel"] RECORDABLE_DTYPES = [ @@ -85,6 +88,7 @@ def get_synapse_id_by_target(self, target): # parameters expected by PyNN default_parameters = { 'error_window_size': 10, + 'output_size': 200, 'constraints': None, 'label': "ICubVorEnv", 'incoming_spike_buffer_size': None, @@ -92,6 +96,7 @@ def get_synapse_id_by_target(self, target): def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size=default_parameters['error_window_size'], + output_size=default_parameters['output_size'], constraints=default_parameters['constraints'], label=default_parameters['label'], incoming_spike_buffer_size=default_parameters[ @@ -109,6 +114,7 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, self._perfect_eye_pos = perfect_eye_pos self._perfect_eye_vel = perfect_eye_vel self._error_window_size = error_window_size + self._output_size = output_size self._number_of_inputs = len(head_pos) if self._number_of_inputs != len(head_vel): raise ConfigurationException( @@ -235,7 +241,7 @@ def generate_data_specification(self, spec, placement, machine_time_step, spec.switch_write_focus( ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.ICUB_VOR_ENV.value) spec.write_value(routing_info.get_first_key_from_pre_vertex( - vertex, constants.SPIKE_PARTITION_ID)) + vertex, constants.LIVE_POISSON_CONTROL_PARTITION_ID)) # Write recording region for score spec.comment("\nWriting icub_vor_env recording region:\n") @@ -253,6 +259,7 @@ def generate_data_specification(self, spec, placement, machine_time_step, spec.switch_write_focus( ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value) spec.write_value(self._error_window_size, data_type=DataType.UINT32) + spec.write_value(self._output_size, data_type=DataType.UINT32) spec.write_value(self._number_of_inputs, data_type=DataType.UINT32) # Write the data - Arrays must be 32-bit values, so convert data = numpy.array( diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 1f7960de..c48890d6 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -48,7 +48,12 @@ def get_recording_region_base_address(self, txrx, placement): placement, self._ICUB_VOR_ENV_REGIONS.RECORDING.value, txrx) def get_n_keys_for_partition(self, partition): - return 2 # for control IDs (CHECK: this should be 2, right?) + n_keys = 0 + # The way this has been written, there should only be one edge, but + # better to be safe than sorry + for edge in partition.edges: + n_keys += edge.post_vertex.get_n_keys_for_partition(partition) + return n_keys @overrides(AbstractHasAssociatedBinary.get_binary_file_name) def get_binary_file_name(self): From db0921096c5cbf4737b4bf5081b45a3e72533059 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 16 Nov 2020 09:15:24 +0000 Subject: [PATCH 04/54] Update icub_vor to match other vertices, switch to [-1,1] for errors --- c_code/icub_vor_env/src/icub_vor_env.c | 18 +++++++++++------- examples/icub_vor_env/icub_vor_env_test.py | 17 ++++++++++++----- examples/logic/logic_test.py | 2 +- spinn_gym/games/icub_vor_env/icub_vor_env.py | 17 ++++++++++++++++- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 12dd8fdd..0355b840 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -110,7 +110,7 @@ uint32_t simulation_ticks = 0; static inline void send_spike(int input, accum value) { // uint32_t payload = bitsk(value); -// io_printf(IO_BUF, "payload %d value %k", payload, value); +// io_printf(IO_BUF, "payload %u value %k time %u", payload, value, _time); // The rate value needs to be sent as a uint32_t, so convert and send spin1_send_mc_packet(key | (input), bitsk(value), WITH_PAYLOAD); // spin1_send_mc_packet(key | (input), value, WITH_PAYLOAD); @@ -145,8 +145,10 @@ static bool initialize(uint32_t *timer_period) io_printf(IO_BUF, "simulation time = %u\n", simulation_ticks); - // Read icub_vor region, which for now contains the information about keys on received mc packets - address_t icub_vor_env_address_region = data_specification_get_region(REGION_ICUB_VOR_ENV, address); + // Read icub_vor region, which for now contains the information + // about keys on received mc packets + address_t icub_vor_env_address_region = data_specification_get_region( + REGION_ICUB_VOR_ENV, address); key = icub_vor_env_address_region[0]; io_printf(IO_BUF, "\tKey=%08x\n", key); io_printf(IO_BUF, "\tTimer period=%d\n", *timer_period); @@ -163,7 +165,8 @@ static bool initialize(uint32_t *timer_period) } // Now get the data associated with the environment - address_t icub_vor_env_data_region = data_specification_get_region(REGION_ICUB_VOR_ENV_DATA, address); + address_t icub_vor_env_data_region = data_specification_get_region( + REGION_ICUB_VOR_ENV_DATA, address); // Ideally I guess this could be set up using a struct, but let's keep it simpler for now error_window_size = icub_vor_env_data_region[0]; @@ -243,8 +246,8 @@ void test_the_head() { // } // Here is where the error should be calculated: for now measure the error - // from the default eye position (middle = 0.5) and stationary velocity (0.0) - accum DEFAULT_EYE_POS = 0.5k; + // from the default eye position (middle = 0.0) and stationary velocity (0.0) + accum DEFAULT_EYE_POS = 0.0k; accum DEFAULT_EYE_VEL = 0.0k; // Error is relative (in both cases) as the test is done based on > or < 0.0 @@ -283,7 +286,8 @@ void test_the_head() { accum loop_to_up_value = loop_value - up_threshold; accum low_to_up_value = low_threshold - up_threshold; // threshold_calc = inter_value1 / inter_value2; - accum encoded_error_rate = max_rate - ((max_rate-min_rate) * (loop_to_up_value / low_to_up_value)); + accum encoded_error_rate = max_rate - ( + (max_rate-min_rate) * (loop_to_up_value / low_to_up_value)); if (error_value >= 0.0k) { // Antagonist is encoded_error_rate antagonist_rate = encoded_error_rate; diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 71c81c3d..25d3812c 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -1,12 +1,12 @@ import spynnaker8 as p import spinn_gym as gym -from pyNN.utility.plotting import Figure, Panel import matplotlib.pyplot as plt import numpy as np import os from spinn_front_end_common.utilities.globals_variables import get_simulator + # Examples of get functions for variables def get_error(icub_vor_env_pop, simulator): b_vertex = icub_vor_env_pop._vertex @@ -50,14 +50,17 @@ def get_head_vel(icub_vor_env_pop, simulator): # Setup p.setup(timestep=1.0) +# p.set_number_of_neurons_per_core(p.SpikeSourcePoisson, 100) # Build input SSP and output population input_size = 2 output_size = 200 input_rate = 20 -input_pop = p.Population(input_size, p.SpikeSourcePoisson(rate=input_rate)) -output_pop = p.Population(output_size, p.SpikeSourcePoisson(rate=0)) +input_pop = p.Population(input_size, p.SpikeSourcePoisson(rate=input_rate), + label='SSP_input') +output_pop = p.Population(output_size, p.SpikeSourcePoisson(rate=0), + label='SSP_output') # get head_positions and head_velocities from file (1000 samples) base_dir = "./" @@ -66,6 +69,12 @@ def get_head_vel(icub_vor_env_pop, simulator): head_vel = np.loadtxt(os.path.join( base_dir, "normalised_head_velocities_1000.csv")) +# The values in the files are [0,1] when we really want [-1,1]; obtain this +# by multiplying by 2 and subtracting 1 + +head_pos = (head_pos * 2.0) - 1.0 +head_vel = (head_vel * 2.0) - 1.0 + # perfect eye positions and velocities are exactly out of phase with head perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) perfect_eye_vel = np.concatenate((head_vel[500:], head_vel[:500])) @@ -126,7 +135,6 @@ def get_head_vel(icub_vor_env_pop, simulator): plt.subplot(5, 1, 1) plt.scatter( [i[1] for i in spikes_in_spin], [i[0] for i in spikes_in_spin], s=1) -plt.legend(loc="best") plt.xlim([0, runtime]) plt.subplot(5, 1, 2) @@ -151,7 +159,6 @@ def get_head_vel(icub_vor_env_pop, simulator): plt.subplot(5, 1, 5) plt.scatter( [i[1] for i in spikes_out_spin], [i[0] for i in spikes_out_spin], s=1) -plt.legend(loc="best") plt.xlim([0, runtime]) plt.show() diff --git a/examples/logic/logic_test.py b/examples/logic/logic_test.py index 85730e4d..735101f4 100644 --- a/examples/logic/logic_test.py +++ b/examples/logic/logic_test.py @@ -63,7 +63,7 @@ def get_scores(logic_pop, simulator): scores = get_scores(logic_pop=logic_pop, simulator=simulator) -print(scores) +print('scores:', scores) spikes_in = input_pop.get_data('spikes').segments[0].spiketrains spikes_out1 = output_pop1.get_data('spikes').segments[0].spiketrains diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index ba330231..e2fca9be 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -45,6 +45,7 @@ NUMPY_DATA_ELEMENT_TYPE = numpy.double + # ---------------------------------------------------------------------------- # ICubVorEnv # ---------------------------------------------------------------------------- @@ -163,7 +164,7 @@ def neurons(self): return self._n_neurons def get_maximum_delay_supported_in_ms(self, machine_time_step): - # ICubVorEnv has no synapses so can simulate only one time step of delay + # ICubVorEnv has no synapses so can simulate only one timestep of delay return machine_time_step / 1000.0 # ------------------------------------------------------------------------ @@ -365,5 +366,19 @@ def get_data(self, variable, n_machine_time_steps, placements, else: return output_data + def _clear_recording_region( + self, buffer_manager, placements, recording_region_id): + """ Clear a recorded data region from the buffer manager. + + :param buffer_manager: the buffer manager object + :param placements: the placements object + :param recording_region_id: the recorded region ID for clearing + :rtype: None + """ + for machine_vertex in self.machine_vertices: + placement = placements.get_placement_of_vertex(machine_vertex) + buffer_manager.clear_recorded_data( + placement.x, placement.y, placement.p, recording_region_id) + def reset_ring_buffer_shifts(self): pass From 010b44bea95dc9b25b24adfbc37348ecafddd457 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Tue, 1 Dec 2020 12:59:53 +0000 Subject: [PATCH 05/54] vor venv normalised error looks better --- c_code/icub_vor_env/src/icub_vor_env.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 12dd8fdd..5a36ad50 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -174,16 +174,16 @@ static bool initialize(uint32_t *timer_period) perfect_eye_pos = (accum *)&icub_vor_env_data_region[3 + (2 * number_of_inputs)]; perfect_eye_vel = (accum *)&icub_vor_env_data_region[3 + (3 * number_of_inputs)]; - // Print some values out to check - io_printf(IO_BUF, "error_window_size %u output_size %u\n", error_window_size, output_size); - io_printf(IO_BUF, "At 0: head pos %k, head vel %k, eye pos %k, eye vel %k\n", - head_positions[0], head_velocities[0], perfect_eye_pos[0], perfect_eye_vel[0]); - io_printf(IO_BUF, "At 250: head pos %k, head vel %k, eye pos %k, eye vel %k\n", - head_positions[250], head_velocities[250], perfect_eye_pos[250], perfect_eye_vel[250]); - io_printf(IO_BUF, "At 500: head pos %k, head vel %k, eye pos %k, eye vel %k\n", - head_positions[500], head_velocities[500], perfect_eye_pos[500], perfect_eye_vel[500]); - io_printf(IO_BUF, "At 750: head pos %k, head vel %k, eye pos %k, eye vel %k\n", - head_positions[750], head_velocities[750], perfect_eye_pos[750], perfect_eye_vel[750]); + // Print some values out to check THIS HAS BEEN CHECKED ON 1st DECEMBER 2020 +// io_printf(IO_BUF, "error_window_size %u output_size %u\n", error_window_size, output_size); +// io_printf(IO_BUF, "At 0: head pos %k, head vel %k, eye pos %k, eye vel %k\n", +// head_positions[0], head_velocities[0], perfect_eye_pos[0], perfect_eye_vel[0]); +// io_printf(IO_BUF, "At 250: head pos %k, head vel %k, eye pos %k, eye vel %k\n", +// head_positions[250], head_velocities[250], perfect_eye_pos[250], perfect_eye_vel[250]); +// io_printf(IO_BUF, "At 500: head pos %k, head vel %k, eye pos %k, eye vel %k\n", +// head_positions[500], head_velocities[500], perfect_eye_pos[500], perfect_eye_vel[500]); +// io_printf(IO_BUF, "At 750: head pos %k, head vel %k, eye pos %k, eye vel %k\n", +// head_positions[750], head_velocities[750], perfect_eye_pos[750], perfect_eye_vel[750]); // End of initialise io_printf(IO_BUF, "Initialise: completed successfully\n"); @@ -250,7 +250,7 @@ void test_the_head() { // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = head_positions[tick_in_head_loop] - DEFAULT_EYE_POS; accum error_vel = head_velocities[tick_in_head_loop] - DEFAULT_EYE_VEL; - error_value = error_pos + error_vel; + error_value = (error_pos + error_vel) * 2 - 1.0k; // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has From 781c2282c35ab83f4b3952b5562245c4abcc8333 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Tue, 1 Dec 2020 13:12:10 +0000 Subject: [PATCH 06/54] rolling back changes. head and eye norm better done in python. --- c_code/icub_vor_env/src/icub_vor_env.c | 2 +- examples/icub_vor_env/icub_vor_env_test.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index adfea1c7..695d2812 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -253,7 +253,7 @@ void test_the_head() { // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = head_positions[tick_in_head_loop] - DEFAULT_EYE_POS; accum error_vel = head_velocities[tick_in_head_loop] - DEFAULT_EYE_VEL; - error_value = (error_pos + error_vel) * 2 - 1.0k; + error_value = (error_pos + error_vel); // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 25d3812c..af5e0736 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -79,6 +79,11 @@ def get_head_vel(icub_vor_env_pop, simulator): perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) perfect_eye_vel = np.concatenate((head_vel[500:], head_vel[:500])) +# Report 4 points: +for i in [0, 250, 500, 750]: + print("At {}: head pos {:4.6f}, head vel {:4.6f}, eye pos {:4.6f}, eye vel {:4.6f}".format( + i, head_pos[i], head_vel[i], perfect_eye_pos[i], perfect_eye_vel[i])) + # build ICubVorEnv model pop error_window_size = 10 icub_vor_env_model = gym.ICubVorEnv( From d6ae3703e3ec731d4e49c6ab6dd0bb84bbc6dfdc Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 2 Dec 2020 09:08:42 +0000 Subject: [PATCH 07/54] Update to remove compiler warnings for old-style function definitions --- c_code/icub_vor_env/src/icub_vor_env.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 695d2812..e4090c6d 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -119,7 +119,7 @@ static inline void send_spike(int input, accum value) } // Required if using auto-pause and resume -void resume_callback() { +void resume_callback(void) { recording_reset(); } @@ -227,7 +227,7 @@ void mc_packet_received_callback(uint keyx, uint payload) } // Test the counters for the head after this loop -void test_the_head() { +void test_the_head(void) { // Here I am testing this is working by sending a spike out to // wherever this vertex connects to, depending on which counter is higher. // if (spike_counters[0] > spike_counters[1]) { From 16be544bde1b94422b9b73186ca9797113c8c3cf Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Wed, 2 Dec 2020 09:15:07 +0000 Subject: [PATCH 08/54] added a comment to clarify what a check was doing --- c_code/icub_vor_env/src/icub_vor_env.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 695d2812..3b7af757 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -207,7 +207,7 @@ void mc_packet_received_callback(uint keyx, uint payload) // io_printf(IO_BUF, "key = %x\n", keyx); // io_printf(IO_BUF, "payload = %x\n", payload); uint32_t compare; - compare = keyx & 0x1; + compare = keyx & 0x1; // This is an odd and even check. // If no payload has been set, make sure the loop will run if (payload == 0) { payload = 1; } From 5c1a94794e134f0b45d09bdcd0a233dc9bd19d77 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Thu, 3 Dec 2020 09:23:17 +0000 Subject: [PATCH 09/54] added eye twist movement --- c_code/icub_vor_env/src/icub_vor_env.c | 64 ++++++++------------------ 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 62cfadb3..856ddfc1 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -19,6 +19,7 @@ // Common includes #include +#include // Front end common includes #include @@ -66,6 +67,10 @@ static uint32_t _time; //! Should simulation run for ever? 0 if not static uint32_t infinite_run; +static accum pos_to_vel = 7.957733154296875k; // This is 20 SMALLER larger than it should be! +//159.15493774414062k; +// + //! Parameters set from Python code go here // - error_window_size // - number_of_inputs @@ -79,9 +84,8 @@ accum *head_velocities; accum *perfect_eye_pos; accum *perfect_eye_vel; -//accum *eye_pos; -//accum *eye_vel; -//accum *encoded_error_rates; +accum current_eye_pos; +accum current_eye_vel; //! Global error value accum error_value = 0.0k; @@ -109,13 +113,8 @@ uint32_t simulation_ticks = 0; // related to the counts at the Left and Right atoms static inline void send_spike(int input, accum value) { -// uint32_t payload = bitsk(value); -// io_printf(IO_BUF, "payload %u value %k time %u", payload, value, _time); // The rate value needs to be sent as a uint32_t, so convert and send spin1_send_mc_packet(key | (input), bitsk(value), WITH_PAYLOAD); -// spin1_send_mc_packet(key | (input), value, WITH_PAYLOAD); -// spin1_send_mc_packet(key | (input), 0, NO_PAYLOAD); -// io_printf(IO_BUF, "sending spike to input %d\n", input); } // Required if using auto-pause and resume @@ -176,18 +175,6 @@ static bool initialize(uint32_t *timer_period) head_velocities = (accum *)&icub_vor_env_data_region[3 + number_of_inputs]; perfect_eye_pos = (accum *)&icub_vor_env_data_region[3 + (2 * number_of_inputs)]; perfect_eye_vel = (accum *)&icub_vor_env_data_region[3 + (3 * number_of_inputs)]; - - // Print some values out to check THIS HAS BEEN CHECKED ON 1st DECEMBER 2020 -// io_printf(IO_BUF, "error_window_size %u output_size %u\n", error_window_size, output_size); -// io_printf(IO_BUF, "At 0: head pos %k, head vel %k, eye pos %k, eye vel %k\n", -// head_positions[0], head_velocities[0], perfect_eye_pos[0], perfect_eye_vel[0]); -// io_printf(IO_BUF, "At 250: head pos %k, head vel %k, eye pos %k, eye vel %k\n", -// head_positions[250], head_velocities[250], perfect_eye_pos[250], perfect_eye_vel[250]); -// io_printf(IO_BUF, "At 500: head pos %k, head vel %k, eye pos %k, eye vel %k\n", -// head_positions[500], head_velocities[500], perfect_eye_pos[500], perfect_eye_vel[500]); -// io_printf(IO_BUF, "At 750: head pos %k, head vel %k, eye pos %k, eye vel %k\n", -// head_positions[750], head_velocities[750], perfect_eye_pos[750], perfect_eye_vel[750]); - // End of initialise io_printf(IO_BUF, "Initialise: completed successfully\n"); @@ -203,9 +190,6 @@ void update_count(uint32_t index) { // when a packet is received, update the error void mc_packet_received_callback(uint keyx, uint payload) { -// io_printf(IO_BUF, "mc_packet_received_callback"); -// io_printf(IO_BUF, "key = %x\n", keyx); -// io_printf(IO_BUF, "payload = %x\n", payload); uint32_t compare; compare = keyx & 0x1; // This is an odd and even check. @@ -230,29 +214,18 @@ void mc_packet_received_callback(uint keyx, uint payload) void test_the_head(void) { // Here I am testing this is working by sending a spike out to // wherever this vertex connects to, depending on which counter is higher. -// if (spike_counters[0] > spike_counters[1]) { -//// io_printf(IO_BUF, "spike_counters[0] %u > spike_counters[1] %u \n", -//// spike_counters[0], spike_counters[1]); -// send_spike(0, 0); -// // L > R so "move eye left" (blank for now while we decide how to do this) -// -// } -// else { -//// io_printf(IO_BUF, "spike_counters[0] %u <= spike_counters[1] %u \n", -//// spike_counters[0], spike_counters[1]); -// send_spike(1, 0); -// // L <= R so "move eye right" (blank for now while we decide how to do this) -// -// } - - // Here is where the error should be calculated: for now measure the error - // from the default eye position (middle = 0.0) and stationary velocity (0.0) - accum DEFAULT_EYE_POS = 0.0k; - accum DEFAULT_EYE_VEL = 0.0k; + accum pos_diff=0.0k, vel_diff=0.0k; + int32_t counter_diff = (spike_counters[0] - spike_counters[1]); + pos_diff = kbits(counter_diff); + vel_diff = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); + current_eye_pos = current_eye_pos + kbits(counter_diff); + current_eye_vel = vel_diff; + io_printf(IO_BUF, "pos_diff %k, current_eye_pos %k, vel_diff %k, current_eye_vel %k\n", + pos_diff, current_eye_pos, vel_diff, current_eye_vel); // Error is relative (in both cases) as the test is done based on > or < 0.0 - accum error_pos = head_positions[tick_in_head_loop] - DEFAULT_EYE_POS; - accum error_vel = head_velocities[tick_in_head_loop] - DEFAULT_EYE_VEL; + accum error_pos = head_positions[tick_in_head_loop] - current_eye_pos; + accum error_vel = head_velocities[tick_in_head_loop] - current_eye_vel; error_value = (error_pos + error_vel); // The above could easily be replaced by a comparison to the perfect eye @@ -395,6 +368,9 @@ void c_main(void) _time = UINT32_MAX; + current_eye_pos = 0.0k; + current_eye_vel = 0.0k; + simulation_run(); } From 64c5e61efec8bdad35c2d62913dc3d6911beb54f Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 4 Dec 2020 12:32:07 +0000 Subject: [PATCH 10/54] eye position works well, eye velocity is broken completely --- c_code/icub_vor_env/src/icub_vor_env.c | 34 +++++++++++++++----------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 856ddfc1..278f73a7 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -67,9 +67,11 @@ static uint32_t _time; //! Should simulation run for ever? 0 if not static uint32_t infinite_run; -static accum pos_to_vel = 7.957733154296875k; // This is 20 SMALLER larger than it should be! +static accum pos_to_vel = 159.15493774414062k; +//7.957733154296875k; // This is 20 SMALLER larger than it should be! //159.15493774414062k; -// +//0.7957763671875k; +//15.915496826171875k; //! Parameters set from Python code go here // - error_window_size @@ -173,8 +175,8 @@ static bool initialize(uint32_t *timer_period) number_of_inputs = icub_vor_env_data_region[2]; head_positions = (accum *)&icub_vor_env_data_region[3]; head_velocities = (accum *)&icub_vor_env_data_region[3 + number_of_inputs]; - perfect_eye_pos = (accum *)&icub_vor_env_data_region[3 + (2 * number_of_inputs)]; - perfect_eye_vel = (accum *)&icub_vor_env_data_region[3 + (3 * number_of_inputs)]; + perfect_eye_vel = (accum *)&icub_vor_env_data_region[3 + (2 * number_of_inputs)]; + perfect_eye_pos = (accum *)&icub_vor_env_data_region[3 + (3 * number_of_inputs)]; // End of initialise io_printf(IO_BUF, "Initialise: completed successfully\n"); @@ -214,19 +216,21 @@ void mc_packet_received_callback(uint keyx, uint payload) void test_the_head(void) { // Here I am testing this is working by sending a spike out to // wherever this vertex connects to, depending on which counter is higher. - accum pos_diff=0.0k, vel_diff=0.0k; + accum pos_diff, vel_diff; int32_t counter_diff = (spike_counters[0] - spike_counters[1]); pos_diff = kbits(counter_diff); - vel_diff = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); + vel_diff = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel)/100.0k; current_eye_pos = current_eye_pos + kbits(counter_diff); - current_eye_vel = vel_diff; - io_printf(IO_BUF, "pos_diff %k, current_eye_pos %k, vel_diff %k, current_eye_vel %k\n", - pos_diff, current_eye_pos, vel_diff, current_eye_vel); + current_eye_vel = current_eye_vel - vel_diff; // Error is relative (in both cases) as the test is done based on > or < 0.0 - accum error_pos = head_positions[tick_in_head_loop] - current_eye_pos; - accum error_vel = head_velocities[tick_in_head_loop] - current_eye_vel; + accum error_pos = perfect_eye_pos[tick_in_head_loop] - current_eye_pos; + accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; error_value = (error_pos + error_vel); +// error_value = (error_pos); + + io_printf(IO_BUF, "counter_diff %d, pos_diff %k, current_eye_vel %k, perfect_eye_vel %k, error_vel %k\n", + counter_diff, pos_diff, current_eye_vel, perfect_eye_vel[tick_in_head_loop], error_vel); // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has @@ -323,8 +327,10 @@ void timer_callback(uint unused, uint dummy) recording_record(0, &spike_counters[0], 4); recording_record(1, &spike_counters[1], 4); recording_record(2, &error_value, 4); - recording_record(3, &head_positions[tick_in_head_loop], 4); - recording_record(4, &head_velocities[tick_in_head_loop], 4); + recording_record(3, ¤t_eye_pos, 4); + recording_record(4, ¤t_eye_vel, 4); +// recording_record(3, &head_positions[tick_in_head_loop], 4); +// recording_record(4, &head_velocities[tick_in_head_loop], 4); // Reset ticks in error window tick_in_error_window = 0; @@ -369,7 +375,7 @@ void c_main(void) _time = UINT32_MAX; current_eye_pos = 0.0k; - current_eye_vel = 0.0k; + current_eye_vel = 1.0k; simulation_run(); From 40694e156e5c8138f1c3dc739cfd98a6c5fd6e79 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 4 Dec 2020 14:31:13 +0000 Subject: [PATCH 11/54] eye velocity now matches as well. I wonder if the error can be brought down more. --- c_code/icub_vor_env/src/icub_vor_env.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 278f73a7..a26e2e27 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -67,11 +67,7 @@ static uint32_t _time; //! Should simulation run for ever? 0 if not static uint32_t infinite_run; -static accum pos_to_vel = 159.15493774414062k; -//7.957733154296875k; // This is 20 SMALLER larger than it should be! -//159.15493774414062k; -//0.7957763671875k; -//15.915496826171875k; +static accum pos_to_vel = 15.915493774414062k; // 1/ (0.001 * 2 * np.pi * 10) //! Parameters set from Python code go here // - error_window_size @@ -219,9 +215,10 @@ void test_the_head(void) { accum pos_diff, vel_diff; int32_t counter_diff = (spike_counters[0] - spike_counters[1]); pos_diff = kbits(counter_diff); - vel_diff = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel)/100.0k; + vel_diff = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); current_eye_pos = current_eye_pos + kbits(counter_diff); - current_eye_vel = current_eye_vel - vel_diff; +// current_eye_vel = current_eye_vel - vel_diff; + current_eye_vel = vel_diff; // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = perfect_eye_pos[tick_in_head_loop] - current_eye_pos; From a0b58a208910655d22cb3453bb1ae30244718829 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 7 Dec 2020 09:28:50 +0000 Subject: [PATCH 12/54] added some comments and a gain factor --- c_code/icub_vor_env/src/icub_vor_env.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index a26e2e27..1a8661ea 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -68,6 +68,7 @@ static uint32_t _time; static uint32_t infinite_run; static accum pos_to_vel = 15.915493774414062k; // 1/ (0.001 * 2 * np.pi * 10) +static accum gain = 20.0k; //! Parameters set from Python code go here // - error_window_size @@ -212,19 +213,19 @@ void mc_packet_received_callback(uint keyx, uint payload) void test_the_head(void) { // Here I am testing this is working by sending a spike out to // wherever this vertex connects to, depending on which counter is higher. - accum pos_diff, vel_diff; + accum pos_diff; + // Compute the integer difference in the number of spikes between L (agonist) and R (antagonist) int32_t counter_diff = (spike_counters[0] - spike_counters[1]); - pos_diff = kbits(counter_diff); - vel_diff = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); - current_eye_pos = current_eye_pos + kbits(counter_diff); -// current_eye_vel = current_eye_vel - vel_diff; - current_eye_vel = vel_diff; + // Compute the contribution to position (1 bit set in counter_diff = 2**-15) + pos_diff = kbits(counter_diff) * gain; + current_eye_pos = current_eye_pos + pos_diff; + // Compute the current velocity + current_eye_vel = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = perfect_eye_pos[tick_in_head_loop] - current_eye_pos; accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; - error_value = (error_pos + error_vel); -// error_value = (error_pos); + error_value = (error_pos + error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? io_printf(IO_BUF, "counter_diff %d, pos_diff %k, current_eye_vel %k, perfect_eye_vel %k, error_vel %k\n", counter_diff, pos_diff, current_eye_vel, perfect_eye_vel[tick_in_head_loop], error_vel); From 8f764fd19f90516055c6c796f25c908b3c845c7e Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 7 Dec 2020 14:39:53 +0000 Subject: [PATCH 13/54] retrieving eye positions, not head pos --- spinn_gym/games/icub_vor_env/icub_vor_env.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index e2fca9be..37c9d5fe 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -81,7 +81,7 @@ def get_synapse_id_by_target(self, target): MAX_SIM_DURATION = 10000 # Probably better ways of doing this too, but keeping it for now RECORDABLE_VARIABLES = [ - "L_count", "R_count", "error", "head_pos", "head_vel"] + "l_count", "r_count", "error", "eye_pos", "eye_vel"] RECORDABLE_DTYPES = [ DataType.UINT32, DataType.UINT32, DataType.S1615, DataType.S1615, DataType.S1615] From 71a0f139c4d3b0058b6180be347c48cecf3bf586 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Tue, 8 Dec 2020 09:09:43 +0000 Subject: [PATCH 14/54] now writing gain and pos_to_vel from python --- c_code/icub_vor_env/src/icub_vor_env.c | 20 ++++++++++++-------- spinn_gym/games/icub_vor_env/icub_vor_env.py | 18 +++++++++++++++--- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 1a8661ea..083ad6aa 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -67,8 +67,6 @@ static uint32_t _time; //! Should simulation run for ever? 0 if not static uint32_t infinite_run; -static accum pos_to_vel = 15.915493774414062k; // 1/ (0.001 * 2 * np.pi * 10) -static accum gain = 20.0k; //! Parameters set from Python code go here // - error_window_size @@ -83,12 +81,16 @@ accum *head_velocities; accum *perfect_eye_pos; accum *perfect_eye_vel; -accum current_eye_pos; -accum current_eye_vel; +accum pos_to_vel; // 1/ (0.001 * 2 * np.pi * 10) +accum gain; //! Global error value accum error_value = 0.0k; +//! Global eye position and velocity +accum current_eye_pos; +accum current_eye_vel; + //! count left and right spikes uint32_t spike_counters[2] = {0}; @@ -170,10 +172,12 @@ static bool initialize(uint32_t *timer_period) error_window_size = icub_vor_env_data_region[0]; output_size = icub_vor_env_data_region[1]; number_of_inputs = icub_vor_env_data_region[2]; - head_positions = (accum *)&icub_vor_env_data_region[3]; - head_velocities = (accum *)&icub_vor_env_data_region[3 + number_of_inputs]; - perfect_eye_vel = (accum *)&icub_vor_env_data_region[3 + (2 * number_of_inputs)]; - perfect_eye_pos = (accum *)&icub_vor_env_data_region[3 + (3 * number_of_inputs)]; + gain = kbits(icub_vor_env_data_region[3]); + pos_to_vel = kbits(icub_vor_env_data_region[4]); + head_positions = (accum *)&icub_vor_env_data_region[5]; + head_velocities = (accum *)&icub_vor_env_data_region[5 + number_of_inputs]; + perfect_eye_vel = (accum *)&icub_vor_env_data_region[5 + (2 * number_of_inputs)]; + perfect_eye_pos = (accum *)&icub_vor_env_data_region[5 + (3 * number_of_inputs)]; // End of initialise io_printf(IO_BUF, "Initialise: completed successfully\n"); diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 37c9d5fe..3cd9f463 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -76,7 +76,7 @@ def get_synapse_id_by_target(self, target): # key value ICUB_VOR_ENV_REGION_BYTES = 4 # error_window_size, output_size, number_of_inputs - BASE_DATA_REGION_BYTES = 3 * 4 + BASE_DATA_REGION_BYTES = 5 * 4 # not sure this is entirely necessary but keeping it for now MAX_SIM_DURATION = 10000 # Probably better ways of doing this too, but keeping it for now @@ -89,6 +89,8 @@ def get_synapse_id_by_target(self, target): # parameters expected by PyNN default_parameters = { 'error_window_size': 10, + 'gain': 20, + 'pos_to_vel': 1 / (0.001 * 2 * numpy.pi * 10), 'output_size': 200, 'constraints': None, 'label': "ICubVorEnv", @@ -98,6 +100,8 @@ def get_synapse_id_by_target(self, target): def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size=default_parameters['error_window_size'], output_size=default_parameters['output_size'], + gain=default_parameters['gain'], + pos_to_vel=default_parameters['pos_to_vel'], constraints=default_parameters['constraints'], label=default_parameters['label'], incoming_spike_buffer_size=default_parameters[ @@ -116,6 +120,8 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, self._perfect_eye_vel = perfect_eye_vel self._error_window_size = error_window_size self._output_size = output_size + self._gain = gain + self._pos_to_vel = pos_to_vel self._number_of_inputs = len(head_pos) if self._number_of_inputs != len(head_vel): raise ConfigurationException( @@ -217,7 +223,7 @@ def generate_data_specification(self, spec, placement, machine_time_step, label='setup') spec.reserve_memory_region( region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS - .ICUB_VOR_ENV.value, + .ICUB_VOR_ENV.value, size=self.ICUB_VOR_ENV_REGION_BYTES, label='ICubVorEnvParams') # reserve recording region spec.reserve_memory_region( @@ -226,7 +232,7 @@ def generate_data_specification(self, spec, placement, machine_time_step, len(self.RECORDABLE_VARIABLES))) spec.reserve_memory_region( region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value, - size=self.BASE_DATA_REGION_BYTES+(self._number_of_inputs*16), + size=self.BASE_DATA_REGION_BYTES + (self._number_of_inputs * 16), label='ICubVorEnvArms') # Write setup region @@ -262,6 +268,8 @@ def generate_data_specification(self, spec, placement, machine_time_step, spec.write_value(self._error_window_size, data_type=DataType.UINT32) spec.write_value(self._output_size, data_type=DataType.UINT32) spec.write_value(self._number_of_inputs, data_type=DataType.UINT32) + spec.write_value(self.__round_to_nearest_accum(self._gain), data_type=DataType.S1615) + spec.write_value(self.__round_to_nearest_accum(self._pos_to_vel), data_type=DataType.S1615) # Write the data - Arrays must be 32-bit values, so convert data = numpy.array( [int(x * float_scale) for x in self._head_pos], @@ -283,6 +291,10 @@ def generate_data_specification(self, spec, placement, machine_time_step, # End-of-Spec: spec.end_specification() + def __round_to_nearest_accum(self, x): + eps = 2. ** (-15) + x_approx = numpy.floor((x / eps) + 0.5) * eps + return x_approx # ------------------------------------------------------------------------ # AbstractProvidesOutgoingPartitionConstraints overrides # ------------------------------------------------------------------------ From c39a69dcb117e17a14e005e0e003572c2809f150 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Wed, 16 Dec 2020 09:38:07 +0000 Subject: [PATCH 15/54] head position now capped between -1 and 1 --- c_code/icub_vor_env/src/icub_vor_env.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 083ad6aa..0d89d8cc 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -222,7 +222,17 @@ void test_the_head(void) { int32_t counter_diff = (spike_counters[0] - spike_counters[1]); // Compute the contribution to position (1 bit set in counter_diff = 2**-15) pos_diff = kbits(counter_diff) * gain; + accum previous_eye_pos = current_eye_pos; current_eye_pos = current_eye_pos + pos_diff; + // Check bounds + if (current_eye_pos < -1.0k) { + current_eye_pos = -1.0k; + } + else if (current_eye_pos > 1.0k) { + current_eye_pos = 1.0k; + } + pos_diff = current_eye_pos - previous_eye_pos; + // Compute the current velocity current_eye_vel = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); From 89c2c5a1aee08027a59da1b4d0a6f05d88d35055 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 18 Dec 2020 09:16:23 +0000 Subject: [PATCH 16/54] not using head arrays anymore and corrected reading order for eye pos and vel --- c_code/icub_vor_env/src/icub_vor_env.c | 22 +++++++++++--------- spinn_gym/games/icub_vor_env/icub_vor_env.py | 8 ------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 0d89d8cc..f4b1af21 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -71,13 +71,10 @@ static uint32_t infinite_run; //! Parameters set from Python code go here // - error_window_size // - number_of_inputs -// - head position, head velocity arrays -// - perfect eye position, perfect eye velocity arrays (unused at present) +// - perfect eye position, perfect eye velocity arrays uint32_t error_window_size; uint32_t output_size; uint32_t number_of_inputs; -accum *head_positions; -accum *head_velocities; accum *perfect_eye_pos; accum *perfect_eye_vel; @@ -174,10 +171,10 @@ static bool initialize(uint32_t *timer_period) number_of_inputs = icub_vor_env_data_region[2]; gain = kbits(icub_vor_env_data_region[3]); pos_to_vel = kbits(icub_vor_env_data_region[4]); - head_positions = (accum *)&icub_vor_env_data_region[5]; - head_velocities = (accum *)&icub_vor_env_data_region[5 + number_of_inputs]; - perfect_eye_vel = (accum *)&icub_vor_env_data_region[5 + (2 * number_of_inputs)]; - perfect_eye_pos = (accum *)&icub_vor_env_data_region[5 + (3 * number_of_inputs)]; + perfect_eye_pos = (accum *)&icub_vor_env_data_region[5]; + perfect_eye_vel = (accum *)&icub_vor_env_data_region[5 + number_of_inputs]; +// perfect_eye_vel = (accum *)&icub_vor_env_data_region[5 + (2 * number_of_inputs)]; +// perfect_eye_pos = (accum *)&icub_vor_env_data_region[5 + (3 * number_of_inputs)]; // End of initialise io_printf(IO_BUF, "Initialise: completed successfully\n"); @@ -219,6 +216,13 @@ void test_the_head(void) { // wherever this vertex connects to, depending on which counter is higher. accum pos_diff; // Compute the integer difference in the number of spikes between L (agonist) and R (antagonist) + // WTA experiments +// int32_t counter_diff; +// if (spike_counters[0] > spike_counters[1]) +// counter_diff = spike_counters[0]; +// else +// counter_diff = -spike_counters[1]; + int32_t counter_diff = (spike_counters[0] - spike_counters[1]); // Compute the contribution to position (1 bit set in counter_diff = 2**-15) pos_diff = kbits(counter_diff) * gain; @@ -341,8 +345,6 @@ void timer_callback(uint unused, uint dummy) recording_record(2, &error_value, 4); recording_record(3, ¤t_eye_pos, 4); recording_record(4, ¤t_eye_vel, 4); -// recording_record(3, &head_positions[tick_in_head_loop], 4); -// recording_record(4, &head_velocities[tick_in_head_loop], 4); // Reset ticks in error window tick_in_error_window = 0; diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 3cd9f463..6afc23cf 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -271,14 +271,6 @@ def generate_data_specification(self, spec, placement, machine_time_step, spec.write_value(self.__round_to_nearest_accum(self._gain), data_type=DataType.S1615) spec.write_value(self.__round_to_nearest_accum(self._pos_to_vel), data_type=DataType.S1615) # Write the data - Arrays must be 32-bit values, so convert - data = numpy.array( - [int(x * float_scale) for x in self._head_pos], - dtype=numpy.uint32) - spec.write_array(data.view(numpy.uint32)) - data = numpy.array( - [int(x * float_scale) for x in self._head_vel], - dtype=numpy.uint32) - spec.write_array(data.view(numpy.uint32)) data = numpy.array( [int(x * float_scale) for x in self._perfect_eye_pos], dtype=numpy.uint32) From 8b59f6c970600a95ecae6528a9d494a10f814436 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 18 Dec 2020 11:15:39 +0000 Subject: [PATCH 17/54] can now toggle between a WTA or a difference based decision --- c_code/icub_vor_env/src/icub_vor_env.c | 27 ++++++++++---------- spinn_gym/games/icub_vor_env/icub_vor_env.py | 8 ++++-- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index f4b1af21..2dd263a9 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -91,6 +91,9 @@ accum current_eye_vel; //! count left and right spikes uint32_t spike_counters[2] = {0}; +//! wta decision or difference in L/R +bool wta_decision; + //! The upper bits of the key value that model should transmit with static uint32_t key; @@ -171,10 +174,9 @@ static bool initialize(uint32_t *timer_period) number_of_inputs = icub_vor_env_data_region[2]; gain = kbits(icub_vor_env_data_region[3]); pos_to_vel = kbits(icub_vor_env_data_region[4]); - perfect_eye_pos = (accum *)&icub_vor_env_data_region[5]; - perfect_eye_vel = (accum *)&icub_vor_env_data_region[5 + number_of_inputs]; -// perfect_eye_vel = (accum *)&icub_vor_env_data_region[5 + (2 * number_of_inputs)]; -// perfect_eye_pos = (accum *)&icub_vor_env_data_region[5 + (3 * number_of_inputs)]; + wta_decision = (bool)(icub_vor_env_data_region[6]); + perfect_eye_pos = (accum *)&icub_vor_env_data_region[6]; + perfect_eye_vel = (accum *)&icub_vor_env_data_region[6 + number_of_inputs]; // End of initialise io_printf(IO_BUF, "Initialise: completed successfully\n"); @@ -217,13 +219,15 @@ void test_the_head(void) { accum pos_diff; // Compute the integer difference in the number of spikes between L (agonist) and R (antagonist) // WTA experiments -// int32_t counter_diff; -// if (spike_counters[0] > spike_counters[1]) -// counter_diff = spike_counters[0]; -// else -// counter_diff = -spike_counters[1]; + int32_t counter_diff; + + if (wta_decision) { + counter_diff = spike_counters[0] > spike_counters[1] ? spike_counters[0] : -spike_counters[1]; + } + else { + counter_diff = (spike_counters[0] - spike_counters[1]); + } - int32_t counter_diff = (spike_counters[0] - spike_counters[1]); // Compute the contribution to position (1 bit set in counter_diff = 2**-15) pos_diff = kbits(counter_diff) * gain; accum previous_eye_pos = current_eye_pos; @@ -245,9 +249,6 @@ void test_the_head(void) { accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; error_value = (error_pos + error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? - io_printf(IO_BUF, "counter_diff %d, pos_diff %k, current_eye_vel %k, perfect_eye_vel %k, error_vel %k\n", - counter_diff, pos_diff, current_eye_vel, perfect_eye_vel[tick_in_head_loop], error_vel); - // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has // been worked out how the spike counters at L and R translate to head/eye movement diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 6afc23cf..98bd197e 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -75,8 +75,8 @@ def get_synapse_id_by_target(self, target): # key value ICUB_VOR_ENV_REGION_BYTES = 4 - # error_window_size, output_size, number_of_inputs - BASE_DATA_REGION_BYTES = 5 * 4 + # error_window_size, output_size, number_of_inputs, gain, pos_to_vel and wta_decision + BASE_DATA_REGION_BYTES = 6 * 4 # not sure this is entirely necessary but keeping it for now MAX_SIM_DURATION = 10000 # Probably better ways of doing this too, but keeping it for now @@ -91,6 +91,7 @@ def get_synapse_id_by_target(self, target): 'error_window_size': 10, 'gain': 20, 'pos_to_vel': 1 / (0.001 * 2 * numpy.pi * 10), + 'wta_decision': False, 'output_size': 200, 'constraints': None, 'label': "ICubVorEnv", @@ -102,6 +103,7 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, output_size=default_parameters['output_size'], gain=default_parameters['gain'], pos_to_vel=default_parameters['pos_to_vel'], + wta_decision=default_parameters['wta_decision'], constraints=default_parameters['constraints'], label=default_parameters['label'], incoming_spike_buffer_size=default_parameters[ @@ -122,6 +124,7 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, self._output_size = output_size self._gain = gain self._pos_to_vel = pos_to_vel + self._wta_decision = wta_decision self._number_of_inputs = len(head_pos) if self._number_of_inputs != len(head_vel): raise ConfigurationException( @@ -270,6 +273,7 @@ def generate_data_specification(self, spec, placement, machine_time_step, spec.write_value(self._number_of_inputs, data_type=DataType.UINT32) spec.write_value(self.__round_to_nearest_accum(self._gain), data_type=DataType.S1615) spec.write_value(self.__round_to_nearest_accum(self._pos_to_vel), data_type=DataType.S1615) + spec.write_value(int(self._wta_decision), data_type=DataType.UINT32) # Write the data - Arrays must be 32-bit values, so convert data = numpy.array( [int(x * float_scale) for x in self._perfect_eye_pos], From 8bbf482edf5a7f35eed43bc225897220034ced18 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 18 Dec 2020 11:55:02 +0000 Subject: [PATCH 18/54] added ability to set min and max error rates --- c_code/icub_vor_env/src/icub_vor_env.c | 16 +++++---- spinn_gym/games/icub_vor_env/icub_vor_env.py | 35 +++++++++++++++++--- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 2dd263a9..f0e0e133 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -94,6 +94,11 @@ uint32_t spike_counters[2] = {0}; //! wta decision or difference in L/R bool wta_decision; + +//! Encode the error into a series of rates which are then sent on +accum min_rate = 2.0k; +accum max_rate = 20.0k; + //! The upper bits of the key value that model should transmit with static uint32_t key; @@ -174,9 +179,11 @@ static bool initialize(uint32_t *timer_period) number_of_inputs = icub_vor_env_data_region[2]; gain = kbits(icub_vor_env_data_region[3]); pos_to_vel = kbits(icub_vor_env_data_region[4]); - wta_decision = (bool)(icub_vor_env_data_region[6]); - perfect_eye_pos = (accum *)&icub_vor_env_data_region[6]; - perfect_eye_vel = (accum *)&icub_vor_env_data_region[6 + number_of_inputs]; + wta_decision = (bool)(icub_vor_env_data_region[5]); + min_rate = kbits(icub_vor_env_data_region[6]); + max_rate = kbits(icub_vor_env_data_region[7]); + perfect_eye_pos = (accum *)&icub_vor_env_data_region[8]; + perfect_eye_vel = (accum *)&icub_vor_env_data_region[8 + number_of_inputs]; // End of initialise io_printf(IO_BUF, "Initialise: completed successfully\n"); @@ -253,9 +260,6 @@ void test_the_head(void) { // position and velocity at the current value of tick_in_head_loop, once it has // been worked out how the spike counters at L and R translate to head/eye movement - // Encode the error into a series of rates which are then sent on - accum min_rate = 2.0k; - accum max_rate = 20.0k; accum mid_neuron = (accum) (output_size) * 0.5k; accum low_threshold = absk(error_value) * mid_neuron; diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 98bd197e..56cd5670 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -75,8 +75,9 @@ def get_synapse_id_by_target(self, target): # key value ICUB_VOR_ENV_REGION_BYTES = 4 - # error_window_size, output_size, number_of_inputs, gain, pos_to_vel and wta_decision - BASE_DATA_REGION_BYTES = 6 * 4 + # error_window_size, output_size, number_of_inputs, gain, pos_to_vel, wta_decision + # low_error_rate and high_error_rate + BASE_DATA_REGION_BYTES = 8 * 4 # not sure this is entirely necessary but keeping it for now MAX_SIM_DURATION = 10000 # Probably better ways of doing this too, but keeping it for now @@ -89,10 +90,12 @@ def get_synapse_id_by_target(self, target): # parameters expected by PyNN default_parameters = { 'error_window_size': 10, - 'gain': 20, - 'pos_to_vel': 1 / (0.001 * 2 * numpy.pi * 10), + 'gain': 20, # boosts the effect of individual spikes + 'pos_to_vel': 1 / (0.001 * 2 * numpy.pi * 10), # magic multiplier to convert movement delta to speed 'wta_decision': False, - 'output_size': 200, + 'low_error_rate': 2, # Hz + 'high_error_rate': 20, # Hz + 'output_size': 200, # neurons encoding error via climbing fibres 'constraints': None, 'label': "ICubVorEnv", 'incoming_spike_buffer_size': None, @@ -104,11 +107,29 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, gain=default_parameters['gain'], pos_to_vel=default_parameters['pos_to_vel'], wta_decision=default_parameters['wta_decision'], + low_error_rate=default_parameters['low_error_rate'], + high_error_rate=default_parameters['high_error_rate'], constraints=default_parameters['constraints'], label=default_parameters['label'], incoming_spike_buffer_size=default_parameters[ 'incoming_spike_buffer_size'], simulation_duration_ms=default_parameters['duration']): + """ + + :param head_pos: array of head positions + :param head_vel: array of head velocities + :param perfect_eye_pos: array of ideal eye positions to produce the VOR + :param perfect_eye_vel: array of ideal eye velocities to produce the VOR + :param error_window_size: how often the environment changes + :param output_size: numbers of neurons encoding the error transmitted via combing fibres + :param gain: boosts the effect of individual spikes + :param pos_to_vel: magic multiplier to convert movement delta to speed + :param wta_decision: whether eye movement takes into account the difference in number of spikes between L / R + :param constraints: usual sPyNNaker constraints + :param label: name of the population + :param incoming_spike_buffer_size: + :param simulation_duration_ms: maximum simulation duration for this application vertex + """ # **NOTE** n_neurons currently ignored - width and height will be # specified as additional parameters, forcing their product to be # duplicated in n_neurons seems pointless @@ -125,6 +146,8 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, self._gain = gain self._pos_to_vel = pos_to_vel self._wta_decision = wta_decision + self._low_error_rate = low_error_rate + self._high_error_rate = high_error_rate self._number_of_inputs = len(head_pos) if self._number_of_inputs != len(head_vel): raise ConfigurationException( @@ -274,6 +297,8 @@ def generate_data_specification(self, spec, placement, machine_time_step, spec.write_value(self.__round_to_nearest_accum(self._gain), data_type=DataType.S1615) spec.write_value(self.__round_to_nearest_accum(self._pos_to_vel), data_type=DataType.S1615) spec.write_value(int(self._wta_decision), data_type=DataType.UINT32) + spec.write_value(self.__round_to_nearest_accum(self._low_error_rate), data_type=DataType.S1615) + spec.write_value(self.__round_to_nearest_accum(self._high_error_rate), data_type=DataType.S1615) # Write the data - Arrays must be 32-bit values, so convert data = numpy.array( [int(x * float_scale) for x in self._perfect_eye_pos], From 112543a4d10b7a6daa982e74f2bf02cf5abe0d7f Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 18 Dec 2020 12:07:37 +0000 Subject: [PATCH 19/54] fixing len checks to eye positions rather than the heads --- spinn_gym/games/icub_vor_env/icub_vor_env.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 56cd5670..767c7004 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -148,12 +148,12 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, self._wta_decision = wta_decision self._low_error_rate = low_error_rate self._high_error_rate = high_error_rate - self._number_of_inputs = len(head_pos) - if self._number_of_inputs != len(head_vel): + self._number_of_inputs = len(perfect_eye_pos) + if self._number_of_inputs != len(perfect_eye_vel): raise ConfigurationException( - "The length of head_positions {} is not the same as the " - "length of head_velocities {}".format( - self._number_of_inputs, len(head_vel))) + "The length of perfect_eye_pos {} is not the same as the " + "length of perfect_eye_vel {}".format( + self._number_of_inputs, len(perfect_eye_vel))) # n_neurons is the number of atoms in the network, which in this # case only needs to be 2 (for receiving "left" and "right") From fade7f1bde5f878a7eef0a9ad34a07319d999ec2 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 18 Jan 2021 14:05:57 +0000 Subject: [PATCH 20/54] error computation biasing position --- c_code/icub_vor_env/src/icub_vor_env.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index f0e0e133..fb9f9e40 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -254,7 +254,7 @@ void test_the_head(void) { // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = perfect_eye_pos[tick_in_head_loop] - current_eye_pos; accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; - error_value = (error_pos + error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? + error_value = (0.8k * error_pos + 0.2k * error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has From 76d758a4284ffa63a10126ea6e9983f2cb1d5886 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 29 Jan 2021 08:44:18 +0000 Subject: [PATCH 21/54] current parameters work somewhat well for 5x slowdown (commit from vor_cerebellum) --- c_code/icub_vor_env/src/icub_vor_env.c | 57 ++++++++++++++++---------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index fb9f9e40..29d48b24 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -52,6 +52,9 @@ typedef enum { // SPECIAL_EVENT_INPUT_8, //} special_event_t; +// printing info during run is enabled +#define PRINT_LOGS false + // These are the keys to be received for left/right choice typedef enum { KEY_CHOICE_LEFT = 0x0, @@ -74,6 +77,7 @@ static uint32_t infinite_run; // - perfect eye position, perfect eye velocity arrays uint32_t error_window_size; uint32_t output_size; +accum mid_neuron; uint32_t number_of_inputs; accum *perfect_eye_pos; accum *perfect_eye_vel; @@ -185,12 +189,14 @@ static bool initialize(uint32_t *timer_period) perfect_eye_pos = (accum *)&icub_vor_env_data_region[8]; perfect_eye_vel = (accum *)&icub_vor_env_data_region[8 + number_of_inputs]; // End of initialise + mid_neuron = (accum) (output_size) * 0.5k; + io_printf(IO_BUF, "Initialise: completed successfully\n"); return true; } -void update_count(uint32_t index) { +static inline void update_count(uint32_t index) { // Update the count values in here when a mc packet is received // io_printf(IO_BUF, "At time %u, update index %u \n", _time, index); spike_counters[index] += 1; @@ -199,24 +205,25 @@ void update_count(uint32_t index) { // when a packet is received, update the error void mc_packet_received_callback(uint keyx, uint payload) { - uint32_t compare; - compare = keyx & 0x1; // This is an odd and even check. - - // If no payload has been set, make sure the loop will run - if (payload == 0) { payload = 1; } + update_count(keyx & 0x1); - // Update the spike counters based on the key value - for (uint count = payload; count > 0; count--) { - if (compare == KEY_CHOICE_LEFT) { - update_count(0); - } - else if (compare == KEY_CHOICE_RIGHT) { - update_count(1); - } - else { - io_printf(IO_BUF, "Unexpected key value %d\n", key); - } - } +// uint32_t compare; +// compare = keyx & 0x1; // This is an odd and even check. +// // If no payload has been set, make sure the loop will run +// if (payload == 0) { payload = 1; } +// +// // Update the spike counters based on the key value +// for (uint count = payload; count > 0; count--) { +// if (compare == KEY_CHOICE_LEFT) { +// update_count(0); +// } +// else if (compare == KEY_CHOICE_RIGHT) { +// update_count(1); +// } +// else { +// io_printf(IO_BUF, "Unexpected key value %d\n", key); +// } +// } } // Test the counters for the head after this loop @@ -250,18 +257,24 @@ void test_the_head(void) { // Compute the current velocity current_eye_vel = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); + // Check speed bounds + if (current_eye_vel < -1.0k) { + current_eye_vel = -1.0k; + } + else if (current_eye_vel > 1.0k) { + current_eye_vel = 1.0k; + } // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = perfect_eye_pos[tick_in_head_loop] - current_eye_pos; accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; - error_value = (0.8k * error_pos + 0.2k * error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? +// error_value = (0.9k * error_pos + 0.1k * error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? + error_value = (error_pos + error_vel); // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has // been worked out how the spike counters at L and R translate to head/eye movement - - accum mid_neuron = (accum) (output_size) * 0.5k; accum low_threshold = absk(error_value) * mid_neuron; accum up_threshold = low_threshold - mid_neuron; @@ -326,7 +339,7 @@ void timer_callback(uint unused, uint dummy) _time -= 1; return; } - // Otherwise + // Otherwise the simulation is still running else { // Increment ticks for head loop and error window tick_in_head_loop++; From b7a8bb5e922bf6a9b0db607300152345c99ccc6b Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 8 Feb 2021 10:18:36 +0000 Subject: [PATCH 22/54] velocity is now the parameter that the network can influence --- c_code/icub_vor_env/src/icub_vor_env.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 29d48b24..ed133aef 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -244,7 +244,10 @@ void test_the_head(void) { // Compute the contribution to position (1 bit set in counter_diff = 2**-15) pos_diff = kbits(counter_diff) * gain; - accum previous_eye_pos = current_eye_pos; + current_eye_vel = pos_diff * 16.5494949k; // TODO why should this scaling factor be cca. 15? 16.54949.. when gain=20 + current_eye_pos = current_eye_pos + MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); + +// accum previous_eye_pos = current_eye_pos; current_eye_pos = current_eye_pos + pos_diff; // Check bounds if (current_eye_pos < -1.0k) { @@ -253,10 +256,11 @@ void test_the_head(void) { else if (current_eye_pos > 1.0k) { current_eye_pos = 1.0k; } - pos_diff = current_eye_pos - previous_eye_pos; +// pos_diff = current_eye_pos - previous_eye_pos; // Compute the current velocity - current_eye_vel = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); + // Version in which the position is modified by the spikes +// current_eye_vel = MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); // Check speed bounds if (current_eye_vel < -1.0k) { current_eye_vel = -1.0k; @@ -267,9 +271,11 @@ void test_the_head(void) { // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = perfect_eye_pos[tick_in_head_loop] - current_eye_pos; +// accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; // error_value = (0.9k * error_pos + 0.1k * error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? - error_value = (error_pos + error_vel); +// error_value = (error_pos + error_vel); + error_value = (error_pos); // The above could easily be replaced by a comparison to the perfect eye // position and velocity at the current value of tick_in_head_loop, once it has From 1bcafded3428c16bc21e7db079605252beb47a82 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 19 Nov 2021 12:28:50 +0000 Subject: [PATCH 23/54] Update ICubVorEnv to match other vertices --- examples/icub_vor_env/icub_vor_env_test.py | 38 +-- examples/icub_vor_env/spynnaker.cfg | 4 + spinn_gym/games/icub_vor_env/icub_vor_env.py | 219 ++++++------------ .../icub_vor_env_machine_vertex.py | 176 +++++++++++++- 4 files changed, 266 insertions(+), 171 deletions(-) create mode 100644 examples/icub_vor_env/spynnaker.cfg diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index af5e0736..97989131 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -12,40 +12,40 @@ def get_error(icub_vor_env_pop, simulator): b_vertex = icub_vor_env_pop._vertex error = b_vertex.get_data( 'error', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager, simulator.machine_time_step) + simulator.buffer_manager) return error.tolist() def get_l_count(icub_vor_env_pop, simulator): b_vertex = icub_vor_env_pop._vertex left_count = b_vertex.get_data( - 'L_count', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager, simulator.machine_time_step) + 'l_count', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) return left_count.tolist() def get_r_count(icub_vor_env_pop, simulator): b_vertex = icub_vor_env_pop._vertex right_count = b_vertex.get_data( - 'R_count', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager, simulator.machine_time_step) + 'r_count', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) return right_count.tolist() -def get_head_pos(icub_vor_env_pop, simulator): +def get_eye_pos(icub_vor_env_pop, simulator): b_vertex = icub_vor_env_pop._vertex - head_positions = b_vertex.get_data( - 'head_pos', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager, simulator.machine_time_step) - return head_positions.tolist() + eye_positions = b_vertex.get_data( + 'eye_pos', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) + return eye_positions.tolist() -def get_head_vel(icub_vor_env_pop, simulator): +def get_eye_vel(icub_vor_env_pop, simulator): b_vertex = icub_vor_env_pop._vertex - head_velocities = b_vertex.get_data( - 'head_vel', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager, simulator.machine_time_step) - return head_velocities.tolist() + eye_velocities = b_vertex.get_data( + 'eye_vel', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) + return eye_velocities.tolist() # Setup @@ -111,9 +111,9 @@ def get_head_vel(icub_vor_env_pop, simulator): errors = get_error(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) l_counts = get_l_count(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) r_counts = get_r_count(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) -rec_head_pos = get_head_pos( +rec_eye_pos = get_eye_pos( icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) -rec_head_vel = get_head_vel( +rec_eye_vel = get_eye_vel( icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) # get the spike data from input and output and plot @@ -149,8 +149,8 @@ def get_head_vel(icub_vor_env_pop, simulator): plt.xlim([0, runtime]) plt.subplot(5, 1, 3) -plt.plot(x_plot, rec_head_pos, label="head position") -plt.plot(x_plot, rec_head_vel, label="head velocity") +plt.plot(x_plot, rec_eye_pos, label="eye position") +plt.plot(x_plot, rec_eye_vel, label="eye velocity") # plt.plot(perfect_eye_pos, label="eye position", ls='--') # plt.plot(perfect_eye_vel, label="eye velocity", ls='--') plt.legend(loc="best") diff --git a/examples/icub_vor_env/spynnaker.cfg b/examples/icub_vor_env/spynnaker.cfg new file mode 100644 index 00000000..8bbf7d2f --- /dev/null +++ b/examples/icub_vor_env/spynnaker.cfg @@ -0,0 +1,4 @@ +[Mapping] + +# Logic doesn't implement delay extensions, so avoid DelaySupportAdder +delay_support_adder = None \ No newline at end of file diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 767c7004..12b8582c 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -1,39 +1,62 @@ +# Copyright (c) 2019-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import numpy + from spinn_utilities.overrides import overrides +from spinn_utilities.config_holder import get_config_int + +from data_specification.enums.data_type import DataType # PACMAN imports -from pacman.executor.injection_decorator import inject_items +# from pacman.executor.injection_decorator import inject_items from pacman.model.constraints.key_allocator_constraints import \ ContiguousKeyRangeContraint -from pacman.model.graphs.application import ApplicationVertex -from pacman.model.resources.cpu_cycles_per_tick_resource import \ - CPUCyclesPerTickResource -from pacman.model.resources.dtcm_resource import DTCMResource -from pacman.model.resources.resource_container import ResourceContainer -from pacman.model.resources.variable_sdram import VariableSDRAM - -from data_specification.enums.data_type import DataType +from pacman.model.graphs.application.abstract import ( + AbstractOneAppOneMachineVertex) +from pacman.model.graphs.common import Slice +# from pacman.model.graphs.application import ApplicationVertex +# from pacman.model.resources.cpu_cycles_per_tick_resource import \ +# CPUCyclesPerTickResource +# from pacman.model.resources.dtcm_resource import DTCMResource +# from pacman.model.resources.resource_container import ResourceContainer +# from pacman.model.resources.variable_sdram import VariableSDRAM + +# from data_specification.enums.data_type import DataType # SpinnFrontEndCommon imports from spinn_front_end_common.abstract_models import AbstractChangableAfterRun -from spinn_front_end_common.interface.buffer_management \ - import recording_utilities -from spinn_front_end_common.abstract_models \ - .abstract_generates_data_specification \ - import AbstractGeneratesDataSpecification +# from spinn_front_end_common.interface.buffer_management \ +# import recording_utilities +# from spinn_front_end_common.abstract_models \ +# .abstract_generates_data_specification \ +# import AbstractGeneratesDataSpecification from spinn_front_end_common.abstract_models. \ abstract_provides_outgoing_partition_constraints import \ AbstractProvidesOutgoingPartitionConstraints -from spinn_front_end_common.utilities import globals_variables -from spinn_front_end_common.interface.simulation import simulation_utilities +# from spinn_front_end_common.utilities import globals_variables +# from spinn_front_end_common.interface.simulation import simulation_utilities from spinn_front_end_common.utilities import constants as \ front_end_common_constants -from spinn_front_end_common.utilities.exceptions import ConfigurationException +# from spinn_front_end_common.utilities.exceptions import ConfigurationException # sPyNNaker imports from spynnaker.pyNN.models.abstract_models import \ AbstractAcceptsIncomingSynapses from spynnaker.pyNN.models.common import AbstractNeuronRecordable -from spynnaker.pyNN.utilities import constants +# from spynnaker.pyNN.utilities import constants from spynnaker.pyNN.models.common.simple_population_settable \ import SimplePopulationSettable @@ -41,19 +64,22 @@ from spinn_gym.games.icub_vor_env.icub_vor_env_machine_vertex \ import ICubVorEnvMachineVertex -import numpy - NUMPY_DATA_ELEMENT_TYPE = numpy.double # ---------------------------------------------------------------------------- # ICubVorEnv # ---------------------------------------------------------------------------- -class ICubVorEnv(ApplicationVertex, AbstractGeneratesDataSpecification, +class ICubVorEnv(AbstractOneAppOneMachineVertex, AbstractProvidesOutgoingPartitionConstraints, AbstractAcceptsIncomingSynapses, AbstractNeuronRecordable, SimplePopulationSettable): + @overrides(AbstractAcceptsIncomingSynapses.verify_splitter) + def verify_splitter(self, splitter): + # Need to ignore this verify + pass + @overrides(AbstractAcceptsIncomingSynapses.get_connections_from_machine) def get_connections_from_machine( self, transceiver, placements, app_edge, synapse_info): @@ -115,7 +141,6 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, 'incoming_spike_buffer_size'], simulation_duration_ms=default_parameters['duration']): """ - :param head_pos: array of head positions :param head_vel: array of head velocities :param perfect_eye_pos: array of ideal eye positions to produce the VOR @@ -177,146 +202,40 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, self._m_vertex = None + resources_required = ( + self.ICUB_VOR_ENV_REGION_BYTES + self.BASE_DATA_REGION_BYTES + + self._recording_size) + + vertex_slice = Slice(0, self._n_neurons - 1) + # Superclasses - ApplicationVertex.__init__( - self, label, constraints, self.n_atoms) + super(ICubVorEnv, self).__init__( + ICubVorEnvMachineVertex( + vertex_slice, resources_required, constraints, label, self, + head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, + error_window_size, output_size, gain, pos_to_vel, wta_decision, + low_error_rate, high_error_rate, incoming_spike_buffer_size, + simulation_duration_ms), + label=label, constraints=constraints) + AbstractProvidesOutgoingPartitionConstraints.__init__(self) SimplePopulationSettable.__init__(self) AbstractChangableAfterRun.__init__(self) AbstractAcceptsIncomingSynapses.__init__(self) self._change_requires_mapping = True - # get config from simulator - config = globals_variables.get_simulator().config - if incoming_spike_buffer_size is None: - self._incoming_spike_buffer_size = config.getint( + self._incoming_spike_buffer_size = get_config_int( "Simulation", "incoming_spike_buffer_size") def neurons(self): return self._n_neurons - def get_maximum_delay_supported_in_ms(self, machine_time_step): - # ICubVorEnv has no synapses so can simulate only one timestep of delay - return machine_time_step / 1000.0 - - # ------------------------------------------------------------------------ - # ApplicationVertex overrides - # ------------------------------------------------------------------------ - @overrides(ApplicationVertex.get_resources_used_by_atoms) - def get_resources_used_by_atoms(self, vertex_slice): - # **HACK** only way to force no partitioning is to zero dtcm and cpu - container = ResourceContainer( - sdram=VariableSDRAM(fixed_sdram=0, per_timestep_sdram=4), - dtcm=DTCMResource(0), - cpu_cycles=CPUCyclesPerTickResource(0)) - - return container - - @overrides(ApplicationVertex.create_machine_vertex) - def create_machine_vertex(self, vertex_slice, resources_required, - label=None, constraints=None): - # Return suitable machine vertex - return ICubVorEnvMachineVertex( - resources_required, constraints, self._label, self, vertex_slice) - @property - @overrides(ApplicationVertex.n_atoms) + @overrides(AbstractOneAppOneMachineVertex.n_atoms) def n_atoms(self): return self._n_neurons # ------------------------------------------------------------------------ - # AbstractGeneratesDataSpecification overrides - # ------------------------------------------------------------------------ - @inject_items({"machine_time_step": "MachineTimeStep", - "time_scale_factor": "TimeScaleFactor", - "routing_info": "MemoryRoutingInfos", - "tags": "MemoryTags"}) - @overrides(AbstractGeneratesDataSpecification.generate_data_specification, - additional_arguments={"machine_time_step", "time_scale_factor", - "routing_info", "tags"} - ) - def generate_data_specification(self, spec, placement, machine_time_step, - time_scale_factor, routing_info, tags): - vertex = placement.vertex - - spec.comment("\n*** Spec for ICubVorEnv Instance ***\n\n") - spec.comment("\nReserving memory space for data regions:\n\n") - - # Reserve memory: - spec.reserve_memory_region( - region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.SYSTEM.value, - size=front_end_common_constants.SYSTEM_BYTES_REQUIREMENT, - label='setup') - spec.reserve_memory_region( - region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS - .ICUB_VOR_ENV.value, - size=self.ICUB_VOR_ENV_REGION_BYTES, label='ICubVorEnvParams') - # reserve recording region - spec.reserve_memory_region( - ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.RECORDING.value, - recording_utilities.get_recording_header_size( - len(self.RECORDABLE_VARIABLES))) - spec.reserve_memory_region( - region=ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value, - size=self.BASE_DATA_REGION_BYTES + (self._number_of_inputs * 16), - label='ICubVorEnvArms') - - # Write setup region - spec.comment("\nWriting setup region:\n") - spec.switch_write_focus( - ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.SYSTEM.value) - spec.write_array(simulation_utilities.get_simulation_header_array( - vertex.get_binary_file_name(), machine_time_step, - time_scale_factor)) - - # Write icub_vor_env region containing routing key to transmit with - spec.comment("\nWriting icub_vor_env region:\n") - spec.switch_write_focus( - ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.ICUB_VOR_ENV.value) - spec.write_value(routing_info.get_first_key_from_pre_vertex( - vertex, constants.LIVE_POISSON_CONTROL_PARTITION_ID)) - - # Write recording region for score - spec.comment("\nWriting icub_vor_env recording region:\n") - spec.switch_write_focus( - ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.RECORDING.value) - ip_tags = tags.get_ip_tags_for_vertex(self) or [] - recording_sizes = [ - self._recording_size for _ in range(self._n_recordable_variables)] - spec.write_array(recording_utilities.get_recording_header_array( - recording_sizes, ip_tags=ip_tags)) - - # Write parameters for ICubVorEnv data - spec.comment("\nWriting icub_vor_env data region:\n") - float_scale = float(DataType.S1615.scale) - spec.switch_write_focus( - ICubVorEnvMachineVertex._ICUB_VOR_ENV_REGIONS.DATA.value) - spec.write_value(self._error_window_size, data_type=DataType.UINT32) - spec.write_value(self._output_size, data_type=DataType.UINT32) - spec.write_value(self._number_of_inputs, data_type=DataType.UINT32) - spec.write_value(self.__round_to_nearest_accum(self._gain), data_type=DataType.S1615) - spec.write_value(self.__round_to_nearest_accum(self._pos_to_vel), data_type=DataType.S1615) - spec.write_value(int(self._wta_decision), data_type=DataType.UINT32) - spec.write_value(self.__round_to_nearest_accum(self._low_error_rate), data_type=DataType.S1615) - spec.write_value(self.__round_to_nearest_accum(self._high_error_rate), data_type=DataType.S1615) - # Write the data - Arrays must be 32-bit values, so convert - data = numpy.array( - [int(x * float_scale) for x in self._perfect_eye_pos], - dtype=numpy.uint32) - spec.write_array(data.view(numpy.uint32)) - data = numpy.array( - [int(x * float_scale) for x in self._perfect_eye_vel], - dtype=numpy.uint32) - spec.write_array(data.view(numpy.uint32)) - - # End-of-Spec: - spec.end_specification() - - def __round_to_nearest_accum(self, x): - eps = 2. ** (-15) - x_approx = numpy.floor((x / eps) + 0.5) * eps - return x_approx - # ------------------------------------------------------------------------ # AbstractProvidesOutgoingPartitionConstraints overrides # ------------------------------------------------------------------------ @overrides(AbstractProvidesOutgoingPartitionConstraints. @@ -366,8 +285,8 @@ def get_neuron_sampling_interval(self, variable): return 10000 # 10 seconds hard coded in as sim duration... ? @overrides(AbstractNeuronRecordable.get_data) - def get_data(self, variable, n_machine_time_steps, placements, - buffer_manager, machine_time_step): + def get_data( + self, variable, n_machine_time_steps, placements, buffer_manager): if self._m_vertex is None: self._m_vertex = self.machine_vertices.pop() print('get_data from machine vertex ', self._m_vertex, @@ -415,3 +334,9 @@ def _clear_recording_region( def reset_ring_buffer_shifts(self): pass + + def __str__(self): + return "{} with {} atoms".format(self._label, self.n_atoms) + + def __repr__(self): + return self.__str__() diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index c48890d6..953d4a6c 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -1,9 +1,29 @@ +# Copyright (c) 2019-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from enum import Enum +import numpy from spinn_utilities.overrides import overrides +from data_specification.enums.data_type import DataType + # PACMAN imports +from pacman.executor.injection_decorator import inject_items from pacman.model.graphs.machine import MachineVertex +from pacman.model.resources import ConstantSDRAM, ResourceContainer # SpinnFrontEndCommon imports from spinn_front_end_common.utilities import helpful_functions @@ -12,13 +32,35 @@ from spinn_front_end_common.abstract_models.abstract_has_associated_binary \ import AbstractHasAssociatedBinary from spinn_front_end_common.utilities.utility_objs import ExecutableType +from spinn_front_end_common.interface.buffer_management \ + import recording_utilities +from spinn_front_end_common.abstract_models \ + .abstract_generates_data_specification \ + import AbstractGeneratesDataSpecification +from spinn_front_end_common.interface.simulation import simulation_utilities +from spinn_front_end_common.utilities import constants as \ + front_end_common_constants + +# sPyNNaker imports +from spynnaker.pyNN.utilities import constants # ---------------------------------------------------------------------------- # ICubVorEnvMachineVertex # ---------------------------------------------------------------------------- -class ICubVorEnvMachineVertex(MachineVertex, AbstractReceiveBuffersToHost, +class ICubVorEnvMachineVertex(MachineVertex, + AbstractGeneratesDataSpecification, + AbstractReceiveBuffersToHost, AbstractHasAssociatedBinary): + ICUB_VOR_ENV_REGION_BYTES = 4 + BASE_DATA_REGION_BYTES = 9 * 4 + # Probably better ways of doing this too, but keeping it for now + RECORDABLE_VARIABLES = [ + "l_count", "r_count", "error", "eye_pos", "eye_vel"] + RECORDABLE_DTYPES = [ + DataType.UINT32, DataType.UINT32, DataType.S1615, DataType.S1615, + DataType.S1615] + _ICUB_VOR_ENV_REGIONS = Enum( value="_ICUB_VOR_ENV_REGIONS", names=[('SYSTEM', 0), @@ -26,12 +68,135 @@ class ICubVorEnvMachineVertex(MachineVertex, AbstractReceiveBuffersToHost, ('RECORDING', 2), ('DATA', 3)]) - def __init__(self, resources_required, constraints=None, label=None, - app_vertex=None, vertex_slice=None): + def __init__(self, vertex_slice, resources_required, constraints, label, + app_vertex, head_pos, head_vel, perfect_eye_pos, + perfect_eye_vel, error_window_size, output_size, gain, + pos_to_vel, wta_decision, low_error_rate, high_error_rate, + incoming_spike_buffer_size, simulation_duration_ms): + + # resources required + self._resources_required = ResourceContainer( + sdram=ConstantSDRAM(resources_required)) + + self._label = label + + # pass in variables + self._head_pos = head_pos + self._head_vel = head_vel + self._perfect_eye_pos = perfect_eye_pos + self._perfect_eye_vel = perfect_eye_vel + self._error_window_size = error_window_size + self._output_size = output_size + self._gain = gain + self._pos_to_vel = pos_to_vel + self._wta_decision = wta_decision + self._low_error_rate = low_error_rate + self._high_error_rate = high_error_rate + self._number_of_inputs = len(perfect_eye_pos) + if self._number_of_inputs != len(perfect_eye_vel): + raise ConfigurationException( + "The length of perfect_eye_pos {} is not the same as the " + "length of perfect_eye_vel {}".format( + self._number_of_inputs, len(perfect_eye_vel))) + + self._n_recordable_variables = len(self.RECORDABLE_VARIABLES) + + self._recording_size = int((simulation_duration_ms / error_window_size) + * front_end_common_constants.BYTES_PER_WORD) + # Superclasses MachineVertex.__init__( self, label, constraints, app_vertex, vertex_slice) - self._resources_required = resources_required + + # ------------------------------------------------------------------------ + # AbstractGeneratesDataSpecification overrides + # ------------------------------------------------------------------------ + @inject_items({"routing_info": "RoutingInfos"}) + @overrides(AbstractGeneratesDataSpecification.generate_data_specification, + additional_arguments={"routing_info"} + ) + def generate_data_specification(self, spec, placement, routing_info): + vertex = placement.vertex + + spec.comment("\n*** Spec for ICubVorEnv Instance ***\n\n") + spec.comment("\nReserving memory space for data regions:\n\n") + + # Reserve memory: + spec.reserve_memory_region( + region=self._ICUB_VOR_ENV_REGIONS.SYSTEM.value, + size=front_end_common_constants.SYSTEM_BYTES_REQUIREMENT, + label='setup') + spec.reserve_memory_region( + region=self._ICUB_VOR_ENV_REGIONS + .ICUB_VOR_ENV.value, + size=self.ICUB_VOR_ENV_REGION_BYTES, label='ICubVorEnvParams') + # reserve recording region + spec.reserve_memory_region( + self._ICUB_VOR_ENV_REGIONS.RECORDING.value, + recording_utilities.get_recording_header_size( + len(self.RECORDABLE_VARIABLES))) + spec.reserve_memory_region( + region=self._ICUB_VOR_ENV_REGIONS.DATA.value, + size=self.BASE_DATA_REGION_BYTES + (self._number_of_inputs * 16), + label='ICubVorEnvArms') + + # Write setup region + spec.comment("\nWriting setup region:\n") + spec.switch_write_focus( + self._ICUB_VOR_ENV_REGIONS.SYSTEM.value) + spec.write_array(simulation_utilities.get_simulation_header_array( + vertex.get_binary_file_name())) + + # Write icub_vor_env region containing routing key to transmit with + spec.comment("\nWriting icub_vor_env region:\n") + spec.switch_write_focus( + self._ICUB_VOR_ENV_REGIONS.ICUB_VOR_ENV.value) + spec.write_value(routing_info.get_first_key_from_pre_vertex( + vertex, constants.LIVE_POISSON_CONTROL_PARTITION_ID)) + + # Write recording region for score + spec.comment("\nWriting icub_vor_env recording region:\n") + spec.switch_write_focus( + self._ICUB_VOR_ENV_REGIONS.RECORDING.value) + recording_sizes = [ + self._recording_size for _ in range(self._n_recordable_variables)] + spec.write_array(recording_utilities.get_recording_header_array( + recording_sizes)) + + # Write parameters for ICubVorEnv data + spec.comment("\nWriting icub_vor_env data region:\n") + float_scale = float(DataType.S1615.scale) + spec.switch_write_focus( + self._ICUB_VOR_ENV_REGIONS.DATA.value) + spec.write_value(self._error_window_size, data_type=DataType.UINT32) + spec.write_value(self._output_size, data_type=DataType.UINT32) + spec.write_value(self._number_of_inputs, data_type=DataType.UINT32) + spec.write_value(self.__round_to_nearest_accum(self._gain), + data_type=DataType.S1615) + spec.write_value(self.__round_to_nearest_accum(self._pos_to_vel), + data_type=DataType.S1615) + spec.write_value(int(self._wta_decision), data_type=DataType.UINT32) + spec.write_value(self.__round_to_nearest_accum(self._low_error_rate), + data_type=DataType.S1615) + spec.write_value(self.__round_to_nearest_accum(self._high_error_rate), + data_type=DataType.S1615) + # Write the data - Arrays must be 32-bit values, so convert + data = numpy.array( + [int(x * float_scale) for x in self._perfect_eye_pos], + dtype=numpy.uint32) + spec.write_array(data.view(numpy.uint32)) + data = numpy.array( + [int(x * float_scale) for x in self._perfect_eye_vel], + dtype=numpy.uint32) + spec.write_array(data.view(numpy.uint32)) + + # End-of-Spec: + spec.end_specification() + + def __round_to_nearest_accum(self, x): + eps = 2. ** (-15) + x_approx = numpy.floor((x / eps) + 0.5) * eps + return x_approx @property def resources_required(self): @@ -52,7 +217,8 @@ def get_n_keys_for_partition(self, partition): # The way this has been written, there should only be one edge, but # better to be safe than sorry for edge in partition.edges: - n_keys += edge.post_vertex.get_n_keys_for_partition(partition) + if edge.pre_vertex is not edge.post_vertex: + n_keys += edge.post_vertex.get_n_keys_for_partition(partition) return n_keys @overrides(AbstractHasAssociatedBinary.get_binary_file_name) From 44c5ae05e3e1e75a599fa516950dea38b0651673 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 19 Nov 2021 12:37:27 +0000 Subject: [PATCH 24/54] C code line length, unused params; update requirements --- c_code/icub_vor_env/src/icub_vor_env.c | 11 +++++++---- requirements.txt | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index ed133aef..30dc52ac 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -205,6 +205,7 @@ static inline void update_count(uint32_t index) { // when a packet is received, update the error void mc_packet_received_callback(uint keyx, uint payload) { + use(payload); update_count(keyx & 0x1); // uint32_t compare; @@ -236,7 +237,8 @@ void test_the_head(void) { int32_t counter_diff; if (wta_decision) { - counter_diff = spike_counters[0] > spike_counters[1] ? spike_counters[0] : -spike_counters[1]; + counter_diff = spike_counters[0] > spike_counters[1] ? + spike_counters[0] : -spike_counters[1]; } else { counter_diff = (spike_counters[0] - spike_counters[1]); @@ -244,7 +246,8 @@ void test_the_head(void) { // Compute the contribution to position (1 bit set in counter_diff = 2**-15) pos_diff = kbits(counter_diff) * gain; - current_eye_vel = pos_diff * 16.5494949k; // TODO why should this scaling factor be cca. 15? 16.54949.. when gain=20 + // TODO why should this scaling factor be cca. 15? 16.54949.. when gain=20 + current_eye_vel = pos_diff * 16.5494949k; current_eye_pos = current_eye_pos + MULT_NO_ROUND_CUSTOM_ACCUM(pos_diff, pos_to_vel); // accum previous_eye_pos = current_eye_pos; @@ -272,8 +275,8 @@ void test_the_head(void) { // Error is relative (in both cases) as the test is done based on > or < 0.0 accum error_pos = perfect_eye_pos[tick_in_head_loop] - current_eye_pos; // accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; - accum error_vel = perfect_eye_vel[tick_in_head_loop] - current_eye_vel; -// error_value = (0.9k * error_pos + 0.1k * error_vel); // TODO what should happen if error_pos and error_vel cancel each other out? + // TODO what should happen if error_pos and error_vel cancel each other out? +// error_value = (0.9k * error_pos + 0.1k * error_vel); // error_value = (error_pos + error_vel); error_value = (error_pos); diff --git a/requirements.txt b/requirements.txt index 6be6d119..51d037df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,3 +25,4 @@ numpy >= 1.19, <= 1.20; python_version == '3.7' numpy; python_version >= '3.8' lxml opencv-python == 4.5.3.56 +pandas From e507cbad9ae7fa9d8dce5a575913d7e29715a3d6 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 19 Nov 2021 13:34:15 +0000 Subject: [PATCH 25/54] flake8 --- examples/icub_vor_env/icub_vor_env_test.py | 6 +++-- setup.py | 2 +- spinn_gym/games/icub_vor_env/icub_vor_env.py | 25 +++++++++++-------- .../icub_vor_env_machine_vertex.py | 4 +-- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 97989131..19c8413a 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -81,8 +81,10 @@ def get_eye_vel(icub_vor_env_pop, simulator): # Report 4 points: for i in [0, 250, 500, 750]: - print("At {}: head pos {:4.6f}, head vel {:4.6f}, eye pos {:4.6f}, eye vel {:4.6f}".format( - i, head_pos[i], head_vel[i], perfect_eye_pos[i], perfect_eye_vel[i])) + print("At {}: head pos {:4.6f}, head vel {:4.6f}, eye pos {:4.6f}, " + " eye vel {:4.6f}".format( + i, head_pos[i], head_vel[i], perfect_eye_pos[i], + perfect_eye_vel[i])) # build ICubVorEnv model pop error_window_size = 10 diff --git a/setup.py b/setup.py index 00e0553c..9e7604ee 100644 --- a/setup.py +++ b/setup.py @@ -67,4 +67,4 @@ packages=packages, package_data=package_data, install_requires=install_requires -) \ No newline at end of file +) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 12b8582c..4f301942 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -50,7 +50,7 @@ # from spinn_front_end_common.interface.simulation import simulation_utilities from spinn_front_end_common.utilities import constants as \ front_end_common_constants -# from spinn_front_end_common.utilities.exceptions import ConfigurationException +from spinn_front_end_common.utilities.exceptions import ConfigurationException # sPyNNaker imports from spynnaker.pyNN.models.abstract_models import \ @@ -101,8 +101,8 @@ def get_synapse_id_by_target(self, target): # key value ICUB_VOR_ENV_REGION_BYTES = 4 - # error_window_size, output_size, number_of_inputs, gain, pos_to_vel, wta_decision - # low_error_rate and high_error_rate + # error_window_size, output_size, number_of_inputs, gain, pos_to_vel, + # wta_decision, low_error_rate and high_error_rate BASE_DATA_REGION_BYTES = 8 * 4 # not sure this is entirely necessary but keeping it for now MAX_SIM_DURATION = 10000 @@ -116,8 +116,10 @@ def get_synapse_id_by_target(self, target): # parameters expected by PyNN default_parameters = { 'error_window_size': 10, - 'gain': 20, # boosts the effect of individual spikes - 'pos_to_vel': 1 / (0.001 * 2 * numpy.pi * 10), # magic multiplier to convert movement delta to speed + # boosts the effect of individual spikes + 'gain': 20, + # magic multiplier to convert movement delta to speed + 'pos_to_vel': 1 / (0.001 * 2 * numpy.pi * 10), 'wta_decision': False, 'low_error_rate': 2, # Hz 'high_error_rate': 20, # Hz @@ -143,17 +145,20 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, """ :param head_pos: array of head positions :param head_vel: array of head velocities - :param perfect_eye_pos: array of ideal eye positions to produce the VOR - :param perfect_eye_vel: array of ideal eye velocities to produce the VOR + :param perfect_eye_pos: array of ideal eye positions to produce VOR + :param perfect_eye_vel: array of ideal eye velocities to produce VOR :param error_window_size: how often the environment changes - :param output_size: numbers of neurons encoding the error transmitted via combing fibres + :param output_size: numbers of neurons encoding the error transmitted \ + via combing fibres :param gain: boosts the effect of individual spikes :param pos_to_vel: magic multiplier to convert movement delta to speed - :param wta_decision: whether eye movement takes into account the difference in number of spikes between L / R + :param wta_decision: whether eye movement takes into account the \ + difference in number of spikes between L and R :param constraints: usual sPyNNaker constraints :param label: name of the population :param incoming_spike_buffer_size: - :param simulation_duration_ms: maximum simulation duration for this application vertex + :param simulation_duration_ms: maximum simulation duration for this \ + application vertex """ # **NOTE** n_neurons currently ignored - width and height will be # specified as additional parameters, forcing their product to be diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 953d4a6c..6a0ebc0f 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -40,6 +40,7 @@ from spinn_front_end_common.interface.simulation import simulation_utilities from spinn_front_end_common.utilities import constants as \ front_end_common_constants +from spinn_front_end_common.utilities.exceptions import ConfigurationException # sPyNNaker imports from spynnaker.pyNN.utilities import constants @@ -127,8 +128,7 @@ def generate_data_specification(self, spec, placement, routing_info): size=front_end_common_constants.SYSTEM_BYTES_REQUIREMENT, label='setup') spec.reserve_memory_region( - region=self._ICUB_VOR_ENV_REGIONS - .ICUB_VOR_ENV.value, + region=self._ICUB_VOR_ENV_REGIONS.ICUB_VOR_ENV.value, size=self.ICUB_VOR_ENV_REGION_BYTES, label='ICubVorEnvParams') # reserve recording region spec.reserve_memory_region( From 115e71be7b3875b12bdcc4a6ab7cfea185cd6d13 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 19 Nov 2021 13:41:05 +0000 Subject: [PATCH 26/54] Add copyrights --- .ratexcludes | 1 + c_code/icub_vor_env/src/icub_vor_env.c | 16 ++++++++++++++++ examples/icub_vor_env/icub_vor_env_test.py | 15 +++++++++++++++ spinn_gym/games/icub_vor_env/__init__.py | 14 ++++++++++++++ 4 files changed, 46 insertions(+) diff --git a/.ratexcludes b/.ratexcludes index e3ce47c9..fd56a9a8 100644 --- a/.ratexcludes +++ b/.ratexcludes @@ -1,5 +1,6 @@ **/*.colour_map **/*.col +**/*.csv **/SpiNNUtils/** **/SpiNNMachine/** **/SpiNNMan/** diff --git a/c_code/icub_vor_env/src/icub_vor_env.c b/c_code/icub_vor_env/src/icub_vor_env.c index 30dc52ac..a29e295b 100644 --- a/c_code/icub_vor_env/src/icub_vor_env.c +++ b/c_code/icub_vor_env/src/icub_vor_env.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2013-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ // // icub_vor_env.c // Environment to simulate ICub robot for particular network, see diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 19c8413a..1c0f8496 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -1,3 +1,18 @@ +# Copyright (c) 2019-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + import spynnaker8 as p import spinn_gym as gym diff --git a/spinn_gym/games/icub_vor_env/__init__.py b/spinn_gym/games/icub_vor_env/__init__.py index e69de29b..be5735ba 100644 --- a/spinn_gym/games/icub_vor_env/__init__.py +++ b/spinn_gym/games/icub_vor_env/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2019-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . From 3ebb978deb70b04d3bd8bb28191bf12f6dde87db Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 2 Mar 2022 11:49:29 +0000 Subject: [PATCH 27/54] Add more icub_vor scripts (moved from examples elsewhere) --- examples/icub_vor_env/icub_utilities.py | 249 ++++++++++++++++++ .../icub_vor_env_test_200_inputs.py | 118 +++++++++ .../icub_vor_venv_test_perfect_motion.py | 131 +++++++++ 3 files changed, 498 insertions(+) create mode 100644 examples/icub_vor_env/icub_utilities.py create mode 100644 examples/icub_vor_env/icub_vor_env_test_200_inputs.py create mode 100644 examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py diff --git a/examples/icub_vor_env/icub_utilities.py b/examples/icub_vor_env/icub_utilities.py new file mode 100644 index 00000000..6648ac8f --- /dev/null +++ b/examples/icub_vor_env/icub_utilities.py @@ -0,0 +1,249 @@ +# Copyright (c) 2019-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import numpy as np +import pylab as plt +import matplotlib as mlib +import copy + +# ensure we use viridis as the default cmap +plt.viridis() + +mlib.use('Agg') +# ensure we use the same rc parameters for all matplotlib outputs +mlib.rcParams.update({'font.size': 24}) +mlib.rcParams.update({'errorbar.capsize': 5}) +mlib.rcParams.update({'figure.autolayout': True}) +viridis_cmap = mlib.cm.get_cmap('viridis') + +ICUB_VOR_VENV_POP_SIZE = 2 +POS_TO_VEL = 2 * np.pi * 0.001 + + +# Examples of get functions for variables +def get_error(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + error = b_vertex.get_data( + 'error', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) + return error.tolist() + + +def get_l_count(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + left_count = b_vertex.get_data( + 'l_count', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) + return left_count.tolist() + + +def get_r_count(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + right_count = b_vertex.get_data( + 'r_count', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) + return right_count.tolist() + + +def get_eye_pos(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + eye_positions = b_vertex.get_data( + 'eye_pos', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) + return eye_positions.tolist() + + +def get_eye_vel(icub_vor_env_pop, simulator): + b_vertex = icub_vor_env_pop._vertex + eye_velocities = b_vertex.get_data( + 'eye_vel', simulator.no_machine_time_steps, simulator.placements, + simulator.buffer_manager) + return eye_velocities.tolist() + + +def generate_head_position_and_velocity(time, dt=0.001): + i = np.arange(0, time, dt) + pos = -np.sin(i * 2 * np.pi) + vel = -np.cos(i * 2 * np.pi) + return pos, vel + + +def retrieve_and_package_results(icub_vor_env_pop, simulator): + # Get the data from the ICubVorEnv pop + errors = np.asarray(get_error( + icub_vor_env_pop=icub_vor_env_pop, simulator=simulator)).ravel() + l_counts = get_l_count(icub_vor_env_pop=icub_vor_env_pop, + simulator=simulator) + r_counts = get_r_count(icub_vor_env_pop=icub_vor_env_pop, + simulator=simulator) + rec_eye_pos = np.asarray(get_eye_pos( + icub_vor_env_pop=icub_vor_env_pop, simulator=simulator)).ravel() + rec_eye_vel = np.asarray(get_eye_vel( + icub_vor_env_pop=icub_vor_env_pop, simulator=simulator)).ravel() + results = { + 'errors': errors, + 'l_counts': l_counts, + 'r_counts': r_counts, + 'rec_eye_pos': rec_eye_pos, + 'rec_eye_vel': rec_eye_vel, + } + return results + + +def highlight_area(ax, runtime, start_nid, stop_nid): + ax.fill_between( + [0, runtime], start_nid, stop_nid, + color='grey', alpha=0.1, + ) + + +def plot_results(results_dict, simulation_parameters, name): + # unpacking results + errors = results_dict['errors'] + l_counts = results_dict['l_counts'] + r_counts = results_dict['r_counts'] + rec_eye_pos = results_dict['rec_eye_pos'] + rec_eye_vel = results_dict['rec_eye_vel'] + + # unpacking simulation params + runtime = simulation_parameters['runtime'] + error_window_size = simulation_parameters['error_window_size'] + vn_spikes = simulation_parameters['vn_spikes'] + cf_spikes = simulation_parameters['cf_spikes'] + perfect_eye_pos = simulation_parameters['perfect_eye_pos'] + perfect_eye_vel = simulation_parameters['perfect_eye_vel'] + vn_size = simulation_parameters['vn_size'] + cf_size = simulation_parameters['cf_size'] + + # plot the data from the ICubVorEnv pop + x_plot = [(n) for n in range(0, runtime, error_window_size)] + fig = plt.figure(figsize=(15, 20), dpi=400) + # Spike raster plot + ax = plt.subplot(5, 1, 1) + highlight_area(ax, runtime, vn_size // 2, vn_size) + first_half_filter = vn_spikes[:, 0] < vn_size // 2 + second_half_filter = ~first_half_filter + plt.scatter( + vn_spikes[second_half_filter, 1], vn_spikes[second_half_filter, 0], + s=1, color=viridis_cmap(.75)) + plt.scatter( + vn_spikes[first_half_filter, 1], vn_spikes[first_half_filter, 0], + s=1, color=viridis_cmap(.25)) + + plt.xlim([0, runtime]) + plt.ylim([-0.1, vn_size+0.1]) + # L/R counts + plt.subplot(5, 1, 2) + plt.plot(x_plot, l_counts, 'o', color=viridis_cmap(.25), label="l_counts") + plt.plot(x_plot, r_counts, 'o', color=viridis_cmap(.75), label="r_counts") + plt.legend(loc="best") + plt.xlim([0, runtime]) + # Positions and velocities + plt.subplot(5, 1, 3) + plt.plot(x_plot, rec_eye_pos, label="rec. eye position") + plt.plot(x_plot, rec_eye_vel, label="rec. eye velocity") + plt.plot(np.tile(perfect_eye_pos, runtime // 1000), label="eye position", + ls=':') + plt.plot(np.tile(perfect_eye_vel, runtime // 1000), label="eye velocity", + ls=':') + plt.legend(loc="best") + plt.xlim([0, runtime]) + # Errors + plt.subplot(5, 1, 4) + plt.plot(x_plot, errors, label="recorded error") + + eye_pos_diff = np.tile( + perfect_eye_pos[::error_window_size], + runtime // 1000) - rec_eye_pos.ravel() + eye_vel_diff = np.tile( + perfect_eye_vel[::error_window_size], + runtime // 1000) - rec_eye_vel.ravel() + reconstructed_error = eye_pos_diff + eye_vel_diff + + plt.plot(x_plot, reconstructed_error, color='k', ls=":", + label="reconstructed error") + plt.plot(x_plot, eye_pos_diff, + label="eye position diff") + plt.plot(x_plot, eye_vel_diff, + label="eye velocity diff") + plt.legend(loc="best") + plt.xlim([0, runtime]) + # Error spikes + ax2 = plt.subplot(5, 1, 5) + highlight_area(ax2, runtime, cf_size // 2, cf_size) + first_half_filter = cf_spikes[:, 0] < cf_size // 2 + second_half_filter = ~first_half_filter + plt.scatter( + cf_spikes[second_half_filter, 1], cf_spikes[second_half_filter, 0], + s=1, color=viridis_cmap(.75)) + plt.scatter( + cf_spikes[first_half_filter, 1], cf_spikes[first_half_filter, 0], + s=1, color=viridis_cmap(.25)) + # plt.legend(loc="best") + plt.xlim([0, runtime]) + plt.ylim([-0.1, cf_size+0.1]) + plt.xlabel("Time (ms)") + save_figure(plt, name, extensions=[".png", ]) + plt.close(fig) + + +def remap_odd_even(original_spikes, size): + remapped_spikes = copy.deepcopy(original_spikes) + mapping = np.arange(size) + mapping[::2] = np.arange(0, size, 2) // 2 + mapping[1::2] = size // 2 + np.arange(size - 1, 0, -2) // 2 + remapped_spikes[:, 0] = mapping[remapped_spikes[:, 0].astype(int)] + return remapped_spikes + + +def remap_second_half_descending(original_spikes, size): + remapped_spikes = copy.deepcopy(original_spikes) + mapping = np.arange(size) + mapping[:size // 2] = np.arange(0, size // 2, 1) + mapping[size // 2:] = np.arange(size, size // 2, -1) + remapped_spikes[:, 0] = mapping[remapped_spikes[:, 0].astype(int)] + return remapped_spikes + + +def color_for_index(index, size, cmap=viridis_cmap): + return cmap(index / (size + 1)) + + +def write_sep(): + print("=" * 80) + + +def write_line(): + print("-" * 80) + + +def write_header(msg): + write_sep() + print(msg) + write_line() + + +def write_short_msg(msg, value): + print("{:40}:{:39}".format(msg, str(value))) + + +def write_value(msg, value): + print("{:60}:{:19}".format(msg, str(value))) + + +def save_figure(plt, name, extensions=(".png",), **kwargs): + for ext in extensions: + write_short_msg("Plotting", name + ext) + plt.savefig(name + ext, **kwargs) diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py new file mode 100644 index 00000000..064a12f9 --- /dev/null +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -0,0 +1,118 @@ +# Copyright (c) 2019-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import spynnaker8 as p +import spinn_gym as gym + +# from pyNN.utility.plotting import Figure, Panel +# import matplotlib.pyplot as plt +import numpy as np +# import os +from spinn_front_end_common.utilities.globals_variables import get_simulator +from icub_utilities import ( + generate_head_position_and_velocity, retrieve_and_package_results, + remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, + plot_results) + + +# Parameter definition +runtime = 5000 +# Build input SSP and output population +input_size = 200 # neurons +output_size = 200 # neurons +gain = 20.0 + +head_pos, head_vel = generate_head_position_and_velocity(1) + +# perfect eye positions and velocities are exactly out of phase with head +perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) +perfect_eye_vel = np.concatenate((head_vel[500:], head_vel[:500])) + +error_window_size = 10 # ms +npc_limit = 50 +input_spike_times = [[] for _ in range(input_size)] + +for i in range(5): + input_spike_times[i * 2] = [250 + (10 * 2 * i) for _ in range(1)] + input_spike_times[2 * i + 1] = [500 + (10 * (2 * i + 1)) for _ in range(1)] + input_spike_times[50 + i * 2] = [750 + (10 * 2 * i) for _ in range(10 + i)] + input_spike_times[100 + 2 * i + 1] = [ + 1000 + (10 * (2 * i + 1)) for _ in range(10 + i)] + input_spike_times[150 + i * 2] = [ + 1250 + (10 * 2 * i) for _ in range(100 + i)] + input_spike_times[150 + 2 * i + 1] = [ + 1500 + (10 * (2 * i + 1)) for _ in range(100 + i)] + +# Setup +p.setup(timestep=1.0) +p.set_number_of_neurons_per_core(p.SpikeSourcePoisson, 50) +p.set_number_of_neurons_per_core(p.SpikeSourceArray, npc_limit) +input_pop = p.Population(input_size, + p.SpikeSourceArray(spike_times=input_spike_times)) + +output_pop = p.Population(output_size, p.SpikeSourcePoisson(rate=0)) + +# Instantiate venv +icub_vor_env_model = gym.ICubVorEnv( + head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, + output_size) +icub_vor_env_pop = p.Population(ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) + +# Set recording for input and output pop (env pop records by default) +input_pop.record('spikes') +output_pop.record('spikes') + +# Input -> ICubVorEnv projection +i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) + +# ICubVorEnv -> output, setup live output to the SSP vertex +p.external_devices.activate_live_output_to( + icub_vor_env_pop, output_pop, "CONTROL") + +# Store simulator and run +simulator = get_simulator() +# Run the simulation +p.run(runtime) + +# Get the data from the ICubVorEnv pop +results = retrieve_and_package_results(icub_vor_env_pop, simulator) + +# get the spike data from input and output +spikes_in_spin = input_pop.spinnaker_get_data('spikes') +spikes_out_spin = output_pop.spinnaker_get_data('spikes') + +# end simulation +p.end() + +remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = remap_second_half_descending(spikes_out_spin, output_size) + +simulation_parameters = { + 'runtime': runtime, + 'error_window_size': error_window_size, + 'vn_spikes': remapped_vn_spikes, + 'cf_spikes': remapped_cf_spikes, + 'perfect_eye_pos': perfect_eye_pos, + 'perfect_eye_vel': perfect_eye_vel, + 'vn_size': input_size, + 'cf_size': output_size, + 'gain': gain +} + +# plot the data from the ICubVorEnv pop +plot_results(results_dict=results, simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_200_inputs") + +print("Done") diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py new file mode 100644 index 00000000..bff484a3 --- /dev/null +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -0,0 +1,131 @@ +# Copyright (c) 2019-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import spynnaker8 as p +import spinn_gym as gym + +# from pyNN.utility.plotting import Figure, Panel +# import matplotlib.pyplot as plt +import numpy as np +# import os +from spinn_front_end_common.utilities.globals_variables import get_simulator +from icub_utilities import ( + generate_head_position_and_velocity, retrieve_and_package_results, + remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, + plot_results) + + +# Parameter definition +runtime = 3000 +# Build input SSP and output population +input_size = 200 # neurons +output_size = 200 # neurons +gain = 20.0 + +head_pos, head_vel = generate_head_position_and_velocity(1) + +# perfect eye positions and velocities are exactly out of phase with head +perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) +perfect_eye_vel = np.concatenate((head_vel[500:], head_vel[:500])) + +input_spike_times = [[] for _ in range(input_size)] +# the constant number (0.000031) is the effect of a single spike on the head +# position +# assert (np.isclose(np.abs(np.diff(head_pos)[0]), +# no_required_spikes_per_chunk * 0.000031), 0.001) +sub_head_pos = np.diff(head_pos) +head_movement_per_spike = 2 ** (-15) * gain +sub_eye_pos = np.diff(np.concatenate((perfect_eye_pos, [perfect_eye_pos[0]]))) + +# no_required_spikes_per_chunk = 200 +no_required_spikes_per_chunk = np.ceil( + np.abs(sub_head_pos[0]) / head_movement_per_spike) + +# build ICubVorEnv model +error_window_size = 10 # ms +npc_limit = 200 # 25 +no_input_cores = int(input_size / npc_limit) +input_spike_times = [[] for _ in range(input_size)] +for ts in range(runtime - 1): + # if 1000 <= ts < 2000: + # continue + sgn = np.sign(sub_eye_pos[ts % 1000]) + spikes_during_chunk = np.ceil( + np.abs(sub_eye_pos[ts % 1000]) / head_movement_per_spike) + for i in range(int(spikes_during_chunk)): + x = int(sgn <= 0) + input_spike_times[(i % no_input_cores) * npc_limit + x].append(ts) + +# Setup +p.setup(timestep=1.0) +p.set_number_of_neurons_per_core(p.SpikeSourcePoisson, 50) +p.set_number_of_neurons_per_core(p.SpikeSourceArray, npc_limit) +input_pop = p.Population(input_size, + p.SpikeSourceArray(spike_times=input_spike_times)) + +output_pop = p.Population(output_size, p.SpikeSourcePoisson(rate=0)) + +# Instantiate venv +icub_vor_env_model = gym.ICubVorEnv( + head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, + output_size) +icub_vor_env_pop = p.Population(ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) + +# Set recording for input and output pop (env pop records by default) +input_pop.record('spikes') +output_pop.record('spikes') + +# Input -> ICubVorEnv projection +i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) + +# ICubVorEnv -> output, setup live output to the SSP vertex +p.external_devices.activate_live_output_to( + icub_vor_env_pop, output_pop, "CONTROL") + +# Store simulator and run +simulator = get_simulator() +# Run the simulation +p.run(runtime) + +# Get the data from the ICubVorEnv pop +results = retrieve_and_package_results(icub_vor_env_pop, simulator) + +# get the spike data from input and output +spikes_in_spin = input_pop.spinnaker_get_data('spikes') +spikes_out_spin = output_pop.spinnaker_get_data('spikes') + +# end simulation +p.end() + +remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = remap_second_half_descending(spikes_out_spin, output_size) + +simulation_parameters = { + 'runtime': runtime, + 'error_window_size': error_window_size, + 'vn_spikes': remapped_vn_spikes, + 'cf_spikes': remapped_cf_spikes, + 'perfect_eye_pos': perfect_eye_pos, + 'perfect_eye_vel': perfect_eye_vel, + 'vn_size': input_size, + 'cf_size': output_size, + 'gain': gain +} + +# plot the data from the ICubVorEnv pop +plot_results(results_dict=results, simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_perfect") + +print("Done") From 9d8b612f60f2abffb9ca18d855c7d823d926e842 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 17 Jun 2022 13:59:02 +0100 Subject: [PATCH 28/54] Change spynnaker8 to pynn.spinnaker --- examples/icub_vor_env/icub_vor_env_test.py | 2 +- examples/icub_vor_env/icub_vor_env_test_200_inputs.py | 2 +- examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 1c0f8496..5e97e2ff 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import spynnaker8 as p +import pyNN.spiNNaker as p import spinn_gym as gym import matplotlib.pyplot as plt diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 064a12f9..2bc6f57b 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import spynnaker8 as p +import pyNN.spiNNaker as p import spinn_gym as gym # from pyNN.utility.plotting import Figure, Panel diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index bff484a3..5afebf80 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import spynnaker8 as p +import pyNN.spiNNaker as p import spinn_gym as gym # from pyNN.utility.plotting import Figure, Panel From 4031773cc589f738b2f7eeadfb4f703c9f2ae3df Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 11 Jul 2022 13:55:18 +0100 Subject: [PATCH 29/54] Update ICubVorEnv to use spinn_gym vertex classes --- spinn_gym/games/icub_vor_env/icub_vor_env.py | 241 +++--------------- .../icub_vor_env_machine_vertex.py | 63 ++--- spinn_gym/games/logic/logic.py | 2 +- 3 files changed, 54 insertions(+), 252 deletions(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 4f301942..09a0906e 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -16,96 +16,30 @@ import numpy from spinn_utilities.overrides import overrides -from spinn_utilities.config_holder import get_config_int from data_specification.enums.data_type import DataType -# PACMAN imports -# from pacman.executor.injection_decorator import inject_items -from pacman.model.constraints.key_allocator_constraints import \ - ContiguousKeyRangeContraint -from pacman.model.graphs.application.abstract import ( - AbstractOneAppOneMachineVertex) -from pacman.model.graphs.common import Slice -# from pacman.model.graphs.application import ApplicationVertex -# from pacman.model.resources.cpu_cycles_per_tick_resource import \ -# CPUCyclesPerTickResource -# from pacman.model.resources.dtcm_resource import DTCMResource -# from pacman.model.resources.resource_container import ResourceContainer -# from pacman.model.resources.variable_sdram import VariableSDRAM - -# from data_specification.enums.data_type import DataType - -# SpinnFrontEndCommon imports -from spinn_front_end_common.abstract_models import AbstractChangableAfterRun -# from spinn_front_end_common.interface.buffer_management \ -# import recording_utilities -# from spinn_front_end_common.abstract_models \ -# .abstract_generates_data_specification \ -# import AbstractGeneratesDataSpecification -from spinn_front_end_common.abstract_models. \ - abstract_provides_outgoing_partition_constraints import \ - AbstractProvidesOutgoingPartitionConstraints -# from spinn_front_end_common.utilities import globals_variables -# from spinn_front_end_common.interface.simulation import simulation_utilities from spinn_front_end_common.utilities import constants as \ front_end_common_constants -from spinn_front_end_common.utilities.exceptions import ConfigurationException -# sPyNNaker imports -from spynnaker.pyNN.models.abstract_models import \ - AbstractAcceptsIncomingSynapses -from spynnaker.pyNN.models.common import AbstractNeuronRecordable -# from spynnaker.pyNN.utilities import constants -from spynnaker.pyNN.models.common.simple_population_settable \ - import SimplePopulationSettable +from spinn_gym.games import SpinnGymApplicationVertex # ICubVorEnv imports from spinn_gym.games.icub_vor_env.icub_vor_env_machine_vertex \ import ICubVorEnvMachineVertex -NUMPY_DATA_ELEMENT_TYPE = numpy.double - # ---------------------------------------------------------------------------- # ICubVorEnv # ---------------------------------------------------------------------------- -class ICubVorEnv(AbstractOneAppOneMachineVertex, - AbstractProvidesOutgoingPartitionConstraints, - AbstractAcceptsIncomingSynapses, AbstractNeuronRecordable, - SimplePopulationSettable): - - @overrides(AbstractAcceptsIncomingSynapses.verify_splitter) - def verify_splitter(self, splitter): - # Need to ignore this verify - pass - - @overrides(AbstractAcceptsIncomingSynapses.get_connections_from_machine) - def get_connections_from_machine( - self, transceiver, placements, app_edge, synapse_info): - - # TODO: make this work properly (the following call does nothing) - - super(ICubVorEnv, self).get_connections_from_machine( - transceiver, placements, app_edge, synapse_info) - - def set_synapse_dynamics(self, synapse_dynamics): - pass - - def clear_connection_cache(self): - pass - - @overrides(AbstractAcceptsIncomingSynapses.get_synapse_id_by_target) - def get_synapse_id_by_target(self, target): - return 0 +class ICubVorEnv(SpinnGymApplicationVertex): - # key value - ICUB_VOR_ENV_REGION_BYTES = 4 - # error_window_size, output_size, number_of_inputs, gain, pos_to_vel, - # wta_decision, low_error_rate and high_error_rate - BASE_DATA_REGION_BYTES = 8 * 4 # not sure this is entirely necessary but keeping it for now MAX_SIM_DURATION = 10000 + RANDOM_SEED = [numpy.random.randint(10000), + numpy.random.randint(10000), + numpy.random.randint(10000), + numpy.random.randint(10000)] # Probably better ways of doing this too, but keeping it for now RECORDABLE_VARIABLES = [ "l_count", "r_count", "error", "eye_pos", "eye_vel"] @@ -113,35 +47,15 @@ def get_synapse_id_by_target(self, target): DataType.UINT32, DataType.UINT32, DataType.S1615, DataType.S1615, DataType.S1615] - # parameters expected by PyNN - default_parameters = { - 'error_window_size': 10, - # boosts the effect of individual spikes - 'gain': 20, - # magic multiplier to convert movement delta to speed - 'pos_to_vel': 1 / (0.001 * 2 * numpy.pi * 10), - 'wta_decision': False, - 'low_error_rate': 2, # Hz - 'high_error_rate': 20, # Hz - 'output_size': 200, # neurons encoding error via climbing fibres - 'constraints': None, - 'label': "ICubVorEnv", - 'incoming_spike_buffer_size': None, - 'duration': MAX_SIM_DURATION} + # magic multiplier to convert movement delta to speed + POS_TO_VEL = 1 / (0.001 * 2 * numpy.pi * 10) def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, - error_window_size=default_parameters['error_window_size'], - output_size=default_parameters['output_size'], - gain=default_parameters['gain'], - pos_to_vel=default_parameters['pos_to_vel'], - wta_decision=default_parameters['wta_decision'], - low_error_rate=default_parameters['low_error_rate'], - high_error_rate=default_parameters['high_error_rate'], - constraints=default_parameters['constraints'], - label=default_parameters['label'], - incoming_spike_buffer_size=default_parameters[ - 'incoming_spike_buffer_size'], - simulation_duration_ms=default_parameters['duration']): + error_window_size=10, output_size=200, gain=20, + pos_to_vel=POS_TO_VEL, wta_decision=False, low_error_rate=2, + high_error_rate=20, constraints=None, label="ICubVorEnv", + incoming_spike_buffer_size=None, + simulation_duration_ms=MAX_SIM_DURATION, random_seed=None): """ :param head_pos: array of head positions :param head_vel: array of head velocities @@ -160,24 +74,6 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, :param simulation_duration_ms: maximum simulation duration for this \ application vertex """ - # **NOTE** n_neurons currently ignored - width and height will be - # specified as additional parameters, forcing their product to be - # duplicated in n_neurons seems pointless - - self._label = label - - # Pass in variables - self._head_pos = head_pos - self._head_vel = head_vel - self._perfect_eye_pos = perfect_eye_pos - self._perfect_eye_vel = perfect_eye_vel - self._error_window_size = error_window_size - self._output_size = output_size - self._gain = gain - self._pos_to_vel = pos_to_vel - self._wta_decision = wta_decision - self._low_error_rate = low_error_rate - self._high_error_rate = high_error_rate self._number_of_inputs = len(perfect_eye_pos) if self._number_of_inputs != len(perfect_eye_vel): raise ConfigurationException( @@ -185,9 +81,12 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, "length of perfect_eye_vel {}".format( self._number_of_inputs, len(perfect_eye_vel))) + if random_seed is None: + random_seed = list(self.RANDOM_SEED) + # n_neurons is the number of atoms in the network, which in this # case only needs to be 2 (for receiving "left" and "right") - self._n_neurons = 2 + n_neurons = 2 # used to define size of recording region: # record variables every error_window_size ms (same size each time) @@ -204,92 +103,32 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, self._region_ids[self.RECORDABLE_VARIABLES[n]] = n self._region_dtypes[ self.RECORDABLE_VARIABLES[n]] = self.RECORDABLE_DTYPES[n] - self._m_vertex = None - resources_required = ( - self.ICUB_VOR_ENV_REGION_BYTES + self.BASE_DATA_REGION_BYTES + - self._recording_size) - - vertex_slice = Slice(0, self._n_neurons - 1) - # Superclasses - super(ICubVorEnv, self).__init__( - ICubVorEnvMachineVertex( - vertex_slice, resources_required, constraints, label, self, - head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, - error_window_size, output_size, gain, pos_to_vel, wta_decision, - low_error_rate, high_error_rate, incoming_spike_buffer_size, - simulation_duration_ms), - label=label, constraints=constraints) - - AbstractProvidesOutgoingPartitionConstraints.__init__(self) - SimplePopulationSettable.__init__(self) - AbstractChangableAfterRun.__init__(self) - AbstractAcceptsIncomingSynapses.__init__(self) - self._change_requires_mapping = True - if incoming_spike_buffer_size is None: - self._incoming_spike_buffer_size = get_config_int( - "Simulation", "incoming_spike_buffer_size") - - def neurons(self): - return self._n_neurons + machine_vertex = ICubVorEnvMachineVertex( + label, constraints, self, n_neurons, simulation_duration_ms, + random_seed, head_pos, head_vel, perfect_eye_pos, + perfect_eye_vel, error_window_size, output_size, gain, + pos_to_vel, wta_decision, low_error_rate, high_error_rate) - @property - @overrides(AbstractOneAppOneMachineVertex.n_atoms) - def n_atoms(self): - return self._n_neurons - - # ------------------------------------------------------------------------ - # AbstractProvidesOutgoingPartitionConstraints overrides - # ------------------------------------------------------------------------ - @overrides(AbstractProvidesOutgoingPartitionConstraints. - get_outgoing_partition_constraints) - def get_outgoing_partition_constraints(self, partition): - return [ContiguousKeyRangeContraint()] - - @property - @overrides(AbstractChangableAfterRun.requires_mapping) - def requires_mapping(self): - return self._change_requires_mapping - - @overrides(AbstractChangableAfterRun.mark_no_changes) - def mark_no_changes(self): - self._change_requires_mapping = False - - @overrides(SimplePopulationSettable.set_value) - def set_value(self, key, value): - SimplePopulationSettable.set_value(self, key, value) - self._change_requires_neuron_parameters_reload = True + super(ICubVorEnv, self).__init__( + machine_vertex, label, constraints, n_neurons) # ------------------------------------------------------------------------ # Recording overrides # ------------------------------------------------------------------------ - @overrides( - AbstractNeuronRecordable.clear_recording) + @overrides(SpinnGymApplicationVertex.clear_recording) def clear_recording( self, variable, buffer_manager, placements): for n in range(len(self.RECORDABLE_VARIABLES)): self._clear_recording_region(buffer_manager, placements, n) - @overrides(AbstractNeuronRecordable.get_recordable_variables) + @overrides(SpinnGymApplicationVertex.get_recordable_variables) def get_recordable_variables(self): return self.RECORDABLE_VARIABLES - @overrides(AbstractNeuronRecordable.is_recording) - def is_recording(self, variable): - return True - - @overrides(AbstractNeuronRecordable.set_recording) - def set_recording(self, variable, new_state=True, sampling_interval=None, - indexes=None): - pass - - @overrides(AbstractNeuronRecordable.get_neuron_sampling_interval) - def get_neuron_sampling_interval(self, variable): - return 10000 # 10 seconds hard coded in as sim duration... ? - - @overrides(AbstractNeuronRecordable.get_data) + @overrides(SpinnGymApplicationVertex.get_data) def get_data( self, variable, n_machine_time_steps, placements, buffer_manager): if self._m_vertex is None: @@ -323,25 +162,7 @@ def get_data( else: return output_data - def _clear_recording_region( - self, buffer_manager, placements, recording_region_id): - """ Clear a recorded data region from the buffer manager. - - :param buffer_manager: the buffer manager object - :param placements: the placements object - :param recording_region_id: the recorded region ID for clearing - :rtype: None - """ - for machine_vertex in self.machine_vertices: - placement = placements.get_placement_of_vertex(machine_vertex) - buffer_manager.clear_recorded_data( - placement.x, placement.y, placement.p, recording_region_id) - - def reset_ring_buffer_shifts(self): - pass - - def __str__(self): - return "{} with {} atoms".format(self._label, self.n_atoms) - - def __repr__(self): - return self.__str__() + @property + @overrides(SpinnGymApplicationVertex.score_format) + def score_format(self): + return numpy.int32 diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 6a0ebc0f..09e995f1 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -22,16 +22,12 @@ # PACMAN imports from pacman.executor.injection_decorator import inject_items -from pacman.model.graphs.machine import MachineVertex from pacman.model.resources import ConstantSDRAM, ResourceContainer # SpinnFrontEndCommon imports from spinn_front_end_common.utilities import helpful_functions -from spinn_front_end_common.interface.buffer_management.buffer_models import \ - AbstractReceiveBuffersToHost from spinn_front_end_common.abstract_models.abstract_has_associated_binary \ import AbstractHasAssociatedBinary -from spinn_front_end_common.utilities.utility_objs import ExecutableType from spinn_front_end_common.interface.buffer_management \ import recording_utilities from spinn_front_end_common.abstract_models \ @@ -45,14 +41,14 @@ # sPyNNaker imports from spynnaker.pyNN.utilities import constants +# spinn_gym imports +from spinn_gym.games.spinn_gym_machine_vertex import SpinnGymMachineVertex + # ---------------------------------------------------------------------------- # ICubVorEnvMachineVertex # ---------------------------------------------------------------------------- -class ICubVorEnvMachineVertex(MachineVertex, - AbstractGeneratesDataSpecification, - AbstractReceiveBuffersToHost, - AbstractHasAssociatedBinary): +class ICubVorEnvMachineVertex(SpinnGymMachineVertex): ICUB_VOR_ENV_REGION_BYTES = 4 BASE_DATA_REGION_BYTES = 9 * 4 # Probably better ways of doing this too, but keeping it for now @@ -69,17 +65,16 @@ class ICubVorEnvMachineVertex(MachineVertex, ('RECORDING', 2), ('DATA', 3)]) - def __init__(self, vertex_slice, resources_required, constraints, label, - app_vertex, head_pos, head_vel, perfect_eye_pos, + def __init__(self, label, constraints, app_vertex, n_neurons, + simulation_duration_ms, random_seed, + head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size, output_size, gain, - pos_to_vel, wta_decision, low_error_rate, high_error_rate, - incoming_spike_buffer_size, simulation_duration_ms): - - # resources required - self._resources_required = ResourceContainer( - sdram=ConstantSDRAM(resources_required)) + pos_to_vel, wta_decision, low_error_rate, high_error_rate): - self._label = label + super(ICubVorEnvMachineVertex, self).__init__( + label, constraints, app_vertex, n_neurons, + self.ICUB_VOR_ENV_REGION_BYTES + self.BASE_DATA_REGION_BYTES, + simulation_duration_ms, random_seed) # pass in variables self._head_pos = head_pos @@ -99,15 +94,20 @@ def __init__(self, vertex_slice, resources_required, constraints, label, "The length of perfect_eye_pos {} is not the same as the " "length of perfect_eye_vel {}".format( self._number_of_inputs, len(perfect_eye_vel))) - self._n_recordable_variables = len(self.RECORDABLE_VARIABLES) self._recording_size = int((simulation_duration_ms / error_window_size) * front_end_common_constants.BYTES_PER_WORD) - # Superclasses - MachineVertex.__init__( - self, label, constraints, app_vertex, vertex_slice) + self._resources_required = ResourceContainer( + sdram=ConstantSDRAM( + self.ICUB_VOR_ENV_REGION_BYTES + self.BASE_DATA_REGION_BYTES + + self._recording_size)) + + @property + @overrides(SpinnGymMachineVertex.resources_required) + def resources_required(self): + return self._resources_required # ------------------------------------------------------------------------ # AbstractGeneratesDataSpecification overrides @@ -198,13 +198,7 @@ def __round_to_nearest_accum(self, x): x_approx = numpy.floor((x / eps) + 0.5) * eps return x_approx - @property - def resources_required(self): - return self._resources_required - - def get_minimum_buffer_sdram_usage(self): - return 0 # probably should make this a user input - + @overrides(SpinnGymMachineVertex.get_recorded_region_ids) def get_recorded_region_ids(self): return [0, 1, 2, 3, 4] @@ -212,19 +206,6 @@ def get_recording_region_base_address(self, txrx, placement): return helpful_functions.locate_memory_region_for_placement( placement, self._ICUB_VOR_ENV_REGIONS.RECORDING.value, txrx) - def get_n_keys_for_partition(self, partition): - n_keys = 0 - # The way this has been written, there should only be one edge, but - # better to be safe than sorry - for edge in partition.edges: - if edge.pre_vertex is not edge.post_vertex: - n_keys += edge.post_vertex.get_n_keys_for_partition(partition) - return n_keys - @overrides(AbstractHasAssociatedBinary.get_binary_file_name) def get_binary_file_name(self): return "icub_vor_env.aplx" - - @overrides(AbstractHasAssociatedBinary.get_binary_start_type) - def get_binary_start_type(self): - return ExecutableType.USES_SIMULATION_INTERFACE diff --git a/spinn_gym/games/logic/logic.py b/spinn_gym/games/logic/logic.py index b1b3f614..a6431807 100644 --- a/spinn_gym/games/logic/logic.py +++ b/spinn_gym/games/logic/logic.py @@ -46,7 +46,7 @@ class Logic(SpinnGymApplicationVertex): def __init__( self, truth_table, input_sequence, rate_on=20.0, rate_off=5.0, score_delay=200.0, stochastic=1, constraints=None, label="Logic", - simulation_duration_ms=ONE_DAY_IN_MS, random_seed=None): + simulation_duration_ms=ONE_DAY_IN_MS, random_seed=None): if random_seed is None: random_seed = list(self.RANDOM_SEED) From 51231dc9733581fed58bc8a5c098fb186eeec4a0 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 11 Jul 2022 14:08:02 +0100 Subject: [PATCH 30/54] Put this import back in --- spinn_gym/games/icub_vor_env/icub_vor_env.py | 1 + 1 file changed, 1 insertion(+) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 09a0906e..8de5d4ee 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -21,6 +21,7 @@ from spinn_front_end_common.utilities import constants as \ front_end_common_constants +from spinn_front_end_common.utilities.exceptions import ConfigurationException from spinn_gym.games import SpinnGymApplicationVertex From 04ca3aef6564e1ec74188af5351d2b36f6fae0a8 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 22 Jul 2022 11:44:33 +0100 Subject: [PATCH 31/54] match function arguments --- spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index f8cd8f3f..094f6967 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -113,7 +113,7 @@ def resources_required(self): # AbstractGeneratesDataSpecification overrides # ------------------------------------------------------------------------ @overrides(AbstractGeneratesDataSpecification.generate_data_specification) - def generate_data_specification(self, spec, placement, routing_info): + def generate_data_specification(self, spec, placement): vertex = placement.vertex spec.comment("\n*** Spec for ICubVorEnv Instance ***\n\n") From 57e479b6ca71b72fb032b056d28f973ea1b26b47 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 22 Jul 2022 12:16:04 +0100 Subject: [PATCH 32/54] Update ICubVorEnv vertices to match downstream changes --- examples/icub_vor_env/icub_utilities.py | 49 +++++++------------ examples/icub_vor_env/icub_vor_env_test.py | 44 ++++++----------- .../icub_vor_env_test_200_inputs.py | 5 +- .../icub_vor_venv_test_perfect_motion.py | 5 +- spinn_gym/games/icub_vor_env/icub_vor_env.py | 13 ++--- .../icub_vor_env_machine_vertex.py | 4 +- .../games/spinn_gym_application_vertex.py | 9 ++-- 7 files changed, 48 insertions(+), 81 deletions(-) diff --git a/examples/icub_vor_env/icub_utilities.py b/examples/icub_vor_env/icub_utilities.py index 6648ac8f..178220aa 100644 --- a/examples/icub_vor_env/icub_utilities.py +++ b/examples/icub_vor_env/icub_utilities.py @@ -33,43 +33,33 @@ # Examples of get functions for variables -def get_error(icub_vor_env_pop, simulator): +def get_error(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - error = b_vertex.get_data( - 'error', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + error = b_vertex.get_data('error') return error.tolist() -def get_l_count(icub_vor_env_pop, simulator): +def get_l_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - left_count = b_vertex.get_data( - 'l_count', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + left_count = b_vertex.get_data('l_count') return left_count.tolist() -def get_r_count(icub_vor_env_pop, simulator): +def get_r_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - right_count = b_vertex.get_data( - 'r_count', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + right_count = b_vertex.get_data('r_count') return right_count.tolist() -def get_eye_pos(icub_vor_env_pop, simulator): +def get_eye_pos(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_positions = b_vertex.get_data( - 'eye_pos', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + eye_positions = b_vertex.get_data('eye_pos') return eye_positions.tolist() -def get_eye_vel(icub_vor_env_pop, simulator): +def get_eye_vel(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_velocities = b_vertex.get_data( - 'eye_vel', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + eye_velocities = b_vertex.get_data('eye_vel') return eye_velocities.tolist() @@ -80,18 +70,15 @@ def generate_head_position_and_velocity(time, dt=0.001): return pos, vel -def retrieve_and_package_results(icub_vor_env_pop, simulator): +def retrieve_and_package_results(icub_vor_env_pop): # Get the data from the ICubVorEnv pop - errors = np.asarray(get_error( - icub_vor_env_pop=icub_vor_env_pop, simulator=simulator)).ravel() - l_counts = get_l_count(icub_vor_env_pop=icub_vor_env_pop, - simulator=simulator) - r_counts = get_r_count(icub_vor_env_pop=icub_vor_env_pop, - simulator=simulator) - rec_eye_pos = np.asarray(get_eye_pos( - icub_vor_env_pop=icub_vor_env_pop, simulator=simulator)).ravel() - rec_eye_vel = np.asarray(get_eye_vel( - icub_vor_env_pop=icub_vor_env_pop, simulator=simulator)).ravel() + errors = np.asarray(get_error(icub_vor_env_pop=icub_vor_env_pop)).ravel() + l_counts = get_l_count(icub_vor_env_pop=icub_vor_env_pop) + r_counts = get_r_count(icub_vor_env_pop=icub_vor_env_pop) + rec_eye_pos = np.asarray( + get_eye_pos(icub_vor_env_pop=icub_vor_env_pop)).ravel() + rec_eye_vel = np.asarray( + get_eye_vel(icub_vor_env_pop=icub_vor_env_pop)).ravel() results = { 'errors': errors, 'l_counts': l_counts, diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 5e97e2ff..eff4db27 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -19,47 +19,36 @@ import matplotlib.pyplot as plt import numpy as np import os -from spinn_front_end_common.utilities.globals_variables import get_simulator # Examples of get functions for variables -def get_error(icub_vor_env_pop, simulator): +def get_error(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - error = b_vertex.get_data( - 'error', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + error = b_vertex.get_data('error') return error.tolist() -def get_l_count(icub_vor_env_pop, simulator): +def get_l_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - left_count = b_vertex.get_data( - 'l_count', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + left_count = b_vertex.get_data('l_count') return left_count.tolist() -def get_r_count(icub_vor_env_pop, simulator): +def get_r_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - right_count = b_vertex.get_data( - 'r_count', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + right_count = b_vertex.get_data('r_count') return right_count.tolist() -def get_eye_pos(icub_vor_env_pop, simulator): +def get_eye_pos(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_positions = b_vertex.get_data( - 'eye_pos', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + eye_positions = b_vertex.get_data('eye_pos') return eye_positions.tolist() -def get_eye_vel(icub_vor_env_pop, simulator): +def get_eye_vel(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_velocities = b_vertex.get_data( - 'eye_vel', simulator.no_machine_time_steps, simulator.placements, - simulator.buffer_manager) + eye_velocities = b_vertex.get_data('eye_vel') return eye_velocities.tolist() @@ -120,18 +109,15 @@ def get_eye_vel(icub_vor_env_pop, simulator): icub_vor_env_pop, output_pop, "CONTROL") # Store simulator and run -simulator = get_simulator() runtime = 10000 p.run(runtime) # Get the data from the ICubVorEnv pop -errors = get_error(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) -l_counts = get_l_count(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) -r_counts = get_r_count(icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) -rec_eye_pos = get_eye_pos( - icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) -rec_eye_vel = get_eye_vel( - icub_vor_env_pop=icub_vor_env_pop, simulator=simulator) +errors = get_error(icub_vor_env_pop=icub_vor_env_pop) +l_counts = get_l_count(icub_vor_env_pop=icub_vor_env_pop) +r_counts = get_r_count(icub_vor_env_pop=icub_vor_env_pop) +rec_eye_pos = get_eye_pos(icub_vor_env_pop=icub_vor_env_pop) +rec_eye_vel = get_eye_vel(icub_vor_env_pop=icub_vor_env_pop) # get the spike data from input and output and plot # spikes_in = input_pop.get_data('spikes').segments[0].spiketrains diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 2bc6f57b..750d4aa2 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -20,7 +20,6 @@ # import matplotlib.pyplot as plt import numpy as np # import os -from spinn_front_end_common.utilities.globals_variables import get_simulator from icub_utilities import ( generate_head_position_and_velocity, retrieve_and_package_results, remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, @@ -81,13 +80,11 @@ p.external_devices.activate_live_output_to( icub_vor_env_pop, output_pop, "CONTROL") -# Store simulator and run -simulator = get_simulator() # Run the simulation p.run(runtime) # Get the data from the ICubVorEnv pop -results = retrieve_and_package_results(icub_vor_env_pop, simulator) +results = retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index 5afebf80..04f6fc56 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -20,7 +20,6 @@ # import matplotlib.pyplot as plt import numpy as np # import os -from spinn_front_end_common.utilities.globals_variables import get_simulator from icub_utilities import ( generate_head_position_and_velocity, retrieve_and_package_results, remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, @@ -94,13 +93,11 @@ p.external_devices.activate_live_output_to( icub_vor_env_pop, output_pop, "CONTROL") -# Store simulator and run -simulator = get_simulator() # Run the simulation p.run(runtime) # Get the data from the ICubVorEnv pop -results = retrieve_and_package_results(icub_vor_env_pop, simulator) +results = retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 8de5d4ee..69872cd8 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -23,6 +23,8 @@ front_end_common_constants from spinn_front_end_common.utilities.exceptions import ConfigurationException +from spynnaker.pyNN.data import SpynnakerDataView + from spinn_gym.games import SpinnGymApplicationVertex # ICubVorEnv imports @@ -120,23 +122,22 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, # Recording overrides # ------------------------------------------------------------------------ @overrides(SpinnGymApplicationVertex.clear_recording) - def clear_recording( - self, variable, buffer_manager, placements): + def clear_recording(self, variable): for n in range(len(self.RECORDABLE_VARIABLES)): - self._clear_recording_region(buffer_manager, placements, n) + self._clear_recording_region(n) @overrides(SpinnGymApplicationVertex.get_recordable_variables) def get_recordable_variables(self): return self.RECORDABLE_VARIABLES @overrides(SpinnGymApplicationVertex.get_data) - def get_data( - self, variable, n_machine_time_steps, placements, buffer_manager): + def get_data(self, variable): if self._m_vertex is None: self._m_vertex = self.machine_vertices.pop() print('get_data from machine vertex ', self._m_vertex, ' for variable ', variable) - placement = placements.get_placement_of_vertex(self._m_vertex) + placement = SpynnakerDataView.get_placement_of_vertex(self._m_vertex) + buffer_manager = SpynnakerDataView.get_buffer_manager() # Read the data recorded data_values, _ = buffer_manager.get_data_by_placement( diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 094f6967..651e4adc 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -200,9 +200,9 @@ def __round_to_nearest_accum(self, x): def get_recorded_region_ids(self): return [0, 1, 2, 3, 4] - def get_recording_region_base_address(self, txrx, placement): + def get_recording_region_base_address(self, placement): return helpful_functions.locate_memory_region_for_placement( - placement, self._ICUB_VOR_ENV_REGIONS.RECORDING.value, txrx) + placement, self._ICUB_VOR_ENV_REGIONS.RECORDING.value) @overrides(AbstractHasAssociatedBinary.get_binary_file_name) def get_binary_file_name(self): diff --git a/spinn_gym/games/spinn_gym_application_vertex.py b/spinn_gym/games/spinn_gym_application_vertex.py index 68827ab1..2a650949 100644 --- a/spinn_gym/games/spinn_gym_application_vertex.py +++ b/spinn_gym/games/spinn_gym_application_vertex.py @@ -159,17 +159,16 @@ def get_data(self, variable): # return formatted_data return output_data - def _clear_recording_region( - self, buffer_manager, placements, recording_region_id): + def _clear_recording_region(self, recording_region_id): """ Clear a recorded data region from the buffer manager. - :param buffer_manager: the buffer manager object - :param placements: the placements object :param recording_region_id: the recorded region ID for clearing :rtype: None """ for machine_vertex in self.machine_vertices: - placement = placements.get_placement_of_vertex(machine_vertex) + placement = SpynnakerDataView.get_placement_of_vertex( + machine_vertex) + buffer_manager = SpynnakerDataView.get_buffer_manager() buffer_manager.clear_recorded_data( placement.x, placement.y, placement.p, recording_region_id) From 0ee23e951e2d6489415f6c4d5847e5c9db8e92d3 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 25 Jul 2022 12:18:08 +0100 Subject: [PATCH 33/54] do flake8 on integration tests and unittests too --- .github/workflows/python_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_actions.yml b/.github/workflows/python_actions.yml index 22d387f4..8610c138 100644 --- a/.github/workflows/python_actions.yml +++ b/.github/workflows/python_actions.yml @@ -65,7 +65,7 @@ jobs: coveralls-token: ${{ secrets.COVERALLS_REPO_TOKEN }} - name: Lint with flake8 - run: flake8 examples spinn_gym + run: flake8 examples spinn_gym integration_tests unittests - name: Lint with pylint uses: ./support/actions/pylint with: From 76e1da2a06bf01b733e84f6b145cfda67651b016 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Tue, 26 Jul 2022 12:55:37 +0100 Subject: [PATCH 34/54] Rename --- examples/icub_vor_env/spynnaker.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/icub_vor_env/spynnaker.cfg b/examples/icub_vor_env/spynnaker.cfg index 8bbf7d2f..c75c989f 100644 --- a/examples/icub_vor_env/spynnaker.cfg +++ b/examples/icub_vor_env/spynnaker.cfg @@ -1,4 +1,3 @@ [Mapping] - -# Logic doesn't implement delay extensions, so avoid DelaySupportAdder +# ICubVor doesn't implement delay extensions, so avoid DelaySupportAdder delay_support_adder = None \ No newline at end of file From f6080799f4790a18461277b161e9318aec2bc82b Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 29 Jul 2022 13:35:31 +0100 Subject: [PATCH 35/54] Get the number of keys needed for the ICub vertex correct --- .../icub_vor_env_machine_vertex.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 651e4adc..fe2c7ce1 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -207,3 +207,24 @@ def get_recording_region_base_address(self, placement): @overrides(AbstractHasAssociatedBinary.get_binary_file_name) def get_binary_file_name(self): return "icub_vor_env.aplx" + + @overrides(SpinnGymMachineVertex.get_n_keys_for_partition) + def get_n_keys_for_partition(self, partition_id): + # If the vertex is controlling another vertex then the number of + # keys needed is related to that vertex! + if partition_id == constants.LIVE_POISSON_CONTROL_PARTITION_ID: + partitions = SpynnakerDataView.\ + get_outgoing_edge_partitions_starting_at_vertex( + self.app_vertex) + n_keys = 0 + for partition in partitions: + if partition.identifier == partition_id: + for edge in partition.edges: + if edge.pre_vertex is not edge.post_vertex: + for m_vert in edge.post_vertex.machine_vertices: + n_keys += ( + m_vert.get_n_keys_for_partition( + partition)) + return n_keys + else: + return MachineVertex.get_n_keys_for_partition(partition_id) From 335ee9576a8ffd68296158cae4636ad95da22b50 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 29 Jul 2022 13:41:00 +0100 Subject: [PATCH 36/54] flake8 missed import --- spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index fe2c7ce1..904f6845 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -22,6 +22,7 @@ # PACMAN imports from pacman.model.resources import ConstantSDRAM, ResourceContainer +from pacman.model.graphs.machine import MachineVertex # SpinnFrontEndCommon imports from spinn_front_end_common.utilities import helpful_functions @@ -208,7 +209,7 @@ def get_recording_region_base_address(self, placement): def get_binary_file_name(self): return "icub_vor_env.aplx" - @overrides(SpinnGymMachineVertex.get_n_keys_for_partition) + @overrides(MachineVertex.get_n_keys_for_partition) def get_n_keys_for_partition(self, partition_id): # If the vertex is controlling another vertex then the number of # keys needed is related to that vertex! From f2f0eb31d5cc96f8197eec898cb9456bb03b4319 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 29 Jul 2022 13:55:03 +0100 Subject: [PATCH 37/54] Better call for super() method --- spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 904f6845..8b05d8db 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -228,4 +228,6 @@ def get_n_keys_for_partition(self, partition_id): partition)) return n_keys else: - return MachineVertex.get_n_keys_for_partition(partition_id) + return ( + super(ICubVorEnvMachineVertex, self).get_n_keys_for_partition( + partition_id)) From f0920030276140738a0809cf9be0f33bf9cb73a9 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 4 Aug 2022 11:41:39 +0100 Subject: [PATCH 38/54] Match downstream changes --- .../icub_vor_env/icub_vor_env_machine_vertex.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index 8b05d8db..b9e4a8d2 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -21,7 +21,7 @@ from data_specification.enums.data_type import DataType # PACMAN imports -from pacman.model.resources import ConstantSDRAM, ResourceContainer +from pacman.model.resources import ConstantSDRAM from pacman.model.graphs.machine import MachineVertex # SpinnFrontEndCommon imports @@ -100,15 +100,14 @@ def __init__(self, label, constraints, app_vertex, n_neurons, self._recording_size = int((simulation_duration_ms / error_window_size) * front_end_common_constants.BYTES_PER_WORD) - self._resources_required = ResourceContainer( - sdram=ConstantSDRAM( - self.ICUB_VOR_ENV_REGION_BYTES + self.BASE_DATA_REGION_BYTES + - self._recording_size)) + self._sdram_required = ConstantSDRAM( + self.ICUB_VOR_ENV_REGION_BYTES + self.BASE_DATA_REGION_BYTES + + self._recording_size) @property - @overrides(SpinnGymMachineVertex.resources_required) - def resources_required(self): - return self._resources_required + @overrides(SpinnGymMachineVertex.sdram_required) + def sdram_required(self): + return self._sdram_required # ------------------------------------------------------------------------ # AbstractGeneratesDataSpecification overrides From f56ff93257146f15df92a8abe45268104a60e4ec Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 17 Nov 2022 16:50:41 +0000 Subject: [PATCH 39/54] Update ICubVorEnv to match changes elsewhere --- examples/icub_vor_env/icub_utilities.py | 10 ++--- examples/icub_vor_env/icub_vor_env_test.py | 13 ++++--- .../icub_vor_env_test_200_inputs.py | 3 +- .../icub_vor_venv_test_perfect_motion.py | 3 +- spinn_gym/games/icub_vor_env/icub_vor_env.py | 39 +++++++++++-------- .../icub_vor_env_machine_vertex.py | 4 +- 6 files changed, 41 insertions(+), 31 deletions(-) diff --git a/examples/icub_vor_env/icub_utilities.py b/examples/icub_vor_env/icub_utilities.py index 178220aa..00052e1c 100644 --- a/examples/icub_vor_env/icub_utilities.py +++ b/examples/icub_vor_env/icub_utilities.py @@ -35,31 +35,31 @@ # Examples of get functions for variables def get_error(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - error = b_vertex.get_data('error') + error = b_vertex.get_recorded_data('error') return error.tolist() def get_l_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - left_count = b_vertex.get_data('l_count') + left_count = b_vertex.get_recorded_data('l_count') return left_count.tolist() def get_r_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - right_count = b_vertex.get_data('r_count') + right_count = b_vertex.get_recorded_data('r_count') return right_count.tolist() def get_eye_pos(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_positions = b_vertex.get_data('eye_pos') + eye_positions = b_vertex.get_recorded_data('eye_pos') return eye_positions.tolist() def get_eye_vel(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_velocities = b_vertex.get_data('eye_vel') + eye_velocities = b_vertex.get_recorded_data('eye_vel') return eye_velocities.tolist() diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index eff4db27..2713ca93 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -24,31 +24,31 @@ # Examples of get functions for variables def get_error(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - error = b_vertex.get_data('error') + error = b_vertex.get_recorded_data('error') return error.tolist() def get_l_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - left_count = b_vertex.get_data('l_count') + left_count = b_vertex.get_recorded_data('l_count') return left_count.tolist() def get_r_count(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - right_count = b_vertex.get_data('r_count') + right_count = b_vertex.get_recorded_data('r_count') return right_count.tolist() def get_eye_pos(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_positions = b_vertex.get_data('eye_pos') + eye_positions = b_vertex.get_recorded_data('eye_pos') return eye_positions.tolist() def get_eye_vel(icub_vor_env_pop): b_vertex = icub_vor_env_pop._vertex - eye_velocities = b_vertex.get_data('eye_vel') + eye_velocities = b_vertex.get_recorded_data('eye_vel') return eye_velocities.tolist() @@ -102,7 +102,8 @@ def get_eye_vel(icub_vor_env_pop): output_pop.record('spikes') # Input -> ICubVorEnv projection -i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) +# i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) +p.external_devices.activate_live_output_to(input_pop, icub_vor_env_pop) # ICubVorEnv -> output, setup live output to the SSP vertex p.external_devices.activate_live_output_to( diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 750d4aa2..945f55da 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -74,7 +74,8 @@ output_pop.record('spikes') # Input -> ICubVorEnv projection -i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) +# i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) +p.external_devices.activate_live_output_to(input_pop, icub_vor_env_pop) # ICubVorEnv -> output, setup live output to the SSP vertex p.external_devices.activate_live_output_to( diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index 04f6fc56..c7a66286 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -87,7 +87,8 @@ output_pop.record('spikes') # Input -> ICubVorEnv projection -i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) +# i2a = p.Projection(input_pop, icub_vor_env_pop, p.AllToAllConnector()) +p.external_devices.activate_live_output_to(input_pop, icub_vor_env_pop) # ICubVorEnv -> output, setup live output to the SSP vertex p.external_devices.activate_live_output_to( diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 69872cd8..eacabed4 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -56,7 +56,7 @@ class ICubVorEnv(SpinnGymApplicationVertex): def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size=10, output_size=200, gain=20, pos_to_vel=POS_TO_VEL, wta_decision=False, low_error_rate=2, - high_error_rate=20, constraints=None, label="ICubVorEnv", + high_error_rate=20, label="ICubVorEnv", incoming_spike_buffer_size=None, simulation_duration_ms=MAX_SIM_DURATION, random_seed=None): """ @@ -110,50 +110,57 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, # Superclasses machine_vertex = ICubVorEnvMachineVertex( - label, constraints, self, n_neurons, simulation_duration_ms, + label, self, n_neurons, simulation_duration_ms, random_seed, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size, output_size, gain, pos_to_vel, wta_decision, low_error_rate, high_error_rate) super(ICubVorEnv, self).__init__( - machine_vertex, label, constraints, n_neurons) + machine_vertex, label, n_neurons) # ------------------------------------------------------------------------ # Recording overrides # ------------------------------------------------------------------------ - @overrides(SpinnGymApplicationVertex.clear_recording) - def clear_recording(self, variable): - for n in range(len(self.RECORDABLE_VARIABLES)): - self._clear_recording_region(n) + @overrides(SpinnGymApplicationVertex.clear_recording_data) + def clear_recording_data(self, name): + if name not in self.RECORDABLE_VARIABLES: + raise KeyError(f"Cannot clear recording for {name}") + for machine_vertex in self.machine_vertices: + placement = SpynnakerDataView.get_placement_of_vertex( + machine_vertex) + buffer_manager = SpynnakerDataView.get_buffer_manager() + buffer_manager.clear_recorded_data( + placement.x, placement.y, placement.p, + self.RECORDABLE_VARIABLES.index(name)) @overrides(SpinnGymApplicationVertex.get_recordable_variables) def get_recordable_variables(self): return self.RECORDABLE_VARIABLES - @overrides(SpinnGymApplicationVertex.get_data) - def get_data(self, variable): + @overrides(SpinnGymApplicationVertex.get_recorded_data) + def get_recorded_data(self, name): if self._m_vertex is None: self._m_vertex = self.machine_vertices.pop() print('get_data from machine vertex ', self._m_vertex, - ' for variable ', variable) + ' for variable ', name) placement = SpynnakerDataView.get_placement_of_vertex(self._m_vertex) buffer_manager = SpynnakerDataView.get_buffer_manager() # Read the data recorded data_values, _ = buffer_manager.get_data_by_placement( - placement, self._region_ids[variable]) + placement, self._region_ids[name]) data = data_values numpy_format = list() output_format = list() - if self._region_dtypes[variable] is DataType.S1615: - numpy_format.append((variable, numpy.int32)) - output_format.append((variable, numpy.float32)) + if self._region_dtypes[name] is DataType.S1615: + numpy_format.append((name, numpy.int32)) + output_format.append((name, numpy.float32)) else: - numpy_format.append((variable, numpy.int32)) + numpy_format.append((name, numpy.int32)) output_data = numpy.array(data, dtype=numpy.uint8).view(numpy_format) - if self._region_dtypes[variable] is DataType.S1615: + if self._region_dtypes[name] is DataType.S1615: convert = numpy.zeros_like( output_data, dtype=numpy.float32).view(output_format) for i in range(output_data.size): diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index b9e4a8d2..c2316b2a 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -66,14 +66,14 @@ class ICubVorEnvMachineVertex(SpinnGymMachineVertex): ('RECORDING', 2), ('DATA', 3)]) - def __init__(self, label, constraints, app_vertex, n_neurons, + def __init__(self, label, app_vertex, n_neurons, simulation_duration_ms, random_seed, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size, output_size, gain, pos_to_vel, wta_decision, low_error_rate, high_error_rate): super(ICubVorEnvMachineVertex, self).__init__( - label, constraints, app_vertex, n_neurons, + label, app_vertex, n_neurons, self.ICUB_VOR_ENV_REGION_BYTES + self.BASE_DATA_REGION_BYTES, simulation_duration_ms, random_seed) From 06dee5a349d3d16da79a563ce2b691da92a5c279 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 12 Jan 2023 17:14:26 +0000 Subject: [PATCH 40/54] Removing unused parameter found by pylint --- spinn_gym/games/icub_vor_env/icub_vor_env.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index eacabed4..8f77944e 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -57,7 +57,6 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, error_window_size=10, output_size=200, gain=20, pos_to_vel=POS_TO_VEL, wta_decision=False, low_error_rate=2, high_error_rate=20, label="ICubVorEnv", - incoming_spike_buffer_size=None, simulation_duration_ms=MAX_SIM_DURATION, random_seed=None): """ :param head_pos: array of head positions @@ -73,7 +72,6 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, difference in number of spikes between L and R :param constraints: usual sPyNNaker constraints :param label: name of the population - :param incoming_spike_buffer_size: :param simulation_duration_ms: maximum simulation duration for this \ application vertex """ From 56d98f4a1e04bbd8068bafead14fdf8be34072c3 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 26 Jun 2023 10:04:47 +0100 Subject: [PATCH 41/54] DataType has moved --- spinn_gym/games/icub_vor_env/icub_vor_env.py | 3 +-- spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 7c814ce9..49421117 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -17,8 +17,7 @@ from spinn_utilities.overrides import overrides -from data_specification.enums.data_type import DataType - +from spinn_front_end_common.interface.ds import DataType from spinn_front_end_common.utilities import constants as \ front_end_common_constants from spinn_front_end_common.utilities.exceptions import ConfigurationException diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py index c2316b2a..cf48b546 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env_machine_vertex.py @@ -18,13 +18,12 @@ from spinn_utilities.overrides import overrides -from data_specification.enums.data_type import DataType - # PACMAN imports from pacman.model.resources import ConstantSDRAM from pacman.model.graphs.machine import MachineVertex # SpinnFrontEndCommon imports +from spinn_front_end_common.interface.ds import DataType from spinn_front_end_common.utilities import helpful_functions from spinn_front_end_common.abstract_models.abstract_has_associated_binary \ import AbstractHasAssociatedBinary From 75c9e04569f2aabb45889e34ebb503558d625074 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 30 Jun 2023 14:52:20 +0100 Subject: [PATCH 42/54] Move icub utilities from examples --- examples/icub_vor_env/icub_vor_env_test_200_inputs.py | 2 +- examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py | 2 +- {examples => spinn_gym/games}/icub_vor_env/icub_utilities.py | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {examples => spinn_gym/games}/icub_vor_env/icub_utilities.py (100%) diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 945f55da..7c4455af 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -20,7 +20,7 @@ # import matplotlib.pyplot as plt import numpy as np # import os -from icub_utilities import ( +from spinn_gym.games.icub_vor_env.icub_utilities import ( generate_head_position_and_velocity, retrieve_and_package_results, remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, plot_results) diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index c7a66286..6c430492 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -20,7 +20,7 @@ # import matplotlib.pyplot as plt import numpy as np # import os -from icub_utilities import ( +from spinn_gym.games.icub_vor_env.icub_utilities import ( generate_head_position_and_velocity, retrieve_and_package_results, remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, plot_results) diff --git a/examples/icub_vor_env/icub_utilities.py b/spinn_gym/games/icub_vor_env/icub_utilities.py similarity index 100% rename from examples/icub_vor_env/icub_utilities.py rename to spinn_gym/games/icub_vor_env/icub_utilities.py From c7a1e60a98e9351d377639f0b2d5936453ea08b4 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 30 Jun 2023 15:04:31 +0100 Subject: [PATCH 43/54] Move icub utilities back to examples --- {spinn_gym/games => examples}/icub_vor_env/icub_utilities.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {spinn_gym/games => examples}/icub_vor_env/icub_utilities.py (100%) diff --git a/spinn_gym/games/icub_vor_env/icub_utilities.py b/examples/icub_vor_env/icub_utilities.py similarity index 100% rename from spinn_gym/games/icub_vor_env/icub_utilities.py rename to examples/icub_vor_env/icub_utilities.py From c1e6386be0ccd850cae0b8f53abb47c1f45848e8 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 30 Jun 2023 15:06:58 +0100 Subject: [PATCH 44/54] Fix imports and add init file --- examples/icub_vor_env/__init__.py | 14 ++++++++++++++ .../icub_vor_env/icub_vor_env_test_200_inputs.py | 2 +- .../icub_vor_venv_test_perfect_motion.py | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 examples/icub_vor_env/__init__.py diff --git a/examples/icub_vor_env/__init__.py b/examples/icub_vor_env/__init__.py new file mode 100644 index 00000000..f3d2ab9a --- /dev/null +++ b/examples/icub_vor_env/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 7c4455af..945f55da 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -20,7 +20,7 @@ # import matplotlib.pyplot as plt import numpy as np # import os -from spinn_gym.games.icub_vor_env.icub_utilities import ( +from icub_utilities import ( generate_head_position_and_velocity, retrieve_and_package_results, remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, plot_results) diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index 6c430492..c7a66286 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -20,7 +20,7 @@ # import matplotlib.pyplot as plt import numpy as np # import os -from spinn_gym.games.icub_vor_env.icub_utilities import ( +from icub_utilities import ( generate_head_position_and_velocity, retrieve_and_package_results, remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, plot_results) From b42f31071d1ed4f5fc0637494bcaa6547a10a7fd Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 3 Jul 2023 09:16:19 +0100 Subject: [PATCH 45/54] Do imports more sensibly and update to single copyright year --- examples/icub_vor_env/icub_utilities.py | 2 +- examples/icub_vor_env/icub_vor_env_test.py | 2 +- .../icub_vor_env_test_200_inputs.py | 28 ++++++++----------- .../icub_vor_venv_test_perfect_motion.py | 28 ++++++++----------- 4 files changed, 26 insertions(+), 34 deletions(-) diff --git a/examples/icub_vor_env/icub_utilities.py b/examples/icub_vor_env/icub_utilities.py index 00052e1c..658af3bd 100644 --- a/examples/icub_vor_env/icub_utilities.py +++ b/examples/icub_vor_env/icub_utilities.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 The University of Manchester +# Copyright (c) 2021 The University of Manchester # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/examples/icub_vor_env/icub_vor_env_test.py b/examples/icub_vor_env/icub_vor_env_test.py index 2713ca93..911c8ecb 100644 --- a/examples/icub_vor_env/icub_vor_env_test.py +++ b/examples/icub_vor_env/icub_vor_env_test.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 The University of Manchester +# Copyright (c) 2021 The University of Manchester # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 945f55da..364c8e9f 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 The University of Manchester +# Copyright (c) 2021 The University of Manchester # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,15 +16,8 @@ import pyNN.spiNNaker as p import spinn_gym as gym -# from pyNN.utility.plotting import Figure, Panel -# import matplotlib.pyplot as plt import numpy as np -# import os -from icub_utilities import ( - generate_head_position_and_velocity, retrieve_and_package_results, - remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, - plot_results) - +import icub_utilities as icub_util # Parameter definition runtime = 5000 @@ -33,7 +26,7 @@ output_size = 200 # neurons gain = 20.0 -head_pos, head_vel = generate_head_position_and_velocity(1) +head_pos, head_vel = icub_util.generate_head_position_and_velocity(1) # perfect eye positions and velocities are exactly out of phase with head perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) @@ -67,7 +60,8 @@ icub_vor_env_model = gym.ICubVorEnv( head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, output_size) -icub_vor_env_pop = p.Population(ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) +icub_vor_env_pop = p.Population( + icub_util.ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) # Set recording for input and output pop (env pop records by default) input_pop.record('spikes') @@ -85,7 +79,7 @@ p.run(runtime) # Get the data from the ICubVorEnv pop -results = retrieve_and_package_results(icub_vor_env_pop) +results = icub_util.retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') @@ -94,8 +88,9 @@ # end simulation p.end() -remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) -remapped_cf_spikes = remap_second_half_descending(spikes_out_spin, output_size) +remapped_vn_spikes = icub_util.remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = icub_util.remap_second_half_descending( + spikes_out_spin, output_size) simulation_parameters = { 'runtime': runtime, @@ -110,7 +105,8 @@ } # plot the data from the ICubVorEnv pop -plot_results(results_dict=results, simulation_parameters=simulation_parameters, - name="spinngym_icub_vor_test_200_inputs") +icub_util.plot_results(results_dict=results, + simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_200_inputs") print("Done") diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index c7a66286..7746558f 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 The University of Manchester +# Copyright (c) 2021 The University of Manchester # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,15 +16,8 @@ import pyNN.spiNNaker as p import spinn_gym as gym -# from pyNN.utility.plotting import Figure, Panel -# import matplotlib.pyplot as plt import numpy as np -# import os -from icub_utilities import ( - generate_head_position_and_velocity, retrieve_and_package_results, - remap_odd_even, remap_second_half_descending, ICUB_VOR_VENV_POP_SIZE, - plot_results) - +import icub_utilities as icub_util # Parameter definition runtime = 3000 @@ -33,7 +26,7 @@ output_size = 200 # neurons gain = 20.0 -head_pos, head_vel = generate_head_position_and_velocity(1) +head_pos, head_vel = icub_util.generate_head_position_and_velocity(1) # perfect eye positions and velocities are exactly out of phase with head perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) @@ -80,7 +73,8 @@ icub_vor_env_model = gym.ICubVorEnv( head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, output_size) -icub_vor_env_pop = p.Population(ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) +icub_vor_env_pop = p.Population( + icub_util.ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) # Set recording for input and output pop (env pop records by default) input_pop.record('spikes') @@ -98,7 +92,7 @@ p.run(runtime) # Get the data from the ICubVorEnv pop -results = retrieve_and_package_results(icub_vor_env_pop) +results = icub_util.retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') @@ -107,8 +101,9 @@ # end simulation p.end() -remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) -remapped_cf_spikes = remap_second_half_descending(spikes_out_spin, output_size) +remapped_vn_spikes = icub_util.remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = icub_util.remap_second_half_descending( + spikes_out_spin, output_size) simulation_parameters = { 'runtime': runtime, @@ -123,7 +118,8 @@ } # plot the data from the ICubVorEnv pop -plot_results(results_dict=results, simulation_parameters=simulation_parameters, - name="spinngym_icub_vor_test_perfect") +icub_util.plot_results(results_dict=results, + simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_perfect") print("Done") From 49c7ad84ad61631d194d4c0a637a18e1546519b2 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 3 Jul 2023 09:30:44 +0100 Subject: [PATCH 46/54] Apparently pylint was complaining about this --- examples/icub_vor_env/__init__.py | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 examples/icub_vor_env/__init__.py diff --git a/examples/icub_vor_env/__init__.py b/examples/icub_vor_env/__init__.py deleted file mode 100644 index f3d2ab9a..00000000 --- a/examples/icub_vor_env/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2021 The University of Manchester -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . From f565eb48478a3a19260c75a786cb2603683949d8 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 27 Jul 2023 11:20:14 +0100 Subject: [PATCH 47/54] Missing init py file --- examples/icub_vor_env/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/icub_vor_env/__init__.py diff --git a/examples/icub_vor_env/__init__.py b/examples/icub_vor_env/__init__.py new file mode 100644 index 00000000..f3d2ab9a --- /dev/null +++ b/examples/icub_vor_env/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . From a2de77060a16878bbca55d2baec44191b1126b71 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 27 Jul 2023 11:34:08 +0100 Subject: [PATCH 48/54] Try this to satisfy pylint instead --- examples/icub_vor_env/icub_utils/__init__.py | 14 ++++++++++++++ .../{ => icub_utils}/icub_utilities.py | 0 .../icub_vor_env/icub_vor_env_test_200_inputs.py | 2 +- .../icub_vor_venv_test_perfect_motion.py | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 examples/icub_vor_env/icub_utils/__init__.py rename examples/icub_vor_env/{ => icub_utils}/icub_utilities.py (100%) diff --git a/examples/icub_vor_env/icub_utils/__init__.py b/examples/icub_vor_env/icub_utils/__init__.py new file mode 100644 index 00000000..f3d2ab9a --- /dev/null +++ b/examples/icub_vor_env/icub_utils/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . diff --git a/examples/icub_vor_env/icub_utilities.py b/examples/icub_vor_env/icub_utils/icub_utilities.py similarity index 100% rename from examples/icub_vor_env/icub_utilities.py rename to examples/icub_vor_env/icub_utils/icub_utilities.py diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 364c8e9f..b3c15d92 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -17,7 +17,7 @@ import spinn_gym as gym import numpy as np -import icub_utilities as icub_util +from icub_utils import icub_utilities as icub_util # Parameter definition runtime = 5000 diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index 7746558f..3b4a40f0 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -17,7 +17,7 @@ import spinn_gym as gym import numpy as np -import icub_utilities as icub_util +from icub_utils import icub_utilities as icub_util # Parameter definition runtime = 3000 From da95f68e8b89ea7f09450f0d4c88b0991f85c2e3 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 27 Jul 2023 13:48:55 +0100 Subject: [PATCH 49/54] Try this setting instead --- .pylintrc | 2 +- .../{icub_utils => }/icub_utilities.py | 0 examples/icub_vor_env/icub_utils/__init__.py | 14 -------------- .../icub_vor_env/icub_vor_env_test_200_inputs.py | 2 +- .../icub_vor_venv_test_perfect_motion.py | 2 +- 5 files changed, 3 insertions(+), 17 deletions(-) rename examples/icub_vor_env/{icub_utils => }/icub_utilities.py (100%) delete mode 100644 examples/icub_vor_env/icub_utils/__init__.py diff --git a/.pylintrc b/.pylintrc index 8814dda1..3e60e815 100644 --- a/.pylintrc +++ b/.pylintrc @@ -30,7 +30,7 @@ ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). -#init-hook= +init-hook='import sys; sys.path.append(".")' # Use multiple processes to speed up Pylint. jobs=1 diff --git a/examples/icub_vor_env/icub_utils/icub_utilities.py b/examples/icub_vor_env/icub_utilities.py similarity index 100% rename from examples/icub_vor_env/icub_utils/icub_utilities.py rename to examples/icub_vor_env/icub_utilities.py diff --git a/examples/icub_vor_env/icub_utils/__init__.py b/examples/icub_vor_env/icub_utils/__init__.py deleted file mode 100644 index f3d2ab9a..00000000 --- a/examples/icub_vor_env/icub_utils/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2021 The University of Manchester -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index b3c15d92..364c8e9f 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -17,7 +17,7 @@ import spinn_gym as gym import numpy as np -from icub_utils import icub_utilities as icub_util +import icub_utilities as icub_util # Parameter definition runtime = 5000 diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index 3b4a40f0..7746558f 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -17,7 +17,7 @@ import spinn_gym as gym import numpy as np -from icub_utils import icub_utilities as icub_util +import icub_utilities as icub_util # Parameter definition runtime = 3000 From e671c7b471d6a599a68b22e6e8d78f5022977b7e Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 27 Jul 2023 14:09:58 +0100 Subject: [PATCH 50/54] Try this instead --- .../icub_vor_env_test_200_inputs.py | 22 +++++++++++-------- .../icub_vor_venv_test_perfect_motion.py | 21 ++++++++++-------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 364c8e9f..9e61dbfa 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -17,7 +17,11 @@ import spinn_gym as gym import numpy as np -import icub_utilities as icub_util +from icub_utilities import ( + generate_head_position_and_velocity, ICUB_VOR_VENV_POP_SIZE, + retrieve_and_package_results, remap_odd_even, + remap_second_half_descending, plot_results) + # Parameter definition runtime = 5000 @@ -26,7 +30,7 @@ output_size = 200 # neurons gain = 20.0 -head_pos, head_vel = icub_util.generate_head_position_and_velocity(1) +head_pos, head_vel = generate_head_position_and_velocity(1) # perfect eye positions and velocities are exactly out of phase with head perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) @@ -61,7 +65,7 @@ head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, output_size) icub_vor_env_pop = p.Population( - icub_util.ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) + ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) # Set recording for input and output pop (env pop records by default) input_pop.record('spikes') @@ -79,7 +83,7 @@ p.run(runtime) # Get the data from the ICubVorEnv pop -results = icub_util.retrieve_and_package_results(icub_vor_env_pop) +results = retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') @@ -88,8 +92,8 @@ # end simulation p.end() -remapped_vn_spikes = icub_util.remap_odd_even(spikes_in_spin, input_size) -remapped_cf_spikes = icub_util.remap_second_half_descending( +remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = remap_second_half_descending( spikes_out_spin, output_size) simulation_parameters = { @@ -105,8 +109,8 @@ } # plot the data from the ICubVorEnv pop -icub_util.plot_results(results_dict=results, - simulation_parameters=simulation_parameters, - name="spinngym_icub_vor_test_200_inputs") +plot_results(results_dict=results, + simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_200_inputs") print("Done") diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index 7746558f..e0e153ca 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -17,7 +17,10 @@ import spinn_gym as gym import numpy as np -import icub_utilities as icub_util +from icub_utilities import ( + generate_head_position_and_velocity, ICUB_VOR_VENV_POP_SIZE, + retrieve_and_package_results, remap_odd_even, + remap_second_half_descending, plot_results) # Parameter definition runtime = 3000 @@ -26,7 +29,7 @@ output_size = 200 # neurons gain = 20.0 -head_pos, head_vel = icub_util.generate_head_position_and_velocity(1) +head_pos, head_vel = generate_head_position_and_velocity(1) # perfect eye positions and velocities are exactly out of phase with head perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) @@ -74,7 +77,7 @@ head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, output_size) icub_vor_env_pop = p.Population( - icub_util.ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) + ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) # Set recording for input and output pop (env pop records by default) input_pop.record('spikes') @@ -92,7 +95,7 @@ p.run(runtime) # Get the data from the ICubVorEnv pop -results = icub_util.retrieve_and_package_results(icub_vor_env_pop) +results = retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') @@ -101,8 +104,8 @@ # end simulation p.end() -remapped_vn_spikes = icub_util.remap_odd_even(spikes_in_spin, input_size) -remapped_cf_spikes = icub_util.remap_second_half_descending( +remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = remap_second_half_descending( spikes_out_spin, output_size) simulation_parameters = { @@ -118,8 +121,8 @@ } # plot the data from the ICubVorEnv pop -icub_util.plot_results(results_dict=results, - simulation_parameters=simulation_parameters, - name="spinngym_icub_vor_test_perfect") +plot_results(results_dict=results, + simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_perfect") print("Done") From 1fea7a1edcdd0dc4d2987cb2632a5ca289508d18 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 27 Jul 2023 14:35:06 +0100 Subject: [PATCH 51/54] This should now work --- .pylintrc | 2 +- examples/icub_vor_env/__init__.py | 14 ------------- .../icub_vor_env_test_200_inputs.py | 21 ++++++++----------- .../icub_vor_venv_test_perfect_motion.py | 21 ++++++++----------- 4 files changed, 19 insertions(+), 39 deletions(-) delete mode 100644 examples/icub_vor_env/__init__.py diff --git a/.pylintrc b/.pylintrc index 3e60e815..8814dda1 100644 --- a/.pylintrc +++ b/.pylintrc @@ -30,7 +30,7 @@ ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). -init-hook='import sys; sys.path.append(".")' +#init-hook= # Use multiple processes to speed up Pylint. jobs=1 diff --git a/examples/icub_vor_env/__init__.py b/examples/icub_vor_env/__init__.py deleted file mode 100644 index f3d2ab9a..00000000 --- a/examples/icub_vor_env/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2021 The University of Manchester -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index 9e61dbfa..fddbc538 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -17,10 +17,7 @@ import spinn_gym as gym import numpy as np -from icub_utilities import ( - generate_head_position_and_velocity, ICUB_VOR_VENV_POP_SIZE, - retrieve_and_package_results, remap_odd_even, - remap_second_half_descending, plot_results) +import icub_utilities as icub_util # Parameter definition @@ -30,7 +27,7 @@ output_size = 200 # neurons gain = 20.0 -head_pos, head_vel = generate_head_position_and_velocity(1) +head_pos, head_vel = icub_util.generate_head_position_and_velocity(1) # perfect eye positions and velocities are exactly out of phase with head perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) @@ -65,7 +62,7 @@ head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, output_size) icub_vor_env_pop = p.Population( - ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) + icub_util.ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) # Set recording for input and output pop (env pop records by default) input_pop.record('spikes') @@ -83,7 +80,7 @@ p.run(runtime) # Get the data from the ICubVorEnv pop -results = retrieve_and_package_results(icub_vor_env_pop) +results = icub_util.retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') @@ -92,8 +89,8 @@ # end simulation p.end() -remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) -remapped_cf_spikes = remap_second_half_descending( +remapped_vn_spikes = icub_util.remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = icub_util.remap_second_half_descending( spikes_out_spin, output_size) simulation_parameters = { @@ -109,8 +106,8 @@ } # plot the data from the ICubVorEnv pop -plot_results(results_dict=results, - simulation_parameters=simulation_parameters, - name="spinngym_icub_vor_test_200_inputs") +icub_util.plot_results(results_dict=results, + simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_200_inputs") print("Done") diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index e0e153ca..7746558f 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -17,10 +17,7 @@ import spinn_gym as gym import numpy as np -from icub_utilities import ( - generate_head_position_and_velocity, ICUB_VOR_VENV_POP_SIZE, - retrieve_and_package_results, remap_odd_even, - remap_second_half_descending, plot_results) +import icub_utilities as icub_util # Parameter definition runtime = 3000 @@ -29,7 +26,7 @@ output_size = 200 # neurons gain = 20.0 -head_pos, head_vel = generate_head_position_and_velocity(1) +head_pos, head_vel = icub_util.generate_head_position_and_velocity(1) # perfect eye positions and velocities are exactly out of phase with head perfect_eye_pos = np.concatenate((head_pos[500:], head_pos[:500])) @@ -77,7 +74,7 @@ head_pos, head_vel, perfect_eye_vel, perfect_eye_pos, error_window_size, output_size) icub_vor_env_pop = p.Population( - ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) + icub_util.ICUB_VOR_VENV_POP_SIZE, icub_vor_env_model) # Set recording for input and output pop (env pop records by default) input_pop.record('spikes') @@ -95,7 +92,7 @@ p.run(runtime) # Get the data from the ICubVorEnv pop -results = retrieve_and_package_results(icub_vor_env_pop) +results = icub_util.retrieve_and_package_results(icub_vor_env_pop) # get the spike data from input and output spikes_in_spin = input_pop.spinnaker_get_data('spikes') @@ -104,8 +101,8 @@ # end simulation p.end() -remapped_vn_spikes = remap_odd_even(spikes_in_spin, input_size) -remapped_cf_spikes = remap_second_half_descending( +remapped_vn_spikes = icub_util.remap_odd_even(spikes_in_spin, input_size) +remapped_cf_spikes = icub_util.remap_second_half_descending( spikes_out_spin, output_size) simulation_parameters = { @@ -121,8 +118,8 @@ } # plot the data from the ICubVorEnv pop -plot_results(results_dict=results, - simulation_parameters=simulation_parameters, - name="spinngym_icub_vor_test_perfect") +icub_util.plot_results(results_dict=results, + simulation_parameters=simulation_parameters, + name="spinngym_icub_vor_test_perfect") print("Done") From 463af625a17ba2ad7e1d6aaae6495d834b538664 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 28 Jul 2023 12:48:54 +0100 Subject: [PATCH 52/54] Update script_builder to skip icub_utilities --- integration_tests/script_builder.py | 8 +++-- integration_tests/test_scripts.py | 51 ++++++++++++++++++----------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/integration_tests/script_builder.py b/integration_tests/script_builder.py index cace985e..810ce5ac 100644 --- a/integration_tests/script_builder.py +++ b/integration_tests/script_builder.py @@ -21,13 +21,15 @@ class ScriptBuilder(RootScriptBuilder): This file will recreate the test_scripts.py file """ - def build_intro_labs_scripts(self): + def build_spinn_gym_scripts(self): # create_test_scripts supports test that are too long or exceptions self.create_test_scripts(["examples"], # This is meant to run "forever" - exceptions={"automated.py": "Runs forever"}) + exceptions={ + "automated.py": "Runs forever", + "icub_utilities.py": "Not a script"}) if __name__ == '__main__': builder = ScriptBuilder() - builder.build_intro_labs_scripts() + builder.build_spinn_gym_scripts() diff --git a/integration_tests/test_scripts.py b/integration_tests/test_scripts.py index 443d9976..3c4cc5fa 100644 --- a/integration_tests/test_scripts.py +++ b/integration_tests/test_scripts.py @@ -1,17 +1,16 @@ -# Copyright (c) 2019-2021 The University of Manchester +# Copyright (c) 2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# https://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spinnaker_testbase import ScriptChecker @@ -28,8 +27,11 @@ class TestScripts(ScriptChecker): """ # flake8: noqa - def test_examples_breakout_automated_bkout_play(self): - self.check_script("examples/breakout/automated_bkout_play.py") + def test_examples_double_inverted_pendulum_double_inverted_pendulum_test(self): + self.check_script("examples/double_inverted_pendulum/double_inverted_pendulum_test.py") + + def test_examples_logic_logic_test(self): + self.check_script("examples/logic/logic_test.py") def test_examples_breakout_breakout_simple_connection(self): self.check_script("examples/breakout/breakout_simple_connection.py") @@ -40,17 +42,26 @@ def test_examples_breakout_breakout_simple_connection(self): def test_examples_breakout_neuromodulated_bkout_play(self): self.check_script("examples/breakout/neuromodulated_bkout_play.py") - def test_examples_logic_logic_test(self): - self.check_script("examples/logic/logic_test.py") - - def test_examples_double_inverted_pendulum_double_inverted_pendulum_test(self): - self.check_script("examples/double_inverted_pendulum/double_inverted_pendulum_test.py") + def test_examples_breakout_automated_bkout_play(self): + self.check_script("examples/breakout/automated_bkout_play.py") def test_examples_store_recall_store_recall_test(self): self.check_script("examples/store_recall/store_recall_test.py") - def test_examples_inverted_pendulum_inverted_pendulum_test(self): - self.check_script("examples/inverted_pendulum/inverted_pendulum_test.py") + # Not testing file due to: Not a script + # examples/icub_vor_env/icub_utilities.py + + def test_examples_icub_vor_env_icub_vor_env_test_200_inputs(self): + self.check_script("examples/icub_vor_env/icub_vor_env_test_200_inputs.py") + + def test_examples_icub_vor_env_icub_vor_venv_test_perfect_motion(self): + self.check_script("examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py") + + def test_examples_icub_vor_env_icub_vor_env_test(self): + self.check_script("examples/icub_vor_env/icub_vor_env_test.py") def test_examples_multi_arm_bandit_bandit_test(self): self.check_script("examples/multi_arm_bandit/bandit_test.py") + + def test_examples_inverted_pendulum_inverted_pendulum_test(self): + self.check_script("examples/inverted_pendulum/inverted_pendulum_test.py") From 2a11cac4a298eaef5a2695c04b5a5f461109e52e Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 31 Jul 2023 12:05:07 +0100 Subject: [PATCH 53/54] Try a different location for icub_utilities --- examples/icub_vor_env/icub_vor_env_test_200_inputs.py | 2 +- examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py | 2 +- {examples => spinn_gym/games}/icub_vor_env/icub_utilities.py | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {examples => spinn_gym/games}/icub_vor_env/icub_utilities.py (100%) diff --git a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py index fddbc538..ceeeb123 100644 --- a/examples/icub_vor_env/icub_vor_env_test_200_inputs.py +++ b/examples/icub_vor_env/icub_vor_env_test_200_inputs.py @@ -17,7 +17,7 @@ import spinn_gym as gym import numpy as np -import icub_utilities as icub_util +import spinn_gym.games.icub_vor_env.icub_utilities as icub_util # Parameter definition diff --git a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py index 7746558f..cf080f8c 100644 --- a/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py +++ b/examples/icub_vor_env/icub_vor_venv_test_perfect_motion.py @@ -17,7 +17,7 @@ import spinn_gym as gym import numpy as np -import icub_utilities as icub_util +import spinn_gym.games.icub_vor_env.icub_utilities as icub_util # Parameter definition runtime = 3000 diff --git a/examples/icub_vor_env/icub_utilities.py b/spinn_gym/games/icub_vor_env/icub_utilities.py similarity index 100% rename from examples/icub_vor_env/icub_utilities.py rename to spinn_gym/games/icub_vor_env/icub_utilities.py From 08ed4e4b54307b5e933d8127d21c6d3d6fd8d7ea Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 31 Jul 2023 12:19:31 +0100 Subject: [PATCH 54/54] More tidying up --- spinn_gym/games/icub_vor_env/icub_utilities.py | 9 +++++++-- spinn_gym/games/icub_vor_env/icub_vor_env.py | 16 ---------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/spinn_gym/games/icub_vor_env/icub_utilities.py b/spinn_gym/games/icub_vor_env/icub_utilities.py index 658af3bd..199ecfb7 100644 --- a/spinn_gym/games/icub_vor_env/icub_utilities.py +++ b/spinn_gym/games/icub_vor_env/icub_utilities.py @@ -34,30 +34,35 @@ # Examples of get functions for variables def get_error(icub_vor_env_pop): + # pylint: disable=protected-access b_vertex = icub_vor_env_pop._vertex error = b_vertex.get_recorded_data('error') return error.tolist() def get_l_count(icub_vor_env_pop): + # pylint: disable=protected-access b_vertex = icub_vor_env_pop._vertex left_count = b_vertex.get_recorded_data('l_count') return left_count.tolist() def get_r_count(icub_vor_env_pop): + # pylint: disable=protected-access b_vertex = icub_vor_env_pop._vertex right_count = b_vertex.get_recorded_data('r_count') return right_count.tolist() def get_eye_pos(icub_vor_env_pop): + # pylint: disable=protected-access b_vertex = icub_vor_env_pop._vertex eye_positions = b_vertex.get_recorded_data('eye_pos') return eye_positions.tolist() def get_eye_vel(icub_vor_env_pop): + # pylint: disable=protected-access b_vertex = icub_vor_env_pop._vertex eye_velocities = b_vertex.get_recorded_data('eye_vel') return eye_velocities.tolist() @@ -230,7 +235,7 @@ def write_value(msg, value): print("{:60}:{:19}".format(msg, str(value))) -def save_figure(plt, name, extensions=(".png",), **kwargs): +def save_figure(plt_fig, name, extensions=(".png",), **kwargs): for ext in extensions: write_short_msg("Plotting", name + ext) - plt.savefig(name + ext, **kwargs) + plt_fig.savefig(name + ext, **kwargs) diff --git a/spinn_gym/games/icub_vor_env/icub_vor_env.py b/spinn_gym/games/icub_vor_env/icub_vor_env.py index 49421117..17982458 100644 --- a/spinn_gym/games/icub_vor_env/icub_vor_env.py +++ b/spinn_gym/games/icub_vor_env/icub_vor_env.py @@ -118,22 +118,6 @@ def __init__(self, head_pos, head_vel, perfect_eye_pos, perfect_eye_vel, # ------------------------------------------------------------------------ # Recording overrides # ------------------------------------------------------------------------ - # @overrides(SpinnGymApplicationVertex.clear_recording_data) - # def clear_recording_data(self, name): - # if name not in self.RECORDABLE_VARIABLES: - # raise KeyError(f"Cannot clear recording for {name}") - # for machine_vertex in self.machine_vertices: - # placement = SpynnakerDataView.get_placement_of_vertex( - # machine_vertex) - # buffer_manager = SpynnakerDataView.get_buffer_manager() - # buffer_manager.clear_recorded_data( - # placement.x, placement.y, placement.p, - # self.RECORDABLE_VARIABLES.index(name)) - # - # @overrides(SpinnGymApplicationVertex.get_recordable_variables) - # def get_recordable_variables(self): - # return self.RECORDABLE_VARIABLES - @overrides(SpinnGymApplicationVertex.get_recorded_data) def get_recorded_data(self, name): if self._m_vertex is None: