<commit_before>#include "ardrone/ardrone.h"

// --------------------------------------------------------------------------
// main(Number of arguments, Argument values)
// Description  : This is the entry point of the program.
// Return value : SUCCESS:0  ERROR:-1
// --------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    // AR.Drone class
    ARDrone ardrone;

    // Initialize
    if (!ardrone.open()) {
        std::cout << "Failed to initialize." << std::endl;
        return -1;
    }

    // Thresholds
    int minH = 0, maxH = 255;
    int minS = 0, maxS = 255;
    int minV = 0, maxV = 255;

    // XML save data
    std::string filename("thresholds.xml");
    cv::FileStorage fs(filename, cv::FileStorage::READ);

    // If there is a save file then read it
    if (fs.isOpened()) {
        maxH = fs["H_MAX"];
        minH = fs["H_MIN"];
        maxS = fs["S_MAX"];
        minS = fs["S_MIN"];
        maxV = fs["V_MAX"];
        minV = fs["V_MIN"];
        fs.release();
    }

    // Create a window
    cv::namedWindow("binalized");
    cv::createTrackbar("H max", "binalized", &maxH, 255);
    cv::createTrackbar("H min", "binalized", &minH, 255);
    cv::createTrackbar("S max", "binalized", &maxS, 255);
    cv::createTrackbar("S min", "binalized", &minS, 255);
    cv::createTrackbar("V max", "binalized", &maxV, 255);
    cv::createTrackbar("V min", "binalized", &minV, 255);
    cv::resizeWindow("binalized", 0, 0);

    // Kalman filter
    cv::KalmanFilter kalman(4, 2, 0);

    // Sampling time [s]
    const double dt = 1.0;

    // Transition matrix (x, y, vx, vy)
    cv::Mat1f A(4, 4);
    A << 1.0, 0.0,  dt, 0.0,
         0.0, 1.0, 0.0,  dt,
         0.0, 0.0, 1.0, 0.0,
         0.0, 0.0, 0.0, 1.0;
    kalman.transitionMatrix = A;

    // Measurement matrix (x, y)
    cv::Mat1f H(2, 4);
    H << 1, 0, 0, 0,
         0, 1, 0, 0;
    kalman.measurementMatrix = H;

    // Process noise covairance (x, y, vx, vy)
    cv::Mat1f Q(4, 4);
    Q << 1e-5,  0.0,  0.0,  0.0,
          0.0, 1e-5,  0.0,  0.0,
          0.0,  0.0, 1e-5,  0.0,
          0.0,  0.0,  0.0, 1e-5;
    kalman.processNoiseCov = Q;

    // Measurement noise covariance (x, y)
    cv::Mat1f R(2, 2);
    R << 1e-1,  0.0,
          0.0, 1e-1;
    kalman.measurementNoiseCov = R;

    // Main loop
    while (1) {
        // Key input
        int key = cv::waitKey(33);
        if (key == 0x1b) break;

        // Get an image
        cv::Mat image = ardrone.getImage();

        // HSV image
        cv::Mat hsv;
        cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV_FULL);

        // Binalize
        cv::Mat binalized;
        cv::Scalar lower(minH, minS, minV);
        cv::Scalar upper(maxH, maxS, maxV);
        cv::inRange(hsv, lower, upper, binalized);

        // Show result
        cv::imshow("binalized", binalized);

        // De-noising
        cv::Mat kernel = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
        cv::morphologyEx(binalized, binalized, cv::MORPH_CLOSE, kernel);
        //cv::imshow("morphologyEx", binalized);

        // Detect contours
        std::vector<std::vector<cv::Point>> contours;
        cv::findContours(binalized.clone(), contours, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);

        // Find largest contour
        int contour_index = -1;
        double max_area = 0.0;
        for (size_t i = 0; i < contours.size(); i++) {
            double area = fabs(cv::contourArea(contours[i]));
            if (area > max_area) {
                contour_index = i;
                max_area = area;
            }
        }

        // Object detected
        if (contour_index >= 0) {
            // Moments
            cv::Moments moments = cv::moments(contours[contour_index], true);
            double marker_y = (int)(moments.m01 / moments.m00);
            double marker_x = (int)(moments.m10 / moments.m00);

            // Measurements
            cv::Mat measurement = (cv::Mat1f(2, 1) << marker_x, marker_y);

            // Correction
            cv::Mat estimated = kalman.correct(measurement);

            // Show result
            cv::Rect rect = cv::boundingRect(contours[contour_index]);
            cv::rectangle(image, rect, cv::Scalar(0, 255, 0));
        }

        // Prediction
        cv::Mat1f prediction = kalman.predict();
        int radius = 1e+3 * kalman.errorCovPre.at<float>(0, 0);

        // Show predicted position
        cv::circle(image, cv::Point(prediction(0, 0), prediction(0, 1)), radius, cv::Scalar(0, 255, 0), 2);

        // Display the image
        cv::imshow("camera", image);
    }

    // Save thresholds
    fs.open(filename, cv::FileStorage::WRITE);
    if (fs.isOpened()) {
        cv::write(fs, "H_MAX", maxH);
        cv::write(fs, "H_MIN", minH);
        cv::write(fs, "S_MAX", maxS);
        cv::write(fs, "S_MIN", minS);
        cv::write(fs, "V_MAX", maxV);
        cv::write(fs, "V_MIN", minV);
        fs.release();
    }

    // See you
    ardrone.close();

    return 0;
}<commit_msg>Drone loiters, keeping the camera pointed at the tracked object.<commit_after>#include "ardrone/ardrone.h"

// --------------------------------------------------------------------------
// main(Number of arguments, Argument values)
// Description  : This is the entry point of the program.
// Return value : SUCCESS:0  ERROR:-1
// --------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    // AR.Drone class
    ARDrone ardrone;

    // Initialize
    if (!ardrone.open()) {
        std::cout << "Failed to initialize." << std::endl;
        return -1;
    }

    // Thresholds
    int minH = 0, maxH = 255;
    int minS = 0, maxS = 255;
    int minV = 0, maxV = 255;

    // XML save data
    std::string filename("thresholds.xml");
    cv::FileStorage fs(filename, cv::FileStorage::READ);

    // If there is a save file then read it
    if (fs.isOpened()) {
        maxH = fs["H_MAX"];
        minH = fs["H_MIN"];
        maxS = fs["S_MAX"];
        minS = fs["S_MIN"];
        maxV = fs["V_MAX"];
        minV = fs["V_MIN"];
        fs.release();
    }

    // Create a window
    cv::namedWindow("binalized");
    cv::createTrackbar("H max", "binalized", &maxH, 255);
    cv::createTrackbar("H min", "binalized", &minH, 255);
    cv::createTrackbar("S max", "binalized", &maxS, 255);
    cv::createTrackbar("S min", "binalized", &minS, 255);
    cv::createTrackbar("V max", "binalized", &maxV, 255);
    cv::createTrackbar("V min", "binalized", &minV, 255);
    cv::resizeWindow("binalized", 0, 0);

    // Kalman filter
    cv::KalmanFilter kalman(4, 2, 0);

    // Sampling time [s]
    const double dt = 1.0;

    // Transition matrix (x, y, vx, vy)
    cv::Mat1f A(4, 4);
    A << 1.0, 0.0,  dt, 0.0,
         0.0, 1.0, 0.0,  dt,
         0.0, 0.0, 1.0, 0.0,
         0.0, 0.0, 0.0, 1.0;
    kalman.transitionMatrix = A;

    // Measurement matrix (x, y)
    cv::Mat1f H(2, 4);
    H << 1, 0, 0, 0,
         0, 1, 0, 0;
    kalman.measurementMatrix = H;

    // Process noise covairance (x, y, vx, vy)
    cv::Mat1f Q(4, 4);
    Q << 1e-5,  0.0,  0.0,  0.0,
          0.0, 1e-5,  0.0,  0.0,
          0.0,  0.0, 1e-5,  0.0,
          0.0,  0.0,  0.0, 1e-5;
    kalman.processNoiseCov = Q;

    // Measurement noise covariance (x, y)
    cv::Mat1f R(2, 2);
    R << 1e-1,  0.0,
          0.0, 1e-1;
    kalman.measurementNoiseCov = R;

    // Main loop
    while (1) {
        // Key input
        int key = cv::waitKey(33);
        if (key == 0x1b) break;

        // Get an image
        cv::Mat image = ardrone.getImage();

        // HSV image
        cv::Mat hsv;
        cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV_FULL);

        // Binalize
        cv::Mat binalized;
        cv::Scalar lower(minH, minS, minV);
        cv::Scalar upper(maxH, maxS, maxV);
        cv::inRange(hsv, lower, upper, binalized);

        // Show result
        cv::imshow("binalized", binalized);

        // De-noising
        cv::Mat kernel = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
        cv::morphologyEx(binalized, binalized, cv::MORPH_CLOSE, kernel);
        //cv::imshow("morphologyEx", binalized);

        // Detect contours
        std::vector<std::vector<cv::Point>> contours;
        cv::findContours(binalized.clone(), contours, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);

        // Find largest contour
        int contour_index = -1;
        double max_area = 0.0;
        for (size_t i = 0; i < contours.size(); i++) {
            double area = fabs(cv::contourArea(contours[i]));
            if (area > max_area) {
                contour_index = i;
                max_area = area;
            }
        }

        // Object detected
        if (contour_index >= 0) {
            // Moments
            cv::Moments moments = cv::moments(contours[contour_index], true);
            double marker_y = (int)(moments.m01 / moments.m00);
            double marker_x = (int)(moments.m10 / moments.m00);

            // Measurements
            cv::Mat measurement = (cv::Mat1f(2, 1) << marker_x, marker_y);

            // Correction
            cv::Mat estimated = kalman.correct(measurement);

            // Show result
            cv::Rect rect = cv::boundingRect(contours[contour_index]);
            cv::rectangle(image, rect, cv::Scalar(0, 255, 0));
        }

        // Prediction
        cv::Mat1f prediction = kalman.predict();
        int radius = 1e+3 * kalman.errorCovPre.at<float>(0, 0);

        // Show predicted position
        cv::circle(image, cv::Point(prediction(0, 0), prediction(0, 1)), radius, cv::Scalar(0, 255, 0), 2);

		// Calculate object heading fraction
		float heading = ((image.cols/2)-prediction(0, 0))/(image.cols/2);
		printf("prediction->data.fl[0]  = %3.2f\n", heading);

		// Control drone
		double vx = 0.0, vy = 0.0, vz = 0.0, vr = 0.0;
        if (key == 0x260000) vx =  1.0;
        if (key == 0x280000) vx = -1.0;
        if (key == 0x250000) vr =  1.0;
        if (key == 0x270000) vr = -1.0;
        if (key == 'q')      vz =  1.0;
        if (key == 'a')      vz = -1.0;
		if(key == -1)
		{
			//vx=0.7;
			vr = heading*2;
		}
        ardrone.move3D(vx, vy, vz, vr);

		// Take off / Landing
        if (key == ' ') {
            if (ardrone.onGround())
			{
				ardrone.takeoff();
			}
            else
			{
				ardrone.landing();
			}
        }

        // Display the image
        cv::imshow("camera", image);

    }

    // Save thresholds
    fs.open(filename, cv::FileStorage::WRITE);
    if (fs.isOpened()) {
        cv::write(fs, "H_MAX", maxH);
        cv::write(fs, "H_MIN", minH);
        cv::write(fs, "S_MAX", maxS);
        cv::write(fs, "S_MIN", minS);
        cv::write(fs, "V_MAX", maxV);
        cv::write(fs, "V_MIN", minV);
        fs.release();
    }

    // See you
    ardrone.close();

    return 0;
}<|endoftext|>


