public override async void ControlDeviceCommand(string command)
        {
            //Debug.WriteLine("PluckyTheRobot: ControlDeviceCommand: " + command);

            bool isDispatcherCommand = true;   // if true, dispatcher will be forwarding command to behaviors

            if (command.StartsWith("button") && previousButtonCommand != command)   // avoid button commands repetitions
            {
                Debug.WriteLine("PluckyTheRobot: ControlDeviceCommand: " + command);
                isDispatcherCommand = false;    // no need for further command processing

                switch (command)
                {
                    case "button1":  // "A" button - caution: screen side effects
                        terminatePreviousBehavior(command);
                        currentBehavior = BehaviorCompositionType.Escape;
                        behaviorFactory.produce(currentBehavior);
                        speaker.Speak("Escape");
                        break;

                    case "button2":  // "B" button terminates current behavior
                        terminatePreviousBehavior(command);
                        behaviorFactory.produce(currentBehavior);   // None - closes all active tasks in Dispatcher
                        break;

                    //case "button3":  // "X" button
                    //    break;

                    case "button4":   // "Y" button
                        robotPose.resetXY();
                        //robotPose.resetRotation();
                        robotPose.direction = new Direction() { heading = currentSensorsData.CompassHeadingDegrees };
                        driveController.OdometryReset();
                        speaker.Speak("Reset X Y");
                        break;

                    case "button5":  // "Left Bumper"
                        terminatePreviousBehavior(command);
                        currentTrack = new Track() { trackFileName = waypointsFileName };
                        waypointsIndex = 0;
                        currentBehavior = BehaviorCompositionType.JoystickAndStop;
                        behaviorFactory.produce(currentBehavior);
                        speaker.Speak("Joystick control");
                        break;

                    case "button6":  // "Right Bumper"
                        terminatePreviousBehavior(command);

                        ComputeGoal();  // for CruiseAndStop - corner-to-corner 

                        //currentBehavior = BehaviorCompositionType.CruiseAndStop;
                        currentBehavior = BehaviorCompositionType.ChaseColorBlob;
                        //currentBehavior = BehaviorCompositionType.AroundTheBlock;
                        behaviorFactory.produce(currentBehavior);
                        //speaker.Speak("Around The Block");
                        //speaker.Speak("Cruise control");
                        speaker.Speak("Chase color");
                        break;

                    // buttons 7 and 8 on RamblePad2 reserved for throttle up/down control. Not on Xbox360 controller.

                    case "button7":  // "Back" to the left of the sphere
                        terminatePreviousBehavior(command);

                        // Load stored waypoints:
                        // from C:\Users\sergei\AppData\Local\Packages\RobotPluckyPackage_sjh4qacv6p1wm\LocalState\MyTrack.xml

                        currentBehavior = BehaviorCompositionType.RouteFollowing;
                        behaviorFactory.TrackFileName = null;   // will be replaced with "MyTrack.xml" and serializer will be used.
                        behaviorFactory.produce(currentBehavior);
                        speaker.Speak("Saved trackpoints following");
                        break;

                    case "button8":  // "Start" to the right of the sphere
                        terminatePreviousBehavior(command);
                        currentBehavior = BehaviorCompositionType.RouteFollowing;
                        behaviorFactory.TrackFileName = "ParkingLot1.waypoints";
                        behaviorFactory.produce(currentBehavior);
                        speaker.Speak("Planned trackpoints following");
                        break;

                    case "button9":  // Left Joystick push
                        {
                            bool allowStaleGps = true;
                            bool allowOnlyGpsFix3D = false;

                            if (!allowStaleGps && (DateTime.Now - new DateTime(currentSensorsData.GpsTimestamp)).TotalSeconds > 3)
                            {
                                speaker.Speak("Cannot add waypoint, GPS data stale");
                            }
                            else
                            {
                                if (!allowOnlyGpsFix3D || allowOnlyGpsFix3D && currentSensorsData.GpsFixType == GpsFixTypes.Fix3D)
                                {
                                    currentTrack.trackpoints.Add(new Trackpoint(
                                        waypointsIndex,
                                        false, //waypointsIndex == 0,       // home
                                        currentSensorsData.GpsLatitude,
                                        currentSensorsData.GpsLongitude,
                                        currentSensorsData.GpsAltitude
                                    ));
                                    waypointsIndex++;
                                    speaker.Speak("Added waypoint " + currentTrack.Count);
                                }
                                else
                                {
                                    speaker.Speak("Cannot add waypoint, low GPS fix: " + currentSensorsData.GpsFixType);
                                }
                            }
                        }
                        break;

                    //case "button10":  // right stick push
                    //    break;

                    default:
                        speaker.Speak(command + " not supported");
                        break;
                }
                previousButtonCommand = command;    // avoid repetitions
            }

            if (isDispatcherCommand)
            {
                // dispatcher will be forwarding command like "speed" to behaviors
                subsumptionTaskDispatcher.ControlDeviceCommand(command);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ddg"></param>
        /// <param name="speaker"></param>
        /// <param name="trackFileName">can be null, for a saved track</param>
        public BehaviorRouteFollowing(IDriveGeometry ddg, ISpeaker speaker, string trackFileName)
            : base(ddg)
        {
            this.speaker = speaker;

            BehaviorActivateCondition = bd =>
            {
                return nextWp != null;
            };

            BehaviorDeactivateCondition = bd =>
            {
                return nextWp == null;
            };

            if (String.IsNullOrWhiteSpace(trackFileName))
            {
                speaker.Speak("Loading saved track");
                try
                {
                    missionTrack = null;

                    // Load stored waypoints:
                    // on the PC, from   C:\Users\sergei\AppData\Local\Packages\RobotPluckyPackage_sjh4qacv6p1wm\LocalState\MyTrack.xml
                    //            RPi:   \\172.16.1.175\c$\Data\Users\DefaultAccount\AppData\Local\Packages\RobotPluckyPackage_sjh4qacv6p1wm\LocalState
                    Track track = SerializableStorage<Track>.Load(savedTrackFileName).Result;

                    if (track != null)
                    {
                        missionTrack = track;
                        speaker.Speak("Loaded file " + missionTrack.Count + " trackpoints");
                    }
                }
                catch (Exception ex)
                {
                    speaker.Speak("could not load saved track file");
                }

                if(missionTrack == null)
                {
                    speaker.Speak("failed to load saved track file");
                    missionTrack = new Track();
                }
                nextWp = missionTrack.nextTargetWp;
            }
            else
            {
                speaker.Speak("Loading file " + trackFileName);

                missionTrack = new Track();

                try
                {
                    missionTrack.Init(trackFileName);

                    speaker.Speak("Loaded file " + missionTrack.Count + " trackpoints");

                    nextWp = missionTrack.nextTargetWp;
                }
                catch (Exception ex)
                {
                    speaker.Speak("could not load planned track file");
                }
            }
        }