Description
Hi!
Basically I have this port of cartographer and I would like to understand how to get the maps more efficiently and prep them for like pathfinding and other stuff. Right now all I am doing is getting all of the submaps and making one big map. I am assuming that that is VERY inefficient in the way that I am using it right now (requesting it every like 0.5 sec).
My code right now that I run to get the map:
`void CartoModule::paint_map(std::vector *output) {
if (isAdded) {
current_map->to_char_array(output);
return;
}
using io::PaintSubmapSlicesResult;
using io::SubmapSlice;
using mapping::SubmapId;
MapInfo info;
pthread_mutex_lock(&mutex);
double resolution = 0.05;
// 获取所有子图的位姿
std::map<SubmapId, SubmapSlice> submap_slices;
auto submap_poses = map_builder->pose_graph()->GetAllSubmapPoses();
for (const auto &submap_id_pose : submap_poses) {
SubmapId submap_id = submap_id_pose.id;
transform::Rigid3d pose = submap_id_pose.data.pose;
int version = submap_id_pose.data.version;
// 查询子图内容
mapping::proto::SubmapQuery::Response response_proto;
const std::string error = map_builder->SubmapToProto(submap_id, &response_proto);
if (!error.empty()) {
// LOG(ERROR) << error;
pthread_mutex_unlock(&mutex);
return;
}
int query_version = response_proto.submap_version();
if (response_proto.textures_size() == 0) {
// LOG(INFO) << "Responds of submap query is empty for submap '" << submap_id.submap_index << "'";
continue;
}
// 提取第一个Texture
auto first_texture = response_proto.textures().begin();
std::string cells = first_texture->cells();
int width = first_texture->width();
int height = first_texture->height();
resolution = first_texture->resolution();
// LOG(INFO) << "############resolution=" << resolution<< "##############";
transform::Rigid3d slice_pose = transform::ToRigid3(first_texture->slice_pose());
auto pixels = io::UnpackTextureData(cells, width, height);
// 填写SubmapSlice
SubmapSlice &submap_slice = submap_slices[submap_id];
submap_slice.pose = pose;
submap_slice.metadata_version = version;
submap_slice.version = query_version;
submap_slice.width = width;
submap_slice.height = height;
submap_slice.slice_pose = slice_pose;
submap_slice.resolution = resolution;
submap_slice.cairo_data.clear();
submap_slice.surface = ::io::DrawTexture(
pixels.intensity, pixels.alpha, width, height,
&submap_slice.cairo_data);
} // for (const auto& submap_id_pose : submap_poses)
pthread_mutex_unlock(&mutex);
// LOG(INFO) << "Get and draw " << submap_slices.size() << " submaps";
// 使用Submap绘制地图
auto painted_slices = PaintSubmapSlices(submap_slices, resolution);
int width = cairo_image_surface_get_width(painted_slices.surface.get());
int height = cairo_image_surface_get_height(painted_slices.surface.get());
info.width = width;
info.height = height;
info.origen_x = -painted_slices.origin.x() * resolution;
info.origen_y = (-height + painted_slices.origin.y()) * resolution;
info.resolution = resolution;
current_map = std::make_unique<SimpleGridMap>(info);
uint32_t *pixel_data = reinterpret_cast<uint32_t *>(cairo_image_surface_get_data(painted_slices.surface.get()));
current_map->datas.reserve(width * height);
for (int y = height - 1; y >= 0; --y) {
for (int x = 0; x < width; ++x) {
const uint32_t packed = pixel_data[y * width + x];
const unsigned char color = packed >> 16;
const unsigned char observed = packed >> 8;
const int value = observed == 0 ? -1 : common::RoundToInt((1. - color / 255.) * 100.);
CHECK_LE(-1, value);
CHECK_GE(100, value);
current_map->datas.push_back((char)value);
}
}
// LOG(INFO) << "Paint map with width " << width << ", height " << height << ", resolution " << resolution;
// isAdded = true;
current_map->to_char_array(output);
};`
I noticed that the "LocalSlamResult" has this thing called "const std::unique_ptr insertion_result." I don't quite understand what that is but my hypothesis is that it is like the submap to which change was made. Am I correct? If so, how can I use it to not have to run the whole rendering of the map many times per second and only run it for a specific submap [that was changed].
My goal is to make a robot that auto-pathfinds around the room and stuff. Although I got the cartographer to work, the only way I can get the map is through that massive function that is (I am assuming) very slow and is not how you are supposed to do it. Is there a proper way to get the map in a 1D vector format with the ints (chars/bytes whatever) representing the color / obstructed not obstructed?