<commit_before>/*
    Copyright 2011 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 2014.

    This file is part of MRtrix.

    MRtrix 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.

    MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <string>
#include <vector>

#include "command.h"
#include "exception.h"
#include "mrtrix.h"

#include "thread_queue.h"

#include "dwi/tractography/file.h"
#include "dwi/tractography/properties.h"
#include "dwi/tractography/roi.h"
#include "dwi/tractography/weights.h"

#include "dwi/tractography/editing/editing.h"
#include "dwi/tractography/editing/loader.h"
#include "dwi/tractography/editing/receiver.h"
#include "dwi/tractography/editing/worker.h"

using namespace MR;
using namespace App;
using namespace MR::DWI;
using namespace MR::DWI::Tractography;
using namespace MR::DWI::Tractography::Editing;

void usage ()
{

  AUTHOR = "Robert E. Smith (r.smith@brain.org.au)";

  DESCRIPTION
  + "perform various editing operations on track files.";

  ARGUMENTS
  + Argument ("tracks_in",  "the input track file(s)").type_file_in().allow_multiple()
  + Argument ("tracks_out", "the output track file").type_file_out();

  OPTIONS
  + ROIOption
  + LengthOption
  + ResampleOption
  + TruncateOption
  + WeightsOption

  + Option ("inverse", "output the inverse selection of streamlines based on the criteria provided, "
                       "i.e. only those streamlines that fail at least one criterion will be written to file.")

  + Option ("test_ends_only", "only test the ends of each streamline against the provided include/exclude ROIs")

  // TODO Input weights with multiple input files currently not supported
  + Tractography::TrackWeightsInOption
  + Tractography::TrackWeightsOutOption;

  // TODO Additional options?
  // - Peak curvature threshold
  // - Mean curvature threshold
  // - Resample streamline to fixed step size

};

void update_output_step_size (Tractography::Properties& properties, const int upsample_ratio, const int downsample_ratio)
{
  if (upsample_ratio == 1 && downsample_ratio == 1)
    return;
  float step_size = 0.0;
  if (properties.find ("output_step_size") == properties.end())
    step_size = (properties.find ("step_size") == properties.end() ? 0.0 : to<float>(properties["step_size"]));
  else
    step_size = to<float>(properties["output_step_size"]);
  properties["output_step_size"] = step_size * float(downsample_ratio) / float(upsample_ratio);
}

void run ()
{

  const size_t num_inputs = argument.size() - 1;
  const std::string output_path = argument[num_inputs];

  // Make sure configuration is sensible
  if (get_options("tck_weights_in").size() && num_inputs > 1)
    throw Exception ("Cannot use per-streamline weighting with multiple input files");
  // TODO Anything else?

  // Get the consensus streamline properties from among the multiple input files
  Tractography::Properties properties;
  size_t count = 0;
  std::vector<std::string> input_file_list;

  for (size_t file_index = 0; file_index != num_inputs; ++file_index) {

    input_file_list.push_back (argument[file_index]);

    Properties p;
    Tractography::Reader<float> reader (argument[file_index], p);

    for (std::vector<std::string>::const_iterator i = p.comments.begin(); i != p.comments.end(); ++i) {
      bool present = false;
      for (std::vector<std::string>::const_iterator j = properties.comments.begin(); !present && j != properties.comments.end(); ++j)
        present = (*i == *j);
      if (!present)
        properties.comments.push_back (*i);
    }

    // ROI paths are ignored - otherwise tckedit will try to find the ROIs used
    //   during streamlines generation!

    size_t this_count = 0, this_total_count = 0;

    for (Properties::const_iterator i = p.begin(); i != p.end(); ++i) {
      if (i->first == "count") {
        this_count = to<float>(i->second);
      } else if (i->first == "total_count") {
        this_total_count += to<float>(i->second);
      } else {
        Properties::iterator existing = properties.find (i->first);
        if (existing == properties.end())
          properties.insert (*i);
        else if (i->second != existing->second)
          existing->second = "variable";
      }
    }

    count += this_count;

  }

  DEBUG ("estimated number of input tracks: " + str(count));

  load_rois (properties);

  // Some properties from tracking may be overwritten by this editing process
  Editing::load_properties (properties);

  // Parameters that the worker threads need to be aware of, but do not appear in Properties
  Options opt = get_options ("upsample");
  const int upsample   = opt.size() ? int(opt[0][0]) : 1;
  opt = get_options ("downsample");
  const int downsample = opt.size() ? int(opt[0][0]) : 1;
  const bool inverse = get_options ("inverse").size();
  const bool test_ends_only = get_options ("test_ends_only").size();
  const bool out_ends_only = get_options ("out_ends_only").size();

  // Parameters that the output thread needs to be aware of
  opt = get_options ("number");
  const size_t number = opt.size() ? size_t(opt[0][0]) : 0;
  opt = get_options ("skip");
  const size_t skip   = opt.size() ? size_t(opt[0][0]) : 0;

  Loader loader (input_file_list);
  Worker worker (properties, upsample, downsample, inverse, test_ends_only);
  // This needs to be run AFTER creation of the Worker class
  // (worker needs to be able to set max & min number of points based on step size in input file,
  //  receiver needs "output_step_size" field to have been updated before file creation)
  update_output_step_size (properties, upsample, downsample);
  Receiver receiver (output_path, properties, number, skip, out_ends_only);

  Thread::run_queue (
      loader,
      Thread::batch (Tractography::Streamline<>()),
      Thread::multi (worker),
      Thread::batch (Tractography::Streamline<>()),
      receiver);

}
<commit_msg>tckedit: Fix 'output_step_size' field in Properties<commit_after>/*
    Copyright 2011 Brain Research Institute, Melbourne, Australia

    Written by Robert E. Smith, 2014.

    This file is part of MRtrix.

    MRtrix 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.

    MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <string>
#include <vector>

#include "command.h"
#include "exception.h"
#include "mrtrix.h"

#include "thread_queue.h"

#include "dwi/tractography/file.h"
#include "dwi/tractography/properties.h"
#include "dwi/tractography/roi.h"
#include "dwi/tractography/weights.h"

#include "dwi/tractography/editing/editing.h"
#include "dwi/tractography/editing/loader.h"
#include "dwi/tractography/editing/receiver.h"
#include "dwi/tractography/editing/worker.h"

using namespace MR;
using namespace App;
using namespace MR::DWI;
using namespace MR::DWI::Tractography;
using namespace MR::DWI::Tractography::Editing;

void usage ()
{

  AUTHOR = "Robert E. Smith (r.smith@brain.org.au)";

  DESCRIPTION
  + "perform various editing operations on track files.";

  ARGUMENTS
  + Argument ("tracks_in",  "the input track file(s)").type_file_in().allow_multiple()
  + Argument ("tracks_out", "the output track file").type_file_out();

  OPTIONS
  + ROIOption
  + LengthOption
  + ResampleOption
  + TruncateOption
  + WeightsOption

  + Option ("inverse", "output the inverse selection of streamlines based on the criteria provided, "
                       "i.e. only those streamlines that fail at least one criterion will be written to file.")

  + Option ("test_ends_only", "only test the ends of each streamline against the provided include/exclude ROIs")

  // TODO Input weights with multiple input files currently not supported
  + Tractography::TrackWeightsInOption
  + Tractography::TrackWeightsOutOption;

  // TODO Additional options?
  // - Peak curvature threshold
  // - Mean curvature threshold
  // - Resample streamline to fixed step size

};

void update_output_step_size (Tractography::Properties& properties, const int upsample_ratio, const int downsample_ratio)
{
  if (upsample_ratio == 1 && downsample_ratio == 1)
    return;
  float step_size = 0.0;
  if (properties.find ("output_step_size") == properties.end())
    step_size = (properties.find ("step_size") == properties.end() ? 0.0 : to<float>(properties["step_size"]));
  else
    step_size = to<float>(properties["output_step_size"]);
  properties["output_step_size"] = str(step_size * float(downsample_ratio) / float(upsample_ratio));
}

void run ()
{

  const size_t num_inputs = argument.size() - 1;
  const std::string output_path = argument[num_inputs];

  // Make sure configuration is sensible
  if (get_options("tck_weights_in").size() && num_inputs > 1)
    throw Exception ("Cannot use per-streamline weighting with multiple input files");
  // TODO Anything else?

  // Get the consensus streamline properties from among the multiple input files
  Tractography::Properties properties;
  size_t count = 0;
  std::vector<std::string> input_file_list;

  for (size_t file_index = 0; file_index != num_inputs; ++file_index) {

    input_file_list.push_back (argument[file_index]);

    Properties p;
    Tractography::Reader<float> reader (argument[file_index], p);

    for (std::vector<std::string>::const_iterator i = p.comments.begin(); i != p.comments.end(); ++i) {
      bool present = false;
      for (std::vector<std::string>::const_iterator j = properties.comments.begin(); !present && j != properties.comments.end(); ++j)
        present = (*i == *j);
      if (!present)
        properties.comments.push_back (*i);
    }

    // ROI paths are ignored - otherwise tckedit will try to find the ROIs used
    //   during streamlines generation!

    size_t this_count = 0, this_total_count = 0;

    for (Properties::const_iterator i = p.begin(); i != p.end(); ++i) {
      if (i->first == "count") {
        this_count = to<float>(i->second);
      } else if (i->first == "total_count") {
        this_total_count += to<float>(i->second);
      } else {
        Properties::iterator existing = properties.find (i->first);
        if (existing == properties.end())
          properties.insert (*i);
        else if (i->second != existing->second)
          existing->second = "variable";
      }
    }

    count += this_count;

  }

  DEBUG ("estimated number of input tracks: " + str(count));

  load_rois (properties);

  // Some properties from tracking may be overwritten by this editing process
  Editing::load_properties (properties);

  // Parameters that the worker threads need to be aware of, but do not appear in Properties
  Options opt = get_options ("upsample");
  const int upsample   = opt.size() ? int(opt[0][0]) : 1;
  opt = get_options ("downsample");
  const int downsample = opt.size() ? int(opt[0][0]) : 1;
  const bool inverse = get_options ("inverse").size();
  const bool test_ends_only = get_options ("test_ends_only").size();
  const bool out_ends_only = get_options ("out_ends_only").size();

  // Parameters that the output thread needs to be aware of
  opt = get_options ("number");
  const size_t number = opt.size() ? size_t(opt[0][0]) : 0;
  opt = get_options ("skip");
  const size_t skip   = opt.size() ? size_t(opt[0][0]) : 0;

  Loader loader (input_file_list);
  Worker worker (properties, upsample, downsample, inverse, test_ends_only);
  // This needs to be run AFTER creation of the Worker class
  // (worker needs to be able to set max & min number of points based on step size in input file,
  //  receiver needs "output_step_size" field to have been updated before file creation)
  update_output_step_size (properties, upsample, downsample);
  Receiver receiver (output_path, properties, number, skip, out_ends_only);

  Thread::run_queue (
      loader,
      Thread::batch (Tractography::Streamline<>()),
      Thread::multi (worker),
      Thread::batch (Tractography::Streamline<>()),
      receiver);

}
<|endoftext|>


<commit_before>#include "SettingsMenu.h"

SettingsMenu::SettingsMenu() : QMenu(){
  this->setTitle( tr("Desktop Settings") );
  this->setIcon( LXDG::findIcon("configure","") );
  //Now setup the possible configuration options
  QAction *act = new QAction(LXDG::findIcon("preferences-desktop-screensaver",""), tr("Screensaver"), this);
	act->setWhatsThis("xscreensaver-demo");
	this->addAction(act);

}

SettingsMenu::~SettingsMenu(){

}<commit_msg>oops, forgot to connect the signal/slot for the settings menu in the last commit.<commit_after>#include "SettingsMenu.h"

SettingsMenu::SettingsMenu() : QMenu(){
  this->setTitle( tr("Desktop Settings") );
  this->setIcon( LXDG::findIcon("configure","") );
  connect(this, SIGNAL(triggered(QAction*)), this, SLOT(runApp(QAction*)) );
  //Now setup the possible configuration options
  QAction *act = new QAction(LXDG::findIcon("preferences-desktop-screensaver",""), tr("Screensaver"), this);
	act->setWhatsThis("xscreensaver-demo");
	this->addAction(act);

}

SettingsMenu::~SettingsMenu(){

}<|endoftext|>


<commit_before>/*
    ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio

    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

        http://www.apache.org/licenses/LICENSE-2.0

    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.
*/

