Запуск фрагмента кода в течение определенного времени на С#?

Я работаю над роботом, способным обнаруживать движение с помощью веб-камеры. Я делаю это на С#

Робот движется слишком быстро, поэтому я хочу включать/выключать его через короткие промежутки времени, чтобы уменьшить его скорость.

Например, он запустит двигатель, затем подождет 0,5 секунды и выключит его, этот цикл повторяется каждые 2 секунды. Таким образом, его скорость не будет слишком быстрой. Я хотел бы включить это в одну функцию с именем Move().

Я просто не знаю, как это сделать, особенно потому, что мой код обнаружения движения работает примерно 20 раз в секунду. В зависимости от положения препятствия мне может потребоваться отключить функцию Move() и активировать другие функции, позволяющие роботу двигаться в других направлениях.

Любые идеи/предложения о том, с чего я должен начать?

Большое спасибо!


person Hazem    schedule 10.05.2010    source источник


Ответы (8)


Прежде всего, нам нужно установить, как работает ваша программа.

Выполняет ли он одну команду, ждет, затем выполняет следующую команду? Или он выполняет команды одновременно? (например, двигаться и делать что-то еще)

Я предполагаю, что вы захотите, чтобы он выполнял команды последовательно, а не какие-то сложные потоки, которые ваша двигательная система может не поддерживать.

Чтобы заставить вашего робота двигаться медленно, я бы предложил создать метод Move(), который принимает параметр, количество времени, которое вы хотите, чтобы он двигался, например:

public void Move(int numberOfSeconds)
{
   while (numberOfSeconds > 0)
   {

      myRobot.MotorOn();
      Thread.Sleep(2000);
      myRobot.MotorOff();
      Thread.Sleep(500);

      numberOfSeconds -= 2;
   }
}

Это не точно, но это один из способов сделать это.

Если вы затем вызовете, например, Move(10), ваш робот будет двигаться в течение 10 секунд и останавливаться каждые 2 секунды на полсекунды.

Что касается ваших вопросов по ходу программы, вы можете думать об этом как о списке инструкций:

ДВИГАТЬСЯ ВПЕРЕД СТОП ПРОВЕРИТЬ ОБЪЕКТ ПОВЕРНУТЬ, ЧТОБЫ НАВЕЛИЧИТЬСЯ НА ОБЪЕКТ ДВИГАТЬСЯ ВПЕРЕД СТОП

и т. д.

Таким образом, в вашем основном цикле управления программой, предполагая, что вызовы синхронны (т.е. ваша программа останавливается во время выполнения команды, как в приведенном выше методе Move), вы можете просто иметь набор операторов IF (или переключатель)

public void Main()
{

   // What calculations should the robot do?
   If (someCalculations == someValue)
   {
     // Rotate the robot to face the object
     robot.RotateRight(10);
   }
   else if (someOtherCalculation == someValue)
   {
     // We are on course, so move forward
     Move(10);
   }
}

Это может помочь вам начать.

Однако, если ваш робот асинхронный, то есть код продолжает работать, пока робот что-то делает (например, вы постоянно получаете обратную связь от датчиков движения), вам придется структурировать свою программу по-другому. Метод Move() может по-прежнему работать, но поток вашей программы должен немного отличаться. Вы можете использовать переменную для отслеживания состояния:

public enum RobotStates
{
  Searching,
  Waiting,
  Hunting,
  Busy,
}

Затем в вашем основном цикле вы можете проверить состояние:

if (myRobotState != RobotStates.Busy)
{
  // Do something
}

Не забудьте изменить состояние, когда ваши действия завершены.

Вполне возможно, что вам придется использовать многопоточность для асинхронного решения, поэтому ваш метод, который получает обратную связь от вашего датчика, не застревает в ожидании движения робота, а может продолжать опрос. Тем не менее, потоки выходят за рамки этого ответа, но существует множество ресурсов.

person NibblyPig    schedule 10.05.2010

