<commit_before>#include <pcl/filters/voxel_grid.h>
#include <pcl/io/pcd_io.h>
#include <pcl/octree/octree_search.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>
#include <pcl_ros/point_cloud.h>
#include <pcl_ros/transforms.h>
#include <ros/publisher.h>
#include <ros/ros.h>
#include <stdlib.h>
#include <string>

pcl::PointCloud<pcl::PointXYZRGB>::Ptr global_map;
ros::Publisher _pointcloud_pub;
ros::Publisher _pointcloud_prob_pub;
tf::TransformListener *tf_listener;
bool firstFrame;
double maxCorrDist;
int maxIter;
pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB>::Ptr octree;
double searchRadius;
double octree_resolution;
double probability_thresh;

std::list<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> pointcloud_list;
int queue_window_size;

void icp_transform(pcl::PointCloud<pcl::PointXYZRGB>::Ptr input)
{
  if (pointcloud_list.size() < queue_window_size)
  {
    pointcloud_list.push_back(input);
  }
  if (pointcloud_list.size() == queue_window_size)
  {
    // Probabilistic calculations here
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr local_pc =
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr(new pcl::PointCloud<pcl::PointXYZRGB>());
    pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB> local_octree(octree_resolution);

    local_octree.setInputCloud(local_pc);

    for (auto it = pointcloud_list.begin(); it != pointcloud_list.end(); it++)
    {
      for (auto point : (**it))
      {
        // G and B represent the probability, they are the same value
        // Add a point to the local octree if we haven't seen it before
        if (!local_octree.isVoxelOccupiedAtPoint(point))
        {
          point.r = 255;
          point.g = 0;
          point.b = 0;
          local_octree.addPointToCloud(point, local_pc);
        }
        else
        {
          // Increase probability of the point in the voxel if we see it again
          int point_idx;
          float dist;
          local_octree.approxNearestSearch(point, point_idx, dist);
          // If the probability is less than the threshold, increase the probability
          local_pc->points[point_idx].g = local_pc->points[point_idx].g + (int)(255.0 / queue_window_size);
          local_pc->points[point_idx].b = local_pc->points[point_idx].b + (int)(255.0 / queue_window_size);
          if (local_pc->points[point_idx].g >= probability_thresh * 255.0 &&
              !octree->isVoxelOccupiedAtPoint(local_pc->points[point_idx]))
          {
            // Add the point to the global map if its probability is greater than or equal to the threshold
            octree->addPointToCloud(local_pc->points[point_idx], global_map);
          }
        }
      }
    }

    (*local_pc).header.frame_id = "/odom";
    _pointcloud_prob_pub.publish(*local_pc);

    // Remove first pointcloud
    pointcloud_list.pop_front();
    std::cout << "Map size: " << global_map->size() << std::endl;
  }

  if (firstFrame && !input->points.empty())
  {
    octree->setInputCloud(global_map);
    for (unsigned int i = 0; i < input->size(); ++i)
    {
      pcl::PointXYZRGB searchPoint(255, 0, 0);
      searchPoint.x = input->points[i].x;
      searchPoint.y = input->points[i].y;
      searchPoint.z = input->points[i].z;

      if (!octree->isVoxelOccupiedAtPoint(searchPoint))
      {
        octree->addPointToCloud(searchPoint, global_map);
      }
    }
    firstFrame = false;
  }
}

void frame_callback(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &msg, const std::string &topic)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr transformed =
      pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>());
  tf::StampedTransform transform;
  if (tf_listener->waitForTransform("/odom", msg->header.frame_id, ros::Time(0), ros::Duration(5)))
  {
    tf_listener->lookupTransform("/odom", msg->header.frame_id, ros::Time(0), transform);
    pcl_ros::transformPointCloud(*msg, *transformed, transform);
    for (auto point : *transformed)
    {
      point.z = 0;
    }

    // Convert PointXYZ to PointXYZRGB
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed_rgb =
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr(new pcl::PointCloud<pcl::PointXYZRGB>());
    pcl::copyPointCloud(*transformed, *transformed_rgb);
    icp_transform(transformed_rgb);

    _pointcloud_pub.publish(global_map);
  }
  else
  {
    ROS_WARN_STREAM("Could not find transform to odom");
  }
}

int main(int argc, char **argv)
{
  global_map = pcl::PointCloud<pcl::PointXYZRGB>::Ptr(new pcl::PointCloud<pcl::PointXYZRGB>());

  ros::init(argc, argv, "global_mapper");
  ros::NodeHandle nh;
  tf_listener = new tf::TransformListener();

  std::string topics;
  std::list<ros::Subscriber> subs;

  ros::NodeHandle pNh("~");
  if (!pNh.hasParam("topics"))
    ROS_WARN_STREAM("No topics specified for mapper. No map will be generated.");

  pNh.getParam("topics", topics);
  pNh.getParam("max_correspondence_distance", maxCorrDist);
  pNh.getParam("max_iterations", maxIter);
  pNh.getParam("search_radius", searchRadius);
  pNh.getParam("octree_resolution", octree_resolution);
  pNh.getParam("queue_window_size", queue_window_size);
  pNh.getParam("probability_thresh", probability_thresh);
  if (topics.empty())
    ROS_WARN_STREAM("No topics specified for mapper. No map will be generated.");

  octree = pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB>::Ptr(
      new pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB>(octree_resolution));
  std::istringstream iss(topics);
  std::vector<std::string> tokens{ std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>() };

  for (auto topic : tokens)
  {
    ROS_INFO_STREAM("Mapper subscribing to " << topic);
    subs.push_back(nh.subscribe<pcl::PointCloud<pcl::PointXYZ>>(topic, 1, boost::bind(frame_callback, _1, topic)));
  }

  global_map->header.frame_id = "/odom";

  _pointcloud_pub = nh.advertise<pcl::PointCloud<pcl::PointXYZRGB>>("/map", 1);
  _pointcloud_prob_pub = nh.advertise<pcl::PointCloud<pcl::PointXYZRGB>>("/prob", 1);

  firstFrame = true;

  ros::spin();
}<commit_msg>Publishing map size and fixed comparison warning<commit_after>#include <pcl/filters/voxel_grid.h>
#include <pcl/io/pcd_io.h>
#include <pcl/octree/octree_search.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>
#include <pcl_ros/point_cloud.h>
#include <pcl_ros/transforms.h>
#include <ros/publisher.h>
#include <ros/ros.h>
#include <stdlib.h>
#include <string>
#include <std_msgs/Int64.h>

pcl::PointCloud<pcl::PointXYZRGB>::Ptr global_map;
ros::Publisher _pointcloud_pub;
ros::Publisher _pointcloud_prob_pub;
ros::Publisher _pointcloud_size_pub;
tf::TransformListener *tf_listener;
bool firstFrame;
double maxCorrDist;
int maxIter;
pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB>::Ptr octree;
double searchRadius;
double octree_resolution;
double probability_thresh;

std::list<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> pointcloud_list;
int queue_window_size;

void icp_transform(pcl::PointCloud<pcl::PointXYZRGB>::Ptr input)
{
  if (pointcloud_list.size() < (unsigned int) queue_window_size)
  {
    pointcloud_list.push_back(input);
  }
  if (pointcloud_list.size() == (unsigned int) queue_window_size)
  {
    // Probabilistic calculations here
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr local_pc =
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr(new pcl::PointCloud<pcl::PointXYZRGB>());
    pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB> local_octree(octree_resolution);

    local_octree.setInputCloud(local_pc);

    for (auto it = pointcloud_list.begin(); it != pointcloud_list.end(); it++)
    {
      for (auto point : (**it))
      {
        // G and B represent the probability, they are the same value
        // Add a point to the local octree if we haven't seen it before
        if (!local_octree.isVoxelOccupiedAtPoint(point))
        {
          point.r = 255;
          point.g = 0;
          point.b = 0;
          local_octree.addPointToCloud(point, local_pc);
        }
        else
        {
          // Increase probability of the point in the voxel if we see it again
          int point_idx;
          float dist;
          local_octree.approxNearestSearch(point, point_idx, dist);
          // If the probability is less than the threshold, increase the probability
          local_pc->points[point_idx].g = local_pc->points[point_idx].g + (int)(255.0 / queue_window_size);
          local_pc->points[point_idx].b = local_pc->points[point_idx].b + (int)(255.0 / queue_window_size);
          if (local_pc->points[point_idx].g >= probability_thresh * 255.0 &&
              !octree->isVoxelOccupiedAtPoint(local_pc->points[point_idx]))
          {
            // Add the point to the global map if its probability is greater than or equal to the threshold
            octree->addPointToCloud(local_pc->points[point_idx], global_map);
          }
        }
      }
    }

    (*local_pc).header.frame_id = "/odom";
    _pointcloud_prob_pub.publish(*local_pc);

    // Remove first pointcloud
    pointcloud_list.pop_front();

    // Publish map size
    std_msgs::Int64 size_msg;
    size_msg.data = global_map->size();
    _pointcloud_size_pub.publish(size_msg);
  }

  if (firstFrame && !input->points.empty())
  {
    octree->setInputCloud(global_map);
    for (unsigned int i = 0; i < input->size(); ++i)
    {
      pcl::PointXYZRGB searchPoint(255, 0, 0);
      searchPoint.x = input->points[i].x;
      searchPoint.y = input->points[i].y;
      searchPoint.z = input->points[i].z;

      if (!octree->isVoxelOccupiedAtPoint(searchPoint))
      {
        octree->addPointToCloud(searchPoint, global_map);
      }
    }
    firstFrame = false;
  }
}

void frame_callback(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &msg, const std::string &topic)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr transformed =
      pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>());
  tf::StampedTransform transform;
  if (tf_listener->waitForTransform("/odom", msg->header.frame_id, ros::Time(0), ros::Duration(5)))
  {
    tf_listener->lookupTransform("/odom", msg->header.frame_id, ros::Time(0), transform);
    pcl_ros::transformPointCloud(*msg, *transformed, transform);
    for (auto point : *transformed)
    {
      point.z = 0;
    }

    // Convert PointXYZ to PointXYZRGB
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed_rgb =
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr(new pcl::PointCloud<pcl::PointXYZRGB>());
    pcl::copyPointCloud(*transformed, *transformed_rgb);
    icp_transform(transformed_rgb);

    _pointcloud_pub.publish(global_map);
  }
  else
  {
    ROS_WARN_STREAM("Could not find transform to odom");
  }
}