<commit_before>// must be the first include in all compile units
#ifndef SASS_SASS_H
#define SASS_SASS_H

// undefine extensions macro to tell sys includes
// that we do not want any macros to be exported
// mainly fixes an issue on SmartOS (SEC macro)
#undef __EXTENSIONS__

#ifdef _MSC_VER
#pragma warning(disable : 4005)
#endif

// aplies to MSVC and MinGW
#ifdef _WIN32
// we do not want the ERROR macro
# define NOGDI
// we do not want the min/max macro
# define NOMINMAX
#endif

// should we be case insensitive
// when dealing with files or paths
#ifndef FS_CASE_SENSITIVE
# ifdef _WIN32
#  define FS_CASE_SENSITIVE 0
# else
#  define FS_CASE_SENSITIVE 1
# endif
#endif

// path separation char
#ifndef PATH_SEP
# ifdef _WIN32
#  define PATH_SEP ';'
# else
#  define PATH_SEP ':'
# endif
#endif

#endif
<commit_msg>Prevent pseudo modifiers from being injected (unity build)<commit_after>// must be the first include in all compile units
#ifndef SASS_SASS_H
#define SASS_SASS_H

// undefine extensions macro to tell sys includes
// that we do not want any macros to be exported
// mainly fixes an issue on SmartOS (SEC macro)
#undef __EXTENSIONS__

#ifdef _MSC_VER
#pragma warning(disable : 4005)
#endif

// aplies to MSVC and MinGW
#ifdef _WIN32
// we do not want the ERROR macro
# define NOGDI
// we do not want the min/max macro
# define NOMINMAX
// we do not want the IN/OUT macro
# define _NO_W32_PSEUDO_MODIFIERS
#endif

// should we be case insensitive
// when dealing with files or paths
#ifndef FS_CASE_SENSITIVE
# ifdef _WIN32
#  define FS_CASE_SENSITIVE 0
# else
#  define FS_CASE_SENSITIVE 1
# endif
#endif

// path separation char
#ifndef PATH_SEP
# ifdef _WIN32
#  define PATH_SEP ';'
# else
#  define PATH_SEP ':'
# endif
#endif

#endif
<|endoftext|>


<commit_before>// This file was developed by Thomas Müller <thomas94@gmx.net>.
// It is published under the BSD 3-Clause License within the LICENSE file.

#include <tev/Image.h>
#include <tev/ImageViewer.h>
#include <tev/Ipc.h>
#include <tev/ThreadPool.h>

#include <args.hxx>
#include <ImfThreading.h>

#include <utf8.h>

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

using namespace args;
using namespace filesystem;
using namespace std;

TEV_NAMESPACE_BEGIN

int mainFunc(const vector<string>& arguments) {
    ArgumentParser parser{
        "tev — The EXR Viewer\n"
        "version " TEV_VERSION "\n"
        "Inspection tool for images with high dynamic range",
        "tev was developed by Thomas Müller <thomas94@gmx.net>. "
        "Its source code is available under the BSD 3-Clause License at https://tom94.net",
    };

    ValueFlag<float> exposureFlag{
        parser,
        "EXPOSURE",
        "Scales the brightness of an image prior to tonemapping by 2^EXPOSURE. Default is 0.",
        {'e', "exposure"},
    };

    ValueFlag<string> filterFlag{
        parser,
        "FILTER",
        "Filter visible images and groups according to a supplied string. "
        "The string must have the format 'image:group'. "
        "Only images whose name contains 'image' and groups whose name contains 'group' will be visible.",
        {'f', "filter"},
    };

    ValueFlag<float> gammaFlag{
        parser,
        "GAMMA",
        "The exponent used when TONEMAP is 'Gamma'. Default is 2.2.",
        {'g', "gamma"},
    };

    HelpFlag helpFlag{
        parser,
        "HELP",
        "Display this help menu.",
        {'h', "help"},
    };

    ValueFlag<string> hostnameFlag{
        parser,
        "HOSTNAME",
        "The hostname to listen on for IPC communication. "
        "tev can have a distinct primary instance for each unique hostname in use. "
        "Default is 127.0.0.1:14158",
        {"host", "hostname"},
    };

    ValueFlag<bool> maximizeFlag{
        parser,
        "MAXIMIZE",
        "Maximize the window on startup. "
        "If no images were supplied via the command line, then the default is FALSE. "
        "Otherwise, the default is TRUE.",
        {"max", "maximize"},
    };

    ValueFlag<string> metricFlag{
        parser,
        "METRIC",
        "The metric to use when comparing two images. "
        "The available metrics are:\n"
        "E   - Error\n"
        "AE  - Absolute Error\n"
        "SE  - Squared Error\n"
        "RAE - Relative Absolute Error\n"
        "RSE - Relative Squared Error\n"
        "Default is E.",
        {'m', "metric"},
    };

    Flag newWindowFlag{
        parser,
        "NEW WINDOW",
        "Open a new window of tev, even if one exists already.",
        {'n', "new"},
    };

    ValueFlag<float> offsetFlag{
        parser,
        "OFFSET",
        "Add an absolute offset to the image after EXPOSURE has been applied. Default is 0.",
        {'o', "offset"},
    };

    ValueFlag<string> tonemapFlag{
        parser,
        "TONEMAP",
        "The tonemapping algorithm to use. "
        "The available tonemaps are:\n"
        "sRGB   - sRGB\n"
        "Gamma  - Gamma curve\n"
        "FC     - False Color\n"
        "PN     - Positive=Green, Negative=Red\n"
        "Default is sRGB.",
        {'t', "tonemap"},
    };

    Flag versionFlag{
        parser,
        "VERSION",
        "Display the version of tev.",
        {'v', "version"},
    };

    PositionalList<string> imageFiles{
        parser,
        "images",
        "The image files to be opened by tev. "
        "If an argument starting with a ':' is encountered, "
        "then this argument is not treated as an image file "
        "but as a comma-separated channel selector. Until the next channel "
        "selector is encountered only channels containing "
        "elements from the current selector will be loaded. This is "
        "especially useful for selectively loading a specific "
        "part of a multi-part EXR file.",
    };

    // Parse command line arguments and react to parsing
    // errors using exceptions.
    try {
        TEV_ASSERT(arguments.size() > 0, "Number of arguments must be bigger than 0.");

        parser.Prog(arguments.front());
        parser.ParseArgs(begin(arguments) + 1, end(arguments));
    } catch (const Help&) {
        cout << parser;
        return 0;
    } catch (const ParseError& e) {
        cerr << e.what() << endl;
        cerr << parser;
        return -1;
    } catch (const ValidationError& e) {
        cerr << e.what() << endl;
        cerr << parser;
        return -2;
    }

    if (versionFlag) {
        tlog::none() << "tev — The EXR Viewer\nversion " TEV_VERSION;
        return 0;
    }

    const string hostname = hostnameFlag ? get(hostnameFlag) : "127.0.0.1:14158";
    auto ipc = make_shared<Ipc>(hostname);

    // If we're not the primary instance and did not request to open a new window,
    // simply send the to-be-opened images to the primary instance.
    if (!ipc->isPrimaryInstance() && !newWindowFlag) {
        string channelSelector;
        for (auto imageFile : get(imageFiles)) {
            if (!imageFile.empty() && imageFile[0] == ':') {
                channelSelector = imageFile.substr(1);
                continue;
            }

            try {
                IpcPacket packet;
                packet.setOpenImage(tfm::format("%s:%s", path{imageFile}.make_absolute(), channelSelector), true);
                ipc->sendToPrimaryInstance(packet);
            } catch (runtime_error e) {
                tlog::error() << tfm::format("Invalid file '%s': %s", imageFile, e.what());
            }
        }

        return 0;
    }

    Imf::setGlobalThreadCount(thread::hardware_concurrency());

    tlog::info() << "Loading window...";

    shared_ptr<BackgroundImagesLoader> imagesLoader = make_shared<BackgroundImagesLoader>();

    atomic<bool> shallShutdown{false};

    // Spawn a background thread that opens images passed via stdin.
    // To allow whitespace characters in filenames, we use the convention that
    // paths in stdin must be separated by newlines.
    thread stdinThread{[&]() {
        string channelSelector;
        while (!shallShutdown) {
            for (string line; getline(cin, line);) {
                string imageFile = tev::ensureUtf8(line);

                if (imageFile.empty()) {
                    continue;
                }

                if (imageFile[0] == ':') {
                    channelSelector = imageFile.substr(1);
                    continue;
                }

                imagesLoader->enqueue(imageFile, channelSelector, false);
            }

            this_thread::sleep_for(chrono::milliseconds{100});
        }
    }};

    // It is unfortunately not easily possible to poll/timeout on cin in a portable manner,
    // so instead we resort to simply detaching this thread, causing it to be forcefully
    // terminated as the main thread terminates.
    stdinThread.detach();

    unique_ptr<ImageViewer> imageViewer;

    // Spawn another background thread, this one dealing with images passed to us
    // via inter-process communication (IPC). This happens when
    // a user starts another instance of tev while one is already running. Note, that this
    // behavior can be overridden by the -n flag, so not _all_ secondary instances send their
    // paths to the primary instance.
    thread ipcThread;
    if (ipc->isPrimaryInstance()) {
        ipcThread = thread{[&]() {
            while (!shallShutdown) {
                while (ipc->receiveFromSecondaryInstance([&](const IpcPacket& packet) {
                    try {
                        switch (packet.type()) {
                            case IpcPacket::OpenImage: {
                                auto info = packet.interpretAsOpenImage();
                                string imageString = ensureUtf8(info.imagePath);
                                size_t colonPos = min(imageString.length() - 1, imageString.find_last_of(":"));
                                imagesLoader->enqueue(imageString.substr(0, colonPos), imageString.substr(colonPos + 1), info.grabFocus);
                                break;
                            }

                            case IpcPacket::ReloadImage: {
                                while (!imageViewer) { }
                                auto info = packet.interpretAsReloadImage();
                                imageViewer->scheduleToUiThread([&,info] {
                                    string imageString = ensureUtf8(info.imagePath);
                                    imageViewer->reloadImage(imageString, info.grabFocus);
                                });
                                break;
                            }

                            case IpcPacket::CloseImage: {
                                while (!imageViewer) { }
                                auto info = packet.interpretAsCloseImage();
                                imageViewer->scheduleToUiThread([&,info] {
                                    string imageString = ensureUtf8(info.imagePath);
                                    imageViewer->removeImage(imageString);
                                });
                                break;
                            }

                            case IpcPacket::UpdateImage: {
                                while (!imageViewer) { }
                                auto info = packet.interpretAsUpdateImage();
                                imageViewer->scheduleToUiThread([&,info] {
                                    string imageString = ensureUtf8(info.imagePath);
                                    imageViewer->updateImage(imageString, info.grabFocus, info.channel, info.x, info.y, info.width, info.height, info.imageData);
                                });
                                break;
                            }

                            default: {
                                throw runtime_error{tfm::format("Invalid IPC packet type %d", (int)packet.type())};
                            }
                        }
                    } catch (const runtime_error& e) {
                        tlog::warning() << "Malformed IPC packet: " << e.what();
                    }
                })) { }

                this_thread::sleep_for(chrono::milliseconds{100});
            }
        }};
    }

    // Load images passed via command line in the background prior to
    // creating our main application such that they are not stalled
    // by the potentially slow initialization of opengl / glfw.
    string channelSelector;
    for (auto imageFile : get(imageFiles)) {
        if (!imageFile.empty() && imageFile[0] == ':') {
            channelSelector = imageFile.substr(1);
            continue;
        }

        imagesLoader->enqueue(imageFile, channelSelector, false);
    }

    // Init nanogui application
    nanogui::init();

    imageViewer.reset(new ImageViewer{imagesLoader, !imageFiles});
    imageViewer->drawAll();
    imageViewer->setVisible(true);

    // Do what the maximize flag tells us---if it exists---and
    // maximize if we have images otherwise.
    if (maximizeFlag ? get(maximizeFlag) : imageFiles) {
        imageViewer->maximize();
    }

    // Apply parameter flags
    if (exposureFlag) { imageViewer->setExposure(get(exposureFlag)); }
    if (filterFlag)   { imageViewer->setFilter(get(filterFlag)); }
    if (gammaFlag)    { imageViewer->setGamma(get(gammaFlag)); }
    if (metricFlag)   { imageViewer->setMetric(toMetric(get(metricFlag))); }
    if (offsetFlag)   { imageViewer->setOffset(get(offsetFlag)); }
    if (tonemapFlag)  { imageViewer->setTonemap(toTonemap(get(tonemapFlag))); }

    // Refresh only every 250ms if there are no user interactions.
    // This makes an idling tev surprisingly energy-efficient. :)
    nanogui::mainloop(250);

    shallShutdown = true;

    // On some linux distributions glfwTerminate() (which is called by
    // nanogui::shutdown()) causes segfaults. Since we are done with our
    // program here anyways, let's let the OS clean up after us.
    //nanogui::shutdown();

    if (ipcThread.joinable()) {
        ipcThread.join();
    }

    if (stdinThread.joinable()) {
        stdinThread.join();
    }

    imageViewer.reset();

    return 0;
}

