Example #1
0
        /// <summary>
        /// Adjusts the velocity based on environment.
        /// </summary>
        /// <param name="laserData">most recently sensed laser range data</param>
        /// <param name="distance">closest obstacle in corridor ahead</param>
        private void AdjustVelocity(sicklrf.State laserData, int distance)
        {
            _state.Mapped = false;
            int test = FindBestFrom(laserData, 0, _state.Velocity / 10, CorridorWidthMoving);

            if (distance > FreeDistance)
            {
                MoveForward(MaximumForwardVelocity);

                if (Math.Abs(test) < 10)
                {
                    Turn(test / 2);
                }
            }
            else if (distance > AwareOfObstacleDistance)
            {
                MoveForward(MaximumForwardVelocity / 2);

                if (Math.Abs(test) < 45)
                {
                    Turn(test / 2);
                }
            }
            else
            {
                MoveForward(MaximumForwardVelocity / 4);

                Turn(test);
                _state.Countdown = Math.Abs(test / 10);
            }
        }
Example #2
0
        /// <summary>
        /// Transitions to "Mapping" meta state or "AdjustHeading" state depending on
        /// environment.
        /// </summary>
        /// <param name="laserData">most recently sensed laser range data</param>
        /// <param name="distance">closest obstacle in corridor ahead</param>
        private void StartMapping(sicklrf.State laserData, int distance)
        {
            StopMoving();

            if (distance < ObstacleDistance)
            {
                if (_state.Mapped)
                {
                    // We have been mapping before but do not seem to
                    // have found anything.
                    _state.LogicalState = LogicalState.RandomTurn;
                }
                else
                {
                    _state.LogicalState = LogicalState.MapSurroundings;
                }
            }
            else
            {
                int step = Math.Min(ObstacleDistance, distance - CorridorWidthMapping);
                // find the best angle from step mm in front of
                // our current position
                _state.NewHeading = FindBestFrom(laserData, 0, step, CorridorWidthMapping);

                LogInfo("Step: " + step + " Turn: " + _state.NewHeading);
                Translate(step);

                _state.LogicalState = LogicalState.AdjustHeading;
                _state.Countdown    = step / 50 + Math.Abs(_state.NewHeading / 10);
            }
        }
        /// <summary>
        /// Handles Replace notifications from the Laser partner
        /// </summary>
        /// <remarks>Posts a <typeparamref name="LaserRangeFinderUpdate"/> to itself.</remarks>
        /// <param name="replace">notification</param>
        /// <returns>task enumerator</returns>
        IEnumerator <ITask> LaserReplaceNotificationHandler(sicklrf.Replace replace)
        {
            //Tracer.Trace("LaserReplaceNotificationHandler() - Replace");

            // When this handler is called a couple of notifications may
            // have piled up. We only want the most recent one.
            sicklrf.State laserData = GetMostRecentLaserNotification(replace.Body);

            LaserRangeFinderUpdate laserUpdate = new LaserRangeFinderUpdate(laserData);

            _mainPort.Post(laserUpdate);    // calls LaserRangeFinderUpdateHandler() with laserUpdate

            yield return(Arbiter.Choice(
                             laserUpdate.ResponsePort,
                             delegate(DefaultUpdateResponseType response) { },
                             delegate(Fault fault) { }
                             ));

            // Skip messages that have been queued up in the meantime.
            // The notification that are lingering are out of date by now.
            GetMostRecentLaserNotification(laserData);

            // Reactivate the handler.
            Activate(
                Arbiter.ReceiveWithIterator <sicklrf.Replace>(false, _laserNotify, LaserReplaceNotificationHandler)
                );

            yield break;
        }
Example #4
0
        /// <summary>
        /// Finds closest obstacle in a corridor.
        /// </summary>
        /// <param name="laserData">laser scan</param>
        /// <param name="width">corridor width</param>
        /// <param name="fov">field of view in degrees</param>
        /// <returns>distance to the closest obstacle</returns>
        private int FindNearestObstacleInCorridor(sicklrf.State laserData, int width, int fov)
        {
            int    index;
            int    best      = 8192;
            int    count     = laserData.DistanceMeasurements.Length;
            double rangeLow  = -laserData.AngularRange / 2.0;
            double rangeHigh = laserData.AngularRange / 2.0;
            double span      = laserData.AngularRange;

            for (index = 0; index < count; index++)
            {
                double angle = rangeLow + (span * index) / count;
                if (Math.Abs(angle) < fov)
                {
                    angle = angle * Math.PI / 180;

                    int range = laserData.DistanceMeasurements[index];
                    int x     = (int)(range * Math.Sin(angle));
                    int y     = (int)(range * Math.Cos(angle));

                    if (Math.Abs(x) < width)
                    {
                        if (range < best)
                        {
                            best = range;
                        }
                    }
                }
            }

            return(best);
        }
        public void ReplaceHandler(sicklrf.Replace replace)
        {
            Tracer.Trace("TrackRoamerUsrfService::ReplaceHandler()");

            _state = replace.Body;
            replace.ResponsePort.Post(DefaultReplaceResponseType.Instance);
        }
Example #6
0
        /// <summary>
        /// Finds the best free corridor (maximum free space ahead) in a 360 degree scan.
        /// </summary>
        /// <param name="south">the backward half of the scan</param>
        /// <param name="north">the forward half of the scan</param>
        /// <returns>beast heading in degrees</returns>
        private int FindBestComposite(sicklrf.State south, sicklrf.State north)
        {
            sicklrf.State composite = new sicklrf.State();

            composite.DistanceMeasurements = new int[720];

            for (int i = 0; i < 720; i++)
            {
                if (i < 180)
                {
                    composite.DistanceMeasurements[i] = south.DistanceMeasurements[i + 180];
                }
                else if (i < 540)
                {
                    composite.DistanceMeasurements[i] = north.DistanceMeasurements[i - 180];
                }
                else
                {
                    composite.DistanceMeasurements[i] = south.DistanceMeasurements[i - 540];
                }
            }

            composite.AngularResolution = 0.5;
            composite.AngularRange      = 360;
            composite.Units             = north.Units;

            return(FindBestFrom(composite, 0, 0, CorridorWidthMoving));
        }
        public IEnumerator <ITask> ReplaceHandler(sicklrf.Replace replace)
        {
            _state = replace.Body;
            if (replace.ResponsePort != null)
            {
                replace.ResponsePort.Post(dssp.DefaultReplaceResponseType.Instance);
            }

            // issue notification
            _subMgrPort.Post(new submgr.Submit(_state, dssp.DsspActions.ReplaceRequest));
            yield break;
        }
