<commit_before>/*
 * qconnman - Connman Applet
 * Copyright (C) 2011 O.S. Systems
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License.
 *
 * This library 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
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "wirelesspage.h"
#include "authdialog.h"
#include "ipv4configurationdialog.h"

#include <qconnman/manager.h>
#include <qconnman/service.h>

#include <QListView>
#include <QMessageBox>
#include <QDebug>
#include <QTreeView>

WirelessPage::WirelessPage(const QModelIndex &technology, Manager *manager, QWidget *parent):
    QWidget(parent),
    m_technology(technology),
    m_service(NULL)
{
    ui.setupUi(this);

    m_wireless = static_cast<ManagerNode*>(technology.internalPointer())->object<Technology *>();

    ui.icon->setPixmap(QIcon::fromTheme("network-wireless").pixmap(QSize(48, 48)));
    ui.enabled->setChecked(m_wireless->isPowered());
    ui.advancedButton->setEnabled(false);
    ui.ipv4Widget->hide();

    ui.networkList->setModel(manager);
    ui.networkList->setRootModelIndex(technology);
    ui.networkList->setCurrentIndex(-1);

    connect(m_wireless, SIGNAL(poweredChanged(bool)), ui.enabled, SLOT(setChecked(bool)));
    connect(m_wireless, SIGNAL(poweredChanged(bool)), SLOT(updateUi()));
    connect(manager, SIGNAL(servicesChanged()), SLOT(configureService()));
    connect(m_wireless, SIGNAL(dataChanged()), SLOT(updateUi()));
    connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(toggleTechnology(bool)));
    connect(ui.networkList, SIGNAL(currentIndexChanged(int)), SLOT(setService(int)));

    configureService();
    updateUi();
}

void WirelessPage::updateUi()
{
	ui.networkList->setEnabled(m_wireless->isPowered());
 	ui.networkNameLabel->setEnabled(m_wireless->isPowered());

    ui.enabled->setChecked(m_wireless->isPowered());

    if (m_service && m_wireless->isPowered() && (m_service->state() == Service::ReadyState || m_service->state() == Service::OnlineState))
    {
        ui.status->setText("Connected");
        ui.ipv4Widget->setService(m_service);
        ui.ipv4Widget->unhide();
        ui.advancedButton->setEnabled(true);
    }
    else if (!m_service || (m_service->state() == Service::IdleState || m_service->state() == Service::DisconnectState))
    {
        ui.status->setText("Disconnected");
        ui.ipv4Widget->hide();
    }
}

void WirelessPage::configureService()
{
    for (int i = 0; i < m_technology.model()->rowCount(m_technology); i++)
    {
        Service *service = static_cast<ManagerNode *>(m_technology.child(i, 0).internalPointer())->object<Service *>();
        if (service->type() != "wifi") continue;

        if (service->state() == Service::ReadyState || service->state() == Service::OnlineState)
        {
            ui.networkList->setCurrentIndex(i);
            m_service = service;
            updateUi();
            break;
        }
    }
}

void WirelessPage::unconfigureService()
{
    Service *service = (Service *)QObject::sender();
    if (!service)
        return;
    m_service = NULL;
}

void WirelessPage::toggleTechnology(bool enable)
{
    m_wireless->setPowered(enable);
    if (!enable)
        ui.networkList->setCurrentIndex(-1);
}

void WirelessPage::setService(int index)
{
	if (index == -1)
    {
        ui.advancedButton->setEnabled(false);
        ui.clearButton->setEnabled(false);
        return;
    }

    ui.advancedButton->setEnabled(true);

    ManagerNode *node = static_cast<ManagerNode *>(m_technology.child(index, 1).internalPointer());
    m_service = node->object<Service *>();

    ui.clearButton->setEnabled(m_service->isFavorite());

    ui.ipv4Widget->setService(m_service);

    connect(m_service, SIGNAL(dataChanged()), SLOT(updateUi()));
    connect(m_service, SIGNAL(destroyed()), SLOT(unconfigureService()));

    if (m_service->state() == Service::ReadyState || m_service->state() == Service::OnlineState)
        ui.ipv4Widget->unhide();
    else
        ui.ipv4Widget->hide();

    m_service->connect();
}

void WirelessPage::on_advancedButton_clicked()
{
    Ipv4ConfigurationDialog dialog(m_service, this);
    if (dialog.exec() == QDialog::Accepted)
    {
        dialog.applyConfiguration();

        if (m_service->isAutoConnect())
        {
            m_service->disconnect();
            m_service->connect();
        }
        else
            m_service->disconnect();
    }
}

void WirelessPage::on_clearButton_clicked()
{
    QMessageBox::StandardButton result = QMessageBox::question(this, trUtf8("Are you sure?"),
                                                               trUtf8("Are you sure want to delete details of this network including password and any other configuration?"));
    if (result == QMessageBox::Yes) m_service->remove();
}
<commit_msg>Set question dialog buttons<commit_after>/*
 * qconnman - Connman Applet
 * Copyright (C) 2011 O.S. Systems
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License.
 *
 * This library 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
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "wirelesspage.h"
#include "authdialog.h"
#include "ipv4configurationdialog.h"

#include <qconnman/manager.h>
#include <qconnman/service.h>

#include <QListView>
#include <QMessageBox>
#include <QDebug>
#include <QTreeView>

WirelessPage::WirelessPage(const QModelIndex &technology, Manager *manager, QWidget *parent):
    QWidget(parent),
    m_technology(technology),
    m_service(NULL)
{
    ui.setupUi(this);

    m_wireless = static_cast<ManagerNode*>(technology.internalPointer())->object<Technology *>();

    ui.icon->setPixmap(QIcon::fromTheme("network-wireless").pixmap(QSize(48, 48)));
    ui.enabled->setChecked(m_wireless->isPowered());
    ui.advancedButton->setEnabled(false);
    ui.ipv4Widget->hide();

    ui.networkList->setModel(manager);
    ui.networkList->setRootModelIndex(technology);
    ui.networkList->setCurrentIndex(-1);

    connect(m_wireless, SIGNAL(poweredChanged(bool)), ui.enabled, SLOT(setChecked(bool)));
    connect(m_wireless, SIGNAL(poweredChanged(bool)), SLOT(updateUi()));
    connect(manager, SIGNAL(servicesChanged()), SLOT(configureService()));
    connect(m_wireless, SIGNAL(dataChanged()), SLOT(updateUi()));
    connect(ui.enabled, SIGNAL(toggled(bool)), SLOT(toggleTechnology(bool)));
    connect(ui.networkList, SIGNAL(currentIndexChanged(int)), SLOT(setService(int)));

    configureService();
    updateUi();
}

void WirelessPage::updateUi()
{
	ui.networkList->setEnabled(m_wireless->isPowered());
 	ui.networkNameLabel->setEnabled(m_wireless->isPowered());

    ui.enabled->setChecked(m_wireless->isPowered());

    if (m_service && m_wireless->isPowered() && (m_service->state() == Service::ReadyState || m_service->state() == Service::OnlineState))
    {
        ui.status->setText("Connected");
        ui.ipv4Widget->setService(m_service);
        ui.ipv4Widget->unhide();
        ui.advancedButton->setEnabled(true);
    }
    else if (!m_service || (m_service->state() == Service::IdleState || m_service->state() == Service::DisconnectState))
    {
        ui.status->setText("Disconnected");
        ui.ipv4Widget->hide();
    }
}

void WirelessPage::configureService()
{
    for (int i = 0; i < m_technology.model()->rowCount(m_technology); i++)
    {
        Service *service = static_cast<ManagerNode *>(m_technology.child(i, 0).internalPointer())->object<Service *>();
        if (service->type() != "wifi") continue;

        if (service->state() == Service::ReadyState || service->state() == Service::OnlineState)
        {
            ui.networkList->setCurrentIndex(i);
            m_service = service;
            updateUi();
            break;
        }
    }
}

void WirelessPage::unconfigureService()
{
    Service *service = (Service *)QObject::sender();
    if (!service)
        return;
    m_service = NULL;
}

void WirelessPage::toggleTechnology(bool enable)
{
    m_wireless->setPowered(enable);
    if (!enable)
        ui.networkList->setCurrentIndex(-1);
}

void WirelessPage::setService(int index)
{
	if (index == -1)
    {
        ui.advancedButton->setEnabled(false);
        ui.clearButton->setEnabled(false);
        return;
    }

    ui.advancedButton->setEnabled(true);

    ManagerNode *node = static_cast<ManagerNode *>(m_technology.child(index, 1).internalPointer());
    m_service = node->object<Service *>();

    ui.clearButton->setEnabled(m_service->isFavorite());

    ui.ipv4Widget->setService(m_service);

    connect(m_service, SIGNAL(dataChanged()), SLOT(updateUi()));
    connect(m_service, SIGNAL(destroyed()), SLOT(unconfigureService()));

    if (m_service->state() == Service::ReadyState || m_service->state() == Service::OnlineState)
        ui.ipv4Widget->unhide();
    else
        ui.ipv4Widget->hide();

    m_service->connect();
}

void WirelessPage::on_advancedButton_clicked()
{
    Ipv4ConfigurationDialog dialog(m_service, this);
    if (dialog.exec() == QDialog::Accepted)
    {
        dialog.applyConfiguration();

        if (m_service->isAutoConnect())
        {
            m_service->disconnect();
            m_service->connect();
        }
        else
            m_service->disconnect();
    }
}

void WirelessPage::on_clearButton_clicked()
{
    QMessageBox::StandardButton result = QMessageBox::question(this, trUtf8("Are you sure?"),
                                                               trUtf8("Are you sure want to delete details of this network including password and any other configuration?"),
                                                               QMessageBox::Yes | QMessageBox::No);
    if (result == QMessageBox::Yes) m_service->remove();
}
<|endoftext|>


<commit_before>#include "server/connection.hpp"
#include "server/request_handler.hpp"
#include "server/request_parser.hpp"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>

#include <iterator>
#include <string>
#include <vector>

namespace osrm
{
namespace server
{

Connection::Connection(boost::asio::io_service &io_service, RequestHandler &handler)
    : strand(io_service), TCP_socket(io_service), timer(io_service), request_handler(handler)
{
}

boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; }

/// Start the first asynchronous operation for the connection.
void Connection::start()
{
    TCP_socket.async_read_some(
        boost::asio::buffer(incoming_data_buffer),
        strand.wrap(boost::bind(&Connection::handle_read,
                                this->shared_from_this(),
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred)));

    if (keep_alive)
    {
        // Ok, we know it is not a first request, as we switched to keepalive
        timer.cancel();
        timer.expires_from_now(boost::posix_time::seconds(keepalive_timeout));
        timer.async_wait(std::bind(
            &Connection::handle_timeout, this->shared_from_this(), std::placeholders::_1));
    }
}

void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred)
{
    if (error)
    {
        return;
    }

    if (keep_alive)
    {
        timer.cancel();
        timer.expires_from_now(boost::posix_time::seconds(0));
    }

    // no error detected, let's parse the request
    http::compression_type compression_type(http::no_compression);
    RequestParser::RequestStatus result;
    std::tie(result, compression_type) =
        request_parser.parse(current_request,
                             incoming_data_buffer.data(),
                             incoming_data_buffer.data() + bytes_transferred);

    // the request has been parsed
    if (result == RequestParser::RequestStatus::valid)
    {
        current_request.endpoint = TCP_socket.remote_endpoint().address();
        request_handler.HandleRequest(current_request, current_reply);

        if (boost::iequals(current_request.connection, "close"))
        {
            current_reply.headers.emplace_back("Connection", "close");
        }
        else
        {
            keep_alive = true;
            current_reply.headers.emplace_back("Connection", "keep-alive");
            current_reply.headers.emplace_back("Keep-Alive", "timeout=5, max=512");
        }

        // compress the result w/ gzip/deflate if requested
        switch (compression_type)
        {
        case http::deflate_rfc1951:
            // use deflate for compression
            current_reply.headers.insert(current_reply.headers.begin(),
                                         {"Content-Encoding", "deflate"});
            compressed_output = compress_buffers(current_reply.content, compression_type);
            current_reply.set_size(static_cast<unsigned>(compressed_output.size()));
            output_buffer = current_reply.headers_to_buffers();
            output_buffer.push_back(boost::asio::buffer(compressed_output));
            break;
        case http::gzip_rfc1952:
            // use gzip for compression
            current_reply.headers.insert(current_reply.headers.begin(),
                                         {"Content-Encoding", "gzip"});
            compressed_output = compress_buffers(current_reply.content, compression_type);
            current_reply.set_size(static_cast<unsigned>(compressed_output.size()));
            output_buffer = current_reply.headers_to_buffers();
            output_buffer.push_back(boost::asio::buffer(compressed_output));
            break;
        case http::no_compression:
            // don't use any compression
            current_reply.set_uncompressed_size();
            output_buffer = current_reply.to_buffers();
            break;
        }
        // write result to stream
        boost::asio::async_write(TCP_socket,
                                 output_buffer,
                                 strand.wrap(boost::bind(&Connection::handle_write,
                                                         this->shared_from_this(),
                                                         boost::asio::placeholders::error)));
    }
    else if (result == RequestParser::RequestStatus::invalid)
    { // request is not parseable
        current_reply = http::reply::stock_reply(http::reply::bad_request);

        boost::asio::async_write(TCP_socket,
                                 current_reply.to_buffers(),
                                 strand.wrap(boost::bind(&Connection::handle_write,
                                                         this->shared_from_this(),
                                                         boost::asio::placeholders::error)));
    }
    else
    {
        // we don't have a result yet, so continue reading
        TCP_socket.async_read_some(
            boost::asio::buffer(incoming_data_buffer),
            strand.wrap(boost::bind(&Connection::handle_read,
                                    this->shared_from_this(),
                                    boost::asio::placeholders::error,
                                    boost::asio::placeholders::bytes_transferred)));
    }
}

/// Handle completion of a write operation.
void Connection::handle_write(const boost::system::error_code &error)
{
    if (!error)
    {
        if (keep_alive && processed_requests > 0)
        {
            --processed_requests;
            current_request = http::request();
            request_parser = RequestParser();
            this->start();
        }
        else
        {
            handle_shutdown();
        }
    }
}

/// Handle completion of a timeout timer..
void Connection::handle_timeout(boost::system::error_code ec)
{
    // We can get there for 3 reasons: spurious wakeup by timer.cancel(), which should be ignored
    // Slow client with a delayed _first_ request, which should be ignored too
    // Absent next request during waiting time in the keepalive mode - should stop right there.
    if (ec != boost::asio::error::operation_aborted)
    {
        TCP_socket.cancel();
        handle_shutdown();
    }
}

void Connection::handle_shutdown()
{
    // Initiate graceful connection closure.
    boost::system::error_code ignore_error;
    TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error);
}

std::vector<char> Connection::compress_buffers(const std::vector<char> &uncompressed_data,
                                               const http::compression_type compression_type)
{
    boost::iostreams::gzip_params compression_parameters;

    // there's a trade-off between speed and size. speed wins
    compression_parameters.level = boost::iostreams::zlib::best_speed;
    // check which compression flavor is used
    if (http::deflate_rfc1951 == compression_type)
    {
        compression_parameters.noheader = true;
    }

    std::vector<char> compressed_data;
    // plug data into boost's compression stream
    boost::iostreams::filtering_ostream gzip_stream;
    gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters));
    gzip_stream.push(boost::iostreams::back_inserter(compressed_data));
    gzip_stream.write(&uncompressed_data[0], uncompressed_data.size());
    boost::iostreams::close(gzip_stream);

    return compressed_data;
}
}
}
<commit_msg>connection's reply needs to be reset before handling next request on same connection.<commit_after>#include "server/connection.hpp"
#include "server/request_handler.hpp"
#include "server/request_parser.hpp"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>

#include <iterator>
#include <string>
#include <vector>

namespace osrm
{
namespace server
{

Connection::Connection(boost::asio::io_service &io_service, RequestHandler &handler)
    : strand(io_service), TCP_socket(io_service), timer(io_service), request_handler(handler)
{
}

boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; }

/// Start the first asynchronous operation for the connection.
void Connection::start()
{
    TCP_socket.async_read_some(
        boost::asio::buffer(incoming_data_buffer),
        strand.wrap(boost::bind(&Connection::handle_read,
                                this->shared_from_this(),
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred)));

    if (keep_alive)
    {
        // Ok, we know it is not a first request, as we switched to keepalive
        timer.cancel();
        timer.expires_from_now(boost::posix_time::seconds(keepalive_timeout));
        timer.async_wait(std::bind(
            &Connection::handle_timeout, this->shared_from_this(), std::placeholders::_1));
    }
}

void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred)
{
    if (error)
    {
        return;
    }

    if (keep_alive)
    {
        timer.cancel();
        timer.expires_from_now(boost::posix_time::seconds(0));
    }

    // no error detected, let's parse the request
    http::compression_type compression_type(http::no_compression);
    RequestParser::RequestStatus result;
    std::tie(result, compression_type) =
        request_parser.parse(current_request,
                             incoming_data_buffer.data(),
                             incoming_data_buffer.data() + bytes_transferred);

    // the request has been parsed
    if (result == RequestParser::RequestStatus::valid)
    {
        current_request.endpoint = TCP_socket.remote_endpoint().address();
        request_handler.HandleRequest(current_request, current_reply);

        if (boost::iequals(current_request.connection, "close"))
        {
            current_reply.headers.emplace_back("Connection", "close");
        }
        else
        {
            keep_alive = true;
            current_reply.headers.emplace_back("Connection", "keep-alive");
            current_reply.headers.emplace_back("Keep-Alive", "timeout=5, max=512");
        }

        // compress the result w/ gzip/deflate if requested
        switch (compression_type)
        {
        case http::deflate_rfc1951:
            // use deflate for compression
            current_reply.headers.insert(current_reply.headers.begin(),
                                         {"Content-Encoding", "deflate"});
            compressed_output = compress_buffers(current_reply.content, compression_type);
            current_reply.set_size(static_cast<unsigned>(compressed_output.size()));
            output_buffer = current_reply.headers_to_buffers();
            output_buffer.push_back(boost::asio::buffer(compressed_output));
            break;
        case http::gzip_rfc1952:
            // use gzip for compression
            current_reply.headers.insert(current_reply.headers.begin(),
                                         {"Content-Encoding", "gzip"});
            compressed_output = compress_buffers(current_reply.content, compression_type);
            current_reply.set_size(static_cast<unsigned>(compressed_output.size()));
            output_buffer = current_reply.headers_to_buffers();
            output_buffer.push_back(boost::asio::buffer(compressed_output));
            break;
        case http::no_compression:
            // don't use any compression
            current_reply.set_uncompressed_size();
            output_buffer = current_reply.to_buffers();
            break;
        }
        // write result to stream
        boost::asio::async_write(TCP_socket,
                                 output_buffer,
                                 strand.wrap(boost::bind(&Connection::handle_write,
                                                         this->shared_from_this(),
                                                         boost::asio::placeholders::error)));
    }
    else if (result == RequestParser::RequestStatus::invalid)
    { // request is not parseable
        current_reply = http::reply::stock_reply(http::reply::bad_request);

        boost::asio::async_write(TCP_socket,
                                 current_reply.to_buffers(),
                                 strand.wrap(boost::bind(&Connection::handle_write,
                                                         this->shared_from_this(),
                                                         boost::asio::placeholders::error)));
    }
    else
    {
        // we don't have a result yet, so continue reading
        TCP_socket.async_read_some(
            boost::asio::buffer(incoming_data_buffer),
            strand.wrap(boost::bind(&Connection::handle_read,
                                    this->shared_from_this(),
                                    boost::asio::placeholders::error,
                                    boost::asio::placeholders::bytes_transferred)));
    }
}

/// Handle completion of a write operation.
void Connection::handle_write(const boost::system::error_code &error)
{
    if (!error)
    {
        if (keep_alive && processed_requests > 0)
        {
            --processed_requests;
            current_request = http::request();
            current_reply = http::reply();
            request_parser = RequestParser();
            this->start();
        }
        else
        {
            handle_shutdown();
        }
    }
}

/// Handle completion of a timeout timer..
void Connection::handle_timeout(boost::system::error_code ec)
{
    // We can get there for 3 reasons: spurious wakeup by timer.cancel(), which should be ignored
    // Slow client with a delayed _first_ request, which should be ignored too
    // Absent next request during waiting time in the keepalive mode - should stop right there.
    if (ec != boost::asio::error::operation_aborted)
    {
        TCP_socket.cancel();
        handle_shutdown();
    }
}

void Connection::handle_shutdown()
{
    // Initiate graceful connection closure.
    boost::system::error_code ignore_error;
    TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error);
}

std::vector<char> Connection::compress_buffers(const std::vector<char> &uncompressed_data,
                                               const http::compression_type compression_type)
{
    boost::iostreams::gzip_params compression_parameters;

    // there's a trade-off between speed and size. speed wins
    compression_parameters.level = boost::iostreams::zlib::best_speed;
    // check which compression flavor is used
    if (http::deflate_rfc1951 == compression_type)
    {
        compression_parameters.noheader = true;
    }

    std::vector<char> compressed_data;
    // plug data into boost's compression stream
    boost::iostreams::filtering_ostream gzip_stream;
    gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters));
    gzip_stream.push(boost::iostreams::back_inserter(compressed_data));
    gzip_stream.write(&uncompressed_data[0], uncompressed_data.size());
    boost::iostreams::close(gzip_stream);

    return compressed_data;
}
}
}
<|endoftext|>


<commit_before>//Copyright (c) 2018 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include <cctype>
#include <fstream>
#include <stdio.h>
#include <sstream> // ostringstream
#include <regex> // regex parsing for temp flow graph
#include <string> // stod (string to double)
#include "../utils/logoutput.h"

#include "Settings.h"
#include "SettingRegistry.h"

namespace cura
{

void Settings::add(const std::string& key, const std::string value, ExtruderTrain* limit_to_extruder)
{
    settings.insert(std::pair<std::string, Setting>(key, Setting(value, limit_to_extruder)));
}

template<> std::string Settings::get<std::string>(const std::string& key) const
{
    if (settings.find(key) != settings.end())
    {
        Setting setting = settings.at(key);
        //TODO: If the setting has limit_to_extruder set, ask that extruder for the value instead.
        return setting.value;
    }
    else if(parent)
    {
        Setting setting = parent->get<std::string>(key);
        //TODO: If the setting has limit_to_extruder set, ask that extruder for the value instead.
        return setting.value;
    }
    else
    {
        logError("Trying to retrieve unregistered setting with no value given: '%s'\n", key.c_str());
        std::exit(2);
    }
}

template<> int Settings::get<int>(const std::string& key) const
{
    return atoi(get<std::string>(key).c_str());
}

template<> double Settings::get<double>(const std::string& key) const
{
    return atof(get<std::string>(key).c_str());
}

////////////////////////////OLD IMPLEMENTATION BELOW////////////////////////////

//c++11 no longer defines M_PI, so add our own constant.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

std::string toString(EGCodeFlavor flavor)
{
    switch (flavor)
    {
        case EGCodeFlavor::BFB:
            return "BFB";
        case EGCodeFlavor::MACH3:
            return "Mach3";
        case EGCodeFlavor::MAKERBOT:
            return "Makerbot";
        case EGCodeFlavor::ULTIGCODE:
            return "UltiGCode";
        case EGCodeFlavor::MARLIN_VOLUMATRIC:
            return "Marlin(Volumetric)";
        case EGCodeFlavor::GRIFFIN:
            return "Griffin";
        case EGCodeFlavor::REPETIER:
            return "Repetier";
        case EGCodeFlavor::REPRAP:
            return "RepRap";
        case EGCodeFlavor::MARLIN:
        default:
            return "Marlin";
    }
}

SettingsBase::SettingsBase()
: SettingsBaseVirtual(nullptr)
{
}

SettingsBase::SettingsBase(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

SettingsMessenger::SettingsMessenger(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

void SettingsBase::_setSetting(std::string key, std::string value)
{
    setting_values[key] = value;
}

void SettingsBase::setSetting(std::string key, std::string value)
{
    if (SettingRegistry::getInstance()->settingExists(key))
    {
        _setSetting(key, value);
    }
    else
    {
        cura::logWarning("Setting an unregistered setting %s to %s\n", key.c_str(), value.c_str());
        _setSetting(key, value); // Handy when programmers are in the process of introducing a new setting
    }
}

void SettingsBase::setSettingInheritBase(std::string key, const SettingsBaseVirtual& parent)
{
    setting_inherit_base.emplace(key, &parent);
}

const std::string& SettingsBase::getSettingString(const std::string& key) const
{
    auto value_it = setting_values.find(key);
    if (value_it != setting_values.end())
    {
        return value_it->second;
    }
    auto inherit_override_it = setting_inherit_base.find(key);
    if (inherit_override_it != setting_inherit_base.end())
    {
        return inherit_override_it->second->getSettingString(key);
    }
    if (parent)
    {
        return parent->getSettingString(key);
    }

    cura::logError("Trying to retrieve unregistered setting with no value given: '%s'\n", key.c_str());
    std::exit(-1);
    static std::string empty_string; // use static object rather than "" to avoid compilation warning
    return empty_string;
}

std::string SettingsBase::getAllLocalSettingsString() const
{
    std::stringstream sstream;
    for (auto pair : setting_values)
    {
        if (!pair.second.empty())
        {
            char buffer[4096];
            snprintf(buffer, 4096, " -s %s=\"%s\"", pair.first.c_str(), Escaped{pair.second.c_str()}.str);
            sstream << buffer;
        }
    }
    return sstream.str();
}

void SettingsMessenger::setSetting(std::string key, std::string value)
{
    parent->setSetting(key, value);
}

void SettingsMessenger::setSettingInheritBase(std::string key, const SettingsBaseVirtual& new_parent)
{
    parent->setSettingInheritBase(key, new_parent);
}

const std::string& SettingsMessenger::getSettingString(const std::string& key) const
{
    return parent->getSettingString(key);
}

}//namespace cura

<commit_msg>Add more overloads for getting settings<commit_after>//Copyright (c) 2018 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include <cctype>
#include <fstream>
#include <stdio.h>
#include <sstream> // ostringstream
#include <regex> // regex parsing for temp flow graph
#include <string> //Parsing strings (stod, stoul).
#include "../utils/logoutput.h"

#include "SettingTypes.h" //To overload and return the correct types from settings.
#include "Settings.h"
#include "SettingRegistry.h"

namespace cura
{

void Settings::add(const std::string& key, const std::string value, ExtruderTrain* limit_to_extruder)
{
    settings.insert(std::pair<std::string, Setting>(key, Setting(value, limit_to_extruder)));
}

template<> std::string Settings::get<std::string>(const std::string& key) const
{
    if (settings.find(key) != settings.end())
    {
        Setting setting = settings.at(key);
        //TODO: If the setting has limit_to_extruder set, ask that extruder for the value instead.
        return setting.value;
    }
    else if(parent)
    {
        Setting setting = parent->get<std::string>(key);
        //TODO: If the setting has limit_to_extruder set, ask that extruder for the value instead.
        return setting.value;
    }
    else
    {
        logError("Trying to retrieve unregistered setting with no value given: '%s'\n", key.c_str());
        std::exit(2);
    }
}

template<> int Settings::get<int>(const std::string& key) const
{
    return atoi(get<std::string>(key).c_str());
}

template<> double Settings::get<double>(const std::string& key) const
{
    return atof(get<std::string>(key).c_str());
}

template<> size_t Settings::get<size_t>(const std::string& key) const
{
    return std::stoul(get<std::string>(key).c_str());
}

template<> unsigned int Settings::get<unsigned int>(const std::string& key) const
{
    return get<size_t>(key);
}

template<> bool Settings::get<bool>(const std::string& key) const
{
    const std::string& value = get<std::string>(key);
    if (value == "on" || value == "yes" || value == "true" || value == "True")
    {
        return true;
    }
    const int num = atoi(value.c_str());
    return num != 0;
}

template<> DraftShieldHeightLimitation Settings::get<DraftShieldHeightLimitation>(const std::string& key) const
{
    const std::string& value = get<std::string>(key);
    if (value == "limited")
    {
        return DraftShieldHeightLimitation::LIMITED;
    }
    else //if (value == "full") or default.
    {
        return DraftShieldHeightLimitation::FULL;
    }
}

template<> FlowTempGraph Settings::get<FlowTempGraph>(const std::string& key) const
{
    std::string value_string = get<std::string>(key);

    FlowTempGraph result;
    if (value_string.empty())
    {
        return result; //Empty at this point.
    }
    /* Match with:
     * - the last opening bracket '['
     * - then a bunch of characters until the first comma
     * - a comma
     * - a bunch of characters until the first closing bracket ']'.
     * This matches with any substring which looks like "[ 124.512 , 124.1 ]".
     */
    std::regex regex("(\\[([^,\\[]*),([^,\\]]*)\\])");

    //Default constructor = end-of-sequence:
    std::regex_token_iterator<std::string::iterator> rend;

    const int submatches[] = {1, 2, 3}; //Match whole pair, first number and second number of a pair.
    std::regex_token_iterator<std::string::iterator> match_iter(value_string.begin(), value_string.end(), regex, submatches);
    while (match_iter != rend)
    {
        match_iter++; //Match the whole pair.
        if (match_iter == rend)
        {
            break;
        }
        std::string first_substring = *match_iter++;
        std::string second_substring = *match_iter++;
        try
        {
            double first = std::stod(first_substring);
            double second = std::stod(second_substring);
            result.data.emplace_back(first, second);
        }
        catch (const std::invalid_argument& e)
        {
            logError("Couldn't read 2D graph element [%s,%s] in setting '%s'. Ignored.\n", first_substring.c_str(), second_substring.c_str(), key.c_str());
        }
    }

    return result;
}