int main(int argc, char **argv)
{
  global_map = pcl::PointCloud<pcl::PointXYZRGB>::Ptr(new pcl::PointCloud<pcl::PointXYZRGB>());

  ros::init(argc, argv, "global_mapper");
  ros::NodeHandle nh;
  tf_listener = new tf::TransformListener();

  std::string topics;
  std::list<ros::Subscriber> subs;

  ros::NodeHandle pNh("~");
  if (!pNh.hasParam("topics"))
    ROS_WARN_STREAM("No topics specified for mapper. No map will be generated.");

  pNh.getParam("topics", topics);
  pNh.getParam("max_correspondence_distance", maxCorrDist);
  pNh.getParam("max_iterations", maxIter);
  pNh.getParam("search_radius", searchRadius);
  pNh.getParam("octree_resolution", octree_resolution);
  pNh.getParam("queue_window_size", queue_window_size);
  pNh.getParam("probability_thresh", probability_thresh);
  if (topics.empty())
    ROS_WARN_STREAM("No topics specified for mapper. No map will be generated.");

  octree = pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB>::Ptr(
      new pcl::octree::OctreePointCloudSearch<pcl::PointXYZRGB>(octree_resolution));
  std::istringstream iss(topics);
  std::vector<std::string> tokens{ std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>() };

  for (auto topic : tokens)
  {
    ROS_INFO_STREAM("Mapper subscribing to " << topic);
    subs.push_back(nh.subscribe<pcl::PointCloud<pcl::PointXYZ>>(topic, 1, boost::bind(frame_callback, _1, topic)));
  }

  global_map->header.frame_id = "/odom";

  _pointcloud_pub = nh.advertise<pcl::PointCloud<pcl::PointXYZRGB>>("/map", 1);
  _pointcloud_prob_pub = nh.advertise<pcl::PointCloud<pcl::PointXYZRGB>>("/prob", 1);
  _pointcloud_size_pub = nh.advertise<std_msgs::Int64>("/map_size", 1);

  firstFrame = true;

  ros::spin();
}<|endoftext|>


<commit_before>/*
 * Copyright 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Box.h"

#include <jpeglib.h>
#include <png.h>
#include <stdio.h>

#include <GL/gl.h>

#include <boost/bind.hpp>

#include "utf.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

// image/png - 89 50 4E 47 0D 0A 1A 0A
// image/gif - "GIF87a" or "GIF89a"
// image/jpeg - FF D8
// image/bmp - "BM"
// image/vnd.microsoft.icon - 00 00 01 00 (.ico), 00 00 02 00 (.cur)

namespace {

unsigned char* readAsPng(FILE* file, unsigned& width, unsigned& height, unsigned& format)
{
    png_byte header[8];
    if (fread(header, 1, 8, file) != 8 || png_sig_cmp(header, 0, 8))
        return 0;

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
        return 0;
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 0;
    }
    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return 0;
    }
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return 0;
    }

    png_init_io(png_ptr, file);
    png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    unsigned bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    unsigned color_type = png_get_color_type(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
        color_type = GL_RGBA;
    }
    if (bit_depth == 16)
        png_set_strip_16(png_ptr);
    switch (color_type) {
    case PNG_COLOR_TYPE_RGB:
    case PNG_COLOR_TYPE_GRAY:
    case PNG_COLOR_TYPE_PALETTE:
        format = GL_RGB;
        break;
    default:
        format = GL_RGBA;
        break;
    }
    png_set_interlace_handling(png_ptr);

    png_read_update_info(png_ptr, info_ptr);

    unsigned rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    png_bytep data = (png_bytep) malloc(rowbytes * height);
    png_bytep* row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
    for (unsigned i = 0; i < height; i++)
        row_pointers[i] = &data[rowbytes * i];
    png_read_image(png_ptr, row_pointers);
    free(row_pointers);

    png_read_end(png_ptr, end_info);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

    return data;
}

unsigned char* readAsJpeg(FILE* file, unsigned& width, unsigned& height, unsigned& format)
{
    unsigned char sig[2];
    if (fread(sig, 1, 2, file) != 2 || sig[0] != 0xFF || sig[1] != 0xD8)
        return 0;
    rewind(file);

    JSAMPARRAY img;
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr);  // TODO: set our own error handdler
    jpeg_create_decompress(&cinfo);

    jpeg_stdio_src(&cinfo, file);
    jpeg_read_header(&cinfo, true);
    width = cinfo.image_width;
    height = cinfo.image_height;
    jpeg_start_decompress(&cinfo);

    unsigned char* data = (unsigned char*) malloc(height * width * cinfo.out_color_components);
    img = (JSAMPARRAY) malloc(sizeof(JSAMPROW) * height);
    for (unsigned i = 0; i < height; ++i)
        img[i] = (JSAMPROW) &data[cinfo.out_color_components * width * i];

    while(cinfo.output_scanline < cinfo.output_height)
        jpeg_read_scanlines(&cinfo,
                            img + cinfo.output_scanline,
                            cinfo.output_height - cinfo.output_scanline);
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    free(img);

    if (cinfo.out_color_components == 1)
        format = GL_LUMINANCE;
    else
        format = GL_RGB;
    return data;
}

}  // namespace

BoxImage::BoxImage(Box* box) :
    box(box),
    state(Unavailable),
    pixels(0),
    naturalWidth(0),
    naturalHeight(0),
    repeat(0),
    format(GL_RGBA),
    img(static_cast<html::HTMLImageElement*>(0) /* nullptr */)
{
}

BoxImage::BoxImage(Box* box, const std::u16string& base, const std::u16string& url, unsigned repeat) :
    box(box),
    state(Unavailable),
    pixels(0),
    naturalWidth(0),
    naturalHeight(0),
    repeat(repeat),
    format(GL_RGBA),
    img(static_cast<html::HTMLImageElement*>(0) /* nullptr */),
    request(base)
{
    open(url);
}

BoxImage::BoxImage(Box* box, const std::u16string& base, html::HTMLImageElement& img) :
    box(box),
    state(Unavailable),
    pixels(0),
    naturalWidth(0),
    naturalHeight(0),
    repeat(Clamp),
    format(GL_RGBA),
    img(img),
    request(base)
{
    open(img.getSrc());
}

void BoxImage::open(const std::u16string& url)
{
    request.open(u"GET", url);
    request.setHanndler(boost::bind(&BoxImage::notify, this));
    request.send();
    state = Sent;
    if (request.getReadyState() != HttpRequest::DONE)
        return;
    if (request.getErrorFlag()) {
        state = Broken;
        return;
    }
    FILE* file = request.openFile();
    if (!file) {
        state = Broken;
        return;
    }
    pixels = readAsPng(file, naturalWidth, naturalHeight, format);
    if (!pixels) {
        rewind(file);
        pixels = readAsJpeg(file, naturalWidth, naturalHeight, format);
    }
    if (pixels)
        state = CompletelyAvailable;
    else
        state = Broken;
    fclose(file);
}

void BoxImage::notify()
{
    if (state == Sent) {
        if (request.getStatus() == 200)
            box->flags = 1;  // for updating render tree.
        else
            state = Unavailable;
    }
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(readAsPng) : Support grayscale images of less than 8 bit depths.<commit_after>/*
 * Copyright 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Box.h"

#include <jpeglib.h>
#include <png.h>
#include <stdio.h>

#include <GL/gl.h>

#include <boost/bind.hpp>

#include "utf.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

// image/png - 89 50 4E 47 0D 0A 1A 0A
// image/gif - "GIF87a" or "GIF89a"
// image/jpeg - FF D8
// image/bmp - "BM"
// image/vnd.microsoft.icon - 00 00 01 00 (.ico), 00 00 02 00 (.cur)

namespace {

unsigned char* readAsPng(FILE* file, unsigned& width, unsigned& height, unsigned& format)
{
    png_byte header[8];
    if (fread(header, 1, 8, file) != 8 || png_sig_cmp(header, 0, 8))
        return 0;

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
        return 0;
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 0;
    }
    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return 0;
    }
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return 0;
    }

    png_init_io(png_ptr, file);
    png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    unsigned bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    unsigned color_type = png_get_color_type(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_gray_1_2_4_to_8(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
        color_type = GL_RGBA;
    }
    if (bit_depth == 16)
        png_set_strip_16(png_ptr);
    switch (color_type) {
    case PNG_COLOR_TYPE_RGB:
    case PNG_COLOR_TYPE_GRAY:
    case PNG_COLOR_TYPE_PALETTE:
        format = GL_RGB;
        break;
    default:
        format = GL_RGBA;
        break;
    }
    png_set_interlace_handling(png_ptr);

    png_read_update_info(png_ptr, info_ptr);

    unsigned rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    png_bytep data = (png_bytep) malloc(rowbytes * height);
    png_bytep* row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
    for (unsigned i = 0; i < height; i++)
        row_pointers[i] = &data[rowbytes * i];
    png_read_image(png_ptr, row_pointers);
    free(row_pointers);

    png_read_end(png_ptr, end_info);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

    return data;
}

unsigned char* readAsJpeg(FILE* file, unsigned& width, unsigned& height, unsigned& format)
{
    unsigned char sig[2];
    if (fread(sig, 1, 2, file) != 2 || sig[0] != 0xFF || sig[1] != 0xD8)
        return 0;
    rewind(file);

    JSAMPARRAY img;
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr);  // TODO: set our own error handdler
    jpeg_create_decompress(&cinfo);

    jpeg_stdio_src(&cinfo, file);
    jpeg_read_header(&cinfo, true);
    width = cinfo.image_width;
    height = cinfo.image_height;
    jpeg_start_decompress(&cinfo);

    unsigned char* data = (unsigned char*) malloc(height * width * cinfo.out_color_components);
    img = (JSAMPARRAY) malloc(sizeof(JSAMPROW) * height);
    for (unsigned i = 0; i < height; ++i)
        img[i] = (JSAMPROW) &data[cinfo.out_color_components * width * i];

    while(cinfo.output_scanline < cinfo.output_height)
        jpeg_read_scanlines(&cinfo,
                            img + cinfo.output_scanline,
                            cinfo.output_height - cinfo.output_scanline);
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    free(img);

    if (cinfo.out_color_components == 1)
        format = GL_LUMINANCE;
    else
        format = GL_RGB;
    return data;
}

}  // namespace

BoxImage::BoxImage(Box* box) :
    box(box),
    state(Unavailable),
    pixels(0),
    naturalWidth(0),
    naturalHeight(0),
    repeat(0),
    format(GL_RGBA),
    img(static_cast<html::HTMLImageElement*>(0) /* nullptr */)
{
}

BoxImage::BoxImage(Box* box, const std::u16string& base, const std::u16string& url, unsigned repeat) :
    box(box),
    state(Unavailable),
    pixels(0),
    naturalWidth(0),
    naturalHeight(0),
    repeat(repeat),
    format(GL_RGBA),
    img(static_cast<html::HTMLImageElement*>(0) /* nullptr */),
    request(base)
{
    open(url);
}

