<commit_before>/*
 * File:   BackpropeagationLearner.cpp
 * Author: janvojt
 *
 * Created on July 13, 2014, 12:10 AM
 */

#include "BackpropagationLearner.h"

#include <cstring>
#include <string>
#include <stdexcept>

#include "../common.h"

#include "../log/LoggerFactory.h"
#include "log4cpp/Category.hh"

const int MAX_IMPROVEMENT_EPOCHS = 1000;

BackpropagationLearner::BackpropagationLearner(Network *network) {
    this->network = network;
    this->learningRate = 1;
    this->epochLimit = 1000000;
    this->targetMse = .0001;
    this->useBias = network->getConfiguration()->getBias();
    this->noLayers = network->getConfiguration()->getLayers();
    this->deltaError = 0;
    this->improveEpochs = 0;
}

BackpropagationLearner::BackpropagationLearner(const BackpropagationLearner &orig) {
}

BackpropagationLearner::~BackpropagationLearner() {
    if (this->errorComputer != NULL) delete this->errorComputer;
    if (this->improveEpochs > 0) delete[] this->errorCache;
}

TrainingResult* BackpropagationLearner::train(LabeledDataset *trainingSet, LabeledDataset *validationSet, int valIdx) {

    LOG()->info("Started training with:\n"
            "   - cross-validation fold: %d,\n"
            "   - epoch limit: %d,\n"
            "   - target MSE: %f,\n"
            "   - epochs in which improvement is required: %d,\n"
            "   - learning rate: %f."
            , valIdx, this->epochLimit, this->targetMse, this->improveEpochs, this->learningRate);

    TrainingResult *result = new TrainingResult();
    long epochCounter = 0;
    do {

        epochCounter++;
        LOG()->debug("Validation fold %d: Starting epoch %d.", valIdx, epochCounter);

        trainingSet->reset();
        int datasetSize = 0;
        data_t mse = 0;

        while (trainingSet->hasNext()) {
            datasetSize++;
            data_t *pattern = trainingSet->next();
            data_t *expOutput = pattern + trainingSet->getInputDimension();

            LOG()->debug("Validation fold %d: Starting forward phase for dataset %d in epoch %d.", valIdx, datasetSize, epochCounter);
            doForwardPhase(pattern);

            LOG()->debug("Validation fold %d: Starting backward phase for dataset %d in epoch %d.", valIdx, datasetSize, epochCounter);
            doBackwardPhase(expOutput);

            mse += this->errorComputer->compute(this->network, expOutput);
        }

        // compute MSE on training data
        mse = mse / datasetSize;
        result->setTrainingError(mse);
        LOG()->info("Validation fold %d: Finished epoch %d with MSE: %f.", valIdx, epochCounter, result->getTrainingError());

        // calculate error on validation dataset
        validationSet->reset();
        if (validationSet->hasNext()) {
            result->setValidationError(computeError(validationSet));
            LOG()->info("Validation fold %d: Computed MSE of %f on validation dataset.", valIdx, result->getValidationError());
        }

        // check criteria for stopping learning
        if (result->getError() <= this->targetMse) {
            LOG()->info("Validation fold %d: Training successful after %d epochs with MSE of %f.", valIdx, epochCounter, result->getError());
            break;
        } else if (!isErrorImprovement(result->getError(), epochCounter)) {
            LOG()->info("Validation fold %d: Training interrupted after %d epochs with MSE of %f, because MSE improvement in last %d epochs was less than %f.", valIdx, epochCounter, result->getError(), improveEpochs, deltaError);
            break;
        } else if (epochCounter >= this->epochLimit) {
            LOG()->info("Validation fold %d: Training interrupted after %d epochs with MSE of %f.", valIdx, epochCounter, result->getError());
            break;
        }

    } while (true); // stopping checks are at the end of the loop

    result->setEpochs(epochCounter);
    return result;
}

void BackpropagationLearner::doForwardPhase(data_t *input) {
    this->network->setInput(input);
    this->network->forward();
}

void BackpropagationLearner::doBackwardPhase(data_t *expectedOutput) {
    this->network->setExpectedOutput(expectedOutput);
    this->network->backward();
}

void BackpropagationLearner::validate(LabeledDataset *dataset) {
    if (dataset->getInputDimension() != this->network->getInputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same input dimension as the number of input neurons!");
    }
    if (dataset->getOutputDimension() != this->network->getOutputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same output dimension as the number of output neurons!");
    }
}

bool BackpropagationLearner::isErrorImprovement(data_t error, int epoch) {
    if (this->improveEpochs <= 0) {
        return true;
    }

    if (epoch > this->improveEpochs) {
        if ((this->errorCache[this->errorCachePtr] - this->deltaError) < error) {
            return false;
        }
    }

    this->errorCache[this->errorCachePtr] = error;
    this->errorCachePtr = (this->errorCachePtr+1) % this->improveEpochs;

    return true;
}

data_t BackpropagationLearner::computeError(LabeledDataset* ds) {
    int datasetSize = 0;
    data_t vMse = 0;
    while (ds->hasNext()) {
        datasetSize++;
        data_t *pattern = ds->next();
        data_t *expOutput = pattern + ds->getInputDimension();
        vMse += this->errorComputer->compute(this->network, expOutput);
    }

    return vMse / datasetSize;
}

void BackpropagationLearner::setImproveEpochs(int improveEpochs) {
    if (improveEpochs > MAX_IMPROVEMENT_EPOCHS) {
        LOG()->warn("Allowed maximum for error improvement epochs is %d, however %d was  requested. Going with %d.", MAX_IMPROVEMENT_EPOCHS, improveEpochs, MAX_IMPROVEMENT_EPOCHS);
        improveEpochs = MAX_IMPROVEMENT_EPOCHS;
    }

    if (this->improveEpochs > 0) {
        delete[] this->errorCache;
    }

    if (improveEpochs > 0) {
        this->errorCache = new data_t[improveEpochs];
        this->errorCachePtr = 0;
    }

    this->improveEpochs = improveEpochs;
}

void BackpropagationLearner::setEpochLimit(long limit) {
    this->epochLimit = limit;
}

void BackpropagationLearner::setErrorComputer(ErrorComputer* errorComputer) {
    this->errorComputer = errorComputer;
}

void BackpropagationLearner::setTargetMse(data_t mse) {
    this->targetMse = mse;
}

