예제 #1
0
        /**
         *
         */
        private void DeviceList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                //Stop the stream of the previously selected event
                foreach (PiCarConnection oldPicar in e.RemovedItems)
                {
                    oldPicar.StopStream();
                    clearStreamImage();
                }
            }
            catch (Exception exception)
            {
                //TODO Remove vehicles that throw exceptions
                LogField.AppendText(DateTime.Now + ":\tException found when removing an old streams!\n" + e + "\n");
                //TODO remove previous car
                Console.WriteLine(exception);
            }
            var picar = SelectedPiCar();

            if (picar is null)
            {
                return;
            }

            StreamToggle.IsEnabled = true;
            StreamToggle.IsChecked = false;


            //Update ipBox and deviceStatus with it's info
            IpBox.Text        = picar.ipAddress.ToString();
            DeviceStatus.Text = picar.Mode.ToString();
        }
예제 #2
0
        /**
         * Method that handles when the GUI buttons are held down (Vehicle is moving a single direction)
         */
        private void ButtonPress_Event(object sender, RoutedEventArgs e)
        {
            //TODO add button up event for stop command
            //var picar = (PiCarConnection)DeviceListMn.SelectedItem;
            //if (picar == null || picar.Mode != ModeRequest.Types.Mode.Lead) return;
            var button = (RepeatButton)sender;

            switch (button.Name)
            {
            case "Forward":
                LogField.AppendText(DateTime.Now + ":\tMoving forward\n");
                MoveVehicle(1.0, 0.0);
                break;

            case "Backwards":
                LogField.AppendText(DateTime.Now + ":\tMoving backwards\n");
                MoveVehicle(-1.0, 0.0);
                break;

            case "Left":
                LogField.AppendText(DateTime.Now + ":\tMoving left\n");
                MoveVehicle(0.0, -1.0);
                break;

            case "Right":
                LogField.AppendText(DateTime.Now + ":\tMoving right\n");
                MoveVehicle(0.0, 1.0);
                break;

            default:
                Console.WriteLine("Mistakes were made");
                break;
            }
            LogField.ScrollToEnd();
        }
예제 #3
0
        /**
         * Method that handles when one or more key is released (Vehicle is stopping in one or more directions)
         */
        private void Key_up(object sender, KeyEventArgs e)
        {
            //var picar = (PiCarConnection)DeviceListMn.SelectedItem;
            //if (picar == null || picar.Mode != ModeRequest.Types.Mode.Lead) return;

            var directionMotor = 0.0;
            var throttleMotor  = 0.0;

            if (Keyboard.IsKeyUp(Key.W) && Keyboard.IsKeyUp(Key.Up))
            {
                throttleMotor--;
            }

            if (Keyboard.IsKeyUp(Key.S) && Keyboard.IsKeyUp(Key.Down))
            {
                throttleMotor++;
            }

            if (Keyboard.IsKeyUp(Key.A) && Keyboard.IsKeyUp(Key.Left))
            {
                directionMotor++;
            }

            if (Keyboard.IsKeyUp(Key.D) && Keyboard.IsKeyUp(Key.Right))
            {
                directionMotor--;
            }

            string output = Direction.EncodeDirection(DateTime.Now, throttleMotor, directionMotor);

            LogField.AppendText(output);
            MoveVehicle(throttleMotor, directionMotor);
            LogField.ScrollToEnd();
        }
예제 #4
0
 /**
  *  Method that handles when the GUI button is released (Vehicle is stopped)
  */
 private void ButtonPress_Released(object sender, RoutedEventArgs e)
 {
     //var picar = (PiCarConnection)DeviceListMn.SelectedItem;
     //if (picar == null || picar.Mode != ModeRequest.Types.Mode.Lead) return;
     LogField.AppendText(DateTime.Now + ":\tNow In Neutral\n");
     MoveVehicle(0.0, 0.0);
     LogField.ScrollToEnd();
 }