BoxImage::BoxImage(Box* box, const std::u16string& base, html::HTMLImageElement& img) :
    box(box),
    state(Unavailable),
    pixels(0),
    naturalWidth(0),
    naturalHeight(0),
    repeat(Clamp),
    format(GL_RGBA),
    img(img),
    request(base)
{
    open(img.getSrc());
}

void BoxImage::open(const std::u16string& url)
{
    request.open(u"GET", url);
    request.setHanndler(boost::bind(&BoxImage::notify, this));
    request.send();
    state = Sent;
    if (request.getReadyState() != HttpRequest::DONE)
        return;
    if (request.getErrorFlag()) {
        state = Broken;
        return;
    }
    FILE* file = request.openFile();
    if (!file) {
        state = Broken;
        return;
    }
    pixels = readAsPng(file, naturalWidth, naturalHeight, format);
    if (!pixels) {
        rewind(file);
        pixels = readAsJpeg(file, naturalWidth, naturalHeight, format);
    }
    if (pixels)
        state = CompletelyAvailable;
    else
        state = Broken;
    fclose(file);
}

void BoxImage::notify()
{
    if (state == Sent) {
        if (request.getStatus() == 200)
            box->flags = 1;  // for updating render tree.
        else
            state = Unavailable;
    }
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>/* Copyright 2019 Andrei Khodko
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "utilities.h"

#include "QsLog.h"

using namespace trikControl;

QImage  Utilities::imageFromBytes(const QVector<int32_t> &array, int width, int height, const QString &format){
	// QImage requires 32-bit aligned scan lines
	// Helper function to convert data
	uchar *formattedData = nullptr;
	auto copyAligned = [&](int perLine){
		const auto realSize = perLine * height;
		if (realSize > array.size()) {
			QLOG_WARN() << "imageFromBytes: not enough data";
			return;
		}
		auto scanLineSize = static_cast<int>((static_cast<unsigned>(perLine + 3)) & 0xFFFFFFFC);
		auto dst = formattedData = new uchar[scanLineSize * height];
		for (auto src = array.begin(); src < array.begin() + realSize; src += perLine) {
			dst = std::copy(src, src + perLine, dst);
			dst += scanLineSize - perLine;
		}
	};

	auto fmt = QImage::Format_Invalid;

	if (!format.compare("rgb32", Qt::CaseInsensitive)) {
		const auto imageSize = width * height;
		fmt = QImage::Format_RGB32;
		if (imageSize <= array.size()) {
			formattedData = new uchar[imageSize * 4];
			auto dstPtr = static_cast<int32_t *>(static_cast<void *>(formattedData));
			std::copy(array.begin(), array.begin() + imageSize, dstPtr);
		}
	} else if (!format.compare("rgb888", Qt::CaseInsensitive)) {
		fmt = QImage::Format_RGB888;
		copyAligned(3 * width);
	} else if (format == "grayscale8") {
		fmt = QImage::Format_Grayscale8;
		copyAligned(1 * width);
	} else {
		QLOG_WARN() << "imageFromBytes: Unsupported format " << format;
	}

	if (!formattedData) {
		return QImage();
	} else {
		static auto cleanUp = [](void *p) { if (p) delete [](static_cast<decltype (formattedData)>(p)); };
		return QImage(formattedData, width, height, fmt, cleanUp, formattedData);
	}
}

static inline int32_t getMedian(uint8_t &a, uint8_t &b, uint8_t &c, uint8_t &d)
{
	if (a > b)
		std::swap(a, b);
	if (c > d)
		std::swap(c, d);
	if (a > c)
		std::swap(a, c);
	if (b > d)
		std::swap(b, d);
	return (static_cast<int32_t>(b) + c) >> 1;
}

QVector<int32_t> Utilities::rescalePhoto(const QVector<uchar> &data)
{
	QVector<int32_t> result;
	result.reserve(data.size() / 3); //Repack RGB88 from 3 x uint8_t into int32_t
	constexpr auto IMAGE_WIDTH = 320;
	constexpr auto IMAGE_HEIGHT = 240;
	if (data.size() >= IMAGE_WIDTH * IMAGE_HEIGHT * 3) {
		for(int row = 0; row < IMAGE_HEIGHT; row += 2) {
			for(int col = 0; col < IMAGE_WIDTH; col += 2) {
				auto row1 = &data[(row * IMAGE_WIDTH + col) * 3];
				auto row2 = row1 + IMAGE_WIDTH * 3;
				auto r1 = row1[0];
				auto g1 = row1[1];
				auto b1 = row1[2];
				auto r2 = row1[3];
				auto g2 = row1[4];
				auto b2 = row1[5];
				auto r3 = row2[0];
				auto g3 = row2[1];
				auto b3 = row2[2];
				auto r4 = row2[3];
				auto g4 = row2[4];
				auto b4 = row2[5];

				result.push_back((getMedian(r1, r2, r3, r4) << 16)
					| (getMedian(g1, g2, g3, g4) << 8)
					| getMedian(b1, b2, b3, b4));
			}
		}
	}

	return result;
}
<commit_msg>Support greyscale8 name (#580)<commit_after>/* Copyright 2019 Andrei Khodko
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "utilities.h"

#include "QsLog.h"

using namespace trikControl;

QImage  Utilities::imageFromBytes(const QVector<int32_t> &array, int width, int height, const QString &format){
	// QImage requires 32-bit aligned scan lines
	// Helper function to convert data
	uchar *formattedData = nullptr;
	auto copyAligned = [&](int perLine){
		const auto realSize = perLine * height;
		if (realSize > array.size()) {
			QLOG_WARN() << "imageFromBytes: not enough data";
			return;
		}
		auto scanLineSize = static_cast<int>((static_cast<unsigned>(perLine + 3)) & 0xFFFFFFFC);
		auto dst = formattedData = new uchar[scanLineSize * height];
		for (auto src = array.begin(); src < array.begin() + realSize; src += perLine) {
			dst = std::copy(src, src + perLine, dst);
			dst += scanLineSize - perLine;
		}
	};

	auto fmt = QImage::Format_Invalid;

	if (!format.compare("rgb32", Qt::CaseInsensitive)) {
		const auto imageSize = width * height;
		fmt = QImage::Format_RGB32;
		if (imageSize <= array.size()) {
			formattedData = new uchar[imageSize * 4];
			auto dstPtr = static_cast<int32_t *>(static_cast<void *>(formattedData));
			std::copy(array.begin(), array.begin() + imageSize, dstPtr);
		}
	} else if (!format.compare("rgb888", Qt::CaseInsensitive)) {
		fmt = QImage::Format_RGB888;
		copyAligned(3 * width);
	} else if (format == "grayscale8" || format == "greyscale8") {
		fmt = QImage::Format_Grayscale8;
		copyAligned(1 * width);
	} else {
		QLOG_WARN() << "imageFromBytes: Unsupported format " << format;
	}

	if (!formattedData) {
		return QImage();
	} else {
		static auto cleanUp = [](void *p) { if (p) delete [](static_cast<decltype (formattedData)>(p)); };
		return QImage(formattedData, width, height, fmt, cleanUp, formattedData);
	}
}

static inline int32_t getMedian(uint8_t &a, uint8_t &b, uint8_t &c, uint8_t &d)
{
	if (a > b)
		std::swap(a, b);
	if (c > d)
		std::swap(c, d);
	if (a > c)
		std::swap(a, c);
	if (b > d)
		std::swap(b, d);
	return (static_cast<int32_t>(b) + c) >> 1;
}

QVector<int32_t> Utilities::rescalePhoto(const QVector<uchar> &data)
{
	QVector<int32_t> result;
	result.reserve(data.size() / 3); //Repack RGB88 from 3 x uint8_t into int32_t
	constexpr auto IMAGE_WIDTH = 320;
	constexpr auto IMAGE_HEIGHT = 240;
	if (data.size() >= IMAGE_WIDTH * IMAGE_HEIGHT * 3) {
		for(int row = 0; row < IMAGE_HEIGHT; row += 2) {
			for(int col = 0; col < IMAGE_WIDTH; col += 2) {
				auto row1 = &data[(row * IMAGE_WIDTH + col) * 3];
				auto row2 = row1 + IMAGE_WIDTH * 3;
				auto r1 = row1[0];
				auto g1 = row1[1];
				auto b1 = row1[2];
				auto r2 = row1[3];
				auto g2 = row1[4];
				auto b2 = row1[5];
				auto r3 = row2[0];
				auto g3 = row2[1];
				auto b3 = row2[2];
				auto r4 = row2[3];
				auto g4 = row2[4];
				auto b4 = row2[5];

				result.push_back((getMedian(r1, r2, r3, r4) << 16)
					| (getMedian(g1, g2, g3, g4) << 8)
					| getMedian(b1, b2, b3, b4));
			}
		}
	}

	return result;
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <gflags/gflags.h>
#include <set>
#include <boost/algorithm/string.hpp>
#include "sort_file.h"
#include "logging.h"
#include "filesystem.h"
#include "common/tools_util.h"

DEFINE_int32(total, 0, "total numbers of map tasks");
DEFINE_int32(reduce_no, 0, "the reduce number of this reduce task");
DEFINE_string(work_dir, "/tmp", "the shuffle work dir");
DEFINE_int32(batch, 100, "merge how many maps output at the same time");
DEFINE_int32(attempt_id, 0, "the attempt_id of this reduce task");

using baidu::common::Log;
using baidu::common::FATAL;
using baidu::common::INFO;
using baidu::common::WARNING;
using namespace baidu::shuttle;

std::set<std::string> g_merged;
int32_t g_file_no(0);
FileSystem* g_fs(NULL);

void CollectFilesToMerge(std::vector<std::string>* maps_to_merge) {
    assert(maps_to_merge);
    std::vector<std::string> children;
    bool ok = g_fs->List(FLAGS_work_dir, &children);
    if (!ok) {
        return;
    }
    std::vector<std::string>::iterator it;
    for (it = children.begin(); it != children.end(); it++) {
        const std::string& file_name = *it;
        if (file_name.find("_temporary/shuffle/map_") != std::string::npos &&
            g_merged.find(file_name) == g_merged.end()) {
            LOG(INFO, "maps_to_merge: %s", file_name.c_str());
            maps_to_merge->push_back(file_name);
        }
    }
}

void MergeMapOutput(const std::vector<std::string>& maps_to_merge) {
    std::vector<std::string> file_names;
    std::vector<std::string>::const_iterator it;
    std::vector<std::string>::iterator jt;
    std::vector<std::string> real_merged_maps;
    int map_ct = 0;
    for (it = maps_to_merge.begin(); it != maps_to_merge.end(); it++) {
        const std::string& map_dir = *it;
        std::vector<std::string> sort_files;
        if (g_fs->List(map_dir, &sort_files)) {
            for (jt = sort_files.begin(); jt != sort_files.end(); jt++) {
                const std::string& file_name = *jt;
                if (boost::ends_with(file_name, ".sort")) {
                    file_names.push_back(file_name);
                }
            }
        } else {
            LOG(FATAL, "fail to list %s", map_dir.c_str());
        }
        map_ct++;
        real_merged_maps.push_back(map_dir);
        if (map_ct >= FLAGS_batch){
            break;
        }
    }
    if (file_names.empty()) {
        LOG(WARNING, "not map output found");
        return;
    }
    MergeFileReader reader;
    FileSystem::Param param;
    Status status = reader.Open(file_names, param, kHdfsFile);
    if (status != kOk) {
        LOG(FATAL, "fail to open: %s", reader.GetErrorFile().c_str());
    }
    char s_reduce_no[256];
    snprintf(s_reduce_no, sizeof(s_reduce_no), "%05d", FLAGS_reduce_no);
    std::string s_reduce_key(s_reduce_no);

    SortFileReader::Iterator* scan_it = reader.Scan(s_reduce_key,
                                                     s_reduce_key + "\xff");
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }

    char output_file[4096];
    snprintf(output_file, sizeof(output_file), "%s/reduce_%d_%d/%d.sort",
             FLAGS_work_dir.c_str(), FLAGS_reduce_no, FLAGS_attempt_id,
             g_file_no++);
    SortFileWriter * writer = SortFileWriter::Create(kHdfsFile, &status);
    if (status != kOk) {
        LOG(FATAL, "fail to create writer");
    }
    FileSystem::Param param_write;
    param_write["replica"] = "2";
    status = writer->Open(output_file, param_write);
    if (status != kOk) {
        LOG(FATAL, "fail to open %s for write", output_file);
    }
    while (!scan_it->Done()) {
        status = writer->Put(scan_it->Key(), scan_it->Value());
        if (status != kOk) {
            LOG(FATAL, "fail to put: %s", output_file);
        }
        scan_it->Next();
    }
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }
    status = writer->Close();
    if (status != kOk) {
        LOG(FATAL, "fail to close: %s", output_file);
    }
    reader.Close();
    delete writer;
    for (it = real_merged_maps.begin(); it != real_merged_maps.end(); it++) {
        LOG(INFO, "g_merged insert: %s", it->c_str());
        g_merged.insert(*it);
    }
}

void MergeAndPrint() {
    char reduce_merge_dir[4096];
    snprintf(reduce_merge_dir, sizeof(reduce_merge_dir),
             "%s/reduce_%d_%d",
             FLAGS_work_dir.c_str(), FLAGS_reduce_no, FLAGS_attempt_id);
    std::vector<std::string> children;
    if (!g_fs->List(reduce_merge_dir, &children)) {
        LOG(FATAL, "fail to list: %s", reduce_merge_dir);
    }
    std::vector<std::string> file_names;
    std::vector<std::string>::iterator it;
    for (it = children.begin(); it != children.end(); it++) {
        const std::string& file_name = *it;
        if (boost::ends_with(file_name, ".sort")) {
            file_names.push_back(file_name);
        }
    }
    if (file_names.empty()) {
        LOG(WARNING, "no data for this reduce task");
        return;
    }
    MergeFileReader reader;
    FileSystem::Param param;
    Status status = reader.Open(file_names, param, kHdfsFile);
    if (status != kOk) {
        LOG(FATAL, "fail to open: %s", reader.GetErrorFile().c_str());
    }
    SortFileReader::Iterator* scan_it = reader.Scan("", "");
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }
    while (!scan_it->Done()) {
        std::cout << scan_it->Value() << std::endl;
        scan_it->Next();
    }
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }
    reader.Close();
}

int main(int argc, char* argv[]) {
    baidu::common::SetLogFile(GetLogName("./shuffle_tool.log").c_str());
    baidu::common::SetWarningFile(GetLogName("./shuffle_tool.log.wf").c_str());
    google::ParseCommandLineFlags(&argc, &argv, true);
    FileSystem::Param param;
    g_fs = FileSystem::CreateInfHdfs(param);
    if (FLAGS_total == 0 ) {
        LOG(FATAL, "invalid map task total");
    }
    while ((int32_t)g_merged.size() < FLAGS_total) {
        std::vector<std::string> maps_to_merge;
        CollectFilesToMerge(&maps_to_merge);
        if (maps_to_merge.size() >= (size_t)FLAGS_batch ||
            maps_to_merge.size() + g_merged.size() >= (size_t)FLAGS_total) {
            MergeMapOutput(maps_to_merge);
        }
        sleep(3);
    }
    MergeAndPrint();
    return 0;
}
<commit_msg>add progress log for shuffle merge<commit_after>#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <gflags/gflags.h>
#include <set>
#include <boost/algorithm/string.hpp>
#include "sort_file.h"
#include "logging.h"
#include "filesystem.h"
#include "common/tools_util.h"

DEFINE_int32(total, 0, "total numbers of map tasks");
DEFINE_int32(reduce_no, 0, "the reduce number of this reduce task");
DEFINE_string(work_dir, "/tmp", "the shuffle work dir");
DEFINE_int32(batch, 100, "merge how many maps output at the same time");
DEFINE_int32(attempt_id, 0, "the attempt_id of this reduce task");

using baidu::common::Log;
using baidu::common::FATAL;
using baidu::common::INFO;
using baidu::common::WARNING;
using namespace baidu::shuttle;

std::set<std::string> g_merged;
int32_t g_file_no(0);
FileSystem* g_fs(NULL);

void CollectFilesToMerge(std::vector<std::string>* maps_to_merge) {
    assert(maps_to_merge);
    std::vector<std::string> children;
    bool ok = g_fs->List(FLAGS_work_dir, &children);
    if (!ok) {
        return;
    }
    std::vector<std::string>::iterator it;
    for (it = children.begin(); it != children.end(); it++) {
        const std::string& file_name = *it;
        if (file_name.find("_temporary/shuffle/map_") != std::string::npos &&
            g_merged.find(file_name) == g_merged.end()) {
            LOG(INFO, "maps_to_merge: %s", file_name.c_str());
            maps_to_merge->push_back(file_name);
        }
    }
}

void MergeMapOutput(const std::vector<std::string>& maps_to_merge) {
    std::vector<std::string> file_names;
    std::vector<std::string>::const_iterator it;
    std::vector<std::string>::iterator jt;
    std::vector<std::string> real_merged_maps;
    int map_ct = 0;
    for (it = maps_to_merge.begin(); it != maps_to_merge.end(); it++) {
        const std::string& map_dir = *it;
        std::vector<std::string> sort_files;
        if (g_fs->List(map_dir, &sort_files)) {
            for (jt = sort_files.begin(); jt != sort_files.end(); jt++) {
                const std::string& file_name = *jt;
                if (boost::ends_with(file_name, ".sort")) {
                    file_names.push_back(file_name);
                }
            }
        } else {
            LOG(FATAL, "fail to list %s", map_dir.c_str());
        }
        map_ct++;
        real_merged_maps.push_back(map_dir);
        if (map_ct >= FLAGS_batch){
            break;
        }
    }
    if (file_names.empty()) {
        LOG(WARNING, "not map output found");
        return;
    }
    MergeFileReader reader;
    FileSystem::Param param;
    Status status = reader.Open(file_names, param, kHdfsFile);
    if (status != kOk) {
        LOG(FATAL, "fail to open: %s", reader.GetErrorFile().c_str());
    }
    char s_reduce_no[256];
    snprintf(s_reduce_no, sizeof(s_reduce_no), "%05d", FLAGS_reduce_no);
    std::string s_reduce_key(s_reduce_no);

    SortFileReader::Iterator* scan_it = reader.Scan(s_reduce_key,
                                                     s_reduce_key + "\xff");
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }

    char output_file[4096];
    snprintf(output_file, sizeof(output_file), "%s/reduce_%d_%d/%d.sort",
             FLAGS_work_dir.c_str(), FLAGS_reduce_no, FLAGS_attempt_id,
             g_file_no++);
    SortFileWriter * writer = SortFileWriter::Create(kHdfsFile, &status);
    if (status != kOk) {
        LOG(FATAL, "fail to create writer");
    }
    FileSystem::Param param_write;
    param_write["replica"] = "2";
    status = writer->Open(output_file, param_write);
    if (status != kOk) {
        LOG(FATAL, "fail to open %s for write", output_file);
    }
    while (!scan_it->Done()) {
        status = writer->Put(scan_it->Key(), scan_it->Value());
        if (status != kOk) {
            LOG(FATAL, "fail to put: %s", output_file);
        }
        scan_it->Next();
    }
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }
    status = writer->Close();
    if (status != kOk) {
        LOG(FATAL, "fail to close: %s", output_file);
    }
    reader.Close();
    delete writer;
    for (it = real_merged_maps.begin(); it != real_merged_maps.end(); it++) {
        LOG(INFO, "g_merged insert: %s", it->c_str());
        g_merged.insert(*it);
    }
}

void MergeAndPrint() {
    char reduce_merge_dir[4096];
    snprintf(reduce_merge_dir, sizeof(reduce_merge_dir),
             "%s/reduce_%d_%d",
             FLAGS_work_dir.c_str(), FLAGS_reduce_no, FLAGS_attempt_id);
    std::vector<std::string> children;
    if (!g_fs->List(reduce_merge_dir, &children)) {
        LOG(FATAL, "fail to list: %s", reduce_merge_dir);
    }
    std::vector<std::string> file_names;
    std::vector<std::string>::iterator it;
    for (it = children.begin(); it != children.end(); it++) {
        const std::string& file_name = *it;
        if (boost::ends_with(file_name, ".sort")) {
            file_names.push_back(file_name);
        }
    }
    if (file_names.empty()) {
        LOG(WARNING, "no data for this reduce task");
        return;
    }
    MergeFileReader reader;
    FileSystem::Param param;
    Status status = reader.Open(file_names, param, kHdfsFile);
    if (status != kOk) {
        LOG(FATAL, "fail to open: %s", reader.GetErrorFile().c_str());
    }
    SortFileReader::Iterator* scan_it = reader.Scan("", "");
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }
    while (!scan_it->Done()) {
        std::cout << scan_it->Value() << std::endl;
        scan_it->Next();
    }
    if (scan_it->Error() != kOk && scan_it->Error() != kNoMore) {
        LOG(FATAL, "fail to scan: %s", reader.GetErrorFile().c_str());
    }
    reader.Close();
}

int main(int argc, char* argv[]) {
    baidu::common::SetLogFile(GetLogName("./shuffle_tool.log").c_str());
    baidu::common::SetWarningFile(GetLogName("./shuffle_tool.log.wf").c_str());
    google::ParseCommandLineFlags(&argc, &argv, true);
    FileSystem::Param param;
    g_fs = FileSystem::CreateInfHdfs(param);
    if (FLAGS_total == 0 ) {
        LOG(FATAL, "invalid map task total");
    }
    while ((int32_t)g_merged.size() < FLAGS_total) {
        std::vector<std::string> maps_to_merge;
        CollectFilesToMerge(&maps_to_merge);
        if (maps_to_merge.size() >= (size_t)FLAGS_batch ||
            maps_to_merge.size() + g_merged.size() >= (size_t)FLAGS_total) {
            MergeMapOutput(maps_to_merge);
        }
        sleep(3);
        LOG(INFO, "merge progress: < %d/%d > ", g_merged.size(), FLAGS_total);
    }
    MergeAndPrint();
    return 0;
}
<|endoftext|>


<commit_before>#include <QApplication>
#include <QSettings>
#include <QIcon>

#include <QDebug>

#include "appcontroller.h"
#include "appwindow.h"
#include "secondarywindow.h"
#include "widgets/librarywidget.h"
#include "widgets/secondary/loginwidget.h"
#include "widgets/secondary/settingswidget.h"

AppController::AppController(QObject* parent)
    : QObject(parent)
    , settingsWindow(NULL)
    , loginWithApiKey(false)
{
    setupSettings();
    api = new ItchioApi(this, settings->apiUrl());

    setupTrayIcon();
    setupAppWindow();

    if (settings->autoLogin() && settings->hasValidApiKey()) {
        api->loginWithApiKey(settings->apiKey(), [this](bool success, QString err) {
            if (success) {
                onLogin();
            } else {
                onAutoLoginFailure(err);
            }
        });

        loginWithApiKey = true;
    } else {
        setupLogin();
    }
}

void AppController::setupSettings()
{
    settingsFile = QCoreApplication::applicationDirPath() + "/itchio.ini";
    settings = new AppSettings(settingsFile, QSettings::IniFormat, this);
}

void AppController::quit()
{
    settings->enableStartMaximized(appWindow->isMaximized);
    settings->setWindowGeometry(appWindow->saveGeometry());
    settings->setWindowOldSize(appWindow->oldSize);
    settings->setWindowOldPosition(appWindow->oldPosition);

    if (settings->autoLogin()) {
        settings->setApiKey(api->userKey);
        settings->setUsername(api->userName);
    }

    QCoreApplication::exit();
}

void AppController::showSettings()
{
    settingsWindow = new SecondaryWindow(new SettingsWidget(this), this);

    settingsWindow->show();
    settingsWindow->raise();
}

void AppController::trayIconDoubleClick(QSystemTrayIcon::ActivationReason reason)
{
    if (reason == QSystemTrayIcon::DoubleClick && !appWindow->isVisible()) {
        appWindow->showWindow();
    }
}

void AppController::setupTrayIcon()
{
    trayIcon = new QSystemTrayIcon(this);

    trayIcon->setIcon(QIcon(":/images/images/itchio-icon-16.png"));
    trayIcon->show();
}

void AppController::setupTrayIconMenu(bool beforeLogin)
{
    trayIconMenu = new QMenu();
    trayIcon->setContextMenu(trayIconMenu);

    if (!beforeLogin) {
        QAction* actionSettings = new QAction("Settings", this);
        trayIconMenu->addAction(actionSettings);
        connect(actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));

        trayIconMenu->addSeparator();
    }

    QAction* actionQuit = new QAction("Quit", this);
    trayIconMenu->addAction(actionQuit);
    connect(actionQuit, SIGNAL(triggered()), this, SLOT(quit()));

    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(trayIconDoubleClick(QSystemTrayIcon::ActivationReason)));
}

void AppController::showTrayIconNotification(TrayNotifications::Notifications notification, QString data)
{
    if (settings->showTrayNotifications()) {
        if((notification == TrayNotifications::LIBRARY_UPDATE &&
            settings->showLibraryUpdateNotifications()) ||
                (notification == TrayNotifications::DOWNLOAD_FINISHED &&
                 settings->showDownloadFinishedNotifications()) ||
                (notification == TrayNotifications::GAME_UPDATE_AVAILABLE &&
                 settings->showGameUpdateAvailableNotifications())){

            trayIcon->showMessage(TrayNotifications::toString(notification),
                                  data, QSystemTrayIcon::NoIcon, 5000);
        }

    }
}

void AppController::setupLogin()
{
    settings->setApiKey("");
    api->userKey = "";

    setupTrayIconMenu(true);

    loginWindow = new SecondaryWindow(new LoginWidget(qobject_cast<QWidget*>(this), this), this);
    loginWindow->show();
}

void AppController::setupAppWindow()
{
    appWindow = new AppWindow(this);
}

void AppController::onLogin()
{
    setupTrayIconMenu();

    if (!loginWithApiKey) {
        loginWindow->deleteLater();
        loginWindow->close();
    }

    appWindow->setupLibrary();
}

void AppController::onAutoLoginFailure(QString)
{
    setupLogin();
}
<commit_msg>Fixed possibility of opening multiple settings windows.<commit_after>#include <QApplication>
#include <QSettings>
#include <QIcon>

#include <QDebug>

#include "appcontroller.h"
#include "appwindow.h"
#include "secondarywindow.h"
#include "widgets/librarywidget.h"
#include "widgets/secondary/loginwidget.h"
#include "widgets/secondary/settingswidget.h"

AppController::AppController(QObject* parent)
    : QObject(parent)
    , settingsWindow(NULL)
    , loginWithApiKey(false)
{
    setupSettings();
    api = new ItchioApi(this, settings->apiUrl());

    setupTrayIcon();
    setupAppWindow();

    if (settings->autoLogin() && settings->hasValidApiKey()) {
        api->loginWithApiKey(settings->apiKey(), [this](bool success, QString err) {
            if (success) {
                onLogin();
            } else {
                onAutoLoginFailure(err);
            }
        });

        loginWithApiKey = true;
    } else {
        setupLogin();
    }
}

void AppController::setupSettings()
{
    settingsFile = QCoreApplication::applicationDirPath() + "/itchio.ini";
    settings = new AppSettings(settingsFile, QSettings::IniFormat, this);
}

void AppController::quit()
{
    settings->enableStartMaximized(appWindow->isMaximized);
    settings->setWindowGeometry(appWindow->saveGeometry());
    settings->setWindowOldSize(appWindow->oldSize);
    settings->setWindowOldPosition(appWindow->oldPosition);

    if (settings->autoLogin()) {
        settings->setApiKey(api->userKey);
        settings->setUsername(api->userName);
    }

    QCoreApplication::exit();
}

void AppController::showSettings()
{
    if(settingsWindow != NULL){
        settingsWindow->hide();
        settingsWindow->close();
    }

    settingsWindow = new SecondaryWindow(new SettingsWidget(this), this);

    settingsWindow->show();
}

void AppController::trayIconDoubleClick(QSystemTrayIcon::ActivationReason reason)
{
    if (reason == QSystemTrayIcon::DoubleClick && !appWindow->isVisible()) {
        appWindow->showWindow();
    }
}

void AppController::setupTrayIcon()
{
    trayIcon = new QSystemTrayIcon(this);

    trayIcon->setIcon(QIcon(":/images/images/itchio-icon-16.png"));
    trayIcon->show();
}

void AppController::setupTrayIconMenu(bool beforeLogin)
{
    trayIconMenu = new QMenu();
    trayIcon->setContextMenu(trayIconMenu);

    if (!beforeLogin) {
        QAction* actionSettings = new QAction("Settings", this);
        trayIconMenu->addAction(actionSettings);
        connect(actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));

        trayIconMenu->addSeparator();
    }

    QAction* actionQuit = new QAction("Quit", this);
    trayIconMenu->addAction(actionQuit);
    connect(actionQuit, SIGNAL(triggered()), this, SLOT(quit()));

    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(trayIconDoubleClick(QSystemTrayIcon::ActivationReason)));
}

void AppController::showTrayIconNotification(TrayNotifications::Notifications notification, QString data)
{
    if (settings->showTrayNotifications()) {
        if((notification == TrayNotifications::LIBRARY_UPDATE &&
            settings->showLibraryUpdateNotifications()) ||
                (notification == TrayNotifications::DOWNLOAD_FINISHED &&
                 settings->showDownloadFinishedNotifications()) ||
                (notification == TrayNotifications::GAME_UPDATE_AVAILABLE &&
                 settings->showGameUpdateAvailableNotifications())){

            trayIcon->showMessage(TrayNotifications::toString(notification),
                                  data, QSystemTrayIcon::NoIcon, 5000);
        }

    }
}

void AppController::setupLogin()
{
    settings->setApiKey("");
    api->userKey = "";

    setupTrayIconMenu(true);

    loginWindow = new SecondaryWindow(new LoginWidget(qobject_cast<QWidget*>(this), this), this);
    loginWindow->show();
}

void AppController::setupAppWindow()
{
    appWindow = new AppWindow(this);
}

void AppController::onLogin()
{
    setupTrayIconMenu();

    if (!loginWithApiKey) {
        loginWindow->deleteLater();
        loginWindow->close();
    }

    appWindow->setupLibrary();
}

void AppController::onAutoLoginFailure(QString)
{
    setupLogin();
}
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen
// =============================================================================
//
// test the pacTire for 3 distinct slip cases, then compare force/moment output
// v. slip (kappa, alpha) to Adams/Car testrig output
// 1) pure longitudinal slip (V_yc = tan(alpha) = 0)
// 2) pure lateral slip, (kappa ~= 0)
// 3) combined slip
//
// we will run our vehicle with default rigid tires, but calculate the output
// for the pacjeka tire in the background
//
// =============================================================================

#include <vector>

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"

#include "utils/ChUtilsInputOutput.h"
#include "utils/ChUtilsData.h"

#include "subsys/tire/ChPacejkaTire.h"
#include "subsys/terrain/FlatTerrain.h"

#include "ChronoT_config.h"

using namespace chrono;

const std::string out_dir = "../PACTEST";
const std::string pov_dir = out_dir + "/POVRAY";

// ============== PacTire settings go here
const int num_pts = 801;                  // # of data points in the slip ranges
const double step_size = 0.01;            // seconds, arbitrary unless calculating transient slip
const double alpha_lim = CH_C_PI_4/3.0;   // slip angle in range [-lim,lim] or [0,lim]
const double kappa_lim = 1;               // slip rate in range [-lim,lim] or [0,lim]
const double F_z = 8000;                  // vertical force, [N]
const double time_end = (num_pts - 1)*step_size;

// for the transient model
const bool use_transient_slip = true;    // use kinematic or transient contact slips?

const std::string pacParamFile = utils::GetModelDataFile("hmmwv/pactest.tir");

std::string outData_filename_long = "test_pacTire_pureLongSlip.csv";
std::string outData_filename_lat = "test_pacTire_pureLatSlip.csv";
std::string outData_filename_combined = "test_pacTire_combinedSlip.csv";

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

  // flat rigid terrain, height = 0 for all (x,y)
  FlatTerrain flat_terrain(0);

  // Create the Pac tires, try to open param file and load empirical constants
  ChPacejkaTire tire_long("LONGITUDINAL", pacParamFile, flat_terrain, F_z, use_transient_slip);
  ChPacejkaTire tire_lat("LATERAL", pacParamFile, flat_terrain, F_z, use_transient_slip);
  ChPacejkaTire tire_combined("COMBINED", pacParamFile, flat_terrain, F_z, use_transient_slip);

  tire_long.Initialize(LEFT);
  tire_lat.Initialize(LEFT);
  tire_combined.Initialize(LEFT);

  // record pacTire output for each of the 3 slip cases
  ChTireForces long_forces(1);
  ChTireForces lat_forces(1);
  ChTireForces combined_forces(1);

  // update body state based on varying input variables to pacTire:
  // alpha, kappa and gamma
  ChWheelState long_state;
  ChWheelState lat_state;
  ChWheelState combined_state;

  // keep track of the input variable values
  std::vector<double> latSlip_range;
  std::vector<double> longSlip_range;
  latSlip_range.resize(num_pts);
  longSlip_range.resize(num_pts);

  double time = 0.0;

  // get the bounds of the slip angles from the input *.tire file
  double k_min, k_max, a_min, a_max;
  k_min = -kappa_lim;
  k_max = kappa_lim;
  a_min = -alpha_lim;
  a_max = alpha_lim;

  // at IC, go straight ahead at zero slip
  double kappa_t = k_min;
  double alpha_t = 0;
  double tanalpha_t = tan(alpha_t);
  double gamma_t = 0.1 * alpha_t;

  // unless we're only using steady-state EQs, then just sweep min to max
  if (!use_transient_slip)
  {
    alpha_t = a_min;
    tanalpha_t = tan(alpha_t);
    gamma_t = 0.1 * alpha_t;
  }
  else {
    outData_filename_long = "test_pacTire_pureLongSlip_transient.csv";
    outData_filename_lat = "test_pacTire_pureLatSlip_transient.csv";
    outData_filename_combined = "test_pacTire_combinedSlip_transient.csv";
  }

  // calculate the increments for each slip case (assuming constant per step)
  double kappa_incr = (k_max - k_min) / double(num_pts);
  double alpha_incr = (a_max - a_min) / double(num_pts);

  // horizontal velocity (x,y components) is constant throughout all runs
  double vel_xy = tire_long.get_longvl();

  // time step is arbitrary, steps determined by slip array length
  for (size_t step = 0; step < num_pts; step++)
  {
    // tire input slip quantities
    tanalpha_t = tan(alpha_t);

    // DEBUGGING
    gamma_t = 0;   // 0.1 * alpha_t;

    latSlip_range[step] = tanalpha_t;
    longSlip_range[step] = kappa_t;

    // **** longitudinal states
    long_state = tire_long.getState_from_KAG(kappa_t, 0, 0, vel_xy);

    // **** lateral states
    lat_state = tire_lat.getState_from_KAG(0, alpha_t, gamma_t, vel_xy);

    // ****  combined states
    combined_state = tire_combined.getState_from_KAG(kappa_t, alpha_t, gamma_t, vel_xy);

    // check states calculated for this step
    // ChWheelState kag_long = tire_long.getState_from_KAG(kappa_t, 0, gamma_t, vel_xy);
    // ChWheelState kag_lat = tire_lat.getState_from_KAG(0, alpha_t, gamma_t, vel_xy;
    // ChWheelState kag_combined = tire_combined.getState_from_KAG(kappa_t, alpha_t, gamma_t, vel_xy);

    // DEBUGGING
    if (step == 250)
      int arg = 2;

    // update all 3 types of tires, with current wheel state data
    tire_long.Update(time, long_state);
    tire_lat.Update(time, lat_state);
    tire_combined.Update(time, combined_state);

    // advance the slip displacements, calculate reactions
    tire_long.Advance(step_size);
    tire_lat.Advance(step_size);
    tire_combined.Advance(step_size);

    // see what the calculated reactions are
    long_forces[0] = tire_long.GetTireForce();
    lat_forces[0] = tire_lat.GetTireForce();
    combined_forces[0] = tire_combined.GetTireForce();

    // output any data at the end of the step
    tire_long.WriteOutData(time, outData_filename_long);
    tire_lat.WriteOutData(time, outData_filename_lat);
    tire_combined.WriteOutData(time, outData_filename_combined);

    // std::cout << "step: " << step << ", kappa = " << kappa_t << ", alpha = " << alpha_t << ", tan(alpha) = " << tanalpha_t << std::endl;

    // increment time, update long. & lat. slips for the next time step
    time += step_size;
    // constant increments. sine waves would be better
    if (use_transient_slip)
    {
      // do a powered lane change
      // Careful !!!!
      // need to properly mimic Adams/Car kappa, alpha vs. time
      // kappa is linear
      kappa_t += kappa_incr;
      // lateral angle is a sine wave
      alpha_t = abs(a_max) * sin(2.0 * chrono::CH_C_PI * time / time_end);
    }
    else {
      kappa_t += kappa_incr;
      alpha_t += alpha_incr;
    }

  }

  // clean up anything

  return 0;
}
<commit_msg>add a tire having a constant non-zero camber with a pure lateral slip test case.<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen
// =============================================================================
//
// test the pacTire for 3 distinct slip cases, then compare force/moment output
// v. slip (kappa, alpha) to Adams/Car testrig output
// 1) pure longitudinal slip (V_yc = tan(alpha) = 0)
// 2) pure lateral slip, (kappa ~= 0)
// 3) combined slip
//
// we will run our vehicle with default rigid tires, but calculate the output
// for the pacjeka tire in the background
//
// =============================================================================

#include <vector>

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"

#include "utils/ChUtilsInputOutput.h"
#include "utils/ChUtilsData.h"

#include "subsys/tire/ChPacejkaTire.h"
#include "subsys/terrain/FlatTerrain.h"

#include "ChronoT_config.h"

using namespace chrono;

const std::string out_dir = "../PACTEST";
const std::string pov_dir = out_dir + "/POVRAY";

// ============== PacTire settings go here
const int num_pts = 801;                  // # of data points in the slip ranges
const double step_size = 0.01;            // seconds, arbitrary unless calculating transient slip
const double alpha_lim = CH_C_PI_4/3.0;   // slip angle in range [-lim,lim] or [0,lim]
const double kappa_lim = 1;               // slip rate in range [-lim,lim] or [0,lim]
const double F_z = 8000;                  // vertical force, [N]
const ChVehicleSide m_side = LEFT;
const double gamma = 10.0 * CH_C_PI/180.0; // gamma, in radians

// for the transient model
const bool use_transient_slip = true;    // use kinematic or transient contact slips?

const std::string pacParamFile = utils::GetModelDataFile("hmmwv/pactest.tir");

// output data filenames
std::string out_name_long = "test_pacTire_pureLongSlip.csv";
std::string out_name_lat = "test_pacTire_pureLatSlip.csv";
std::string out_name_latGamma = "test_pacTire_pureLatSlipGamma.csv";
std::string out_name_combined = "test_pacTire_combinedSlip.csv";

const double time_end = (num_pts - 1)*step_size;

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

  // flat rigid terrain, height = 0 for all (x,y)
  FlatTerrain flat_terrain(0);

  // Create the Pac tires, try to open param file and load empirical constants
  ChPacejkaTire tire_long("LONGITUDINAL", pacParamFile, flat_terrain, F_z, use_transient_slip);
  ChPacejkaTire tire_lat("LATERAL", pacParamFile, flat_terrain, F_z, use_transient_slip);
  ChPacejkaTire tire_lat_gamma("LATERAL_GAMMA", pacParamFile, flat_terrain, F_z, use_transient_slip);
  ChPacejkaTire tire_combined("COMBINED", pacParamFile, flat_terrain, F_z, use_transient_slip);

  // initialize the tire on the left or right side
  tire_long.Initialize(m_side);
  tire_lat.Initialize(m_side);
  tire_lat_gamma.Initialize(m_side);
  tire_combined.Initialize(m_side);

  // record pacTire output for each of the 3 slip cases
  ChTireForces long_forces(1);
  ChTireForces lat_forces(1);
  ChTireForces latGamma_forces(1);
  ChTireForces combined_forces(1);

  // update body state based on varying input variables to pacTire:
  // alpha, kappa and gamma
  ChWheelState long_state;
  ChWheelState lat_state;
  ChWheelState latGamma_state;
  ChWheelState combined_state;

  // keep track of the input variable values
  std::vector<double> latSlip_range;
  std::vector<double> longSlip_range;
  latSlip_range.resize(num_pts);
  longSlip_range.resize(num_pts);

  double time = 0.0;

  // get the bounds of the slip angles from the input *.tire file
  double k_min, k_max, a_min, a_max;
  k_min = -kappa_lim;
  k_max = kappa_lim;
  a_min = -alpha_lim;
  a_max = alpha_lim;

  // at IC, go straight ahead at zero slip
  double kappa_t = k_min;
  double alpha_t = 0;
  double tanalpha_t = tan(alpha_t);
  double gamma_t = 0.1 * alpha_t;

  // unless we're only using steady-state EQs, then just sweep min to max
  if (!use_transient_slip)
  {
    alpha_t = a_min;
    tanalpha_t = tan(alpha_t);
    gamma_t = 0.1 * alpha_t;
  }
  else {
    out_name_long = "test_pacTire_pureLongSlip_transient.csv";
    out_name_lat = "test_pacTire_pureLatSlip_transient.csv";
    out_name_latGamma = "test_pacTire_pacLatSlipGamma_transient.csv";
    out_name_combined = "test_pacTire_combinedSlip_transient.csv";
  }

  // calculate the increments for each slip case (assuming constant per step)
  double kappa_incr = (k_max - k_min) / double(num_pts);
  double alpha_incr = (a_max - a_min) / double(num_pts);

  // horizontal velocity (x,y components) is constant throughout all runs
  double vel_xy = tire_long.get_longvl();

  // time step is arbitrary, steps determined by slip array length
  for (size_t step = 0; step < num_pts; step++)
  {
    // tire input slip quantities
    tanalpha_t = tan(alpha_t);

    latSlip_range[step] = tanalpha_t;
    longSlip_range[step] = kappa_t;

    // **** longitudinal states
    long_state = tire_long.getState_from_KAG(kappa_t, 0, 0, vel_xy);

    // **** lateral states
    lat_state = tire_lat.getState_from_KAG(0, alpha_t, 0, vel_xy);

    // ***** lateral w/ specified gamma
    latGamma_state = tire_lat_gamma.getState_from_KAG(0, alpha_t, gamma, vel_xy);

    // ****  combined states
    combined_state = tire_combined.getState_from_KAG(kappa_t, alpha_t, gamma_t, vel_xy);

    // DEBUGGING
    if (step == 200)
      int arg = 2;

    // update all 4 types of tires, with current wheel state data
    tire_long.Update(time, long_state);
    tire_lat.Update(time, lat_state);
    tire_lat_gamma.Update(time, latGamma_state);
    tire_combined.Update(time, combined_state);

    // advance the slip displacements, calculate reactions
    tire_long.Advance(step_size);
    tire_lat.Advance(step_size);
    tire_lat_gamma.Advance(step_size);
    tire_combined.Advance(step_size);

    // see what the calculated reactions are
    long_forces[0] = tire_long.GetTireForce();
    lat_forces[0] = tire_lat.GetTireForce();
    latGamma_forces[0] = tire_lat_gamma.GetTireForce();
    combined_forces[0] = tire_combined.GetTireForce();

    // output any data at the end of the step
    tire_long.WriteOutData(time, out_name_long);
    tire_lat.WriteOutData(time, out_name_lat);
    tire_lat_gamma.WriteOutData(time, out_name_latGamma);
    tire_combined.WriteOutData(time, out_name_combined);

    // std::cout << "step: " << step << ", kappa = " << kappa_t << ", alpha = " << alpha_t << ", tan(alpha) = " << tanalpha_t << std::endl;

    // increment time, update long. & lat. slips for the next time step
    time += step_size;
    // constant increments. sine waves would be better
    if (use_transient_slip)
    {
      // do a powered lane change
      // Careful !!!!
      // need to properly mimic Adams/Car kappa, alpha vs. time
      // kappa is linear
      kappa_t += kappa_incr;
      // lateral angle is a sine wave
      alpha_t = abs(a_max) * sin(2.0 * chrono::CH_C_PI * time / time_end);
    }
    else {
      kappa_t += kappa_incr;
      alpha_t += alpha_incr;
    }

  }

  // clean up anything

  return 0;
}
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2018 ScyllaDB Ltd.
 */

#include <boost/range.hpp>
#include <boost/range/irange.hpp>

#include <seastar/testing/perf_tests.hh>
#include <seastar/core/loop.hh>
#include <seastar/util/later.hh>

struct parallel_for_each {
    std::vector<int> empty_range;
    std::vector<int> range;
    int value;

    parallel_for_each()
        : empty_range()
        , range(boost::copy_range<std::vector<int>>(boost::irange(1, 100)))
    { }
};

PERF_TEST_F(parallel_for_each, empty)
{
    return seastar::parallel_for_each(empty_range, [] (int) -> future<> {
        abort();
    });
}

[[gnu::noinline]]
future<> immediate(int v, int& vs)
{
    vs += v;
    return make_ready_future<>();
}

PERF_TEST_F(parallel_for_each, immediate)
{
    return seastar::parallel_for_each(range, [this] (int v) {
        return immediate(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
    });
}

[[gnu::noinline]]
future<> suspend(int v, int& vs)
{
    vs += v;
    return yield();
}

PERF_TEST_F(parallel_for_each, suspend)
{
    return seastar::parallel_for_each(range, [this] (int v) {
        return suspend(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
    });
}
<commit_msg>tests: perf: future_util: consider range size<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2018 ScyllaDB Ltd.
 */

#include <boost/range.hpp>
#include <boost/range/irange.hpp>

#include <seastar/testing/perf_tests.hh>
#include <seastar/core/loop.hh>
#include <seastar/util/later.hh>

struct parallel_for_each {
    std::vector<int> empty_range;
    std::vector<int> range;
    int value;

    static constexpr int max_range_size = 100;

    parallel_for_each()
        : empty_range()
        , range(boost::copy_range<std::vector<int>>(boost::irange(1, max_range_size)))
    { }
};

PERF_TEST_F(parallel_for_each, empty)
{
    return seastar::parallel_for_each(empty_range, [] (int) -> future<> {
        abort();
    });
}

[[gnu::noinline]]
future<> immediate(int v, int& vs)
{
    vs += v;
    return make_ready_future<>();
}

PERF_TEST_F(parallel_for_each, immediate_1)
{
    auto&& begin = range.begin();
    auto&& end = begin + 1;
    return seastar::parallel_for_each(std::move(begin), std::move(end), [this] (int v) {
        return immediate(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return 1;
    });
}

PERF_TEST_F(parallel_for_each, immediate_2)
{
    auto&& begin = range.begin();
    auto&& end = begin + 2;
    return seastar::parallel_for_each(std::move(begin), std::move(end), [this] (int v) {
        return immediate(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return 2;
    });
}

PERF_TEST_F(parallel_for_each, immediate_10)
{
    auto&& begin = range.begin();
    auto&& end = begin + 10;
    return seastar::parallel_for_each(std::move(begin), std::move(end), [this] (int v) {
        return immediate(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return 10;
    });
}

PERF_TEST_F(parallel_for_each, immediate_100)
{
    return seastar::parallel_for_each(range, [this] (int v) {
        return immediate(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return range.size();
    });
}

[[gnu::noinline]]
future<> suspend(int v, int& vs)
{
    vs += v;
    return yield();
}

PERF_TEST_F(parallel_for_each, suspend_1)
{
    auto&& begin = range.begin();
    auto&& end = begin + 1;
    return seastar::parallel_for_each(std::move(begin), std::move(end), [this] (int v) {
        return suspend(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return 1;
    });
}

PERF_TEST_F(parallel_for_each, suspend_2)
{
    auto&& begin = range.begin();
    auto&& end = begin + 2;
    return seastar::parallel_for_each(std::move(begin), std::move(end), [this] (int v) {
        return suspend(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return 2;
    });
}

PERF_TEST_F(parallel_for_each, suspend_10)
{
    auto&& begin = range.begin();
    auto&& end = begin + 10;
    return seastar::parallel_for_each(std::move(begin), std::move(end), [this] (int v) {
        return suspend(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return 10;
    });
}

PERF_TEST_F(parallel_for_each, suspend_100)
{
    return seastar::parallel_for_each(range, [this] (int v) {
        return suspend(v, value);
    }).then([this] {
        perf_tests::do_not_optimize(value);
        return range.size();
    });
}
<|endoftext|>


<commit_before>#include "SceneRace.hpp"
#include "Game.hpp"

SceneRace::SceneRace(Game* g, sf::RenderWindow* w) : Scene(g,w) {
	sf::Vector2u targetResolution(640,360);
	initView(sf::Vector2i(targetResolution));
	sf::Vector2u displayResolution(_view.getSize());

	_speed = 0;
	_nPlayers = 4;
	_rotation = 0;
	_players = std::vector<Player>(_nPlayers);
	_background = new Background(displayResolution);

	_rect.setSize(sf::Vector2f(displayResolution.x, displayResolution.y));
	_rect.setPosition(sf::Vector2f(-0.5*displayResolution.x,displayResolution.y*3.0/4.0));
	_rect.setFillColor(sf::Color::Yellow);
	_rect2.setSize(sf::Vector2f(displayResolution.x, displayResolution.y));
	_rect2.setPosition(sf::Vector2f(0.5*displayResolution.x,displayResolution.y*3.0/4.0));
	_rect2.setFillColor(sf::Color::Red);
	_rect3.setSize(sf::Vector2f(displayResolution.x, displayResolution.y));
	_rect3.setPosition(sf::Vector2f(1.5*displayResolution.x,displayResolution.y*3.0/4.0));
	_rect3.setFillColor(sf::Color::Blue);

	_groundBounds = sf::IntRect(0,displayResolution.y*3.0/4.0,displayResolution.x, displayResolution.y/4.0);
}

SceneRace::~SceneRace() {
	delete _background;
}

void SceneRace::init(int nPlayers) {
	_nPlayers = nPlayers;
	_rotation = 0;
}

void SceneRace::processInput() {
    sf::Event event;
    while (_window->pollEvent(event)) {
        if (event.type == sf::Event::Closed) {_window->close(); exit(0);}
        else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
            _window->close(); exit(0);
        }
        else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Right) {
            setRotation(_rotation+0.2);
        }
        else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Left) {
            setRotation(_rotation-0.2);
        }
    }
}

void SceneRace::update(float deltaTime) {
	_rotation = (_rotation < 0 ? _rotation + 360 : (_rotation > 360? _rotation - 360 : _rotation) );
	_speed += 0.5*sin(_rotation*TO_RADIANS)*TO_DEGREES*deltaTime;
	_speed = std::min(50.0f, std::max(_speed,-50.0f));
	_rect.move(sf::Vector2f(_speed,0));
	_rect2.move(sf::Vector2f(_speed,0));
	_rect3.move(sf::Vector2f(_speed,0));
	if (_rect.getPosition().x  < -1.5*_view.getSize().x) _rect.move( sf::Vector2f(3*_view.getSize().x,0));
	else if(_rect.getPosition().x  > 1.5*_view.getSize().x) _rect.move( sf::Vector2f(-3*_view.getSize().x,0));
	if (_rect2.getPosition().x < -1.5*_view.getSize().x) _rect2.move(sf::Vector2f(3*_view.getSize().x,0));
	else if(_rect2.getPosition().x  > 1.5*_view.getSize().x) _rect2.move( sf::Vector2f(-3*_view.getSize().x,0));
	if (_rect3.getPosition().x < -1.5*_view.getSize().x) _rect3.move(sf::Vector2f(3*_view.getSize().x,0));
	else if(_rect3.getPosition().x  > 1.5*_view.getSize().x) _rect3.move( sf::Vector2f(-3*_view.getSize().x,0));

	for (int i = 0; i < _nPlayers; ++i) {
		float rot = _rotation > 180 ? _rotation - 360 : _rotation;
		float maxRotation = 70;
		float destination = (-rot+maxRotation)*_view.getSize().x/(maxRotation*2);
		std::cout << "destination " << destination << std::endl;
		float factor = 0.5;
		if ((rot < 0 && destination - _players[i].getPosition().x < 0) ||
			(rot > 0 && destination - _players[i].getPosition().x > 0)) {
			factor = 0.1;
			std::cout << rot << " " << destination - _players[i].getPosition().x << std::endl;
		}
		sf::Vector2f acceleration(factor*(destination - _players[i].getPosition().x),2);
		_players[i].setAcceleration(acceleration);
		_players[i].update(deltaTime);
        sf::Vector2f oldPlayerPosition;
        oldPlayerPosition = _players[i].getPosition();
		_players[i].move(deltaTime);
		if (_players[i].getPosition().y > _groundBounds.top - _players[i].getMBounds().height) {
			_players[i].setPosition(_players[i].getPosition().x, _groundBounds.top-_players[i].getMBounds().height);
            _players[i].setJumping(false);
        }
        for(int p = 0; p < _players.size(); ++p){

            sf::IntRect colision;
            if(p != i){
                if(_players[i].getMGlobalBounds().intersects(_players[p].getMGlobalBounds(), colision)){
                    if(_players[i].velocity().x > 0){
                        _players[i].setPosition(colision.left-_players[i].getMGlobalBounds().width, 0);
                    }
                    else {
                        _players[i].setPosition(colision.left+colision.width, 0);
                    }
                }
            }
        }
	}

}

void SceneRace::render(sf::RenderTarget* target) {
	_background->draw(target);

	target->draw(_rect);
	target->draw(_rect2);
	target->draw(_rect3);
	for (int i = 0; i < _nPlayers; ++i) target->draw(_players[i]);
}

void SceneRace::setRotation(float rotation) {
	_rotation = rotation;
	_background->setRotation(_rotation);
    _view.setRotation(_rotation);
}
<commit_msg>no salten<commit_after>#include "SceneRace.hpp"
#include "Game.hpp"

SceneRace::SceneRace(Game* g, sf::RenderWindow* w) : Scene(g,w) {
	sf::Vector2u targetResolution(640,360);
	initView(sf::Vector2i(targetResolution));
	sf::Vector2u displayResolution(_view.getSize());

	_speed = 0;
	_nPlayers = 4;
	_rotation = 0;
	_players = std::vector<Player>(_nPlayers);
	_background = new Background(displayResolution);

	_rect.setSize(sf::Vector2f(displayResolution.x, displayResolution.y));
	_rect.setPosition(sf::Vector2f(-0.5*displayResolution.x,displayResolution.y*3.0/4.0));
	_rect.setFillColor(sf::Color::Yellow);
	_rect2.setSize(sf::Vector2f(displayResolution.x, displayResolution.y));
	_rect2.setPosition(sf::Vector2f(0.5*displayResolution.x,displayResolution.y*3.0/4.0));
	_rect2.setFillColor(sf::Color::Red);
	_rect3.setSize(sf::Vector2f(displayResolution.x, displayResolution.y));
	_rect3.setPosition(sf::Vector2f(1.5*displayResolution.x,displayResolution.y*3.0/4.0));
	_rect3.setFillColor(sf::Color::Blue);

	_groundBounds = sf::IntRect(0,displayResolution.y*3.0/4.0,displayResolution.x, displayResolution.y/4.0);
}

SceneRace::~SceneRace() {
	delete _background;
}

void SceneRace::init(int nPlayers) {
	_nPlayers = nPlayers;
	_rotation = 0;
}

void SceneRace::processInput() {
    sf::Event event;
    while (_window->pollEvent(event)) {
        if (event.type == sf::Event::Closed) {_window->close(); exit(0);}
        else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
            _window->close(); exit(0);
        }
        else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Right) {
            setRotation(_rotation+0.2);
        }
        else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Left) {
            setRotation(_rotation-0.2);
        }
    }
}

void SceneRace::update(float deltaTime) {
    _background->update(deltaTime);
	_rotation = (_rotation < 0 ? _rotation + 360 : (_rotation > 360? _rotation - 360 : _rotation) );
	_speed += 0.5*sin(_rotation*TO_RADIANS)*TO_DEGREES*deltaTime;
	_speed = std::min(50.0f, std::max(_speed,-50.0f));
	_rect.move(sf::Vector2f(_speed,0));
	_rect2.move(sf::Vector2f(_speed,0));
	_rect3.move(sf::Vector2f(_speed,0));
	if (_rect.getPosition().x  < -1.5*_view.getSize().x) _rect.move( sf::Vector2f(3*_view.getSize().x,0));
	else if(_rect.getPosition().x  > 1.5*_view.getSize().x) _rect.move( sf::Vector2f(-3*_view.getSize().x,0));
	if (_rect2.getPosition().x < -1.5*_view.getSize().x) _rect2.move(sf::Vector2f(3*_view.getSize().x,0));
	else if(_rect2.getPosition().x  > 1.5*_view.getSize().x) _rect2.move( sf::Vector2f(-3*_view.getSize().x,0));
	if (_rect3.getPosition().x < -1.5*_view.getSize().x) _rect3.move(sf::Vector2f(3*_view.getSize().x,0));
	else if(_rect3.getPosition().x  > 1.5*_view.getSize().x) _rect3.move( sf::Vector2f(-3*_view.getSize().x,0));

	for (int i = 0; i < _nPlayers; ++i) {
		float rot = _rotation > 180 ? _rotation - 360 : _rotation;
		float maxRotation = 70;
		float destination = (-rot+maxRotation)*_view.getSize().x/(maxRotation*2);
		std::cout << "destination " << destination << std::endl;
		float factor = 0.5;
		if ((rot < 0 && destination - _players[i].getPosition().x < 0) ||
			(rot > 0 && destination - _players[i].getPosition().x > 0)) {
			factor = 0.1;
			std::cout << rot << " " << destination - _players[i].getPosition().x << std::endl;
		}
		sf::Vector2f acceleration(factor*(destination - _players[i].getPosition().x),2);
		_players[i].setAcceleration(acceleration);
		_players[i].update(deltaTime);
        sf::Vector2f oldPlayerPosition;
        oldPlayerPosition = _players[i].getPosition();
		_players[i].move(deltaTime);
		if (_players[i].getPosition().y > _groundBounds.top - _players[i].getMBounds().height) {
			_players[i].setPosition(_players[i].getPosition().x, _groundBounds.top-_players[i].getMBounds().height);
            _players[i].setJumping(false);
        }
        for(int p = 0; p < _players.size(); ++p){

            sf::IntRect colision;
            if(p != i){
                if(_players[i].getMGlobalBounds().intersects(_players[p].getMGlobalBounds(), colision)){
                    if(_players[i].velocity().x > 0){
                        _players[i].setPosition(colision.left-_players[i].getMGlobalBounds().width,
                                                _players[i].getPosition().y);
                    }
                    else {
                        _players[i].setPosition(colision.left+colision.width, _players[i].getPosition().y);
                    }
                }
            }
        }
	}
}

void SceneRace::render(sf::RenderTarget* target) {
	_background->draw(target);

	target->draw(_rect);
	target->draw(_rect2);
	target->draw(_rect3);
	for (int i = 0; i < _nPlayers; ++i) target->draw(_players[i]);
}

void SceneRace::setRotation(float rotation) {
	_rotation = rotation;
	_background->setRotation(_rotation);
    _view.setRotation(_rotation);
}
<|endoftext|>


<commit_before>#include "catch.hpp"

#include <member_iterator.hpp>
#include <vector>
#include <forward_list>
#include <string>

TEST_CASE("member_iterator to member of a mock struct in std::vector",
          "[member_iterator]")
{

    struct mock
    {
        int something;
        double the_member;
    };

    typedef helene::member_iterator<double,
                                    mock,
                                    std::vector<mock>::iterator,
                                    &mock::the_member>
        my_iter;

    std::vector<mock> container{{1, 1.0}, {2, 2.0}, {3, 3.0}};
}

TEST_CASE("member_iterator to member of a mock struct in a std::forward_list",
          "[member_iterator]")
{
    struct mock
    {
        std::string name;
        int value;
    };

    typedef helene::member_iterator<int,
                                    mock,
                                    std::forward_list<mock>::iterator,
                                    &mock::value>
        my_iter;

    std::forward_list<mock> container;
    container.push_front({std::string("one"), 1});
    container.push_front({std::string("two"), 2});
    container.push_front({std::string("three"), 3});

    my_iter it_beg(container.begin());
    my_iter it_end(container.end());

    REQUIRE(it_beg != it_end);
    REQUIRE(*it_beg == 3);

    SECTION("increment iterator")
    {
        ++it_beg;
        REQUIRE(*it_beg == 2);

        SECTION("increment again")
        {
            ++it_beg;
            REQUIRE(*it_beg == 1);

            SECTION("increment again")
            {
                ++it_beg;
                REQUIRE_FALSE(it_beg != it_end);
            }
        }
    }

    SECTION("mutate element through iterator")
    {
        *it_beg = 10;

        REQUIRE(*it_beg == 10);
    }
}
<commit_msg>Add tests for postincrement operator. 	modified:   tests/test_member_iterator.cpp<commit_after>#include "catch.hpp"

#include <member_iterator.hpp>
#include <vector>
#include <forward_list>
#include <list>
#include <string>

TEST_CASE("member_iterator to member of a mock struct in std::vector",
          "[member_iterator]")
{

    struct mock
    {
        int something;
        double the_member;
    };

    typedef helene::member_iterator<double,
                                    mock,
                                    std::vector<mock>::iterator,
                                    &mock::the_member>
        my_iter;

    std::vector<mock> container{{1, 1.0}, {2, 2.0}, {3, 3.0}};
}

TEST_CASE("member_iterator to member of a mock struct in a std::forward_list",
          "[member_iterator]")
{
    struct mock
    {
        std::string name;
        int value;
    };

    typedef helene::member_iterator<int,
                                    mock,
                                    std::forward_list<mock>::iterator,
                                    &mock::value>
        my_iter;

    std::forward_list<mock> container;
    container.push_front({std::string("one"), 1});
    container.push_front({std::string("two"), 2});
    container.push_front({std::string("three"), 3});

    my_iter it_beg(container.begin());
    my_iter it_end(container.end());

    REQUIRE(it_beg != it_end);
    REQUIRE(*it_beg == 3);

    SECTION("preincrement iterator")
    {
        ++it_beg;
        REQUIRE(*it_beg == 2);

        SECTION("preincrement again")
        {
            ++it_beg;
            REQUIRE(*it_beg == 1);

            SECTION("preincrement again")
            {
                ++it_beg;
                REQUIRE_FALSE(it_beg != it_end);
            }
        }
    }

    SECTION("preincrement and dereference")
    {
        REQUIRE(*(++it_beg) == 2);
    }

    SECTION("postincrement")
    {
        auto prev = it_beg++;
        REQUIRE(*prev == 3);
        REQUIRE(*it_beg == 2);
    }

    SECTION("mutate element through iterator")
    {
        *it_beg = 10;

        REQUIRE(*it_beg == 10);
    }
}

TEST_CASE("member_iterator to member of a mock struct in a std::list",
          "[member_iterator]")
{
}
<|endoftext|>