#include "ch.h"
#include "hal.h"

#include "analog.h"
#include "encoder.h"
#include "packet/frame.h"
#include "filter/movingaverage.h"

#include "gitsha1.h"
#include "angle.h"
#include "blink.h"
#include "simplebicycle.h"
#include "usbconfig.h"
#include "saconfig.h"

#include "parameters.h"

#include <algorithm>
#include <array>

namespace {
    float v = 3.0;
    /* sensors */
    Analog analog;
    Encoder encoder_steer(sa::RLS_ROLIN_ENC, sa::RLS_ROLIN_ENC_INDEX_CFG);
    EncoderFoaw<float, 32> encoder_rear_wheel(sa::RLS_GTS35_ENC,
                                              sa::RLS_GTS35_ENC_CFG,
                                              MS2ST(1), 3.0f);
    filter::MovingAverage<float, 5> velocity_filter;

    struct __attribute__((__packed__)) pose_t {
        float x; /* m */
        float y; /* m */
        float pitch; /* rad */
        float yaw; /* rad */
        float roll; /* rad */
        float steer; /* rad */
        float rear_wheel; /* rad */
        float v; /* m/s */
        uint8_t timestamp;  /* Converted from system ticks to milliseconds
                             * and contains only the least significant bits */
    }; /* 33 bytes */

    pose_t pose = {};

    using namespace packet::frame;
    std::array<uint8_t, sizeof(pose_t) + PACKET_OVERHEAD> packet_buffer;
} // namespace

/*
 * Application entry point.
 */
int main(void) {

    /*
     * System initializations.
     * - HAL initialization, this also initializes the configured device drivers
     *   and performs the board-specific initializations.
     * - Kernel initialization, the main() function becomes a thread and the
     *   RTOS is active.
     */
    halInit();
    chSysInit();

    /*
     * Initialize a serial-over-USB CDC driver.
     */
    sduObjectInit(&SDU1);
    sduStart(&SDU1, &serusbcfg);

    /*
     * Activate the USB driver and then the USB bus pull-up on D+.
     * Note, a delay is inserted in order to not have to disconnect the cable
     * after a reset.
     */
    board_usb_lld_disconnect_bus();   //usbDisconnectBus(serusbcfg.usbp);
    chThdSleepMilliseconds(1500);
    usbStart(serusbcfg.usbp, &usbcfg);
    board_usb_lld_connect_bus();      //usbConnectBus(serusbcfg.usbp);

    /* create the blink thread and print state monitor */
    chBlinkThreadCreateStatic();

    /*
     * Start sensors.
     * Encoder:
     *   Initialize encoder driver 5 on pins PA0, PA1 (EXT2-4, EXT2-8).
     *   Pins for encoder driver 3 are already set in board.h.
     */
    palSetLineMode(LINE_TIM5_CH1, PAL_MODE_ALTERNATE(2) | PAL_STM32_PUPDR_FLOATING);
    palSetLineMode(LINE_TIM5_CH2, PAL_MODE_ALTERNATE(2) | PAL_STM32_PUPDR_FLOATING);
    encoder_steer.start();
    encoder_rear_wheel.start();
    analog.start(1000); /* trigger ADC conversion at 1 kHz */

    /*
     * Set torque measurement enable line low.
     * The output of the Kistler torque sensor is not valid until after a falling edge
     * on the measurement line and it is held low. The 'LINE_TORQUE_MEAS_EN' line is
     * reversed due to NPN switch Q1.
     */
    palClearLine(LINE_TORQUE_MEAS_EN);
    chThdSleepMilliseconds(1);
    palSetLine(LINE_TORQUE_MEAS_EN);

    /*
     * Start DAC1 driver and set output pin as analog as suggested in Reference Manual.
     * The default line configuration is OUTPUT_OPENDRAIN_PULLUP  for SPI1_ENC1_NSS
     * and must be changed to use as analog output.
     */
    palSetLineMode(LINE_KOLLM_ACTL_TORQUE, PAL_MODE_INPUT_ANALOG);
    dacStart(sa::KOLLM_DAC, sa::KOLLM_DAC_CFG);

    /*
     * Initialize bicycle with default parameters, dt = 0.005 s.
     */
    model::SimpleBicycle bicycle(v);

    /* transmit git sha information, block until receiver is ready */
    uint8_t bytes_written = packet::frame::stuff(g_GITSHA1, packet_buffer.data(), 7);
    while ((SDU1.config->usbp->state != USB_ACTIVE) || (SDU1.state != SDU_READY)) {
        chThdSleepMilliseconds(10);
    }
    usbTransmit(SDU1.config->usbp, SDU1.config->bulk_in, packet_buffer.data(), bytes_written);

    /*
     * Normal main() thread activity, in this demo it simulates the bicycle
     * dynamics in real-time (roughly).
     */
    while (true) {
        systime_t starttime = chVTGetSystemTime();

        constexpr float roll_torque = 0.0f;

        /* get sensor measurements */
        float steer_torque = static_cast<float>(analog.get_adc12()*2.0f*sa::MAX_KISTLER_TORQUE/4096 -
                sa::MAX_KISTLER_TORQUE);
        float motor_torque = static_cast<float>(
                analog.get_adc13()*2.0f*sa::MAX_KOLLMORGEN_TORQUE/4096 -
                sa::MAX_KOLLMORGEN_TORQUE);
        float steer_angle = angle::encoder_count<float>(encoder_steer);
        float rear_wheel_angle = -angle::encoder_count<float>(encoder_rear_wheel);

        (void)motor_torque; /* remove build warning */
        v = velocity_filter.output(
                -sa::REAR_WHEEL_RADIUS*(angle::encoder_rate(encoder_rear_wheel)));

        /* yaw angle, just use previous state value */
        float yaw_angle = angle::wrap(bicycle.pose().yaw);

        /* simulate bicycle */
        bicycle.set_v(v);
        bicycle.update(roll_torque, steer_torque, yaw_angle, steer_angle, rear_wheel_angle);

        /* generate an example torque output for testing */
        float feedback_torque = bicycle.handlebar_feedback_torque();
        int32_t saturated_value = (feedback_torque/sa::MAX_KOLLMORGEN_TORQUE * 2048) + 2048;
        saturated_value = std::min<int32_t>(std::max<int32_t>(saturated_value, 0), 4096);
        dacsample_t aout = static_cast<dacsample_t>(saturated_value);
        dacPutChannelX(sa::KOLLM_DAC, 0, aout);

        pose = pose_t{}; /* reset pose to zero */
        pose.x = bicycle.pose().x;
        pose.y = bicycle.pose().y;
        pose.pitch = angle::wrap(bicycle.pose().pitch);
        pose.yaw = angle::wrap(bicycle.pose().yaw);
        pose.roll = angle::wrap(bicycle.pose().roll);
        pose.steer = angle::wrap(bicycle.pose().steer);
        pose.rear_wheel = angle::wrap(bicycle.pose().rear_wheel);
        pose.v = bicycle.v();
        pose.timestamp = static_cast<decltype(pose.timestamp)>(ST2MS(chVTGetSystemTime()));
        /*
         * Timing information
         * (replaced chVTGetSystemTIme() with chSysGetRealtimeCounterX() and two
         * uint32_t timing related fields added to pose_t)
         * - Debug mode with all ChibiOS debug config options enabled: computation ~3.1 ms, tx ~20 us
         * - Release mode: computation ~200 us, tx ~10 us
         *
         * TODO: Pose message should be transmitted asynchronously.
         * After starting transmission, the simulation should start to calculate pose for the next timestep.
         * This is currently not necessary given the observed timings.
         */
        bytes_written = packet::frame::stuff(&pose, packet_buffer.data(), sizeof(pose));
        if ((SDU1.config->usbp->state == USB_ACTIVE) && (SDU1.state == SDU_READY)) {
            usbTransmit(SDU1.config->usbp, SDU1.config->bulk_in, packet_buffer.data(), bytes_written);
        }

        systime_t dt = MS2ST(static_cast<systime_t>(1000*bicycle.dt()));
        systime_t sleeptime = dt + starttime - chVTGetSystemTime();
        if (sleeptime >= dt) {
            //chDbgAssert(false, "deadline missed");
            continue;
        }
        if (sleeptime != 0) {
            chThdSleep(sleeptime);
        }
    }
}
<commit_msg>Add computation time to pose<commit_after>/*
    ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio

    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

        http://www.apache.org/licenses/LICENSE-2.0

    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.
*/

#include "ch.h"
#include "hal.h"

#include "analog.h"
#include "encoder.h"
#include "packet/frame.h"
#include "filter/movingaverage.h"

#include "gitsha1.h"
#include "angle.h"
#include "blink.h"
#include "simplebicycle.h"
#include "usbconfig.h"
#include "saconfig.h"

#include "parameters.h"

#include <algorithm>
#include <array>

namespace {
    float v = 3.0;
    /* sensors */
    Analog analog;
    Encoder encoder_steer(sa::RLS_ROLIN_ENC, sa::RLS_ROLIN_ENC_INDEX_CFG);
    EncoderFoaw<float, 32> encoder_rear_wheel(sa::RLS_GTS35_ENC,
                                              sa::RLS_GTS35_ENC_CFG,
                                              MS2ST(1), 3.0f);
    filter::MovingAverage<float, 5> velocity_filter;