TEV_NAMESPACE_END

#ifdef _WIN32
int wmain(int argc, wchar_t* argv[]) {
#else
int main(int argc, char* argv[]) {
#endif
    try {
        vector<string> arguments;
        for (int i = 0; i < argc; ++i) {
#ifdef _WIN32
            arguments.emplace_back(tev::utf16to8(argv[i]));
#else
            string arg = argv[i];
            // OSX sometimes (seemingly sporadically) passes the
            // process serial number via a command line parameter.
            // We would like to ignore this.
            if (arg.find("-psn") != 0) {
                arguments.emplace_back(tev::ensureUtf8(argv[i]));
            }
#endif
        }

        tev::mainFunc(arguments);
    } catch (const exception& e) {
        tlog::error() << tfm::format("Uncaught exception: %s", e.what());
        return 1;
    }
}
<commit_msg>Fix off by one error spotted by Matt<commit_after>// This file was developed by Thomas Müller <thomas94@gmx.net>.
// It is published under the BSD 3-Clause License within the LICENSE file.

#include <tev/Image.h>
#include <tev/ImageViewer.h>
#include <tev/Ipc.h>
#include <tev/ThreadPool.h>

#include <args.hxx>
#include <ImfThreading.h>

#include <utf8.h>

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

using namespace args;
using namespace filesystem;
using namespace std;

TEV_NAMESPACE_BEGIN

int mainFunc(const vector<string>& arguments) {
    ArgumentParser parser{
        "tev — The EXR Viewer\n"
        "version " TEV_VERSION "\n"
        "Inspection tool for images with high dynamic range",
        "tev was developed by Thomas Müller <thomas94@gmx.net>. "
        "Its source code is available under the BSD 3-Clause License at https://tom94.net",
    };

    ValueFlag<float> exposureFlag{
        parser,
        "EXPOSURE",
        "Scales the brightness of an image prior to tonemapping by 2^EXPOSURE. Default is 0.",
        {'e', "exposure"},
    };

    ValueFlag<string> filterFlag{
        parser,
        "FILTER",
        "Filter visible images and groups according to a supplied string. "
        "The string must have the format 'image:group'. "
        "Only images whose name contains 'image' and groups whose name contains 'group' will be visible.",
        {'f', "filter"},
    };

    ValueFlag<float> gammaFlag{
        parser,
        "GAMMA",
        "The exponent used when TONEMAP is 'Gamma'. Default is 2.2.",
        {'g', "gamma"},
    };

    HelpFlag helpFlag{
        parser,
        "HELP",
        "Display this help menu.",
        {'h', "help"},
    };

    ValueFlag<string> hostnameFlag{
        parser,
        "HOSTNAME",
        "The hostname to listen on for IPC communication. "
        "tev can have a distinct primary instance for each unique hostname in use. "
        "Default is 127.0.0.1:14158",
        {"host", "hostname"},
    };

    ValueFlag<bool> maximizeFlag{
        parser,
        "MAXIMIZE",
        "Maximize the window on startup. "
        "If no images were supplied via the command line, then the default is FALSE. "
        "Otherwise, the default is TRUE.",
        {"max", "maximize"},
    };

    ValueFlag<string> metricFlag{
        parser,
        "METRIC",
        "The metric to use when comparing two images. "
        "The available metrics are:\n"
        "E   - Error\n"
        "AE  - Absolute Error\n"
        "SE  - Squared Error\n"
        "RAE - Relative Absolute Error\n"
        "RSE - Relative Squared Error\n"
        "Default is E.",
        {'m', "metric"},
    };

    Flag newWindowFlag{
        parser,
        "NEW WINDOW",
        "Open a new window of tev, even if one exists already.",
        {'n', "new"},
    };

    ValueFlag<float> offsetFlag{
        parser,
        "OFFSET",
        "Add an absolute offset to the image after EXPOSURE has been applied. Default is 0.",
        {'o', "offset"},
    };

    ValueFlag<string> tonemapFlag{
        parser,
        "TONEMAP",
        "The tonemapping algorithm to use. "
        "The available tonemaps are:\n"
        "sRGB   - sRGB\n"
        "Gamma  - Gamma curve\n"
        "FC     - False Color\n"
        "PN     - Positive=Green, Negative=Red\n"
        "Default is sRGB.",
        {'t', "tonemap"},
    };

    Flag versionFlag{
        parser,
        "VERSION",
        "Display the version of tev.",
        {'v', "version"},
    };

    PositionalList<string> imageFiles{
        parser,
        "images",
        "The image files to be opened by tev. "
        "If an argument starting with a ':' is encountered, "
        "then this argument is not treated as an image file "
        "but as a comma-separated channel selector. Until the next channel "
        "selector is encountered only channels containing "
        "elements from the current selector will be loaded. This is "
        "especially useful for selectively loading a specific "
        "part of a multi-part EXR file.",
    };

    // Parse command line arguments and react to parsing
    // errors using exceptions.
    try {
        TEV_ASSERT(arguments.size() > 0, "Number of arguments must be bigger than 0.");

        parser.Prog(arguments.front());
        parser.ParseArgs(begin(arguments) + 1, end(arguments));
    } catch (const Help&) {
        cout << parser;
        return 0;
    } catch (const ParseError& e) {
        cerr << e.what() << endl;
        cerr << parser;
        return -1;
    } catch (const ValidationError& e) {
        cerr << e.what() << endl;
        cerr << parser;
        return -2;
    }

    if (versionFlag) {
        tlog::none() << "tev — The EXR Viewer\nversion " TEV_VERSION;
        return 0;
    }

    const string hostname = hostnameFlag ? get(hostnameFlag) : "127.0.0.1:14158";
    auto ipc = make_shared<Ipc>(hostname);

    // If we're not the primary instance and did not request to open a new window,
    // simply send the to-be-opened images to the primary instance.
    if (!ipc->isPrimaryInstance() && !newWindowFlag) {
        string channelSelector;
        for (auto imageFile : get(imageFiles)) {
            if (!imageFile.empty() && imageFile[0] == ':') {
                channelSelector = imageFile.substr(1);
                continue;
            }

            try {
                IpcPacket packet;
                packet.setOpenImage(tfm::format("%s:%s", path{imageFile}.make_absolute(), channelSelector), true);
                ipc->sendToPrimaryInstance(packet);
            } catch (runtime_error e) {
                tlog::error() << tfm::format("Invalid file '%s': %s", imageFile, e.what());
            }
        }

        return 0;
    }

    Imf::setGlobalThreadCount(thread::hardware_concurrency());

    tlog::info() << "Loading window...";

    shared_ptr<BackgroundImagesLoader> imagesLoader = make_shared<BackgroundImagesLoader>();

    atomic<bool> shallShutdown{false};

    // Spawn a background thread that opens images passed via stdin.
    // To allow whitespace characters in filenames, we use the convention that
    // paths in stdin must be separated by newlines.
    thread stdinThread{[&]() {
        string channelSelector;
        while (!shallShutdown) {
            for (string line; getline(cin, line);) {
                string imageFile = tev::ensureUtf8(line);

                if (imageFile.empty()) {
                    continue;
                }

                if (imageFile[0] == ':') {
                    channelSelector = imageFile.substr(1);
                    continue;
                }

                imagesLoader->enqueue(imageFile, channelSelector, false);
            }

            this_thread::sleep_for(chrono::milliseconds{100});
        }
    }};

    // It is unfortunately not easily possible to poll/timeout on cin in a portable manner,
    // so instead we resort to simply detaching this thread, causing it to be forcefully
    // terminated as the main thread terminates.
    stdinThread.detach();

    unique_ptr<ImageViewer> imageViewer;

    // Spawn another background thread, this one dealing with images passed to us
    // via inter-process communication (IPC). This happens when
    // a user starts another instance of tev while one is already running. Note, that this
    // behavior can be overridden by the -n flag, so not _all_ secondary instances send their
    // paths to the primary instance.
    thread ipcThread;
    if (ipc->isPrimaryInstance()) {
        ipcThread = thread{[&]() {
            while (!shallShutdown) {
                while (ipc->receiveFromSecondaryInstance([&](const IpcPacket& packet) {
                    try {
                        switch (packet.type()) {
                            case IpcPacket::OpenImage: {
                                auto info = packet.interpretAsOpenImage();
                                string imageString = ensureUtf8(info.imagePath);
                                size_t colonPos = min(imageString.length(), imageString.find_last_of(":"));
                                imagesLoader->enqueue(imageString.substr(0, colonPos), imageString.substr(colonPos + 1), info.grabFocus);
                                break;
                            }

                            case IpcPacket::ReloadImage: {
                                while (!imageViewer) { }
                                auto info = packet.interpretAsReloadImage();
                                imageViewer->scheduleToUiThread([&,info] {
                                    string imageString = ensureUtf8(info.imagePath);
                                    imageViewer->reloadImage(imageString, info.grabFocus);
                                });
                                break;
                            }

                            case IpcPacket::CloseImage: {
                                while (!imageViewer) { }
                                auto info = packet.interpretAsCloseImage();
                                imageViewer->scheduleToUiThread([&,info] {
                                    string imageString = ensureUtf8(info.imagePath);
                                    imageViewer->removeImage(imageString);
                                });
                                break;
                            }

                            case IpcPacket::UpdateImage: {
                                while (!imageViewer) { }
                                auto info = packet.interpretAsUpdateImage();
                                imageViewer->scheduleToUiThread([&,info] {
                                    string imageString = ensureUtf8(info.imagePath);
                                    imageViewer->updateImage(imageString, info.grabFocus, info.channel, info.x, info.y, info.width, info.height, info.imageData);
                                });
                                break;
                            }

                            default: {
                                throw runtime_error{tfm::format("Invalid IPC packet type %d", (int)packet.type())};
                            }
                        }
                    } catch (const runtime_error& e) {
                        tlog::warning() << "Malformed IPC packet: " << e.what();
                    }
                })) { }

                this_thread::sleep_for(chrono::milliseconds{100});
            }
        }};
    }

    // Load images passed via command line in the background prior to
    // creating our main application such that they are not stalled
    // by the potentially slow initialization of opengl / glfw.
    string channelSelector;
    for (auto imageFile : get(imageFiles)) {
        if (!imageFile.empty() && imageFile[0] == ':') {
            channelSelector = imageFile.substr(1);
            continue;
        }

        imagesLoader->enqueue(imageFile, channelSelector, false);
    }

    // Init nanogui application
    nanogui::init();

    imageViewer.reset(new ImageViewer{imagesLoader, !imageFiles});
    imageViewer->drawAll();
    imageViewer->setVisible(true);

    // Do what the maximize flag tells us---if it exists---and
    // maximize if we have images otherwise.
    if (maximizeFlag ? get(maximizeFlag) : imageFiles) {
        imageViewer->maximize();
    }

    // Apply parameter flags
    if (exposureFlag) { imageViewer->setExposure(get(exposureFlag)); }
    if (filterFlag)   { imageViewer->setFilter(get(filterFlag)); }
    if (gammaFlag)    { imageViewer->setGamma(get(gammaFlag)); }
    if (metricFlag)   { imageViewer->setMetric(toMetric(get(metricFlag))); }
    if (offsetFlag)   { imageViewer->setOffset(get(offsetFlag)); }
    if (tonemapFlag)  { imageViewer->setTonemap(toTonemap(get(tonemapFlag))); }

    // Refresh only every 250ms if there are no user interactions.
    // This makes an idling tev surprisingly energy-efficient. :)
    nanogui::mainloop(250);

    shallShutdown = true;

    // On some linux distributions glfwTerminate() (which is called by
    // nanogui::shutdown()) causes segfaults. Since we are done with our
    // program here anyways, let's let the OS clean up after us.
    //nanogui::shutdown();

    if (ipcThread.joinable()) {
        ipcThread.join();
    }

    if (stdinThread.joinable()) {
        stdinThread.join();
    }

    imageViewer.reset();

    return 0;
}

TEV_NAMESPACE_END

#ifdef _WIN32
int wmain(int argc, wchar_t* argv[]) {
#else
int main(int argc, char* argv[]) {
#endif
    try {
        vector<string> arguments;
        for (int i = 0; i < argc; ++i) {
#ifdef _WIN32
            arguments.emplace_back(tev::utf16to8(argv[i]));
#else
            string arg = argv[i];
            // OSX sometimes (seemingly sporadically) passes the
            // process serial number via a command line parameter.
            // We would like to ignore this.
            if (arg.find("-psn") != 0) {
                arguments.emplace_back(tev::ensureUtf8(argv[i]));
            }
#endif
        }

        tev::mainFunc(arguments);
    } catch (const exception& e) {
        tlog::error() << tfm::format("Uncaught exception: %s", e.what());
        return 1;
    }
}
<|endoftext|>


<commit_before>/***
 * Copyright (c) 2013, Dan Hasting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the organization nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
 *
 ***/

#include "logdialog.h"

LogDialog::LogDialog(QString lastOutput, QWidget *parent) : QDialog(parent)
{
    setWindowTitle(tr("CEN64 Log"));
    setMinimumSize(600, 400);

    logLayout = new QGridLayout(this);
    logLayout->setContentsMargins(5, 10, 5, 10);

    logArea = new QTextEdit(this);
    logArea->setWordWrapMode(QTextOption::NoWrap);

    QFont font;
#ifdef OS_LINUX_OR_BSD
    font.setFamily("Monospace");
    font.setPointSize(9);
#else
    font.setFamily("Courier");
    font.setPointSize(10);
#endif
    font.setFixedPitch(true);
    logArea->setFont(font);

    logArea->setPlainText(lastOutput);

    logButtonBox = new QDialogButtonBox(Qt::Horizontal, this);
    logButtonBox->addButton(tr("Close"), QDialogButtonBox::AcceptRole);

    logLayout->addWidget(logArea, 0, 0);
    logLayout->addWidget(logButtonBox, 1, 0);

    connect(logButtonBox, SIGNAL(accepted()), this, SLOT(close()));

    setLayout(logLayout);
}
<commit_msg>Fix monospaced font in log dialog<commit_after>/***
 * Copyright (c) 2013, Dan Hasting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the organization nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
 *
 ***/

#include "logdialog.h"

#if QT_VERSION >= 0x050200
#include <QFontDatabase>
#endif

LogDialog::LogDialog(QString lastOutput, QWidget *parent) : QDialog(parent)
{
    setWindowTitle(tr("CEN64 Log"));
    setMinimumSize(600, 400);

    logLayout = new QGridLayout(this);
    logLayout->setContentsMargins(5, 10, 5, 10);

    logArea = new QTextEdit(this);
    logArea->setWordWrapMode(QTextOption::NoWrap);

#if QT_VERSION >= 0x050200
    QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
#else
    QFont font("Monospace");
    font.setStyleHint(QFont::TypeWriter);
#endif
    logArea->setFont(font);

    logArea->setPlainText(lastOutput);

    logButtonBox = new QDialogButtonBox(Qt::Horizontal, this);
    logButtonBox->addButton(tr("Close"), QDialogButtonBox::AcceptRole);

    logLayout->addWidget(logArea, 0, 0);
    logLayout->addWidget(logButtonBox, 1, 0);

    connect(logButtonBox, SIGNAL(accepted()), this, SLOT(close()));

    setLayout(logLayout);
}
<|endoftext|>


<commit_before>/* openrtb_bid_request.cc
   Jeremy Barnes, 19 February 2013
   Copyright (c) 2013 Datacratic Inc.  All rights reserved.

   Bid request parser for OpenRTB.
*/

#include "openrtb_bid_request.h"
#include "jml/utils/json_parsing.h"
#include "rtbkit/openrtb/openrtb.h"
#include "rtbkit/openrtb/openrtb_parsing.h"

using namespace std;

namespace RTBKIT {

/*****************************************************************************/
/* OPENRTB BID REQUEST PARSER                                                */
/*****************************************************************************/

BidRequest *
fromOpenRtb(OpenRTB::BidRequest && req,
            const std::string & provider,
            const std::string & exchange)
{
    std::unique_ptr<BidRequest> result(new BidRequest());

    result->auctionId = std::move(req.id);
    result->auctionType = AuctionType::SECOND_PRICE;
    result->timeAvailableMs = req.tmax.value();
    result->timestamp = Date::now();
    result->isTest = false;
    result->unparseable = std::move(req.unparseable);

    result->provider = provider;
    result->exchange = (exchange.empty() ? provider : exchange);

    auto onImpression = [&] (OpenRTB::Impression && imp)
        {
            AdSpot spot(std::move(imp));

            // Copy the ad formats in for the moment
            if (spot.banner) {
                for (unsigned i = 0;  i < spot.banner->w.size();  ++i) {
                    spot.formats.push_back(Format(spot.banner->w[i],
                                                 spot.banner->h[i]));
                }
                spot.position = spot.banner->pos;
            }

            // Now create tags
            spot.id = std::move(imp.id);
            if (imp.banner) {
                auto & b = *imp.banner;

                if (b.w.size() != b.h.size())
                    throw ML::Exception("widths and heights must match");

                for (unsigned i = 0;  i < b.w.size();  ++i) {
                    int w = b.w[i];
                    int h = b.h[i];

                    Format format(w, h);
                    spot.formats.push_back(format);
                }
#if 0
                if (!b.expdir.empty()) {
                    spot.tagFilter.mustInclude.add("expandableTargetingNotSupported");
                }
                if (!b.api.empty()) {
                    spot.tagFilter.mustInclude.add("apiFrameworksNotSupported");
                }
                if (!b.btype.empty()) {
                    spot.tagFilter.mustInclude.add("creativeTypeBlockingNotSupported");
                }
                if (!b.battr.empty()) {
                    spot.tagFilter.mustInclude.add("creativeTypeB");
                    // Blocked creative attributes
                }
                if (!b.mimes.empty()) {
                    // We must have specified a MIME type and it must be
                    // supported by the exchange.

                }
#endif

            } else if (imp.video) {
                auto & v = *imp.video;

                if(!v.mimes.empty()) {
                    // We need at least one MIME type supported by the exchange
                }

                if(v.linearity.value() < 0) {

                }

                if(v.minduration.value() < 0) {

                }

                if(v.maxduration.value() < 0) {

                }

                Format format(v.w.value(), v.h.value());
                spot.formats.push_back(format);
            }
#if 0
            if (!imp.displaymanager.empty()) {
                tags.add("displayManager", imp.displaymanager);
            }
            if (!imp.displaymanagerver.empty()) {
                tags.add("displayManagerVersion", imp.displaymanagerver);
            }
            if (!imp.instl.unspecified()) {
                tags.add("interstitial", imp.instl.value());
            }
            if (!imp.tagid.empty()) {
                tags.add("tagid", imp.tagid.value());
            }
            if (imp.bidfloor.value() != 0.0) {
                if (!imp.bidfloorcur.empty())
                    spot.reservePrice = Amount(imp.bidfloorcur,
                                               imp.bidfloor.value() * 0.001);
                else
                    spot.reservePrice = USD_CPM(imp.bidfloor.value());
            }
            for (b: imp.iframebuster) {
                spot.tags.add("iframebuster", b);
            }
#endif
            result->imp.emplace_back(std::move(spot));
        };

    result->imp.reserve(req.imp.size());

    for (auto & i: req.imp)
        onImpression(std::move(i));

    if (req.site && req.app)
        throw ML::Exception("can't have site and app");

    if (req.site) {
        result->site.reset(req.site.release());
        if (!result->site->page.empty())
            result->url = result->site->page;
        else if (result->site->id)
            result->url = Url("http://" + result->site->id.toString() + ".siteid/");
    }
    else if (req.app) {
        result->app.reset(req.app.release());

        if (!result->app->bundle.empty())
            result->url = Url(result->app->bundle);
        else if (result->app->id)
            result->url = Url("http://" + result->app->id.toString() + ".appid/");
    }

    if (req.device) {
        result->device.reset(req.device.release());
        result->language = result->device->language;
        result->userAgent = result->device->ua;
        if (!result->device->ip.empty())
            result->ipAddress = result->device->ip;
        else if (!result->device->ipv6.empty())
            result->ipAddress = result->device->ipv6;

        if (result->device->geo) {
            const auto & g = *result->device->geo;
            auto & l = result->location;
            l.countryCode = g.country;
            if (!g.region.empty())
                l.regionCode = g.region;
            else l.regionCode = g.regionfips104;
            l.cityName = g.city;
            l.postalCode = g.zip;
            if(!g.metro.empty())
                l.metro = boost::lexical_cast<int> (g.metro);
// TODO DMA
        }
    }

    if (req.user) {
        result->user.reset(req.user.release());
        for (auto & d: result->user->data) {
            string key;
            if (d.id)
                key = d.id.toString();
            else key = d.name.extractAscii();

            vector<string> values;
            for (auto & v: d.segment) {
                if (v.id)
                    values.push_back(v.id.toString());
                else if (!v.name.empty())
                    values.push_back(v.name.extractAscii());
            }

            result->segments.addStrings(key, values);
        }

        if (result->user->tz.val != -1)
            result->location.timezoneOffsetMinutes = result->user->tz.val;

        if (result->user->id)
            result->userIds.add(result->user->id, ID_EXCHANGE);
        if (result->user->buyeruid)
            result->userIds.add(result->user->buyeruid, ID_PROVIDER);
        else if (result->user->id)
            result->userIds.add(result->user->id, ID_PROVIDER);
        else if(result->device && !result->device->ip.empty() && !result->device->ua.empty()) {
            const std::string &strToHash = (result->device->ip + result->device->ua.extractAscii());
            result->userAgentIPHash = Id(CityHash64(strToHash.c_str(), strToHash.length()));
            result->userIds.add(result->userAgentIPHash, ID_PROVIDER);
        }

        else
            result->userIds.add(Id(0), ID_PROVIDER);

    }
    else
    {
        // We don't receive a user object, we need at least to set provider_ID in order to identify
        // the user

        if(result->device && !result->device->ip.empty() && !result->device->ua.empty()) {
            const std::string &strToHash = (result->device->ip + result->device->ua.extractAscii());
            result->userAgentIPHash = Id(CityHash64(strToHash.c_str(), strToHash.length()));
            result->userIds.add(result->userAgentIPHash, ID_PROVIDER);
        }
        else {
            result->userIds.add(Id(0), ID_PROVIDER);
        }
    }

    if (!req.cur.empty()) {
        for (unsigned i = 0;  i < req.cur.size();  ++i) {
            result->bidCurrency.push_back(parseCurrencyCode(req.cur[i]));
        }
    }
    else {
        result->bidCurrency.push_back(CurrencyCode::CC_USD);
    }

    result->blockedCategories = std::move(req.bcat);

    // blocked tld advertisers
    result->badv = std::move(req.badv);
    vector<string> badv ;
    for (auto s: req.badv)
    	badv.push_back (s.extractAscii());
    result->restrictions.addStrings("badv", badv);

    result->ext = std::move(req.ext);

    result->segments.addStrings("openrtb-wseat", req.wseat);

    return result.release();
}

OpenRTB::BidRequest toOpenRtb(const BidRequest &req)
{
    OpenRTB::BidRequest result;

    result.id = req.auctionId;
    result.at = req.auctionType;
    result.tmax = req.timeAvailableMs;
    result.unparseable = req.unparseable;

    auto onAdSpot = [&](const AdSpot &spot) {
        OpenRTB::Impression imp(spot);

        result.imp.push_back(std::move(imp));
    };

    result.imp.reserve(req.imp.size());
    for (const auto &spot: req.imp) {
        onAdSpot(spot);
    }

    if (req.site && req.app)
        throw ML::Exception("can't have site and app");

    if (req.site) {
        result.site.reset(new OpenRTB::Site(*req.site));
    }
    else if (req.app) {
        result.app.reset(new OpenRTB::App(*req.app));
    }

    if (req.user) {
        result.user.reset(new OpenRTB::User(*req.user));
    }

    if (req.device) {
        result.device.reset(new OpenRTB::Device(*req.device));
    }

    result.bcat = req.blockedCategories;
    result.cur.reserve(req.bidCurrency.size());

    for (const auto &cur: req.bidCurrency) {

        result.cur.push_back(toString(cur));
    }

    result.badv = req.badv;

    result.ext = req.ext;
    const auto &wseatSegments = req.segments.get("openrtb-wseat");
    std::vector<std::string> wseat;
    wseatSegments.forEach([&](int, const std::string &str, float) {
        wseat.push_back(str);
    });

    result.wseat = std::move(wseat);

    return result;
}

namespace {

static DefaultDescription<OpenRTB::BidRequest> desc;

} // file scope

OpenRTB::BidRequest
OpenRtbBidRequestParser::
parseBidRequest(const std::string & jsonValue)
{
    const char * strStart = jsonValue.c_str();
    StreamingJsonParsingContext jsonContext(jsonValue, strStart,
                                            strStart + jsonValue.size());

    OpenRTB::BidRequest req;
    desc.parseJson(&req, jsonContext);
    return std::move(req);
}

BidRequest *
OpenRtbBidRequestParser::
parseBidRequest(const std::string & jsonValue,
                const std::string & provider,
                const std::string & exchange)
{
    return fromOpenRtb(parseBidRequest(jsonValue), provider, exchange);
}

OpenRTB::BidRequest
OpenRtbBidRequestParser::
parseBidRequest(ML::Parse_Context & context)
{
    StreamingJsonParsingContext jsonContext(context);

    OpenRTB::BidRequest req;
    desc.parseJson(&req, jsonContext);
    return std::move(req);
}

BidRequest *
OpenRtbBidRequestParser::
parseBidRequest(ML::Parse_Context & context,
                const std::string & provider,
                const std::string & exchange)
{
    return fromOpenRtb(parseBidRequest(context), provider, exchange);
}

} // namespace RTBKIT
<commit_msg>fixed to use spot instead of imp that offered a reference to nothing (damn move)<commit_after>/* openrtb_bid_request.cc
   Jeremy Barnes, 19 February 2013
   Copyright (c) 2013 Datacratic Inc.  All rights reserved.

   Bid request parser for OpenRTB.
*/

#include "openrtb_bid_request.h"
#include "jml/utils/json_parsing.h"
#include "rtbkit/openrtb/openrtb.h"
#include "rtbkit/openrtb/openrtb_parsing.h"

using namespace std;

namespace RTBKIT {

/*****************************************************************************/
/* OPENRTB BID REQUEST PARSER                                                */
/*****************************************************************************/

BidRequest *
fromOpenRtb(OpenRTB::BidRequest && req,
            const std::string & provider,
            const std::string & exchange)
{
    std::unique_ptr<BidRequest> result(new BidRequest());

    result->auctionId = std::move(req.id);
    result->auctionType = AuctionType::SECOND_PRICE;
    result->timeAvailableMs = req.tmax.value();
    result->timestamp = Date::now();
    result->isTest = false;
    result->unparseable = std::move(req.unparseable);

    result->provider = provider;
    result->exchange = (exchange.empty() ? provider : exchange);

    auto onImpression = [&] (OpenRTB::Impression && imp)
        {
            AdSpot spot(std::move(imp));

            // Copy the ad formats in for the moment
            if (spot.banner) {

                for (unsigned i = 0;  i < spot.banner->w.size();  ++i) {
                    spot.formats.push_back(Format(spot.banner->w[i],
                                                 spot.banner->h[i]));
                }
                spot.position = spot.banner->pos;

            } else if (spot.video) {

                // Unique ptr doesn't overload operators.. great.
                auto & v = *spot.video;

                if(!v.mimes.empty()) {
                    // We need at least one MIME type supported by the exchange
                }

                if(v.linearity.value() < 0) {

                }

                if(v.minduration.value() < 0) {

                }

                if(v.maxduration.value() < 0) {

                }

                Format format(v.w.value(), v.h.value());
                spot.formats.push_back(format);
            }

#if 0
            if (imp.banner) {
                auto & b = *imp.banner;

                if (b.w.size() != b.h.size())
                    throw ML::Exception("widths and heights must match");

                for (unsigned i = 0;  i < b.w.size();  ++i) {
                    int w = b.w[i];
                    int h = b.h[i];

                    Format format(w, h);
                    spot.formats.push_back(format);
                }

                if (!b.expdir.empty()) {
                    spot.tagFilter.mustInclude.add("expandableTargetingNotSupported");
                }
                if (!b.api.empty()) {
                    spot.tagFilter.mustInclude.add("apiFrameworksNotSupported");
                }
                if (!b.btype.empty()) {
                    spot.tagFilter.mustInclude.add("creativeTypeBlockingNotSupported");
                }
                if (!b.battr.empty()) {
                    spot.tagFilter.mustInclude.add("creativeTypeB");
                    // Blocked creative attributes
                }
                if (!b.mimes.empty()) {
                    // We must have specified a MIME type and it must be
                    // supported by the exchange.

                }

            if (!imp.displaymanager.empty()) {
                tags.add("displayManager", imp.displaymanager);
            }
            if (!imp.displaymanagerver.empty()) {
                tags.add("displayManagerVersion", imp.displaymanagerver);
            }
            if (!imp.instl.unspecified()) {
                tags.add("interstitial", imp.instl.value());
            }
            if (!imp.tagid.empty()) {
                tags.add("tagid", imp.tagid.value());
            }
            if (imp.bidfloor.value() != 0.0) {
                if (!imp.bidfloorcur.empty())
                    spot.reservePrice = Amount(imp.bidfloorcur,
                                               imp.bidfloor.value() * 0.001);
                else
                    spot.reservePrice = USD_CPM(imp.bidfloor.value());
            }
            for (b: imp.iframebuster) {
                spot.tags.add("iframebuster", b);
            }
#endif
            result->imp.emplace_back(std::move(spot));
        };

    result->imp.reserve(req.imp.size());

    for (auto & i: req.imp)
        onImpression(std::move(i));

    if (req.site && req.app)
        throw ML::Exception("can't have site and app");

    if (req.site) {
        result->site.reset(req.site.release());
        if (!result->site->page.empty())
            result->url = result->site->page;
        else if (result->site->id)
            result->url = Url("http://" + result->site->id.toString() + ".siteid/");
    }
    else if (req.app) {
        result->app.reset(req.app.release());

        if (!result->app->bundle.empty())
            result->url = Url(result->app->bundle);
        else if (result->app->id)
            result->url = Url("http://" + result->app->id.toString() + ".appid/");
    }

    if (req.device) {
        result->device.reset(req.device.release());
        result->language = result->device->language;
        result->userAgent = result->device->ua;
        if (!result->device->ip.empty())
            result->ipAddress = result->device->ip;
        else if (!result->device->ipv6.empty())
            result->ipAddress = result->device->ipv6;

        if (result->device->geo) {
            const auto & g = *result->device->geo;
            auto & l = result->location;
            l.countryCode = g.country;
            if (!g.region.empty())
                l.regionCode = g.region;
            else l.regionCode = g.regionfips104;
            l.cityName = g.city;
            l.postalCode = g.zip;
            if(!g.metro.empty())
                l.metro = boost::lexical_cast<int> (g.metro);
// TODO DMA
        }
    }

    if (req.user) {
        result->user.reset(req.user.release());
        for (auto & d: result->user->data) {
            string key;
            if (d.id)
                key = d.id.toString();
            else key = d.name.extractAscii();

            vector<string> values;
            for (auto & v: d.segment) {
                if (v.id)
                    values.push_back(v.id.toString());
                else if (!v.name.empty())
                    values.push_back(v.name.extractAscii());
            }

            result->segments.addStrings(key, values);
        }

        if (result->user->tz.val != -1)
            result->location.timezoneOffsetMinutes = result->user->tz.val;

        if (result->user->id)
            result->userIds.add(result->user->id, ID_EXCHANGE);
        if (result->user->buyeruid)
            result->userIds.add(result->user->buyeruid, ID_PROVIDER);
        else if (result->user->id)
            result->userIds.add(result->user->id, ID_PROVIDER);
        else if(result->device && !result->device->ip.empty() && !result->device->ua.empty()) {
            const std::string &strToHash = (result->device->ip + result->device->ua.extractAscii());
            result->userAgentIPHash = Id(CityHash64(strToHash.c_str(), strToHash.length()));
            result->userIds.add(result->userAgentIPHash, ID_PROVIDER);
        }

        else
            result->userIds.add(Id(0), ID_PROVIDER);

    }
    else
    {
        // We don't receive a user object, we need at least to set provider_ID in order to identify
        // the user

        if(result->device && !result->device->ip.empty() && !result->device->ua.empty()) {
            const std::string &strToHash = (result->device->ip + result->device->ua.extractAscii());
            result->userAgentIPHash = Id(CityHash64(strToHash.c_str(), strToHash.length()));
            result->userIds.add(result->userAgentIPHash, ID_PROVIDER);
        }
        else {
            result->userIds.add(Id(0), ID_PROVIDER);
        }
    }

    if (!req.cur.empty()) {
        for (unsigned i = 0;  i < req.cur.size();  ++i) {
            result->bidCurrency.push_back(parseCurrencyCode(req.cur[i]));
        }
    }
    else {
        result->bidCurrency.push_back(CurrencyCode::CC_USD);
    }

    result->blockedCategories = std::move(req.bcat);

    // blocked tld advertisers
    result->badv = std::move(req.badv);
    vector<string> badv ;
    for (auto s: req.badv)
    	badv.push_back (s.extractAscii());
    result->restrictions.addStrings("badv", badv);

    result->ext = std::move(req.ext);

    result->segments.addStrings("openrtb-wseat", req.wseat);

    return result.release();
}

OpenRTB::BidRequest toOpenRtb(const BidRequest &req)
{
    OpenRTB::BidRequest result;

    result.id = req.auctionId;
    result.at = req.auctionType;
    result.tmax = req.timeAvailableMs;
    result.unparseable = req.unparseable;

    auto onAdSpot = [&](const AdSpot &spot) {
        OpenRTB::Impression imp(spot);

        result.imp.push_back(std::move(imp));
    };

    result.imp.reserve(req.imp.size());
    for (const auto &spot: req.imp) {
        onAdSpot(spot);
    }

    if (req.site && req.app)
        throw ML::Exception("can't have site and app");

    if (req.site) {
        result.site.reset(new OpenRTB::Site(*req.site));
    }
    else if (req.app) {
        result.app.reset(new OpenRTB::App(*req.app));
    }

    if (req.user) {
        result.user.reset(new OpenRTB::User(*req.user));
    }

    if (req.device) {
        result.device.reset(new OpenRTB::Device(*req.device));
    }

    result.bcat = req.blockedCategories;
    result.cur.reserve(req.bidCurrency.size());

    for (const auto &cur: req.bidCurrency) {

        result.cur.push_back(toString(cur));
    }

    result.badv = req.badv;

    result.ext = req.ext;
    const auto &wseatSegments = req.segments.get("openrtb-wseat");
    std::vector<std::string> wseat;
    wseatSegments.forEach([&](int, const std::string &str, float) {
        wseat.push_back(str);
    });

    result.wseat = std::move(wseat);

    return result;
}

namespace {

static DefaultDescription<OpenRTB::BidRequest> desc;

} // file scope

OpenRTB::BidRequest
OpenRtbBidRequestParser::
parseBidRequest(const std::string & jsonValue)
{
    const char * strStart = jsonValue.c_str();
    StreamingJsonParsingContext jsonContext(jsonValue, strStart,
                                            strStart + jsonValue.size());

    OpenRTB::BidRequest req;
    desc.parseJson(&req, jsonContext);
    return std::move(req);
}

BidRequest *
OpenRtbBidRequestParser::
parseBidRequest(const std::string & jsonValue,
                const std::string & provider,
                const std::string & exchange)
{
    return fromOpenRtb(parseBidRequest(jsonValue), provider, exchange);
}

OpenRTB::BidRequest
OpenRtbBidRequestParser::
parseBidRequest(ML::Parse_Context & context)
{
    StreamingJsonParsingContext jsonContext(context);

    OpenRTB::BidRequest req;
    desc.parseJson(&req, jsonContext);
    return std::move(req);
}

BidRequest *
OpenRtbBidRequestParser::
parseBidRequest(ML::Parse_Context & context,
                const std::string & provider,
                const std::string & exchange)
{
    return fromOpenRtb(parseBidRequest(context), provider, exchange);
}

} // namespace RTBKIT
<|endoftext|>


<commit_before>/*
 * FlightVars
 * Copyright (c) 2014 Alvaro Polo
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef FLIGHTVARS_UTIL_OPTION_H
#define FLIGHTVARS_UTIL_OPTION_H

#include <memory>

#include <flightvars/util/exception.hpp>

namespace flightvars { namespace util {

FV_DECL_EXCEPTION(option_undefined);

template <class T>
class option {
public:

    static_assert(std::is_copy_constructible<T>::value,
        "option cannot be instantiated with non-copy constructible types");

    template <class T1>
    friend class option;

    option() : _data(nullptr) {}

    option(const T& data) : _data(new T(data)) {}

    option(T&& data) : _data(new T(std::move(data))) {}

    option(const option& other) : _data(other.is_defined() ? new T(other.get()) : nullptr) {}

    option(option&& other) : _data(std::move(other._data)) {}

    template <class T1>
    option(const option<T1>& other) :
        _data(other.is_defined() ? new T(other.get()) : nullptr) {}

    template <class T1>
    option(option<T1>&& other) : _data(std::move(other._data)) {}

    option& operator = (const option& other) {
        _data.reset(other.is_defined() ? new T(other.get()) : nullptr);
        return *this;
    }

    template <class T1>
    option& operator = (const option<T1>& other) {
        _data.reset(other.is_defined() ? new T(other.get()) : nullptr);
        return *this;
    }

    bool is_defined() const { return bool(_data); }

    T& get() const {
        if (is_defined()) {
            return *_data;
        } else {
            throw option_undefined("cannot get on not defined option");
        }
    }

    const T& get_or_else(const T& other) const {
        return is_defined() ? get() : other;
    }

    void set(const T& data) {
        _data.reset(new T(data));
    }

    T extract() {
        if (is_defined()) {
            auto r = std::move(*_data);
            _data.reset(nullptr);
            return std::move(r);
        } else {
            throw option_undefined("cannot extract on not defined option");
        }
    }

    template <class T1, class Func>
    option<T1> map(const Func& f) const {
        return is_defined() ? option<T1>(f(get())) : option<T1>();
    }

    template <class T1, class Func>
    option<T1> fmap(const Func& f) const {
        return is_defined() ? f(get()) : option<T1>();
    }

    template <class Func>
    void foreach(const Func& f) const {
        if (is_defined()) {
            f(get());
        }
    }

private:

    std::unique_ptr<T> _data;
};

template <>
class option<void> {
public:

    template <class T1>
    friend class option;

    option(bool is_defined = false) : _is_defined(is_defined) {}

    option(const option& other) : _is_defined(other._is_defined) {}

    option& operator = (const option& other) {
        _is_defined = other._is_defined;
        return *this;
    }

    bool is_defined() const { return _is_defined; }

    void get() const {
        if (!is_defined()) {
            throw option_undefined("cannot get on not defined option");
        }
    }

    void set(bool is_defined = true) {
        _is_defined = is_defined;
    }

    void extract() {
        if (!is_defined()) {
            throw option_undefined("cannot extract on not defined option");
        }
        _is_defined = false;
    }

private:

    bool _is_defined;
};

template <class T>
option<T> make_some(const T& value) {
    return option<T>(value);
}

template <class T>
option<T> move_some(T&& value) {
    return option<T>(std::forward<T>(value));
}

inline option<void> make_some() {
    return option<void>();
}

template <class T>
option<T> make_none() {
    return option<T>();
}

}}

#endif
<commit_msg>Add `valid()` checker & remove unrequired constraints in `option` class<commit_after>/*
 * FlightVars
 * Copyright (c) 2014 Alvaro Polo
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef FLIGHTVARS_UTIL_OPTION_H
#define FLIGHTVARS_UTIL_OPTION_H

#include <memory>

#include <flightvars/util/exception.hpp>

namespace flightvars { namespace util {

FV_DECL_EXCEPTION(option_undefined);

template <class T>
class option {
public:

    template <class T1>
    friend class option;

    option() : _data(nullptr) {}

    option(const T& data) : _data(new T(data)) {}

    option(T&& data) : _data(new T(std::move(data))) {}

    option(const option& other) : _data(other.is_defined() ? new T(other.get()) : nullptr) {}

    option(option&& other) : _data(std::move(other._data)) {}

    template <class T1>
    option(const option<T1>& other) :
        _data(other.is_defined() ? new T(other.get()) : nullptr) {}

    template <class T1>
    option(option<T1>&& other) : _data(std::move(other._data)) {}

    option& operator = (const option& other) {
        _data.reset(other.is_defined() ? new T(other.get()) : nullptr);
        return *this;
    }

    template <class T1>
    option& operator = (const option<T1>& other) {
        _data.reset(other.is_defined() ? new T(other.get()) : nullptr);
        return *this;
    }

    bool valid() const { return is_defined(); }

    bool is_defined() const { return bool(_data); }

    T& get() const {
        if (is_defined()) {
            return *_data;
        } else {
            throw option_undefined("cannot get on not defined option");
        }
    }

    const T& get_or_else(const T& other) const {
        return is_defined() ? get() : other;
    }

    void set(const T& data) {
        _data.reset(new T(data));
    }

    T extract() {
        if (is_defined()) {
            auto r = std::move(*_data);
            _data.reset(nullptr);
            return std::move(r);
        } else {
            throw option_undefined("cannot extract on not defined option");
        }
    }

    template <class T1, class Func>
    option<T1> map(const Func& f) const {
        return is_defined() ? option<T1>(f(get())) : option<T1>();
    }

    template <class T1, class Func>
    option<T1> fmap(const Func& f) const {
        return is_defined() ? f(get()) : option<T1>();
    }

    template <class Func>
    void foreach(const Func& f) const {
        if (is_defined()) {
            f(get());
        }
    }

private:

    std::unique_ptr<T> _data;
};

template <>
class option<void> {
public:

    template <class T1>
    friend class option;

    option(bool is_defined = false) : _is_defined(is_defined) {}

    option(const option& other) : _is_defined(other._is_defined) {}

    option& operator = (const option& other) {
        _is_defined = other._is_defined;
        return *this;
    }

    bool valid() const { return is_defined(); }

    bool is_defined() const { return _is_defined; }

    void get() const {
        if (!is_defined()) {
            throw option_undefined("cannot get on not defined option");
        }
    }

    void set(bool is_defined = true) {
        _is_defined = is_defined;
    }

    void extract() {
        if (!is_defined()) {
            throw option_undefined("cannot extract on not defined option");
        }
        _is_defined = false;
    }

private:

    bool _is_defined;
};

template <class T>
option<T> make_some(const T& value) {
    return option<T>(value);
}

template <class T>
option<T> move_some(T&& value) {
    return option<T>(std::forward<T>(value));
}

inline option<void> make_some() {
    return option<void>();
}

template <class T>
option<T> make_none() {
    return option<T>();
}

}}

#endif
<|endoftext|>


<commit_before>
#pragma once

// note: for an odd Qt-related issue, this python include has to come before
// the Qt includes (because of the 'slots' macro)
#include <boost/python.hpp>

#include <Geometry2d/TransformMatrix.hpp>
#include <Geometry2d/Polygon.hpp>
#include <Geometry2d/Point.hpp>
#include <Geometry2d/CompositeShape.hpp>
#include <Geometry2d/ShapeSet.hpp>

#include <set>
#include <QMutex>
#include <QString>

#include <boost/ptr_container/ptr_vector.hpp>

class OurRobot;
class SystemState;

/**
 * @brief Higher-level logic for soccer
 * @details The Gameplay namespace contains things like Plays, Behaviors,
 * Tactics
 * and the GameplayModule.
 */
namespace Gameplay {

/**
 * @brief Coordinator of high-level logic
 *
 * @details The gameplay module has an embedded python interpreter and serves as
 * the bridge between our python and c++ code.
 * The python side of things is responsible for high-level gameplay.  At each
 * iteration of the main run loop, the GameplayModule
 * calls into python, which does all of the high-level planning, resulting in
 * updated motion targets, etc for the robots.  The
 * GameplayModule then executes path planning for each OurRobot.
 */
class GameplayModule {
public:
    GameplayModule(SystemState* state);
    virtual ~GameplayModule();

    SystemState* state() const { return _state; }

    virtual void run();

    void setupUI();

    /**
     * @brief Loads a playbook file to enable specified plays.
     * If isAbsolute is false, the path is treated as relative to the
     * playbooks directory. Otherwise, it is treated as an absolute path.
     */
    void loadPlaybook(const std::string& playbookFile, bool isAbsolute = false);

    /**
     * @brief Saves the currently enabled plays to a playbook file
     * If isAbsolute is false, the path is treated as relative to the
     * playbooks directory. Otherwise, it is treated as an absolute path.
     */
    void savePlaybook(const std::string& playbookFile, bool isAbsolute = false);

    void goalieID(int value);
    int goalieID() { return _goalieID; }

    /**
     * @defgroup matrices Coordinate Conversion Matrices
     * Each of these matrices converts coordinates from some other system
     * to team space.
     *
     * Example:
     * team = _gameplay->oppMatrix() * Geometry2d::Point(1, 0);
     */

    /**
     * Centered on the ball
     * @ingroup matrices
     */
    Geometry2d::TransformMatrix ballMatrix() const { return _ballMatrix; }

    /**
     * Center of the field
     * @ingroup matrices
     */
    Geometry2d::TransformMatrix centerMatrix() const { return _centerMatrix; }

    /**
     * Opponent's coordinates
     * @ingroup matrices
     */
    Geometry2d::TransformMatrix oppMatrix() const { return _oppMatrix; }

    /// All robots on our team that are usable by plays
    const std::set<OurRobot*>& playRobots() const { return _playRobots; }

    void sendFieldDimensionsToPython();

    void calculateFieldObstacles();

    /**
     * Returns the current set of global obstacles, including the field
     */
    Geometry2d::ShapeSet globalObstacles() const;

    /// Returns a ShapeSet containing both goal zones
    Geometry2d::ShapeSet goalZoneObstacles() const;

protected:
    boost::python::object getRootPlay();

    /// gets the instance of the main.py module that's loaded at GameplayModule
    boost::python::object getMainModule();

    boost::python::object getConstantsModule();

private:
    /// This protects all of Gameplay.
    /// This is held while plays are running.
    QMutex _mutex;

    SystemState* _state;

    std::set<OurRobot*> _playRobots;

    Geometry2d::TransformMatrix _ballMatrix;
    Geometry2d::TransformMatrix _centerMatrix;
    Geometry2d::TransformMatrix _oppMatrix;

    /// Obstacles to prevent using half the field
    std::shared_ptr<Geometry2d::Polygon> _ourHalf;
    std::shared_ptr<Geometry2d::Polygon> _opponentHalf;

    std::shared_ptr<Geometry2d::Shape> _sideObstacle;

    /// outside of the floor boundaries
    std::shared_ptr<Geometry2d::Shape> _nonFloor[4];

    /// goal areas
    std::shared_ptr<Geometry2d::CompositeShape> _ourGoalArea;
    std::shared_ptr<Geometry2d::CompositeShape> _theirGoalArea;

    std::shared_ptr<Geometry2d::Polygon> _ourGoal;
    std::shared_ptr<Geometry2d::Polygon> _theirGoal;

    /// utility functions

    int _our_score_last_frame;

    // Shell ID of the robot to assign the goalie position
    int _goalieID;

    // python
    boost::python::object _mainPyNamespace;
};
}
<commit_msg>removed getConstantsModule from hpp<commit_after>
#pragma once

// note: for an odd Qt-related issue, this python include has to come before
// the Qt includes (because of the 'slots' macro)
#include <boost/python.hpp>

#include <Geometry2d/TransformMatrix.hpp>
#include <Geometry2d/Polygon.hpp>
#include <Geometry2d/Point.hpp>
#include <Geometry2d/CompositeShape.hpp>
#include <Geometry2d/ShapeSet.hpp>

#include <set>
#include <QMutex>
#include <QString>

#include <boost/ptr_container/ptr_vector.hpp>

class OurRobot;
class SystemState;

/**
 * @brief Higher-level logic for soccer
 * @details The Gameplay namespace contains things like Plays, Behaviors,
 * Tactics
 * and the GameplayModule.
 */
namespace Gameplay {

/**
 * @brief Coordinator of high-level logic
 *
 * @details The gameplay module has an embedded python interpreter and serves as
 * the bridge between our python and c++ code.
 * The python side of things is responsible for high-level gameplay.  At each
 * iteration of the main run loop, the GameplayModule
 * calls into python, which does all of the high-level planning, resulting in
 * updated motion targets, etc for the robots.  The
 * GameplayModule then executes path planning for each OurRobot.
 */
class GameplayModule {
public:
    GameplayModule(SystemState* state);
    virtual ~GameplayModule();

    SystemState* state() const { return _state; }

    virtual void run();

    void setupUI();

    /**
     * @brief Loads a playbook file to enable specified plays.
     * If isAbsolute is false, the path is treated as relative to the
     * playbooks directory. Otherwise, it is treated as an absolute path.
     */
    void loadPlaybook(const std::string& playbookFile, bool isAbsolute = false);

    /**
     * @brief Saves the currently enabled plays to a playbook file
     * If isAbsolute is false, the path is treated as relative to the
     * playbooks directory. Otherwise, it is treated as an absolute path.
     */
    void savePlaybook(const std::string& playbookFile, bool isAbsolute = false);

    void goalieID(int value);
    int goalieID() { return _goalieID; }

    /**
     * @defgroup matrices Coordinate Conversion Matrices
     * Each of these matrices converts coordinates from some other system
     * to team space.
     *
     * Example:
     * team = _gameplay->oppMatrix() * Geometry2d::Point(1, 0);
     */

    /**
     * Centered on the ball
     * @ingroup matrices
     */
    Geometry2d::TransformMatrix ballMatrix() const { return _ballMatrix; }

    /**
     * Center of the field
     * @ingroup matrices
     */
    Geometry2d::TransformMatrix centerMatrix() const { return _centerMatrix; }

    /**
     * Opponent's coordinates
     * @ingroup matrices
     */
    Geometry2d::TransformMatrix oppMatrix() const { return _oppMatrix; }

    /// All robots on our team that are usable by plays
    const std::set<OurRobot*>& playRobots() const { return _playRobots; }

    void sendFieldDimensionsToPython();

    void calculateFieldObstacles();

    /**
     * Returns the current set of global obstacles, including the field
     */
    Geometry2d::ShapeSet globalObstacles() const;

    /// Returns a ShapeSet containing both goal zones
    Geometry2d::ShapeSet goalZoneObstacles() const;

protected:
    boost::python::object getRootPlay();

    /// gets the instance of the main.py module that's loaded at GameplayModule
    boost::python::object getMainModule();

private:
    /// This protects all of Gameplay.
    /// This is held while plays are running.
    QMutex _mutex;

    SystemState* _state;

    std::set<OurRobot*> _playRobots;

    Geometry2d::TransformMatrix _ballMatrix;
    Geometry2d::TransformMatrix _centerMatrix;
    Geometry2d::TransformMatrix _oppMatrix;

    /// Obstacles to prevent using half the field
    std::shared_ptr<Geometry2d::Polygon> _ourHalf;
    std::shared_ptr<Geometry2d::Polygon> _opponentHalf;

    std::shared_ptr<Geometry2d::Shape> _sideObstacle;

    /// outside of the floor boundaries
    std::shared_ptr<Geometry2d::Shape> _nonFloor[4];

    /// goal areas
    std::shared_ptr<Geometry2d::CompositeShape> _ourGoalArea;
    std::shared_ptr<Geometry2d::CompositeShape> _theirGoalArea;

    std::shared_ptr<Geometry2d::Polygon> _ourGoal;
    std::shared_ptr<Geometry2d::Polygon> _theirGoal;

    /// utility functions

    int _our_score_last_frame;

    // Shell ID of the robot to assign the goalie position
    int _goalieID;

    // python
    boost::python::object _mainPyNamespace;
};
}
<|endoftext|>


<commit_before>#include "mfile.h"
#include <iostream>
#include <chrono>
#include <random>

using namespace std;
using namespace std::chrono;

#define START_TEST(MESSAGE)\
void test_##MESSAGE()\
{\
    const char * message = "" #MESSAGE "";\
    MemoryMapped file("data.dat");\
    auto start = high_resolution_clock::now();\
    auto fileSize = file.size();

#define END_TEST\
    file.flush();\
    auto end = high_resolution_clock::now();\
    auto dur = duration_cast<milliseconds>(end - start).count();\
    std::cout << message << " time: " << dur << "ms" << std::endl;\
}

START_TEST(forward_read)
uint8_t x;
for (uint64_t c = 0; c < fileSize; ++c) {
    x = file[c];
}
END_TEST

START_TEST(backward_read)
uint8_t x;
for (uint64_t c = fileSize - 1; c > 0; --c) {
    x = file[c];
}
END_TEST

START_TEST(stride_forward_read)
uint8_t x;
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = 0; c + r < fileSize; c += MemoryMapped::pageSize) {
        x = file[c + r];
    }
}
END_TEST

START_TEST(stride_backward_read)
uint8_t x;
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = file.size() - 1; c - r > 0 && c - r < fileSize; c -= MemoryMapped::pageSize) {
        x = file[c - r];
    }
}
END_TEST