Вы столкнулись с очень распространенной проблемой: как управлять процессом, когда ваш привод имеет только состояния ВКЛ и ВЫКЛ. Предложенное вами решение является распространенным решением, которое заключается в установке «рабочего цикла» путем включения / выключения двигателя. В большинстве случаев вы можете купить контроллеры двигателей, которые сделают это за вас, так что вам не придется беспокоиться о деталях. Как правило, вы хотите, чтобы пульсация была более высокой частоты, чтобы в движении было менее заметное «заикание».

Если это образовательный проект, вас может заинтересовать теория контроллеров двигателей. Вы также можете прочитать о теории управления (в частности, о ПИД-регулировании). используйте другую обратную связь (у вас есть способ определить скорость?), чтобы автоматически управлять двигателем для поддержания желаемой скорости.

person Dan Bryant    schedule 10.05.2010

Thread.Sleep() может быть не тем, что вам нужно, потому что, если ваше оборудование способно, вы хотите, чтобы ваши датчики работали во время движения и т. д. Первое решение, которое приходит мне на ум, — это использовать таймер. Таким образом, вы можете продолжать обрабатывать и управлять своим движением, когда это необходимо.

(не проверял этот код, но идея понятна)

System.Timers.Timer Timer = new Timer();
bool Moving;

void init()
{
  Timer.AutoReset = false;
  Timer.Elapsed += OnMoveTimerEvent;
  Moving = false;
}

void MainLoop()
{
   //stuff

   if(should move)
   {
     timer.start();
   }

   if(should stop moving)
   {
     timer.stop();
   }
}


void OnMoveTimerEvent(object source, ElapsedEventArgs e)        
{
  if (!Moving)
  {
    //start motor
    Timer.Interval = 500;
    Moving = true;
    Timer.Start();
  }
  else
  {
    //stop motor
    Moving = true;
    Timer.Interval = 2000;
    Timer.Start();
  }
}
person Josh Sterling    schedule 10.05.2010
comment
Если программа имеет более одного потока, Thread.Sleep приостановит только этот конкретный поток, а другие потоки могут свободно обрабатывать ввод или что-то еще. - person Hank; 10.05.2010

Я бы посоветовал вам заглянуть в Microsoft Robotics Studio? Никогда не использовал ее. , но они могут на самом деле решить эту проблему. И, возможно, другие, с которыми вы еще не сталкивались.

Другой вариант — написать приложение с использованием механизмов синхронизации XNA. Только вместо рендеринга на экран вы будете рендерить как бы своего робота.

person Community    schedule 10.05.2010
comment
Я на 90% уверен, что Robotics Studio действительно решит эту проблему. Синхронизация и параллельная обработка — вот что такое библиотека. +1 базиллионы. - person Randolpho; 10.05.2010

Вы можете попробовать использовать -

Thread.Sleep(500);

Этот фрагмент кода переводит текущий запущенный поток в спящий режим на 500 миллисекунд.

person Kirtan    schedule 10.05.2010

Одним из способов приостановки работы является добавление сна между звонками. Вы можете поспать между звонками. Ставить сон так: System.Threading.Thread.Sleep(5000); 5000 - это 5000 миллисекунд.

person Kangkan    schedule 10.05.2010

Похоже, вы хотите, чтобы основной поток периодически выполнял функции. Если на вашем роботе установлена ​​.NET-Framework, вы можете использовать библиотеку Threading.

while(condition)
{
    //Wait a number ms (2000 ms = 2 secons)
    Thread.Sleep(2000); 
    //Do something here, e.g. move

    Thread.Sleep(500);
    //...
}

Но у вас очень сложный вопрос. Не могли бы вы указать, какая операционная система и/или среда (библиотеки, фреймворки и т. д.) установлены на вашем роботе?

person Simon    schedule 10.05.2010

Что касается обнаружения движения и обнаружения препятствий, ваш код должен использовать сложную многопоточность. Для вашей проблемы со скоростью двигателя вы пытались выполнить вызов Move() в отдельном потоке.

и в цикле for вы можете использовать Thread.Sleep(2*1000) после каждого вызова MotorOff().

С уважением.

person Shoaib Shaikh    schedule 10.05.2010