    struct __attribute__((__packed__)) pose_t {
        float x; /* m */
        float y; /* m */
        float pitch; /* rad */
        float yaw; /* rad */
        float roll; /* rad */
        float steer; /* rad */
        float rear_wheel; /* rad */
        float v; /* m/s */
        uint32_t computation_time; /* time to acquire sensor data,
                                      update bicycle model,
                                      and command actuators */
        uint32_t timestamp;  /* Converted from system ticks to microseconds */
    }; /* 40 bytes */

    pose_t pose = {};

    using namespace packet::frame;
    std::array<uint8_t, sizeof(pose_t) + PACKET_OVERHEAD> packet_buffer;
} // namespace

/*
 * Application entry point.
 */
int main(void) {

    /*
     * System initializations.
     * - HAL initialization, this also initializes the configured device drivers
     *   and performs the board-specific initializations.
     * - Kernel initialization, the main() function becomes a thread and the
     *   RTOS is active.
     */
    halInit();
    chSysInit();

    /*
     * Initialize a serial-over-USB CDC driver.
     */
    sduObjectInit(&SDU1);
    sduStart(&SDU1, &serusbcfg);

    /*
     * Activate the USB driver and then the USB bus pull-up on D+.
     * Note, a delay is inserted in order to not have to disconnect the cable
     * after a reset.
     */
    board_usb_lld_disconnect_bus();   //usbDisconnectBus(serusbcfg.usbp);
    chThdSleepMilliseconds(1500);
    usbStart(serusbcfg.usbp, &usbcfg);
    board_usb_lld_connect_bus();      //usbConnectBus(serusbcfg.usbp);

    /* create the blink thread and print state monitor */
    chBlinkThreadCreateStatic();

    /*
     * Start sensors.
     * Encoder:
     *   Initialize encoder driver 5 on pins PA0, PA1 (EXT2-4, EXT2-8).
     *   Pins for encoder driver 3 are already set in board.h.
     */
    palSetLineMode(LINE_TIM5_CH1, PAL_MODE_ALTERNATE(2) | PAL_STM32_PUPDR_FLOATING);
    palSetLineMode(LINE_TIM5_CH2, PAL_MODE_ALTERNATE(2) | PAL_STM32_PUPDR_FLOATING);
    encoder_steer.start();
    encoder_rear_wheel.start();
    analog.start(1000); /* trigger ADC conversion at 1 kHz */

    /*
     * Set torque measurement enable line low.
     * The output of the Kistler torque sensor is not valid until after a falling edge
     * on the measurement line and it is held low. The 'LINE_TORQUE_MEAS_EN' line is
     * reversed due to NPN switch Q1.
     */
    palClearLine(LINE_TORQUE_MEAS_EN);
    chThdSleepMilliseconds(1);
    palSetLine(LINE_TORQUE_MEAS_EN);

    /*
     * Start DAC1 driver and set output pin as analog as suggested in Reference Manual.
     * The default line configuration is OUTPUT_OPENDRAIN_PULLUP  for SPI1_ENC1_NSS
     * and must be changed to use as analog output.
     */
    palSetLineMode(LINE_KOLLM_ACTL_TORQUE, PAL_MODE_INPUT_ANALOG);
    dacStart(sa::KOLLM_DAC, sa::KOLLM_DAC_CFG);

    /*
     * Initialize bicycle with default parameters, dt = 0.005 s.
     */
    model::SimpleBicycle bicycle(v);

    /* transmit git sha information, block until receiver is ready */
    uint8_t bytes_written = packet::frame::stuff(g_GITSHA1, packet_buffer.data(), 7);
    while ((SDU1.config->usbp->state != USB_ACTIVE) || (SDU1.state != SDU_READY)) {
        chThdSleepMilliseconds(10);
    }
    usbTransmit(SDU1.config->usbp, SDU1.config->bulk_in, packet_buffer.data(), bytes_written);

    /*
     * Normal main() thread activity, in this demo it simulates the bicycle
     * dynamics in real-time (roughly).
     */
    time_measurement_t dt;
    chTMObjectInit(&dt);
    while (true) {
        systime_t starttime = chVTGetSystemTime();
        chTMStartMeasurementX(&dt);
        constexpr float roll_torque = 0.0f;

        /* get sensor measurements */
        float steer_torque = static_cast<float>(analog.get_adc12()*2.0f*sa::MAX_KISTLER_TORQUE/4096 -
                sa::MAX_KISTLER_TORQUE);
        float motor_torque = static_cast<float>(
                analog.get_adc13()*2.0f*sa::MAX_KOLLMORGEN_TORQUE/4096 -
                sa::MAX_KOLLMORGEN_TORQUE);
        float steer_angle = angle::encoder_count<float>(encoder_steer);
        float rear_wheel_angle = -angle::encoder_count<float>(encoder_rear_wheel);

        (void)motor_torque; /* remove build warning */
        v = velocity_filter.output(
                -sa::REAR_WHEEL_RADIUS*(angle::encoder_rate(encoder_rear_wheel)));

        /* yaw angle, just use previous state value */
        float yaw_angle = angle::wrap(bicycle.pose().yaw);

        /* simulate bicycle */
        bicycle.set_v(v);
        bicycle.update(roll_torque, steer_torque, yaw_angle, steer_angle, rear_wheel_angle);

        /* generate an example torque output for testing */
        float feedback_torque = bicycle.handlebar_feedback_torque();
        int32_t saturated_value = (feedback_torque/sa::MAX_KOLLMORGEN_TORQUE * 2048) + 2048;
        saturated_value = std::min<int32_t>(std::max<int32_t>(saturated_value, 0), 4096);
        dacsample_t aout = static_cast<dacsample_t>(saturated_value);
        dacPutChannelX(sa::KOLLM_DAC, 0, aout);
        chTMStopMeasurementX(&dt);

        pose = pose_t{}; /* reset pose to zero */
        pose.x = bicycle.pose().x;
        pose.y = bicycle.pose().y;
        pose.pitch = angle::wrap(bicycle.pose().pitch);
        pose.yaw = angle::wrap(bicycle.pose().yaw);
        pose.roll = angle::wrap(bicycle.pose().roll);
        pose.steer = angle::wrap(bicycle.pose().steer);
        pose.rear_wheel = angle::wrap(bicycle.pose().rear_wheel);
        pose.v = bicycle.v();
        pose.computation_time = RTC2US(STM32_SYSCLK, dt.last);
        pose.timestamp = RTC2US(STM32_SYSCLK, chSysGetRealtimeCounterX());
        /*
         * TODO: Pose message should be transmitted asynchronously.
         * After starting transmission, the simulation should start to calculate pose for the next timestep.
         * This is currently not necessary given the observed timings.
         */
        bytes_written = packet::frame::stuff(&pose, packet_buffer.data(), sizeof(pose));
        if ((SDU1.config->usbp->state == USB_ACTIVE) && (SDU1.state == SDU_READY)) {
            usbTransmit(SDU1.config->usbp, SDU1.config->bulk_in, packet_buffer.data(), bytes_written);
        }

        systime_t dt = MS2ST(static_cast<systime_t>(1000*bicycle.dt()));
        systime_t sleeptime = dt + starttime - chVTGetSystemTime();
        if (sleeptime >= dt) {
            //chDbgAssert(false, "deadline missed");
            continue;
        }
        if (sleeptime != 0) {
            chThdSleep(sleeptime);
        }
    }
}
<|endoftext|>


<commit_before>#include "cli_parser.h"

#include <boost/filesystem.hpp>
#include <iostream>
#include <sstream>
#include <vector>

#include "log4cxx/logger.h"

template< typename TElemType >
std::ostream &operator<<(std::ostream &s, const std::vector< TElemType >& v)
{
	std::stringstream ss;

	if( !v.empty() )
	{
		typename std::vector< TElemType >::const_iterator it = v.begin(), begin = v.begin(), end = v.end();

		for( ; it < end; ++it )
		{
			if(it != begin)
				ss << " ";
			ss << *it;
		}
	}

	return s << ss.str();
}

CliParser::CliParser()
{}

CliParser::ParseResult CliParser::parse_argv(int argc, char ** argv)
{
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	LOG4CXX_INFO(logger, "Parsing command line options");

	po::options_description desc("Command line parameters");
	desc.add_options()
		("help,h",
			"Produce help message.")
		("debug",
			"Enables debug mode (will export graphs).")
		("input-image,i",
			po::value< std::string >(&(this->input_image)),
			"Input image.")
		("roi,r",
			po::value< std::string >(&(this->region_of_interest))->default_value(""),
			"Region of interest.")
		("export-dir,E",
			po::value< std::string >(&(this->export_dir))->default_value(""),
			"Export directory.")
		("export-interval,e",
			po::value< PositiveInteger >(&(this->export_interval))->default_value(0),
			"Export interval during regularization.")
		("num-iter,n",
			po::value< PositiveInteger >(&(this->num_iter))->default_value(0),
			"Number of iterations for the regularization.")
		("lambda1",
			po::value< Double >(&(this->lambda1))->default_value(1.0),
			"Lambda 1 parameter for regularization.")
		("lambda2",
			po::value< Double >(&(this->lambda2))->default_value(1.0),
			"Lambda 2 parameter for regularization.")
		("ann-image",
			po::value< std::vector< std::string > >(&(this->ann_images))->multitoken(),
			"An image from which the texture is learned (use --ann-image-class to define the regions to learn). Multiple images can be specified. If no image is specified, the input image will be used.")
		("ann-image-class",
			po::value< std::vector< std::string > >(&(this->ann_images_classes))->multitoken(),
			"Defines a class to be learned from a binary image. At least 2 values required. If multiple images are used, they must have the same number of classes.")
		("ann-config-dir",
			po::value< std::string >(&(this->ann_config_dir))->default_value(""),
			"Directory containing the neural networks configuration files.")
		("ann-hidden-layer",
			po::value< HiddenLayerVector >(&(this->ann_hidden_layers))->multitoken()->default_value(HiddenLayerVector(1, 3)),
			"Number of neurons per hidden layer (default: one layer of 3 neurons).")
		("ann-learning-rate",
			po::value< Float >(&(this->ann_learning_rate))->default_value(0.1),
			"Learning rate of the neural networks.")
		("ann-max-epoch",
			po::value< StrictlyPositiveInteger >(&(this->ann_max_epoch))->default_value(1000),
			"Maximum number of training iterations for the neural networks.")
		("ann-mse-target",
			po::value< Float >(&(this->ann_mse_target))->default_value(0.0001),
			"Mean squared error targeted by the neural networks training algorithm.")
		("ann-validation-image",
			po::value< std::vector< std::string > >(&(this->ann_validation_images))->multitoken(),
			"The images to use to validate the training of the neural network (use --ann-validation-image-class to define associated classes). Multiple images can be specified. They mush have the same number of components per pixels than the images on which the neural network is trained.")
		("ann-validation-image-class",
			po::value< std::vector< std::string > >(&(this->ann_validation_images_classes))->multitoken(),
			"Defines the classes of the images used to validate de training of the neural network. If multiple images are used, they must have as much classes as the images on which the neural network is trained.")
		("ann-build-validation-from-training",
			po::value< Percentage >(&(this->ann_validation_training_ratio))->default_value(Percentage(0.0f)),
			"The percentage of elements from the training-set to extract to build the validation-set.")
		;

	po::variables_map vm;

	try {
		po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);

		// Handling --help before notify() in order to allow ->required()
		// http://stackoverflow.com/questions/5395503/required-and-optional-arguments-using-boost-library-program-options#answer-5517755
		if (vm.count("help")) {
			std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
			std::cout << desc;
			return EXIT;
		}

		po::notify(vm);
	} catch(po::error &err) {
		throw CliException(err.what());
	}

	this->debug = vm.count("debug");

	check_ann_parameters(vm);

	if( !this->input_image.empty() ) {
		check_regularization_parameters(vm);
	} else {
		if(this->ann_config_dir.empty()) {
			throw CliException("The directory where to save the neural networks configuration is not specified.");
		}
	}

	print_ann_parameters();

	if( !this->input_image.empty() )
		print_regularization_parameters();

	return CONTINUE;
}