START_TEST(forward_write)
for (uint64_t c = 0; c < fileSize; ++c) {
    file[c] = c % 255;
}
END_TEST

START_TEST(backward_write)
uint8_t x;
for (uint64_t c = fileSize - 1; c > 0; --c) {
    file[c] = c % 255;
}
END_TEST

START_TEST(stride_forward_write)
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = 0; c + r < fileSize; c += MemoryMapped::pageSize) {
        file[c + r] = c % 255;
    }
}
END_TEST

START_TEST(stride_backward_write)
uint8_t x;
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = file.size() - 1; c - r > 0 && c - r < fileSize; c -= MemoryMapped::pageSize) {
        file[c - r] = c % 255;
    }
}
END_TEST

random_device dev;
mt19937 rnd(dev());

START_TEST(random_read_100000)
uniform_int_distribution<uint64_t> dist(0, fileSize - 1);
uint64_t x;
for (uint64_t c = 0; c < 100000; ++c) {
    x = file[dist(rnd)];
}
END_TEST

START_TEST(random_write_100000)
uniform_int_distribution<uint64_t> dist(0, fileSize - 1);
for (uint64_t c = 0; c < 100000; ++c) {
    file[dist(rnd)] = c % 255;
}
END_TEST

int main() {
    try {
        test_forward_read();
        test_backward_read();

        test_stride_forward_read();
        test_stride_backward_read();

        test_forward_write();
        test_backward_write();

        test_stride_forward_write();
        test_stride_backward_write();

        test_random_read_100000();
        test_random_write_100000();

    } catch (std::exception & e) {
        std::cerr << e.what() << std::endl;
    }

    std::cout << "done";

    return 0;
}
<commit_msg>Add random part to writes so we avoid optimization<commit_after>#include "mfile.h"
#include <iostream>
#include <chrono>
#include <random>