예제 #5
0
 //stops the stream from being saved
 private void StopSaving_Click(object sender, RoutedEventArgs e)
 {
     StreamSavingHeader.IsEnabled     = true;
     StopStreamSavingHeader.IsEnabled = false;
     if (_saveStreamEnabled == true)
     {
         LogField.AppendText(DateTime.Now + ":\tStream will no longer be saved to a file\n");
         LogField.ScrollToEnd();
     }
     _saveStreamEnabled = false;
 }
예제 #6
0
 /**
  * Clear the image that was displayed by the stream
  */
 public void clearStreamImage()
 {
     try
     {
         synchronizationContext.Post(o => StreamImage.Source = (ImageSource)o, null);
     }
     catch (Exception e)
     {
         LogField.AppendText($"{DateTime.Now}:\tError clearing stream image: {e}\n");
     }
 }
예제 #7
0
        private void SetFollowerModelPID_Click(object sender, RoutedEventArgs e)
        {
            var picar = SelectedPiCar();

            if (picar is null)
            {
                return;
            }
            LogField.AppendText(DateTime.Now + ":\tSetting " + picar + "to legacy PID follower model\n");
            LogField.ScrollToEnd();
            picar.SetFollowerModel(1);
        }
예제 #8
0
        /**
         * Method that runs when the main window launches
         */
        public MainWindow()
        {
            InitializeComponent();

            //Setup sync context
            synchronizationContext = SynchronizationContext.Current;

            Title = "Welcome " + Environment.UserName;

            //Adds shortcut to open the registration window with Ctrl + R
            var newKeybind = new RoutedCommand();

            newKeybind.InputGestures.Add(new KeyGesture(Key.R, ModifierKeys.Control));
            CommandBindings.Add(new CommandBinding(newKeybind, Register_Click));

            _controlMode = true;

            _saveStreamEnabled = false;

            //Adds shortut Ctrl + S for stream saving and Ctrl + D for disabling stream saving
            var streamKeybind = new RoutedCommand();

            streamKeybind.InputGestures.Add(new KeyGesture(Key.S, ModifierKeys.Control));
            CommandBindings.Add(new CommandBinding(streamKeybind, ImageSaving_Click));

            var dStreamKeybind = new RoutedCommand();

            dStreamKeybind.InputGestures.Add(new KeyGesture(Key.D, ModifierKeys.Control));
            CommandBindings.Add(new CommandBinding(dStreamKeybind, StopSaving_Click));



            //Checks if a controller is plugged into the current OS
            _controller = new Controller(UserIndex.One);
            if (!_controller.IsConnected)
            {
                LogField.AppendText(DateTime.Now + ":\tNo controller found!\n");
            }
            else
            {
                //Uses a timer to loop a method that checks the status of the controller
                LogField.AppendText(DateTime.Now + ":\tController detected!\n");
                _timer = new DispatcherTimer {
                    Interval = TimeSpan.FromSeconds(1 / 30)
                };
                _timer.Tick += _timer_Tick;
                _timer.Start();
                _directionController = 0.0;
                _throttleController  = 0.0;
            }
            //sets initial connection configuration specified by .ini file
            initializeUI();
        }
예제 #9
0
        //tries to connect to cars specified in .ini file
        private async Task IPConnect(string selectedIP, string selectedName)
        {
            //Handle the dummy connection
            if (selectedIP == "DummyIP")
            {
                var dummyConnection = new DummyConnection(selectedName, selectedIP);
                deviceListMain.Add(dummyConnection);
                LogField.AppendText(DateTime.Now + ":\t" + "Added " + selectedName + " for testing\n");
                //LogFieldReg.AppendText("Added " + selectedName + " for testing\n");
            }

            else if (!CheckIfValidIP(selectedIP))
            {
                //LogFieldReg.AppendText("Invalid IP used, try again!\n");
                LogField.AppendText(DateTime.Now + ":\tInvalid IP used, try again!\n");
            }

            else
            {
                PiCarConnection newConnection = null;
                var             canConnect    = false;
                try
                {
                    newConnection = new PiCarConnection(selectedName, selectedIP);
                    var connectResponse = newConnection.RequestConnect();
                    Console.Write(connectResponse.Item2);
                    //LogFieldReg.AppendText(connectResponse.Item2);
                    LogField.AppendText(DateTime.Now + ":\t" + connectResponse.Item2);
                    canConnect = connectResponse.Item1;
                }
                catch (RpcException rpcE)
                {
                    LogField.AppendText(DateTime.Now + ":\tRPC error: " + rpcE.Message + "\n");
                }
                catch (Exception exception)
                {
                    LogField.AppendText(DateTime.Now + ":\tError! " + exception + "\n");
                }

                if (canConnect)
                {
                    LogField.AppendText(DateTime.Now + ":\t" + "Connected to " + selectedName + " with IP: " + selectedIP + "\n");
                    //LogFieldReg.AppendText("Connected to " + selectedName + " with IP: " + selectedIP + "\n");
                    deviceListMain.Add(newConnection);
                }
                else
                {
                    LogField.AppendText(DateTime.Now + ":\t" + "Failed to connect to " + selectedName + " with IP: " + selectedIP + "\n");
                    //LogFieldReg.AppendText("Failed to connect to " + selectedName + " with IP: " + selectedIP + "\n");
                }
            }
        }