const bool CliParser::get_debug() const
{
	return this->debug;
}

const std::string CliParser::get_input_image() const
{
	return this->input_image;
}

const std::string CliParser::get_export_dir() const
{
	return this->export_dir;
}

const std::string CliParser::get_region_of_interest() const
{
	return this->region_of_interest;
}

const int CliParser::get_export_interval() const
{
	return this->export_interval;
}

const int CliParser::get_num_iter() const
{
	return this->num_iter;
}

const double CliParser::get_lambda1() const {
	return this->lambda1;
}

const double CliParser::get_lambda2() const {
	return this->lambda2;
}

const std::string CliParser::get_ann_config_dir() const
{
	return this->ann_config_dir;
}

const std::vector<std::string> CliParser::get_ann_images() const
{
	return this->ann_images;
}

const std::vector<std::string> CliParser::get_ann_images_classes() const
{
	return this->ann_images_classes;
}

const std::vector< unsigned int > CliParser::get_ann_hidden_layers() const {
	return std::vector< unsigned int >(this->ann_hidden_layers.begin(), this->ann_hidden_layers.end());
}

const float CliParser::get_ann_learning_rate() const {
	return this->ann_learning_rate;
}

const unsigned int CliParser::get_ann_max_epoch() const {
	return this->ann_max_epoch;
}

const float CliParser::get_ann_mse_target() const {
	return this->ann_mse_target;
}

const std::vector<std::string> CliParser::get_ann_validation_images() const
{
	return this->ann_validation_images;
}

const std::vector<std::string> CliParser::get_ann_validation_images_classes() const
{
	return this->ann_validation_images_classes;
}

const float CliParser::get_ann_validation_training_ratio() const {
	return this->ann_validation_training_ratio;
}

/*
 * If there is no image classes, the classifier must be loaded from a stored configuration (no training will be performed):
 *     Throw an exception if no directory for the sorted configuration is provided.
 * Otherwise, (we need to find everything to train the classifiers):
 *     If there is no training image provided, we will use the input-image that will be processed.
 *         Throw an exception if there is no input-image.
 *         Set the number of images and classes.
 *     Otherwise, (at least one training-image is provided):
 *         Throw an exception if the number of training-image is not coherent with the number of classes
 *         (there must be at least two classes per image, and the total number of image-classes must
 *         be a multiple of the number of training-images).
 *
 *     If there is at least one validation-image provided:
 *         Throw an exception if there is an option asking to build the validation-set from the training-set.
 *         Throw an exception if the number of validation-classes is not coherent with the number of
 *         validation-images or if the number of validation classes is different from tne number of training-classes.
 */
void CliParser::check_ann_parameters(po::variables_map &vm) {
	if(this->ann_images_classes.empty()) {
		/*
		 * If no class is specified, the neural network
		 * must be loaded from a stored configuration.
		 */
		if(this->ann_config_dir.empty()) {
			throw CliException("You must either load the neural network from a stored configuration or specify"
			                   " the image(s) and classes to use for training.");
		}
	} else {
		/*
		 * Some classes have been provided.
		 */
		int number_of_images, number_of_classes, number_of_classes_per_image;

		if(this->ann_images.empty()) {
			/*
			 * If no learning image have been provided,
			 * we use the input image of the algorithm.
			 */
			if(this->input_image.empty()) {
				throw CliException("No image can be used to train the neural networks. You need to either specify"
				                   "a list of images to use to train the neural networks, or provide an input image"
				                   "for the algorithm.");
			}

			number_of_images            = 1;
			number_of_classes           = this->ann_images_classes.size();
			number_of_classes_per_image = number_of_classes;
		} else {
			/*
			 * We need to have the same number of classes (at least 2) for every
			 * image used for the training of the neural networks.
			 */
			number_of_images            = this->ann_images.size();
			number_of_classes           = this->ann_images_classes.size();
			number_of_classes_per_image = number_of_classes / number_of_images;

			if((number_of_classes % number_of_images != 0) || // Enough class for each image
			   (number_of_classes_per_image < 2))             // At least two class per image
			{
				throw CliException("You need to provide the same number of classes (at least two) "
						"for every image used for learning.");
			}
		}

		if(!this->ann_validation_images.empty()) {
			if(vm.count("ann-build-validation-from-training")) {
				throw CliException("You can't use the --ann-build-validation-from-training option when you specify the classes for the validation-set.");
			}

			const int number_of_validation_images = this->ann_validation_images.size(),
			          number_of_validation_classes = this->ann_validation_images_classes.size(),
			          number_of_classes_per_validation_image = number_of_validation_classes / number_of_validation_images;

			if((number_of_validation_classes % number_of_validation_images != 0) ||     // Enough class for each image
			   (number_of_classes_per_validation_image < 2) ||                          // At least two class per image
			   (number_of_classes_per_validation_image != number_of_classes_per_image)) // As many classes as the for the images used in training
			{
				throw CliException("You have an invalid number of classes for the validation images.");
			}
		}
	}
}

void CliParser::check_regularization_parameters(po::variables_map &vm) {
	if(this->export_dir.empty())
		throw CliException("You need to provide an export directory.");
}

void CliParser::print_ann_parameters() {
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	if(this->ann_images_classes.empty()) {
		if(!this->ann_config_dir.empty()) {
			LOG4CXX_INFO(logger, "The neural networks will be loaded from: " << this->ann_config_dir);
		}
	} else {
		std::vector< std::string > training_images = (this->ann_images.size() == 0 ? std::vector< std::string >(1, this->input_image) : this->ann_images);
		const int number_of_images = training_images.size();
		const int number_of_classes = this->ann_images_classes.size();
		const int number_of_classes_per_image = number_of_classes / number_of_images;

		LOG4CXX_INFO(logger, "Neural networks parameters:");
		LOG4CXX_INFO(logger, number_of_images << " images provided for training.");

		for(int j = 0; j < number_of_images; ++j) {
			LOG4CXX_INFO(logger, "\tImage " << (j + 1) << ": " << training_images[j]);

			for(int i = 0; i < number_of_classes_per_image; ++i) {
				LOG4CXX_INFO(logger, "\t\tClass " << (i + 1) << ": " << this->ann_images_classes[j * number_of_classes_per_image + i]);
			}
		}

		std::stringstream m;
		m << this->ann_hidden_layers;
		LOG4CXX_INFO(logger, "\tNumber of hidden neurons per layer: " << m.str());

		LOG4CXX_INFO(logger, "\tLearning rate: " << this->ann_learning_rate);
		LOG4CXX_INFO(logger, "\tMaximum number of iterations: " << this->ann_max_epoch.value);
		LOG4CXX_INFO(logger, "\tMean squared error targeted: " << this->ann_mse_target);
	}
}

void CliParser::print_regularization_parameters() {
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	LOG4CXX_INFO(logger, "Regularization parameters:");
	LOG4CXX_INFO(logger,    "\tInput image: "          << this->input_image);
	LOG4CXX_INFO(logger,    "\tExport directory: "     << this->export_dir);
	LOG4CXX_INFO(logger,    "\tRegion of interest: "   << this->region_of_interest);
	LOG4CXX_INFO(logger,    "\tExport interval: "      << this->export_interval);
	LOG4CXX_INFO(logger,    "\tNumber of iterations: " << this->num_iter);
	LOG4CXX_INFO(logger,    "\tLambda1: "              << this->lambda1);
	LOG4CXX_INFO(logger,    "\tLambda2: "              << this->lambda2);
}
<commit_msg>Removes a blank line.<commit_after>#include "cli_parser.h"

#include <boost/filesystem.hpp>
#include <iostream>
#include <sstream>
#include <vector>

#include "log4cxx/logger.h"

template< typename TElemType >
std::ostream &operator<<(std::ostream &s, const std::vector< TElemType >& v)
{
	std::stringstream ss;

	if( !v.empty() )
	{
		typename std::vector< TElemType >::const_iterator it = v.begin(), begin = v.begin(), end = v.end();

		for( ; it < end; ++it )
		{
			if(it != begin)
				ss << " ";
			ss << *it;
		}
	}

	return s << ss.str();
}

CliParser::CliParser()
{}

