Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions apps/multi_view_tls_registration/multi_view_tls_registration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,14 @@ void save_trajectories_to_laz(
}
}

void createDXFPolyline(const std::string& filename, const std::vector<Eigen::Vector3d>& points)
bool createDXFPolyline(const std::string& filename, const std::vector<Eigen::Vector3d>& points)
{
std::ofstream dxfFile(filename);
dxfFile << std::setprecision(20);
if (!dxfFile.is_open())
{
std::cerr << "Failed to open file: " << filename << std::endl;
return;
return false;
}

// DXF header
Expand Down Expand Up @@ -196,10 +196,16 @@ void createDXFPolyline(const std::string& filename, const std::vector<Eigen::Vec
dxfFile << "0\nEOF\n";

dxfFile.close();
if (!dxfFile.good())
{
std::cerr << "Failed to write file: " << filename << std::endl;
return false;
}
std::cout << "DXF file created: " << filename << std::endl;
return true;
}

void save_trajectories(
bool save_trajectories(
Session& session,
std::string output_file_name,
float curve_consecutive_distance_meters,
Expand Down Expand Up @@ -303,12 +309,20 @@ void save_trajectories(
if (!save_to_dxf)
{
outfile.close();
if (!outfile.good())
{
std::cerr << "Failed to write file: " << output_file_name << std::endl;
return false;
}
return true;
}
else
{
createDXFPolyline(output_file_name, polylinePoints);
return createDXFPolyline(output_file_name, polylinePoints);
}
}
std::cerr << "Failed to open file: " << output_file_name << std::endl;
return false;
}

void save_scale_board_to_laz(const Session& session, std::string output_file_name, float dec, float side_len)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ void save_trajectories_to_laz(

void save_scale_board_to_laz(const Session& session, std::string output_file_name, float dec, float side_len = -1.0);

void createDXFPolyline(const std::string& filename, const std::vector<Eigen::Vector3d>& points);
bool createDXFPolyline(const std::string& filename, const std::vector<Eigen::Vector3d>& points);

// void load_available_geo_points(Session& session, std::string input_file_name);

void save_trajectories(
bool save_trajectories(
Session& session,
std::string output_file_name,
float curve_consecutive_distance_meters,
Expand Down
139 changes: 134 additions & 5 deletions apps/multi_view_tls_registration/multi_view_tls_registration_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6548,22 +6548,150 @@ bool initGL(int* argc, char** argv, const std::string& winTitleArg, void (*)(),
return true;
}

int exportSessionToDirectory(const fs::path& input_file, const fs::path& output_directory, bool same_as_gui)
{
const fs::path laz_file = output_directory / "all_step_2.laz";
const fs::path trajectory_file = output_directory / "trajectories.csv";
if (!fs::is_regular_file(input_file))
{
spdlog::error("Session file does not exist or is not a regular file: '{}'", input_file.string());
return 1;
}
if (fs::exists(laz_file) || fs::exists(trajectory_file))
{
spdlog::error("Export files already exist in '{}'; refusing to overwrite them", output_directory.string());
return 1;
}

Session export_session;
if (!export_session.load(
input_file.string(),
same_as_gui && tls_registration.is_decimate,
tls_registration.bucket_x,
tls_registration.bucket_y,
tls_registration.bucket_z,
same_as_gui && tls_registration.calculate_offset))
{
spdlog::error("Failed loading session: '{}'", input_file.string());
return 1;
}
if (export_session.point_clouds_container.point_clouds.empty())
{
spdlog::error("Session contains no point clouds: '{}'", input_file.string());
return 1;
}
bool missing_unix_timestamps = false;
for (const auto& pc : export_session.point_clouds_container.point_clouds)
{
if ((!same_as_gui && pc.points_local.empty()) || pc.local_trajectory.empty())
{
spdlog::error("Point cloud has no points or trajectory: '{}'", pc.file_name);
return 1;
}
missing_unix_timestamps |= std::any_of(
pc.local_trajectory.begin(),
pc.local_trajectory.end(),
[](const auto& node)
{
return node.timestamps.second == 0.0;
});
}
if (missing_unix_timestamps)
spdlog::warn("Some Unix trajectory timestamps are missing; their exported values remain zero");

fs::create_directories(output_directory);
if (!save_all_to_las(export_session, laz_file.string(), false, true))
{
spdlog::error("Failed exporting global LAZ: '{}'", laz_file.string());
return 1;
}
if (!save_trajectories(
export_session,
trajectory_file.string(),
tls_registration.curve_consecutive_distance_meters,
tls_registration.not_curve_consecutive_distance_meters,
same_as_gui && tls_registration.is_trajectory_export_downsampling,
true,
true,
true,
false))
{
spdlog::error("Failed exporting trajectory: '{}'", trajectory_file.string());
return 1;
}
spdlog::info("Exported global LAZ to '{}' and trajectory to '{}'", laz_file.string(), trajectory_file.string());
return 0;
}

int main(int argc, char* argv[])
{
bool export_requested = false;
try
{
if (checkClHelp(argc, argv))
{
std::cout << winTitle << "\n\n"
<< "USAGE:\n"
<< std::filesystem::path(argv[0]).stem().string() << " <input_file> /?\n\n"
<< std::filesystem::path(argv[0]).stem().string() << " <input_file> [--export <directory> [--same-as-gui]] /?\n\n"
<< "where\n"
<< " <input_file> Path to Mandeye JSON Session file (*.mjs)\n"
<< " <input_file> Path to Mandeye JSON Session file (*.mjs, *.json)\n"
<< " --export <directory> Export global LAZ and quaternion CSV with Lidar/Unix timestamps, then exit;\n"
<< " requires *.mjs or *.json, creates directory, refuses existing export files\n"
<< " --same-as-gui Use GUI default loading/export settings (requires --export)\n"
<< " -h, /h, --help, /? Show this help and exit\n\n";

return 0;
}

// Parse optional headless export without changing normal GUI startup.
fs::path export_directory;
bool same_as_gui = false;
std::vector<std::string> input_arguments;
for (int i = 1; i < argc; ++i)
{
if (std::string(argv[i]) == "--export")
{
if (export_requested || i + 1 == argc || std::string(argv[i + 1]).empty() || std::string(argv[i + 1]).rfind("--", 0) == 0)
{
spdlog::error("--export requires exactly one directory argument");
return 1;
}
export_requested = true;
export_directory = argv[++i];
}
else if (std::string(argv[i]) == "--same-as-gui")
{
if (same_as_gui)
{
spdlog::error("--same-as-gui may only be specified once");
return 1;
}
same_as_gui = true;
}
else
input_arguments.emplace_back(argv[i]);
}
if (same_as_gui && !export_requested)
{
spdlog::error("--same-as-gui requires --export");
return 1;
}
if (export_requested)
{
if (input_arguments.size() != 1)
{
spdlog::error("--export requires exactly one session input");
return 1;
}
const std::string ext = lowerExtension(input_arguments.front());
if (ext != ".mjs" && ext != ".json")
{
spdlog::error("Unsupported session extension '{}'; expected .mjs or .json", ext);
return 1;
}
return exportSessionToDirectory(input_arguments.front(), export_directory, same_as_gui);
}

// search for available geoid models in the system and populate the menu
geoids = GNSS::get_available_geoids();

Expand Down Expand Up @@ -6642,14 +6770,15 @@ int main(int argc, char* argv[])
} catch (const std::bad_alloc& e)
{
spdlog::error("System is out of memory : {}", e.what());
mandeye::fd::OutOfMemMessage();
if (!export_requested)
mandeye::fd::OutOfMemMessage();
} catch (const std::exception& e)
{
spdlog::error(e.what());
spdlog::error("{}", e.what());
} catch (...)
{
spdlog::error("Unknown fatal error occurred!");
}

return 0;
return export_requested ? 1 : 0;
}
10 changes: 6 additions & 4 deletions core/include/Core/export_laz.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ inline void save_intersection(
}
}

inline void save_all_to_las(const Session& session, std::string output_las_name, bool as_local, bool skip_ts_0)
inline bool save_all_to_las(const Session& session, std::string output_las_name, bool as_local, bool skip_ts_0)
{
Eigen::Affine3d first_pose = Eigen::Affine3d::Identity();
bool found_first_pose = false;
Expand All @@ -474,7 +474,7 @@ inline void save_all_to_las(const Session& session, std::string output_las_name,
if (!writer.open(output_las_name, offset.x(), offset.y(), offset.z()))
{
std::cout << "problem with saving file: " << output_las_name << std::endl;
return;
return false;
}

for (size_t scan_idx = 0; scan_idx < clouds.size(); ++scan_idx)
Expand Down Expand Up @@ -506,10 +506,12 @@ inline void save_all_to_las(const Session& session, std::string output_las_name,
double ts = (i < p.timestamps.size()) ? p.timestamps[i] : 0.0;

if (!writer.writePoint(vp, inten, ts, offset.x(), offset.y(), offset.z(), psid))
return;
{
return false;
}
}
}
}

writer.close();
return writer.close();
}
12 changes: 12 additions & 0 deletions core/src/point_clouds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ bool PointClouds::load_whu_tls(
if (!infile.good())
{
// std::cout << "problem with file: '" << trj_path.string() << "'" << std::endl;
spdlog::error("Failed opening trajectory: '{}'", trj_path.string());
return false;
}

Expand Down Expand Up @@ -1268,6 +1269,7 @@ bool PointClouds::load_whu_tls(

//// load actual pointclouds
point_clouds.resize(point_clouds_nodata.size());
std::vector<unsigned char> load_success(point_clouds_nodata.size(), 1);

std::transform(
#if USE_EXECUTION_PAR_UNSEQ
Expand All @@ -1292,11 +1294,21 @@ bool PointClouds::load_whu_tls(
// << sum_points_after_decimation << std::endl;
}
}
else
{
load_success[&pc - point_clouds_nodata.data()] = 0;
}
}

return pc;
});

if (std::find(load_success.begin(), load_success.end(), 0) != load_success.end())
{
spdlog::error("Failed loading one or more point clouds");
return false;
}

// calculate average position of a subset of points from all clouds to center the point clouds around the origin
if (calculate_offset)
{
Expand Down
8 changes: 6 additions & 2 deletions core/src/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,12 @@ bool Session::load(const std::string& file_name, bool is_decimate, double bucket
std::cout << "-----------------------------" << std::endl;

// loading all data
point_clouds_container.load_whu_tls(
laz_file_names, is_decimate, bucket_x, bucket_y, bucket_z, calculate_offset, this->load_cache_mode);
if (!point_clouds_container.load_whu_tls(
laz_file_names, is_decimate, bucket_x, bucket_y, bucket_z, calculate_offset, this->load_cache_mode))
{
std::cerr << "Failed loading session point clouds: " << file_name << std::endl;
return false;
}

if (laz_file_names.size() > 0)
{
Expand Down
Loading