void Read(
    std::istream& fin, double minsep, double binsize,
    std::vector<CellData>& celldata, 
    std::vector<std::vector<CellData> >& expcelldata, double& vare)
{
    double sumw=0.;
    vare=0.;
    int j;
    double x,y,e1,e2,w;
    while(fin >> j>>x>>y>>e1>>e2>>w) {
        // Note: e1,e2 are really gamma_1, gamma_2
        // _NOT_ observed ellipticities

        Position2D pos(x,y);
        std::complex<double> e(e1,e2);
        sumw += w;
        vare += w*w*norm(e);

        celldata.push_back(CellData(pos,e,w));

        while(j >= int(expcelldata.size())) 
            expcelldata.push_back(std::vector<CellData>());
        expcelldata[j].push_back(CellData(pos,e,w));
    }
    int ngal = celldata.size();
    vare /= 2*sumw*sumw/ngal; // 2 because want var per component
    dbg<<"ngal = "<<ngal<<", totw = "<<sumw<<std::endl;
}
Mod::Mod(const Position pos)
{
	Position northWestPos = Position(pos.x - 1, pos.y + 1);
	northWest = CellData(northWestPos, World::getInstance().getTerrain(northWestPos));

	Position northPos = Position(pos.x, pos.y + 1);
	north = CellData(northPos, World::getInstance().getTerrain(northPos));

	Position northEastPos = Position(pos.x + 1, pos.y + 1);
	northEast = CellData(northEastPos, World::getInstance().getTerrain(northEastPos));

	Position westPos = Position(pos.x - 1, pos.y);
	west = CellData(westPos, World::getInstance().getTerrain(westPos));

	Position eastPos = Position(pos.x + 1, pos.y);
	east = CellData(eastPos, World::getInstance().getTerrain(eastPos));

	Position southWestPos = Position(pos.x - 1, pos.y - 1);
	southWest = CellData(southWestPos, World::getInstance().getTerrain(southWestPos));

	Position southPos = Position(pos.x, pos.y - 1);
	south = CellData(southPos, World::getInstance().getTerrain(southPos));

	Position southEastPos = Position(pos.x + 1, pos.y - 1);
	southEast = CellData(southEastPos, World::getInstance().getTerrain(southEastPos));

	destroyWorld();
}
std::pair<TRasterP, TCacheResource::CellData *> TCacheResource::touch(const PointLess &cellIndex)
{
	std::string cellId(getCellCacheId(cellIndex.x, cellIndex.y));

	std::map<PointLess, CellData>::iterator it = m_cellDatas.find(cellIndex);
	if (it != m_cellDatas.end()) {
		//Retrieve the raster from image cache
		TImageP img(TImageCache::instance()->get(cellId, true));
		if (img)
			return std::make_pair(getRaster(img), &it->second);
	}

	it = m_cellDatas.insert(std::make_pair(cellIndex, CellData())).first;

	//Then, attempt retrieval from back resource
	TRasterP ras(load(cellIndex));
	if (ras) {
		TImageCache::instance()->add(cellId, TRasterImageP(ras));
		return std::make_pair(ras, &it->second);
	}

	//Else, create it
	return std::make_pair(
		createCellRaster(m_tileType, cellId), //increases m_cellsCount too
		&it->second);
}
Exemple #4
0
	void _notifier_update_cells(VisibilityNotifier2D *p_notifier,const Rect2& p_rect,bool p_add) {

		Point2i begin = p_rect.pos;
		begin/=cell_size;
		Point2i end = p_rect.pos+p_rect.size;
		end/=cell_size;
		for(int i=begin.x;i<=end.x;i++) {

			for(int j=begin.y;j<=end.y;j++) {

				CellKey ck;
				ck.x=i;
				ck.y=j;
				Map<CellKey,CellData>::Element *E=cells.find(ck);

				if (p_add) {

					if (!E)
						E=cells.insert(ck,CellData());
					E->get().notifiers[p_notifier].inc();
				} else {

					ERR_CONTINUE(!E);
					if (E->get().notifiers[p_notifier].dec()==0) {

						E->get().notifiers.erase(p_notifier);
						if (E->get().notifiers.empty()) {
							cells.erase(E);
						}
					}
				}
			}
		}
	}
    void renderLine(const geo::Vector3& p1, const geo::Vector3& p2)
    {
        geo::Vector3 v_diff = p2 - p1;
        double n_diff = v_diff.length();

        geo::Vector3 vd = v_diff / n_diff * res_;
        int n = n_diff / res_ + 1;

        geo::Vector3 p = p1;
        for(int i = 0; i < n; ++i)
        {
            int x = -p.y / res_ + grid_size_ / 2;
            int y = -p.x / res_ + grid_size_ / 2;

            if (x >= 0 && y >= 0 && x < grid_size_ && y <grid_size_) {
                int index = y * grid_size_ + x;
                Q_.push(CellData(index, 0, 0, 0));
            }
            p += vd;
        }

        p_min.x = std::min(p_min.x, std::min(p1.x, p2.x));
        p_max.x = std::max(p_max.x, std::max(p1.x, p2.x));

        p_min.y = std::min(p_min.y, std::min(p1.y, p2.y));
        p_max.y = std::max(p_max.y, std::max(p1.y, p2.y));
    }