using namespace std;
using namespace std::chrono;

random_device dev;
mt19937 rnd(dev());

char writeSeed = dev() % 255;

#define START_TEST(MESSAGE)\
void test_##MESSAGE()\
{\
    const char * message = "" #MESSAGE "";\
    MemoryMapped file("data.dat");\
    auto start = high_resolution_clock::now();\
    auto fileSize = file.size();

#define END_TEST\
    file.flush();\
    auto end = high_resolution_clock::now();\
    auto dur = duration_cast<milliseconds>(end - start).count();\
    std::cout << message << " time: " << dur << "ms" << std::endl;\
}

START_TEST(forward_read)
uint8_t x;
for (uint64_t c = 0; c < fileSize; ++c) {
    x = file[c];
}
END_TEST

START_TEST(backward_read)
uint8_t x;
for (uint64_t c = fileSize - 1; c > 0; --c) {
    x = file[c];
}
END_TEST

START_TEST(stride_forward_read)
uint8_t x;
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = 0; c + r < fileSize; c += MemoryMapped::pageSize) {
        x = file[c + r];
    }
}
END_TEST

START_TEST(stride_backward_read)
uint8_t x;
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = file.size() - 1; c - r > 0 && c - r < fileSize; c -= MemoryMapped::pageSize) {
        x = file[c - r];
    }
}
END_TEST