Example #8
0
        private void createCylinder(sicklrf.State stateType)
        {
            Bitmap   bmp = new Bitmap(stateType.DistanceMeasurements.Length, 100);
            Graphics g   = Graphics.FromImage(bmp);

            g.Clear(Color.LightGray);

            int half = bmp.Height / 2;

            for (int x = 0; x < stateType.DistanceMeasurements.Length; x++)
            {
                int range = stateType.DistanceMeasurements[x];

                //for red marking
                double angle     = x * Math.PI * stateType.AngularRange / stateType.DistanceMeasurements.Length / 180; //radians
                double obsThresh = Math.Abs(robotWidth / (2 * Math.Cos(angle)));

                if (range > 0 && range < maxDist)
                {
                    int h = (int)Math.Round(bmp.Height * 500.0 / range);
                    if (h < 0)
                    {
                        h = 0;
                    }

                    Color col;
                    if (range < obsThresh)
                    {
                        col = LinearColor(Color.DarkRed, Color.LightGray, 0, maxDist, range);
                    }
                    else
                    {
                        col = LinearColor(Color.DarkBlue, Color.LightGray, 0, maxDist, range);
                    }

                    g.DrawLine(new Pen(col), bmp.Width - x, half - h, bmp.Width - x, half + h);
                }

                int hlim = (int)Math.Round(bmp.Height * 500.0 / obsThresh);
                if (hlim < 0)
                {
                    hlim = 0;
                }
                if (hlim < half)
                {
                    bmp.SetPixel(bmp.Width - x, half + hlim, Color.Green);
                }
            }
            picLRF.Image = bmp;
        }
        private const int step            = 6; // for speed and given that we are actually dealing with sonar data, pick only Nth points.

        protected void updateMapperWithLaserData(sicklrf.State laserData)
        {
            int numRays = laserData.DistanceMeasurements.Length;

            List <IDetectedObject> laserObjects = new List <IDetectedObject>(numRays / step + 5);

            for (int i = 0; i < laserData.DistanceMeasurements.Length; i += step)
            {
                double rangeMeters = laserData.DistanceMeasurements[i] / 1000.0d;  // DistanceMeasurements is in millimeters;

                if (rangeMeters > minReliableRangeMeters && rangeMeters < maxReliableRangeMeters)
                {
                    double relBearing = forwardAngle - i * 180.0d / numRays;

                    GeoPosition pos1 = (GeoPosition)_mapperVicinity.robotPosition.Clone();

                    pos1.translate(new Direction()
                    {
                        heading = _mapperVicinity.robotDirection.heading, bearingRelative = relBearing
                    }, new Distance(rangeMeters));

                    DetectedObstacle dobst1 = new DetectedObstacle()
                    {
                        geoPosition  = pos1,
                        firstSeen    = laserData.TimeStamp.Ticks,
                        lastSeen     = laserData.TimeStamp.Ticks,
                        detectorType = DetectorType.SONAR_SCANNING,
                        objectType   = DetectedObjectType.Obstacle
                    };

                    dobst1.SetColorByType();

                    laserObjects.Add(dobst1);
                }
            }

            if (laserObjects.Count > 0)
            {
                int countBefore = 0;
                lock (_mapperVicinity)
                {
                    countBefore = _mapperVicinity.Count;
                    _mapperVicinity.AddRange(laserObjects);
                    _mapperVicinity.computeMapPositions();
                }
                //Tracer.Trace(string.Format("laser ready - added {0} to {1}", laserObjects.Count, countBefore));
            }
        }
        /// <summary>
        /// Finds the best free corridor (maximum free space ahead) in a 360 degree scan.
        /// </summary>
        /// <param name="south">the backward half of the scan</param>
        /// <param name="north">the forward half of the scan</param>
        /// <returns>best heading in degrees (right turn - positive, left turn - negative)</returns>
        private int FindBestComposite(sicklrf.State south, sicklrf.State north)
        {
            try
            {
                // sanity check:
                LogInfo("FindBestComposite() south: " + south.DistanceMeasurements.Length + " points,  north: " + north.DistanceMeasurements.Length + " points");

                if (south.DistanceMeasurements.Length + north.DistanceMeasurements.Length < 360)
                {
                    LogError("FindBestComposite() - bad laser measurement");
                    return(0);
                }

                sicklrf.State composite = new sicklrf.State();

                composite.DistanceMeasurements = new int[361];

                for (int i = 0; i < composite.DistanceMeasurements.Length; i++)
                {
                    // the trick is to have halves of the South scan become sides of the full North scan,
                    // so that a 360 degrees composite has heading 0 in the middle.

                    if (i < 90)
                    {
                        composite.DistanceMeasurements[i] = south.DistanceMeasurements[i + 90];
                    }
                    else if (i < 270)
                    {
                        composite.DistanceMeasurements[i] = north.DistanceMeasurements[i - 90];
                    }
                    else // 270...359
                    {
                        composite.DistanceMeasurements[i] = south.DistanceMeasurements[i - 270];
                    }
                }

                composite.AngularResolution = 1.0;
                composite.AngularRange      = 360;
                composite.Units             = north.Units;

                return(FindBestHeading(composite, 0, 0, CorridorWidthMoving, "Best Composite"));
            }
            catch (Exception exc)
            {
                LogError(exc);
                return(0);
            }
        }