예제 #10
0
 /**
  * Timer method that calls the method that checks the controller status
  */
 private void _timer_Tick(object sender, EventArgs e)
 {
     try
     {
         ControllerMovement();
     }
     catch (Exception exception)
     {
         Console.WriteLine(exception);
         LogField.AppendText(DateTime.Now + ":\tController disconnected\n");
         _timer.Stop();
     }
 }
예제 #11
0
        private void DisconnectCar(PiCarConnection picar)
        {
            if (picar.GetType() == typeof(DummyConnection))
            {
                return;
            }

            LogField.AppendText(DateTime.Now + ":\t" + picar + " stopped responding, disconnecting.\n");
            LogField.ScrollToEnd();
            deviceListMain.Remove(picar);
            DeviceListMn.ItemsSource = null;
            DeviceListMn.ItemsSource = deviceListMain;
        }
예제 #12
0
        /**
         * Update method which gets called by PiCarConnection when sending image frames and car actions.
         */
        public void HandleStream(byte[] imageBytes, SetMotion action)
        {
            if (imageBytes == null)
            {
                return;
            }

            var  save_dir_path  = getPathName();
            var  session_prefix = getSessionName();
            bool save_to_disk   = getSaveEnabled();

            //Convert bytes to ImageSource type for GUI
            var imgSource = (ImageSource) new ImageSourceConverter().ConvertFrom(imageBytes);

            // Update the GUI
            try
            {
                synchronizationContext.Post(o => StreamImage.Source = (ImageSource)o, imgSource);
            }
            catch (Exception e)
            {
                LogField.AppendText($"{DateTime.Now}: Error updating the GUI with image received from car: {e}\n");
            }

            if (save_to_disk)
            {
                try
                {
                    var csv_path        = $"{save_dir_path}\\{session_prefix}.csv";
                    var image_file_name = $"{session_prefix}_{saved_frame_count.ToString("D5")}.jpg";

                    saved_frame_count += 1;
                    using (var fileStream = new FileStream($"{save_dir_path}\\train\\{image_file_name}", FileMode.Create))
                    {
                        //Console.WriteLine($"Writing image of length {imageBytes.Length}");
                        fileStream.Write(imageBytes, 0, imageBytes.Length);
                        fileStream.Flush();
                    }

                    using (var streamWriter = new StreamWriter(csv_path, true))
                    {
                        streamWriter.WriteLineAsync($"train/{image_file_name},{action.Throttle},{action.Direction}");
                    }
                }
                catch (IOException e)
                {
                    LogField.AppendText($"{DateTime.Now}:\tError writing stream data to disk: {e.Message}\n");
                }
            }
        }
예제 #13
0
 private void SetVehicleMode(PiCarConnection picar, ModeRequest.Types.Mode mode)
 {
     try
     {
         picar.SetMode(mode);
         DeviceStatus.Text = picar.Mode.ToString();
         LogField.AppendText(DateTime.Now + ":\tSetting " + picar + "to " + picar.Mode.ToString() + "\n");
         LogField.ScrollToEnd();
     }
     catch (Exception e)
     {
         DisconnectCar(picar);
         Console.WriteLine(e);
     }
 }