void BackpropagationLearner::setLearningRate(data_t learningRate) {
    this->learningRate = learningRate;
}

void BackpropagationLearner::setDeltaError(data_t deltaError) {
    this->deltaError = deltaError;
}
<commit_msg>Zero or negative epoch limit disables learning.<commit_after>/*
 * File:   BackpropeagationLearner.cpp
 * Author: janvojt
 *
 * Created on July 13, 2014, 12:10 AM
 */

#include "BackpropagationLearner.h"

#include <cstring>
#include <string>
#include <stdexcept>

#include "../common.h"

#include "../log/LoggerFactory.h"
#include "log4cpp/Category.hh"

const int MAX_IMPROVEMENT_EPOCHS = 1000;

BackpropagationLearner::BackpropagationLearner(Network *network) {
    this->network = network;
    this->learningRate = 1;
    this->epochLimit = 1000000;
    this->targetMse = .0001;
    this->useBias = network->getConfiguration()->getBias();
    this->noLayers = network->getConfiguration()->getLayers();
    this->deltaError = 0;
    this->improveEpochs = 0;
}

BackpropagationLearner::BackpropagationLearner(const BackpropagationLearner &orig) {
}

BackpropagationLearner::~BackpropagationLearner() {
    if (this->errorComputer != NULL) delete this->errorComputer;
    if (this->improveEpochs > 0) delete[] this->errorCache;
}

TrainingResult* BackpropagationLearner::train(LabeledDataset *trainingSet, LabeledDataset *validationSet, int valIdx) {

    TrainingResult *result = new TrainingResult();
    if (epochLimit <= 0) {
        LOG()->info("Learning skipped based on zero epoch limit.");
        return result;
    }

    LOG()->info("Started training with:\n"
            "   - cross-validation fold: %d,\n"
            "   - epoch limit: %d,\n"
            "   - target MSE: %f,\n"
            "   - epochs in which improvement is required: %d,\n"
            "   - learning rate: %f."
            , valIdx, this->epochLimit, this->targetMse, this->improveEpochs, this->learningRate);

    long epochCounter = 0;
    do {

        epochCounter++;
        LOG()->debug("Validation fold %d: Starting epoch %d.", valIdx, epochCounter);

        trainingSet->reset();
        int datasetSize = 0;
        data_t mse = 0;

        while (trainingSet->hasNext()) {
            datasetSize++;
            data_t *pattern = trainingSet->next();
            data_t *expOutput = pattern + trainingSet->getInputDimension();

            LOG()->debug("Validation fold %d: Starting forward phase for dataset %d in epoch %d.", valIdx, datasetSize, epochCounter);
            doForwardPhase(pattern);

            LOG()->debug("Validation fold %d: Starting backward phase for dataset %d in epoch %d.", valIdx, datasetSize, epochCounter);
            doBackwardPhase(expOutput);

            mse += this->errorComputer->compute(this->network, expOutput);
        }

        // compute MSE on training data
        mse = mse / datasetSize;
        result->setTrainingError(mse);
        LOG()->info("Validation fold %d: Finished epoch %d with MSE: %f.", valIdx, epochCounter, result->getTrainingError());

        // calculate error on validation dataset
        validationSet->reset();
        if (validationSet->hasNext()) {
            result->setValidationError(computeError(validationSet));
            LOG()->info("Validation fold %d: Computed MSE of %f on validation dataset.", valIdx, result->getValidationError());
        }

        // check criteria for stopping learning
        if (result->getError() <= this->targetMse) {
            LOG()->info("Validation fold %d: Training successful after %d epochs with MSE of %f.", valIdx, epochCounter, result->getError());
            break;
        } else if (!isErrorImprovement(result->getError(), epochCounter)) {
            LOG()->info("Validation fold %d: Training interrupted after %d epochs with MSE of %f, because MSE improvement in last %d epochs was less than %f.", valIdx, epochCounter, result->getError(), improveEpochs, deltaError);
            break;
        } else if (epochCounter >= this->epochLimit) {
            LOG()->info("Validation fold %d: Training interrupted after %d epochs with MSE of %f.", valIdx, epochCounter, result->getError());
            break;
        }

    } while (true); // stopping checks are at the end of the loop

    result->setEpochs(epochCounter);
    return result;
}

void BackpropagationLearner::doForwardPhase(data_t *input) {
    this->network->setInput(input);
    this->network->forward();
}

void BackpropagationLearner::doBackwardPhase(data_t *expectedOutput) {
    this->network->setExpectedOutput(expectedOutput);
    this->network->backward();
}

void BackpropagationLearner::validate(LabeledDataset *dataset) {
    if (dataset->getInputDimension() != this->network->getInputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same input dimension as the number of input neurons!");
    }
    if (dataset->getOutputDimension() != this->network->getOutputNeurons()) {
        throw new std::invalid_argument("Provided dataset must have the same output dimension as the number of output neurons!");
    }
}

bool BackpropagationLearner::isErrorImprovement(data_t error, int epoch) {
    if (this->improveEpochs <= 0) {
        return true;
    }

    if (epoch > this->improveEpochs) {
        if ((this->errorCache[this->errorCachePtr] - this->deltaError) < error) {
            return false;
        }
    }

    this->errorCache[this->errorCachePtr] = error;
    this->errorCachePtr = (this->errorCachePtr+1) % this->improveEpochs;

    return true;
}

data_t BackpropagationLearner::computeError(LabeledDataset* ds) {
    int datasetSize = 0;
    data_t vMse = 0;
    while (ds->hasNext()) {
        datasetSize++;
        data_t *pattern = ds->next();
        data_t *expOutput = pattern + ds->getInputDimension();
        vMse += this->errorComputer->compute(this->network, expOutput);
    }

    return vMse / datasetSize;
}

void BackpropagationLearner::setImproveEpochs(int improveEpochs) {
    if (improveEpochs > MAX_IMPROVEMENT_EPOCHS) {
        LOG()->warn("Allowed maximum for error improvement epochs is %d, however %d was  requested. Going with %d.", MAX_IMPROVEMENT_EPOCHS, improveEpochs, MAX_IMPROVEMENT_EPOCHS);
        improveEpochs = MAX_IMPROVEMENT_EPOCHS;
    }

    if (this->improveEpochs > 0) {
        delete[] this->errorCache;
    }

    if (improveEpochs > 0) {
        this->errorCache = new data_t[improveEpochs];
        this->errorCachePtr = 0;
    }

    this->improveEpochs = improveEpochs;
}

