CogniPilot

MODELICA LIBRARY · ENGINEERING REFERENCE

SLAM/Localization/RGBDVisualObservation.mo

Download original .moGitHub source

Documentation: SLAM.Localization.RGBDVisualObservation

within SLAM.Localization;
// Review graph: raw RGB/depth -> descriptors -> matches -> rigid registration
// -> map-frame body pose. Compile with RGBDFeatureMatching,
// RigidPointRegistration and RGBDRelativePose source files.
// The reference descriptors, optical points and body pose are retained estimated
// keyframe data. No ground-truth pose or host feature matching enters this graph.
// This is a visual observation frontend, not a persistent SLAM estimator.
model RGBDVisualObservation
  import RGBDDescriptorFrame = Vision.Matching.RGBDDescriptorFrame;
  import RGBDFeatureMatching = Vision.Matching.RGBDFeatureMatching;
  import RGBDRelativePose = SLAM.Localization.RGBDRelativePose;
  import RigidPointRegistration = Vision.Registration.RigidPointRegistration;

  parameter Integer imageWidth(min=1) = 160;
  parameter Integer imageHeight(min=1) = 90;
  // RGB8 uses three channels; historical RGBA recordings may retain alpha.
  parameter Integer channelCount(min=3,max=4) = 4;
  constant Integer featureCapacity = 350;
  constant Integer descriptorWidth = 7;
  constant Integer descriptorSize = descriptorWidth*descriptorWidth;
  input Boolean imageEnabled = true;
  input Real rgb[imageHeight,imageWidth,channelCount];
  input Real depth[imageHeight,imageWidth];
  input Real depthUnits = 1.0 "Meters per depth sample";
  input Real pixels[featureCapacity,2];
  input Real activeCount;
  input Real rgbCalibration[4];
  input Real depthCalibration[4];
  input Real disparityNoise = 0.08;
  input Real noiseReferenceFx;
  input Real baseline = 0.05;
  input Real referenceDescriptor[featureCapacity,descriptorSize];
  input Real referencePoint[featureCapacity,3];
  input Real referenceEnabled[featureCapacity];
  input Real referenceCount;
  input Real referenceBodyRotation[3,3] = identity(3);
  input Real referenceBodyPosition[3] = zeros(3);
  input Real opticalToBody[3,3] = [0.0,0.0,1.0;-1.0,0.0,0.0;0.0,-1.0,0.0];
  input Real cameraOriginBody[3] = {0.18,0.0,-0.04};
  // Optional predicted optical reference->current transform for association.
  input Real usePrediction = 0.0;
  input Real predictedRotation[3,3] = identity(3);
  input Real predictedTranslation[3] = zeros(3);
  output Real observedBodyRotation[3,3];
  output Real observedBodyPosition[3];
  output Real valid;
  output Real matchCount;
  output Real registrationRms;
  output Real registrationRejectionReason;
  output Real currentIndex[featureCapacity];
  // Complete current frame data for retaining a future reference keyframe.
  output Real currentDescriptor[featureCapacity,descriptorSize];
  output Real currentPoint[featureCapacity,3];
  output Real currentEnabled[featureCapacity];
protected
  RGBDDescriptorFrame description(imageHeight=imageHeight,imageWidth=imageWidth,
    channelCount=channelCount,imageEnabled=imageEnabled,rgb=rgb,depth=depth,depthUnits=depthUnits,pixels=pixels,
    activeCount=activeCount,rgbCalibration=rgbCalibration,depthCalibration=depthCalibration,
    disparityNoise=disparityNoise,noiseReferenceFx=noiseReferenceFx,baseline=baseline);
  RGBDFeatureMatching matching(referenceDescriptor=referenceDescriptor,
    currentDescriptor=description.descriptor,referencePoint=referencePoint,
    currentPoint=description.point,referenceEnabled=referenceEnabled,
    currentEnabled=description.enabled,referenceCount=referenceCount,currentCount=activeCount,
    usePrediction=usePrediction,predictedRotation=predictedRotation,
    predictedTranslation=predictedTranslation);
  // Pair masks can have holes anywhere in the full reference domain. Using
  // matching.count as activeCount would silently discard matches in later slots.
  RigidPointRegistration registration(capacity=featureCapacity,
    activeCount=featureCapacity,sourcePoint=matching.sourcePoint,
    targetPoint=matching.targetPoint,pairEnabled=matching.pairEnabled);
  RGBDRelativePose pose(referenceBodyRotation=referenceBodyRotation,
    referenceBodyPosition=referenceBodyPosition,currentFromReference=registration.rotation,
    currentFromReferenceTranslation=registration.translation,opticalToBody=opticalToBody,
    cameraOriginBody=cameraOriginBody,registrationAccepted=registration.accepted);
equation
  observedBodyRotation = pose.observedBodyRotation;
  observedBodyPosition = pose.observedBodyPosition;
  valid = if noEvent(matching.configurationValid > 0.5) then pose.valid else 0.0;
  matchCount = matching.count;
  registrationRms = registration.rms;
  registrationRejectionReason = registration.rejectionReason;
  currentIndex = matching.currentIndex;
  currentDescriptor = description.descriptor;
  currentPoint = description.point;
  currentEnabled = description.enabled;
end RGBDVisualObservation;