/**
 * @brief  Given an index of a cell in the costmap, place it into a list pending for obstacle inflation
 * @param  grid The costmap
 * @param  index The index of the cell
 * @param  mx The x coordinate of the cell (can be computed from the index, but saves time to store it)
 * @param  my The y coordinate of the cell (can be computed from the index, but saves time to store it)
 * @param  src_x The x index of the obstacle point inflation started at
 * @param  src_y The y index of the obstacle point inflation started at
 */
inline void InflationLayer::enqueue(unsigned int index, unsigned int mx, unsigned int my,
                                    unsigned int src_x, unsigned int src_y)
{
  if (!seen_[index])
  {
    // we compute our distance table one cell further than the inflation radius dictates so we can make the check below
    double distance = distanceLookup(mx, my, src_x, src_y);

    // we only want to put the cell in the list if it is within the inflation radius of the obstacle point
    if (distance > cell_inflation_radius_)
      return;

    // push the cell data onto the inflation list and mark
    inflation_cells_[distance].push_back(CellData(index, mx, my, src_x, src_y));
  }
}
void LocalizationPlugin::process(const ed::WorldModel& world, ed::UpdateRequest& req)
{
    last_laser_msg_.reset();
    cb_queue_.callAvailable();

    if (!last_laser_msg_)
        return;

    tue::Timer timer;
    timer.start();

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // -     Update sensor model
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    if (lrf_.getNumBeams() != last_laser_msg_->ranges.size())
    {
        lrf_.setNumBeams(last_laser_msg_->ranges.size());
        lrf_.setRangeLimits(last_laser_msg_->range_min, last_laser_msg_->range_max);
        lrf_.setAngleLimits(last_laser_msg_->angle_min, last_laser_msg_->angle_max);
    }

    std::vector<double> sensor_ranges(last_laser_msg_->ranges.size());
    for (unsigned int i = 0; i < last_laser_msg_->ranges.size(); ++i)
        sensor_ranges[i] = last_laser_msg_->ranges[i];

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // -     Create world model cross section
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    std::vector<ed::EntityConstPtr> entities;
    for(ed::WorldModel::const_iterator it = world.begin(); it != world.end(); ++it)
    {
        // if (it->second->id() == "pico_case")
        if (it->second->shape())
            entities.push_back(it->second);
    }

    geo::Pose3D laser_pose;
    laser_pose.t = laser_pose_.t + geo::Vector3(0, 0, 0);
    laser_pose.R.setRPY(0, 0, 0);

    double grid_resolution = 0.025;
    int grid_size = 800;

    std::queue<CellData> Q;
    LineRenderResult render_result(Q, grid_size, grid_resolution);

    for(std::vector<ed::EntityConstPtr>::const_iterator it = entities.begin(); it != entities.end(); ++it)
    {
        const ed::EntityConstPtr& e = *it;

        geo::LaserRangeFinder::RenderOptions options;
        geo::Transform t_inv = laser_pose.inverse() * e->pose();
        options.setMesh(e->shape()->getMesh(), t_inv);
        lrf_.render(options, render_result);
    }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // -     Create distance map
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    double max_dist = 0.3;

    cv::Mat distance_map(grid_size, grid_size, CV_32FC1, (max_dist / grid_resolution) * (max_dist / grid_resolution));
    for(int i = 0; i < grid_size; ++i)
    {
        distance_map.at<float>(i, 0) = 0;
        distance_map.at<float>(i, grid_size - 1) = 0;
        distance_map.at<float>(0, i) = 0;
        distance_map.at<float>(grid_size - 1, i) = 0;
    }

    std::vector<KernelCell> kernel;

    kernel.push_back(KernelCell(-distance_map.cols, 0, -1));
    kernel.push_back(KernelCell(distance_map.cols, 0, 1));
    kernel.push_back(KernelCell(-1, -1, 0));
    kernel.push_back(KernelCell( 1,  1, 0));

    while(!Q.empty())
    {
        const CellData& c = Q.front();

        double current_distance = distance_map.at<float>(c.index);
        if (c.distance < current_distance)
        {
            distance_map.at<float>(c.index) = c.distance;
            for(unsigned int i = 0; i < kernel.size(); ++i)
            {
                const KernelCell& kc = kernel[i];
                int new_index = c.index + kc.d_index;
                int dx_new = c.dx + kc.dx;
                int dy_new = c.dy + kc.dy;

                int new_distance = (dx_new * dx_new) + (dy_new * dy_new);
                Q.push(CellData(new_index, dx_new, dy_new, new_distance));
            }
        }

        Q.pop();
    }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // -     Create samples
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    std::vector<geo::Pose3D> poses;

    if (!pose_initialized_)
    {
        // Uniform sampling over world

        for(double x = render_result.p_min.x; x < render_result.p_max.x; x += 0.2)
        {
            for(double y = render_result.p_min.y; y < render_result.p_max.y; y += 0.2)
            {
                for(double a = 0; a < 6.28; a += 0.1)
                {
                    geo::Pose3D laser_pose;
                    laser_pose.t = geo::Vector3(x, y, 0);
                    laser_pose.R.setRPY(0, 0, a);

                    poses.push_back(laser_pose);
                }
            }
        }
    }
    else
    {
        poses.push_back(best_laser_pose_);

        for(double dx = -0.3; dx < 0.3; dx += 0.1)
        {
            for(double dy = -0.3; dy < 0.3; dy += 0.1)
            {
                for(double da = -1; da < 1; da += 0.1)
                {
                    geo::Pose3D dT;
                    dT.t = geo::Vector3(dx, dy, 0);
                    dT.R.setRPY(0, 0, da);

                    poses.push_back(best_laser_pose_ * dT);
                }
            }
        }
    }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // -     Test samples and find sample with lowest error
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    std::vector<geo::Vector3> sensor_points;
    lrf_.rangesToPoints(sensor_ranges, sensor_points);

    int i_step = 1;
    if (poses.size() > 10000)
        i_step = sensor_points.size() / 100;  // limit to 100 beams

    std::cout << "i_step = " << i_step << std::endl;

    double min_sum_sq_error = 1e10;
    for(std::vector<geo::Pose3D>::const_iterator it = poses.begin(); it != poses.end(); ++it)
    {
        const geo::Pose3D& laser_pose = *it;

        double z1 = laser_pose.R.xx / grid_resolution;
        double z2 = laser_pose.R.xy / grid_resolution;
        double z3 = laser_pose.R.yx / grid_resolution;
        double z4 = laser_pose.R.yy / grid_resolution;
        double t1 = laser_pose.t.x / grid_resolution - distance_map.cols / 2;
        double t2 = laser_pose.t.y / grid_resolution - distance_map.cols / 2;

        double sum_sq_error = 0;
        for(unsigned int i = 0; i < sensor_points.size(); i += i_step)
        {
            const geo::Vector3& v = sensor_points[i];
            double py = z3 * v.x + z4 * v.y + t2;
            int mx = -py;

            if (mx > 0 && mx < grid_size)
            {
                double px = z1 * v.x + z2 * v.y + t1;
                int my = -px;

                if (my > 0 && my < grid_size)
                {
                    sum_sq_error += distance_map.at<float>(my, mx);
                }
            }
        }

        if (sum_sq_error < min_sum_sq_error)
        {
            min_sum_sq_error = sum_sq_error;
            best_laser_pose_ = laser_pose;
            pose_initialized_ = true;
        }
    }

    std::cout << min_sum_sq_error << std::endl;
    std::cout << best_laser_pose_ << std::endl;

    std::cout << timer.getElapsedTimeInMilliSec() << " ms" << std::endl;

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // -     Visualization
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    bool visualize = true;
    if (visualize)
    {
        cv::Mat rgb_image(distance_map.rows, distance_map.cols, CV_8UC3, cv::Scalar(0, 0, 0));
        for(int y = 0; y < rgb_image.rows; ++y)
        {
            for(int x = 0; x < rgb_image.cols; ++x)
            {
                int c = distance_map.at<float>(y, x) / ((max_dist / grid_resolution) * (max_dist / grid_resolution)) * 255;
                rgb_image.at<cv::Vec3b>(y, x) = cv::Vec3b(c, c, c);
            }
        }

        for(unsigned int i = 0; i < sensor_points.size(); ++i)
        {
            const geo::Vector3& p = best_laser_pose_ * sensor_points[i];
            int mx = -p.y / grid_resolution + grid_size / 2;
            int my = -p.x / grid_resolution + grid_size / 2;

            if (mx >= 0 && my >= 0 && mx < grid_size && my <grid_size)
            {
                rgb_image.at<cv::Vec3b>(my, mx) = cv::Vec3b(0, 255, 0);
            }
        }

        // Visualize sensor
        int lmx = -best_laser_pose_.t.y / grid_resolution + grid_size / 2;
        int lmy = -best_laser_pose_.t.x / grid_resolution + grid_size / 2;
        cv::circle(rgb_image, cv::Point(lmx,lmy), 0.3 / grid_resolution, cv::Scalar(0, 0, 255), 1);

        geo::Vector3 d = best_laser_pose_.R * geo::Vector3(0.3, 0, 0);
        int dmx = -d.y / grid_resolution;
        int dmy = -d.x / grid_resolution;
        cv::line(rgb_image, cv::Point(lmx, lmy), cv::Point(lmx + dmx, lmy + dmy), cv::Scalar(0, 0, 255), 1);

        cv::imshow("distance_map", rgb_image);
        cv::waitKey(1);
    }
}
void InflationLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
{
  boost::unique_lock < boost::recursive_mutex > lock(*inflation_access_);
  if (!enabled_ || (cell_inflation_radius_ == 0))
    return;

  // make sure the inflation list is empty at the beginning of the cycle (should always be true)
  ROS_ASSERT_MSG(inflation_cells_.empty(), "The inflation list must be empty at the beginning of inflation");

  unsigned char* master_array = master_grid.getCharMap();
  unsigned int size_x = master_grid.getSizeInCellsX(), size_y = master_grid.getSizeInCellsY();

  if (seen_ == NULL) {
    ROS_WARN("InflationLayer::updateCosts(): seen_ array is NULL");
    seen_size_ = size_x * size_y;
    seen_ = new bool[seen_size_];
  }
  else if (seen_size_ != size_x * size_y)
  {
    ROS_WARN("InflationLayer::updateCosts(): seen_ array size is wrong");
    delete[] seen_;
    seen_size_ = size_x * size_y;
    seen_ = new bool[seen_size_];
  }
  memset(seen_, false, size_x * size_y * sizeof(bool));

  // We need to include in the inflation cells outside the bounding
  // box min_i...max_j, by the amount cell_inflation_radius_.  Cells
  // up to that distance outside the box can still influence the costs
  // stored in cells inside the box.
  min_i -= cell_inflation_radius_;
  min_j -= cell_inflation_radius_;
  max_i += cell_inflation_radius_;
  max_j += cell_inflation_radius_;

  min_i = std::max(0, min_i);
  min_j = std::max(0, min_j);
  max_i = std::min(int(size_x), max_i);
  max_j = std::min(int(size_y), max_j);

  // Inflation list; we append cells to visit in a list associated with its distance to the nearest obstacle
  // We use a map<distance, list> to emulate the priority queue used before, with a notable performance boost

  // Start with lethal obstacles: by definition distance is 0.0
  std::vector<CellData>& obs_bin = inflation_cells_[0.0];
  for (int j = min_j; j < max_j; j++)
  {
    for (int i = min_i; i < max_i; i++)
    {
      int index = master_grid.getIndex(i, j);
      unsigned char cost = master_array[index];
      if (cost == LETHAL_OBSTACLE)
      {
        obs_bin.push_back(CellData(index, i, j, i, j));
      }
    }
  }

  // Process cells by increasing distance; new cells are appended to the corresponding distance bin, so they
  // can overtake previously inserted but farther away cells
  std::map<double, std::vector<CellData> >::iterator bin;
  for (bin = inflation_cells_.begin(); bin != inflation_cells_.end(); ++bin)
  {
    for (int i = 0; i < bin->second.size(); ++i)
    {
      // process all cells at distance dist_bin.first
      const CellData& cell = bin->second[i];

      unsigned int index = cell.index_;

      // ignore if already visited
      if (seen_[index])
      {
        continue;
      }

      seen_[index] = true;

      unsigned int mx = cell.x_;
      unsigned int my = cell.y_;
      unsigned int sx = cell.src_x_;
      unsigned int sy = cell.src_y_;

      // assign the cost associated with the distance from an obstacle to the cell
      unsigned char cost = costLookup(mx, my, sx, sy);
      unsigned char old_cost = master_array[index];
      if (old_cost == NO_INFORMATION && (inflate_unknown_ ? (cost > FREE_SPACE) : (cost >= INSCRIBED_INFLATED_OBSTACLE)))
        master_array[index] = cost;
      else
        master_array[index] = std::max(old_cost, cost);

      // attempt to put the neighbors of the current cell onto the inflation list
      if (mx > 0)
        enqueue(index - 1, mx - 1, my, sx, sy);
      if (my > 0)
        enqueue(index - size_x, mx, my - 1, sx, sy);
      if (mx < size_x - 1)
        enqueue(index + 1, mx + 1, my, sx, sy);
      if (my < size_y - 1)
        enqueue(index + size_x, mx, my + 1, sx, sy);
    }
  }

  inflation_cells_.clear();
}