Выполнить кусок кода в течение определенного времени в C #? - PullRequest
6 голосов
/ 10 мая 2010

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

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

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

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

Какие-нибудь идеи / предложения о том, с чего мне начать?

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

Ответы [ 8 ]

5 голосов
/ 10 мая 2010

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

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

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

Чтобы заставить вашего робота двигаться медленно, я бы предложил создать метод 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
}

Не забудьте изменить состояние после завершения ваших действий.

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

3 голосов
/ 10 мая 2010

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

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

2 голосов
/ 10 мая 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();
  }
}
1 голос
/ 10 мая 2010

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

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

0 голосов
/ 10 мая 2010

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

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

Привет.

0 голосов
/ 10 мая 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);
    //...
}

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

0 голосов
/ 10 мая 2010

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

0 голосов
/ 10 мая 2010

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

Thread.Sleep(500);

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

...