START_TEST(forward_write)
for (uint64_t c = 0; c < fileSize; ++c) {
    file[c] = writeSeed + c;
}
END_TEST

START_TEST(backward_write)
uint8_t x;
for (uint64_t c = fileSize - 1; c > 0; --c) {
    file[c] = writeSeed + c;
}
END_TEST

START_TEST(stride_forward_write)
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = 0; c + r < fileSize; c += MemoryMapped::pageSize) {
        file[c + r] = writeSeed + c;
    }
}
END_TEST

START_TEST(stride_backward_write)
uint8_t x;
for (int r = 0; r < 10; ++r) {
    for (uint64_t c = file.size() - 1; c - r > 0 && c - r < fileSize; c -= MemoryMapped::pageSize) {
        file[c - r] = writeSeed + c;
    }
}
END_TEST

START_TEST(random_read_100000)
uniform_int_distribution<uint64_t> dist(0, fileSize - 1);
uint64_t x;
for (uint64_t c = 0; c < 100000; ++c) {
    x = file[dist(rnd)];
}
END_TEST

START_TEST(random_write_100000)
uniform_int_distribution<uint64_t> dist(0, fileSize - 1);
for (uint64_t c = 0; c < 100000; ++c) {
    file[dist(rnd)] = writeSeed + c;
}
END_TEST