Example #11
0
        /// <summary>
        /// Handles the <typeparamref name="LaserRangeFinderUpdate"/> request.
        /// </summary>
        /// <param name="update">request</param>
        void LaserRangeFinderUpdateHandler(LaserRangeFinderUpdate update)
        {
            sicklrf.State laserData = update.Body;
            _state.MostRecentLaser = laserData.TimeStamp;

            int distance = FindNearestObstacleInCorridor(laserData, CorridorWidthMapping, 45);

            // AvoidCollision and EnterOpenSpace have precedence over
            // all other state transitions and are thus handled first.
            AvoidCollision(distance);
            EnterOpenSpace(distance);

            UpdateLogicalState(laserData, distance);

            update.ResponsePort.Post(DefaultUpdateResponseType.Instance);
        }
        IEnumerator <ITask> UpdateLRF()
        {
            var sensorOrFault = _simulatedLRFServicePort.Get();

            yield return(sensorOrFault.Choice());

            if (!HasError(sensorOrFault))
            {
                sicklrf.State sensorState = (sicklrf.State)sensorOrFault;
                WinFormsServicePort.Post(new FormInvoke(() =>
                {
                    _imageProcessingForm.SetLRFData(sensorState.DistanceMeasurements, sensorState.Units);
                }));
            }
            yield break;
        }
Example #13
0
        /// <summary>
        /// Implements the "Moving" meta state.
        /// </summary>
        /// <param name="laserData">most recently sensed laser range data</param>
        /// <param name="distance">closest obstacle in corridor ahead</param>
        private void Move(sicklrf.State laserData, int distance)
        {
            switch (_state.LogicalState)
            {
            case LogicalState.AdjustHeading:
                AdjustHeading();
                break;

            case LogicalState.FreeForwards:
                AdjustVelocity(laserData, distance);
                break;

            default:
                LogInfo("Explorer.Move() called in illegal state");
                break;
            }
        }
        private sicklrf.State _laserData = null;     // not part of the state, but still accessible from all components

        #region Laser handlers

        /// <summary>
        /// Handles the <typeparamref name="LaserRangeFinderUpdate"/> request.
        /// </summary>
        /// <param name="update">request</param>
        protected void LaserRangeFinderUpdateHandler(LaserRangeFinderUpdate update)
        {
            //Tracer.Trace("LaserRangeFinderUpdateHandler() - Update");

            try
            {
                if (!_doSimulatedLaser)                              // if simulated, ignore real data - do not call Decide()
                {
                    _laserData = (sicklrf.State)update.Body.Clone(); // laserData.DistanceMeasurements is cloned here all right

                    _state.MostRecentLaserTimeStamp = _laserData.TimeStamp;

                    updateMapperWithOdometryData();

                    if (!_mapperVicinity.robotState.ignoreLaser)        // if asked to ignore laser, we just do not update mapper with obstacles, but still call Decide() and everything else
                    {
                        updateMapperWithLaserData(_laserData);
                    }
                    else
                    {
                        lock (_mapperVicinity)
                        {
                            _mapperVicinity.computeMapPositions();
                        }
                    }

                    if (!_testBumpMode && !_state.Dropping && !_doUnitTest)
                    {
                        Decide(SensorEventSource.LaserScanning);
                    }

                    setGuiCurrentLaserData(new LaserDataSerializable()
                    {
                        TimeStamp = _laserData.TimeStamp.Ticks, DistanceMeasurements = (int[])_laserData.DistanceMeasurements.Clone()
                    });
                }
            }
            catch (Exception exc)
            {
                Tracer.Trace("LaserRangeFinderUpdateHandler() - " + exc);
            }

            update.ResponsePort.Post(DefaultUpdateResponseType.Instance);
        }
Example #15
0
 /// <summary>
 /// Transitions to the most appropriate state.
 /// </summary>
 /// <param name="laserData">most recently sensed laser range data</param>
 /// <param name="distance">closest obstacle in corridor ahead</param>
 private void UpdateLogicalState(sicklrf.State laserData, int distance)
 {
     if (_state.Countdown > 0)
     {
         _state.Countdown--;
     }
     else if (_state.IsUnknown)
     {
         StartMapping(laserData, distance);
     }
     else if (_state.IsMoving)
     {
         Move(laserData, distance);
     }
     else if (_state.IsMapping)
     {
         Map(laserData, distance);
     }
 }