예제 #14
0
        public void writeStreamCsvHeader()
        {
            var save_dir_path  = getPathName();
            var session_prefix = getSessionName();
            var csv_path       = $"{save_dir_path}\\{session_prefix}.csv";

            if (!File.Exists(csv_path))
            {
                try {
                    using (var streamWriter = new StreamWriter(csv_path, true)) {
                        streamWriter.WriteLineAsync($"image_file,throttle,direction");
                    }
                }
                catch (IOException e) {
                    LogField.AppendText($"{DateTime.Now}:\tError opening csv: {e.Message}\n");
                }
            }
        }
예제 #15
0
 private void ModeChanger_Click(object sender, RoutedEventArgs e)
 {
     if (_controlMode)
     {
         _controlMode                = false;
         DefaultHeader.IsEnabled     = true;
         AlternativeHeader.IsEnabled = false;
         LogField.AppendText(DateTime.Now + ":\tUsing RC control mode\n");
     }
     else
     {
         _controlMode                = true;
         DefaultHeader.IsEnabled     = false;
         AlternativeHeader.IsEnabled = true;
         LogField.AppendText(DateTime.Now + ":\tUsing simulator control mode\n");
     }
     LogField.ScrollToEnd();
 }
예제 #16
0
        /**
         * Method that handles when one or more key is pressed down (Vehicle is moving in one or more directions)
         */
        private void Key_down(object sender, KeyEventArgs e)
        {
            //var picar = (PiCarConnection)DeviceListMn.SelectedItem;
            //if (picar == null || picar.Mode != ModeRequest.Types.Mode.Lead) return;
            if (e.IsRepeat)
            {
                return;
            }

            var directionMotor = 0.0;
            var throttleMotor  = 0.0;

            string[] throttleStrings  = { "Moving backwards", "In Neutral", "Moving forwards" };
            string[] directionStrings = { "and left", "", "and right" };


            if (Keyboard.IsKeyDown(Key.W) || Keyboard.IsKeyDown(Key.Up))
            {
                throttleMotor++;
            }

            if (Keyboard.IsKeyDown(Key.S) || Keyboard.IsKeyDown(Key.Down))
            {
                throttleMotor--;
            }

            if (Keyboard.IsKeyDown(Key.A) || Keyboard.IsKeyDown(Key.Left))
            {
                directionMotor--;
            }

            if (Keyboard.IsKeyDown(Key.D) || Keyboard.IsKeyDown(Key.Right))
            {
                directionMotor++;
            }

            string output = Direction.EncodeDirection(DateTime.Now, throttleMotor, directionMotor);

            LogField.AppendText(output);
            MoveVehicle(throttleMotor, directionMotor);
            LogField.ScrollToEnd();
        }
예제 #17
0
        /**
         * Method that handles shutdown confirmation
         */
        private void Window_Closing(object sender, CancelEventArgs e)
        {
            foreach (var t in DeviceListMn.Items)
            {
                try
                {
                    if (!(t is PiCarConnection temp) || temp.Mode != ModeRequest.Types.Mode.Lead)
                    {
                        continue;
                    }
                    LogField.AppendText(DateTime.Now + ":\t" + temp.Name + " is stopping");
                    clearStreamImage();
                    temp.StopStream();
                    MoveVehicle(0.0, 0.0);
                    SetVehicleMode(ModeRequest.Types.Mode.Idle);
                }
                catch (Exception exception)
                {
                    LogField.AppendText(DateTime.Now + ":\tSomething went wrong: " + exception.ToString());
                }
            }

            Application.Current.Shutdown();
        }
