/* * 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.Sensor; using CartographerSharp.Transform; using RobotNet10.Shared.Numbers; namespace CartographerSharp.Mapping; /// /// Interface for pose graph operations. /// public interface IPoseGraph { /// /// A "constraint" as in the paper by Konolige, Kurt, et al. "Efficient sparse /// pose adjustment for 2d mapping." Intelligent Robots and Systems (IROS), /// 2010 IEEE/RSJ International Conference on (pp. 22--29). IEEE, 2010. /// public struct Constraint(SubmapId submapId, NodeId nodeId, Constraint.Pose pose, Constraint.Tag tag, double score = 0.0, Constraint.State state = Constraint.State.Enabled) { /// /// Constraint pose information. /// public struct Pose(Rigid3d zbarIj, double translationWeight, double rotationWeight) { public Rigid3d ZbarIj { get; set; } = zbarIj; public double TranslationWeight { get; set; } = translationWeight; public double RotationWeight { get; set; } = rotationWeight; } public SubmapId SubmapId { get; set; } = submapId; public NodeId NodeId { get; set; } = nodeId; /// /// Pose of the node 'j' relative to submap 'i'. /// public Pose ConstraintPose { get; set; } = pose; /// /// Differentiates between intra-submap (where node 'j' was inserted into /// submap 'i') and inter-submap constraints (where node 'j' was not inserted /// into submap 'i'). /// public enum Tag { IntraSubmap, InterSubmap } public Tag ConstraintTag { get; set; } = tag; /// /// Match C++: score field for constraint quality. /// public double Score { get; set; } = score; /// /// Match C++: state enum for enabled/disabled constraints. /// public enum State { Enabled, Disabled } public State ConstraintState { get; set; } = state; } /// /// Landmark node information. /// public struct LandmarkNode( List? landmarkObservations = null, Rigid3d? globalLandmarkPose = null, bool frozen = false) { /// /// Landmark observation. /// public struct LandmarkObservation( int trajectoryId, long time, Rigid3d landmarkToTrackingTransform, double translationWeight, double rotationWeight) { public int TrajectoryId { get; set; } = trajectoryId; public long Time { get; set; } = time; public Rigid3d LandmarkToTrackingTransform { get; set; } = landmarkToTrackingTransform; public double TranslationWeight { get; set; } = translationWeight; public double RotationWeight { get; set; } = rotationWeight; } public List LandmarkObservations { get; set; } = landmarkObservations ?? []; public Rigid3d? GlobalLandmarkPose { get; set; } = globalLandmarkPose; public bool Frozen { get; set; } = frozen; } /// /// Submap pose information. /// public struct SubmapPose(int version, Rigid3d pose) { public int Version { get; set; } = version; public Rigid3d Pose { get; set; } = pose; } /// /// Submap data with pose. /// public struct SubmapData(Submap? submap, Rigid3d pose) { public Submap? Submap { get; set; } = submap; public Rigid3d Pose { get; set; } = pose; } /// /// Trajectory data. /// public struct TrajectoryData( double gravityConstant = 9.8, Quaternion? imuCalibration = null, Rigid3d? fixedFrameOriginInMap = null) { public double GravityConstant { get; set; } = gravityConstant; public Quaternion ImuCalibration { get; set; } = imuCalibration ?? Quaternion.Identity; public Rigid3d? FixedFrameOriginInMap { get; set; } = fixedFrameOriginInMap; } /// /// Trajectory state enumeration. /// public enum TrajectoryState { Active, Finished, Frozen, Deleted } /// /// Gets the total number of work items added to the work queue. /// public int WorkItemsAdded { get; } /// /// Gets the total number of work items completed by the work queue. /// public int WorkItemsCompleted { get; } /// /// Gets the number of work items currently pending in the work queue. /// public int WorkItemsPending { get; } /// /// Gets the current number of items in the work queue. /// public int WorkQueueCount { get; } /// /// Gets the number of nodes started in the constraint builder. /// public int ConstraintBuilderNodesStarted { get; } /// /// Gets the number of nodes finished in the constraint builder. /// public int ConstraintBuilderNodesFinished { get; } /// /// Gets the total number of trajectory nodes in the pose graph. /// Used for progress tracking during optimization. /// public int TrajectoryNodesCount { get; } /// /// Gets the total number of constraint tasks dispatched for scan matching. /// public int ConstraintTasksTotal { get; } /// /// Gets the number of constraint tasks that have finished scan matching. /// public int ConstraintTasksFinished { get; } /// /// Inserts an IMU measurement. /// void AddImuData(int trajectoryId, ImuData imuData); /// /// Inserts an odometry measurement. /// void AddOdometryData(int trajectoryId, OdometryData odometryData); /// /// Inserts a fixed frame pose measurement. /// void AddFixedFramePoseData(int trajectoryId, FixedFramePoseData fixedFramePoseData); /// /// Inserts landmarks observations. /// void AddLandmarkData(int trajectoryId, LandmarkData landmarkData); /// /// Drains the work queue to ensure all pending operations are completed. /// This should be called before finishing a trajectory to avoid race conditions. /// void DrainWorkQueue(); /// /// Finishes the given trajectory. /// void FinishTrajectory(int trajectoryId); /// /// Freezes a trajectory. Poses in this trajectory will not be optimized. /// void FreezeTrajectory(int trajectoryId); /// /// Adds a 'submap' from a proto with the given 'global_pose' to the /// appropriate trajectory. /// void AddSubmapFromProto(Rigid3d globalPose, Models.Mapping.Submap submap); /// /// Adds a 'node' from a proto with the given 'global_pose' to the /// appropriate trajectory. /// void AddNodeFromProto(Rigid3d globalPose, Models.Mapping.Node node); /// /// Sets the trajectory data from a proto. /// void SetTrajectoryDataFromProto(Models.Mapping.TrajectoryData data); /// /// Adds information that 'node_id' was inserted into 'submap_id'. The submap /// has to be deserialized first. /// void AddNodeToSubmap(NodeId nodeId, SubmapId submapId); /// /// Adds serialized constraints. The corresponding trajectory nodes and submaps /// have to be deserialized before calling this function. /// void AddSerializedConstraints(List constraints); /// /// Adds a 'trimmer'. It will be used after all data added before it has been /// included in the pose graph. /// void AddTrimmer(PoseGraphTrimmer trimmer); /// /// Returns the current trajectory clusters. /// List> GetConnectedTrajectories(); /// /// Returns the IMU data. /// Dictionary> GetImuData(); /// /// Returns the odometry data. /// Dictionary> GetOdometryData(); /// /// Returns the fixed frame pose data. /// Dictionary> GetFixedFramePoseData(); /// /// Returns the landmark data. /// Dictionary GetLandmarkNodes(); /// /// Sets a relative initial pose 'relative_pose' for 'from_trajectory_id' with /// respect to 'to_trajectory_id' at time 'time'. /// void SetInitialTrajectoryPose( int fromTrajectoryId, int toTrajectoryId, Rigid3d pose, long time); /// /// Waits for all computations to finish and computes optimized poses. /// void RunFinalOptimization(); /// /// Returns data for all submaps. /// MapById GetAllSubmapData(); /// /// Returns the current optimized transform and submap itself for the given /// 'submap_id'. Returns 'null' for the 'submap' member if the submap does /// not exist (anymore). /// SubmapData GetSubmapData(SubmapId submapId); /// /// Returns the global poses for all submaps. /// MapById GetAllSubmapPoses(); /// /// Returns the transform converting data in the local map frame (i.e. the /// continuous, non-loop-closed frame) into the global map frame (i.e. the /// discontinuous, loop-closed frame). /// Rigid3d GetLocalToGlobalTransform(int trajectoryId); /// /// Returns the current optimized trajectories. /// MapById GetTrajectoryNodes(); /// /// Returns the current optimized trajectory poses. /// MapById GetTrajectoryNodePoses(); /// /// Returns the states of trajectories. /// Dictionary GetTrajectoryStates(); /// /// Returns the current optimized landmark poses. /// Dictionary GetLandmarkPoses(); /// /// Sets global pose of landmark 'landmark_id' to given 'global_pose'. /// void SetLandmarkPose(string landmarkId, Rigid3d globalPose, bool frozen = false); /// /// Deletes a trajectory asynchronously. /// void DeleteTrajectory(int trajectoryId); /// /// Checks if the given trajectory is finished. /// bool IsTrajectoryFinished(int trajectoryId); /// /// Checks if the given trajectory is frozen. /// bool IsTrajectoryFrozen(int trajectoryId); /// /// Returns the trajectory data. /// Dictionary GetTrajectoryData(); /// /// Returns the collection of constraints. /// List Constraints(); /// /// Serializes the constraints and trajectories. If /// 'include_unfinished_submaps' is set to 'true', unfinished submaps, i.e. /// submaps that have not yet received all rangefinder data insertions, will /// be included, otherwise not. /// Models.Mapping.PoseGraph ToProto(bool includeUnfinishedSubmaps); /// /// Sets the callback function that is invoked whenever the global optimization /// problem is solved. /// void SetGlobalSlamOptimizationCallback(GlobalSlamOptimizationCallback callback); /// /// Sets the transform from local map frame to global map frame (map origin). /// Used when loading state from pbstream; matches C++ SetTransformToMap. /// void SetTransformToMap(Rigid3d transform); /// /// Returns the transform from local map frame to global map frame. /// Matches C++ GetTransformToMap. /// Rigid3d GetTransformToMap(); /// /// Manually compute a constraint between a node and submap using global scan matching. /// Match C++: manualComputeConstraint (pose_graph_interface.h:181-192) /// (double Score, Constraint? Constraint) ManualComputeConstraint(NodeId nodeId, SubmapId submapId); /// /// Manually compute constraint score from an initial pose estimate. /// Match C++: manualComputeConstraintScore (pose_graph_interface.h:194-197) /// double ManualComputeConstraintScore(NodeId nodeId, SubmapId submapId, Rigid3d initialPose); /// /// Manually compute scan matcher score with refined pose output. /// Match C++: manualComputeScanMatcher (pose_graph_interface.h:199-202) /// double ManualComputeScanMatcher(NodeId nodeId, SubmapId submapId, Rigid3d initialPose, out Rigid3d poseManualEstimate); /// /// Manually relocalize a trajectory against finished submaps. /// Match C++: ManualRelocalization (pose_graph_interface.h:212-216) /// bool ManualRelocalization(int trajectoryId, out double score, Rigid2d initialPose, LocalizationResultCallback? callback); } /// /// Callback for global SLAM optimization. /// public delegate void GlobalSlamOptimizationCallback( Dictionary submapIds, Dictionary nodeIds); /// /// Result of manual relocalization operation. /// Match C++: LocalizationResultCallback (pose_graph_interface.h) /// public struct LocalizationResult { public NodeId NodeId { get; init; } public SubmapId SubmapId { get; init; } public Rigid3d GlobalPose { get; init; } public double Score { get; init; } } /// /// Callback for localization/relocalization results. /// Match C++: LocalizationResultCallback (pose_graph_interface.h) /// public delegate void LocalizationResultCallback(LocalizationResult result);