CliParser::ParseResult CliParser::parse_argv(int argc, char ** argv)
{
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	LOG4CXX_INFO(logger, "Parsing command line options");

	po::options_description desc("Command line parameters");
	desc.add_options()
		("help,h",
			"Produce help message.")
		("debug",
			"Enables debug mode (will export graphs).")
		("input-image,i",
			po::value< std::string >(&(this->input_image)),
			"Input image.")
		("roi,r",
			po::value< std::string >(&(this->region_of_interest))->default_value(""),
			"Region of interest.")
		("export-dir,E",
			po::value< std::string >(&(this->export_dir))->default_value(""),
			"Export directory.")
		("export-interval,e",
			po::value< PositiveInteger >(&(this->export_interval))->default_value(0),
			"Export interval during regularization.")
		("num-iter,n",
			po::value< PositiveInteger >(&(this->num_iter))->default_value(0),
			"Number of iterations for the regularization.")
		("lambda1",
			po::value< Double >(&(this->lambda1))->default_value(1.0),
			"Lambda 1 parameter for regularization.")
		("lambda2",
			po::value< Double >(&(this->lambda2))->default_value(1.0),
			"Lambda 2 parameter for regularization.")
		("ann-image",
			po::value< std::vector< std::string > >(&(this->ann_images))->multitoken(),
			"An image from which the texture is learned (use --ann-image-class to define the regions to learn). Multiple images can be specified. If no image is specified, the input image will be used.")
		("ann-image-class",
			po::value< std::vector< std::string > >(&(this->ann_images_classes))->multitoken(),
			"Defines a class to be learned from a binary image. At least 2 values required. If multiple images are used, they must have the same number of classes.")
		("ann-config-dir",
			po::value< std::string >(&(this->ann_config_dir))->default_value(""),
			"Directory containing the neural networks configuration files.")
		("ann-hidden-layer",
			po::value< HiddenLayerVector >(&(this->ann_hidden_layers))->multitoken()->default_value(HiddenLayerVector(1, 3)),
			"Number of neurons per hidden layer (default: one layer of 3 neurons).")
		("ann-learning-rate",
			po::value< Float >(&(this->ann_learning_rate))->default_value(0.1),
			"Learning rate of the neural networks.")
		("ann-max-epoch",
			po::value< StrictlyPositiveInteger >(&(this->ann_max_epoch))->default_value(1000),
			"Maximum number of training iterations for the neural networks.")
		("ann-mse-target",
			po::value< Float >(&(this->ann_mse_target))->default_value(0.0001),
			"Mean squared error targeted by the neural networks training algorithm.")
		("ann-validation-image",
			po::value< std::vector< std::string > >(&(this->ann_validation_images))->multitoken(),
			"The images to use to validate the training of the neural network (use --ann-validation-image-class to define associated classes). Multiple images can be specified. They mush have the same number of components per pixels than the images on which the neural network is trained.")
		("ann-validation-image-class",
			po::value< std::vector< std::string > >(&(this->ann_validation_images_classes))->multitoken(),
			"Defines the classes of the images used to validate de training of the neural network. If multiple images are used, they must have as much classes as the images on which the neural network is trained.")
		("ann-build-validation-from-training",
			po::value< Percentage >(&(this->ann_validation_training_ratio))->default_value(Percentage(0.0f)),
			"The percentage of elements from the training-set to extract to build the validation-set.")
		;

	po::variables_map vm;

	try {
		po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);

		// Handling --help before notify() in order to allow ->required()
		// http://stackoverflow.com/questions/5395503/required-and-optional-arguments-using-boost-library-program-options#answer-5517755
		if (vm.count("help")) {
			std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
			std::cout << desc;
			return EXIT;
		}

		po::notify(vm);
	} catch(po::error &err) {
		throw CliException(err.what());
	}

	this->debug = vm.count("debug");

	check_ann_parameters(vm);

	if( !this->input_image.empty() ) {
		check_regularization_parameters(vm);
	} else {
		if(this->ann_config_dir.empty()) {
			throw CliException("The directory where to save the neural networks configuration is not specified.");
		}
	}

	print_ann_parameters();

	if( !this->input_image.empty() )
		print_regularization_parameters();

	return CONTINUE;
}

const bool CliParser::get_debug() const
{
	return this->debug;
}

const std::string CliParser::get_input_image() const
{
	return this->input_image;
}

const std::string CliParser::get_export_dir() const
{
	return this->export_dir;
}

const std::string CliParser::get_region_of_interest() const
{
	return this->region_of_interest;
}

const int CliParser::get_export_interval() const
{
	return this->export_interval;
}

const int CliParser::get_num_iter() const
{
	return this->num_iter;
}

const double CliParser::get_lambda1() const {
	return this->lambda1;
}

const double CliParser::get_lambda2() const {
	return this->lambda2;
}

const std::string CliParser::get_ann_config_dir() const
{
	return this->ann_config_dir;
}

const std::vector<std::string> CliParser::get_ann_images() const
{
	return this->ann_images;
}

const std::vector<std::string> CliParser::get_ann_images_classes() const
{
	return this->ann_images_classes;
}

const std::vector< unsigned int > CliParser::get_ann_hidden_layers() const {
	return std::vector< unsigned int >(this->ann_hidden_layers.begin(), this->ann_hidden_layers.end());
}

const float CliParser::get_ann_learning_rate() const {
	return this->ann_learning_rate;
}

const unsigned int CliParser::get_ann_max_epoch() const {
	return this->ann_max_epoch;
}

const float CliParser::get_ann_mse_target() const {
	return this->ann_mse_target;
}

const std::vector<std::string> CliParser::get_ann_validation_images() const
{
	return this->ann_validation_images;
}

const std::vector<std::string> CliParser::get_ann_validation_images_classes() const
{
	return this->ann_validation_images_classes;
}

const float CliParser::get_ann_validation_training_ratio() const {
	return this->ann_validation_training_ratio;
}

/*
 * If there is no image classes, the classifier must be loaded from a stored configuration (no training will be performed):
 *     Throw an exception if no directory for the sorted configuration is provided.
 * Otherwise, (we need to find everything to train the classifiers):
 *     If there is no training image provided, we will use the input-image that will be processed.
 *         Throw an exception if there is no input-image.
 *         Set the number of images and classes.
 *     Otherwise, (at least one training-image is provided):
 *         Throw an exception if the number of training-image is not coherent with the number of classes
 *         (there must be at least two classes per image, and the total number of image-classes must
 *         be a multiple of the number of training-images).
 *
 *     If there is at least one validation-image provided:
 *         Throw an exception if there is an option asking to build the validation-set from the training-set.
 *         Throw an exception if the number of validation-classes is not coherent with the number of
 *         validation-images or if the number of validation classes is different from tne number of training-classes.
 */
void CliParser::check_ann_parameters(po::variables_map &vm) {
	if(this->ann_images_classes.empty()) {
		/*
		 * If no class is specified, the neural network
		 * must be loaded from a stored configuration.
		 */
		if(this->ann_config_dir.empty()) {
			throw CliException("You must either load the neural network from a stored configuration or specify"
			                   " the image(s) and classes to use for training.");
		}
	} else {
		/*
		 * Some classes have been provided.
		 */
		int number_of_images, number_of_classes, number_of_classes_per_image;

		if(this->ann_images.empty()) {
			/*
			 * If no learning image have been provided,
			 * we use the input image of the algorithm.
			 */
			if(this->input_image.empty()) {
				throw CliException("No image can be used to train the neural networks. You need to either specify"
				                   "a list of images to use to train the neural networks, or provide an input image"
				                   "for the algorithm.");
			}

			number_of_images            = 1;
			number_of_classes           = this->ann_images_classes.size();
			number_of_classes_per_image = number_of_classes;
		} else {
			/*
			 * We need to have the same number of classes (at least 2) for every
			 * image used for the training of the neural networks.
			 */
			number_of_images            = this->ann_images.size();
			number_of_classes           = this->ann_images_classes.size();
			number_of_classes_per_image = number_of_classes / number_of_images;

			if((number_of_classes % number_of_images != 0) || // Enough class for each image
			   (number_of_classes_per_image < 2))             // At least two class per image
			{
				throw CliException("You need to provide the same number of classes (at least two) "
						"for every image used for learning.");
			}
		}

		if(!this->ann_validation_images.empty()) {
			if(vm.count("ann-build-validation-from-training")) {
				throw CliException("You can't use the --ann-build-validation-from-training option when you specify the classes for the validation-set.");
			}

			const int number_of_validation_images = this->ann_validation_images.size(),
			          number_of_validation_classes = this->ann_validation_images_classes.size(),
			          number_of_classes_per_validation_image = number_of_validation_classes / number_of_validation_images;

			if((number_of_validation_classes % number_of_validation_images != 0) ||     // Enough class for each image
			   (number_of_classes_per_validation_image < 2) ||                          // At least two class per image
			   (number_of_classes_per_validation_image != number_of_classes_per_image)) // As many classes as the for the images used in training
			{
				throw CliException("You have an invalid number of classes for the validation images.");
			}
		}
	}
}

void CliParser::check_regularization_parameters(po::variables_map &vm) {
	if(this->export_dir.empty())
		throw CliException("You need to provide an export directory.");
}

void CliParser::print_ann_parameters() {
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	if(this->ann_images_classes.empty()) {
		if(!this->ann_config_dir.empty()) {
			LOG4CXX_INFO(logger, "The neural networks will be loaded from: " << this->ann_config_dir);
		}
	} else {
		std::vector< std::string > training_images = (this->ann_images.size() == 0 ? std::vector< std::string >(1, this->input_image) : this->ann_images);
		const int number_of_images = training_images.size();
		const int number_of_classes = this->ann_images_classes.size();
		const int number_of_classes_per_image = number_of_classes / number_of_images;

		LOG4CXX_INFO(logger, "Neural networks parameters:");
		LOG4CXX_INFO(logger, number_of_images << " images provided for training.");

		for(int j = 0; j < number_of_images; ++j) {
			LOG4CXX_INFO(logger, "\tImage " << (j + 1) << ": " << training_images[j]);

			for(int i = 0; i < number_of_classes_per_image; ++i) {
				LOG4CXX_INFO(logger, "\t\tClass " << (i + 1) << ": " << this->ann_images_classes[j * number_of_classes_per_image + i]);
			}
		}

		std::stringstream m;
		m << this->ann_hidden_layers;
		LOG4CXX_INFO(logger, "\tNumber of hidden neurons per layer: " << m.str());

		LOG4CXX_INFO(logger, "\tLearning rate: " << this->ann_learning_rate);
		LOG4CXX_INFO(logger, "\tMaximum number of iterations: " << this->ann_max_epoch.value);
		LOG4CXX_INFO(logger, "\tMean squared error targeted: " << this->ann_mse_target);
	}
}

void CliParser::print_regularization_parameters() {
	log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("main"));

	LOG4CXX_INFO(logger, "Regularization parameters:");
	LOG4CXX_INFO(logger,    "\tInput image: "          << this->input_image);
	LOG4CXX_INFO(logger,    "\tExport directory: "     << this->export_dir);
	LOG4CXX_INFO(logger,    "\tRegion of interest: "   << this->region_of_interest);
	LOG4CXX_INFO(logger,    "\tExport interval: "      << this->export_interval);
	LOG4CXX_INFO(logger,    "\tNumber of iterations: " << this->num_iter);
	LOG4CXX_INFO(logger,    "\tLambda1: "              << this->lambda1);
	LOG4CXX_INFO(logger,    "\tLambda2: "              << this->lambda2);
}
<|endoftext|>


<commit_before>#include "trajectory/dubins_steer.h"

#include <iostream>
#include <cmath>

int main()
{
	std::vector<std::vector<double> > traj_desc(3, std::vector<double>(7, INFINITY));
	std::vector<double> z_0 = {0, 0, 0};
	std::vector<double> z_f = {5, 5, M_PI/2};
	double radius_L = 5;
	double radius_R = 5;
	double min_length;
	DubinsSteer::SteerData dubins_steer_data;
	min_length = DubinsSteer::GetDubinsCurveLength(z_0, z_f, radius_L, radius_R);
	// std::cout << "min length is " << min_length << std::endl;
	dubins_steer_data = DubinsSteer::GetDubinsTrajectoryPointWise(z_0, z_f, radius_L, radius_R);
	std::vector<double> test_traj_point_wise = dubins_steer_data.traj_point_wise[0];
	std::cout << "piece_wise: " << test_traj_point_wise[0] << ", " << test_traj_point_wise[1] << ", " << test_traj_point_wise[2] << std::endl;
	std::cout << "Min curve length is " << dubins_steer_data.traj_length << std::endl;
	// for (int i = 0; i < dubins_steer_data.traj_len_map.size(); i++) {
	// 	std::cout << "traj_len_map: " << dubins_steer_data.traj_len_map[i] << std::endl;
	// }

    return 0;
}<commit_msg>bug fixing<commit_after>#include "trajectory/dubins_steer.h"

