Initial commit

This commit is contained in:
2026-07-03 16:37:12 +07:00
commit 63b8c1ea8b
1931 changed files with 640587 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Common;
/// <summary>
/// Protocol buffer representation of Ceres Solver options.
/// Configure the Ceres solver. See the Ceres documentation for more
/// information: https://code.google.com/p/ceres-solver/
/// </summary>
public struct CeresSolverOptions(
bool useNonmonotonicSteps,
int maxNumIterations,
int numThreads,
double? functionTolerance = null,
double? gradientTolerance = null,
double? parameterTolerance = null)
{
/// <summary>
/// Use non-monotonic steps in the solver.
/// </summary>
[JsonPropertyName("use_nonmonotonic_steps")]
public bool UseNonmonotonicSteps { get; set; } = useNonmonotonicSteps;
/// <summary>
/// Maximum number of iterations for the solver.
/// </summary>
[JsonPropertyName("max_num_iterations")]
public int MaxNumIterations { get; set; } = maxNumIterations;
/// <summary>
/// Number of threads to use in the solver.
/// </summary>
[JsonPropertyName("num_threads")]
public int NumThreads { get; set; } = numThreads;
/// <summary>
/// Function tolerance for convergence check.
/// Minimizer terminates when (new_cost - old_cost) < function_tolerance * old_cost
/// </summary>
[JsonPropertyName("function_tolerance")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? FunctionTolerance { get; set; } = functionTolerance;
/// <summary>
/// Gradient tolerance for convergence check.
/// Minimizer terminates when max_i |x - Project(Plus(x, -g(x))| < gradient_tolerance
/// </summary>
[JsonPropertyName("gradient_tolerance")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? GradientTolerance { get; set; } = gradientTolerance;
/// <summary>
/// Parameter tolerance for convergence check.
/// Minimizer terminates when |step|_2 <= parameter_tolerance * (|x|_2 + parameter_tolerance)
/// </summary>
[JsonPropertyName("parameter_tolerance")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? ParameterTolerance { get; set; } = parameterTolerance;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using CartographerSharp.Models.Transform;
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.GroundTruth;
/// <summary>
/// Relation between two timestamps with expected relative transform.
/// </summary>
public struct Relation
{
[JsonPropertyName("timestamp1")]
public long Timestamp1 { get; set; }
[JsonPropertyName("timestamp2")]
public long Timestamp2 { get; set; }
/// <summary>
/// The 'expected' relative transform of the tracking frame from 'timestamp2'
/// to 'timestamp1'.
/// </summary>
[JsonPropertyName("expected")]
public Rigid3dProto Expected { get; set; }
/// <summary>
/// Covered distance between the two timestamps.
/// </summary>
[JsonPropertyName("covered_distance")]
public double CoveredDistance { get; set; }
}
/// <summary>
/// Ground truth data containing relations.
/// </summary>
public struct GroundTruth
{
[JsonPropertyName("relation")]
public List<Relation> Relations { get; set; }
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of 2D cell limits.
/// </summary>
public struct CellLimits
{
[JsonPropertyName("num_x_cells")]
public int NumXCells { get; set; }
[JsonPropertyName("num_y_cells")]
public int NumYCells { get; set; }
public CellLimits(int numXCells, int numYCells)
{
NumXCells = numXCells;
NumYCells = numYCells;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of Ceres scan matcher options for 2D.
/// </summary>
public struct CeresScanMatcherOptions2D
{
/// <summary>
/// Scaling parameters for each cost functor.
/// </summary>
[JsonPropertyName("occupied_space_weight")]
public double OccupiedSpaceWeight { get; set; }
[JsonPropertyName("translation_weight")]
public double TranslationWeight { get; set; }
[JsonPropertyName("rotation_weight")]
public double RotationWeight { get; set; }
/// <summary>
/// High resolution occupied space weight.
/// Used when matching against high resolution grid.
/// </summary>
[JsonPropertyName("high_res_occupied_space_weight")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? HighResOccupiedSpaceWeight { get; set; }
/// <summary>
/// High resolution translation weight.
/// Used when matching against high resolution grid.
/// </summary>
[JsonPropertyName("high_res_translation_weight")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? HighResTranslationWeight { get; set; }
/// <summary>
/// High resolution rotation weight.
/// Used when matching against high resolution grid.
/// </summary>
[JsonPropertyName("high_res_rotation_weight")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? HighResRotationWeight { get; set; }
/// <summary>
/// Landmark weight.
/// Weight for landmark constraints in scan matching.
/// </summary>
[JsonPropertyName("landmark_weight")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? LandmarkWeight { get; set; }
/// <summary>
/// Ceres solver options.
/// </summary>
[JsonPropertyName("ceres_solver_options")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Models.Common.CeresSolverOptions? CeresSolverOptions { get; set; }
public CeresScanMatcherOptions2D(
double occupiedSpaceWeight,
double translationWeight,
double rotationWeight,
Models.Common.CeresSolverOptions? ceresSolverOptions = null,
double? highResOccupiedSpaceWeight = null,
double? highResTranslationWeight = null,
double? highResRotationWeight = null,
double? landmarkWeight = null)
{
OccupiedSpaceWeight = occupiedSpaceWeight;
TranslationWeight = translationWeight;
RotationWeight = rotationWeight;
CeresSolverOptions = ceresSolverOptions;
HighResOccupiedSpaceWeight = highResOccupiedSpaceWeight;
HighResTranslationWeight = highResTranslationWeight;
HighResRotationWeight = highResRotationWeight;
LandmarkWeight = landmarkWeight;
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Models.Common;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Intensity cost function options for 3D scan matching.
/// </summary>
public struct IntensityCostFunctionOptions3D
{
[JsonPropertyName("weight")]
public double Weight { get; set; }
[JsonPropertyName("huber_scale")]
public double HuberScale { get; set; }
[JsonPropertyName("intensity_threshold")]
public double IntensityThreshold { get; set; }
public IntensityCostFunctionOptions3D(double weight, double huberScale, double intensityThreshold)
{
Weight = weight;
HuberScale = huberScale;
IntensityThreshold = intensityThreshold;
}
}
/// <summary>
/// Protocol buffer representation of Ceres scan matcher options for 3D.
/// </summary>
public struct CeresScanMatcherOptions3D
{
/// <summary>
/// Occupied space weights for each point cloud/grid pair.
/// </summary>
[JsonPropertyName("occupied_space_weight")]
public List<double> OccupiedSpaceWeight { get; set; }
/// <summary>
/// Intensity cost function options for each point cloud/grid pair.
/// </summary>
[JsonPropertyName("intensity_cost_function_options")]
public List<IntensityCostFunctionOptions3D> IntensityCostFunctionOptions { get; set; }
/// <summary>
/// Translation weight.
/// </summary>
[JsonPropertyName("translation_weight")]
public double TranslationWeight { get; set; }
/// <summary>
/// Rotation weight.
/// </summary>
[JsonPropertyName("rotation_weight")]
public double RotationWeight { get; set; }
/// <summary>
/// Only optimize yaw (ignore roll and pitch).
/// </summary>
[JsonPropertyName("only_optimize_yaw")]
public bool OnlyOptimizeYaw { get; set; }
/// <summary>
/// Ceres solver options.
/// </summary>
[JsonPropertyName("ceres_solver_options")]
public CeresSolverOptions? CeresSolverOptions { get; set; }
public CeresScanMatcherOptions3D(
List<double>? occupiedSpaceWeight = null,
List<IntensityCostFunctionOptions3D>? intensityCostFunctionOptions = null,
double translationWeight = 5.0,
double rotationWeight = 200.0,
bool onlyOptimizeYaw = false,
CeresSolverOptions? ceresSolverOptions = null)
{
OccupiedSpaceWeight = occupiedSpaceWeight ?? new List<double> { 5.0 };
IntensityCostFunctionOptions = intensityCostFunctionOptions ?? new List<IntensityCostFunctionOptions3D>();
TranslationWeight = translationWeight;
RotationWeight = rotationWeight;
OnlyOptimizeYaw = onlyOptimizeYaw;
CeresSolverOptions = ceresSolverOptions;
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of constraint builder options.
/// </summary>
public struct ConstraintBuilderOptions
{
/// <summary>
/// A constraint will be added if the proportion of added constraints to
/// potential constraints drops below this number.
/// </summary>
[JsonPropertyName("sampling_ratio")]
public double SamplingRatio { get; set; }
/// <summary>
/// Threshold for poses to be considered near a submap.
/// </summary>
[JsonPropertyName("max_constraint_distance")]
public double MaxConstraintDistance { get; set; }
/// <summary>
/// Threshold for the scan match score below which a match is not considered.
/// Low scores indicate that the scan and map do not look similar.
/// </summary>
[JsonPropertyName("min_score")]
public double MinScore { get; set; }
/// <summary>
/// Threshold below which global localizations are not trusted.
/// </summary>
[JsonPropertyName("global_localization_min_score")]
public double GlobalLocalizationMinScore { get; set; }
/// <summary>
/// Weight used in the optimization problem for the translational component of
/// loop closure constraints.
/// </summary>
[JsonPropertyName("loop_closure_translation_weight")]
public double LoopClosureTranslationWeight { get; set; }
/// <summary>
/// Weight used in the optimization problem for the rotational component of
/// loop closure constraints.
/// </summary>
[JsonPropertyName("loop_closure_rotation_weight")]
public double LoopClosureRotationWeight { get; set; }
/// <summary>
/// If enabled, logs information of loop-closing constraints for debugging.
/// </summary>
[JsonPropertyName("log_matches")]
public bool LogMatches { get; set; }
/// <summary>
/// Options for the fast correlative scan matcher (2D).
/// </summary>
[JsonPropertyName("fast_correlative_scan_matcher_options")]
public FastCorrelativeScanMatcherOptions2D? FastCorrelativeScanMatcherOptions { get; set; }
/// <summary>
/// Options for the Ceres scan matcher (2D).
/// </summary>
[JsonPropertyName("ceres_scan_matcher_options")]
public CeresScanMatcherOptions2D? CeresScanMatcherOptions { get; set; }
/// <summary>
/// Options for the fast correlative scan matcher (3D).
/// </summary>
[JsonPropertyName("fast_correlative_scan_matcher_options_3d")]
public FastCorrelativeScanMatcherOptions3D? FastCorrelativeScanMatcherOptions3D { get; set; }
/// <summary>
/// Options for the Ceres scan matcher (3D).
/// </summary>
[JsonPropertyName("ceres_scan_matcher_options_3d")]
public CeresScanMatcherOptions3D? CeresScanMatcherOptions3D { get; set; }
public ConstraintBuilderOptions()
{
SamplingRatio = 0.3;
MaxConstraintDistance = 15.0;
MinScore = 0.55;
GlobalLocalizationMinScore = 0.6;
LoopClosureTranslationWeight = 1.1e4;
LoopClosureRotationWeight = 1.0;
LogMatches = true;
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of fast correlative scan matcher options for 2D.
/// </summary>
public struct FastCorrelativeScanMatcherOptions2D
{
/// <summary>
/// Linear search window in meters.
/// </summary>
[JsonPropertyName("linear_search_window")]
public double LinearSearchWindow { get; set; }
/// <summary>
/// Angular search window in radians.
/// </summary>
[JsonPropertyName("angular_search_window")]
public double AngularSearchWindow { get; set; }
/// <summary>
/// Branch and bound depth.
/// </summary>
[JsonPropertyName("branch_and_bound_depth")]
public int BranchAndBoundDepth { get; set; }
/// <summary>
/// Linear search window for localization (meters).
/// Used when performing global localization.
/// </summary>
[JsonPropertyName("localization_linear_search_window")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? LocalizationLinearSearchWindow { get; set; }
/// <summary>
/// Angular search window for localization (radians).
/// Used when performing global localization.
/// </summary>
[JsonPropertyName("localization_angular_search_window")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? LocalizationAngularSearchWindow { get; set; }
public FastCorrelativeScanMatcherOptions2D(
double linearSearchWindow = 0.1,
double angularSearchWindow = 0.1,
int branchAndBoundDepth = 7,
double? localizationLinearSearchWindow = null,
double? localizationAngularSearchWindow = null)
{
LinearSearchWindow = linearSearchWindow;
AngularSearchWindow = angularSearchWindow;
BranchAndBoundDepth = branchAndBoundDepth;
LocalizationLinearSearchWindow = localizationLinearSearchWindow;
LocalizationAngularSearchWindow = localizationAngularSearchWindow;
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of fast correlative scan matcher options for 3D.
/// </summary>
public struct FastCorrelativeScanMatcherOptions3D
{
/// <summary>
/// Branch and bound depth.
/// </summary>
[JsonPropertyName("branch_and_bound_depth")]
public int BranchAndBoundDepth { get; set; }
/// <summary>
/// Full resolution depth.
/// </summary>
[JsonPropertyName("full_resolution_depth")]
public int FullResolutionDepth { get; set; }
/// <summary>
/// Minimum rotational score.
/// </summary>
[JsonPropertyName("min_rotational_score")]
public double MinRotationalScore { get; set; }
/// <summary>
/// Minimum low resolution score.
/// </summary>
[JsonPropertyName("min_low_resolution_score")]
public double MinLowResolutionScore { get; set; }
/// <summary>
/// Linear XY search window (meters).
/// </summary>
[JsonPropertyName("linear_xy_search_window")]
public double LinearXySearchWindow { get; set; }
/// <summary>
/// Linear Z search window (meters).
/// </summary>
[JsonPropertyName("linear_z_search_window")]
public double LinearZSearchWindow { get; set; }
/// <summary>
/// Angular search window (radians).
/// </summary>
[JsonPropertyName("angular_search_window")]
public double AngularSearchWindow { get; set; }
public FastCorrelativeScanMatcherOptions3D(
int branchAndBoundDepth = 7,
int fullResolutionDepth = 2,
double minRotationalScore = 0.77,
double minLowResolutionScore = 0.55,
double linearXySearchWindow = 0.1,
double linearZSearchWindow = 0.1,
double angularSearchWindow = 0.1)
{
BranchAndBoundDepth = branchAndBoundDepth;
FullResolutionDepth = fullResolutionDepth;
MinRotationalScore = minRotationalScore;
MinLowResolutionScore = minLowResolutionScore;
LinearXySearchWindow = linearXySearchWindow;
LinearZSearchWindow = linearZSearchWindow;
AngularSearchWindow = angularSearchWindow;
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of a 2D grid.
/// </summary>
public struct Grid2D
{
/// <summary>
/// Cell box for known cells.
/// </summary>
public struct CellBox
{
[JsonPropertyName("max_x")]
public int MaxX { get; set; }
[JsonPropertyName("max_y")]
public int MaxY { get; set; }
[JsonPropertyName("min_x")]
public int MinX { get; set; }
[JsonPropertyName("min_y")]
public int MinY { get; set; }
public CellBox(int maxX, int maxY, int minX, int minY)
{
MaxX = maxX;
MaxY = maxY;
MinX = minX;
MinY = minY;
}
}
[JsonPropertyName("limits")]
public MapLimits Limits { get; set; }
/// <summary>
/// These values are actually int16s, but protos don't have a native int16 type.
/// </summary>
[JsonPropertyName("cells")]
public List<int> Cells { get; set; }
[JsonPropertyName("known_cells_box")]
public CellBox KnownCellsBox { get; set; }
/// <summary>
/// Grid type - oneof probability_grid_2d or tsdf_2d.
/// Using JsonPolymorphic for oneof support in System.Text.Json.
/// </summary>
[JsonPropertyName("probability_grid_2d")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ProbabilityGrid? ProbabilityGrid2D { get; set; }
[JsonPropertyName("tsdf_2d")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public TSDF2D? Tsdf2D { get; set; }
[JsonPropertyName("min_correspondence_cost")]
public double MinCorrespondenceCost { get; set; }
[JsonPropertyName("max_correspondence_cost")]
public double MaxCorrespondenceCost { get; set; }
public Grid2D(
MapLimits limits,
List<int>? cells = null,
CellBox knownCellsBox = default,
ProbabilityGrid? probabilityGrid2D = null,
TSDF2D? tsdf2D = null,
double minCorrespondenceCost = 0.0,
double maxCorrespondenceCost = 0.0)
{
Limits = limits;
Cells = cells ?? new List<int>();
KnownCellsBox = knownCellsBox;
ProbabilityGrid2D = probabilityGrid2D;
Tsdf2D = tsdf2D;
MinCorrespondenceCost = minCorrespondenceCost;
MaxCorrespondenceCost = maxCorrespondenceCost;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of grid options for 2D.
/// </summary>
public struct GridOptions2D
{
public enum GridType
{
InvalidGrid = 0,
ProbabilityGrid = 1,
Tsdf = 2
}
[JsonPropertyName("grid_type")]
public GridType GridTypeValue { get; set; }
[JsonPropertyName("resolution")]
public double Resolution { get; set; }
[JsonPropertyName("tsdf_options")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public TSDFOptions2D? TsdfOptions { get; set; }
public GridOptions2D(GridType gridType, double resolution, TSDFOptions2D? tsdfOptions = null)
{
GridTypeValue = gridType;
Resolution = resolution;
TsdfOptions = tsdfOptions;
}
/// <summary>
/// Options for TSDF2D grid.
/// </summary>
public struct TSDFOptions2D
{
[JsonPropertyName("truncation_distance")]
public double TruncationDistance { get; set; }
[JsonPropertyName("max_weight")]
public double MaxWeight { get; set; }
public TSDFOptions2D(double truncationDistance, double maxWeight)
{
TruncationDistance = truncationDistance;
MaxWeight = maxWeight;
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of a hybrid grid.
/// </summary>
public struct HybridGrid
{
/// <summary>
/// Resolution of the grid.
/// </summary>
[JsonPropertyName("resolution")]
public double Resolution { get; set; }
/// <summary>
/// X indices. '{x, y, z}_indices[i]' is the index of 'values[i]'.
/// </summary>
[JsonPropertyName("x_indices")]
public List<int> XIndices { get; set; }
/// <summary>
/// Y indices.
/// </summary>
[JsonPropertyName("y_indices")]
public List<int> YIndices { get; set; }
/// <summary>
/// Z indices.
/// </summary>
[JsonPropertyName("z_indices")]
public List<int> ZIndices { get; set; }
/// <summary>
/// The entries in 'values' should be uint16s, not int32s, but protos don't
/// have a uint16 type.
/// </summary>
[JsonPropertyName("values")]
public List<int> Values { get; set; }
public HybridGrid(
double resolution,
List<int>? xIndices = null,
List<int>? yIndices = null,
List<int>? zIndices = null,
List<int>? values = null)
{
Resolution = resolution;
XIndices = xIndices ?? new List<int>();
YIndices = yIndices ?? new List<int>();
ZIndices = zIndices ?? new List<int>();
Values = values ?? new List<int>();
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
using CeresSolverOptions = CartographerSharp.Models.Common.CeresSolverOptions;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of IMU-based pose extrapolator options.
/// </summary>
public struct ImuBasedPoseExtrapolatorOptions
{
[JsonPropertyName("pose_queue_duration")]
public double PoseQueueDuration { get; set; }
[JsonPropertyName("gravity_constant")]
public double GravityConstant { get; set; }
[JsonPropertyName("pose_translation_weight")]
public double PoseTranslationWeight { get; set; }
[JsonPropertyName("pose_rotation_weight")]
public double PoseRotationWeight { get; set; }
[JsonPropertyName("imu_acceleration_weight")]
public double ImuAccelerationWeight { get; set; }
[JsonPropertyName("imu_rotation_weight")]
public double ImuRotationWeight { get; set; }
[JsonPropertyName("solver_options")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public CeresSolverOptions? SolverOptions { get; set; }
[JsonPropertyName("odometry_translation_weight")]
public double OdometryTranslationWeight { get; set; }
[JsonPropertyName("odometry_rotation_weight")]
public double OdometryRotationWeight { get; set; }
public ImuBasedPoseExtrapolatorOptions(
double poseQueueDuration = 0.001,
double gravityConstant = 9.806,
double poseTranslationWeight = 1.0,
double poseRotationWeight = 1.0,
double imuAccelerationWeight = 1.0,
double imuRotationWeight = 1.0,
CeresSolverOptions? solverOptions = null,
double odometryTranslationWeight = 1.0,
double odometryRotationWeight = 1.0)
{
PoseQueueDuration = poseQueueDuration;
GravityConstant = gravityConstant;
PoseTranslationWeight = poseTranslationWeight;
PoseRotationWeight = poseRotationWeight;
ImuAccelerationWeight = imuAccelerationWeight;
ImuRotationWeight = imuRotationWeight;
SolverOptions = solverOptions;
OdometryTranslationWeight = odometryTranslationWeight;
OdometryRotationWeight = odometryRotationWeight;
}
}

View File

@@ -0,0 +1,249 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
using AdaptiveVoxelFilterOptions = CartographerSharp.Models.Sensor.AdaptiveVoxelFilterOptions;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of local trajectory builder options for 2D.
/// </summary>
public struct LocalTrajectoryBuilderOptions2D
{
/// <summary>
/// Rangefinder points outside these ranges will be dropped.
/// </summary>
[JsonPropertyName("min_range")]
public double MinRange { get; set; }
[JsonPropertyName("max_range")]
public double MaxRange { get; set; }
[JsonPropertyName("min_z")]
public double MinZ { get; set; }
[JsonPropertyName("max_z")]
public double MaxZ { get; set; }
/// <summary>
/// Points beyond 'max_range' will be inserted with this length as empty space.
/// </summary>
[JsonPropertyName("missing_data_ray_length")]
public double MissingDataRayLength { get; set; }
/// <summary>
/// Number of range data to accumulate into one unwarped, combined range data
/// to use for scan matching.
/// </summary>
[JsonPropertyName("num_accumulated_range_data")]
public int NumAccumulatedRangeData { get; set; }
/// <summary>
/// Voxel filter that gets applied to the range data immediately after cropping.
/// </summary>
[JsonPropertyName("voxel_filter_size")]
public double VoxelFilterSize { get; set; }
/// <summary>
/// Whether to solve the online scan matching first using the correlative scan
/// matcher to generate a good starting point for Ceres.
/// </summary>
[JsonPropertyName("use_online_correlative_scan_matching")]
public bool UseOnlineCorrelativeScanMatching { get; set; }
[JsonPropertyName("real_time_correlative_scan_matcher_options")]
public RealTimeCorrelativeScanMatcherOptions RealTimeCorrelativeScanMatcherOptions { get; set; }
[JsonPropertyName("ceres_scan_matcher_options")]
public CeresScanMatcherOptions2D CeresScanMatcherOptions { get; set; }
[JsonPropertyName("motion_filter_options")]
public MotionFilterOptions MotionFilterOptions { get; set; }
[JsonPropertyName("submaps_options")]
public SubmapsOptions2D SubmapsOptions { get; set; }
/// <summary>
/// True if IMU data should be expected and used.
/// </summary>
[JsonPropertyName("use_imu_data")]
public bool UseImuData { get; set; }
/// <summary>
/// Adaptive voxel filter options for 2D.
/// Used instead of fixed voxel_filter_size when configured.
/// </summary>
[JsonPropertyName("adaptive_voxel_filter_options")]
public Models.Sensor.AdaptiveVoxelFilterOptions AdaptiveVoxelFilterOptions { get; set; }
/// <summary>
/// Voxel filter used to compute a sparser point cloud for finding loop closures.
/// </summary>
[JsonPropertyName("loop_closure_adaptive_voxel_filter_options")]
public Models.Sensor.AdaptiveVoxelFilterOptions LoopClosureAdaptiveVoxelFilterOptions { get; set; }
/// <summary>
/// Time constant in seconds for the orientation moving average based on
/// observed gravity via the IMU. It should be chosen so that the error
/// 1. from acceleration measurements not due to gravity (which gets worse when
/// the constant is reduced) and
/// 2. from integration of angular velocities (which gets worse when the
/// constant is increased) is balanced.
/// TODO(schwoere,wohe): Remove this constant. This is only used for ROS and
/// was replaced by pose_extrapolator_options.
/// </summary>
[JsonPropertyName("imu_gravity_time_constant")]
public double ImuGravityTimeConstant { get; set; }
[JsonPropertyName("pose_extrapolator_options")]
public PoseExtrapolatorOptions PoseExtrapolatorOptions { get; set; }
/// <summary>
/// Scan matcher options used when applying a pending initial pose (SetInitialPose called mid-run).
/// The next accumulated range data uses this pose as prediction and matches with wider search and stricter Ceres.
/// Configured with wider search windows for relocalization scenarios.
/// </summary>
[JsonPropertyName("initial_pose_real_time_correlative_scan_matcher_options")]
public RealTimeCorrelativeScanMatcherOptions InitialPoseRealTimeCorrelativeScanMatcherOptions { get; set; }
[JsonPropertyName("initial_pose_ceres_scan_matcher_options")]
public CeresScanMatcherOptions2D InitialPoseCeresScanMatcherOptions { get; set; }
/// <summary>
/// If true, provides a confidence score for the pose estimate based on
/// real-time correlative scan matching.
/// Match C++: provide_confidence_score option in LocalTrajectoryBuilderOptions2D
/// </summary>
[JsonPropertyName("provide_confidence_score")]
public bool ProvideConfidenceScore { get; set; }
/// <summary>
/// Soft limit for Ceres scan match cost. When ceresScore exceeds this threshold
/// but is below HardLimit, the pose is trusted (AddPose is called) but the scan
/// is NOT inserted into the submap to avoid corrupting the map.
/// Set to 0 to disable. Default: 0 (disabled).
/// DEPRECATED: Use ProbabilityGridCeresScoreSoftLimit / TsdfCeresScoreSoftLimit instead.
/// Kept as fallback when per-grid-type values are not set (both == 0).
/// </summary>
[JsonPropertyName("ceres_score_soft_limit")]
public double CeresScoreSoftLimit { get; set; }
/// <summary>
/// Hard limit for Ceres scan match cost. When ceresScore exceeds this threshold,
/// the scan-matched pose is considered unreliable: neither AddPose nor InsertIntoSubmap
/// is called. The odometry prediction is used instead.
/// Set to 0 to disable. Default: 0 (disabled).
/// Must be >= CeresScoreSoftLimit when both are > 0.
/// DEPRECATED: Use ProbabilityGridCeresScoreHardLimit / TsdfCeresScoreHardLimit instead.
/// Kept as fallback when per-grid-type values are not set (both == 0).
/// </summary>
[JsonPropertyName("ceres_score_hard_limit")]
public double CeresScoreHardLimit { get; set; }
/// <summary>
/// After this many consecutive hard-limit failures, forces creation of a new submap
/// at the current odometry-predicted position. This breaks the deadlock when the robot
/// enters a genuinely new area that cannot match any existing submap.
/// Set to 0 to disable. Default: 5.
/// </summary>
[JsonPropertyName("max_consecutive_high_cost_before_new_submap")]
public int MaxConsecutiveHighCostBeforeNewSubmap { get; set; }
public LocalTrajectoryBuilderOptions2D(
double minRange = 0.0,
double maxRange = 30.0,
double minZ = -0.8f,
double maxZ = 2.0,
double missingDataRayLength = 5.0,
int numAccumulatedRangeData = 1,
double voxelFilterSize = 0.025f,
bool useOnlineCorrelativeScanMatching = true,
RealTimeCorrelativeScanMatcherOptions realTimeCorrelativeScanMatcherOptions = default,
CeresScanMatcherOptions2D ceresScanMatcherOptions = default,
MotionFilterOptions motionFilterOptions = default,
SubmapsOptions2D submapsOptions = default,
bool useImuData = false,
AdaptiveVoxelFilterOptions adaptiveVoxelFilterOptions = default,
AdaptiveVoxelFilterOptions loopClosureAdaptiveVoxelFilterOptions = default,
double imuGravityTimeConstant = 10.0,
PoseExtrapolatorOptions poseExtrapolatorOptions = default,
RealTimeCorrelativeScanMatcherOptions initialPoseRealTimeCorrelativeScanMatcherOptions = default,
CeresScanMatcherOptions2D initialPoseCeresScanMatcherOptions = default,
bool provideConfidenceScore = false,
double ceresScoreSoftLimit = 0,
double ceresScoreHardLimit = 0,
int maxConsecutiveHighCostBeforeNewSubmap = 5)
{
MinRange = minRange;
MaxRange = maxRange;
MinZ = minZ;
MaxZ = maxZ;
MissingDataRayLength = missingDataRayLength;
NumAccumulatedRangeData = numAccumulatedRangeData;
VoxelFilterSize = voxelFilterSize;
UseOnlineCorrelativeScanMatching = useOnlineCorrelativeScanMatching;
// Set default values if not provided (default struct check)
RealTimeCorrelativeScanMatcherOptions = realTimeCorrelativeScanMatcherOptions.Equals(default(RealTimeCorrelativeScanMatcherOptions))
? new RealTimeCorrelativeScanMatcherOptions(linearSearchWindow: 0.1, angularSearchWindow: 0.2)
: realTimeCorrelativeScanMatcherOptions;
CeresScanMatcherOptions = ceresScanMatcherOptions.Equals(default(CeresScanMatcherOptions2D))
? new CeresScanMatcherOptions2D(occupiedSpaceWeight: 1.0, translationWeight: 10.0, rotationWeight: 1.0)
: ceresScanMatcherOptions;
MotionFilterOptions = motionFilterOptions.Equals(default(MotionFilterOptions))
? new MotionFilterOptions(maxTimeSeconds: 5.0, maxDistanceMeters: 0.2, maxAngleRadians: 0.1)
: motionFilterOptions;
SubmapsOptions = submapsOptions.Equals(default(SubmapsOptions2D))
? new SubmapsOptions2D(
numRangeData: 90,
new GridOptions2D(GridOptions2D.GridType.ProbabilityGrid, 0.05f),
new RangeDataInserterOptions(RangeDataInserterOptions.RangeDataInserterType.ProbabilityGridInserter2D))
: submapsOptions;
UseImuData = useImuData;
AdaptiveVoxelFilterOptions = adaptiveVoxelFilterOptions.Equals(default(AdaptiveVoxelFilterOptions))
? new AdaptiveVoxelFilterOptions(maxLength: 0.3, minNumPoints: 250, maxRange: 50.0)
: adaptiveVoxelFilterOptions;
LoopClosureAdaptiveVoxelFilterOptions = loopClosureAdaptiveVoxelFilterOptions.Equals(default(AdaptiveVoxelFilterOptions))
? new AdaptiveVoxelFilterOptions(maxLength: 0.9, minNumPoints: 100, maxRange: 50.0)
: loopClosureAdaptiveVoxelFilterOptions;
ImuGravityTimeConstant = imuGravityTimeConstant;
PoseExtrapolatorOptions = poseExtrapolatorOptions.Equals(default(PoseExtrapolatorOptions))
? new PoseExtrapolatorOptions()
: poseExtrapolatorOptions;
InitialPoseRealTimeCorrelativeScanMatcherOptions = initialPoseRealTimeCorrelativeScanMatcherOptions.Equals(default(RealTimeCorrelativeScanMatcherOptions))
? new RealTimeCorrelativeScanMatcherOptions(linearSearchWindow: 0.5, angularSearchWindow: 0.5)
: initialPoseRealTimeCorrelativeScanMatcherOptions;
InitialPoseCeresScanMatcherOptions = initialPoseCeresScanMatcherOptions.Equals(default(CeresScanMatcherOptions2D))
? new CeresScanMatcherOptions2D(occupiedSpaceWeight: 20.0, translationWeight: 50.0, rotationWeight: 10.0)
: initialPoseCeresScanMatcherOptions;
ProvideConfidenceScore = provideConfidenceScore;
CeresScoreSoftLimit = ceresScoreSoftLimit;
CeresScoreHardLimit = ceresScoreHardLimit;
MaxConsecutiveHighCostBeforeNewSubmap = maxConsecutiveHighCostBeforeNewSubmap;
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Mapping.D3D;
using CartographerSharp.Models.Sensor;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of local trajectory builder options for 3D.
/// </summary>
public struct LocalTrajectoryBuilderOptions3D
{
/// <summary>
/// Rangefinder points outside these ranges will be dropped.
/// </summary>
[JsonPropertyName("min_range")]
public double MinRange { get; set; }
[JsonPropertyName("max_range")]
public double MaxRange { get; set; }
/// <summary>
/// Number of range data to accumulate into one unwarped, combined range data
/// to use for scan matching.
/// </summary>
[JsonPropertyName("num_accumulated_range_data")]
public int NumAccumulatedRangeData { get; set; }
/// <summary>
/// Voxel filter that gets applied to the range data immediately after cropping.
/// </summary>
[JsonPropertyName("voxel_filter_size")]
public double VoxelFilterSize { get; set; }
/// <summary>
/// Voxel filter used to compute a sparser point cloud for matching.
/// </summary>
[JsonPropertyName("high_resolution_adaptive_voxel_filter_options")]
public AdaptiveVoxelFilterOptions? HighResolutionAdaptiveVoxelFilterOptions { get; set; }
[JsonPropertyName("low_resolution_adaptive_voxel_filter_options")]
public AdaptiveVoxelFilterOptions? LowResolutionAdaptiveVoxelFilterOptions { get; set; }
/// <summary>
/// Whether to solve the online scan matching first using the correlative scan
/// matcher to generate a good starting point for Ceres.
/// </summary>
[JsonPropertyName("use_online_correlative_scan_matching")]
public bool UseOnlineCorrelativeScanMatching { get; set; }
[JsonPropertyName("real_time_correlative_scan_matcher_options")]
public RealTimeCorrelativeScanMatcherOptions? RealTimeCorrelativeScanMatcherOptions { get; set; }
[JsonPropertyName("ceres_scan_matcher_options")]
public CeresScanMatcherOptions3D? CeresScanMatcherOptions { get; set; }
[JsonPropertyName("motion_filter_options")]
public MotionFilterOptions MotionFilterOptions { get; set; }
/// <summary>
/// Time constant in seconds for the orientation moving average based on
/// observed gravity via the IMU.
/// </summary>
[JsonPropertyName("imu_gravity_time_constant")]
public double ImuGravityTimeConstant { get; set; }
/// <summary>
/// Number of histogram buckets for the rotational scan matcher.
/// </summary>
[JsonPropertyName("rotational_histogram_size")]
public int RotationalHistogramSize { get; set; }
[JsonPropertyName("pose_extrapolator_options")]
public PoseExtrapolatorOptions PoseExtrapolatorOptions { get; set; }
[JsonPropertyName("initial_poses")]
public List<TimestampedTransform>? InitialPoses { get; set; }
[JsonPropertyName("initial_imu_data")]
public List<Sensor.ImuData>? InitialImuData { get; set; }
[JsonPropertyName("submaps_options")]
public SubmapsOptions3D SubmapsOptions { get; set; }
/// <summary>
/// Whether to use Lidar intensities in Ceres Scan Matcher.
/// </summary>
[JsonPropertyName("use_intensities")]
public bool UseIntensities { get; set; }
public LocalTrajectoryBuilderOptions3D(
double minRange = 0.0,
double maxRange = 60.0,
int numAccumulatedRangeData = 1,
double voxelFilterSize = 0.15f,
AdaptiveVoxelFilterOptions? highResolutionAdaptiveVoxelFilterOptions = null,
AdaptiveVoxelFilterOptions? lowResolutionAdaptiveVoxelFilterOptions = null,
bool useOnlineCorrelativeScanMatching = false,
RealTimeCorrelativeScanMatcherOptions? realTimeCorrelativeScanMatcherOptions = null,
CeresScanMatcherOptions3D? ceresScanMatcherOptions = null,
MotionFilterOptions? motionFilterOptions = null,
double imuGravityTimeConstant = 10.0,
int rotationalHistogramSize = 120,
PoseExtrapolatorOptions? poseExtrapolatorOptions = null,
List<TimestampedTransform>? initialPoses = null,
List<Sensor.ImuData>? initialImuData = null,
SubmapsOptions3D? submapsOptions = null,
bool useIntensities = false)
{
MinRange = minRange;
MaxRange = maxRange;
NumAccumulatedRangeData = numAccumulatedRangeData;
VoxelFilterSize = voxelFilterSize;
HighResolutionAdaptiveVoxelFilterOptions = highResolutionAdaptiveVoxelFilterOptions;
LowResolutionAdaptiveVoxelFilterOptions = lowResolutionAdaptiveVoxelFilterOptions;
UseOnlineCorrelativeScanMatching = useOnlineCorrelativeScanMatching;
RealTimeCorrelativeScanMatcherOptions = realTimeCorrelativeScanMatcherOptions;
CeresScanMatcherOptions = ceresScanMatcherOptions;
MotionFilterOptions = motionFilterOptions ?? new MotionFilterOptions();
ImuGravityTimeConstant = imuGravityTimeConstant;
RotationalHistogramSize = rotationalHistogramSize;
PoseExtrapolatorOptions = poseExtrapolatorOptions ?? new PoseExtrapolatorOptions();
InitialPoses = initialPoses;
InitialImuData = initialImuData;
SubmapsOptions = submapsOptions ?? new SubmapsOptions3D();
UseIntensities = useIntensities;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of map builder options.
/// </summary>
public struct MapBuilderOptions
{
[JsonPropertyName("use_trajectory_builder_2d")]
public bool UseTrajectoryBuilder2D { get; set; }
[JsonPropertyName("use_trajectory_builder_3d")]
public bool UseTrajectoryBuilder3D { get; set; }
/// <summary>
/// Number of threads to use for background computations.
/// </summary>
[JsonPropertyName("num_background_threads")]
public int NumBackgroundThreads { get; set; }
[JsonPropertyName("pose_graph_options")]
public PoseGraphOptions PoseGraphOptions { get; set; }
/// <summary>
/// Sort sensor input independently for each trajectory.
/// </summary>
[JsonPropertyName("collate_by_trajectory")]
public bool CollateByTrajectory { get; set; }
public MapBuilderOptions(
bool useTrajectoryBuilder2D = true,
bool useTrajectoryBuilder3D = false,
int numBackgroundThreads = 4,
PoseGraphOptions? poseGraphOptions = null,
bool collateByTrajectory = false)
{
UseTrajectoryBuilder2D = useTrajectoryBuilder2D;
UseTrajectoryBuilder3D = useTrajectoryBuilder3D;
NumBackgroundThreads = numBackgroundThreads;
PoseGraphOptions = poseGraphOptions ?? new PoseGraphOptions();
CollateByTrajectory = collateByTrajectory;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of map limits.
/// </summary>
public struct MapLimits
{
[JsonPropertyName("resolution")]
public double Resolution { get; set; }
[JsonPropertyName("max")]
public Vector2d Max { get; set; }
[JsonPropertyName("cell_limits")]
public CellLimits CellLimits { get; set; }
public MapLimits(double resolution, Vector2d max, CellLimits cellLimits)
{
Resolution = resolution;
Max = max;
CellLimits = cellLimits;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of motion filter options.
/// </summary>
public struct MotionFilterOptions
{
/// <summary>
/// Threshold above which range data is inserted based on time.
/// </summary>
[JsonPropertyName("max_time_seconds")]
public double MaxTimeSeconds { get; set; }
/// <summary>
/// Threshold above which range data is inserted based on linear motion.
/// </summary>
[JsonPropertyName("max_distance_meters")]
public double MaxDistanceMeters { get; set; }
/// <summary>
/// Threshold above which range data is inserted based on rotational motion.
/// </summary>
[JsonPropertyName("max_angle_radians")]
public double MaxAngleRadians { get; set; }
public MotionFilterOptions(double maxTimeSeconds, double maxDistanceMeters, double maxAngleRadians)
{
MaxTimeSeconds = maxTimeSeconds;
MaxDistanceMeters = maxDistanceMeters;
MaxAngleRadians = maxAngleRadians;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of normal estimation options for 2D.
/// </summary>
public struct NormalEstimationOptions2D
{
[JsonPropertyName("num_normal_samples")]
public int NumNormalSamples { get; set; }
[JsonPropertyName("sample_radius")]
public double SampleRadius { get; set; }
public NormalEstimationOptions2D(int numNormalSamples, double sampleRadius)
{
NumNormalSamples = numNormalSamples;
SampleRadius = sampleRadius;
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of optimization problem options.
/// </summary>
public struct OptimizationProblemOptions
{
[JsonPropertyName("huber_scale")]
public double HuberScale { get; set; }
[JsonPropertyName("odometry_huber_scale")]
public double OdometryHuberScale { get; set; }
[JsonPropertyName("local_slam_pose_huber_scale")]
public double LocalSlamPoseHuberScale { get; set; }
[JsonPropertyName("odometry_translation_weight")]
public double OdometryTranslationWeight { get; set; }
[JsonPropertyName("odometry_rotation_weight")]
public double OdometryRotationWeight { get; set; }
[JsonPropertyName("local_slam_pose_translation_weight")]
public double LocalSlamPoseTranslationWeight { get; set; }
[JsonPropertyName("local_slam_pose_rotation_weight")]
public double LocalSlamPoseRotationWeight { get; set; }
[JsonPropertyName("fixed_frame_pose_translation_weight")]
public double FixedFramePoseTranslationWeight { get; set; }
[JsonPropertyName("fixed_frame_pose_rotation_weight")]
public double FixedFramePoseRotationWeight { get; set; }
[JsonPropertyName("fixed_frame_pose_use_tolerant_loss")]
public bool FixedFramePoseUseTolerantLoss { get; set; }
[JsonPropertyName("fixed_frame_pose_tolerant_loss_param_a")]
public double FixedFramePoseTolerantLossParamA { get; set; }
[JsonPropertyName("fixed_frame_pose_tolerant_loss_param_b")]
public double FixedFramePoseTolerantLossParamB { get; set; }
[JsonPropertyName("log_solver_summary")]
public bool LogSolverSummary { get; set; }
/// <summary>
/// Maximum number of iterations for the Ceres solver.
/// </summary>
[JsonPropertyName("max_num_iterations")]
public int MaxNumIterations { get; set; }
/// <summary>
/// Scaling parameter for the IMU acceleration term.
/// </summary>
[JsonPropertyName("acceleration_weight")]
public double AccelerationWeight { get; set; }
/// <summary>
/// Scaling parameter for the IMU rotation term.
/// </summary>
[JsonPropertyName("rotation_weight")]
public double RotationWeight { get; set; }
public OptimizationProblemOptions()
{
HuberScale = 1.0;
OdometryHuberScale = 1.0;
LocalSlamPoseHuberScale = 1.0;
OdometryTranslationWeight = 1.0;
OdometryRotationWeight = 1.0;
LocalSlamPoseTranslationWeight = 1.0;
LocalSlamPoseRotationWeight = 1.0;
FixedFramePoseTranslationWeight = 1.0;
FixedFramePoseRotationWeight = 1.0;
FixedFramePoseUseTolerantLoss = false;
FixedFramePoseTolerantLossParamA = 1.0;
FixedFramePoseTolerantLossParamB = 1.0;
LogSolverSummary = false;
MaxNumIterations = 50; // Default for pose graph optimization
AccelerationWeight = 8.0; // Default from C++ proto
RotationWeight = 9.0; // Default from C++ proto
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of pose extrapolator options.
/// </summary>
public struct PoseExtrapolatorOptions
{
[JsonPropertyName("use_imu_based")]
public bool UseImuBased { get; set; }
[JsonPropertyName("constant_velocity")]
public ConstantVelocityPoseExtrapolatorOptions ConstantVelocity { get; set; }
[JsonPropertyName("imu_based")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ImuBasedPoseExtrapolatorOptions? ImuBased { get; set; }
/// <summary>
/// Velocity threshold for detecting robot movement (m/s).
/// Robot is considered "moving" if horizontal velocity exceeds this threshold.
/// Default: 0.003 m/s (3 mm/s)
/// </summary>
[JsonPropertyName("velocity_threshold")]
public double? VelocityThreshold { get; set; }
/// <summary>
/// Acceleration threshold for detecting IMU acceleration (m/s²).
/// IMU is considered "accelerating" if horizontal acceleration exceeds this threshold.
/// Default: 0.4 m/s²
/// </summary>
[JsonPropertyName("acceleration_threshold")]
public double? AccelerationThreshold { get; set; }
/// <summary>
/// Gravity deviation threshold for detecting vertical acceleration changes (m/s²).
/// Used to detect changes in vertical acceleration (gravity deviation).
/// Default: 0.1 m/s²
/// </summary>
[JsonPropertyName("gravity_deviation_threshold")]
public double? GravityDeviationThreshold { get; set; }
/// <summary>
/// If true, use odometry pose directly at the time of range data instead of calculating velocity.
/// This is useful when odometry data is accurate and reliable.
/// When enabled, ExtrapolatePose will use the latest odometry data at or before the requested time,
/// instead of extrapolating from the last pose using calculated velocity.
/// Default: false (use velocity-based extrapolation)
/// </summary>
[JsonPropertyName("use_odometry_directly")]
public bool UseOdometryDirectly { get; set; }
public PoseExtrapolatorOptions(
bool useImuBased = false,
ConstantVelocityPoseExtrapolatorOptions? constantVelocity = null,
ImuBasedPoseExtrapolatorOptions? imuBased = null,
double? velocityThreshold = null,
double? accelerationThreshold = null,
double? gravityDeviationThreshold = null,
bool useOdometryDirectly = false)
{
UseImuBased = useImuBased;
ConstantVelocity = constantVelocity ?? new ConstantVelocityPoseExtrapolatorOptions();
ImuBased = imuBased;
VelocityThreshold = velocityThreshold;
AccelerationThreshold = accelerationThreshold;
GravityDeviationThreshold = gravityDeviationThreshold;
UseOdometryDirectly = useOdometryDirectly;
}
}
/// <summary>
/// Constant velocity pose extrapolator options.
/// </summary>
public struct ConstantVelocityPoseExtrapolatorOptions
{
/// <summary>
/// Time constant in seconds for the orientation moving average based on
/// observed gravity via the IMU.
/// </summary>
[JsonPropertyName("imu_gravity_time_constant")]
public double ImuGravityTimeConstant { get; set; }
[JsonPropertyName("pose_queue_duration")]
public double PoseQueueDuration { get; set; }
public ConstantVelocityPoseExtrapolatorOptions(
double imuGravityTimeConstant = 10.0,
double poseQueueDuration = 0.001)
{
ImuGravityTimeConstant = imuGravityTimeConstant;
PoseQueueDuration = poseQueueDuration;
}
}

View File

@@ -0,0 +1,277 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of a pose graph.
/// </summary>
public struct PoseGraph
{
/// <summary>
/// Submap ID.
/// </summary>
public struct SubmapId
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
/// <summary>
/// Submap index in the given trajectory.
/// </summary>
[JsonPropertyName("submap_index")]
public int SubmapIndex { get; set; }
public SubmapId(int trajectoryId, int submapIndex)
{
TrajectoryId = trajectoryId;
SubmapIndex = submapIndex;
}
}
/// <summary>
/// Node ID.
/// </summary>
public struct NodeId
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
/// <summary>
/// Node index in the given trajectory.
/// </summary>
[JsonPropertyName("node_index")]
public int NodeIndex { get; set; }
public NodeId(int trajectoryId, int nodeIndex)
{
TrajectoryId = trajectoryId;
NodeIndex = nodeIndex;
}
}
/// <summary>
/// Constraint in the pose graph.
/// </summary>
public struct Constraint
{
/// <summary>
/// Differentiates between intra-submap (where the range data was inserted
/// into the submap) and inter-submap constraints (where the range data was
/// not inserted into the submap).
/// </summary>
public enum Tag
{
IntraSubmap = 0,
InterSubmap = 1
}
/// <summary>
/// Differentiates between enable state (condition to add to optimization)
/// and disable state (do not use to optimize).
/// </summary>
public enum State
{
Enabled = 0,
Disabled = 1
}
/// <summary>
/// Submap ID.
/// </summary>
[JsonPropertyName("submap_id")]
public SubmapId SubmapId { get; set; }
/// <summary>
/// Node ID.
/// </summary>
[JsonPropertyName("node_id")]
public NodeId NodeId { get; set; }
/// <summary>
/// Pose of the node relative to submap, i.e. taking data from the node frame
/// into the submap frame.
/// </summary>
[JsonPropertyName("relative_pose")]
public Rigid3dProto RelativePose { get; set; }
/// <summary>
/// Weight of the translational part of the constraint.
/// </summary>
[JsonPropertyName("translation_weight")]
public double TranslationWeight { get; set; }
/// <summary>
/// Weight of the rotational part of the constraint.
/// </summary>
[JsonPropertyName("rotation_weight")]
public double RotationWeight { get; set; }
/// <summary>
/// Tag indicating constraint type.
/// </summary>
[JsonPropertyName("tag")]
public Tag ConstraintTag { get; set; }
/// <summary>
/// Score of the constraint.
/// </summary>
[JsonPropertyName("score")]
public double Score { get; set; }
/// <summary>
/// State of the constraint (enabled or disabled).
/// </summary>
[JsonPropertyName("state")]
public State ConstraintState { get; set; }
public Constraint(
SubmapId submapId,
NodeId nodeId,
Rigid3dProto relativePose,
double translationWeight,
double rotationWeight,
Tag constraintTag,
double score = 0.0,
State constraintState = State.Enabled)
{
SubmapId = submapId;
NodeId = nodeId;
RelativePose = relativePose;
TranslationWeight = translationWeight;
RotationWeight = rotationWeight;
ConstraintTag = constraintTag;
Score = score;
ConstraintState = constraintState;
}
}
/// <summary>
/// Landmark pose in the pose graph.
/// </summary>
public struct LandmarkPose
{
[JsonPropertyName("landmark_id")]
public string LandmarkId { get; set; }
[JsonPropertyName("global_pose")]
public Rigid3dProto GlobalPose { get; set; }
public LandmarkPose(string landmarkId, Rigid3dProto globalPose)
{
LandmarkId = landmarkId;
GlobalPose = globalPose;
}
}
/// <summary>
/// Accurate submap in the pose graph.
/// </summary>
public struct AccurateSubmap
{
[JsonPropertyName("submap_id")]
public SubmapId SubmapId { get; set; }
[JsonPropertyName("parent_id")]
public SubmapId ParentId { get; set; }
[JsonPropertyName("pose")]
public Rigid2dProto Pose { get; set; }
[JsonPropertyName("parent_relative_pose")]
public Rigid2dProto ParentRelativePose { get; set; }
/// <summary>
/// Stop station in the accurate submap.
/// </summary>
public struct StopStation
{
public enum StopStationType
{
StartPoint = 0,
StopPoint = 1
}
[JsonPropertyName("pose")]
public Rigid2dProto Pose { get; set; }
[JsonPropertyName("type")]
public StopStationType Type { get; set; }
public StopStation(Rigid2dProto pose, StopStationType type)
{
Pose = pose;
Type = type;
}
}
[JsonPropertyName("stop_stations")]
public List<StopStation> StopStations { get; set; }
[JsonPropertyName("is_shelf")]
public bool IsShelf { get; set; }
public AccurateSubmap(
SubmapId submapId,
SubmapId parentId,
Rigid2dProto pose,
Rigid2dProto parentRelativePose,
List<StopStation>? stopStations = null,
bool isShelf = false)
{
SubmapId = submapId;
ParentId = parentId;
Pose = pose;
ParentRelativePose = parentRelativePose;
StopStations = stopStations ?? new List<StopStation>();
IsShelf = isShelf;
}
}
[JsonPropertyName("constraint")]
public List<Constraint> Constraints { get; set; }
[JsonPropertyName("trajectory")]
public List<Trajectory> Trajectories { get; set; }
[JsonPropertyName("landmark_poses")]
public List<LandmarkPose> LandmarkPoses { get; set; }
[JsonPropertyName("accurate_submaps")]
public List<AccurateSubmap> AccurateSubmaps { get; set; }
[JsonPropertyName("transform_to_map")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Rigid3dProto? TransformToMap { get; set; }
public PoseGraph(
List<Constraint>? constraints = null,
List<Trajectory>? trajectories = null,
List<LandmarkPose>? landmarkPoses = null,
List<AccurateSubmap>? accurateSubmaps = null,
Rigid3dProto? transformToMap = null)
{
Constraints = constraints ?? new List<Constraint>();
Trajectories = trajectories ?? new List<Trajectory>();
LandmarkPoses = landmarkPoses ?? new List<LandmarkPose>();
AccurateSubmaps = accurateSubmaps ?? new List<AccurateSubmap>();
TransformToMap = transformToMap;
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of pose graph options.
/// </summary>
public struct PoseGraphOptions
{
/// <summary>
/// Overlapping submaps trimmer options for 2D.
/// </summary>
public struct OverlappingSubmapsTrimmerOptions2D
{
[JsonPropertyName("fresh_submaps_count")]
public int FreshSubmapsCount { get; set; }
[JsonPropertyName("min_covered_area")]
public double MinCoveredArea { get; set; }
[JsonPropertyName("min_added_submaps_count")]
public int MinAddedSubmapsCount { get; set; }
public OverlappingSubmapsTrimmerOptions2D(int freshSubmapsCount, double minCoveredArea, int minAddedSubmapsCount)
{
FreshSubmapsCount = freshSubmapsCount;
MinCoveredArea = minCoveredArea;
MinAddedSubmapsCount = minAddedSubmapsCount;
}
}
/// <summary>
/// Online loop closure: If positive, will run the loop closure while the map is built.
/// </summary>
[JsonPropertyName("optimize_every_n_nodes")]
public int OptimizeEveryNNodes { get; set; }
/// <summary>
/// Weight used in the optimization problem for the translational component of
/// non-loop-closure scan matcher constraints.
/// </summary>
[JsonPropertyName("matcher_translation_weight")]
public double MatcherTranslationWeight { get; set; }
/// <summary>
/// Weight used in the optimization problem for the rotational component of
/// non-loop-closure scan matcher constraints.
/// </summary>
[JsonPropertyName("matcher_rotation_weight")]
public double MatcherRotationWeight { get; set; }
/// <summary>
/// Number of iterations to use in 'optimization_problem_options' for the final optimization.
/// </summary>
[JsonPropertyName("max_num_final_iterations")]
public int MaxNumFinalIterations { get; set; }
/// <summary>
/// Rate at which we sample a single trajectory's nodes for global localization.
/// </summary>
[JsonPropertyName("global_sampling_ratio")]
public double GlobalSamplingRatio { get; set; }
/// <summary>
/// Whether to output histograms for the pose residuals.
/// </summary>
[JsonPropertyName("log_residual_histograms")]
public bool LogResidualHistograms { get; set; }
/// <summary>
/// If for the duration specified by this option no global constraint has been
/// added between two trajectories, loop closure searches will be performed
/// globally rather than in a smaller search window.
/// </summary>
[JsonPropertyName("global_constraint_search_after_n_seconds")]
public double GlobalConstraintSearchAfterNSeconds { get; set; }
/// <summary>
/// Instantiates the 'OverlappingSubmapsTrimmer2d' which trims submaps from the
/// pose graph based on the area of overlap.
/// </summary>
[JsonPropertyName("overlapping_submaps_trimmer_2d")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public OverlappingSubmapsTrimmerOptions2D? OverlappingSubmapsTrimmer2D { get; set; }
/// <summary>
/// Options for the constraint builder used to find loop closures.
/// </summary>
[JsonPropertyName("constraint_builder_options")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ConstraintBuilderOptions? ConstraintBuilderOptions { get; set; }
/// <summary>
/// Options for the optimization problem.
/// </summary>
[JsonPropertyName("optimization_problem_options")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public OptimizationProblemOptions? OptimizationProblemOptions { get; set; }
/// <summary>
/// Max number of nodes to search for relocalization constraint (match C++ max_number_relocalization_nodes).
/// </summary>
[JsonPropertyName("max_number_relocalization_nodes")]
public int MaxNumberRelocalizationNodes { get; set; } = 12;
/// <summary>
/// Enable loop closure detection within single trajectory.
/// When enabled, uses MatchFullSubmap instead of Match for nodes that are
/// far from their insertion submap but close to older finished submaps.
/// This is an extension to C++ Cartographer which only supports multi-trajectory loop closure.
/// </summary>
[JsonPropertyName("enable_single_trajectory_loop_closure")]
public bool EnableSingleTrajectoryLoopClosure { get; set; } = true;
/// <summary>
/// Distance threshold (in meters) for triggering single-trajectory loop closure.
/// If a node's initial_relative_pose distance to a finished submap exceeds this threshold,
/// but the node is within search range, use MatchFullSubmap for global search.
/// Only used when EnableSingleTrajectoryLoopClosure is true.
/// </summary>
[JsonPropertyName("single_trajectory_loop_closure_distance_threshold")]
public double SingleTrajectoryLoopClosureDistanceThreshold { get; set; } = 3.0;
public PoseGraphOptions(
int optimizeEveryNNodes = 90,
double matcherTranslationWeight = 5e2,
double matcherRotationWeight = 1.6e3,
int maxNumFinalIterations = 200,
double globalSamplingRatio = 0.003,
bool logResidualHistograms = false,
double globalConstraintSearchAfterNSeconds = 0.0,
OverlappingSubmapsTrimmerOptions2D? overlappingSubmapsTrimmer2D = null,
ConstraintBuilderOptions? constraintBuilderOptions = null,
OptimizationProblemOptions? optimizationProblemOptions = null)
{
OptimizeEveryNNodes = optimizeEveryNNodes;
MatcherTranslationWeight = matcherTranslationWeight;
MatcherRotationWeight = matcherRotationWeight;
MaxNumFinalIterations = maxNumFinalIterations;
GlobalSamplingRatio = globalSamplingRatio;
LogResidualHistograms = logResidualHistograms;
GlobalConstraintSearchAfterNSeconds = globalConstraintSearchAfterNSeconds;
OverlappingSubmapsTrimmer2D = overlappingSubmapsTrimmer2D;
ConstraintBuilderOptions = constraintBuilderOptions;
OptimizationProblemOptions = optimizationProblemOptions;
MaxNumberRelocalizationNodes = 12;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of a probability grid.
/// </summary>
public struct ProbabilityGrid
{
// Empty struct - no fields in proto definition
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of probability grid range data inserter options for 2D.
/// </summary>
public struct ProbabilityGridRangeDataInserterOptions2D
{
/// <summary>
/// Probability change for a hit (this will be converted to odds and therefore
/// must be greater than 0.5).
/// </summary>
[JsonPropertyName("hit_probability")]
public double HitProbability { get; set; }
/// <summary>
/// Probability change for a miss (this will be converted to odds and therefore
/// must be less than 0.5).
/// </summary>
[JsonPropertyName("miss_probability")]
public double MissProbability { get; set; }
/// <summary>
/// If 'false', free space will not change the probabilities in the occupancy
/// grid.
/// </summary>
[JsonPropertyName("insert_free_space")]
public bool InsertFreeSpace { get; set; }
public ProbabilityGridRangeDataInserterOptions2D(
double hitProbability,
double missProbability,
bool insertFreeSpace = true)
{
HitProbability = hitProbability;
MissProbability = missProbability;
InsertFreeSpace = insertFreeSpace;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of range data inserter options.
/// </summary>
public struct RangeDataInserterOptions
{
public enum RangeDataInserterType
{
InvalidInserter = 0,
ProbabilityGridInserter2D = 1,
TsdfInserter2D = 2
}
[JsonPropertyName("range_data_inserter_type")]
public RangeDataInserterType RangeDataInserterTypeValue { get; set; }
[JsonPropertyName("probability_grid_range_data_inserter_options_2d")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ProbabilityGridRangeDataInserterOptions2D? ProbabilityGridRangeDataInserterOptions2D { get; set; }
[JsonPropertyName("tsdf_range_data_inserter_options_2d")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public TSDFRangeDataInserterOptions2D? TsdfRangeDataInserterOptions2D { get; set; }
public RangeDataInserterOptions(
RangeDataInserterType rangeDataInserterType,
ProbabilityGridRangeDataInserterOptions2D? probabilityGridRangeDataInserterOptions2D = null,
TSDFRangeDataInserterOptions2D? tsdfRangeDataInserterOptions2D = null)
{
RangeDataInserterTypeValue = rangeDataInserterType;
ProbabilityGridRangeDataInserterOptions2D = probabilityGridRangeDataInserterOptions2D;
TsdfRangeDataInserterOptions2D = tsdfRangeDataInserterOptions2D;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of real-time correlative scan matcher options.
/// </summary>
public struct RealTimeCorrelativeScanMatcherOptions
{
/// <summary>
/// Minimum linear search window in which the best possible scan alignment
/// will be found.
/// </summary>
[JsonPropertyName("linear_search_window")]
public double LinearSearchWindow { get; set; }
/// <summary>
/// Minimum angular search window in which the best possible scan alignment
/// will be found.
/// </summary>
[JsonPropertyName("angular_search_window")]
public double AngularSearchWindow { get; set; }
/// <summary>
/// Weights applied to each part of the score.
/// </summary>
[JsonPropertyName("translation_delta_cost_weight")]
public double TranslationDeltaCostWeight { get; set; }
[JsonPropertyName("rotation_delta_cost_weight")]
public double RotationDeltaCostWeight { get; set; }
/// <summary>
/// Number of threads to use for parallel candidate scoring.
/// If 0 or 1, scoring will be done sequentially.
/// </summary>
[JsonPropertyName("num_threads")]
public int NumThreads { get; set; } = 1;
public RealTimeCorrelativeScanMatcherOptions(
double linearSearchWindow,
double angularSearchWindow,
double translationDeltaCostWeight = 1.0,
double rotationDeltaCostWeight = 1.0,
int numThreads = 1)
{
LinearSearchWindow = linearSearchWindow;
AngularSearchWindow = angularSearchWindow;
TranslationDeltaCostWeight = translationDeltaCostWeight;
RotationDeltaCostWeight = rotationDeltaCostWeight;
NumThreads = numThreads;
}
}

View File

@@ -0,0 +1,268 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Models.Sensor;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Header of the serialization format. At the moment it only contains the version of the format.
/// </summary>
public struct SerializationHeader
{
[JsonPropertyName("format_version")]
public uint FormatVersion { get; set; }
public SerializationHeader(uint formatVersion)
{
FormatVersion = formatVersion;
}
}
/// <summary>
/// Protocol buffer representation of a Submap with ID.
/// </summary>
public struct Submap
{
[JsonPropertyName("submap_id")]
public PoseGraph.SubmapId SubmapId { get; set; }
[JsonPropertyName("submap_2d")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Submap2D? Submap2D { get; set; }
[JsonPropertyName("submap_3d")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Submap3D? Submap3D { get; set; }
public Submap(PoseGraph.SubmapId submapId, Submap2D? submap2D = null, Submap3D? submap3D = null)
{
SubmapId = submapId;
Submap2D = submap2D;
Submap3D = submap3D;
}
}
/// <summary>
/// Protocol buffer representation of a Node with ID.
/// </summary>
public struct Node
{
[JsonPropertyName("node_id")]
public PoseGraph.NodeId NodeId { get; set; }
[JsonPropertyName("node_data")]
public TrajectoryNodeData NodeData { get; set; }
public Node(PoseGraph.NodeId nodeId, TrajectoryNodeData nodeData)
{
NodeId = nodeId;
NodeData = nodeData;
}
}
/// <summary>
/// IMU data with trajectory ID for serialization.
/// </summary>
public struct SerializedImuData
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
[JsonPropertyName("imu_data")]
public Sensor.ImuData ImuDataValue { get; set; }
public SerializedImuData(int trajectoryId, Sensor.ImuData imuData)
{
TrajectoryId = trajectoryId;
ImuDataValue = imuData;
}
}
/// <summary>
/// Odometry data with trajectory ID for serialization.
/// </summary>
public struct SerializedOdometryData
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
[JsonPropertyName("odometry_data")]
public Sensor.OdometryData OdometryDataValue { get; set; }
public SerializedOdometryData(int trajectoryId, Sensor.OdometryData odometryData)
{
TrajectoryId = trajectoryId;
OdometryDataValue = odometryData;
}
}
/// <summary>
/// Fixed frame pose data with trajectory ID for serialization.
/// </summary>
public struct SerializedFixedFramePoseData
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
[JsonPropertyName("fixed_frame_pose_data")]
public Sensor.FixedFramePoseData FixedFramePoseDataValue { get; set; }
public SerializedFixedFramePoseData(int trajectoryId, Sensor.FixedFramePoseData fixedFramePoseData)
{
TrajectoryId = trajectoryId;
FixedFramePoseDataValue = fixedFramePoseData;
}
}
/// <summary>
/// Landmark data with trajectory ID for serialization.
/// </summary>
public struct SerializedLandmarkData
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
[JsonPropertyName("landmark_data")]
public Sensor.LandmarkData LandmarkDataValue { get; set; }
public SerializedLandmarkData(int trajectoryId, Sensor.LandmarkData landmarkData)
{
TrajectoryId = trajectoryId;
LandmarkDataValue = landmarkData;
}
}
/// <summary>
/// Trajectory data for serialization.
/// </summary>
public struct SerializedTrajectoryData
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
[JsonPropertyName("gravity_constant")]
public double GravityConstant { get; set; }
[JsonPropertyName("imu_calibration")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Quaterniond? ImuCalibration { get; set; }
[JsonPropertyName("fixed_frame_origin_in_map")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Rigid3dProto? FixedFrameOriginInMap { get; set; }
public SerializedTrajectoryData(int trajectoryId, double gravityConstant, Quaterniond? imuCalibration = null, Rigid3dProto? fixedFrameOriginInMap = null)
{
TrajectoryId = trajectoryId;
GravityConstant = gravityConstant;
ImuCalibration = imuCalibration;
FixedFrameOriginInMap = fixedFrameOriginInMap;
}
}
/// <summary>
/// Stop station data for serialization.
/// </summary>
public struct StopStationData
{
[JsonPropertyName("id")]
public int Id { get; set; }
[JsonPropertyName("time")]
public long Time { get; set; }
[JsonPropertyName("local_pose")]
public Rigid3dProto LocalPose { get; set; }
public StopStationData(int id, long time, Rigid3dProto localPose)
{
Id = id;
Time = time;
LocalPose = localPose;
}
}
/// <summary>
/// Accurate submap for serialization (different from PoseGraph.AccurateSubmap).
/// </summary>
public struct SerializedAccurateSubmap
{
[JsonPropertyName("submap")]
public Submap Submap { get; set; }
[JsonPropertyName("stop_stations")]
public List<StopStationData> StopStations { get; set; }
public SerializedAccurateSubmap(Submap submap, List<StopStationData>? stopStations = null)
{
Submap = submap;
StopStations = stopStations ?? new List<StopStationData>();
}
}
/// <summary>
/// Serialized data container (oneof in proto).
/// </summary>
public struct SerializedData
{
[JsonPropertyName("serialization_header")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SerializationHeader? SerializationHeader { get; set; }
[JsonPropertyName("pose_graph")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public PoseGraph? PoseGraph { get; set; }
[JsonPropertyName("all_trajectory_builder_options")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public AllTrajectoryBuilderOptions? AllTrajectoryBuilderOptions { get; set; }
[JsonPropertyName("submap")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Submap? Submap { get; set; }
[JsonPropertyName("node")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Node? Node { get; set; }
[JsonPropertyName("trajectory_data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SerializedTrajectoryData? SerializedTrajectoryData { get; set; }
[JsonPropertyName("imu_data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SerializedImuData? ImuData { get; set; }
[JsonPropertyName("odometry_data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SerializedOdometryData? OdometryData { get; set; }
[JsonPropertyName("fixed_frame_pose_data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SerializedFixedFramePoseData? FixedFramePoseData { get; set; }
[JsonPropertyName("landmark_data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SerializedLandmarkData? LandmarkData { get; set; }
[JsonPropertyName("accurate_submap")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SerializedAccurateSubmap? AccurateSubmap { get; set; }
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Active area of the submap.
/// </summary>
public struct ActiveArea
{
[JsonPropertyName("min_x")]
public double MinX { get; set; }
[JsonPropertyName("min_y")]
public double MinY { get; set; }
[JsonPropertyName("max_x")]
public double MaxX { get; set; }
[JsonPropertyName("max_y")]
public double MaxY { get; set; }
[JsonPropertyName("origin")]
public Rigid3dProto Origin { get; set; }
public ActiveArea(double minX, double minY, double maxX, double maxY, Rigid3dProto origin)
{
MinX = minX;
MinY = minY;
MaxX = maxX;
MaxY = maxY;
Origin = origin;
}
}
/// <summary>
/// Serialized state of a Submap2D.
/// </summary>
public struct Submap2D
{
[JsonPropertyName("local_pose")]
public Rigid3dProto LocalPose { get; set; }
[JsonPropertyName("num_range_data")]
public int NumRangeData { get; set; }
[JsonPropertyName("finished")]
public bool Finished { get; set; }
[JsonPropertyName("grid")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Grid2D? Grid { get; set; }
[JsonPropertyName("active_area")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ActiveArea? ActiveArea { get; set; }
[JsonPropertyName("merged_from_others")]
public bool MergedFromOthers { get; set; }
public Submap2D(
Rigid3dProto localPose,
int numRangeData,
bool finished,
Grid2D? grid = null,
ActiveArea? activeArea = null,
bool mergedFromOthers = false)
{
LocalPose = localPose;
NumRangeData = numRangeData;
Finished = finished;
Grid = grid;
ActiveArea = activeArea;
MergedFromOthers = mergedFromOthers;
}
}
/// <summary>
/// Serialized state of a Submap3D.
/// </summary>
public struct Submap3D
{
[JsonPropertyName("local_pose")]
public Rigid3dProto LocalPose { get; set; }
[JsonPropertyName("num_range_data")]
public int NumRangeData { get; set; }
[JsonPropertyName("finished")]
public bool Finished { get; set; }
[JsonPropertyName("high_resolution_hybrid_grid")]
public HybridGrid HighResolutionHybridGrid { get; set; }
[JsonPropertyName("low_resolution_hybrid_grid")]
public HybridGrid LowResolutionHybridGrid { get; set; }
[JsonPropertyName("rotational_scan_matcher_histogram")]
public List<double> RotationalScanMatcherHistogram { get; set; }
public Submap3D(
Rigid3dProto localPose,
int numRangeData,
bool finished,
HybridGrid highResolutionHybridGrid,
HybridGrid lowResolutionHybridGrid,
List<double>? rotationalScanMatcherHistogram = null)
{
LocalPose = localPose;
NumRangeData = numRangeData;
Finished = finished;
HighResolutionHybridGrid = highResolutionHybridGrid;
LowResolutionHybridGrid = lowResolutionHybridGrid;
RotationalScanMatcherHistogram = rotationalScanMatcherHistogram ?? new List<double>();
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of submap query response.
/// </summary>
public struct SubmapQuery
{
public struct Response
{
[JsonPropertyName("submap_version")]
public int SubmapVersion { get; set; }
[JsonPropertyName("textures")]
public List<Texture> Textures { get; set; }
[JsonPropertyName("error_message")]
public string? ErrorMessage { get; set; }
public Response(int submapVersion, List<Texture> textures, string? errorMessage = null)
{
SubmapVersion = submapVersion;
Textures = textures ?? new List<Texture>();
ErrorMessage = errorMessage;
}
}
public struct Texture
{
[JsonPropertyName("cells")]
public List<byte> Cells { get; set; }
[JsonPropertyName("width")]
public int Width { get; set; }
[JsonPropertyName("height")]
public int Height { get; set; }
[JsonPropertyName("resolution")]
public double Resolution { get; set; }
[JsonPropertyName("slice_pose")]
public Transform.Rigid3dProto SlicePose { get; set; }
public Texture(
List<byte> cells,
int width,
int height,
double resolution,
Transform.Rigid3dProto slicePose)
{
Cells = cells ?? new List<byte>();
Width = width;
Height = height;
Resolution = resolution;
SlicePose = slicePose;
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of submaps options for 2D.
/// </summary>
public struct SubmapsOptions2D
{
/// <summary>
/// Number of range data before adding a new submap. Each submap will get twice
/// the number of range data inserted: First for initialization without being
/// matched against, then while being matched.
/// </summary>
[JsonPropertyName("num_range_data")]
public int NumRangeData { get; set; }
[JsonPropertyName("grid_options_2d")]
public GridOptions2D GridOptions2D { get; set; }
[JsonPropertyName("range_data_inserter_options")]
public RangeDataInserterOptions RangeDataInserterOptions { get; set; }
/// <summary>
/// Optional high resolution grid options for fine-grained Ceres scan matching.
/// When set, a second grid at higher resolution is maintained per submap and
/// passed to CeresScanMatcher2D for more precise wall alignment.
/// </summary>
[JsonPropertyName("high_res_grid_options_2d")]
public GridOptions2D? HighResGridOptions2D { get; set; }
public SubmapsOptions2D(
int numRangeData,
GridOptions2D gridOptions2D,
RangeDataInserterOptions rangeDataInserterOptions,
GridOptions2D? highResGridOptions2D = null)
{
NumRangeData = numRangeData;
GridOptions2D = gridOptions2D;
RangeDataInserterOptions = rangeDataInserterOptions;
HighResGridOptions2D = highResGridOptions2D;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of TSDF2D grid.
/// </summary>
public struct TSDF2D
{
[JsonPropertyName("truncation_distance")]
public double TruncationDistance { get; set; }
[JsonPropertyName("max_weight")]
public double MaxWeight { get; set; }
[JsonPropertyName("weight_cells")]
public List<int> WeightCells { get; set; }
public TSDF2D(double truncationDistance, double maxWeight, List<int>? weightCells = null)
{
TruncationDistance = truncationDistance;
MaxWeight = maxWeight;
WeightCells = weightCells ?? new List<int>();
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of TSDF range data inserter options for 2D.
/// </summary>
public struct TSDFRangeDataInserterOptions2D
{
/// <summary>
/// Distance to the surface within the signed distance function is evaluated.
/// </summary>
[JsonPropertyName("truncation_distance")]
public double TruncationDistance { get; set; }
/// <summary>
/// Maximum weight that can be stored in a cell.
/// </summary>
[JsonPropertyName("maximum_weight")]
public double MaximumWeight { get; set; }
/// <summary>
/// Enables updating cells between the sensor origin and the range observation as free space.
/// </summary>
[JsonPropertyName("update_free_space")]
public bool UpdateFreeSpace { get; set; }
[JsonPropertyName("normal_estimation_options")]
public NormalEstimationOptions2D NormalEstimationOptions { get; set; }
/// <summary>
/// Project the distance between the updated cell and the range observation to the estimated scan normal.
/// </summary>
[JsonPropertyName("project_sdf_distance_to_scan_normal")]
public bool ProjectSdfDistanceToScanNormal { get; set; }
/// <summary>
/// Update weight is scaled with 1/distance(origin,hit)^range_exponent.
/// </summary>
[JsonPropertyName("update_weight_range_exponent")]
public int UpdateWeightRangeExponent { get; set; }
/// <summary>
/// Kernel bandwidth of the weight factor based on the angle between scan normal and ray.
/// </summary>
[JsonPropertyName("update_weight_angle_scan_normal_to_ray_kernel_bandwidth")]
public double UpdateWeightAngleScanNormalToRayKernelBandwidth { get; set; }
/// <summary>
/// Kernel bandwidth of the weight factor based on the distance between cell and scan observation.
/// </summary>
[JsonPropertyName("update_weight_distance_cell_to_hit_kernel_bandwidth")]
public double UpdateWeightDistanceCellToHitKernelBandwidth { get; set; }
public TSDFRangeDataInserterOptions2D(
double truncationDistance,
double maximumWeight,
bool updateFreeSpace = false,
NormalEstimationOptions2D normalEstimationOptions = default,
bool projectSdfDistanceToScanNormal = false,
int updateWeightRangeExponent = 0,
double updateWeightAngleScanNormalToRayKernelBandwidth = 0.0,
double updateWeightDistanceCellToHitKernelBandwidth = 0.0)
{
TruncationDistance = truncationDistance;
MaximumWeight = maximumWeight;
UpdateFreeSpace = updateFreeSpace;
NormalEstimationOptions = normalEstimationOptions;
ProjectSdfDistanceToScanNormal = projectSdfDistanceToScanNormal;
UpdateWeightRangeExponent = updateWeightRangeExponent;
UpdateWeightAngleScanNormalToRayKernelBandwidth = updateWeightAngleScanNormalToRayKernelBandwidth;
UpdateWeightDistanceCellToHitKernelBandwidth = updateWeightDistanceCellToHitKernelBandwidth;
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of a trajectory.
/// </summary>
public struct Trajectory
{
/// <summary>
/// Node within a trajectory.
/// </summary>
public struct Node
{
/// <summary>
/// Index of this node within its trajectory.
/// </summary>
[JsonPropertyName("node_index")]
public int NodeIndex { get; set; }
/// <summary>
/// Timestamp of this node.
/// </summary>
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; }
/// <summary>
/// Transform from tracking to global map frame.
/// </summary>
[JsonPropertyName("pose")]
public Rigid3dProto Pose { get; set; }
public Node(int nodeIndex, long timestamp, Rigid3dProto pose)
{
NodeIndex = nodeIndex;
Timestamp = timestamp;
Pose = pose;
}
}
/// <summary>
/// Submap within a trajectory.
/// </summary>
public struct Submap
{
/// <summary>
/// Index of this submap within its trajectory.
/// </summary>
[JsonPropertyName("submap_index")]
public int SubmapIndex { get; set; }
/// <summary>
/// Transform from submap to global map frame.
/// </summary>
[JsonPropertyName("pose")]
public Rigid3dProto Pose { get; set; }
public Submap(int submapIndex, Rigid3dProto pose)
{
SubmapIndex = submapIndex;
Pose = pose;
}
}
/// <summary>
/// ID of this trajectory.
/// </summary>
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
/// <summary>
/// Time-ordered sequence of Nodes.
/// </summary>
[JsonPropertyName("node")]
public List<Node> Nodes { get; set; }
/// <summary>
/// Submaps associated with the trajectory.
/// </summary>
[JsonPropertyName("submap")]
public List<Submap> Submaps { get; set; }
public Trajectory(int trajectoryId, List<Node>? nodes = null, List<Submap>? submaps = null)
{
TrajectoryId = trajectoryId;
Nodes = nodes ?? new List<Node>();
Submaps = submaps ?? new List<Submap>();
}
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of initial trajectory pose.
/// </summary>
public struct InitialTrajectoryPose
{
[JsonPropertyName("relative_pose")]
public Rigid3dProto RelativePose { get; set; }
[JsonPropertyName("to_trajectory_id")]
public int ToTrajectoryId { get; set; }
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; }
public InitialTrajectoryPose(Rigid3dProto relativePose, int toTrajectoryId, long timestamp)
{
RelativePose = relativePose;
ToTrajectoryId = toTrajectoryId;
Timestamp = timestamp;
}
}
/// <summary>
/// Protocol buffer representation of trajectory builder options.
/// Note: LocalTrajectoryBuilderOptions2D and LocalTrajectoryBuilderOptions3D
/// are complex types that will be implemented in later phases.
/// </summary>
public struct TrajectoryBuilderOptions(
System.Text.Json.JsonElement? trajectoryBuilder2DOptions = null,
System.Text.Json.JsonElement? trajectoryBuilder3DOptions = null,
InitialTrajectoryPose? initialTrajectoryPose = null,
TrajectoryBuilderOptions.PureLocalizationTrimmerOptions? pureLocalizationTrimmer = null,
bool collateFixedFrame = false,
bool collateLandmarks = false,
MotionFilterOptions? poseGraphOdometryMotionFilter = null)
{
// Note: These will be implemented as separate proto files in later phases
// For now, we use JsonElement to handle them as raw JSON
[JsonPropertyName("trajectory_builder_2d_options")]
public System.Text.Json.JsonElement? TrajectoryBuilder2DOptions { get; set; } = trajectoryBuilder2DOptions;
[JsonPropertyName("trajectory_builder_3d_options")]
public System.Text.Json.JsonElement? TrajectoryBuilder3DOptions { get; set; } = trajectoryBuilder3DOptions;
[JsonPropertyName("initial_trajectory_pose")]
public InitialTrajectoryPose? InitialTrajectoryPose { get; set; } = initialTrajectoryPose;
[JsonPropertyName("pure_localization")]
[System.Obsolete("Deprecated")]
public bool PureLocalization { get; set; }
/// <summary>
/// Pure localization trimmer options.
/// </summary>
public struct PureLocalizationTrimmerOptions
{
[JsonPropertyName("max_submaps_to_keep")]
public int MaxSubmapsToKeep { get; set; }
public PureLocalizationTrimmerOptions(int maxSubmapsToKeep)
{
MaxSubmapsToKeep = maxSubmapsToKeep;
}
}
[JsonPropertyName("pure_localization_trimmer")]
public PureLocalizationTrimmerOptions? PureLocalizationTrimmer { get; set; } = pureLocalizationTrimmer;
[JsonPropertyName("collate_fixed_frame")]
public bool CollateFixedFrame { get; set; } = collateFixedFrame;
[JsonPropertyName("collate_landmarks")]
public bool CollateLandmarks { get; set; } = collateLandmarks;
[JsonPropertyName("pose_graph_odometry_motion_filter")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public MotionFilterOptions? PoseGraphOdometryMotionFilter { get; set; } = poseGraphOdometryMotionFilter;
}
/// <summary>
/// Protocol buffer representation of sensor ID.
/// </summary>
public struct SensorId
{
/// <summary>
/// Sensor type enumeration.
/// </summary>
public enum SensorType
{
Range = 0,
Imu = 1,
Odometry = 2,
FixedFramePose = 3,
Landmark = 4,
LocalSlamResult = 5
}
[JsonPropertyName("type")]
public SensorType Type { get; set; }
[JsonPropertyName("id")]
public string Id { get; set; }
public SensorId(SensorType type, string id)
{
Type = type;
Id = id;
}
}
/// <summary>
/// Protocol buffer representation of trajectory builder options with sensor IDs.
/// </summary>
public struct TrajectoryBuilderOptionsWithSensorIds
{
[JsonPropertyName("sensor_id")]
public List<SensorId> SensorIds { get; set; }
[JsonPropertyName("trajectory_builder_options")]
public TrajectoryBuilderOptions TrajectoryBuilderOptions { get; set; }
public TrajectoryBuilderOptionsWithSensorIds(
List<SensorId>? sensorIds = null,
TrajectoryBuilderOptions trajectoryBuilderOptions = default)
{
SensorIds = sensorIds ?? new List<SensorId>();
TrajectoryBuilderOptions = trajectoryBuilderOptions;
}
}
/// <summary>
/// Protocol buffer representation of all trajectory builder options.
/// </summary>
public struct AllTrajectoryBuilderOptions
{
[JsonPropertyName("options_with_sensor_ids")]
public List<TrajectoryBuilderOptionsWithSensorIds> OptionsWithSensorIds { get; set; }
public AllTrajectoryBuilderOptions(List<TrajectoryBuilderOptionsWithSensorIds>? optionsWithSensorIds = null)
{
OptionsWithSensorIds = optionsWithSensorIds ?? new List<TrajectoryBuilderOptionsWithSensorIds>();
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Protocol buffer representation of trajectory data.
/// </summary>
public struct TrajectoryData
{
[JsonPropertyName("trajectory_id")]
public int TrajectoryId { get; set; }
[JsonPropertyName("gravity_constant")]
public double GravityConstant { get; set; }
[JsonPropertyName("imu_calibration")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Quaterniond? ImuCalibration { get; set; }
[JsonPropertyName("fixed_frame_origin_in_map")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Rigid3dProto? FixedFrameOriginInMap { get; set; }
public TrajectoryData(
int trajectoryId,
double gravityConstant = 9.8,
Quaterniond? imuCalibration = null,
Rigid3dProto? fixedFrameOriginInMap = null)
{
TrajectoryId = trajectoryId;
GravityConstant = gravityConstant;
ImuCalibration = imuCalibration;
FixedFrameOriginInMap = fixedFrameOriginInMap;
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2017 The Cartographer Authors
*
* 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.
*/
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CartographerSharp.Models.Sensor;
using CartographerSharp.Models.Transform;
namespace CartographerSharp.Models.Mapping;
/// <summary>
/// Serialized state of a mapping::TrajectoryNode::Data.
/// </summary>
public struct TrajectoryNodeData
{
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; }
[JsonPropertyName("gravity_alignment")]
public Quaterniond GravityAlignment { get; set; }
[JsonPropertyName("filtered_gravity_aligned_point_cloud")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public CompressedPointCloud? FilteredGravityAlignedPointCloud { get; set; }
[JsonPropertyName("high_resolution_point_cloud")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public CompressedPointCloud? HighResolutionPointCloud { get; set; }
[JsonPropertyName("low_resolution_point_cloud")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public CompressedPointCloud? LowResolutionPointCloud { get; set; }
[JsonPropertyName("rotational_scan_matcher_histogram")]
public List<double>? RotationalScanMatcherHistogram { get; set; }
[JsonPropertyName("local_pose")]
public Rigid3dProto LocalPose { get; set; }
public TrajectoryNodeData(
long timestamp,
Quaterniond gravityAlignment,
Rigid3dProto localPose,
CompressedPointCloud? filteredGravityAlignedPointCloud = null,
CompressedPointCloud? highResolutionPointCloud = null,
CompressedPointCloud? lowResolutionPointCloud = null,
List<double>? rotationalScanMatcherHistogram = null)
{
Timestamp = timestamp;
GravityAlignment = gravityAlignment;
LocalPose = localPose;
FilteredGravityAlignedPointCloud = filteredGravityAlignedPointCloud;
HighResolutionPointCloud = highResolutionPointCloud;
LowResolutionPointCloud = lowResolutionPointCloud;
RotationalScanMatcherHistogram = rotationalScanMatcherHistogram;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Sensor;
/// <summary>
/// Protocol buffer representation of adaptive voxel filter options.
/// </summary>
public struct AdaptiveVoxelFilterOptions(double maxLength, double minNumPoints, double maxRange)
{
/// <summary>
/// Maximum length of a voxel edge.
/// </summary>
[JsonPropertyName("max_length")]
public double MaxLength { get; set; } = maxLength;
/// <summary>
/// If there are more points and not at least 'min_num_points' remain, the
/// voxel length is reduced trying to get this minimum number of points.
/// </summary>
[JsonPropertyName("min_num_points")]
public double MinNumPoints { get; set; } = minNumPoints;
/// <summary>
/// Points further away from the origin are removed.
/// </summary>
[JsonPropertyName("max_range")]
public double MaxRange { get; set; } = maxRange;
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using CartographerSharp.Models.Transform;
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Sensor;
/// <summary>
/// Protocol buffer representation of a rangefinder point.
/// </summary>
public struct RangefinderPoint(Vector3f position)
{
[JsonPropertyName("position")]
public Vector3f Position { get; set; } = position;
}
/// <summary>
/// Protocol buffer representation of a timed rangefinder point.
/// </summary>
public struct TimedRangefinderPoint(Vector3f position, double time)
{
[JsonPropertyName("position")]
public Vector3f Position { get; set; } = position;
[JsonPropertyName("time")]
public double Time { get; set; } = time;
}
/// <summary>
/// Compressed collection of a 3D point cloud.
/// </summary>
public struct CompressedPointCloud(int numPoints, List<int> pointData)
{
[JsonPropertyName("num_points")]
public int NumPoints { get; set; } = numPoints;
[JsonPropertyName("point_data")]
public List<int> PointData { get; set; } = pointData ?? [];
}
/// <summary>
/// Proto representation of ::cartographer::sensor::TimedPointCloudData.
/// </summary>
public struct TimedPointCloudData(
long timestamp,
Vector3f origin,
List<Vector4f>? pointDataLegacy = null,
List<TimedRangefinderPoint>? pointData = null,
List<double>? intensities = null)
{
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; } = timestamp;
[JsonPropertyName("origin")]
public Vector3f Origin { get; set; } = origin;
[JsonPropertyName("point_data_legacy")]
public List<Vector4f> PointDataLegacy { get; set; } = pointDataLegacy ?? [];
[JsonPropertyName("point_data")]
public List<TimedRangefinderPoint> PointData { get; set; } = pointData ?? [];
[JsonPropertyName("intensities")]
public List<double> Intensities { get; set; } = intensities ?? [];
}
/// <summary>
/// Proto representation of ::cartographer::sensor::RangeData.
/// </summary>
public struct RangeData(
Vector3f origin,
List<Vector3f>? returnsLegacy = null,
List<Vector3f>? missesLegacy = null,
List<RangefinderPoint>? returns = null,
List<RangefinderPoint>? misses = null)
{
[JsonPropertyName("origin")]
public Vector3f Origin { get; set; } = origin;
[JsonPropertyName("returns_legacy")]
public List<Vector3f> ReturnsLegacy { get; set; } = returnsLegacy ?? [];
[JsonPropertyName("misses_legacy")]
public List<Vector3f> MissesLegacy { get; set; } = missesLegacy ?? [];
[JsonPropertyName("returns")]
public List<RangefinderPoint> Returns { get; set; } = returns ?? [];
[JsonPropertyName("misses")]
public List<RangefinderPoint> Misses { get; set; } = misses ?? [];
}
/// <summary>
/// Proto representation of ::cartographer::sensor::ImuData.
/// </summary>
public struct ImuData(long timestamp, Vector3d linearAcceleration, Vector3d angularVelocity)
{
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; } = timestamp;
[JsonPropertyName("linear_acceleration")]
public Vector3d LinearAcceleration { get; set; } = linearAcceleration;
[JsonPropertyName("angular_velocity")]
public Vector3d AngularVelocity { get; set; } = angularVelocity;
}
/// <summary>
/// Proto representation of ::cartographer::sensor::OdometryData.
/// </summary>
public struct OdometryData(long timestamp, Rigid3dProto pose)
{
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; } = timestamp;
[JsonPropertyName("pose")]
public Rigid3dProto Pose { get; set; } = pose;
}
/// <summary>
/// Proto representation of ::cartographer::sensor::FixedFramePoseData.
/// </summary>
public struct FixedFramePoseData(long timestamp, Rigid3dProto pose)
{
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; } = timestamp;
[JsonPropertyName("pose")]
public Rigid3dProto Pose { get; set; } = pose;
}
/// <summary>
/// Proto representation of ::cartographer::sensor::LandmarkData.
/// </summary>
public struct LandmarkData(long timestamp, List<LandmarkData.LandmarkObservation>? landmarkObservations = null)
{
/// <summary>
/// Landmark observation within LandmarkData.
/// </summary>
public struct LandmarkObservation(
byte[] id,
Rigid3dProto landmarkToTrackingTransform,
double translationWeight,
double rotationWeight)
{
[JsonPropertyName("id")]
public byte[] Id { get; set; } = id ?? [];
[JsonPropertyName("landmark_to_tracking_transform")]
public Rigid3dProto LandmarkToTrackingTransform { get; set; } = landmarkToTrackingTransform;
[JsonPropertyName("translation_weight")]
public double TranslationWeight { get; set; } = translationWeight;
[JsonPropertyName("rotation_weight")]
public double RotationWeight { get; set; } = rotationWeight;
}
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; } = timestamp;
[JsonPropertyName("landmark_observations")]
public List<LandmarkObservation> LandmarkObservations { get; set; } = landmarkObservations ?? [];
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2018 The Cartographer Authors
*
* 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.
*/
using CartographerSharp.Common.Time;
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Transform;
/// <summary>
/// Protocol buffer representation of a timestamped 3D transformation.
/// </summary>
public struct TimestampedTransform(long time, Rigid3dProto transform)
{
/// <summary>
/// Time in Universal Time Scale ticks (100 nanosecond ticks since epoch).
/// </summary>
[JsonPropertyName("time")]
public long Time { get; set; } = time;
/// <summary>
/// The 3D transformation.
/// </summary>
[JsonPropertyName("transform")]
public Rigid3dProto Transform { get; set; } = transform;
/// <summary>
/// Creates a TimestampedTransform from a DateTime and Rigid3d.
/// </summary>
public static TimestampedTransform FromDateTime(DateTime time, CartographerSharp.Transform.Rigid3d transform)
{
return new TimestampedTransform(
TimeUtils.ToUniversal(time),
transform
);
}
/// <summary>
/// Converts the time to a DateTime.
/// </summary>
public readonly DateTime ToDateTime()
{
return TimeUtils.FromUniversal(Time);
}
}

View File

@@ -0,0 +1,235 @@
/*
* Copyright 2016 The Cartographer Authors
*
* 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.
*/
using CartographerSharp.Transform;
using RobotNet10.Shared.Numbers;
using System.Text.Json.Serialization;
namespace CartographerSharp.Models.Transform;
/// <summary>
/// Protocol buffer representation of a 2D vector (double precision).
/// </summary>
public struct Vector2d(double x, double y)
{
[JsonPropertyName("x")]
public double X { get; set; } = x;
[JsonPropertyName("y")]
public double Y { get; set; } = y;
public static implicit operator Vector2(Vector2d v) => new(v.X, v.Y);
public static implicit operator Vector2d(Vector2 v) => new(v.X, v.Y);
}
/// <summary>
/// Protocol buffer representation of a 2D vector (single precision).
/// </summary>
public struct Vector2f(double x, double y)
{
[JsonPropertyName("x")]
public double X { get; set; } = x;
[JsonPropertyName("y")]
public double Y { get; set; } = y;
public static implicit operator Vector2(Vector2f v) => new(v.X, v.Y);
public static implicit operator Vector2f(Vector2 v) => new(v.X, v.Y);
}
/// <summary>
/// Protocol buffer representation of a 3D vector (double precision).
/// </summary>
public struct Vector3d(double x, double y, double z)
{
[JsonPropertyName("x")]
public double X { get; set; } = x;
[JsonPropertyName("y")]
public double Y { get; set; } = y;
[JsonPropertyName("z")]
public double Z { get; set; } = z;
public static implicit operator Vector3(Vector3d v) => new(v.X, v.Y, v.Z);
public static implicit operator Vector3d(Vector3 v) => new(v.X, v.Y, v.Z);
}
/// <summary>
/// Protocol buffer representation of a 3D vector (single precision).
/// </summary>
public struct Vector3f(double x, double y, double z)
{
[JsonPropertyName("x")]
public double X { get; set; } = x;
[JsonPropertyName("y")]
public double Y { get; set; } = y;
[JsonPropertyName("z")]
public double Z { get; set; } = z;
public static implicit operator Vector3(Vector3f v) => new(v.X, v.Y, v.Z);
public static implicit operator Vector3f(Vector3 v) => new(v.X, v.Y, v.Z);
}
/// <summary>
/// Protocol buffer representation of a 4D vector (single precision).
/// </summary>
public struct Vector4f(double x, double y, double z, double t)
{
[JsonPropertyName("x")]
public double X { get; set; } = x;
[JsonPropertyName("y")]
public double Y { get; set; } = y;
[JsonPropertyName("z")]
public double Z { get; set; } = z;
[JsonPropertyName("t")]
public double T { get; set; } = t;
}
/// <summary>
/// Protocol buffer representation of a quaternion (double precision).
/// </summary>
public struct Quaterniond(double x, double y, double z, double w)
{
[JsonPropertyName("x")]
public double X { get; set; } = x;
[JsonPropertyName("y")]
public double Y { get; set; } = y;
[JsonPropertyName("z")]
public double Z { get; set; } = z;
[JsonPropertyName("w")]
public double W { get; set; } = w;
public static implicit operator Quaternion(Quaterniond q) => new(q.X, q.Y, q.Z, q.W);
public static implicit operator Quaterniond(Quaternion q) => new(q.X, q.Y, q.Z, q.W);
}
/// <summary>
/// Protocol buffer representation of a quaternion (single precision).
/// </summary>
public struct Quaternionf(double x, double y, double z, double w)
{
[JsonPropertyName("x")]
public double X { get; set; } = x;
[JsonPropertyName("y")]
public double Y { get; set; } = y;
[JsonPropertyName("z")]
public double Z { get; set; } = z;
[JsonPropertyName("w")]
public double W { get; set; } = w;
public static implicit operator Quaternion(Quaternionf q) => new(q.X, q.Y, q.Z, q.W);
public static implicit operator Quaternionf(Quaternion q) => new(q.X, q.Y, q.Z, q.W);
}
/// <summary>
/// Protocol buffer representation of a rigid 2D transformation (double precision).
/// </summary>
public struct Rigid2dProto(Vector2d translation, double rotation)
{
[JsonPropertyName("translation")]
public Vector2d Translation { get; set; } = translation;
[JsonPropertyName("rotation")]
public double Rotation { get; set; } = rotation;
public static implicit operator Rigid2d(Rigid2dProto proto)
{
return new Rigid2d(proto.Translation, proto.Rotation);
}
public static implicit operator Rigid2dProto(Rigid2d rigid)
{
return new Rigid2dProto(rigid.Translation, rigid.Rotation);
}
}
/// <summary>
/// Protocol buffer representation of a rigid 2D transformation (single precision).
/// </summary>
public struct Rigid2fProto(Vector2f translation, double rotation)
{
[JsonPropertyName("translation")]
public Vector2f Translation { get; set; } = translation;
[JsonPropertyName("rotation")]
public double Rotation { get; set; } = rotation;
public static implicit operator Rigid2f(Rigid2fProto proto)
{
return new Rigid2f(proto.Translation, proto.Rotation);
}
public static implicit operator Rigid2fProto(Rigid2f rigid)
{
return new Rigid2fProto(rigid.Translation, rigid.Rotation);
}
}
/// <summary>
/// Protocol buffer representation of a rigid 3D transformation (double precision).
/// </summary>
public struct Rigid3dProto(Vector3d translation, Quaterniond rotation)
{
[JsonPropertyName("translation")]
public Vector3d Translation { get; set; } = translation;
[JsonPropertyName("rotation")]
public Quaterniond Rotation { get; set; } = rotation;
public static implicit operator Rigid3d(Rigid3dProto proto)
{
return new Rigid3d(proto.Translation, proto.Rotation);
}
public static implicit operator Rigid3dProto(Rigid3d rigid)
{
return new Rigid3dProto(rigid.Translation, rigid.Rotation);
}
}
/// <summary>
/// Protocol buffer representation of a rigid 3D transformation (single precision).
/// </summary>
public struct Rigid3fProto(Vector3f translation, Quaternionf rotation)
{
[JsonPropertyName("translation")]
public Vector3f Translation { get; set; } = translation;
[JsonPropertyName("rotation")]
public Quaternionf Rotation { get; set; } = rotation;
public static implicit operator Rigid3f(Rigid3fProto proto)
{
return new Rigid3f(proto.Translation, proto.Rotation);
}
public static implicit operator Rigid3fProto(Rigid3f rigid)
{
return new Rigid3fProto(rigid.Translation, rigid.Rotation);
}
}