CogniPilot

MODELICA LIBRARY · ENGINEERING REFERENCE

SLAM/Mapping/AssignLandmarkAnchors.mo

Download original .moGitHub source

Documentation: SLAM.Mapping.AssignLandmarkAnchors

within SLAM.Mapping;
// Consume private map insertion receipts. Anchor outputs are a proposal until
// the surrounding owner commits map geometry, metadata and anchors together.
function AssignLandmarkAnchors
  import RGBDMapAnchors = SLAM.Mapping.RGBDMapAnchors;

  input Real previousPoint[:,3];
  input Real previousOccupied[size(previousPoint,1)];
  input Real previousLocalPoint[size(previousPoint,1),3];
  input Integer previousAnchorId[size(previousPoint,1)];
  input Integer previousAnchorSlot[size(previousPoint,1)];
  input Integer previousGeneration;
  input Real nextPoint[size(previousPoint,1),3];
  input Real nextOccupied[size(previousPoint,1)];
  input Integer insertedFeature[size(previousPoint,1)];
  input Real candidatePoint[:,3];
  input Real candidateEnabled[size(candidatePoint,1)]; input Real candidateCount;
  input Boolean nodeEnabled[:]; input Integer nodeId[size(nodeEnabled,1)];
  input Real nodePosition[size(nodeEnabled,1),3]; input Real nodeRotation[size(nodeEnabled,1),3,3];
  input Integer catalogGeneration; input Integer generation;
  input Integer selectedAnchorId; input Integer selectedAnchorSlot;
  input Boolean mapAccepted; input Boolean requested; input Boolean reset;
  input Real coordinateLimit; input Real consistencyTolerance;
  output Real localPoint[size(previousPoint,1),3];
  output Integer anchorId[size(previousPoint,1)]; output Integer anchorSlot[size(previousPoint,1)];
  output Integer nextGeneration; output Boolean accepted; output Integer rejectionReason;
  output Integer assignedCount; output Integer retainedCount; output Integer clearedCount;
protected
  constant Integer featureCapacity = 350;
  Boolean configuration; Boolean valid; Boolean slotValid; Boolean selectedValid;
  Boolean seen[size(candidatePoint,1)];
  Integer feature; Integer owner; Real local[3]; Real reconstructed[3];
algorithm
  localPoint := previousLocalPoint; anchorId := previousAnchorId; anchorSlot := previousAnchorSlot;
  nextGeneration := previousGeneration; accepted := false; rejectionReason := 1;
  assignedCount := 0; retainedCount := 0; clearedCount := 0;
  if requested then
    configuration := size(previousPoint,1) >= 1 and size(previousPoint,1) <= RGBDMapAnchors.mapCapacity
      and size(candidatePoint,1) >= 1 and size(candidatePoint,1) <= featureCapacity
      and size(nodeEnabled,1) >= 1 and size(nodeEnabled,1) <= RGBDMapAnchors.keyframeCapacity
      and candidateCount >= 0.0 and candidateCount <= size(candidatePoint,1) and floor(candidateCount) == candidateCount
      and generation >= 1 and generation <= RGBDMapAnchors.identifierLimit and catalogGeneration == generation
      and ((reset and previousGeneration >= 0 and previousGeneration < RGBDMapAnchors.identifierLimit
        and generation == previousGeneration+1) or (not reset and previousGeneration == generation))
      and selectedAnchorSlot >= 0 and selectedAnchorSlot <= size(nodeEnabled,1)
      and selectedAnchorId >= 0 and selectedAnchorId <= RGBDMapAnchors.identifierLimit
      and coordinateLimit > 0.0 and coordinateLimit <= 1e6
      and consistencyTolerance > 0.0 and consistencyTolerance <= 0.01;
    rejectionReason := 2;
    if configuration then
      rejectionReason := 3;
      if mapAccepted then
        rejectionReason := 4;
        if RGBDMapAnchors.ValidNodes(nodeEnabled,nodeId,nodePosition,nodeRotation,coordinateLimit) then
          selectedValid := false;
          if selectedAnchorSlot >= 1 and selectedAnchorId >= 1 then
            selectedValid := nodeEnabled[selectedAnchorSlot] and nodeId[selectedAnchorSlot] == selectedAnchorId;
          end if;
          valid := true; seen := fill(false,size(candidatePoint,1));
          for slot in 1:size(previousPoint,1) loop
            feature := insertedFeature[slot];
            slotValid := feature >= 0 and feature <= size(candidatePoint,1)
              and (nextOccupied[slot] == 0.0 or nextOccupied[slot] == 1.0);
            if slotValid then
              if nextOccupied[slot] == 0.0 then
                slotValid := feature == 0;
                localPoint[slot,:] := zeros(3); anchorId[slot] := 0; anchorSlot[slot] := 0;
                clearedCount := clearedCount+1;
              elseif feature > 0 then
                slotValid := selectedValid and feature <= candidateCount and candidateEnabled[feature] == 1.0
                  and not seen[feature];
                seen[feature] := true;
                for axis in 1:3 loop
                  slotValid := slotValid and abs(nextPoint[slot,axis]) <= coordinateLimit
                    and nextPoint[slot,axis] == candidatePoint[feature,axis];
                end for;
                if slotValid then
                  local := transpose(nodeRotation[selectedAnchorSlot,:,:])*(nextPoint[slot,:]-nodePosition[selectedAnchorSlot,:]);
                  reconstructed := nodeRotation[selectedAnchorSlot,:,:]*local+nodePosition[selectedAnchorSlot,:];
                  for axis in 1:3 loop
                    slotValid := slotValid and abs(local[axis]) <= coordinateLimit
                      and abs(reconstructed[axis]-nextPoint[slot,axis]) <= consistencyTolerance;
                  end for;
                  localPoint[slot,:] := local;
                  anchorId[slot] := selectedAnchorId; anchorSlot[slot] := selectedAnchorSlot;
                  assignedCount := assignedCount+1;
                end if;
              else
                owner := previousAnchorSlot[slot];
                slotValid := not reset and previousOccupied[slot] == 1.0
                  and previousAnchorId[slot] >= 1 and previousAnchorId[slot] <= RGBDMapAnchors.identifierLimit
                  and owner >= 1 and owner <= size(nodeEnabled,1);
                for axis in 1:3 loop
                  slotValid := slotValid and abs(previousLocalPoint[slot,axis]) <= coordinateLimit
                    and abs(previousPoint[slot,axis]) <= coordinateLimit
                    and nextPoint[slot,axis] == previousPoint[slot,axis];
                end for;
                if slotValid then
                  slotValid := nodeEnabled[owner] and nodeId[owner] == previousAnchorId[slot];
                  if slotValid then
                    reconstructed := nodeRotation[owner,:,:]*previousLocalPoint[slot,:]+nodePosition[owner,:];
                    for axis in 1:3 loop
                      slotValid := slotValid and abs(reconstructed[axis]-previousPoint[slot,axis]) <= consistencyTolerance;
                    end for;
                    retainedCount := retainedCount+1;
                  end if;
                end if;
              end if;
            end if;
            valid := valid and slotValid;
          end for;
          accepted := valid; rejectionReason := if valid then 0 else 5;
          if accepted then nextGeneration := generation; end if;
        end if;
      end if;
    end if;
  end if;
  if not accepted then
    localPoint := previousLocalPoint; anchorId := previousAnchorId; anchorSlot := previousAnchorSlot;
    nextGeneration := previousGeneration; assignedCount := 0; retainedCount := 0; clearedCount := 0;
  end if;
end AssignLandmarkAnchors;