#include <iostream>
#include <cmath>

int main()
{
	std::vector<std::vector<double> > traj_desc(3, std::vector<double>(7, INFINITY));
	std::vector<double> z_0 = {0, 0, 0};
	std::vector<double> z_f = {5, 5, M_PI/2};
	double radius_L = 5;
	double radius_R = 5;
	double min_length;
	DubinsSteer::SteerData dubins_steer_data;
	min_length = DubinsSteer::GetDubinsCurveLength(z_0, z_f, radius_L, radius_R);
	// std::cout << "min length is " << min_length << std::endl;
	dubins_steer_data = DubinsSteer::GetDubinsTrajectoryPointWise(z_0, z_f, radius_L, radius_R);
	std::vector<std::vector<double>> test_traj_point_wise = dubins_steer_data.traj_point_wise;
	for (int i =0; i < test_traj_point_wise.size(); i++) {
		std::cout << "piece_wise: " << test_traj_point_wise[i][0] << ", " << test_traj_point_wise[i][1] << ", " << test_traj_point_wise[i][2] << std::endl;
	}
	std::cout << "piece_wise: " << test_traj_point_wise[0] << ", " << test_traj_point_wise[1] << ", " << test_traj_point_wise[2] << std::endl;
	std::cout << "Min curve length is " << dubins_steer_data.traj_length << std::endl;
	// for (int i = 0; i < dubins_steer_data.traj_len_map.size(); i++) {
	// 	std::cout << "traj_len_map: " << dubins_steer_data.traj_len_map[i] << std::endl;
	// }

    return 0;
}<|endoftext|>


<commit_before>// $Id$
//
// Emcal physics selection class
//
//

#include "AliEmcalPhysicsSelection.h"
#include "AliESDEvent.h"
#include "AliLog.h"

ClassImp(AliEmcalPhysicsSelection)

AliEmcalPhysicsSelection::AliEmcalPhysicsSelection() :
  AliPhysicsSelection(),
  fMarkFastOnly(0),
  fMarkLedEvent(0),
  fSkipFastOnly(0),
  fSkipLedEvent(0),
  fCellMinE(2),
  fClusMinE(5),
  fIsFastOnly(0),
  fIsLedEvent(0),
  fIsGoodEvent(0),
  fCellMaxE(0),
  fClusMaxE(0)
{
  // Default constructor.
}

//__________________________________________________________________________________________________
UInt_t AliEmcalPhysicsSelection::GetSelectionMask(const TObject* obj)
{
  const AliESDEvent *ev = static_cast<const AliESDEvent*>(obj);
  UInt_t res = IsCollisionCandidate(ev);

  fIsFastOnly  = kFALSE;
  fIsGoodEvent = kFALSE;
  fIsLedEvent  = kFALSE;
  fCellMaxE    = 0;
  fClusMaxE    = 0;

  if ((res & AliVEvent::kAnyINT) ||
      (res & AliVEvent::kEMC1)   ||
      (res & AliVEvent::kEMC7))
    fIsGoodEvent = kTRUE;

  AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
  am->LoadBranch("EMCALCells.");
  am->LoadBranch("CaloClusters");

  AliESDCaloCells *cells = ev->GetEMCALCells();
  const Short_t nCells   = cells->GetNumberOfCells();

  // mark LHC11a fast only partition if requested
  if (res & AliVEvent::kFastOnly) {
    fIsFastOnly = kTRUE;
    if (fMarkFastOnly||fSkipFastOnly) {
      if (nCells>0) {
        AliFatal(Form("Number of cells %d, even though EMCAL should not be in fast only partition.",nCells));
      }
      fIsGoodEvent = kFALSE;
    }
  }

  // count cells above threshold
  Int_t nCellCount[10] = {0,0,0,0,0,0,0,0,0,0};
  for(Int_t iCell=0; iCell<nCells; ++iCell) {
    Short_t cellId = cells->GetCellNumber(iCell);
    Double_t cellE = cells->GetCellAmplitude(cellId);
    Int_t sm       = cellId / (24*48);
    if (cellE>0.1)
      ++nCellCount[sm];
    if (cellE>fCellMaxE)
      fCellMaxE = cellE;
  }

  const Int_t nCaloClusters = ev->GetNumberOfCaloClusters();
  for(Int_t iClus = 0; iClus<nCaloClusters; ++iClus) {
    AliESDCaloCluster *cl = ev->GetCaloCluster(iClus);
    if (!cl->IsEMCAL())
      continue;
    Double_t e = cl->E();
    if (e>fClusMaxE)
      fClusMaxE = e;
  }

  // bad cell criterion for LHC11a from
  // https://indico.cern.ch/materialDisplay.py?contribId=4&materialId=slides&confId=147067
  const Int_t runN = ev->GetRunNumber();
  if ((runN>=144871) && (runN<=146860)) {
    if (nCellCount[4] > 100)
      fIsLedEvent = kTRUE;
    else {
      if ((runN>=146858) && (runN<=146860)) {
        if ((res&AliVEvent::kMB) && (nCellCount[3]>=21))
          fIsLedEvent = kTRUE;
        else if ((res&AliVEvent::kEMC1) && (nCellCount[3]>=35))
          fIsLedEvent = kTRUE;
      }
    }
    if (fIsLedEvent) {
      fIsGoodEvent = kFALSE;
    }
  }

  if (fCellMaxE>=fCellMinE)
    res |= kEmcalHC;

  if (fClusMaxE>=fClusMinE)
    res |= kEmcalHT;

  if (fIsGoodEvent)
    res |= kEmcalOk;

  if ((fSkipLedEvent && fIsLedEvent) ||
      (fSkipFastOnly && fIsFastOnly))
    res = 0;

  return res;
}
<commit_msg>handle AOD<commit_after>// $Id$
//
// Emcal physics selection class
//
//

#include "AliEmcalPhysicsSelection.h"
#include "AliAODEvent.h"
#include "AliESDEvent.h"
#include "AliLog.h"

ClassImp(AliEmcalPhysicsSelection)

AliEmcalPhysicsSelection::AliEmcalPhysicsSelection() :
  AliPhysicsSelection(),
  fMarkFastOnly(0),
  fMarkLedEvent(0),
  fSkipFastOnly(0),
  fSkipLedEvent(0),
  fCellMinE(2),
  fClusMinE(5),
  fIsFastOnly(0),
  fIsLedEvent(0),
  fIsGoodEvent(0),
  fCellMaxE(0),
  fClusMaxE(0)
{
  // Default constructor.
}