Example #16
0
        public void ReplaceLaserData(sicklrf.State stateType)
        {
            if (stateType.TimeStamp < _lastLaser)
            {
                return;
            }
            _lastLaser = stateType.TimeStamp;
            TimeSpan delay = DateTime.Now - stateType.TimeStamp;

            lblDelay.Text = delay.ToString();

            Bitmap   bmp = new Bitmap(stateType.DistanceMeasurements.Length, 100);
            Graphics g   = Graphics.FromImage(bmp);

            g.Clear(Color.LightGray);

            int half = bmp.Height / 2;

            for (int x = 0; x < stateType.DistanceMeasurements.Length; x++)
            {
                int range = stateType.DistanceMeasurements[x];
                if (range > 0 && range < 8192)
                {
                    int h = bmp.Height * 500 / stateType.DistanceMeasurements[x];
                    if (h < 0)
                    {
                        h = 0;
                    }
                    Color col = ColorHelper.LinearColor(Color.DarkBlue, Color.LightGray, 0, 8192, range);
                    g.DrawLine(new Pen(col), bmp.Width - x, half - h, bmp.Width - x, half + h);
                }
            }
            picLRF.Image = bmp;

            if (btnConnectLRF.Enabled)
            {
                btnConnectLRF.Enabled = false;
            }
            if (!btnDisconnect.Enabled)
            {
                btnDisconnect.Enabled = true;
            }
        }
        private sicklrf.State _laserData = null; // not part of the state, but still accessible from all components

        #endregion Fields

        #region Methods

        /// <summary>
        /// Handles the <typeparamref name="LaserRangeFinderUpdate"/> request.
        /// </summary>
        /// <param name="update">request</param>
        protected void LaserRangeFinderUpdateHandler(LaserRangeFinderUpdate update)
        {
            //Tracer.Trace("LaserRangeFinderUpdateHandler() - Update");

            try
            {
                if (!_doSimulatedLaser)  // if simulated, ignore real data - do not call Decide()
                {
                    _laserData = (sicklrf.State)update.Body.Clone();   // laserData.DistanceMeasurements is cloned here all right

                    _state.MostRecentLaserTimeStamp = _laserData.TimeStamp;

                    updateMapperWithOdometryData();

                    if (!_mapperVicinity.robotState.ignoreLaser)        // if asked to ignore laser, we just do not update mapper with obstacles, but still call Decide() and everything else
                    {
                        updateMapperWithLaserData(_laserData);
                    }
                    else
                    {
                        lock (_mapperVicinity)
                        {
                            _mapperVicinity.computeMapPositions();
                        }
                    }

                    if (!_testBumpMode && !_state.Dropping && !_doUnitTest)
                    {
                        Decide(SensorEventSource.LaserScanning);
                    }

                    setGuiCurrentLaserData(new LaserDataSerializable() { TimeStamp = _laserData.TimeStamp.Ticks, DistanceMeasurements = (int[])_laserData.DistanceMeasurements.Clone() });
                }
            }
            catch (Exception exc)
            {
                Tracer.Trace("LaserRangeFinderUpdateHandler() - " + exc);
            }

            update.ResponsePort.Post(DefaultUpdateResponseType.Instance);
        }
Example #18
0
        /// <summary>
        /// Implements the "Mapping" meta state.
        /// </summary>
        /// <param name="laserData">most recently sensed laser range data</param>
        /// <param name="distance">closest obstacle in corridor ahead</param>
        private void Map(sicklrf.State laserData, int distance)
        {
            switch (_state.LogicalState)
            {
            case LogicalState.RandomTurn:
                RandomTurn();
                break;

            case LogicalState.MapSurroundings:
                _state.Mapped = true;
                LogInfo("Turning 180 deg to map");
                Turn(180);

                _state.LogicalState = LogicalState.MapSouth;
                _state.Countdown    = 15;
                break;

            case LogicalState.MapSouth:
                LogInfo("Mapping the View South");
                _state.South = laserData;
                Turn(180);

                _state.LogicalState = LogicalState.MapNorth;
                _state.Countdown    = 15;
                break;

            case LogicalState.MapNorth:
                LogInfo("Mapping the View North");
                _state.NewHeading = FindBestComposite(_state.South, laserData);
                LogInfo("Map suggest turn: " + _state.NewHeading);
                _state.South        = null;
                _state.LogicalState = LogicalState.AdjustHeading;
                break;

            default:
                LogInfo("Explorer.Map() called in illegal state");
                break;
            }
        }
        /// <summary>
        /// Gets the most recent laser notification. Older notifications are dropped.
        /// </summary>
        /// <param name="laserData">last known laser data</param>
        /// <returns>most recent laser data</returns>
        private sicklrf.State GetMostRecentLaserNotification(sicklrf.State laserData)
        {
            sicklrf.Replace testReplace;

            // _laserNotify is a PortSet<>, P3 represents IPort<sicklrf.Replace> that
            // the portset contains
            int count = _laserNotify.P3.ItemCount - 1;

            for (int i = 0; i < count; i++)
            {
                testReplace = _laserNotify.Test <sicklrf.Replace>();
                if (testReplace.Body.TimeStamp > laserData.TimeStamp)
                {
                    laserData = testReplace.Body;
                }
            }

            if (count > 0)
            {
                LogInfo(string.Format("Dropped {0} laser readings (laser start)", count));
            }
            return(laserData);
        }
Example #20
0
        public void ReplaceLaserData(sicklrf.State stateType)
        {
            if (stateType.TimeStamp < _lastLaser)
            {
                return;
            }
            _lastLaser = stateType.TimeStamp;
            TimeSpan delay = DateTime.Now - stateType.TimeStamp;

            lblDelay.Text = delay.ToString();

            createCylinder(stateType);
            createTop(stateType);

            if (btnConnectLRF.Enabled)
            {
                btnConnectLRF.Enabled = false;
            }
            if (!btnDisconnect.Enabled)
            {
                btnDisconnect.Enabled = true;
            }
        }
        private void RaycastResultsHandler(physics.RaycastResult result)
        {
            // we just receive ray cast information from physics. Currently we just use
            // the distance measurement for each impact point reported. However, our simulation
            // engine also provides you the material properties so you can decide here to simulate
            // scattering, reflections, noise etc.

            sicklrf.State latestResults = new sicklrf.State();
            latestResults.DistanceMeasurements = new int[result.SampleCount + 1];
            int initValue = (int)(LASER_RANGE * 1000f);

            for (int i = 0; i < (result.SampleCount + 1); i++)
            {
                latestResults.DistanceMeasurements[i] = initValue;
            }

            foreach (physics.RaycastImpactPoint pt in result.ImpactPoints)
            {
                // the distance to the impact has been pre-calculted from the origin
                // and it's in the fourth element of the vector
                latestResults.DistanceMeasurements[pt.ReadingIndex] = (int)(pt.Position.W * 1000f);
            }

            latestResults.AngularRange      = (int)Math.Abs(_entity.RaycastProperties.EndAngle - _entity.RaycastProperties.StartAngle);
            latestResults.AngularResolution = _entity.RaycastProperties.AngleIncrement;
            latestResults.Units             = sicklrf.Units.Millimeters;
            latestResults.LinkState         = "Measurement received";
            latestResults.TimeStamp         = DateTime.Now;

            // send replace message to self
            sicklrf.Replace replace = new sicklrf.Replace();
            // for perf reasons dont set response port, we are just talking to ourself anyway
            replace.ResponsePort = null;
            replace.Body         = latestResults;
            _mainPort.Post(replace);
        }