void BackpropagationLearner::setEpochLimit(long limit) {
    this->epochLimit = limit;
}

void BackpropagationLearner::setErrorComputer(ErrorComputer* errorComputer) {
    this->errorComputer = errorComputer;
}

void BackpropagationLearner::setTargetMse(data_t mse) {
    this->targetMse = mse;
}

void BackpropagationLearner::setLearningRate(data_t learningRate) {
    this->learningRate = learningRate;
}

void BackpropagationLearner::setDeltaError(data_t deltaError) {
    this->deltaError = deltaError;
}
<|endoftext|>


<commit_before>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <ctype.h>                                          /* isxxx() */
#include <ros/ros.h>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */
#include <base_controller/md49data.h>                       /* Custom message /encoders */

int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                     /* speed to set for MD49 */
unsigned char last_speed_l=128, last_speed_r=128;           /* speed to set for MD49 */
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

unsigned char serialBuffer[18];                             /* Serial buffer to store uart data */
void read_MD49_Data (void);
void set_md49_speed (unsigned char speed_l, unsigned char speed_r);
char* itoa(int value, char* result, int base);

using namespace std;

base_controller::encoders encoders;
base_controller::md49data md49data;

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

        if (vel_cmd.linear.x>0){
            speed_l = 255;
            speed_r = 255;
        }
        if (vel_cmd.linear.x<0){
            speed_l = 0;
            speed_r = 0;
        }
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
            speed_l = 128;
            speed_r = 128;
        }
        if (vel_cmd.angular.z>0){
            speed_l = 0;
            speed_r = 255;
        }
        if (vel_cmd.angular.z<0){
            speed_l = 255;
            speed_r = 0;
        }

    /*
        //ANFANG Alternative
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
        else if(vel_cmd.linear.x == 0){
            // turning
            vr = vel_cmd.angular.z * base_width / 2.0;
            vl = (-1) * vr;
        }
        else if(vel_cmd.angular.z == 0){
            // forward / backward
            vl = vr = vel_cmd.linear.x;
        }
        else{
            // moving doing arcs
            vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
            if (vl > max_vl) {vl=max_vl;}
            if (vl < min_vl) {vl=min_vl;}
            vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
            if (vr > max_vr) {vr=max_vr;}
            if (vr < min_vr) {vr=min_vr;}
        }
        //ENDE Alternative
    */
}

int main( int argc, char* argv[] ){

    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 10, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",10);
    ros::Publisher md49data_pub = n.advertise<base_controller::md49data>("md49data",10);

    // Set nodes looprate 10Hz
    // ***********************
    ros::Rate loop_rate(10);
    ROS_INFO("base_controller is running:");
    ROS_INFO("reading md49data from md49_data.txt");
    ROS_INFO("writing md49commands to md49_commands.txt");
    ROS_INFO("============================================");
    ROS_INFO("base_controller subscribes to topic /cmd_vel");
    ROS_INFO("base_controller publises to topic /encoders");
    ROS_INFO("base_controller publises to topic /md49data");

    while(n.ok())
    {
        // Read encoder values and other data from MD49:
        // serial_controller_node reads data from AVR-Master
        // and provides that data in md49_data.txt
        // *************************************************
        read_MD49_Data();

        // Set MD49 speed_l and speed_r:
        // serial_controller_node reads commands from
        // md49_commands.txt and writes commands to AVR-Master
        // ***************************************************
        if ((speed_l != last_speed_l) || (speed_r != last_speed_r)){
            set_md49_speed(speed_l,speed_r);
            last_speed_l=speed_l;
            last_speed_r=speed_r;
        }

        // Publish encoder values to topic /encoders (custom message)
        // **********************************************************
        encoders.encoder_l=EncoderL;
        encoders.encoder_r=EncoderR;
        encoders_pub.publish(encoders);

        // Publish MD49 data to topic /md49data (custom message)
        // *****************************************************
        md49data.speed_l = serialBuffer[8];
        md49data.speed_r = serialBuffer[9];
        md49data.volt = serialBuffer[10];
        md49data.current_l = serialBuffer[11];
        md49data.current_r = serialBuffer[12];
        md49data.error = serialBuffer[13];
        md49data.acceleration = serialBuffer[14];
        md49data.mode = serialBuffer[15];
        md49data.regulator = serialBuffer[16];
        md49data.timeout = serialBuffer[17];
        md49data_pub.publish(md49data);

        ros::spinOnce();
        loop_rate.sleep();

    }// end.mainloop

    return 1;
} // end.main

void read_MD49_Data (void){

    // Read all MD49 data from md49_data.txt
    // *************************************
    string line;
    ifstream myfile ("md49_data.txt");
    if (myfile.is_open()){
        int i=0;
        while (getline (myfile,line)){
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            serialBuffer[i]=atoi(data);
            i =i++;
        }
        myfile.close();

    }
    else ROS_ERROR("Unable to open file: md49_data.txt");

    // Put toghether new encodervalues
    // *******************************
    EncoderL = serialBuffer[0] << 24;                        // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                        // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

}

void set_md49_speed (unsigned char speed_l, unsigned char speed_r){

    char buffer[33];
    ofstream myfile;
    myfile.open ("md49_commands.txt");
    //myfile << "Writing this to a file.\n";
    if (speed_l==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_l<10){
        myfile << "00";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else if (speed_l<100){
        myfile << "0";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }

    if (speed_r==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_r<10){
        myfile << "00";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else if (speed_r<100){
        myfile << "0";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    myfile.close();
}

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
    }
<commit_msg>Update code<commit_after>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <ctype.h>                                          /* isxxx() */
#include <ros/ros.h>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */
#include <base_controller/md49data.h>                       /* Custom message /encoders */

int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                     /* speed to set for MD49 */
unsigned char last_speed_l=128, last_speed_r=128;           /* speed to set for MD49 */
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

unsigned char serialBuffer[18];                             /* Serial buffer to store uart data */
void read_MD49_Data (void);
void set_md49_speed (unsigned char speed_l, unsigned char speed_r);
char* itoa(int value, char* result, int base);

using namespace std;

base_controller::encoders encoders;
base_controller::md49data md49data;

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

        if (vel_cmd.linear.x>0){
            speed_l = 255;
            speed_r = 255;
        }
        if (vel_cmd.linear.x<0){
            speed_l = 0;
            speed_r = 0;
        }
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
            speed_l = 128;
            speed_r = 128;
        }
        if (vel_cmd.angular.z>0){
            speed_l = 0;
            speed_r = 255;
        }
        if (vel_cmd.angular.z<0){
            speed_l = 255;
            speed_r = 0;
        }

    /*
        //ANFANG Alternative
        if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
        else if(vel_cmd.linear.x == 0){
            // turning
            vr = vel_cmd.angular.z * base_width / 2.0;
            vl = (-1) * vr;
        }
        else if(vel_cmd.angular.z == 0){
            // forward / backward
            vl = vr = vel_cmd.linear.x;
        }
        else{
            // moving doing arcs
            vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
            if (vl > max_vl) {vl=max_vl;}
            if (vl < min_vl) {vl=min_vl;}
            vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
            if (vr > max_vr) {vr=max_vr;}
            if (vr < min_vr) {vr=min_vr;}
        }
        //ENDE Alternative
    */
}

