Sequence

Sequence Control

제조업에서 제어파트 및 비전 파트에서는 Sequence방식의 제어를 빈번하게 사용한다. switch-case문으로 구현 해왔고, 그렇게 배웠다. 사용하는 중에 명확한 코드 시인성이지만, 유지보수 측면에서 아쉬웠다. 수정 할 부분을 찾아야 하는 경우나, 모든 스탭에 반복적인 로직을 추가해야 하는 경우에 번거로웠다.
편리해진 AI기능을 사용하여 질의하여 더 나아 보이는 구조를 테스트 해보았다.

기존 구조.

기존 구조는 C Style의 Enum과 Switch-Case를 사용한 구조이다. 장점은 코드 시인성이 좋고, 직관적이다. 스탭을 추가하거나 삭제하는 경우에 직관적으로 코드를 수정 할 수 있다. 단점은 유지보수 측면에서 아쉬웠다. 수정 할 부분을 찾아야 하는 경우나, 모든 스탭에 반복적인 로직을 추가해야 하는 경우에 번거로웠다.

     
  enum EN_STEP
  {
    EN_STEP_IDLE = 0,
    EN_STEP_MOVE_MOTOR,
    EN_STEP_MOVE_MOTOR_CHECK,
    EN_STEP_MOVE_CYLINDER,
    EN_STEP_MOVE_CYLINDER_CHECK,
    EN_STEP_DONE
  }
  void Update()
  {
    switch(step)
    {
       case EN_STEP::EN_STEP_IDLE:
       break;
       case EN_STEP::EN_STEP_MOVE_MOTOR:
       // move motor
       step++;
       break;
       case EN_STEP::EN_STEP_MOVE_MOTOR_CHECK:
       // if move done
       {
        step++;
       }
       break;
       case EN_STEP::EN_STEP_MOVE_CYLINDER:
       // move cylinder
       step++;
       break;
       case EN_STEP::EN_STEP_MOVE_CYLINDER_CHECK:
       // if cylinder move done
       {
        step++;
       }
       break;
       case EN_STEP::EN_STEP_DONE:
       // step done.
       break;
    }
  }
  

테스트 구조.

테스트 구조는 C++의 함수 포인터를 사용한 구조이다. 스탭 함수를 별도로 구현하여, 함수 포인터로 등록하여 반환 값에 따라 순차적으로 함수 포인터를 수행한다. GetStepName()을 통해 현재 스탭의 이름을 반환 받을 수 있다. Time-Out과 같은 로직은 Update함수에서 처리 할 수 있다.

     
  using StepFunc = std::function<bool(void*)>;
  class Sequence
  {
    private:
    std::vector<std::tuple<int, StepFunc, std::string>> steps;
    int currentStep;
    public:
    Sequence()
    {
      currentStep = 0;
    }
    ~Sequence()
    {
      steps.clear();
    }
    void SetStep(int step)
    {
      currentStep = step;
    }
    void AddStep(StepFunc stepFunc, std::string stepName)
    {
      steps.push_back(std::make_tuple(steps.size(), stepFunc, stepName));
    }
    std::string GetStepName()
    {
      return std::get<2>(steps[currentStep]);
    }
    void Update()
    {
      if (currentStep < steps.size())
      {
        if (std::get<1>(steps[currentStep])())
        {
          currentStep++;
        }
      }
    }
  };