예제 #18
0
        //sets up initia configuration for connection and log using specified .ini file
        private async void initializeUI()
        {
            ArrayList carInfoArray = new ArrayList();

            var file_path = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}\\picar\\gui_config.ini";

            if (!File.Exists(file_path))
            {
                return;
            }

            //gets text from specified .ini file
            try {
                string[] lines = File.ReadAllLines(file_path);

                string   selectedIP;
                string   selectedName;
                string[] ipNameAndMode;

                string mode;
                string path;
                string session;

                string[] path_and_session;
                for (int i = 0; i < lines.Length; i++)
                {
                    if (lines[i].StartsWith("#"))
                    {
                        continue;
                    }
                    ;

                    if (lines[i] == "(*connect)")
                    {
                        while (lines[i + 1] != "(connect*)")
                        {
                            ipNameAndMode = lines[i + 1].Split(',');
                            selectedIP    = ipNameAndMode[0];
                            selectedName  = ipNameAndMode[1];
                            mode          = ipNameAndMode[2];
                            carInfoArray.Add(ipNameAndMode);
                            await IPConnect(selectedIP, selectedName);

                            i = i + 1;
                        }
                    }

                    if (lines[i] == "(*stream)")
                    {
                        while (lines[i + 1] != "(stream*)")
                        {
                            path_and_session = lines[i + 1].Split(',');
                            path             = path_and_session[0];
                            session          = path_and_session[1];
                            setPathName(path);
                            setSessionName(session);
                            i = i + 1;
                        }
                    }

                    if (lines[i] == "(*log)")
                    {
                        while (lines[i + 1] != "(log*)")
                        {
                            LogField.AppendText(lines[i + 1] + "\n");
                            i = i + 1;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogField.AppendText($"{DateTime.Now}:\tError when initializing configuration: {e.Message}\n");
            }
            DeviceListMn.ItemsSource = null;
            DeviceListMn.ItemsSource = deviceListMain;

            //initializes mode for each connection in .ini
            foreach (string[] m in carInfoArray)
            {
                initializeMode(m[1], m[2]);
            }
        }
예제 #19
0
        /**
         * Method that handles the simulator style input for variable speed and direction
         */
        private void ControllerMovement()
        {
            //var picar = (PiCarConnection)DeviceListMn.SelectedItem;
            //if (picar == null || picar.Mode != ModeRequest.Types.Mode.Lead) return;
            var state = _controller.GetState().Gamepad;

            //Default control settings (Simulator Mode)
            if (_controlMode)
            {
                if (state.LeftThumbX.Equals(_previousState.LeftThumbX) &&
                    state.LeftTrigger.Equals(_previousState.LeftTrigger) &&
                    state.RightTrigger.Equals(_previousState.RightTrigger))
                {
                    return;
                }


                //_Motor1 produces either -1.0 for left or 1.0 for right motion
                _directionController = Math.Abs((double)state.LeftThumbX) < DeadzoneValue
                    ? 0 :
                                       (double)state.LeftThumbX / short.MinValue * -1;
                _directionController = Math.Round(_directionController, 3);

                /**
                 * These variables produce either 1.0 for forward motion, or -1 for backwards.
                 * If the values are both non-zero, then there will be no motion in either direction
                 */
                var forwardSpeed  = Math.Round(state.RightTrigger / 255.0, 3);
                var backwardSpeed = Math.Round(state.LeftTrigger / 255.0 * -1.0, 3);

                if (forwardSpeed > 0 && backwardSpeed == 0)
                {
                    _throttleController = forwardSpeed;
                }
                else if (backwardSpeed < 0 && forwardSpeed == 0)
                {
                    _throttleController = backwardSpeed;
                }
                else
                {
                    _throttleController = 0.0;
                }
            }

            //Alternative control settings (RC Mode)
            else
            {
                if (state.LeftThumbY.Equals(_previousState.LeftThumbY) &&
                    state.RightThumbX.Equals(_previousState.RightThumbX))
                {
                    return;
                }

                _directionController = Math.Abs((double)state.RightThumbX) < DeadzoneValue
                    ? 0
                    : (double)state.RightThumbX / short.MinValue * -1;
                _directionController = Math.Round(_directionController, 3);

                _throttleController = Math.Abs((double)state.LeftThumbY) < DeadzoneValue
                    ? 0
                    : (double)state.LeftThumbY / short.MinValue * -1;
            }

            string output = Direction.EncodeDirection(DateTime.Now, _throttleController, _directionController);

            LogField.AppendText(output);
            LogField.ScrollToEnd();
            MoveVehicle(_throttleController, _directionController);
            _previousState = state;
        }