CogniPilot

MODELICA LIBRARY · ENGINEERING REFERENCE

package

SLAM.Mapping.RGBDMapAnchors

Public declarations

Explicit source declarations; dimensions, modifications and defaults are shown as written, without evaluation.

RoleNameTypeDimensions / attributes / defaultDescription
constantimageHeightInteger= 90
constantimageWidthInteger= 160
constantmapCapacityInteger= imageHeight*imageWidth
constantkeyframeCapacityInteger= 128
constantdimensionInteger= 3
constantidentifierLimitInteger= 1000000000

Members

NameKindDescription
ProperRotationfunction
ValidNodesfunction
Reprojectfunction

Modelica declarations and implementation

Show parameters, interfaces and source

Parameters, inputs, outputs, defaults and equations from the source file.

package RGBDMapAnchors
  constant Integer imageHeight = 90;
  constant Integer imageWidth = 160;
  constant Integer mapCapacity = imageHeight*imageWidth;
  constant Integer keyframeCapacity = 128;
  constant Integer dimension = 3;
  constant Integer identifierLimit = 1000000000;

  function ProperRotation
    input Real rotation[dimension,dimension];
    output Boolean valid;
  protected
    Real gram[dimension,dimension]; Real determinant;
  algorithm
    valid := true;
    for row in 1:dimension loop
      for column in 1:dimension loop
        valid := valid and abs(rotation[row,column]) <= 1.000001;
      end for;
    end for;
    if valid then
      gram := transpose(rotation)*rotation;
      for row in 1:dimension loop
        for column in 1:dimension loop
          valid := valid and abs(gram[row,column]-(if row == column then 1.0 else 0.0)) <= 1e-6;
        end for;
      end for;
      determinant := rotation[1,1]*(rotation[2,2]*rotation[3,3]-rotation[2,3]*rotation[3,2])
        -rotation[1,2]*(rotation[2,1]*rotation[3,3]-rotation[2,3]*rotation[3,1])
        +rotation[1,3]*(rotation[2,1]*rotation[3,2]-rotation[2,2]*rotation[3,1]);
      valid := valid and abs(determinant-1.0) <= 1e-6;
    end if;
  end ProperRotation;

  // Catalog/graph slots never relocate within a generation. Reuse changes
  // the monotone identity; a cached slot alone cannot keep an anchor alive.
  function ValidNodes
    input Boolean enabled[:];
    input Integer ids[size(enabled,1)];
    input Real position[size(enabled,1),dimension];
    input Real rotation[size(enabled,1),dimension,dimension];
    input Real coordinateLimit;
    output Boolean valid;
  algorithm
    valid := true;
    for node in 1:size(enabled,1) loop
      if enabled[node] then
        valid := valid and ids[node] >= 1 and ids[node] <= identifierLimit
          and ProperRotation(rotation[node,:,:]);
        for axis in 1:dimension loop
          valid := valid and abs(position[node,axis]) <= coordinateLimit;
        end for;
        for other in 1:node-1 loop
          if enabled[other] then valid := valid and ids[node] <> ids[other]; end if;
        end for;
      end if;
    end for;
  end ValidNodes;

  function Reproject
    input Real previousPoint[:,dimension];
    input Real previousLocalPoint[size(previousPoint,1),dimension];
    input Real previousOccupied[size(previousPoint,1)];
    input Integer previousAnchorId[size(previousPoint,1)];
    input Integer previousAnchorSlot[size(previousPoint,1)];
    input Integer mapGeneration; input Integer previousRevision;
    input Boolean nodeEnabled[:];
    input Integer nodeId[size(nodeEnabled,1)];
    input Real nodePosition[size(nodeEnabled,1),dimension];
    input Real nodeRotation[size(nodeEnabled,1),dimension,dimension];
    input Integer graphGeneration; input Integer graphRevision;
    input Boolean graphAccepted; input Boolean requested;
    input Real coordinateLimit;
    output Real point[size(previousPoint,1),dimension];
    output Real localPoint[size(previousPoint,1),dimension];
    output Real occupied[size(previousPoint,1)];
    output Integer anchorId[size(previousPoint,1)];
    output Integer anchorSlot[size(previousPoint,1)];
    output Integer nextRevision;
    output Boolean accepted;
    output Integer rejectionReason;
    output Integer projectedCount; output Integer prunedCount;
  protected
    Boolean configuration; Boolean stateValid; Boolean slotValid;
    Boolean coordinatesValid; Boolean retained;
    Integer owner; Real candidate[dimension];
  algorithm
    point := previousPoint; localPoint := previousLocalPoint;
    occupied := previousOccupied; anchorId := previousAnchorId; anchorSlot := previousAnchorSlot;
    nextRevision := previousRevision; accepted := false; rejectionReason := 1;
    projectedCount := 0; prunedCount := 0;
    if requested then
      configuration := size(previousPoint,1) >= 1 and size(previousPoint,1) <= mapCapacity
        and size(nodeEnabled,1) >= 1 and size(nodeEnabled,1) <= keyframeCapacity
        and coordinateLimit > 0.0 and coordinateLimit <= 1e6
        and mapGeneration >= 1 and mapGeneration <= identifierLimit and graphGeneration == mapGeneration
        and previousRevision >= 0 and previousRevision < identifierLimit and graphRevision == previousRevision+1;
      rejectionReason := 2;
      if configuration then
        rejectionReason := 3;
        if graphAccepted then
          rejectionReason := 4;
          if ValidNodes(nodeEnabled,nodeId,nodePosition,nodeRotation,coordinateLimit) then
            stateValid := true; coordinatesValid := true;
            for slot in 1:size(previousPoint,1) loop
              if previousOccupied[slot] == 0.0 then
                point[slot,:] := zeros(dimension); localPoint[slot,:] := zeros(dimension);
                occupied[slot] := 0.0; anchorId[slot] := 0; anchorSlot[slot] := 0;
              elseif previousOccupied[slot] == 1.0 then
                owner := previousAnchorSlot[slot];
                slotValid := previousAnchorId[slot] >= 1 and previousAnchorId[slot] <= identifierLimit
                  and owner >= 1 and owner <= size(nodeEnabled,1);
                for axis in 1:dimension loop
                  slotValid := slotValid and abs(previousPoint[slot,axis]) <= coordinateLimit
                    and abs(previousLocalPoint[slot,axis]) <= coordinateLimit;
                end for;
                stateValid := stateValid and slotValid;
                if slotValid then
                  retained := nodeEnabled[owner] and nodeId[owner] == previousAnchorId[slot];
                  if retained then
                    candidate := nodeRotation[owner,:,:]*previousLocalPoint[slot,:]+nodePosition[owner,:];
                    for axis in 1:dimension loop
                      coordinatesValid := coordinatesValid and abs(candidate[axis]) <= coordinateLimit;
                    end for;
                    point[slot,:] := candidate; projectedCount := projectedCount+1;
                  else
                    // Eviction or slot reuse cannot transfer a landmark to a
                    // new keyframe that happens to occupy the same array slot.
                    point[slot,:] := zeros(dimension); localPoint[slot,:] := zeros(dimension);
                    occupied[slot] := 0.0; anchorId[slot] := 0; anchorSlot[slot] := 0;
                    prunedCount := prunedCount+1;
                  end if;
                end if;
              else
                stateValid := false;
              end if;
            end for;
            accepted := stateValid and coordinatesValid;
            rejectionReason := if not stateValid then 5 else if not coordinatesValid then 6 else 0;
            if accepted then nextRevision := graphRevision; end if;
          end if;
        end if;
      end if;
    end if;
    // Late failures preserve all previous fields, including poisoned disabled
    // payload. Canonicalization, pruning and version advancement commit together.
    if not accepted then
      point := previousPoint; localPoint := previousLocalPoint; occupied := previousOccupied;
      anchorId := previousAnchorId; anchorSlot := previousAnchorSlot;
      nextRevision := previousRevision; projectedCount := 0; prunedCount := 0;
    end if;
  end Reproject;
end RGBDMapAnchors;