int main() {
    try {
        test_forward_read();
        test_backward_read();

        test_stride_forward_read();
        test_stride_backward_read();

        test_forward_write();
        test_backward_write();

        test_stride_forward_write();
        test_stride_backward_write();

        test_random_read_100000();
        test_random_write_100000();

    } catch (std::exception & e) {
        std::cerr << e.what() << std::endl;
    }

    std::cout << "done";

    return 0;
}
<|endoftext|>


<commit_before>#include "global.h"

/*
Created by: Avery Reed on 2/14/17
Last Edited by: Avery Reed 2/14/17
*/

Global::Global() {
  setAnnotation(1);
  out("Global variables and functions initiated.\n");
}

Global::~Global() {
  out("Deconstructing global class.\n");
}
<commit_msg>Delete global.cpp<commit_after><|endoftext|>


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

 /**
  * @file HMC5883_I2C.cpp
  *
  * I2C interface for HMC5883 / HMC 5983
  */

/* XXX trim includes */
#include <nuttx/config.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <unistd.h>

#include <arch/board/board.h>

#include <drivers/device/i2c.h>
#include <drivers/drv_mag.h>
#include <drivers/drv_device.h>

#include "hmc5883.h"

#include "board_config.h"

#ifdef PX4_I2C_OBDEV_HMC5883