Example #22
0
        /// <summary>
        /// Finds the best free corridor (maximum free space ahead) in a 360 degree scan.
        /// </summary>
        /// <param name="south">the backward half of the scan</param>
        /// <param name="north">the forward half of the scan</param>
        /// <returns>beast heading in degrees</returns>
        private int FindBestComposite(sicklrf.State south, sicklrf.State north)
        {
            sicklrf.State composite = new sicklrf.State();

            composite.DistanceMeasurements = new int[720];

            for (int i = 0; i < 720; i++)
            {
                if (i < 180)
                {
                    composite.DistanceMeasurements[i] = south.DistanceMeasurements[i + 180];
                }
                else if (i < 540)
                {
                    composite.DistanceMeasurements[i] = north.DistanceMeasurements[i - 180];
                }
                else
                {
                    composite.DistanceMeasurements[i] = south.DistanceMeasurements[i - 540];
                }
            }

            composite.AngularResolution = 0.5;
            composite.AngularRange = 360;
            composite.Units = north.Units;

            return FindBestFrom(composite, 0, 0, CorridorWidthMoving);
        }
Example #23
0
 public LaserRangeFinderUpdate(sicklrf.State body)
     : base(body)
 {
 }
        protected void GenerateTop(sicklrf.State laserData, int fieldOfView, RoutePlan plan)
        {
            //lock (lockStatusGraphics)
            //{

            if (currentStatusGraphics != null)
            {
                bool haveLaser = laserData != null && laserData.DistanceMeasurements != null && (DateTime.Now - _laserData.TimeStamp).TotalSeconds < 2.0d;

                //Bitmap bmp = (_state.MovingState == MovingState.MapSouth) ? currentStatusGraphics.statusBmp : currentStatusGraphics.northBmp;
                //Bitmap bmp = currentStatusGraphics.statusBmp;
                Bitmap bmp = currentStatusGraphics.northBmp;

                lock (bmp)
                {
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        g.Clear(Color.LightGray);

                        List <Lbl> labels = new List <Lbl>();

                        if (haveLaser)
                        {
                            double angularOffset = -90 + laserData.AngularRange / 2.0;
                            double piBy180       = Math.PI / 180.0;
                            double halfAngle     = laserData.AngularResolution / 2.0;
                            double drangeMax     = 0.0d;

                            GraphicsPath path = new GraphicsPath();

                            // make two passes, drawing laser data and label every 20th range:
                            for (int pass = 1; pass <= 2; pass++)
                            {
                                for (int i = 0; i < laserData.DistanceMeasurements.Length; i++)
                                {
                                    int range = laserData.DistanceMeasurements[i];
                                    if (range > 0 && range < 8192)
                                    {
                                        double angle     = i * laserData.AngularResolution - angularOffset;
                                        double lowAngle  = (angle - halfAngle) * piBy180;
                                        double highAngle = (angle + halfAngle) * piBy180;

                                        double drange = range * StatusGraphics.scale;

                                        float lx = (float)(StatusGraphics.xCenter + drange * Math.Cos(lowAngle));
                                        float ly = (float)(StatusGraphics.xCenter - drange * Math.Sin(lowAngle));
                                        float hx = (float)(StatusGraphics.xCenter + drange * Math.Cos(highAngle));
                                        float hy = (float)(StatusGraphics.xCenter - drange * Math.Sin(highAngle));

                                        if (pass == 1)
                                        {
                                            // on the first pass just add lines to the Path and calculate the max range:
                                            if (i == 0)
                                            {
                                                path.AddLine(StatusGraphics.xCenter, StatusGraphics.imageHeight, lx, ly);
                                            }
                                            path.AddLine(lx, ly, hx, hy);

                                            drangeMax = Math.Max(drangeMax, drange);
                                        }
                                        else
                                        {
                                            // on the second pass draw the perimeter and label every 20th range:
                                            g.DrawLine(Pens.DarkBlue, lx, ly, hx, hy);

                                            if (i > 0 && i % 20 == 0 && i < laserData.DistanceMeasurements.Length - 10)
                                            {
                                                float  llx        = (float)(StatusGraphics.xCenter + drangeMax * 1.3f * Math.Cos(lowAngle));
                                                float  lly        = (float)(StatusGraphics.xCenter - drangeMax * 1.3f * Math.Sin(lowAngle));
                                                double roundRange = Math.Round(range / 1000.0d, 1); // meters
                                                string str        = "" + roundRange;
                                                labels.Add(new Lbl()
                                                {
                                                    label = str, lx = llx, ly = lly, brush = Brushes.Black
                                                });
                                            }
                                        }
                                    }
                                }

                                if (pass == 1)
                                {
                                    // draw the laser sweep on the first pass:
                                    g.FillPath(Brushes.White, path);
                                }
                            }
                        }

                        // draw important decision-influencing boundaries:
                        float startAngle = -150.0f;
                        float sweepAngle = 120.0f;

                        // the "stop moving" distance:
                        float radius = (float)(ObstacleDistanceMm * StatusGraphics.scale);
                        //g.DrawRectangle(Pens.Red, xCenter - radius, imageHeight - radius, radius * 2, radius * 2);
                        g.DrawArc(Pens.Red, StatusGraphics.xCenter - radius, StatusGraphics.imageHeight - radius, radius * 2, radius * 2, startAngle, sweepAngle);
                        rayLabel("stop", labels, ObstacleDistanceMm, -60.0d, Brushes.Red);

                        // the "slow down" distance:
                        radius = (float)(AwareOfObstacleDistanceMm * StatusGraphics.scale);
                        g.DrawArc(Pens.Orange, StatusGraphics.xCenter - radius, StatusGraphics.imageHeight - radius, radius * 2, radius * 2, startAngle, sweepAngle);
                        rayLabel("slow", labels, AwareOfObstacleDistanceMm, -60.0d, Brushes.Orange);

                        // the "stop mapping, enter the open space" distance
                        radius = (float)(SafeDistanceMm * StatusGraphics.scale);
                        g.DrawArc(Pens.LightBlue, StatusGraphics.xCenter - radius, StatusGraphics.imageHeight - radius, radius * 2, radius * 2, startAngle, sweepAngle);
                        rayLabel("enter", labels, SafeDistanceMm, -60.0d, Brushes.LightBlue);

                        // the "max velocity" distance:
                        radius = (float)(FreeDistanceMm * StatusGraphics.scale);
                        g.DrawArc(Pens.Green, StatusGraphics.xCenter - radius, StatusGraphics.imageHeight - radius, radius * 2, radius * 2, startAngle, sweepAngle);
                        rayLabel("free", labels, FreeDistanceMm, -60.0d, Brushes.Green);

                        // the fieldOfView arc:
                        radius = (float)(StatusGraphics.imageHeight - 10);
                        g.DrawArc(Pens.LimeGreen, StatusGraphics.xCenter - radius, StatusGraphics.imageHeight - radius, radius * 2, radius * 2, (float)(-90 - fieldOfView), (float)(fieldOfView * 2));
                        rayLabel("field of view", labels, (StatusGraphics.imageHeight + 5) / StatusGraphics.scale, 10.0d, Brushes.LimeGreen);

                        // now draw the robot. Trackroamer is 680 mm wide.
                        float botHalfWidth = (float)(680 / 2.0d * StatusGraphics.scale);
                        DrawHelper.drawRobotBoundaries(g, botHalfWidth, StatusGraphics.imageWidth / 2, StatusGraphics.imageHeight);

                        // debug- draw a ray pointing to predefined direction; left is positive, right is negative:
                        //double rayLength = 2000.0d;
                        //rayLine("20", g, rayLength, 20.0d, Pens.Cyan, Brushes.DarkCyan);
                        //rayLine("-20", g, rayLength, -20.0d, Pens.Blue, Brushes.Blue);
                        //rayLine("70", g, rayLength, 70.0d, Pens.Red, Brushes.Red);
                        //rayLine("-70", g, rayLength, -70.0d, Pens.Green, Brushes.Green);

                        // draw laser's time stamp:
                        if (haveLaser)
                        {
                            TimeSpan howOld = DateTime.Now - laserData.TimeStamp;
                            g.DrawString(laserData.TimeStamp.ToString() + " (" + howOld + ")", StatusGraphics.fontBmp, Brushes.Black, 0, 0);
                        }

                        HistoryItem latestDecisionsHistory = StatusGraphics.HistoryDecisions.Peek();
                        HistoryItem latestSaidHistory      = Talker.HistorySaid.Peek();

                        if (latestSaidHistory != null)
                        {
                            g.DrawString(latestSaidHistory.message, StatusGraphics.fontBmpL, Brushes.Black, StatusGraphics.imageWidth / 2 + 80, StatusGraphics.imageHeight + StatusGraphics.extraHeight - 20);
                        }

                        if (latestDecisionsHistory != null)
                        {
                            g.DrawString(latestDecisionsHistory.message, StatusGraphics.fontBmpL, Brushes.Black, StatusGraphics.imageWidth / 2 + 80, StatusGraphics.imageHeight + StatusGraphics.extraHeight - 40);
                        }

                        g.DrawString(_state.MovingState.ToString(), StatusGraphics.fontBmpL, Brushes.Black, StatusGraphics.imageWidth / 2 - 40, StatusGraphics.imageHeight + StatusGraphics.extraHeight - 20);

                        // draw distance labels over all other graphics:
                        foreach (Lbl lbl in labels)
                        {
                            g.DrawString(lbl.label, StatusGraphics.fontBmp, lbl.brush, lbl.lx, lbl.ly + 20);
                        }

                        // a 200W x 400H rectangle:
                        Rectangle drawRect = new Rectangle(StatusGraphics.imageWidth / 2 - StatusGraphics.extraHeight, StatusGraphics.imageHeight - StatusGraphics.extraHeight * 2, StatusGraphics.extraHeight * 2, StatusGraphics.extraHeight * 4);

                        if (_state.MostRecentProximity != null)
                        {
                            // the MostRecentProximity class here comes from the proxy, and does not have arrangedForDrawing member. Restore it:

                            double[] arrangedForDrawing = new double[8];

                            arrangedForDrawing[0] = _state.MostRecentProximity.mbr;
                            arrangedForDrawing[1] = _state.MostRecentProximity.mbbr;
                            arrangedForDrawing[2] = _state.MostRecentProximity.mbbl;
                            arrangedForDrawing[3] = _state.MostRecentProximity.mbl;

                            arrangedForDrawing[4] = _state.MostRecentProximity.mfr;
                            arrangedForDrawing[5] = _state.MostRecentProximity.mffr;
                            arrangedForDrawing[6] = _state.MostRecentProximity.mffl;
                            arrangedForDrawing[7] = _state.MostRecentProximity.mfl;

                            // draw a 200x400 image of IR proximity sensors:

                            DrawHelper.drawProximityVectors(g, drawRect, arrangedForDrawing, 1);
                        }

                        if (_state.MostRecentParkingSensor != null)
                        {
                            // the MostRecentParkingSensor class here comes from the proxy, and does not have arrangedForDrawing member. Restore it:

                            double[] arrangedForDrawing = new double[4];

                            arrangedForDrawing[0] = _state.MostRecentParkingSensor.parkingSensorMetersRB;
                            arrangedForDrawing[1] = _state.MostRecentParkingSensor.parkingSensorMetersLB;
                            arrangedForDrawing[2] = _state.MostRecentParkingSensor.parkingSensorMetersLF;
                            arrangedForDrawing[3] = _state.MostRecentParkingSensor.parkingSensorMetersRF;

                            // draw a 200x400 image of parking sensors:

                            DrawHelper.drawProximityVectors(g, drawRect, arrangedForDrawing, 2);
                        }

                        if (plan != null && plan.isGoodPlan)
                        {
                            // right turn - positive, left turn - negative, expressed in degrees:
                            int    bestHeadingInt      = (int)Math.Round((double)plan.bestHeadingRelative(_mapperVicinity));
                            double bestHeadingDistance = plan.legMeters.Value * 1000.0d;

                            using (Pen dirPen = new Pen(Color.Green, 5.0f))
                            {
                                dirPen.EndCap = LineCap.ArrowAnchor;
                                rayLine("best:" + bestHeadingInt, g, bestHeadingDistance * 1.1d, (double)bestHeadingInt, dirPen, Brushes.Green);
                            }

                            //int xLbl = 10;
                            //int yLbl = bmp.Height - 40;

                            //g.DrawString(comment, StatusGraphics.fontBmpL, Brushes.Green, xLbl, yLbl);
                        }

                        if (_mapperVicinity.robotDirection.bearingRelative.HasValue)
                        {
                            int    goalBearingInt = (int)Math.Round((double)_mapperVicinity.robotDirection.bearingRelative);
                            double goalDistance   = 3000.0d;

                            using (Pen dirPen = new Pen(Color.LimeGreen, 2.0f))
                            {
                                dirPen.EndCap = LineCap.ArrowAnchor;
                                rayLine("goal:" + goalBearingInt, g, goalDistance, (double)goalBearingInt, dirPen, Brushes.LimeGreen);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Finds the best free corridor (maximum free space ahead) in a 360 degree scan.
        /// </summary>
        /// <param name="south">the backward half of the scan</param>
        /// <param name="north">the forward half of the scan</param>
        /// <returns>best heading in degrees (right turn - positive, left turn - negative)</returns>
        private int FindBestComposite(sicklrf.State south, sicklrf.State north)
        {
            try
            {
                // sanity check:
                LogInfo("FindBestComposite() south: " + south.DistanceMeasurements.Length + " points,  north: " + north.DistanceMeasurements.Length + " points");

                if (south.DistanceMeasurements.Length + north.DistanceMeasurements.Length < 360)
                {
                    LogError("FindBestComposite() - bad laser measurement");
                    return 0;
                }

                sicklrf.State composite = new sicklrf.State();

                composite.DistanceMeasurements = new int[361];

                for (int i = 0; i < composite.DistanceMeasurements.Length; i++)
                {
                    // the trick is to have halves of the South scan become sides of the full North scan,
                    // so that a 360 degrees composite has heading 0 in the middle.

                    if (i < 90)
                    {
                        composite.DistanceMeasurements[i] = south.DistanceMeasurements[i + 90];
                    }
                    else if (i < 270)
                    {
                        composite.DistanceMeasurements[i] = north.DistanceMeasurements[i - 90];
                    }
                    else // 270...359
                    {
                        composite.DistanceMeasurements[i] = south.DistanceMeasurements[i - 270];
                    }
                }

                composite.AngularResolution = 1.0;
                composite.AngularRange = 360;
                composite.Units = north.Units;

                return FindBestHeading(composite, 0, 0, CorridorWidthMoving, "Best Composite");
            }
            catch (Exception exc)
            {
                LogError(exc);
                return 0;
            }
        }
Example #26
0
        protected void LaserHandler(sicklrf.Replace replace)
        {
            // Angular Range = r
            // Desired Angular Range = rd
            // Minimum Angle = amin = (r/2) - (rd/2)
            // Maximum Angle = amax = (r/2) + (rd/2)
            // Angular Resolution = e
            // Minimum measurement = mmin = floor(amin / e)
            // Maximum measurement = mmax = ceil(amax / e)
            // Assert e > 0
            // Assert rd > e
            // Total measurements = mtot
            // Assert mtot > 1 (or two)

            if (replace == null)
            {
                return;
            }

            sicklrf.State laserState = replace.Body;
            if (laserState == null)
            {
                return;
            }

            if (laserState.DistanceMeasurements == null)
            {
                return;
            }

            if (laserState.DistanceMeasurements.Length < 2)
            {
                return;
            }

            if (laserState.AngularResolution <= 0)
            {
                return;
            }

            if ((_halfObstacleAngleRange * 2) <= laserState.AngularResolution)
            {
                return;
            }

            // Note: this assumes laserState.AngularRange % 2 = 0
            int    halfRange = laserState.AngularRange / 2;
            double amin      = halfRange - _halfObstacleAngleRange;
            double amax      = halfRange + _halfObstacleAngleRange;

            int mmin = (int)Math.Floor(amin / laserState.AngularResolution);
            int mmax = (int)Math.Ceiling(amax / laserState.AngularResolution);

            // TODO: check that MinimumObstacleRange is less than this
            int computedRange = 8000; // 8000 is around the maximum reported value from the sicklrf

            if (mmin == mmax)
            {
                computedRange = laserState.DistanceMeasurements[mmin];
            }
            else
            {
                for (int index = mmin; index <= mmax; ++index)
                {
                    computedRange = Math.Min(computedRange, laserState.DistanceMeasurements[index]);
                }
            }

            //Trace.WriteLine("samples: " + (mmax - mmin) + ", range: " + computedRange);

            if (computedRange <= _state.MinimumObstacleRange)
            {
                _soar.Obstacle = true;
            }
            else
            {
                _soar.Obstacle = false;
            }
        }
Example #27
0
        private void createTop(sicklrf.State stateType)
        {
            int height = 200;
            int width  = 400;

            Bitmap   bmp = new Bitmap(width, height);
            Graphics g   = Graphics.FromImage(bmp);

            g.Clear(Color.LightGray);

            double angularOffset = -90 + stateType.AngularRange / 2.0;
            double piBy180       = Math.PI / 180.0;
            double halfAngle     = stateType.AngularRange / 360.0 / 2.0;
            double scale         = (double)height / (double)maxDist;

            GraphicsPath path = new GraphicsPath();

            for (int pass = 0; pass != 2; pass++)
            {
                for (int i = 0; i < stateType.DistanceMeasurements.Length; i++)
                {
                    int range = stateType.DistanceMeasurements[i];

                    if (range <= 0)
                    {
                        range = maxDist;
                    }

                    double angle     = i * (stateType.AngularRange / 360.0) - angularOffset;
                    double lowAngle  = (angle - halfAngle) * piBy180;
                    double highAngle = (angle + halfAngle) * piBy180;

                    double drange = range * scale;

                    float lx = (float)(height + drange * Math.Cos(lowAngle));
                    float ly = (float)(height - drange * Math.Sin(lowAngle));
                    float hx = (float)(height + drange * Math.Cos(highAngle));
                    float hy = (float)(height - drange * Math.Sin(highAngle));

                    if (pass == 0)
                    {
                        if (i == 0)
                        {
                            path.AddLine(height, height, lx, ly);
                        }
                        path.AddLine(lx, ly, hx, hy);
                    }
                    else
                    {
                        if (range < maxDist)
                        {
                            double myangle   = i * Math.PI * stateType.AngularRange / stateType.DistanceMeasurements.Length / 180; //radians
                            double obsThresh = Math.Abs(robotWidth / (2 * Math.Cos(myangle)));
                            if (range < obsThresh)
                            {
                                g.DrawLine(Pens.Red, lx, ly, hx, hy);
                            }
                            else
                            {
                                g.DrawLine(Pens.DarkBlue, lx, ly, hx, hy);
                            }
                        }
                    }
                }

                if (pass == 0)
                {
                    g.FillPath(Brushes.White, path);
                }
            }

            float botWidth = (float)((robotWidth / 2.0) * scale);

            g.DrawLine(Pens.Red, height, height - botWidth, height, height);
            g.DrawLine(Pens.Red, height - 3, height - botWidth, height + 3, height - botWidth);
            g.DrawLine(Pens.Red, height - botWidth, height - 3, height - botWidth, height);
            g.DrawLine(Pens.Red, height + botWidth, height - 3, height + botWidth, height);
            g.DrawLine(Pens.Red, height - botWidth, height - 1, height + botWidth, height - 1);

            g.DrawString(
                stateType.TimeStamp.ToString(),
                new Font(FontFamily.GenericSansSerif, 10, GraphicsUnit.Pixel),
                Brushes.Gray, 0, 0
                );

            picLRFtop.Image = bmp;
        }
Example #28
0
        /// <summary>
        /// Finds the best heading in a 180 degree laser scan
        /// </summary>
        /// <param name="laserData">laser scan</param>
        /// <param name="dx">horizontal offset</param>
        /// <param name="dy">vertical offset</param>
        /// <param name="width">width of corridor that must be free</param>
        /// <returns>best heading in degrees</returns>
        private int FindBestFrom(sicklrf.State laserData, int dx, int dy, int width)
        {
            int    count = laserData.DistanceMeasurements.Length;
            double span  = Math.PI * laserData.AngularRange / 180.0;

            List <RangeData> ranges = new List <RangeData>();

            for (int i = 0; i < count; i++)
            {
                int    range = laserData.DistanceMeasurements[i];
                double angle = span * i / count - span / 2.0;

                double x = range * Math.Sin(angle) - dx;
                double y = range * Math.Cos(angle) - dy;

                angle = Math.Atan2(-x, y);
                range = (int)Math.Sqrt(x * x + y * y);

                ranges.Add(new RangeData(range, angle));
            }

            ranges.Sort(RangeData.ByDistance);

            for (int i = 0; i < ranges.Count; i++)
            {
                RangeData curr = ranges[i];

                double delta = Math.Atan2(width, curr.Distance);
                double low   = curr.Heading - delta;
                double high  = curr.Heading + delta;

                for (int j = i + 1; j < ranges.Count; j++)
                {
                    if (ranges[j].Heading > low &&
                        ranges[j].Heading < high)
                    {
                        ranges.RemoveAt(j);
                        j--;
                    }
                }
            }

            ranges.Reverse();

            int    bestDistance = ranges[0].Distance;
            double bestHeading  = ranges[0].Heading;
            Random rand         = new Random();

            for (int i = 0; i < ranges.Count; i++)
            {
                if (ranges[i].Distance < bestDistance)
                {
                    break;
                }
                if (rand.Next(i + 1) == 0)
                {
                    bestHeading = ranges[i].Heading;
                }
            }

            return(-(int)Math.Round(180 * bestHeading / Math.PI));
        }
        public void ReplaceHandler(sicklrf.Replace replace)
        {
            Tracer.Trace("TrackRoamerUsrfService::ReplaceHandler()");

            _state = replace.Body;
            replace.ResponsePort.Post(DefaultReplaceResponseType.Instance);
        }
        protected sicklrf.State simulatedLaser()
        {
            sicklrf.State laserData = new sicklrf.State();
            laserData.Description = "simulated";
            laserData.DistanceMeasurements = new int[181];
            for (int i = 0; i < laserData.DistanceMeasurements.Length; i++)
            {
                laserData.DistanceMeasurements[i] = 3500;
            }
            laserData.Units = sicklrf.Units.Millimeters;
            laserData.AngularResolution = 1.0d;
            laserData.AngularRange = 180;
            laserData.TimeStamp = DateTime.Now;

            _state.MostRecentLaserTimeStamp = laserData.TimeStamp;

            return laserData;
        }