// The constructor uses the appropriate settings in the config file to // properly set up the sensor model for the specified "phase" of the LGMD // input signal. SensorModel::SensorModel(const std::string& lgmd_phase) : m_sigma(0.0f), m_name(lgmd_phase) { const range<float> lgmd_range = get_conf(locust_model(), "spike_range", make_range(0.0f, 800.0f)) ; // Get the LGMD ranges for the columns of the sensor model m_lgmd_ranges = string_to_deque<float>( conf<std::string>(lgmd_phase + "_lgmd_ranges", "0 800")) ; if (m_lgmd_ranges.size() < 2) { // crappy configuration! m_lgmd_ranges.clear() ; m_lgmd_ranges.push_back(lgmd_range.min()) ; m_lgmd_ranges.push_back(lgmd_range.max()) ; } sort(m_lgmd_ranges.begin(), m_lgmd_ranges.end()) ; if (m_lgmd_ranges.front() > lgmd_range.min()) m_lgmd_ranges.push_front(lgmd_range.min()) ; if (m_lgmd_ranges.back() < lgmd_range.max()) m_lgmd_ranges.push_back(lgmd_range.max()) ; // Figure out how many rows and columns the sensor model's probability // table has and allocate space for the required number of elements. // Initialize the probability table using a uniform distribution. const int C = m_lgmd_ranges.size() - 1 ; const int R = column_size() ; const int N = R * C ; m_prob.reserve(N) ; std::fill_n(std::back_inserter(m_prob), N, 1.0f/N) ; // Apply Gabbiani model to obtain causal probabilities and Gaussian // blur neighbouring bins in each row. update(clamp(conf(lgmd_phase + "_sigma", 1.0f), 0.1f, static_cast<float>(row_size()))) ; }
// Quick helper to return a label for the current range of probability // values used for scaling the texels used to represent the sensor // model's probabilities. static std::string prob_label(const range<float>& prob_range) { std::ostringstream str ; str << "P-range: [" << prob_range.min() << ", " << prob_range.max() << ']' ; return str.str() ; }
// This method regenerates the sensor model's probabilities using the // Gabbiani LGMD model and the given standard deviation for the Gaussian // blurring operation for bins near the ones actually "pointed to" by the // [TTI, LGMD] pairs returned by the Gabbiani model. // // DEVNOTE: The sigma provided to this function is actually added to the // m_sigma member variable. This allows client behaviours to increment or // decrement the current sigma value rather than provide an actual sigma. // The very first sigma will be read from the config file (see // constructor). void SensorModel::update(float dsigma) { AutoMutex M(m_mutex) ; // Record new standard deviation const float R = row_size() ; m_sigma = clamp(m_sigma + dsigma, 0.1f, R) ; // Begin with a uniform distribution for each state const int N = m_prob.size() ; std::fill_n(m_prob.begin(), N, 1/R) ; // Apply Gabbiani LGMD model to generate causal likelihoods const float step = row_step()/4.0f ; const range<float> tti = conf(m_name + "_tti_range", Params::tti_range()) ; for (float t = tti.min(); t <= tti.max(); t += step) update_row(t, GabbianiModel::spike_rate(t), m_sigma) ; }