#define HMC5883L_ADDRESS		PX4_I2C_OBDEV_HMC5883

device::Device *HMC5883_I2C_interface(int bus);

class HMC5883_I2C : public device::I2C
{
public:
	HMC5883_I2C(int bus);
	virtual ~HMC5883_I2C();

	virtual int	init();
	virtual int	read(unsigned address, void *data, unsigned count);
	virtual int	write(unsigned address, void *data, unsigned count);

	virtual int	ioctl(unsigned operation, unsigned &arg);

protected:
	virtual int	probe();

};

device::Device *
HMC5883_I2C_interface(int bus)
{
	return new HMC5883_I2C(bus);
}

HMC5883_I2C::HMC5883_I2C(int bus) :
	I2C("HMC5883_I2C", nullptr, bus, HMC5883L_ADDRESS, 400000)
{
	_device_id.devid_s.devtype = DRV_MAG_DEVTYPE_HMC5883;
}

HMC5883_I2C::~HMC5883_I2C()
{
}

int
HMC5883_I2C::init()
{
	/* this will call probe() */
	return I2C::init();
}

int
HMC5883_I2C::ioctl(unsigned operation, unsigned &arg)
{
	int ret;

	switch (operation) {

	case MAGIOCGEXTERNAL:
		if (_bus == PX4_I2C_BUS_EXPANSION) {
			return 1;
		} else {
			return 0;
		}

	case DEVIOCGDEVICEID:
		return CDev::ioctl(nullptr, operation, arg);

	default:
		ret = -EINVAL;
	}

	return ret;
}

int
HMC5883_I2C::probe()
{
	uint8_t data[3] = {0, 0, 0};

	_retries = 10;

	if (read(ADDR_ID_A, &data[0], 1) ||
	    read(ADDR_ID_B, &data[1], 1) ||
	    read(ADDR_ID_C, &data[2], 1)) {
		debug("read_reg fail");
		return -EIO;
	}

	_retries = 2;

	if ((data[0] != ID_A_WHO_AM_I) ||
	    (data[1] != ID_B_WHO_AM_I) ||
	    (data[2] != ID_C_WHO_AM_I)) {
		debug("ID byte mismatch (%02x,%02x,%02x)", data[0], data[1], data[2]);
		return -EIO;
	}

	return OK;
}

int
HMC5883_I2C::write(unsigned address, void *data, unsigned count)
{
	uint8_t buf[32];

	if (sizeof(buf) < (count + 1)) {
		return -EIO;
	}

	buf[0] = address;
	memcpy(&buf[1], data, count);

	return transfer(&buf[0], count + 1, nullptr, 0);
}

int
HMC5883_I2C::read(unsigned address, void *data, unsigned count)
{
	uint8_t cmd = address;
	return transfer(&cmd, 1, (uint8_t *)data, count);
}

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

 /**
  * @file HMC5883_I2C.cpp
  *
  * I2C interface for HMC5883 / HMC 5983
  */

/* XXX trim includes */
#include <nuttx/config.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <unistd.h>

#include <arch/board/board.h>

#include <drivers/device/i2c.h>
#include <drivers/drv_mag.h>
#include <drivers/drv_device.h>

#include "hmc5883.h"

#include "board_config.h"

#ifdef PX4_I2C_OBDEV_HMC5883

#define HMC5883L_ADDRESS		PX4_I2C_OBDEV_HMC5883

device::Device *HMC5883_I2C_interface(int bus);

class HMC5883_I2C : public device::I2C
{
public:
	HMC5883_I2C(int bus);
	virtual ~HMC5883_I2C();

	virtual int	init();
	virtual int	read(unsigned address, void *data, unsigned count);
	virtual int	write(unsigned address, void *data, unsigned count);

	virtual int	ioctl(unsigned operation, unsigned &arg);

protected:
	virtual int	probe();

};

device::Device *
HMC5883_I2C_interface(int bus)
{
	return new HMC5883_I2C(bus);
}

HMC5883_I2C::HMC5883_I2C(int bus) :
	I2C("HMC5883_I2C", nullptr, bus, HMC5883L_ADDRESS, 400000)
{
	_device_id.devid_s.devtype = DRV_MAG_DEVTYPE_HMC5883;
}

HMC5883_I2C::~HMC5883_I2C()
{
}

int
HMC5883_I2C::init()
{
	/* this will call probe() */
	return I2C::init();
}

int
HMC5883_I2C::ioctl(unsigned operation, unsigned &arg)
{
	int ret;

	switch (operation) {

	case MAGIOCGEXTERNAL:
// On PX4v1 the MAG can be on an internal I2C
// On everything else its always external
#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
		if (_bus == PX4_I2C_BUS_EXPANSION) {
			return 1;
		} else {
			return 0;
		}
#else
                return 1;
#endif

	case DEVIOCGDEVICEID:
		return CDev::ioctl(nullptr, operation, arg);

	default:
		ret = -EINVAL;
	}

	return ret;
}

int
HMC5883_I2C::probe()
{
	uint8_t data[3] = {0, 0, 0};

	_retries = 10;

	if (read(ADDR_ID_A, &data[0], 1) ||
	    read(ADDR_ID_B, &data[1], 1) ||
	    read(ADDR_ID_C, &data[2], 1)) {
		debug("read_reg fail");
		return -EIO;
	}

	_retries = 2;

	if ((data[0] != ID_A_WHO_AM_I) ||
	    (data[1] != ID_B_WHO_AM_I) ||
	    (data[2] != ID_C_WHO_AM_I)) {
		debug("ID byte mismatch (%02x,%02x,%02x)", data[0], data[1], data[2]);
		return -EIO;
	}

	return OK;
}

int
HMC5883_I2C::write(unsigned address, void *data, unsigned count)
{
	uint8_t buf[32];

	if (sizeof(buf) < (count + 1)) {
		return -EIO;
	}

	buf[0] = address;
	memcpy(&buf[1], data, count);

	return transfer(&buf[0], count + 1, nullptr, 0);
}

int
HMC5883_I2C::read(unsigned address, void *data, unsigned count)
{
	uint8_t cmd = address;
	return transfer(&cmd, 1, (uint8_t *)data, count);
}

#endif /* PX4_I2C_OBDEV_HMC5883 */
<|endoftext|>