void MoveTo(PointPlus target, float offset) { ModuleBehavior mBehavior = (ModuleBehavior)FindModleu(typeof(ModuleBehavior)); target.X -= offset; //body radius mBehavior.TurnTo(-target.Theta); mBehavior.MoveTo(target.R); mBehavior.TurnTo(target.Theta); //return to previous orientation }
void DoBackOff(Segment s) { ModuleBehavior mBehavior = (ModuleBehavior)FindModleu(typeof(ModuleBehavior)); PointPlus target = new PointPlus(s.MidPoint + new PointPlus { R = 2f, Theta = s.Angle - PI / 2 }); mBehavior.TurnTo(-target.Theta); mBehavior.MoveTo(target.R); mBehavior.TurnTo(target.Theta); //return to previous orientation }
private void CorrectModelPosition(Module2DModel nmModel, ModuleBehavior nmBehavior, Thing best, List <Thing> near) { //locations are not very accurate and accumulate errors //whenever we encounter a landmark, we update the orientation/location of the model to correct errors Segment s2 = Module2DModel.SegmentFromUKSThing(near[0]); Segment s1 = null; foreach (Link l in best.References) { Segment s = Module2DModel.SegmentFromUKSThing(l.T); if (s.theColor == s2.theColor) { s1 = s; break; } } if (s1 != null) { PointPlus m1 = s1.MidPoint; PointPlus m2 = s2.MidPoint; float deltaX = m1.X - m2.X; float deltaY = m1.Y - m2.Y; PointPlus a1 = new PointPlus() { P = (Point)(s1.P1.V - s1.P2.V) }; PointPlus a2 = new PointPlus() { P = (Point)(s2.P1.V - s2.P2.V) }; Angle deltaTheta = a1.Theta - a2.Theta; nmModel.Move(-deltaX, -deltaY); nmBehavior.TurnTo(deltaTheta); } }
void DoFaceSegment(Segment s) { ModuleBehavior mBehavior = (ModuleBehavior)FindModleu(typeof(ModuleBehavior)); Utils.FindDistanceToSegment(s, out Point closest); PointPlus closestPP = new PointPlus { P = closest }; mBehavior.TurnTo(-closestPP.Theta); }
void Push(Segment s) { ModuleBehavior mBehavior = (ModuleBehavior)FindModleu(typeof(ModuleBehavior)); float dist = (float)Utils.FindDistanceToSegment(s, out Point closest); PointPlus closestPP = new PointPlus { P = closest }; mBehavior.TurnTo(-closestPP.Theta); mBehavior.MoveTo(closestPP.R - .1f); }
void FaceMidPoint(Segment s) { ModuleBehavior mBehavior = (ModuleBehavior)FindModleu(typeof(ModuleBehavior)); mBehavior.TurnTo(-s.MidPoint.Theta); }
public override void Fire() { Init(); //be sure to leave this here //get the external references ModuleUKSN UKS = (ModuleUKSN)FindModuleByType(typeof(ModuleUKSN)); if (UKS == null) { return; } Module2DModel nmModel = (Module2DModel)FindModuleByType(typeof(Module2DModel)); if (nmModel == null) { return; } ModuleBehavior nmBehavior = (ModuleBehavior)FindModuleByType(typeof(ModuleBehavior)); if (nmBehavior == null) { return; } ModuleEvent mEvent = (ModuleEvent)FindModuleByType(typeof(ModuleEvent)); if (mEvent == null) { return; } //check on the various input neurons... //check for a goal selection foreach (Neuron n in na.Neurons()) { if (n.Fired() && n.Label.IndexOf("c") == 0 && n.Model == Neuron.modelType.Std) { Thing newTarget = UKS.Labeled(n.Label); if (newTarget == currentTarget) { currentTarget = null; } else { currentTarget = newTarget; } currentTargetReached = null; break; } } //check for operating mode auto = (GetNeuronValue(null, "Auto") == 1) ? true : false; //don't do anything while a behavior is in progress if (GetNeuronValue("ModuleBehavior", "Done") == 0) { return; } //is there an existing landmark? Do I recognize I'm near a spot I was before? //this only calculates "R" so it is rotation-independent Thing best = null; float bestDist = 1000; List <Thing> near = nmModel.NearbySegments(3); FindBestLandmarkMatch(UKS, ref best, ref bestDist, near); nmModel.FireVisibleObjects(); //not really needed if (bestDist < .2f) //are we near a landmark we've been at before? { SetNeuronValue(null, "Found", 1); //yse, we have returned to a landmark we've been at before currentLandmark = best; currentEvent = currentLandmark.ReferencedBy[0].T; //we need to reorient ourselves to face the same way as we did before (set a flag) if (lastLandmark != currentLandmark) { lastLandmark = currentLandmark; orienting = true; } } else { //we're not near an existing landmark currentLandmark = null; currentEvent = null; lastLandmark = null; } //this is on arrival back at a landmark if (orienting) { Angle totalAngleError = GetTotalAngleError(near); if (Abs(totalAngleError) > PI / 2 - .1f) { //turn in large increments until the angular error gets small Angle angle = (float)PI / 2; nmBehavior.TurnTo(angle); return; } //this corrects for roundoff errors CorrectModelPosition(nmModel, nmBehavior, best, near); orienting = false; return; } //we are in going-to-goal mode if (currentTarget != null) //goingToGoal) { if (currentEvent != null) //currentEvent means we're at a decision point...check for the decision and execute it { Thing action = GoToGoal(currentTarget); if (action != null) { float angle = GetAngleFromAction(action); if (angle != 0) { nmBehavior.TurnTo(angle); } nmBehavior.MoveTo(1); currentEvent = null; return; } } } //we are in exploration mode //We're not at a known landmark //decide which way to turn at an obstacle //If I am up to an obstacle...is there a decision or can I only go one way float distAhead = nmModel.GetDistanceAtDirection(0); float distLeft = nmModel.GetDistanceAtDirection((float)PI / 2); float distRight = nmModel.GetDistanceAtDirection((float)-PI / 2); bool canGoAhead = distAhead > 1; bool canGoLeft = distLeft > 1; bool canGoRight = distRight > 1; int options = (canGoAhead ? 1 : 0) + (canGoRight ? 1 : 0) + (canGoLeft ? 1 : 0); //First determine if there is a decision to be made or if there is only one option if (options == 1 && auto) { //we have no choice but to follow the path if (canGoAhead) { nmBehavior.MoveTo(1); return; } if (canGoLeft) { nmBehavior.TurnTo((float)-PI / 2); nmBehavior.MoveTo(1); return; } if (canGoRight) { nmBehavior.TurnTo((float)PI / 2); nmBehavior.MoveTo(1); return; } } else if (options == 0 && auto) { //we're trapped...note the color ahead and turn around Thing thingAhead = nmModel.GetNearestThing(); currentTargetReached = thingAhead.References[2].T; if (mostRecentDecisionPoint != null) { mEvent.AddOutcomePair(mostRecentDecisionPoint, mostRecentAction, currentTargetReached); mostRecentAction = null; mostRecentDecisionPoint = null; } Neuron n1 = null; if (currentTargetReached != null) { n1 = na.GetNeuronAt(currentTargetReached.Label); } //color a new goal neuron if (n1 == null && currentTargetReached != null) { n1 = AddLabel(currentTargetReached.Label + " "); n1.Model = Neuron.modelType.Color; n1.SetValueInt((int)currentTargetReached.V); na.GetNeuronLocation(n1, out int X, out int Y); Neuron n2 = na.GetNeuronAt(X + 1, Y); if (n2 != null) { n2.Label = currentTargetReached.Label; } } if (currentTargetReached == currentTarget) { //if we're looking for a goal, we've reached it, so stop //currentTarget = null; currentEvent = null; } else { //make a U-Turn and start backtracking nmBehavior.TurnTo((float)-PI); } } else if (auto) { //we have a choice... //if the current landmark is null, create a new landmark & Event if (currentLandmark == null) { //Create new Landmark...it clones the points so they are not modified by the model module Thing newLandmark = mEvent.CreateLandmark(near); currentEvent = mEvent.CreateEvent(newLandmark); currentLandmark = newLandmark; if (mostRecentDecisionPoint != null) { mEvent.AddOutcomePair(mostRecentDecisionPoint, mostRecentAction, currentEvent); } } else { if (mostRecentDecisionPoint != null && mostRecentDecisionPoint.Children.Find(t1 => t1.References[0].T == mostRecentAction) == null) { mEvent.AddOutcomePair(mostRecentDecisionPoint, mostRecentAction, currentEvent); } } //TODO improve the method of finding something not tried before //Decide which untried path to take //priorities...1)continue ahead 2)left 3)right or randomized (depending on comment below) Thing newAction = UKS.Labeled("NoAction"); List <Thing> possibleActions = new List <Thing>(); if (currentEvent.Children.Find(t => t.References[0].T.Label == "GoS") == null && canGoAhead) { possibleActions.Add(UKS.Labeled("GoS")); } if (currentEvent.Children.Find(t => t.References[0].T.Label == "LTurnS") == null && canGoLeft) { possibleActions.Add(UKS.Labeled("LTurnS")); } if (currentEvent.Children.Find(t => t.References[0].T.Label == "RTurnS") == null && canGoRight) { possibleActions.Add(UKS.Labeled("RTurnS")); } if (possibleActions.Count == 0 && currentEvent.Children.Find(t => t.References[0].T.Label == "UTurnS") == null) { newAction = UKS.Labeled("UTurnS"); } else if (possibleActions.Count == 1) { newAction = possibleActions[0]; } else if (possibleActions.Count > 0) { //for debugging, eliminate the ransomization by alternately commenting the 2 stmts below // newAction = possibleActions[0]; newAction = possibleActions[rand.Next(possibleActions.Count)]; } if (newAction.Label != "NoAction") { mostRecentAction = newAction; mostRecentDecisionPoint = currentEvent; Angle angle = GetAngleFromAction(newAction); nmBehavior.TurnTo(angle); nmBehavior.MoveTo(1); } else { //TODO: all actions at the current Event have been tried, is there another Event which hasn't been exhausted? } lastLandmark = currentLandmark; return; } }
public override void Fire() { Init(); //be sure to leave this here to enable use of the na variable if (countDown > 0) { countDown--; return; } //Input is an object in the model //generate some alternate points of view (current position is the first) //for each points of view ////can dest be seen? ////record distance //if shortest distance > 0 ///1) go to pov ///2) go to dest ///else recursive? /// ModuleView naBehavior = MainWindow.theNeuronArray.FindModuleByLabel("ModuleBehavior"); if (naBehavior == null) { return; } ModuleBehavior nmBehavior = (ModuleBehavior)naBehavior.TheModule; ModuleView naModel = theNeuronArray.FindModuleByLabel("Module2DModel"); Module2DModel nmModel = (Module2DModel)naModel.TheModule; if (!nmBehavior.IsIdle()) { return; } if (pvTry != null) { PointPlus pvTargetSave = new PointPlus { P = pvTarget.P }; pvTarget.X -= pvTry.X; pvTarget.Y -= pvTry.Y; pvTarget.Theta -= pvTry.Theta; PointPlus pv1 = nmModel.CanISGoStraightTo(pvTarget, out Segment obstacle); nmModel.ImagineEnd(); if (pv1 != null) { pvTry.Theta = -pvTry.Theta; nmBehavior.TurnTo(pvTry.Theta); nmBehavior.MoveTo(pvTry.R); //SetNeuronValue("ModuleBehavior", "TurnTo", 1); //SetNeuronValue("ModuleBehavior", "Theta", (float)pvTry.Theta); //SetNeuronValue("ModuleBehavior", "MoveTo", 1); //SetNeuronValue("ModuleBehavior", "R", (float)pvTry.R); //SetNeuronValue("ModuleBehavior", "Done", 0); //we made a partial move...update the target pointsToTry.Clear(); tryAgain = true; countDown = 5; } else { pvTarget = pvTargetSave; } pvTry = null; return; } if (pointsToTry.Count > 0 && !nmModel.imagining) { pvTry = pointsToTry[0]; pointsToTry.RemoveAt(0); nmModel.ImagineStart(pvTry, 0); countDown = 15; return; } if (GetNeuronValue(null, "Go") == 0 && !tryAgain) { return; } if (GetNeuronValue("ModuleBehavior", "Done") == 0) { return; } if (!tryAgain) { pvTarget = new PointPlus { R = GetNeuronValue(null, "R"), Theta = GetNeuronValue(null, "Theta") }; SetNeuronValue(null, "Go", 0); SetNeuronValue(null, "R", 0); SetNeuronValue(null, "Theta", 0); } // if (pvTarget.R == 0) // pvTarget = nmModel.FindGreen().MidPoint(); if (pvTarget != null) { PointPlus pv1 = nmModel.CanISGoStraightTo(pvTarget, out Segment obstacle); if (pv1 != null) { SetNeuronValue("ModuleBehavior", "TurnTo", 1); SetNeuronValue("ModuleBehavior", "Theta", (float)-pv1.Theta); SetNeuronValue("ModuleBehavior", "MoveTo", 1); SetNeuronValue("ModuleBehavior", "R", (float)pv1.R); tryAgain = false; pvTry = null; } else { PointPlus pvTry1 = Utils.ExtendSegment(obstacle.P1.P, obstacle.P2.P, 0.5f, true); PointPlus pvTry2 = Utils.ExtendSegment(obstacle.P1.P, obstacle.P2.P, 0.5f, false); pointsToTry.Add(pvTry1); pointsToTry.Add(pvTry2); } } }