int main( int argc, char* argv[] ){

    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 10, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",10);
    ros::Publisher md49data_pub = n.advertise<base_controller::md49data>("md49data",10);

    // Set nodes looprate 10Hz
    // ***********************
    ros::Rate loop_rate(10);
    ROS_INFO("base_controller is running:");
    ROS_INFO("reading md49data from md49_data.txt");
    ROS_INFO("writing md49commands to md49_commands.txt");
    ROS_INFO("============================================");
    ROS_INFO("base_controller subscribes to topic /cmd_vel");
    ROS_INFO("base_controller publises to topic /encoders");
    ROS_INFO("base_controller publises to topic /md49data");

    while(n.ok())
    {
        // Read encoder values and other data from MD49:
        // serial_controller_node reads data from AVR-Master
        // and provides that data in md49_data.txt
        // *************************************************
        read_MD49_Data();

        // Set MD49 speed_l and speed_r:
        // serial_controller_node reads commands from
        // md49_commands.txt and writes commands to AVR-Master
        // ***************************************************
        if ((speed_l != last_speed_l) || (speed_r != last_speed_r)){
            set_md49_speed(speed_l,speed_r);
            last_speed_l=speed_l;
            last_speed_r=speed_r;
        }

        // Publish encoder values to topic /encoders (custom message)
        // **********************************************************
        encoders.encoder_l=EncoderL;
        encoders.encoder_r=EncoderR;
        encoders_pub.publish(encoders);

        // Publish MD49 data to topic /md49data (custom message)
        // *****************************************************
        md49data.speed_l = serialBuffer[8];
        md49data.speed_r = serialBuffer[9];
        md49data.volt = serialBuffer[10];
        md49data.current_l = serialBuffer[11];
        md49data.current_r = serialBuffer[12];
        md49data.error = serialBuffer[13];
        md49data.acceleration = serialBuffer[14];
        md49data.mode = serialBuffer[15];
        md49data.regulator = serialBuffer[16];
        md49data.timeout = serialBuffer[17];
        md49data_pub.publish(md49data);

        ros::spinOnce();
        loop_rate.sleep();

    }// end.mainloop

    return 1;
} // end.main

void read_MD49_Data (void){

    // Read all MD49 data from md49_data.txt
    // *************************************
    string line;
    ifstream myfile ("md49_data.txt");
    if (myfile.is_open()){
        int i=0;
        while (getline (myfile,line)){
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            serialBuffer[i]=atoi(data);
            i =i++;
        }
        myfile.close();

    }
    else ROS_ERROR("Unable to open file: md49_data.txt");

    // Put toghether new encodervalues
    // *******************************
    EncoderL = serialBuffer[0] << 24;                        // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                        // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

}