//__________________________________________________________________________________________________
UInt_t AliEmcalPhysicsSelection::GetSelectionMask(const TObject* obj)
{
  // Calculate selection mask.

  const AliVEvent *ev   = dynamic_cast<const AliVEvent*>(obj);
  if (!ev) {
    return 0;
  }

  UInt_t res = 0;
  const AliESDEvent *eev = dynamic_cast<const AliESDEvent*>(obj);
  const AliAODEvent *aev = 0;
  if (eev) {
    res = IsCollisionCandidate(eev);
  } else {
    aev = dynamic_cast<const AliAODEvent*>(obj);
    res = aev->GetHeader()->GetOfflineTrigger();
  }

  fIsFastOnly  = kFALSE;
  fIsGoodEvent = kFALSE;
  fIsLedEvent  = kFALSE;
  fCellMaxE    = 0;
  fClusMaxE    = 0;

  if ((res & AliVEvent::kAnyINT) ||
      (res & AliVEvent::kEMC1)   ||
      (res & AliVEvent::kEMC7)   ||
      (res & AliVEvent::kEMCEJE) ||
      (res & AliVEvent::kEMCEGA))
    fIsGoodEvent = kTRUE;

  AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
  am->LoadBranch("EMCALCells.");
  am->LoadBranch("CaloClusters");

  AliVCaloCells *cells = ev->GetEMCALCells();
  const Short_t nCells   = cells->GetNumberOfCells();

  // mark LHC11a fast only partition if requested
  if (res & AliVEvent::kFastOnly) {
    fIsFastOnly = kTRUE;
    if (fMarkFastOnly||fSkipFastOnly) {
      if (nCells>0) {
        AliFatal(Form("Number of cells %d, even though EMCAL should not be in fast only partition.",nCells));
      }
      fIsGoodEvent = kFALSE;
    }
  }

  // count cells above threshold
  Int_t nCellCount[10] = {0,0,0,0,0,0,0,0,0,0};
  for(Int_t iCell=0; iCell<nCells; ++iCell) {
    Short_t cellId = cells->GetCellNumber(iCell);
    Double_t cellE = cells->GetCellAmplitude(cellId);
    Int_t sm       = cellId / (24*48);
    if (cellE>0.1)
      ++nCellCount[sm];
    if (cellE>fCellMaxE)
      fCellMaxE = cellE;
  }

  const Int_t nCaloClusters = ev->GetNumberOfCaloClusters();
  for(Int_t iClus = 0; iClus<nCaloClusters; ++iClus) {
    AliVCluster *cl = ev->GetCaloCluster(iClus);
    if (!cl->IsEMCAL())
      continue;
    Double_t e = cl->E();
    if (e>fClusMaxE)
      fClusMaxE = e;
  }

  // bad cell criterion for LHC11a from
  // https://indico.cern.ch/materialDisplay.py?contribId=4&materialId=slides&confId=147067
  const Int_t runN = ev->GetRunNumber();
  if ((runN>=144871) && (runN<=146860)) {
    if (nCellCount[4] > 100)
      fIsLedEvent = kTRUE;
    else {
      if ((runN>=146858) && (runN<=146860)) {
        if ((res&AliVEvent::kMB) && (nCellCount[3]>=21))
          fIsLedEvent = kTRUE;
        else if ((res&AliVEvent::kEMC1) && (nCellCount[3]>=35))
          fIsLedEvent = kTRUE;
      }
    }
    if (fIsLedEvent) {
      fIsGoodEvent = kFALSE;
    }
  }

  if (fCellMaxE>=fCellMinE)
    res |= kEmcalHC;

  if (fClusMaxE>=fClusMinE)
    res |= kEmcalHT;

  if (fIsGoodEvent)
    res |= kEmcalOk;

  if ((fSkipLedEvent && fIsLedEvent) ||
      (fSkipFastOnly && fIsFastOnly))
    res = 0;

  return res;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
//
////////////////////////////////////////////////////////////////////////////

#define CATCH_CONFIG_RUNNER
#include "realm/util/features.h"
#if REALM_PLATFORM_APPLE
#define CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#include <catch2/catch.hpp>
#include <external/json/json.hpp>
#include <realm/util/to_string.hpp>

#include <limits.h>

#ifdef _MSC_VER
#include <Windows.h>

// PathCchRemoveFileSpec()
#include <pathcch.h>
#pragma comment(lib, "Pathcch.lib")
#else
#include <libgen.h>
#endif

int main(int argc, char** argv)
{
#ifdef _MSC_VER
    wchar_t path[MAX_PATH];
    if (GetModuleFileName(NULL, path, MAX_PATH) == 0) {
        fprintf(stderr, "Failed to retrieve path to exectuable.\n");
        return 1;
    }
    PathCchRemoveFileSpec(path, MAX_PATH);
    SetCurrentDirectory(path);
#else
    char executable[PATH_MAX];
    if (realpath(argv[0], executable) == NULL) {
        fprintf(stderr, "Failed to resolve path to exectuable.\n");
        return 1;
    }
    const char* directory = dirname(executable);
    if (chdir(directory) < 0) {
        fprintf(stderr, "Failed to change directory.\n");
        return 1;
    }
#endif
    int result = -1;
    if (const char* str = getenv("UNITTEST_EVERGREEN_TEST_RESULTS"); str && strlen(str) != 0) {
        std::cout << "Configuring evergreen reporter to store test results in " << str << std::endl;
        Catch::ConfigData config;
        config.reporterName = "evergreen";
        config.outputFilename = str;
        Catch::Session session;
        session.useConfigData(config);
        result = session.run();
    }
    else {
        result = Catch::Session().run(argc, argv);
    }
    return result < 0xff ? result : 0xff;
}

namespace Catch {
class EvergreenReporter : public CumulativeReporterBase<EvergreenReporter> {
public:
    using Base = CumulativeReporterBase<EvergreenReporter>;
    explicit EvergreenReporter(ReporterConfig const& config)
        : Base(config)
    {
    }
    ~EvergreenReporter() = default;
    static std::string getDescription()
    {
        return "Reports test results in a format consumable by Evergreen.";
    }
    void noMatchingTestCases(std::string const& /*spec*/) override {}
    using Base::assertionEnded;
    using Base::testGroupEnded;
    using Base::testGroupStarting;
    using Base::testRunStarting;

    void testCaseStarting(TestCaseInfo const& testCaseInfo) override
    {
        m_results.emplace(std::make_pair(testCaseInfo.name, TestResult{}));
        Base::testCaseStarting(testCaseInfo);
    }
    void testCaseEnded(TestCaseStats const& testCaseStats) override
    {
        auto it = m_results.find(testCaseStats.testInfo.name);
        if (it == m_results.end()) {
            throw std::runtime_error("logic error in Evergreen section reporter, could not end test case '" +
                                     testCaseStats.testInfo.name + "' which was never tracked as started.");
        }
        if (testCaseStats.totals.assertions.allPassed()) {
            it->second.status = "pass";
        }
        else {
            it->second.status = "fail";
        }
        it->second.end_time = std::chrono::system_clock::now();
        Base::testCaseEnded(testCaseStats);
    }
    void sectionStarting(SectionInfo const& sectionInfo) override
    {
        if (m_pending_name.empty()) {
            m_pending_name = sectionInfo.name;
        }
        else {
            m_pending_name += "::" + sectionInfo.name;
        }
        m_pending_test = {};
        Base::sectionStarting(sectionInfo);
    }
    void sectionEnded(SectionStats const& sectionStats) override
    {
        if (!m_pending_name.empty()) {
            if (sectionStats.assertions.allPassed()) {
                m_pending_test.status = "pass";
            }
            else {
                m_pending_test.status = "fail";
            }
            m_pending_test.end_time = std::chrono::system_clock::now();
            m_results.emplace(std::make_pair(m_pending_name, m_pending_test));
            m_pending_name = "";
        }
        Base::sectionEnded(sectionStats);
    }
    void testRunEndedCumulative() override
    {
        auto results_arr = nlohmann::json::array();
        for (const auto& [test_name, cur_result] : m_results) {
            auto to_millis = [](const auto& tp) -> double {
                return static_cast<double>(
                    std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count());
            };
            double start_secs = to_millis(cur_result.start_time) / 1000;
            double end_secs = to_millis(cur_result.end_time) / 1000;
            int exit_code = 0;
            if (cur_result.status != "pass") {
                exit_code = 1;
            }

            nlohmann::json cur_result_obj = {{"test_file", test_name}, {"status", cur_result.status},
                                             {"exit_code", exit_code}, {"start", start_secs},
                                             {"end", end_secs},        {"elapsed", end_secs - start_secs}};
            results_arr.push_back(std::move(cur_result_obj));
        }
        auto result_file_obj = nlohmann::json{{"results", std::move(results_arr)}};
        stream << result_file_obj << std::endl;
    }

    struct TestResult {
        TestResult()
            : start_time{std::chrono::system_clock::now()}
            , end_time{}
            , status{"unknown"}
        {
        }
        std::chrono::system_clock::time_point start_time;
        std::chrono::system_clock::time_point end_time;
        std::string status;
    };
    TestResult m_pending_test;
    std::string m_pending_name;
    std::vector<std::pair<std::string, TestResult>> m_current_stack;
    std::map<std::string, TestResult> m_results;
};

CATCH_REGISTER_REPORTER("evergreen", EvergreenReporter)

} // end namespace Catch
<commit_msg>print error info when object-store tests fail on evergreen (#4661)<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
//
////////////////////////////////////////////////////////////////////////////

#define CATCH_CONFIG_RUNNER
#include "realm/util/features.h"
#if REALM_PLATFORM_APPLE
#define CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#include <catch2/catch.hpp>
#include <external/json/json.hpp>
#include <realm/util/to_string.hpp>

#include <limits.h>

#ifdef _MSC_VER
#include <Windows.h>

// PathCchRemoveFileSpec()
#include <pathcch.h>
#pragma comment(lib, "Pathcch.lib")
#else
#include <libgen.h>
#endif

int main(int argc, char** argv)
{
#ifdef _MSC_VER
    wchar_t path[MAX_PATH];
    if (GetModuleFileName(NULL, path, MAX_PATH) == 0) {
        fprintf(stderr, "Failed to retrieve path to exectuable.\n");
        return 1;
    }
    PathCchRemoveFileSpec(path, MAX_PATH);
    SetCurrentDirectory(path);
#else
    char executable[PATH_MAX];
    if (realpath(argv[0], executable) == NULL) {
        fprintf(stderr, "Failed to resolve path to exectuable.\n");
        return 1;
    }
    const char* directory = dirname(executable);
    if (chdir(directory) < 0) {
        fprintf(stderr, "Failed to change directory.\n");
        return 1;
    }
#endif
    int result = -1;
    if (const char* str = getenv("UNITTEST_EVERGREEN_TEST_RESULTS"); str && strlen(str) != 0) {
        std::cout << "Configuring evergreen reporter to store test results in " << str << std::endl;
        Catch::ConfigData config;
        config.reporterName = "evergreen";
        config.outputFilename = str;
        Catch::Session session;
        session.useConfigData(config);
        result = session.run();
    }
    else {
        result = Catch::Session().run(argc, argv);
    }
    return result < 0xff ? result : 0xff;
}

namespace Catch {
class EvergreenReporter : public CumulativeReporterBase<EvergreenReporter> {
public:
    using Base = CumulativeReporterBase<EvergreenReporter>;
    explicit EvergreenReporter(ReporterConfig const& config)
        : Base(config)
    {
    }
    ~EvergreenReporter() = default;
    static std::string getDescription()
    {
        return "Reports test results in a format consumable by Evergreen.";
    }
    void noMatchingTestCases(std::string const& /*spec*/) override {}
    using Base::testGroupEnded;
    using Base::testGroupStarting;
    using Base::testRunStarting;

    bool assertionEnded(AssertionStats const& assertionStats) override
    {
        if (!assertionStats.assertionResult.isOk()) {
            std::cerr << "Assertion failure: " << assertionStats.assertionResult.getSourceInfo() << std::endl;
            std::cerr << "\t from expresion: '" << assertionStats.assertionResult.getExpression() << "'" << std::endl;
            std::cerr << "\t with expansion: '" << assertionStats.assertionResult.getExpandedExpression() << "'"
                      << std::endl;
            for (auto& message : assertionStats.infoMessages) {
                std::cerr << "\t message: " << message.message << std::endl;
            }
            std::cerr << std::endl;
        }
        return true;
    }
    void testCaseStarting(TestCaseInfo const& testCaseInfo) override
    {
        m_results.emplace(std::make_pair(testCaseInfo.name, TestResult{}));
        Base::testCaseStarting(testCaseInfo);
    }
    void testCaseEnded(TestCaseStats const& testCaseStats) override
    {
        auto it = m_results.find(testCaseStats.testInfo.name);
        if (it == m_results.end()) {
            throw std::runtime_error("logic error in Evergreen section reporter, could not end test case '" +
                                     testCaseStats.testInfo.name + "' which was never tracked as started.");
        }
        if (testCaseStats.totals.assertions.allPassed()) {
            it->second.status = "pass";
        }
        else {
            it->second.status = "fail";
        }
        it->second.end_time = std::chrono::system_clock::now();
        Base::testCaseEnded(testCaseStats);
    }
    void sectionStarting(SectionInfo const& sectionInfo) override
    {
        if (m_pending_name.empty()) {
            m_pending_name = sectionInfo.name;
        }
        else {
            m_pending_name += "::" + sectionInfo.name;
        }
        m_pending_test = {};
        Base::sectionStarting(sectionInfo);
    }
    void sectionEnded(SectionStats const& sectionStats) override
    {
        if (!m_pending_name.empty()) {
            if (sectionStats.assertions.allPassed()) {
                m_pending_test.status = "pass";
            }
            else {
                m_pending_test.status = "fail";
            }
            m_pending_test.end_time = std::chrono::system_clock::now();
            m_results.emplace(std::make_pair(m_pending_name, m_pending_test));
            m_pending_name = "";
        }
        Base::sectionEnded(sectionStats);
    }
    void testRunEndedCumulative() override
    {
        auto results_arr = nlohmann::json::array();
        for (const auto& [test_name, cur_result] : m_results) {
            auto to_millis = [](const auto& tp) -> double {
                return static_cast<double>(
                    std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count());
            };
            double start_secs = to_millis(cur_result.start_time) / 1000;
            double end_secs = to_millis(cur_result.end_time) / 1000;
            int exit_code = 0;
            if (cur_result.status != "pass") {
                exit_code = 1;
            }

            nlohmann::json cur_result_obj = {{"test_file", test_name}, {"status", cur_result.status},
                                             {"exit_code", exit_code}, {"start", start_secs},
                                             {"end", end_secs},        {"elapsed", end_secs - start_secs}};
            results_arr.push_back(std::move(cur_result_obj));
        }
        auto result_file_obj = nlohmann::json{{"results", std::move(results_arr)}};
        stream << result_file_obj << std::endl;
    }

    struct TestResult {
        TestResult()
            : start_time{std::chrono::system_clock::now()}
            , end_time{}
            , status{"unknown"}
        {
        }
        std::chrono::system_clock::time_point start_time;
        std::chrono::system_clock::time_point end_time;
        std::string status;
    };
    TestResult m_pending_test;
    std::string m_pending_name;
    std::vector<std::pair<std::string, TestResult>> m_current_stack;
    std::map<std::string, TestResult> m_results;
};

CATCH_REGISTER_REPORTER("evergreen", EvergreenReporter)

} // end namespace Catch
<|endoftext|>


<commit_before><commit_msg>MetafileXmlDump: Add dumping of META_CLIPREGION_ACTION's.<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <time.h>
#include "../Eigen/Dense"

using namespace Eigen;

// My own implementation of LU decomposition with partial pivoting
// PA = LU
bool LU(const MatrixXf &a, MatrixXf &l, MatrixXf &u, MatrixXf &p) {
	// 'a' should be a square matrix, so does 'l', 'u', and 'p'
	assert(a.rows() == a.cols());
	int size = a.rows();

	// upper triangular matrix
	u = a;

	// lower triangular matrix
	l = MatrixXf::Identity(size, size);

	// indexes for row exchanges
	ArrayXi row_indexes(size);
	for (int r = 0; r < size; r++) {
		row_indexes(r) = r;
	}

	// 'i' is diagonal index of the matrix
	for (int i = 0; i < size; i++) {
		// find pivot index
		int pivot_index = -1;
		float maximum = 0.0f;
		for (int r = i; r < a.rows(); r++) {
			float value = abs(u(r, i));

			if (value > maximum) {
				pivot_index = r;
				maximum = value;
			}
		}

		// get the pivot
		float pivot = u(pivot_index, i);
		if (pivot == 0.0f) {
			// abandon elimination if pivot is not exist
			return false;
		}

		// if row exchange is required
		if (pivot_index > i) {
			// swap row indexes
			std::swap(row_indexes[i], row_indexes[pivot_index]);

			// swap rows of U
			u.row(i).swap(u.row(pivot_index));

			// swap rows of L
			for (int c = 0; c < i; c++) {
				std::swap(l(i, c), l(pivot_index, c));
			}
		}

		float invPivot = 1.0f / pivot;

		// elimination process
		for (int r = i + 1; r < size; r++) {
			// scalar for subtract a row
			float scalar = u(r, i) * invPivot;

			// subtract a row from scaled pivot row
			for (int c = i; c < size; c++) {
				u(r, c) -= scalar * u(i, c);
			}

			// scalar matches with L component
			l(r, i) = scalar;
		}
	}

	// generate permutation matrix P with 'row_indexes'
	p = MatrixXf::Zero(size, size);
	for (int r = 0; r < size; r++) {
		p.row(r)(row_indexes[r]) = 1.0f;
	}

	return true;
}

// Solve Lx = b, L is lower triangular matrix
const VectorXf SolveLTriangular(const MatrixXf &l, const VectorXf &b) {
	VectorXf x(b.rows());

	for (int r = 0; r < l.rows(); r++) {
		float k = 0;

		for (int c = 0; c < r; c++) {
			k += l(r, c) * x(c);
		}

		x(r) = (b(r) - k) / l(r, r);
	}

	return x;
}

// Solve Ux = b, U is upper triangular matrix
const VectorXf SolveUTriangular(const MatrixXf &u, const VectorXf &b) {
	VectorXf x(b.rows());

	for (int r = u.rows() - 1; r >= 0; r--) {
		float k = 0;

		for (int c = r + 1; c < u.cols(); c++) {
			k += u(r, c) * x(c);
		}

		x(r) = (b(r) - k) / u(r, r);
	}

	return x;
}

// Solve (P^T)LUx = b
const VectorXf SolvePLU(const MatrixXf &l, const MatrixXf &u, const MatrixXf &p, const VectorXf &b) {
	// Step 1 : LUx = Pb
	// Step 2 : Lc = Pb
	// Step 3 : Ux = c

	// Step 1
	VectorXf pb = p * b;

	// Step 2
	VectorXf c = SolveLTriangular(l, pb);

	// Step 3
	VectorXf x = SolveUTriangular(u, c);

	return x;
}

void TestLU() {
	const int DIMENSION = 4;

	MatrixXf a(DIMENSION, DIMENSION);
	a << MatrixXf::Random(DIMENSION, DIMENSION);

	VectorXf b(DIMENSION);
	b << VectorXf::Random(DIMENSION);

	MatrixXf l(DIMENSION, DIMENSION);
	MatrixXf u(DIMENSION, DIMENSION);
	MatrixXf p(DIMENSION, DIMENSION);

	bool invertible = ::LU(a, l, u, p);
	if (!invertible) {
		std::cout << "ERROR: A is not invertible !!\n";
		return;
	}

	std::cout << "A =\n";
	std::cout << a << "\n\n";

	std::cout << "b =\n";
	std::cout << b << "\n\n";

	std::cout << "A * b =\n";
	std::cout << a * b << "\n\n";

	// PA = LU
	// A = (P^T)LU
	std::cout << "P^T * L * U * b =\n";
	std::cout << p.transpose() * l * u * b << "\n\n";;

	// Solve Ax = b
	VectorXf x = SolvePLU(l, u, p, b);
	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";

	// Solve Ax = b with Eigen solver
	PartialPivLU<MatrixXf> decomp(a);
	x = decomp.solve(b);
	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";
}

int main() {
	srand((unsigned int)time(0));

	TestLU();

	getchar();

	return 0;
}
<commit_msg>Added comments<commit_after>#include <iostream>
#include <algorithm>
#include <time.h>
#include "../Eigen/Dense"

using namespace Eigen;

// My own implementation of LU decomposition with partial pivoting
// PA = LU
bool LU(const MatrixXf &a, MatrixXf &l, MatrixXf &u, MatrixXf &p) {
	// 'a' should be a square matrix, so does 'l', 'u', and 'p'
	assert(a.rows() == a.cols());
	int size = a.rows();

	// upper triangular matrix U
	// A will be changed to the U
	u = a;

	// lower triangular matrix L
	l = MatrixXf::Identity(size, size);

	// indexes for row exchanges
	ArrayXi row_indexes(size);
	for (int r = 0; r < size; r++) {
		row_indexes(r) = r;
	}

	// 'i' is diagonal index of the matrix
	for (int i = 0; i < size; i++) {
		// find pivot index
		int pivot_index = -1;
		float maximum = 0.0f;
		for (int r = i; r < a.rows(); r++) {
			float value = abs(u(r, i));

			if (value > maximum) {
				pivot_index = r;
				maximum = value;
			}
		}

		// get the pivot
		float pivot = u(pivot_index, i);
		if (pivot == 0.0f) {
			// abandon elimination if pivot is not exist
			return false;
		}

		// if row exchange is required
		if (pivot_index > i) {
			// swap row indexes
			std::swap(row_indexes[i], row_indexes[pivot_index]);

			// swap rows of U
			u.row(i).swap(u.row(pivot_index));

			// swap rows of L
			for (int c = 0; c < i; c++) {
				std::swap(l(i, c), l(pivot_index, c));
			}
		}

		float invPivot = 1.0f / pivot;

		// elimination process
		for (int r = i + 1; r < size; r++) {
			// scalar for subtract a row
			float scalar = u(r, i) * invPivot;

			// subtract a row from scaled pivot row
			for (int c = i; c < size; c++) {
				u(r, c) -= scalar * u(i, c);
			}

			// scalar matches with L component
			l(r, i) = scalar;
		}
	}

	// generate permutation matrix P with 'row_indexes'
	p = MatrixXf::Zero(size, size);
	for (int r = 0; r < size; r++) {
		p.row(r)(row_indexes[r]) = 1.0f;
	}

	return true;
}

// Solve Lx = b, L is lower triangular matrix
const VectorXf SolveLTriangular(const MatrixXf &l, const VectorXf &b) {
	VectorXf x(b.rows());

	for (int r = 0; r < l.rows(); r++) {
		float k = 0;

		for (int c = 0; c < r; c++) {
			k += l(r, c) * x(c);
		}

		x(r) = (b(r) - k) / l(r, r);
	}

	return x;
}

// Solve Ux = b, U is upper triangular matrix
const VectorXf SolveUTriangular(const MatrixXf &u, const VectorXf &b) {
	VectorXf x(b.rows());

	for (int r = u.rows() - 1; r >= 0; r--) {
		float k = 0;

		for (int c = r + 1; c < u.cols(); c++) {
			k += u(r, c) * x(c);
		}

		x(r) = (b(r) - k) / u(r, r);
	}

	return x;
}

// Solve (P^T)LUx = b
const VectorXf SolvePLU(const MatrixXf &l, const MatrixXf &u, const MatrixXf &p, const VectorXf &b) {
	// Step 1 : LUx = Pb
	// Step 2 : Lc = Pb
	// Step 3 : Ux = c

	// Step 1
	VectorXf pb = p * b;

	// Step 2
	VectorXf c = SolveLTriangular(l, pb);

	// Step 3
	VectorXf x = SolveUTriangular(u, c);

	return x;
}

void TestLU() {
	const int DIMENSION = 4;

	MatrixXf a(DIMENSION, DIMENSION);
	a << MatrixXf::Random(DIMENSION, DIMENSION);

	VectorXf b(DIMENSION);
	b << VectorXf::Random(DIMENSION);

	MatrixXf l(DIMENSION, DIMENSION);
	MatrixXf u(DIMENSION, DIMENSION);
	MatrixXf p(DIMENSION, DIMENSION);

	bool invertible = ::LU(a, l, u, p);
	if (!invertible) {
		std::cout << "ERROR: A is not invertible !!\n";
		return;
	}

	std::cout << "A =\n";
	std::cout << a << "\n\n";

	std::cout << "b =\n";
	std::cout << b << "\n\n";

	std::cout << "A * b =\n";
	std::cout << a * b << "\n\n";

	// PA = LU
	// A = (P^T)LU
	std::cout << "P^T * L * U * b =\n";
	std::cout << p.transpose() * l * u * b << "\n\n";;

	// Solve Ax = b
	VectorXf x = SolvePLU(l, u, p, b);
	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";

	// Solve Ax = b with Eigen solver
	PartialPivLU<MatrixXf> decomp(a);
	x = decomp.solve(b);
	std::cout << "Ax = b, x =\n";
	std::cout << x << "\n\n";
}

int main() {
	srand((unsigned int)time(0));

	TestLU();

	getchar();

	return 0;
}
<|endoftext|>