zoukankan      html  css  js  c++  java
  • 四、通过Socket实现跟AGV小车通信(仅做Demo演示,跟实际工厂运行无关)

    在通常情况下AGV的开发是使用PLC或者单片机,我们会使用MOXA等串口服务器配置485或者232通信。
    我们会将AGV的MOXA设备配置成服务端。我们按照一定的数据协议从PLC或者单片机获得AGV的信息。

    今天我抛开这些协议,通过工具模拟实现openTCS的Socket通信。
    我这边用winform写了一个简单的Socket服务端工具(超简单那种)
    在这里插入图片描述

    我们的代码是基于第一篇文章的,具体参照 https://blog.csdn.net/jielounlee/article/details/85985715

    那接下来,我们来具体操作一下
    一、在地图上设置AGV的IP地址与端口号
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    每辆小车都要加上IP和Port。我这儿就将其他车辆删掉了,然后保存一下

    二、在第一篇文章的TestCommAdapter中写上具体通信
    我们首先写一个Socket工具类
    在这里插入图片描述

    package org.opentcs.testvehicle;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    /**
     *
     * @author zjw
     */
    public class SocketUtils {
        private String ip;
      private int port;
    
      public SocketUtils(String ip, int port) {
        this.ip = ip;
        this.port = port;
      }
    
      public SocketUtils(String ip, String port) {
        this.ip = ip;
        try {
          this.port = Integer.parseInt(port);
        }
        catch (Exception ex) {
          this.port = 4001;
        }
      }
    
      public String send(String msg) {
        Socket socket = null;
        String ret = "";
        try {
          socket = new Socket(ip, port);
          socket.setSoTimeout(1000);
          OutputStream out = socket.getOutputStream();
          out.write(msg.getBytes());
          InputStream in = socket.getInputStream();
          byte[] buf = new byte[4096];
          int len = in.read(buf);
          ret = new String(buf, 0, len);
          out.close();
          in.close();
          socket.close();
          return ret;
        }
        catch (Exception ex) {
          try {
            socket.close();
          }
          catch (Exception e) {
          }
          return "";
        }
        finally {
          try {
            socket.close();
          }
          catch (Exception e) {
          }
        }
    
      }
    
      public byte[] send(byte[] bytes) {
        Socket socket = null;
        try {
          socket = new Socket(ip, port);
          socket.setSoTimeout(500);
          OutputStream out = socket.getOutputStream();
          out.write(bytes);
          InputStream in = socket.getInputStream();
          byte[] buf = new byte[8];
          int len = in.read(buf);
          out.close();
          in.close();
          socket.close();
          return buf;
        }
        catch (Exception ex) {
          try {
            socket.close();
          }
          catch (Exception e) {
          }
          return null;
        }
        finally {
          try {
            socket.close();
          }
          catch (Exception e) {
          }
        }
      }
    }
    
    

    在TestCommAdapter的构造方法中实例化SocketUtils
    在这里插入图片描述
    在选择AGV适配器的时候会获取AGV的位置,显示在画面上,开启线程
    在这里插入图片描述
    停用的时候将线程也停止了
    在这里插入图片描述
    接下来就是在线程中处理逻辑了
    我这边比较简单,仅仅只是模拟了获取状态以及移动操作。

    具体完整Adapter代码如下:

    package org.opentcs.testvehicle;
    
    import com.google.inject.assistedinject.Assisted;
    import java.util.List;
    import static java.util.Objects.requireNonNull;
    import javax.inject.Inject;
    import org.opentcs.data.model.Vehicle;
    import org.opentcs.data.order.Route.Step;
    import org.opentcs.drivers.vehicle.BasicVehicleCommAdapter;
    import org.opentcs.drivers.vehicle.MovementCommand;
    import org.opentcs.util.CyclicTask;
    import org.opentcs.util.ExplainedBoolean;
    import org.opentcs.data.model.Vehicle.Orientation;
    
    /**
     *
     * @author zjw
     */
    public class TestCommAdapter extends BasicVehicleCommAdapter {
    
      private final SocketUtils socketUtils;
      private TestAdapterComponentsFactory componentsFactory;
      private Vehicle vehicle;
      private boolean initialized;
      private CyclicTask testTask;
    
      @Inject
      public TestCommAdapter(TestAdapterComponentsFactory componentsFactory, @Assisted Vehicle vehicle) {
        super(new TestVehicleModel(vehicle), 2, 1, "CHARGE");
        this.componentsFactory = componentsFactory;
        this.vehicle = vehicle;
        String ip = vehicle.getProperty("IP");
        String port = vehicle.getProperty("Port");
        this.socketUtils = new SocketUtils(ip, port);
      }
    
      @Override
      public void initialize() {
        initialized = true;
        //网络通信,获取当前位置,电量,等信息
        //getProcessModel().setVehicleState(Vehicle.State.IDLE);
        //getProcessModel().setVehiclePosition("Point-0001");
      }
    
      @Override
      public synchronized void enable() {
        if (isEnabled()) {
          return;
        }
        //开启线程(略)
        testTask = new TestTask();
        Thread simThread = new Thread(testTask, getName() + "-Task");
        simThread.start();
        super.enable();
      }
    
      @Override
      public synchronized void disable() {
        if (!isEnabled()) {
          return;
        }
        //线程停止
        testTask.terminate();
        testTask = null;
        super.disable();
      }
    
      @Override
      public void sendCommand(MovementCommand cmd)
          throws IllegalArgumentException {
        requireNonNull(cmd, "cmd");
      }
    
      @Override
      public ExplainedBoolean canProcess(List<String> operations) {
        requireNonNull(operations, "operations");
    
        final boolean canProcess = isEnabled();
        final String reason = canProcess ? "" : "adapter not enabled";
        return new ExplainedBoolean(canProcess, reason);
      }
    
      @Override
      public void processMessage(Object message) {
      }
    
      @Override
      protected void connectVehicle() {
    
      }
    
      @Override
      protected void disconnectVehicle() {
    
      }
    
      @Override
      protected boolean isVehicleConnected() {
        return true;
      }
    
      /**
       * 内部类,用于处理运行步骤
       */
      private class TestTask
          extends CyclicTask {
    
        private TestTask() {
          super(0);
        }
    
        //线程执行
        @Override
        protected void runActualTask() {
          try {
            //获取状态  位置  速度  方向等
            String str = socketUtils.send("{"cmd":"Read","pathFrom":"","pathTo":""}");
            if (str == null) {
              Thread.sleep(1000);
              return;
            }
            if (!str.contains(";")) {
              Thread.sleep(1000);
              return;
            }
            String currentPoint = str.split(";")[0];
            String currentStatus = str.split(";")[1];
            getProcessModel().setVehiclePosition(currentPoint);
            if (currentStatus.equals("free")) {
              getProcessModel().setVehicleState(Vehicle.State.IDLE);
            }
            else if (currentStatus.equals("executing")) {
              getProcessModel().setVehicleState(Vehicle.State.EXECUTING);
            }
            
            
            final MovementCommand curCommand;
            synchronized (TestCommAdapter.this) {
              curCommand = getSentQueue().peek();
            }
            if (curCommand == null) {
             Thread.sleep(1000);
              return;
            }
            final Step curStep = curCommand.getStep();
            simulateMovement(curStep);
            if (!curCommand.isWithoutOperation()) {
              simulateOperation(curCommand.getOperation());
            }
            if (isTerminated()) {
              Thread.sleep(1000);
              return;
            }
            if (getSentQueue().size() <= 1 && getCommandQueue().isEmpty()) {
              getProcessModel().setVehicleState(Vehicle.State.IDLE);
            }
            synchronized (TestCommAdapter.this) {
              MovementCommand sentCmd = getSentQueue().poll();
              if (sentCmd != null && sentCmd.equals(curCommand)) {
                getProcessModel().commandExecuted(curCommand);
                TestCommAdapter.this.notify();
              }
            }
            Thread.sleep(1000);
          }
          catch (Exception ex) {
    
          }
        }
        
         private void simulateMovement(Step step) throws Exception{
          if (step.getPath() == null) {
            return;
          }
          Orientation orientation = step.getVehicleOrientation();
          long pathLength = step.getPath().getLength();
          int maxVelocity;
          switch (orientation) {
            case BACKWARD:
              maxVelocity = step.getPath().getMaxReverseVelocity();
              break;
            default:
              maxVelocity = step.getPath().getMaxVelocity();
              break;
          }
          String pointName = step.getDestinationPoint().getName();
          getProcessModel().setVehicleState(Vehicle.State.EXECUTING);
          String currentPoint = "";
          String currentStatus = "";
          boolean flag = false;
          while (!flag) {
            String str = socketUtils.send("{"cmd":"Path","pathFrom":"" + currentPoint + "","pathTo":"" + pointName + ""}");
            if (str.equals("OK")) {
              flag = true;
            }
            Thread.sleep(1000);
          }
    
          while (!currentPoint.equals(pointName) && !isTerminated()) {
            String str = socketUtils.send("{"cmd":"Read","pathFrom":"","pathTo":""}");
            if (str == null) {
              Thread.sleep(1000);
              continue;
            }
            if (!str.contains(";")) {
              Thread.sleep(1000);
              continue;
            }
            currentPoint = str.split(";")[0];
            currentStatus = str.split(";")[1];
            getProcessModel().setVehiclePosition(currentPoint);
            if (currentStatus.equals("free")) {
              getProcessModel().setVehicleState(Vehicle.State.IDLE);
            }
            else if (currentStatus.equals("executing")) {
              getProcessModel().setVehicleState(Vehicle.State.EXECUTING);
            }
          }
        }
    
        private void simulateOperation(String operation) throws Exception{
          requireNonNull(operation, "operation");
          if (isTerminated()) {
            return;
          }
    //      getProcessModel().setVehicleState(Vehicle.State.EXECUTING);
    //      if (operation.equals(getProcessModel().getLoadOperation())) {
    //        //getProcessModel().setVehicleLoadHandlingDevices(Arrays.asList(new LoadHandlingDevice(LHD_NAME, true)));
    //      }
    //      else if (operation.equals(getProcessModel().getUnloadOperation())) {
    //        //getProcessModel().setVehicleLoadHandlingDevices(Arrays.asList(new LoadHandlingDevice(LHD_NAME, false)));
    //      }
        }
      }
    }
    
    
    
    

    附件:AGV模拟工具
    链接:https://pan.baidu.com/s/1VgupmQKX0sQvIdzQQ63Q8Q
    提取码:n2e8

  • 相关阅读:
    Qt5对付中文真好用
    Qt5下的常见问题————C1083
    macbook pro retina 编程字体推荐
    boost::xml————又一次失败的尝试
    boost::xml——基本操作以及中文乱码解决方案 (续)
    C++单元测试2
    C++单元测试
    生成dll文件的示例
    咋一看你能看明白吗?
    boost::function实践——来自《Beyond the C++ Standard Library ( An Introduction to Boost )》
  • 原文地址:https://www.cnblogs.com/zjwno1/p/13097327.html
Copyright © 2011-2022 走看看