void set_md49_speed (unsigned char speed_l, unsigned char speed_r){

    char buffer[33];
    ofstream myfile;
    myfile.open ("md49_commands.txt");
    //myfile << "Writing this to a file.\n";
    /*
    if (speed_l==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_l<10){
        myfile << "00";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else if (speed_l<100){
        myfile << "0";
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_l,buffer,10);
        myfile << "\n";
    }

    if (speed_r==0){
        myfile << "000";
        myfile << "\n";
    }
    else if (speed_r<10){
        myfile << "00";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else if (speed_r<100){
        myfile << "0";
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    else{
        myfile << itoa(speed_r,buffer,10);
        myfile << "\n";
    }
    */
    myfile << itoa(speed_l,buffer,10);
    myfile << "\n";
    myfile << itoa(speed_r,buffer,10);
    myfile << "\n";
    myfile.close();
}

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
    }
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino{

	class Request;
	class Response;

	struct {

		time_t time;
   		struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	string openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		return string(buf.begin(), buf.end());;
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			}
		}
	}

	class Request{
		unordered_map<string, string> headerset;
		unordered_map<string, string> paramset;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{}

		const string method;
		const string url;
		const string protocol;

		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}
	};

    class Response{
		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body_(bod),
			protocol_(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* file(string filename){
			body_ = openFile(*context.view_root + "/" + filename);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + filename;
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
		    closedir(dir);
			delete dent;
			delete dir;
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory));
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

		int I = 0;
	    while(1) {

			if(I>5){
				return;
			}

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd,
	                        (struct sockaddr *)&client,(socklen_t *) &len);
	                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;

							I++;

	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		string res = openFile("html/index.html");
		auto lines = utils::split(res, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			string res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<commit_msg>[Add] Content-Type<commit_after>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#if defined(__APPLE__) || defined(__GNUC__) && __GNUC__ * 10  + __GNUC_MINOR__ >= 49
#include <regex>
#endif

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino{

	class Request;
	class Response;

	struct {

		time_t time;
   		struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<" "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	pair<string,string> openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		string response(buf.cbegin(), buf.cend());

		if( response[0] == '\xFF' && response[1] == '\xD8'){
			return make_pair(response, "image/jpg");
		}else if( response[0] == '\x89' && response[1] == 'P' && response[2] == 'N' && response[3] == 'G'){
			return make_pair(response, "image/png");
		}else if( response[0] == 'G' && response[1] == 'I' && response[2] == 'F' && response[3] == '8' && (response[4] == '7' || response[4] == '9') && response[2] == 'a'){
			return make_pair(response, "image/gif");
		}else{
			return make_pair(response, "text/html");
		}
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			}
		}
	}

	class Request{
		unordered_map<string, string> headerset;
		unordered_map<string, string> paramset;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{}

		const string method;
		const string url;
		const string protocol;

		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}
	};

    class Response{

		unordered_map<string, string> headerset;

		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body_(bod),
			protocol_(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* file(string filename){
			auto file = openFile(*context.view_root + "/" + filename);
			body_ = file.first;
			headerset["Content-type"] = move(file.second);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename!="")
			directory += "/" + filename;
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
		    closedir(dir);
			delete dent;
			delete dir;
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory).first);
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

		int I = 0;
	    while(1) {

			if(I>5){
				return;
			}

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
	                    int clientfd = accept(context.sockfd,
	                        (struct sockaddr *)&client,(socklen_t *) &len);
	                        FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;

							I++;

	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		auto res = openFile("html/index.html");
		auto lines = utils::split(res.first, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			auto res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<|endoftext|>


<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2013, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Matt Maly */

#include <ompl/control/SpaceInformation.h>
#include <ompl/base/spaces/SE2StateSpace.h>
#include <ompl/control/spaces/RealVectorControlSpace.h>
#include <ompl/control/SimpleSetup.h>
#include <ompl/config.h>
#include <iostream>
#include <vector>

#include <ompl/extensions/triangle/PropositionalTriangularDecomposition.h>
#include <ompl/control/planners/ltl/PropositionalDecomposition.h>
#include <ompl/control/planners/ltl/Automaton.h>
#include <ompl/control/planners/ltl/ProductGraph.h>
#include <ompl/control/planners/ltl/LTLPlanner.h>
#include <ompl/control/planners/ltl/LTLProblemDefinition.h>

namespace ob = ompl::base;
namespace oc = ompl::control;

typedef oc::PropositionalTriangularDecomposition::Polygon Polygon;
typedef oc::PropositionalTriangularDecomposition::Vertex Vertex;

// a decomposition is only needed for SyclopRRT and SyclopEST
// use TriangularDecomp
class MyDecomposition : public oc::PropositionalTriangularDecomposition
{
public:
    MyDecomposition(const ob::RealVectorBounds& bounds)
        : oc::PropositionalTriangularDecomposition(bounds) { }
    virtual ~MyDecomposition() { }

    virtual void project(const ob::State* s, std::vector<double>& coord) const
    {
        coord.resize(2);
        coord[0] = s->as<ob::SE2StateSpace::StateType>()->getX();
        coord[1] = s->as<ob::SE2StateSpace::StateType>()->getY();
    }

    virtual void sampleFullState(const ob::StateSamplerPtr& sampler, const std::vector<double>& coord, ob::State* s) const
    {
       sampler->sampleUniform(s);
       ob::SE2StateSpace::StateType* ws = s->as<ob::SE2StateSpace::StateType>();
       ws->setXY(coord[0], coord[1]);
    }

private:
    ompl::RNG rng_;
};

void addObstaclesAndPropositions(oc::PropositionalTriangularDecomposition* decomp)
{
    Polygon obstacle(4);
    obstacle.pts[0] = Vertex(0.,.9);
    obstacle.pts[1] = Vertex(1.1,.9);
    obstacle.pts[2] = Vertex(1.1,1.1);
    obstacle.pts[3] = Vertex(0.,1.1);
    decomp->addHole(obstacle);

    Polygon p0(4);
    p0.pts[0] = Vertex(.9,.3);
    p0.pts[1] = Vertex(1.1,.3);
    p0.pts[2] = Vertex(1.1,.5);
    p0.pts[3] = Vertex(.9,.5);
    decomp->addProposition(p0);

    Polygon p1(4);
    p1.pts[0] = Vertex(1.5,1.6);
    p1.pts[1] = Vertex(1.6,1.6);
    p1.pts[2] = Vertex(1.6,1.7);
    p1.pts[3] = Vertex(1.5,1.7);
    decomp->addProposition(p1);

    Polygon p2(4);
    p2.pts[0] = Vertex(.2,1.7);
    p2.pts[1] = Vertex(.3,1.7);
    p2.pts[2] = Vertex(.3,1.8);
    p2.pts[3] = Vertex(.2,1.8);
    decomp->addProposition(p2);
}

/* Returns whether a point (x,y) is within a given polygon.
   We are assuming that the polygon is a axis-aligned rectangle, with vertices stored
   in counter-clockwise order, beginning with the bottom-left vertex. */
bool polyContains(const Polygon& poly, double x, double y)
{
    return x >= poly.pts[0].x && x <= poly.pts[2].x
        && y >= poly.pts[0].y && y <= poly.pts[2].y;
}

/* Our state validity checker queries the decomposition for its obstacles,
   and checks for collisions against them.
   This is to prevent us from having to redefine the obstacles in multiple places. */
bool isStateValid(
    const oc::SpaceInformation *si,
    const oc::PropositionalTriangularDecomposition* decomp,
    const ob::State *state)
{
    if (!si->satisfiesBounds(state))
        return false;
    const ob::SE2StateSpace::StateType* se2 = state->as<ob::SE2StateSpace::StateType>();

	double x = se2->getX();
	double y = se2->getY();
    const std::vector<Polygon>& obstacles = decomp->getHoles();
    typedef std::vector<Polygon>::const_iterator ObstacleIter;
    for (ObstacleIter o = obstacles.begin(); o != obstacles.end(); ++o)
    {
        if (polyContains(*o, x, y))
            return false;
    }
	return true;
}

void propagate(const ob::State *start, const oc::Control *control, const double duration, ob::State *result)
{
    const ob::SE2StateSpace::StateType* se2 = start->as<ob::SE2StateSpace::StateType>();
    const oc::RealVectorControlSpace::ControlType* rctrl = control->as<oc::RealVectorControlSpace::ControlType>();

    double xout = se2->getX() + rctrl->values[0]*duration*cos(se2->getYaw());
    double yout = se2->getY() + rctrl->values[0]*duration*sin(se2->getYaw());
    double yawout = se2->getYaw() + rctrl->values[1];

    ob::SE2StateSpace::StateType* se2out = result->as<ob::SE2StateSpace::StateType>();
    se2out->setXY(xout, yout);
    se2out->setYaw(yawout);

    ob::SO2StateSpace::StateType* so2out = se2out->as<ob::SO2StateSpace::StateType>(1);
    ob::SO2StateSpace SO2;
    SO2.enforceBounds (so2out);
}

void plan(void)
{
    // construct the state space we are planning in
    ob::StateSpacePtr space(new ob::SE2StateSpace());

    // set the bounds for the R^2 part of SE(2)
    ob::RealVectorBounds bounds(2);
    bounds.setLow(0);
    bounds.setHigh(2);

    space->as<ob::SE2StateSpace>()->setBounds(bounds);

    // create triangulation that ignores obstacle and respects propositions
    MyDecomposition* ptd = new MyDecomposition(bounds);
    addObstaclesAndPropositions(ptd);
    ptd->setup();
    // print the triangulation, with proposition information, to stdout
    ptd->print(std::cout);
    oc::PropositionalDecompositionPtr pd(ptd);

    // create a control space
    oc::ControlSpacePtr cspace(new oc::RealVectorControlSpace(space, 2));

    // set the bounds for the control space
    ob::RealVectorBounds cbounds(2);
    cbounds.setLow(-.5);
    cbounds.setHigh(.5);

    cspace->as<oc::RealVectorControlSpace>()->setBounds(cbounds);

    oc::SpaceInformationPtr si(new oc::SpaceInformation(space, cspace));
    si->setStateValidityChecker(boost::bind(&isStateValid, si.get(), ptd, _1));
    si->setStatePropagator(boost::bind(&propagate, _1, _2, _3, _4));
    si->setPropagationStepSize(0.025);

    //LTL co-safety sequencing formula: visit p2,p0 in that order
    std::vector<unsigned int> sequence(2);
    sequence[0] = 2;
    sequence[1] = 0;
    oc::AutomatonPtr cosafety = oc::Automaton::SequenceAutomaton(3, sequence);

    //LTL safety avoidance formula: never visit p1
    std::vector<unsigned int> toAvoid(1);
    toAvoid[0] = 1;
    oc::AutomatonPtr safety = oc::Automaton::AvoidanceAutomaton(3, toAvoid);

    //construct product graph (propDecomp x A_{cosafety} x A_{safety})
    oc::ProductGraphPtr product(new oc::ProductGraph(pd, cosafety, safety));
    oc::LTLSpaceInformationPtr ltlsi(new oc::LTLSpaceInformation(si, product));

    ob::LTLProblemDefinitionPtr pdef(new ob::LTLProblemDefinition(ltlsi));

    // create a start state
    ob::ScopedState<ob::SE2StateSpace> start(space);
    start->setX(0.2);
    start->setY(0.2);
    start->setYaw(0.0);

    pdef->addLowerStartState(start.get());

    //LTL planner (input: state information, product automaton)
    oc::LTLPlanner* ltlPlanner = new oc::LTLPlanner(ltlsi, product);

    ltlPlanner->setProblemDefinition(pdef);

    // attempt to solve the problem within thirty seconds of planning time
    ob::PlannerStatus solved = ltlPlanner->as<ob::Planner>()->solve(30.0);

    if (solved)
    {
        std::cout << "Found solution:" << std::endl;
        pdef->getLowerSolutionPath()->print(std::cout);
    }
    else
        std::cout << "No solution found" << std::endl;
}

int main(int, char **)
{
    plan();
    return 0;
}
<commit_msg>changed demo to no longer print triangulation<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2013, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Matt Maly */

#include <ompl/control/SpaceInformation.h>
#include <ompl/base/spaces/SE2StateSpace.h>
#include <ompl/control/spaces/RealVectorControlSpace.h>
#include <ompl/control/SimpleSetup.h>
#include <ompl/config.h>
#include <iostream>
#include <vector>

#include <ompl/extensions/triangle/PropositionalTriangularDecomposition.h>
#include <ompl/control/planners/ltl/PropositionalDecomposition.h>
#include <ompl/control/planners/ltl/Automaton.h>
#include <ompl/control/planners/ltl/ProductGraph.h>
#include <ompl/control/planners/ltl/LTLPlanner.h>
#include <ompl/control/planners/ltl/LTLProblemDefinition.h>

namespace ob = ompl::base;
namespace oc = ompl::control;

typedef oc::PropositionalTriangularDecomposition::Polygon Polygon;
typedef oc::PropositionalTriangularDecomposition::Vertex Vertex;

// a decomposition is only needed for SyclopRRT and SyclopEST
// use TriangularDecomp
class MyDecomposition : public oc::PropositionalTriangularDecomposition
{
public:
    MyDecomposition(const ob::RealVectorBounds& bounds)
        : oc::PropositionalTriangularDecomposition(bounds) { }
    virtual ~MyDecomposition() { }

    virtual void project(const ob::State* s, std::vector<double>& coord) const
    {
        coord.resize(2);
        coord[0] = s->as<ob::SE2StateSpace::StateType>()->getX();
        coord[1] = s->as<ob::SE2StateSpace::StateType>()->getY();
    }

    virtual void sampleFullState(const ob::StateSamplerPtr& sampler, const std::vector<double>& coord, ob::State* s) const
    {
       sampler->sampleUniform(s);
       ob::SE2StateSpace::StateType* ws = s->as<ob::SE2StateSpace::StateType>();
       ws->setXY(coord[0], coord[1]);
    }

private:
    ompl::RNG rng_;
};

void addObstaclesAndPropositions(oc::PropositionalTriangularDecomposition* decomp)
{
    Polygon obstacle(4);
    obstacle.pts[0] = Vertex(0.,.9);
    obstacle.pts[1] = Vertex(1.1,.9);
    obstacle.pts[2] = Vertex(1.1,1.1);
    obstacle.pts[3] = Vertex(0.,1.1);
    decomp->addHole(obstacle);

    Polygon p0(4);
    p0.pts[0] = Vertex(.9,.3);
    p0.pts[1] = Vertex(1.1,.3);
    p0.pts[2] = Vertex(1.1,.5);
    p0.pts[3] = Vertex(.9,.5);
    decomp->addProposition(p0);

    Polygon p1(4);
    p1.pts[0] = Vertex(1.5,1.6);
    p1.pts[1] = Vertex(1.6,1.6);
    p1.pts[2] = Vertex(1.6,1.7);
    p1.pts[3] = Vertex(1.5,1.7);
    decomp->addProposition(p1);

    Polygon p2(4);
    p2.pts[0] = Vertex(.2,1.7);
    p2.pts[1] = Vertex(.3,1.7);
    p2.pts[2] = Vertex(.3,1.8);
    p2.pts[3] = Vertex(.2,1.8);
    decomp->addProposition(p2);
}

/* Returns whether a point (x,y) is within a given polygon.
   We are assuming that the polygon is a axis-aligned rectangle, with vertices stored
   in counter-clockwise order, beginning with the bottom-left vertex. */
bool polyContains(const Polygon& poly, double x, double y)
{
    return x >= poly.pts[0].x && x <= poly.pts[2].x
        && y >= poly.pts[0].y && y <= poly.pts[2].y;
}

/* Our state validity checker queries the decomposition for its obstacles,
   and checks for collisions against them.
   This is to prevent us from having to redefine the obstacles in multiple places. */
bool isStateValid(
    const oc::SpaceInformation *si,
    const oc::PropositionalTriangularDecomposition* decomp,
    const ob::State *state)
{
    if (!si->satisfiesBounds(state))
        return false;
    const ob::SE2StateSpace::StateType* se2 = state->as<ob::SE2StateSpace::StateType>();

	double x = se2->getX();
	double y = se2->getY();
    const std::vector<Polygon>& obstacles = decomp->getHoles();
    typedef std::vector<Polygon>::const_iterator ObstacleIter;
    for (ObstacleIter o = obstacles.begin(); o != obstacles.end(); ++o)
    {
        if (polyContains(*o, x, y))
            return false;
    }
	return true;
}

void propagate(const ob::State *start, const oc::Control *control, const double duration, ob::State *result)
{
    const ob::SE2StateSpace::StateType* se2 = start->as<ob::SE2StateSpace::StateType>();
    const oc::RealVectorControlSpace::ControlType* rctrl = control->as<oc::RealVectorControlSpace::ControlType>();

    double xout = se2->getX() + rctrl->values[0]*duration*cos(se2->getYaw());
    double yout = se2->getY() + rctrl->values[0]*duration*sin(se2->getYaw());
    double yawout = se2->getYaw() + rctrl->values[1];

    ob::SE2StateSpace::StateType* se2out = result->as<ob::SE2StateSpace::StateType>();
    se2out->setXY(xout, yout);
    se2out->setYaw(yawout);

    ob::SO2StateSpace::StateType* so2out = se2out->as<ob::SO2StateSpace::StateType>(1);
    ob::SO2StateSpace SO2;
    SO2.enforceBounds (so2out);
}

void plan(void)
{
    // construct the state space we are planning in
    ob::StateSpacePtr space(new ob::SE2StateSpace());

    // set the bounds for the R^2 part of SE(2)
    ob::RealVectorBounds bounds(2);
    bounds.setLow(0);
    bounds.setHigh(2);

    space->as<ob::SE2StateSpace>()->setBounds(bounds);

    // create triangulation that ignores obstacle and respects propositions
    MyDecomposition* ptd = new MyDecomposition(bounds);
    addObstaclesAndPropositions(ptd);
    ptd->setup();
    oc::PropositionalDecompositionPtr pd(ptd);

    // create a control space
    oc::ControlSpacePtr cspace(new oc::RealVectorControlSpace(space, 2));

    // set the bounds for the control space
    ob::RealVectorBounds cbounds(2);
    cbounds.setLow(-.5);
    cbounds.setHigh(.5);

    cspace->as<oc::RealVectorControlSpace>()->setBounds(cbounds);

    oc::SpaceInformationPtr si(new oc::SpaceInformation(space, cspace));
    si->setStateValidityChecker(boost::bind(&isStateValid, si.get(), ptd, _1));
    si->setStatePropagator(boost::bind(&propagate, _1, _2, _3, _4));
    si->setPropagationStepSize(0.025);

    //LTL co-safety sequencing formula: visit p2,p0 in that order
    std::vector<unsigned int> sequence(2);
    sequence[0] = 2;
    sequence[1] = 0;
    oc::AutomatonPtr cosafety = oc::Automaton::SequenceAutomaton(3, sequence);

    //LTL safety avoidance formula: never visit p1
    std::vector<unsigned int> toAvoid(1);
    toAvoid[0] = 1;
    oc::AutomatonPtr safety = oc::Automaton::AvoidanceAutomaton(3, toAvoid);

    //construct product graph (propDecomp x A_{cosafety} x A_{safety})
    oc::ProductGraphPtr product(new oc::ProductGraph(pd, cosafety, safety));
    oc::LTLSpaceInformationPtr ltlsi(new oc::LTLSpaceInformation(si, product));

    ob::LTLProblemDefinitionPtr pdef(new ob::LTLProblemDefinition(ltlsi));

    // create a start state
    ob::ScopedState<ob::SE2StateSpace> start(space);
    start->setX(0.2);
    start->setY(0.2);
    start->setYaw(0.0);

    pdef->addLowerStartState(start.get());

    //LTL planner (input: state information, product automaton)
    oc::LTLPlanner* ltlPlanner = new oc::LTLPlanner(ltlsi, product);

    ltlPlanner->setProblemDefinition(pdef);

    // attempt to solve the problem within thirty seconds of planning time
    ob::PlannerStatus solved = ltlPlanner->as<ob::Planner>()->solve(30.0);

    if (solved)
    {
        std::cout << "Found solution:" << std::endl;
        pdef->getLowerSolutionPath()->print(std::cout);
    }
    else
        std::cout << "No solution found" << std::endl;
}

int main(int, char **)
{
    plan();
    return 0;
}
<|endoftext|>


<commit_before>#ifndef RBX_CONFIGURATION_HPP
#define RBX_CONFIGURATION_HPP

#include "util/configuration.hpp"

namespace rubinius {
  class Configuration : public config::Configuration {
  public:
    // GC
    config::Integer gc_bytes;
    config::Integer gc_large_object;
    config::Integer gc_lifetime;
    config::Bool    gc_show;

    // JIT/Interpreter
    config::Bool    dynamic_interpreter_enabled;
    config::Bool    jit_enabled;
    config::Integer jit_dump_code;
    config::Integer jit_call_til_compile;
    config::Integer jit_max_method_size;
    config::Bool    jit_show_compiling;
    config::Bool    jit_profile;
    config::Bool    jit_inline_generic;
    config::Bool    jit_inline_debug;

    // Debug
    config::Bool    gil_debug;
    config::Integer print_config;
    config::Bool    ic_stats;

    // defaults
    static const int default_gc_bytes = 1048576 * 3;
    static const int default_gc_large_object = 2700;
    static const int default_gc_lifetime = 6;
    static const int default_jit_dump_code = 0;
    static const int default_jit_call_til_compile = 200;
    static const int default_jit_max_method_size = 2048;

    Configuration()
      : gc_bytes(this,        "gc.bytes", default_gc_bytes)
      , gc_large_object(this, "gc.large_object", default_gc_large_object)
      , gc_lifetime(this,     "gc.lifetime", default_gc_lifetime)
      , gc_show(this,         "gc.show")
      , dynamic_interpreter_enabled(this, "interpreter.dynamic")
      , jit_enabled(this,     "jit.enabled")
      , jit_dump_code(this,   "jit.dump_code", default_jit_dump_code)
      , jit_call_til_compile(this, "jit.call_til_compile",
                             default_jit_call_til_compile)
      , jit_max_method_size(this, "jit.max_method_size",
                            default_jit_max_method_size)
      , jit_show_compiling(this, "jit.show")
      , jit_profile(this,     "jit.profile")
      , jit_inline_generic(this, "jit.inline.generic")
      , jit_inline_debug(this, "jit.inline.debug")
      , gil_debug(this,       "vm.gil.debug")
      , print_config(this,    "config.print")
      , ic_stats(this,        "ic.stats")
    {
      gc_bytes.set_description(
          "The number of bytes the young generation of the GC should use");

      gc_large_object.set_description(
          "The size (in bytes) of the large object threshold");

      gc_lifetime.set_description(
          "How many young GC cycles an object lives before promoption");

      jit_enabled.set_description(
          "Whether or not to use the dynamic JIT");

      jit_dump_code.set_description(
          "1 == show simple IR, 2 == show optimized IR, 4 == show machine code");

      jit_call_til_compile.set_description(
          "How many times a method is called before the JIT is run on it");

      jit_max_method_size.set_description(
          "The max size of a method that will be JIT");

      jit_show_compiling.set_description(
          "Print out a status message when the JIT is operating");

      jit_profile.set_description(
          "The JIT will emit code to be sure JITd methods can be profile");

      jit_inline_generic.set_description(
          "Have the JIT inline generic methods");

      jit_inline_debug.set_description(
          "Have the JIT print out information about inlining");

      print_config.set_description(
          "blank or 1 == names and values, 2 == description as well");

      gil_debug.set_description(
          "Print out debugging when the GIL is locked/unlocked");

      gc_show.set_description(
          "Print out whenever the GC runs");

      ic_stats.set_description(
          "Print out stats about the InlineCaches before exiting");
    }
  };
}

#endif
<commit_msg>Bump up the call_til_compile to a sane number (found via profiling)<commit_after>#ifndef RBX_CONFIGURATION_HPP
#define RBX_CONFIGURATION_HPP

#include "util/configuration.hpp"

namespace rubinius {
  class Configuration : public config::Configuration {
  public:
    // GC
    config::Integer gc_bytes;
    config::Integer gc_large_object;
    config::Integer gc_lifetime;
    config::Bool    gc_show;

    // JIT/Interpreter
    config::Bool    dynamic_interpreter_enabled;
    config::Bool    jit_enabled;
    config::Integer jit_dump_code;
    config::Integer jit_call_til_compile;
    config::Integer jit_max_method_size;
    config::Bool    jit_show_compiling;
    config::Bool    jit_profile;
    config::Bool    jit_inline_generic;
    config::Bool    jit_inline_debug;

    // Debug
    config::Bool    gil_debug;
    config::Integer print_config;
    config::Bool    ic_stats;

    // defaults
    static const int default_gc_bytes = 1048576 * 3;
    static const int default_gc_large_object = 2700;
    static const int default_gc_lifetime = 6;
    static const int default_jit_dump_code = 0;
    static const int default_jit_call_til_compile = 4000;
    static const int default_jit_max_method_size = 2048;

    Configuration()
      : gc_bytes(this,        "gc.bytes", default_gc_bytes)
      , gc_large_object(this, "gc.large_object", default_gc_large_object)
      , gc_lifetime(this,     "gc.lifetime", default_gc_lifetime)
      , gc_show(this,         "gc.show")
      , dynamic_interpreter_enabled(this, "interpreter.dynamic")
      , jit_enabled(this,     "jit.enabled")
      , jit_dump_code(this,   "jit.dump_code", default_jit_dump_code)
      , jit_call_til_compile(this, "jit.call_til_compile",
                             default_jit_call_til_compile)
      , jit_max_method_size(this, "jit.max_method_size",
                            default_jit_max_method_size)
      , jit_show_compiling(this, "jit.show")
      , jit_profile(this,     "jit.profile")
      , jit_inline_generic(this, "jit.inline.generic")
      , jit_inline_debug(this, "jit.inline.debug")
      , gil_debug(this,       "vm.gil.debug")
      , print_config(this,    "config.print")
      , ic_stats(this,        "ic.stats")
    {
      gc_bytes.set_description(
          "The number of bytes the young generation of the GC should use");

      gc_large_object.set_description(
          "The size (in bytes) of the large object threshold");

      gc_lifetime.set_description(
          "How many young GC cycles an object lives before promoption");

      jit_enabled.set_description(
          "Whether or not to use the dynamic JIT");

      jit_dump_code.set_description(
          "1 == show simple IR, 2 == show optimized IR, 4 == show machine code");

      jit_call_til_compile.set_description(
          "How many times a method is called before the JIT is run on it");

      jit_max_method_size.set_description(
          "The max size of a method that will be JIT");

      jit_show_compiling.set_description(
          "Print out a status message when the JIT is operating");

      jit_profile.set_description(
          "The JIT will emit code to be sure JITd methods can be profile");

      jit_inline_generic.set_description(
          "Have the JIT inline generic methods");

      jit_inline_debug.set_description(
          "Have the JIT print out information about inlining");

      print_config.set_description(
          "blank or 1 == names and values, 2 == description as well");

      gil_debug.set_description(
          "Print out debugging when the GIL is locked/unlocked");

      gc_show.set_description(
          "Print out whenever the GC runs");

      ic_stats.set_description(
          "Print out stats about the InlineCaches before exiting");
    }
  };
}

#endif
<|endoftext|>