////////////////////////////OLD IMPLEMENTATION BELOW////////////////////////////

//c++11 no longer defines M_PI, so add our own constant.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

std::string toString(EGCodeFlavor flavor)
{
    switch (flavor)
    {
        case EGCodeFlavor::BFB:
            return "BFB";
        case EGCodeFlavor::MACH3:
            return "Mach3";
        case EGCodeFlavor::MAKERBOT:
            return "Makerbot";
        case EGCodeFlavor::ULTIGCODE:
            return "UltiGCode";
        case EGCodeFlavor::MARLIN_VOLUMATRIC:
            return "Marlin(Volumetric)";
        case EGCodeFlavor::GRIFFIN:
            return "Griffin";
        case EGCodeFlavor::REPETIER:
            return "Repetier";
        case EGCodeFlavor::REPRAP:
            return "RepRap";
        case EGCodeFlavor::MARLIN:
        default:
            return "Marlin";
    }
}

SettingsBase::SettingsBase()
: SettingsBaseVirtual(nullptr)
{
}

SettingsBase::SettingsBase(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

SettingsMessenger::SettingsMessenger(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

void SettingsBase::_setSetting(std::string key, std::string value)
{
    setting_values[key] = value;
}

void SettingsBase::setSetting(std::string key, std::string value)
{
    if (SettingRegistry::getInstance()->settingExists(key))
    {
        _setSetting(key, value);
    }
    else
    {
        cura::logWarning("Setting an unregistered setting %s to %s\n", key.c_str(), value.c_str());
        _setSetting(key, value); // Handy when programmers are in the process of introducing a new setting
    }
}

void SettingsBase::setSettingInheritBase(std::string key, const SettingsBaseVirtual& parent)
{
    setting_inherit_base.emplace(key, &parent);
}

const std::string& SettingsBase::getSettingString(const std::string& key) const
{
    auto value_it = setting_values.find(key);
    if (value_it != setting_values.end())
    {
        return value_it->second;
    }
    auto inherit_override_it = setting_inherit_base.find(key);
    if (inherit_override_it != setting_inherit_base.end())
    {
        return inherit_override_it->second->getSettingString(key);
    }
    if (parent)
    {
        return parent->getSettingString(key);
    }

    cura::logError("Trying to retrieve unregistered setting with no value given: '%s'\n", key.c_str());
    std::exit(-1);
    static std::string empty_string; // use static object rather than "" to avoid compilation warning
    return empty_string;
}

std::string SettingsBase::getAllLocalSettingsString() const
{
    std::stringstream sstream;
    for (auto pair : setting_values)
    {
        if (!pair.second.empty())
        {
            char buffer[4096];
            snprintf(buffer, 4096, " -s %s=\"%s\"", pair.first.c_str(), Escaped{pair.second.c_str()}.str);
            sstream << buffer;
        }
    }
    return sstream.str();
}

void SettingsMessenger::setSetting(std::string key, std::string value)
{
    parent->setSetting(key, value);
}

void SettingsMessenger::setSettingInheritBase(std::string key, const SettingsBaseVirtual& new_parent)
{
    parent->setSettingInheritBase(key, new_parent);
}

const std::string& SettingsMessenger::getSettingString(const std::string& key) const
{
    return parent->getSettingString(key);
}

}//namespace cura

<|endoftext|>


<commit_before>#include <sstream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/program_options.hpp>
#include <condition_variable>
#include <signal.h>
#include <chrono>
#include <atomic>
#include <random>
#include <rados/librados.hpp>
#include "libzlog.h"

namespace po = boost::program_options;

//#define VERIFY_IOS
//#define SLOPPY_SEQ

struct AioState {
  zlog::Log *log;
  ceph::bufferlist append_bl;
  ceph::bufferlist read_bl;
  zlog::Log::AioCompletion *c;
  uint64_t position;
  std::chrono::time_point<std::chrono::steady_clock> submitted;
};

static std::condition_variable io_cond;
static std::mutex io_lock;
static std::atomic<uint64_t> outstanding_ios;
static std::atomic<uint64_t> ios_completed;
static std::atomic<uint64_t> ios_completed_total;
static std::atomic<uint64_t> latency_ms;

static volatile int stop = 0;
static void sigint_handler(int sig) {
  stop = 1;
}

#ifdef VERIFY_IOS
static void verify_append_cb(zlog::Log::AioCompletion::completion_t cb,
    void *arg)
{
  AioState *s = (AioState*)arg;

  assert(s->c->get_return_value() == 0);
  s->c->release();

  assert(s->read_bl == s->append_bl);
  int sum1 = 0, sum2 = 0;
  for (unsigned i = 0; i < s->read_bl.length(); i++) {
    sum1 += (int)s->read_bl[i];
    sum2 += (int)s->append_bl[i];
  }
  assert(sum1 == sum2);

  delete s;
}
#endif

static void handle_append_cb(zlog::Log::AioCompletion::completion_t cb,
    void *arg)
{
  AioState *s = (AioState*)arg;
  auto completed = std::chrono::steady_clock::now();
  zlog::Log *log = s->log;

  ios_completed++;
  ios_completed_total++;
  outstanding_ios--;
  io_cond.notify_one();

  assert(s->c->get_return_value() == 0);
  s->c->release();
  s->c = NULL;

  auto diff_ms = std::chrono::duration_cast<
    std::chrono::milliseconds>(completed - s->submitted);
  latency_ms += diff_ms.count();

#ifdef VERIFY_IOS
  if (s->append_bl.length() > 0)
    assert(!(s->append_bl == s->read_bl));
  s->c = zlog::Log::aio_create_completion(s, verify_append_cb);
  int ret = log->AioRead(s->position, s->c, &s->read_bl);
  assert(ret == 0);
#else
  delete s;
#endif
}

static void handle_read_cb(zlog::Log::AioCompletion::completion_t cb,
    void *arg)
{
  AioState *s = (AioState*)arg;
  auto completed = std::chrono::steady_clock::now();

  ios_completed++;
  ios_completed_total++;
  outstanding_ios--;
  io_cond.notify_one();

  int op_rv = s->c->get_return_value();
  if (op_rv) {
    std::cout << op_rv << " " << s->position << std::endl;
  }
  assert(s->c->get_return_value() == 0);
  assert(s->read_bl.length() > 0);

  s->c->release();
  s->c = NULL;

  auto diff_ms = std::chrono::duration_cast<
    std::chrono::milliseconds>(completed - s->submitted);
  latency_ms += diff_ms.count();

  delete s;
}

class FakeSeqrClient : public zlog::SeqrClient {
 public:
  FakeSeqrClient(const std::string& name) :
    SeqrClient("", ""), seq_(0), name_(name)
  {
    assert(seq_.is_lock_free());
  }

  void Init(librados::IoCtx& ioctx) {
    zlog::Log log;
    int ret = zlog::Log::Open(ioctx, name_, NULL, log);
    assert(ret == 0);

    uint64_t epoch;
    ret = log.SetProjection(&epoch);
    assert(ret == 0);

    ret = log.Seal(epoch);
    assert(ret == 0);

    uint64_t position;
    ret = log.FindMaxPosition(epoch, &position);
    assert(ret == 0);

    epoch_ = epoch;
    seq_.store(position);

    std::cout << "init seq: pos=" << seq_.load() << std::endl;
  }

  void Connect() {}

  int CheckTail(uint64_t epoch, const std::string& pool,
      const std::string& name, uint64_t *position, bool next)
  {
    assert(name == name_);

    if (epoch_ < epoch)
      return -ERANGE;

    if (next) {
#ifdef SLOPPY_SEQ
      if (seq_ > 100 && seq_ % 10 == 0) {
        *position = seq_ / 2;
        seq_++;
      } else {
        uint64_t tail = seq_.fetch_add(1); // returns previous value
        *position = tail + 1;
      }
#else
      uint64_t tail = seq_.fetch_add(1); // returns previous value
      *position = tail + 1;
#endif
    } else
      *position = seq_.load();

    return 0;
  }

 private:
  std::atomic<uint64_t> seq_;
  std::string name_;
  uint64_t epoch_;
};

int main(int argc, char **argv)
{
  int width;
  std::string pool;
  std::string logname_req;
  int qdepth;
  int iosize;
  bool read_mode;

  po::options_description desc("Allowed options");
  desc.add_options()
    ("pool", po::value<std::string>(&pool)->required(), "Pool name")
    ("logname", po::value<std::string>(&logname_req)->default_value(""), "Log name")
    ("width", po::value<int>(&width)->required(), "Width")
    ("qdepth", po::value<int>(&qdepth)->default_value(1), "Queue depth")
    ("iosize", po::value<int>(&iosize)->default_value(0), "IO Size")
    ("read", po::value<bool>(&read_mode)->default_value(false), "Read mode")
  ;

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  assert(qdepth > 0);

  if (read_mode)
    assert(logname_req.length());

  // connect to rados
  librados::Rados cluster;
  cluster.init(NULL);
  cluster.conf_read_file(NULL);
  cluster.conf_parse_env(NULL);
  int ret = cluster.connect();
  assert(ret == 0);

  // open pool i/o context
  librados::IoCtx ioctx;
  ret = cluster.ioctx_create(pool.c_str(), ioctx);
  assert(ret == 0);

  signal(SIGINT, sigint_handler);

  // build a log name
  std::string logname;
  {
    std::stringstream ss;
    if (logname_req.size())
      ss << logname_req;
    else {
      boost::uuids::uuid uuid = boost::uuids::random_generator()();
      ss << uuid;
    }
    ss << ".log";
    logname = ss.str();
  }

  // setup log instance
  zlog::Log log;
  FakeSeqrClient client(logname);
  ret = zlog::Log::OpenOrCreate(ioctx, logname, width, &client, log);
  client.Init(ioctx);
  assert(ret == 0);

  // this is just a little hack that forces the epoch to be refreshed in the
  // log instance. otherwise when we blast out a bunch of async requests they
  // all end up having old epochs.
  ceph::bufferlist bl;
  log.Append(bl);

  /*
   * For read mode we look up the current tail and then issue random reads
   * within the range of the log.
   */
  uint64_t tail = 0;
  if (read_mode) {
    ret = log.CheckTail(&tail, false);
    assert(!ret);
    // teardown/setup is sloppy, so we trim off a bit so we don't hit any
    // unwritten entries.
    std::cout << "read mode tail: " << tail << std::endl;
    tail -= 50;
    assert(tail > 0);
  }
  std::random_device rd;
  std::mt19937 gen(rd());
  // skip the front of the log if there was some problems getting this setup
  // and those entries were skipped or filled.
  std::uniform_int_distribution<unsigned long long> dis(50, tail);
  if (read_mode)
    std::cout << "tail generation: " << dis.min() << " .. " << dis.max() << std::endl;

  std::unique_lock<std::mutex> lock(io_lock);

  ios_completed = 0;
  ios_completed_total = 0;
  outstanding_ios = 0;
  latency_ms = 0;

  char iobuf[iosize];

  auto start = std::chrono::steady_clock::now();
  for (;;) {
    uint64_t ios_completed_end = ios_completed;
    uint64_t latency_ms_end = latency_ms;
    auto end = std::chrono::steady_clock::now();
    std::chrono::duration<double> diff = std::chrono::duration_cast<
      std::chrono::duration<double>>(end - start);
    double secs = diff.count();
    if (secs > 5) {
      double ios_per_sec = (double)ios_completed_end / secs;
      double avg_ms_lat = (double)latency_ms_end / (double)ios_completed_end;
      std::cout << "total_iops: " << ios_completed_total <<
        " iops: " << ios_per_sec <<
        " avg_lat_ms: " << avg_ms_lat << std::endl;
      ios_completed = 0;
      latency_ms = 0;
      start = std::chrono::steady_clock::now();
    }

    while (outstanding_ios < qdepth) {

      AioState *state = new AioState;

      state->log = &log;

      if (read_mode) {
        state->position = dis(gen);
        state->c = zlog::Log::aio_create_completion(state, handle_read_cb);
        assert(state->c);
        state->submitted = std::chrono::steady_clock::now();
        ret = log.AioRead(state->position, state->c, &state->read_bl);
        assert(ret == 0);
      } else {
        state->c = zlog::Log::aio_create_completion(state, handle_append_cb);
        assert(state->c);
        for (unsigned i = 0; i < iosize; i++) {
          iobuf[i] = (char)rand();
        }
        state->append_bl.append(iobuf, iosize);
        state->submitted = std::chrono::steady_clock::now();
        ret = log.AioAppend(state->c, state->append_bl, &state->position);
        assert(ret == 0);
      }

      outstanding_ios++;
    }
    io_cond.wait(lock, [&]{ return outstanding_ios < qdepth; });

    if (stop)
      break;
  }

  // draining the ios is useful for running the read workload because
  // otherwise there is a section near the tail of the log that has unwritten
  // entries that would otherwise need to be handled in some way when they
  // were read.
  while (1) {
    std::cout << "draining ios: " << outstanding_ios << " remaining" << std::endl;
    if (outstanding_ios == 0)
      break;
    sleep(1);
  }

  return 0;
}
<commit_msg>bench: create a perf reporting thread<commit_after>#include <sstream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/program_options.hpp>
#include <condition_variable>
#include <signal.h>
#include <chrono>
#include <atomic>
#include <thread>
#include <random>
#include <rados/librados.hpp>
#include "libzlog.h"

namespace po = boost::program_options;

//#define VERIFY_IOS
//#define SLOPPY_SEQ

struct AioState {
  zlog::Log *log;
  ceph::bufferlist append_bl;
  ceph::bufferlist read_bl;
  zlog::Log::AioCompletion *c;
  uint64_t position;
  std::chrono::time_point<std::chrono::steady_clock> submitted;
};

static std::condition_variable io_cond;
static std::mutex io_lock;
static std::atomic<uint64_t> outstanding_ios;
static std::atomic<uint64_t> ios_completed;
static std::atomic<uint64_t> ios_completed_total;
static std::atomic<uint64_t> latency_ms;

static volatile int stop = 0;
static void sigint_handler(int sig) {
  stop = 1;
}

static void report()
{
  while (!stop) {
    auto start = std::chrono::steady_clock::now();
    uint64_t ios_completed_start = ios_completed;
    uint64_t latency_ms_start = latency_ms;

    sleep(5);
    if (stop)
      break;

    auto end = std::chrono::steady_clock::now();
    uint64_t ios_completed_end = ios_completed;
    uint64_t latency_ms_end = latency_ms;

    auto diff = std::chrono::duration_cast<
        std::chrono::duration<double>>(end - start);

    double ios_per_sec = (double)(ios_completed_end - ios_completed_start) / diff.count();
    double avg_ms_lat = (double)(latency_ms_end - latency_ms_start) /
      (double)(ios_completed_end - ios_completed_start);

    std::cout << "period: " << diff.count() <<
      " total_iops: " << ios_completed_total <<
      " iops: " << ios_per_sec <<
      " avg_lat_ms: " << avg_ms_lat << std::endl;
  }
}

#ifdef VERIFY_IOS
static void verify_append_cb(zlog::Log::AioCompletion::completion_t cb,
    void *arg)
{
  AioState *s = (AioState*)arg;

  assert(s->c->get_return_value() == 0);
  s->c->release();

  assert(s->read_bl == s->append_bl);
  int sum1 = 0, sum2 = 0;
  for (unsigned i = 0; i < s->read_bl.length(); i++) {
    sum1 += (int)s->read_bl[i];
    sum2 += (int)s->append_bl[i];
  }
  assert(sum1 == sum2);

  delete s;
}
#endif

static void handle_append_cb(zlog::Log::AioCompletion::completion_t cb,
    void *arg)
{
  AioState *s = (AioState*)arg;
  auto completed = std::chrono::steady_clock::now();
  zlog::Log *log = s->log;

  ios_completed++;
  ios_completed_total++;
  outstanding_ios--;
  io_cond.notify_one();

  assert(s->c->get_return_value() == 0);
  s->c->release();
  s->c = NULL;

  auto diff_ms = std::chrono::duration_cast<
    std::chrono::milliseconds>(completed - s->submitted);
  latency_ms += diff_ms.count();

#ifdef VERIFY_IOS
  if (s->append_bl.length() > 0)
    assert(!(s->append_bl == s->read_bl));
  s->c = zlog::Log::aio_create_completion(s, verify_append_cb);
  int ret = log->AioRead(s->position, s->c, &s->read_bl);
  assert(ret == 0);
#else
  delete s;
#endif
}

static void handle_read_cb(zlog::Log::AioCompletion::completion_t cb,
    void *arg)
{
  AioState *s = (AioState*)arg;
  auto completed = std::chrono::steady_clock::now();

  ios_completed++;
  ios_completed_total++;
  outstanding_ios--;
  io_cond.notify_one();

  int op_rv = s->c->get_return_value();
  if (op_rv) {
    std::cout << op_rv << " " << s->position << std::endl;
  }
  assert(s->c->get_return_value() == 0);
  assert(s->read_bl.length() > 0);

  s->c->release();
  s->c = NULL;

  auto diff_ms = std::chrono::duration_cast<
    std::chrono::milliseconds>(completed - s->submitted);
  latency_ms += diff_ms.count();

  delete s;
}

class FakeSeqrClient : public zlog::SeqrClient {
 public:
  FakeSeqrClient(const std::string& name) :
    SeqrClient("", ""), seq_(0), name_(name)
  {
    assert(seq_.is_lock_free());
  }

  void Init(librados::IoCtx& ioctx) {
    zlog::Log log;
    int ret = zlog::Log::Open(ioctx, name_, NULL, log);
    assert(ret == 0);

    uint64_t epoch;
    ret = log.SetProjection(&epoch);
    assert(ret == 0);

    ret = log.Seal(epoch);
    assert(ret == 0);

    uint64_t position;
    ret = log.FindMaxPosition(epoch, &position);
    assert(ret == 0);

    epoch_ = epoch;
    seq_.store(position);

    std::cout << "init seq: pos=" << seq_.load() << std::endl;
  }

  void Connect() {}

  int CheckTail(uint64_t epoch, const std::string& pool,
      const std::string& name, uint64_t *position, bool next)
  {
    assert(name == name_);

    if (epoch_ < epoch)
      return -ERANGE;

    if (next) {
#ifdef SLOPPY_SEQ
      if (seq_ > 100 && seq_ % 10 == 0) {
        *position = seq_ / 2;
        seq_++;
      } else {
        uint64_t tail = seq_.fetch_add(1); // returns previous value
        *position = tail + 1;
      }
#else
      uint64_t tail = seq_.fetch_add(1); // returns previous value
      *position = tail + 1;
#endif
    } else
      *position = seq_.load();

    return 0;
  }

 private:
  std::atomic<uint64_t> seq_;
  std::string name_;
  uint64_t epoch_;
};

int main(int argc, char **argv)
{
  int width;
  std::string pool;
  std::string logname_req;
  int qdepth;
  int iosize;
  bool read_mode;

  po::options_description desc("Allowed options");
  desc.add_options()
    ("pool", po::value<std::string>(&pool)->required(), "Pool name")
    ("logname", po::value<std::string>(&logname_req)->default_value(""), "Log name")
    ("width", po::value<int>(&width)->required(), "Width")
    ("qdepth", po::value<int>(&qdepth)->default_value(1), "Queue depth")
    ("iosize", po::value<int>(&iosize)->default_value(0), "IO Size")
    ("read", po::value<bool>(&read_mode)->default_value(false), "Read mode")
  ;

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  assert(qdepth > 0);

  if (read_mode)
    assert(logname_req.length());

  // connect to rados
  librados::Rados cluster;
  cluster.init(NULL);
  cluster.conf_read_file(NULL);
  cluster.conf_parse_env(NULL);
  int ret = cluster.connect();
  assert(ret == 0);

  // open pool i/o context
  librados::IoCtx ioctx;
  ret = cluster.ioctx_create(pool.c_str(), ioctx);
  assert(ret == 0);

  signal(SIGINT, sigint_handler);

  // build a log name
  std::string logname;
  {
    std::stringstream ss;
    if (logname_req.size())
      ss << logname_req;
    else {
      boost::uuids::uuid uuid = boost::uuids::random_generator()();
      ss << uuid;
    }
    ss << ".log";
    logname = ss.str();
  }

  // setup log instance
  zlog::Log log;
  FakeSeqrClient client(logname);
  ret = zlog::Log::OpenOrCreate(ioctx, logname, width, &client, log);
  client.Init(ioctx);
  assert(ret == 0);

  // this is just a little hack that forces the epoch to be refreshed in the
  // log instance. otherwise when we blast out a bunch of async requests they
  // all end up having old epochs.
  ceph::bufferlist bl;
  log.Append(bl);

  /*
   * For read mode we look up the current tail and then issue random reads
   * within the range of the log.
   */
  uint64_t tail = 0;
  if (read_mode) {
    ret = log.CheckTail(&tail, false);
    assert(!ret);
    // teardown/setup is sloppy, so we trim off a bit so we don't hit any
    // unwritten entries.
    std::cout << "read mode tail: " << tail << std::endl;
    tail -= 50;
    assert(tail > 0);
  }
  std::random_device rd;
  std::mt19937 gen(rd());
  // skip the front of the log if there was some problems getting this setup
  // and those entries were skipped or filled.
  std::uniform_int_distribution<unsigned long long> dis(50, tail);
  if (read_mode)
    std::cout << "tail generation: " << dis.min() << " .. " << dis.max() << std::endl;

  std::unique_lock<std::mutex> lock(io_lock);

  ios_completed = 0;
  ios_completed_total = 0;
  outstanding_ios = 0;
  latency_ms = 0;

  char iobuf[iosize];

  std::thread reporting_thread(report);

  for (;;) {
    while (outstanding_ios < qdepth) {

      AioState *state = new AioState;

      state->log = &log;

      if (read_mode) {
        state->position = dis(gen);
        state->c = zlog::Log::aio_create_completion(state, handle_read_cb);
        assert(state->c);
        state->submitted = std::chrono::steady_clock::now();
        ret = log.AioRead(state->position, state->c, &state->read_bl);
        assert(ret == 0);
      } else {
        state->c = zlog::Log::aio_create_completion(state, handle_append_cb);
        assert(state->c);
        for (unsigned i = 0; i < iosize; i++) {
          iobuf[i] = (char)rand();
        }
        state->append_bl.append(iobuf, iosize);
        state->submitted = std::chrono::steady_clock::now();
        ret = log.AioAppend(state->c, state->append_bl, &state->position);
        assert(ret == 0);
      }

      outstanding_ios++;
    }
    io_cond.wait(lock, [&]{ return outstanding_ios < qdepth; });

    if (stop)
      break;
  }

  // draining the ios is useful for running the read workload because
  // otherwise there is a section near the tail of the log that has unwritten
  // entries that would otherwise need to be handled in some way when they
  // were read.
  while (1) {
    std::cout << "draining ios: " << outstanding_ios << " remaining" << std::endl;
    if (outstanding_ios == 0)
      break;
    sleep(1);
  }

  reporting_thread.join();

  return 0;
}
<|endoftext|>


<commit_before>#include "zombieplayer.h"
#include "auxiliary.h"
#include "physics/moving/unit.h"

#include <sdl/graphic.h>

#include <list>
#include <cassert>

#include <glm/gtx/rotate_vector.hpp>

namespace zombie {

	ZombiePlayer::ZombiePlayer(std::unique_ptr<Unit> unit)
		: findNewTargetTime_{random(0.f, 3.f)}
		, timeToUpdateAngleDirection_{random()}
		, targetAngle_{unit->getDirection()}
		, unit_{std::move(unit)} {
	}

	void ZombiePlayer::updateInput(double time, double deltaTime) {
		Input input{};

		if (time > findNewTargetTime_) {
			findNewTargetTime_ = random(0.f, 3.f) + static_cast<float>(time);

			target_ = findUninfectedTarget(unit_->getPosition(), unit_->getVisibleObjects());
		}

		if (time > timeToUpdateAngleDirection_) {
			timeToUpdateAngleDirection_ = random() + static_cast<float>(time);

			// Has a target?
			if (target_ != nullptr && target_->isEnabled() && !target_->isDead()) {
				auto dir = target_->getPosition() - unit_->getPosition();
				targetAngle_ = std::atan2(dir.y, dir.x);
				forward_ = true;

				auto distSquared = dir.LengthSquared();

				// Target is in range?
				if (auto& weapon = unit_->getWeapon();
					weapon != nullptr && distSquared < weapon->getRange() * weapon->getRange()) {

					// Attack!
					input.shoot = true;
				}
			} else {
				targetAngle_ +=  random(-0.5f, 0.5f) * 2.f * Pi * 2.f * 0.05f;
				forward_ = random() > 0.25f;
			}
		}

		auto diffAngle = calculateDifferenceBetweenAngles(targetAngle_, unit_->getDirection());

		// Turn?
		if (std::abs(diffAngle) > 0.1f) {
			if (diffAngle > 0) {
				input.turnLeft = true;
			} else {
				input.turnRight = true;
			}
		}

		input.forward = forward_;
		unit_->setInput(input);
		unit_->updatePhysics(time, deltaTime);
	}

	void ZombiePlayer::draw(sdl::Graphic& graphic) {
		auto pos = unit_->getPosition();
		graphic.addCircle({pos.x, pos.y}, unit_->getRadius(), sdl::color::html::Firebrick);
		graphic.addCircleOutline({pos.x, pos.y}, unit_->getViewDistance(), 0.04f, sdl::color::html::Firebrick);
        graphic.addLine({pos.x, pos.y}, glm::vec2{pos.x, pos.y} + glm::rotate(glm::vec2{1.f, 0.f}*0.5f, unit_->getDirection()), 0.1f, sdl::color::html::Firebrick);
	}

	MovingObject* ZombiePlayer::getMovingObject() const {
		return unit_.get();;
	}

	MovingObject* ZombiePlayer::findUninfectedTarget(Position position, const std::list<MovingObject*>& units) const {
		MovingObject* target = nullptr;
		float distance = 100.f;
		for (auto unit : units) {
			if (!unit->isInfected()) {
				auto tmp = (position - unit->getPosition()).LengthSquared();
				if (tmp < distance) {
					target = unit;
					distance = tmp;
				}
			}
		}
		return target;
	}

}
<commit_msg>Dont search for targets<commit_after>#include "zombieplayer.h"
#include "auxiliary.h"
#include "physics/moving/unit.h"

#include <sdl/graphic.h>

#include <list>
#include <cassert>

#include <glm/gtx/rotate_vector.hpp>

namespace zombie {

	ZombiePlayer::ZombiePlayer(std::unique_ptr<Unit> unit)
		: findNewTargetTime_{random(0.f, 3.f)}
		, timeToUpdateAngleDirection_{random()}
		, targetAngle_{unit->getDirection()}
		, unit_{std::move(unit)} {
	}

	void ZombiePlayer::updateInput(double time, double deltaTime) {
		Input input{};

		if (time > findNewTargetTime_) {
			findNewTargetTime_ = random(0.f, 3.f) + static_cast<float>(time);

			target_ = findUninfectedTarget(unit_->getPosition(), unit_->getVisibleObjects());
		}

		if (time > timeToUpdateAngleDirection_) {
			timeToUpdateAngleDirection_ = random() + static_cast<float>(time);

			// Has a target?
			if (false && target_ != nullptr && target_->isEnabled() && !target_->isDead()) {
				auto dir = target_->getPosition() - unit_->getPosition();
				targetAngle_ = std::atan2(dir.y, dir.x);
				forward_ = true;

				auto distSquared = dir.LengthSquared();

				// Target is in range?
				if (auto& weapon = unit_->getWeapon();
					weapon != nullptr && distSquared < weapon->getRange() * weapon->getRange()) {

					// Attack!
					input.shoot = true;
				}
			} else {
				targetAngle_ +=  random(-0.5f, 0.5f) * 2.f * Pi * 2.f * 0.05f;
				forward_ = random() > 0.25f;
			}
		}

		auto diffAngle = calculateDifferenceBetweenAngles(targetAngle_, unit_->getDirection());

		// Turn?
		if (std::abs(diffAngle) > 0.1f) {
			if (diffAngle > 0) {
				input.turnLeft = true;
			} else {
				input.turnRight = true;
			}
		}

		input.forward = forward_;
		unit_->setInput(input);
		unit_->updatePhysics(time, deltaTime);
	}

	void ZombiePlayer::draw(sdl::Graphic& graphic) {
		auto pos = unit_->getPosition();
		graphic.addCircle({pos.x, pos.y}, unit_->getRadius(), sdl::color::html::Firebrick);
		graphic.addCircleOutline({pos.x, pos.y}, unit_->getViewDistance(), 0.04f, sdl::color::html::Firebrick);
        graphic.addLine({pos.x, pos.y}, glm::vec2{pos.x, pos.y} + glm::rotate(glm::vec2{1.f, 0.f}*0.5f, unit_->getDirection()), 0.1f, sdl::color::html::Firebrick);
	}

	MovingObject* ZombiePlayer::getMovingObject() const {
		return unit_.get();;
	}

	MovingObject* ZombiePlayer::findUninfectedTarget(Position position, const std::list<MovingObject*>& units) const {
		MovingObject* target = nullptr;
		float distance = 100.f;
		for (auto unit : units) {
			if (!unit->isInfected()) {
				auto tmp = (position - unit->getPosition()).LengthSquared();
				if (tmp < distance) {
					target = unit;
					distance = tmp;
				}
			}
		}
		return target;
	}

}
<|endoftext|>


<commit_before>#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <ctype.h>
#include <iostream>

using namespace cv;
using namespace std;

int sigma = 3;
int smoothType = CV_GAUSSIAN;

int main( int argc, char** argv )
{
    VideoCapture cap;

    if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        cap.open(argc == 2 ? argv[1][0] - '0' : 0);
    else if( argc == 2 )
        cap.open(argv[1]);

    if( !cap.isOpened() )
    {
        cout << "Could not initialize capturing...\n";
        return -1;
    }

    namedWindow( "Laplacian", 0 );
    createTrackbar( "Sigma", "Laplacian", &sigma, 15, 0 );

    Mat smoothed, laplace, result;

    for(;;)
    {
        Mat frame;
        cap >> frame;
        if( frame.empty() )
            break;

        int ksize = (sigma*5)|1;
        if(smoothType == CV_GAUSSIAN)
            GaussianBlur(frame, smoothed, Size(ksize, ksize), sigma, sigma);
        else if(smoothType == CV_BLUR)
            blur(frame, smoothed, Size(ksize, ksize));
        else
            medianBlur(frame, smoothed, ksize);

        Laplacian(smoothed, laplace, CV_16S, 5);
        convertScaleAbs(laplace, result, (sigma+1)*0.25);
        imshow("Laplacian", result);

        int c = waitKey(30);
        if( c == ' ' )
            smoothType = smoothType == CV_GAUSSIAN ? CV_BLUR : smoothType == CV_BLUR ? CV_MEDIAN : CV_GAUSSIAN;
        if( c == 'q' || c == 'Q' || (c & 255) == 27 )
            break;
    }

    return 0;
}
<commit_msg>revamped<commit_after>#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <ctype.h>
#include <iostream>

using namespace cv;
using namespace std;

void help()
{
	cout <<
			"\nThis program demonstrates Laplace point/edge detection using OpenCV function Laplacian()\n"
			"It captures from the camera of your choice: 0, 1, ... default 0\n"
			"Call:\n"
			"./laplace [camera #, default 0]\n" << endl;
}

int sigma = 3;
int smoothType = CV_GAUSSIAN;

int main( int argc, char** argv )
{
    VideoCapture cap;
    help();

    if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        cap.open(argc == 2 ? argv[1][0] - '0' : 0);
    else if( argc == 2 )
        cap.open(argv[1]);

    if( !cap.isOpened() )
    {
        cout << "Could not initialize capturing...\n";
        return -1;
    }

    namedWindow( "Laplacian", 0 );
    createTrackbar( "Sigma", "Laplacian", &sigma, 15, 0 );

    Mat smoothed, laplace, result;

    for(;;)
    {
        Mat frame;
        cap >> frame;
        if( frame.empty() )
            break;

        int ksize = (sigma*5)|1;
        if(smoothType == CV_GAUSSIAN)
            GaussianBlur(frame, smoothed, Size(ksize, ksize), sigma, sigma);
        else if(smoothType == CV_BLUR)
            blur(frame, smoothed, Size(ksize, ksize));
        else
            medianBlur(frame, smoothed, ksize);

        Laplacian(smoothed, laplace, CV_16S, 5);
        convertScaleAbs(laplace, result, (sigma+1)*0.25);
        imshow("Laplacian", result);

        int c = waitKey(30);
        if( c == ' ' )
            smoothType = smoothType == CV_GAUSSIAN ? CV_BLUR : smoothType == CV_BLUR ? CV_MEDIAN : CV_GAUSSIAN;
        if( c == 'q' || c == 'Q' || (c & 255) == 27 )
            break;
    }

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2016 Dolotov Evgeniy
#include <iostream>

using std::cout;
using std::endl;
int main() {
    cout << "Hello, World!!" << endl;
    return 0;
}
<commit_msg>clear project<commit_after><|endoftext|>


<commit_before>//! Copyright (c) 2013 ASMlover. 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 ofconditions 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 materialsprovided with the
//!    distribution.
//!
//! 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 HOLDER 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.
#if defined(_WINDOWS_) || defined(_MSC_VER)
# ifndef _WINDOWS_
#   include <winsock2.h>
# endif
  typedef int socklen_t;
#elif defined(__linux__)
# include <sys/types.h>
# include <sys/socket.h>
# include <arpa/inet.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <unistd.h>
# include <fcntl.h>
#endif
#include "net.h"
#include "address.h"
#include "socket.h"

Socket::Socket(void)
  : fd_(kNetTypeInval)
{
}

Socket::~Socket(void)
{
  Close();
}

bool
Socket::SetOption(int level, int optname, int optval)
{
  if (kNetTypeInval == fd_)
    return false;

  if (kNetTypeError == setsockopt(fd_, level,
        optname,
#if defined(_WINDOWS_) || defined(_MSC_VER)
        (const char*)&optval,
#elif defined(__linux__)
        (const void*)&optval,
#endif
        sizeof(optval)))
    return false;

  return true;
}

bool
Socket::SetNonBlock(void)
{
  if (kNetTypeInval == fd_)
    return false;

#if defined(_WINDOWS_) || defined(_MSC_VER)
  u_long mode = 1;
  if (kNetTypeError == ioctlsocket(fd_, FIONBIO, &mode))
    return false;
#elif defined(__linux__)
  int opt = fcntl(fd_, F_GETFL);
  if (kNetTypeError == fd_)
    return false;
  if (kNetTypeError == fcntl(fd_, F_SETFL, opt | O_NONBLOCK))
    return false;
#endif

  return true;
}

bool
Socket::SetTcpNoDelay(bool nodelay)
{
  return SetOption(IPPROTO_TCP, TCP_NODELAY, (nodelay ? 1 : 0));
}

bool
Socket::SetReuseAddr(bool reuse)
{
  return SetOption(SOL_SOCKET, SO_REUSEADDR, (reuse ? 1 : 0));
}

bool
Socket::SetKeepAlive(bool keep)
{
  return SetOption(SOL_SOCKET, SO_KEEPALIVE, (keep ? 1 : 0));
}

bool
Socket::SetReadBuffer(int bytes)
{
  return SetOption(SOL_SOCKET, SO_RCVBUF, bytes);
}

bool
Socket::SetWriteBuffer(int bytes)
{
  return SetOption(SOL_SOCKET, SO_SNDBUF, bytes);
}

bool
Socket::SetSelfReadBuffer(int bytes)
{
  return rbuf_.Init(bytes);
}

bool
Socket::SetSelfWriteBuffer(int bytes)
{
  return wbuf_.Init(bytes);
}

bool
Socket::Open(void)
{
  fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (kNetTypeInval == fd_)
    return false;

  return true;
}

void
Socket::Close(void)
{
  if (kNetTypeInval == fd_) {
#if defined(_WINDOWS_) || defined(_MSC_VER)
    shutdown(fd_, SD_BOTH);
    closesocket(fd_);
#elif defined(__linux__)
    shutdown(fd_, SHUT_RDWR);
    close(fd_);
#endif
    fd_ = kNetTypeInval;
  }
}

bool
Socket::Bind(const char* ip, unsigned short port)
{
  if (kNetTypeInval == fd_)
    return false;

  struct sockaddr_in host_addr;
  host_addr.sin_addr.s_addr =
    (NULL == ip ? htonl(INADDR_ANY) : inet_addr(ip));
  host_addr.sin_family      = AF_INET;
  host_addr.sin_port        = htons(port);

  if (kNetTypeError == bind(fd_,
        (struct sockaddr*)&host_addr, sizeof(host_addr)))
    return false;

  return true;
}

bool
Socket::Listen(void)
{
  if (kNetTypeInval == fd_)
    return false;

  if (kNetTypeError == listen(fd_, SOMAXCONN))
    return false;

  return true;
}

bool
Socket::Accept(Socket* s, Address* addr)
{
  if (kNetTypeInval == fd_ || NULL == s)
    return false;

  struct sockaddr_in remote_addr;
  socklen_t addrlen = sizeof(remote_addr);
  int fd = accept(fd_, (struct sockaddr*)&remote_addr, &addrlen);
  if (kNetTypeInval == fd)
    return false;

  s->Attach(fd);
  if (NULL != addr)
    addr->Attach(&remote_addr);

  return true;
}

bool
Socket::Connect(const char* ip, unsigned short port)
{
  if (kNetTypeInval == fd_)
    return false;

  if (NULL == ip)
    ip = "127.0.0.1";
  struct sockaddr_in remote_addr;
  remote_addr.sin_addr.s_addr = inet_addr(ip);
  remote_addr.sin_family      = AF_INET;
  remote_addr.sin_port        = htons(port);
  if (kNetTypeError == connect(fd_,
        (struct sockaddr*)&remote_addr, sizeof(remote_addr)))
    return false;

  return true;
}

int
Socket::ReadBlock(int bytes, char* buffer)
{
  if (kNetTypeInval == fd_ || bytes <= 0 || NULL == buffer)
    return kNetTypeError;

  int ret = recv(fd_, buffer, bytes, 0);

  return ret;
}

int
Socket::WriteBlock(const char* buffer, int bytes)
{
  if (kNetTypeInval == fd_ || NULL == buffer || bytes <= 0)
    return kNetTypeError;

  int write_bytes = 0;
  int ret;
  while (write_bytes < bytes) {
    ret = send(fd_, buffer + write_bytes, bytes - write_bytes, 0);
    if (kNetTypeError == ret)
      return ret;

    write_bytes += ret;
  }

  return write_bytes;
}

int
Socket::Read(int bytes, char* buffer)
{
  if (kNetTypeInval == fd_ || bytes <= 0 || NULL == buffer)
    return kNetTypeError;

  return rbuf_.Get(bytes, buffer);
}

int
Socket::Write(const char* buffer, int bytes)
{
  if (kNetTypeInval == fd_ || NULL == buffer || bytes <= 0)
    return kNetTypeError;

  return wbuf_.Put(buffer, bytes);
}

int
Socket::DealWithAsyncRead(void)
{
  if (kNetTypeInval == fd_)
    return kNetTypeError;

  int read_bytes = 0;
  int ret;
  char* free_buffer = rbuf_.free_buffer();
  int   free_length = rbuf_.free_length();
  while (true) {
    if (0 == free_length) {
      rbuf_.Regrow();
      free_buffer = rbuf_.free_buffer();
      free_length = rbuf_.free_length();
    }

    ret = recv(fd_, free_buffer, free_length, 0);
    if (ret > 0) {
      rbuf_.Increment(ret);
      read_bytes += ret;
      if (ret < free_length)
        break;
    }
    else if (0 == ret) {
      if (read_bytes > 0)
        break;
      else
        return ret;
    }
    else {
      return ret;
    }
  }

  return read_bytes;
}

int
Socket::DealWithAsyncWrite(void)
{
  if (kNetTypeInval == fd_)
    return kNetTypeError;

  int write_bytes = 0;
  while (true) {
    int length = wbuf_.length();
    if (length <= 0)
      return 0;

    const char* buffer = wbuf_.buffer();
    int ret = send(fd_, buffer, length, 0);

    if (ret > 0) {
      wbuf_.Decrement(ret);
      write_bytes += ret;
      if (ret < length)
        break;
    }
    else if (0 == ret) {
      if (write_bytes > 0)
        break;
      else
        return ret;
    }
    else {
      return ret;
    }
  }

  return write_bytes;
}

bool
Socket::CheckValidMessageInReadBuffer(void)
{
  return true;
}
<commit_msg>fixed bug of socket module<commit_after>//! Copyright (c) 2013 ASMlover. 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 ofconditions 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 materialsprovided with the
//!    distribution.
//!
//! 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 HOLDER 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.
#if defined(_WINDOWS_) || defined(_MSC_VER)
# ifndef _WINDOWS_
#   include <winsock2.h>
# endif
  typedef int socklen_t;
#elif defined(__linux__)
# include <sys/types.h>
# include <sys/socket.h>
# include <arpa/inet.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <unistd.h>
# include <fcntl.h>
#endif
#include "net.h"
#include "address.h"
#include "socket.h"

Socket::Socket(void)
  : fd_(kNetTypeInval)
{
}

Socket::~Socket(void)
{
  Close();
}

bool
Socket::SetOption(int level, int optname, int optval)
{
  if (kNetTypeInval == fd_)
    return false;

  if (kNetTypeError == setsockopt(fd_, level,
        optname,
#if defined(_WINDOWS_) || defined(_MSC_VER)
        (const char*)&optval,
#elif defined(__linux__)
        (const void*)&optval,
#endif
        sizeof(optval)))
    return false;

  return true;
}

bool
Socket::SetNonBlock(void)
{
  if (kNetTypeInval == fd_)
    return false;

#if defined(_WINDOWS_) || defined(_MSC_VER)
  u_long mode = 1;
  if (kNetTypeError == ioctlsocket(fd_, FIONBIO, &mode))
    return false;
#elif defined(__linux__)
  int opt = fcntl(fd_, F_GETFL);
  if (kNetTypeError == fd_)
    return false;
  if (kNetTypeError == fcntl(fd_, F_SETFL, opt | O_NONBLOCK))
    return false;
#endif

  return true;
}

bool
Socket::SetTcpNoDelay(bool nodelay)
{
  return SetOption(IPPROTO_TCP, TCP_NODELAY, (nodelay ? 1 : 0));
}

bool
Socket::SetReuseAddr(bool reuse)
{
  return SetOption(SOL_SOCKET, SO_REUSEADDR, (reuse ? 1 : 0));
}

bool
Socket::SetKeepAlive(bool keep)
{
  return SetOption(SOL_SOCKET, SO_KEEPALIVE, (keep ? 1 : 0));
}

bool
Socket::SetReadBuffer(int bytes)
{
  return SetOption(SOL_SOCKET, SO_RCVBUF, bytes);
}

bool
Socket::SetWriteBuffer(int bytes)
{
  return SetOption(SOL_SOCKET, SO_SNDBUF, bytes);
}

bool
Socket::SetSelfReadBuffer(int bytes)
{
  return rbuf_.Init(bytes);
}

bool
Socket::SetSelfWriteBuffer(int bytes)
{
  return wbuf_.Init(bytes);
}

bool
Socket::Open(void)
{
  fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (kNetTypeInval == fd_)
    return false;

  return true;
}

void
Socket::Close(void)
{
  if (kNetTypeInval != fd_) {
#if defined(_WINDOWS_) || defined(_MSC_VER)
    shutdown(fd_, SD_BOTH);
    closesocket(fd_);
#elif defined(__linux__)
    shutdown(fd_, SHUT_RDWR);
    close(fd_);
#endif
    fd_ = kNetTypeInval;
  }
}

bool
Socket::Bind(const char* ip, unsigned short port)
{
  if (kNetTypeInval == fd_)
    return false;

  struct sockaddr_in host_addr;
  host_addr.sin_addr.s_addr =
    (NULL == ip ? htonl(INADDR_ANY) : inet_addr(ip));
  host_addr.sin_family      = AF_INET;
  host_addr.sin_port        = htons(port);

  if (kNetTypeError == bind(fd_,
        (struct sockaddr*)&host_addr, sizeof(host_addr)))
    return false;

  return true;
}

bool
Socket::Listen(void)
{
  if (kNetTypeInval == fd_)
    return false;

  if (kNetTypeError == listen(fd_, SOMAXCONN))
    return false;

  return true;
}

bool
Socket::Accept(Socket* s, Address* addr)
{
  if (kNetTypeInval == fd_ || NULL == s)
    return false;

  struct sockaddr_in remote_addr;
  socklen_t addrlen = sizeof(remote_addr);
  int fd = accept(fd_, (struct sockaddr*)&remote_addr, &addrlen);
  if (kNetTypeInval == fd)
    return false;

  s->Attach(fd);
  if (NULL != addr)
    addr->Attach(&remote_addr);

  return true;
}

bool
Socket::Connect(const char* ip, unsigned short port)
{
  if (kNetTypeInval == fd_)
    return false;

  if (NULL == ip)
    ip = "127.0.0.1";
  struct sockaddr_in remote_addr;
  remote_addr.sin_addr.s_addr = inet_addr(ip);
  remote_addr.sin_family      = AF_INET;
  remote_addr.sin_port        = htons(port);
  if (kNetTypeError == connect(fd_,
        (struct sockaddr*)&remote_addr, sizeof(remote_addr)))
    return false;

  return true;
}

int
Socket::ReadBlock(int bytes, char* buffer)
{
  if (kNetTypeInval == fd_ || bytes <= 0 || NULL == buffer)
    return kNetTypeError;

  int ret = recv(fd_, buffer, bytes, 0);

  return ret;
}

int
Socket::WriteBlock(const char* buffer, int bytes)
{
  if (kNetTypeInval == fd_ || NULL == buffer || bytes <= 0)
    return kNetTypeError;

  int write_bytes = 0;
  int ret;
  while (write_bytes < bytes) {
    ret = send(fd_, buffer + write_bytes, bytes - write_bytes, 0);
    if (kNetTypeError == ret)
      return ret;

    write_bytes += ret;
  }

  return write_bytes;
}

int
Socket::Read(int bytes, char* buffer)
{
  if (kNetTypeInval == fd_ || bytes <= 0 || NULL == buffer)
    return kNetTypeError;

  return rbuf_.Get(bytes, buffer);
}

int
Socket::Write(const char* buffer, int bytes)
{
  if (kNetTypeInval == fd_ || NULL == buffer || bytes <= 0)
    return kNetTypeError;

  return wbuf_.Put(buffer, bytes);
}

int
Socket::DealWithAsyncRead(void)
{
  if (kNetTypeInval == fd_)
    return kNetTypeError;

  int read_bytes = 0;
  int ret;
  char* free_buffer = rbuf_.free_buffer();
  int   free_length = rbuf_.free_length();
  while (true) {
    if (0 == free_length) {
      rbuf_.Regrow();
      free_buffer = rbuf_.free_buffer();
      free_length = rbuf_.free_length();
    }

    ret = recv(fd_, free_buffer, free_length, 0);
    if (ret > 0) {
      rbuf_.Increment(ret);
      read_bytes += ret;
      if (ret < free_length)
        break;
    }
    else if (0 == ret) {
      if (read_bytes > 0)
        break;
      else
        return ret;
    }
    else {
      return ret;
    }
  }

  return read_bytes;
}

int
Socket::DealWithAsyncWrite(void)
{
  if (kNetTypeInval == fd_)
    return kNetTypeError;

  int write_bytes = 0;
  while (true) {
    int length = wbuf_.length();
    if (length <= 0)
      return 0;

    const char* buffer = wbuf_.buffer();
    int ret = send(fd_, buffer, length, 0);

    if (ret > 0) {
      wbuf_.Decrement(ret);
      write_bytes += ret;
      if (ret < length)
        break;
    }
    else if (0 == ret) {
      if (write_bytes > 0)
        break;
      else
        return ret;
    }
    else {
      return ret;
    }
  }

  return write_bytes;
}

bool
Socket::CheckValidMessageInReadBuffer(void)
{
  return true;
}
<|endoftext|>


<commit_before>#include "aerial_autonomy/controllers/qrotor_backstepping_controller.h"
#include "aerial_autonomy/tests/test_utils.h"
#include "qrotor_backstepping_controller_config.pb.h"

#include <chrono>
#include <cmath>
#include <gcop/hrotor.h>
#include <tf_conversions/tf_eigen.h>

#include <gtest/gtest.h>

using namespace gcop;

class QrotorBacksteppingControllerTests : public ::testing::Test {
public:
  QrotorBacksteppingControllerTests() : sys() {
    config_.set_mass(sys.m);
    config_.set_jxx(sys.J(0));
    config_.set_jyy(sys.J(1));
    config_.set_jzz(sys.J(2));
    config_.set_k2(0.1);
    config_.set_k1(0.1);
    config_.set_kp_xy(0.4);
    config_.set_kp_z(0.4);
    config_.set_kd_xy(0.2);
    config_.set_kd_z(0.2);
    auto vel_tolerance = config_.mutable_goal_velocity_tolerance();
    vel_tolerance->set_vx(0.05);
    vel_tolerance->set_vy(0.05);
    vel_tolerance->set_vz(0.05);

    auto pos_tolerance = config_.mutable_goal_position_tolerance();
    pos_tolerance->set_x(0.05);
    pos_tolerance->set_y(0.05);
    pos_tolerance->set_z(0.05);
  }

  void testConvergence(ReferenceTrajectory<ParticleState, Snap> ref, QrotorBacksteppingState x0) {
    QrotorBacksteppingController controller(config_);

    auto sensor_data = std::make_pair(0.0, x0);
    double &time = std::get<0>(sensor_data);
    auto &qrotor_state = std::get<1>(sensor_data);
    qrotor_state.thrust = config_.mass() * config_.acc_gravity();

    std::chrono::duration<double> dt = std::chrono::milliseconds(20);

    controller.setGoal(ref);

    auto convergence = [&]() {
      QrotorBacksteppingControl controls;
      controller.run(sensor_data, controls);

      qrotor_state.thrust_dot += controls.thrust_ddot * dt.count();
      qrotor_state.thrust += qrotor_state.thrust_dot * dt.count();

      Body3dState xa;
      tf::matrixTFToEigen(qrotor_state.pose.getBasis(), xa.R);
      tf::vectorTFToEigen(qrotor_state.pose.getOrigin(), xa.p);
      tf::vectorTFToEigen(qrotor_state.w, xa.w);
      tf::vectorTFToEigen(qrotor_state.v, xa.v);

      Body3dState xb;
      Eigen::Vector4d controls_eig(controls.torque.x(), controls.torque.y(),
                                   controls.torque.z(), qrotor_state.thrust);
      sys.Step(xb, time, xa, controls_eig, dt.count());
      time += dt.count();

      tf::matrixEigenToTF(xb.R, qrotor_state.pose.getBasis());
      tf::vectorEigenToTF(xb.p, qrotor_state.pose.getOrigin());
      tf::vectorEigenToTF(xb.w, qrotor_state.w);
      tf::vectorEigenToTF(xb.v, qrotor_state.v);

      return bool(controller.isConverged(sensor_data));
    };

    ASSERT_TRUE(test_utils::waitUntilTrue()(
        convergence, std::chrono::seconds(5), std::chrono::milliseconds(0)));
  }

protected:
  Hrotor sys;
  QrotorBacksteppingControllerConfig config_;
};

TEST_F(QrotorBacksteppingControllerTests, Constructor) {
  ASSERT_NO_THROW(new QrotorBacksteppingController(config_));
}

TEST_F(QrotorBacksteppingControllerTests, Convergence) {
  ReferenceTrajectory<ParticleState, Snap> ref;
  for(double t = 0; t < 200; t+= 0.05) {
    ref.ts.push_back(t);
    ref.states.push_back(ParticleState());
    ref.controls.push_back(Snap());
  }

  QrotorBacksteppingState qrotor_state;
  qrotor_state.pose.setOrigin(tf::Vector3(3, -3, 1));
  testConvergence(ref, qrotor_state);

  // Non-zero linear velocity
  qrotor_state.v = tf::Vector3(1, 1, -1);
  testConvergence(ref, qrotor_state);

  // Non-zero angular velocity
  qrotor_state.w = tf::Vector3(M_PI / 6, -M_PI / 4, 0);
  testConvergence(ref, qrotor_state);
}

TEST_F(QrotorBacksteppingControllerTests, ConvergenceSpiral) {
  ReferenceTrajectory<ParticleState, Snap> ref;
  double w_xy = 2 * M_PI * 0.2;
  double w_z = 2 * M_PI * 0.2;
  for(double t = 0; t < 200; t+= 0.05) {
    ref.ts.push_back(t);
    ParticleState desired_state;
    desired_state.p.x = cos(w_xy * t);
    desired_state.p.y = sin(w_xy * t);
    desired_state.p.z = sin(w_z * t) + 3;
    desired_state.v.x = w_xy * -sin(w_xy * t);
    desired_state.v.y = w_xy * cos(w_xy * t);
    desired_state.v.z = w_z * cos(w_z * t);
    desired_state.a.x = std::pow(w_xy, 2) * -cos(w_xy * t);
    desired_state.a.y = std::pow(w_xy, 2) * -sin(w_xy * t);
    desired_state.a.z = std::pow(w_z, 2) * -sin(w_z * t);
    desired_state.j.x = std::pow(w_xy, 3) * sin(w_xy * t);
    desired_state.j.y = std::pow(w_xy, 3) * -cos(w_xy * t);
    desired_state.j.z = std::pow(w_z, 3) * -cos(w_z * t);

    Snap desired_control(std::pow(w_xy, 4) * cos(w_xy * t),
                         std::pow(w_xy, 4) * sin(w_xy * t),
                         std::pow(w_z, 4) * sin(w_z * t));

    ref.states.push_back(desired_state);
    ref.controls.push_back(desired_control);
  }

  QrotorBacksteppingState qrotor_state;
  testConvergence(ref, qrotor_state);

  // Non-zero linear velocity
  qrotor_state.v = tf::Vector3(1, 1, -1);
  testConvergence(ref, qrotor_state);

  // Non-zero angular velocity
  qrotor_state.w = tf::Vector3(M_PI / 6, -M_PI / 4, 0);
  testConvergence(ref, qrotor_state);
}

TEST_F(QrotorBacksteppingControllerTests, SmallThrust) {
  ReferenceTrajectory<ParticleState, Snap> ref;
  ref.ts.push_back(0);
  ref.states.push_back(ParticleState());
  ref.controls.push_back(Snap());
  QrotorBacksteppingController controller(config_);

  controller.setGoal(ref);

  auto sensor_data = std::make_pair(0.0, QrotorBacksteppingState());
  auto &qrotor_state = std::get<1>(sensor_data);
  qrotor_state.thrust = 0;
  qrotor_state.pose.setOrigin(tf::Vector3(3, 2, 1));

  QrotorBacksteppingControl controls;
  controller.run(sensor_data, controls);

  ASSERT_EQ(controls.torque.x(), 0);
  ASSERT_EQ(controls.torque.y(), 0);

  qrotor_state.thrust = config_.thrust_eps() + 1e-5;
  controller.run(sensor_data, controls);

  ASSERT_NE(controls.torque.x(), 0);
  ASSERT_NE(controls.torque.y(), 0);
}

// TODO Matt: add test for actual trajectory tracking once trajectory generation
// is implemented

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Remove todo<commit_after>#include "aerial_autonomy/controllers/qrotor_backstepping_controller.h"
#include "aerial_autonomy/tests/test_utils.h"
#include "qrotor_backstepping_controller_config.pb.h"

#include <chrono>
#include <cmath>
#include <gcop/hrotor.h>
#include <tf_conversions/tf_eigen.h>

#include <gtest/gtest.h>

using namespace gcop;

class QrotorBacksteppingControllerTests : public ::testing::Test {
public:
  QrotorBacksteppingControllerTests() : sys() {
    config_.set_mass(sys.m);
    config_.set_jxx(sys.J(0));
    config_.set_jyy(sys.J(1));
    config_.set_jzz(sys.J(2));
    config_.set_k2(0.1);
    config_.set_k1(0.1);
    config_.set_kp_xy(0.4);
    config_.set_kp_z(0.4);
    config_.set_kd_xy(0.2);
    config_.set_kd_z(0.2);
    auto vel_tolerance = config_.mutable_goal_velocity_tolerance();
    vel_tolerance->set_vx(0.05);
    vel_tolerance->set_vy(0.05);
    vel_tolerance->set_vz(0.05);

    auto pos_tolerance = config_.mutable_goal_position_tolerance();
    pos_tolerance->set_x(0.05);
    pos_tolerance->set_y(0.05);
    pos_tolerance->set_z(0.05);
  }

  void testConvergence(ReferenceTrajectory<ParticleState, Snap> ref, QrotorBacksteppingState x0) {
    QrotorBacksteppingController controller(config_);

    auto sensor_data = std::make_pair(0.0, x0);
    double &time = std::get<0>(sensor_data);
    auto &qrotor_state = std::get<1>(sensor_data);
    qrotor_state.thrust = config_.mass() * config_.acc_gravity();

    std::chrono::duration<double> dt = std::chrono::milliseconds(20);

    controller.setGoal(ref);

    auto convergence = [&]() {
      QrotorBacksteppingControl controls;
      controller.run(sensor_data, controls);

      qrotor_state.thrust_dot += controls.thrust_ddot * dt.count();
      qrotor_state.thrust += qrotor_state.thrust_dot * dt.count();

      Body3dState xa;
      tf::matrixTFToEigen(qrotor_state.pose.getBasis(), xa.R);
      tf::vectorTFToEigen(qrotor_state.pose.getOrigin(), xa.p);
      tf::vectorTFToEigen(qrotor_state.w, xa.w);
      tf::vectorTFToEigen(qrotor_state.v, xa.v);

      Body3dState xb;
      Eigen::Vector4d controls_eig(controls.torque.x(), controls.torque.y(),
                                   controls.torque.z(), qrotor_state.thrust);
      sys.Step(xb, time, xa, controls_eig, dt.count());
      time += dt.count();

      tf::matrixEigenToTF(xb.R, qrotor_state.pose.getBasis());
      tf::vectorEigenToTF(xb.p, qrotor_state.pose.getOrigin());
      tf::vectorEigenToTF(xb.w, qrotor_state.w);
      tf::vectorEigenToTF(xb.v, qrotor_state.v);

      return bool(controller.isConverged(sensor_data));
    };

    ASSERT_TRUE(test_utils::waitUntilTrue()(
        convergence, std::chrono::seconds(5), std::chrono::milliseconds(0)));
  }

protected:
  Hrotor sys;
  QrotorBacksteppingControllerConfig config_;
};

TEST_F(QrotorBacksteppingControllerTests, Constructor) {
  ASSERT_NO_THROW(new QrotorBacksteppingController(config_));
}

TEST_F(QrotorBacksteppingControllerTests, Convergence) {
  ReferenceTrajectory<ParticleState, Snap> ref;
  for(double t = 0; t < 200; t+= 0.05) {
    ref.ts.push_back(t);
    ref.states.push_back(ParticleState());
    ref.controls.push_back(Snap());
  }

  QrotorBacksteppingState qrotor_state;
  qrotor_state.pose.setOrigin(tf::Vector3(3, -3, 1));
  testConvergence(ref, qrotor_state);

  // Non-zero linear velocity
  qrotor_state.v = tf::Vector3(1, 1, -1);
  testConvergence(ref, qrotor_state);

  // Non-zero angular velocity
  qrotor_state.w = tf::Vector3(M_PI / 6, -M_PI / 4, 0);
  testConvergence(ref, qrotor_state);
}

TEST_F(QrotorBacksteppingControllerTests, ConvergenceSpiral) {
  ReferenceTrajectory<ParticleState, Snap> ref;
  double w_xy = 2 * M_PI * 0.2;
  double w_z = 2 * M_PI * 0.2;
  for(double t = 0; t < 200; t+= 0.05) {
    ref.ts.push_back(t);
    ParticleState desired_state;
    desired_state.p.x = cos(w_xy * t);
    desired_state.p.y = sin(w_xy * t);
    desired_state.p.z = sin(w_z * t) + 3;
    desired_state.v.x = w_xy * -sin(w_xy * t);
    desired_state.v.y = w_xy * cos(w_xy * t);
    desired_state.v.z = w_z * cos(w_z * t);
    desired_state.a.x = std::pow(w_xy, 2) * -cos(w_xy * t);
    desired_state.a.y = std::pow(w_xy, 2) * -sin(w_xy * t);
    desired_state.a.z = std::pow(w_z, 2) * -sin(w_z * t);
    desired_state.j.x = std::pow(w_xy, 3) * sin(w_xy * t);
    desired_state.j.y = std::pow(w_xy, 3) * -cos(w_xy * t);
    desired_state.j.z = std::pow(w_z, 3) * -cos(w_z * t);

    Snap desired_control(std::pow(w_xy, 4) * cos(w_xy * t),
                         std::pow(w_xy, 4) * sin(w_xy * t),
                         std::pow(w_z, 4) * sin(w_z * t));

    ref.states.push_back(desired_state);
    ref.controls.push_back(desired_control);
  }

  QrotorBacksteppingState qrotor_state;
  testConvergence(ref, qrotor_state);

  // Non-zero linear velocity
  qrotor_state.v = tf::Vector3(1, 1, -1);
  testConvergence(ref, qrotor_state);

  // Non-zero angular velocity
  qrotor_state.w = tf::Vector3(M_PI / 6, -M_PI / 4, 0);
  testConvergence(ref, qrotor_state);
}

TEST_F(QrotorBacksteppingControllerTests, SmallThrust) {
  ReferenceTrajectory<ParticleState, Snap> ref;
  ref.ts.push_back(0);
  ref.states.push_back(ParticleState());
  ref.controls.push_back(Snap());
  QrotorBacksteppingController controller(config_);

  controller.setGoal(ref);

  auto sensor_data = std::make_pair(0.0, QrotorBacksteppingState());
  auto &qrotor_state = std::get<1>(sensor_data);
  qrotor_state.thrust = 0;
  qrotor_state.pose.setOrigin(tf::Vector3(3, 2, 1));

  QrotorBacksteppingControl controls;
  controller.run(sensor_data, controls);

  ASSERT_EQ(controls.torque.x(), 0);
  ASSERT_EQ(controls.torque.y(), 0);

  qrotor_state.thrust = config_.thrust_eps() + 1e-5;
  controller.run(sensor_data, controls);

  ASSERT_NE(controls.torque.x(), 0);
  ASSERT_NE(controls.torque.y(), 0);
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>