通過rosbridge和roslibjs與 gauss 機械臂通信

let ROSLIB = require('roslib');
import intl from 'react-intl-universal';
import { isLegal } from './message.type'
import { LocalStorage } from './localStorage'
import { notification } from 'antd';

let instance = null;
let reconnect = false;
/**
 *  與 ROS 進行 pub/sub 通訊工具
 *  單例模式
 *
 *  任意位置 用法:
 *      import { Networking } from './network'
 *      let network =  new Networking();
 *       //發佈消息
 *       network.publish(……);
 *
 *       訂閱消息
 *       let sub = network.listen('/add_two_ints','rospy_tutorials/AddTwoInts',(name,data)=>{
 *          console.log(name,data)
 *          sub.unsubscribe();
 *       })
 *
 *
 */
export class Networking {

  constructor() {
    if (!instance) {

      let t = this;
      let localStorage = new LocalStorage();
      let ip = localStorage.getItem("ip");

      instance = new ROSLIB.Ros({
        url: 'ws://' + ip + ':9090'
      });

      instance.on('connection', function () {
        console.log('Connected to websocket server.');
        instance.isConnect = true;
        notification.close('closeMsg1');
        notification.close('closeMsg2');
        reconnect = false;
        notification['success']({
          message: intl.get('SUCCESS'),
          description: intl.get('CONNECTSUCCESS'),
        });
      });

      instance.on('error', function (error) {
        instance.isConnect = false;
        if (reconnect === false) {
          notification['error']({
            key:'closeMsg1',
            message: intl.get('FAIL'),
            description: intl.get('CONNECTFAIL'),
            duration:null,
          });
          reconnect = true;
        }
      });

      instance.on('close', function () {
        instance.isConnect = false;
        // 斷開重連
        instance.connect('ws://' + ip + ':9090');
        if (reconnect === false) {
          notification['error']({
            key:'closeMsg2',
            message: intl.get('FAIL'),
            description: intl.get('CONNECTFAIL'),
            duration:null,
          });
          reconnect = true;
        }
      });
    }

  }

  /**
   * 獲取連接狀態
   * @returns {boolean}
   */
  getIsConnect = () => {
    return instance && instance.isConnect;
  }


  /**
   * 發佈消息
   *  @param topic   消息 topic
   * @param messageType  消息類型 ,例如 /cmd_vel
   * @param message  消息內容
   * @returns {boolean} 發送狀態
   */
  publish = (topic, messageType, message) => {

    if (!isLegal(messageType)) {

      console.error(`publish 不存在 ${messageType} 這樣的類型`);

      return false;
    }


    let type = new ROSLIB.Topic({
      ros: instance,
      name: topic,
      messageType: messageType
    });

    let value = new ROSLIB.Message(message);
    type.publish(value);
    return true;
  }


  /**
   * 訂閱消息
   * @param topic   消息 topic
   * @param messageType 消息類型 ,例如 /cmd_vel
   * @param listener  接收到消息後的回調
   * @returns {sub} 返回 sub,由用戶決定何時取消訂閱  sub.unsubscribe();
   */
  listen = (topic, messageType, listener) => {

    if (!isLegal(messageType)) {
      console.error(`listener 不存在 ${messageType} 這樣的類型`);
      return false;
    }

    let sub = new ROSLIB.Topic({
      ros: instance,
      name: topic,
      messageType: messageType
    });

    sub.subscribe(function (message) {
      // console.log('Received message on ' + sub.name + ': ' + message);
      listener(sub.name, message);
    });
    return sub;
  }

  /**
   * 調用 service
   * @param topic
   * @param messageType
   * @param reqParams   調用參數
   * @param resListener  服務器響應後的回調,傳入響應結果
   */
  callService = (topic, messageType, reqParams, resListener) => {
    let client = new ROSLIB.Service({
      ros: instance,
      name: topic,
      serviceType: messageType
    });

    let request = new ROSLIB.ServiceRequest(reqParams);

    client.callService(request, function (result) {
      console.log('Result for service call on ', client.name, ': ', result);
      resListener(result);
    });
  }

  /**
   *  發佈一個 service    (本項目可能用不到)
   * @param topic
   * @param messageType
   * @param serviceListener
   *
   * serviceListener的用法如下:
   * function (request , response) {
      console.log('Received service request on ' + service.name + ': ' + request.data);
      response['success'] = true;
      response['message'] = 'Set successfully';
      return true;
    }
   * 傳入兩個參數:request 和 response
   * 最後給 response 賦值,並 return ,
   */
  adsService = (topic, messageType, serviceListener) => {
    let service = new ROSLIB.Service({
      ros: instance,
      name: topic,
      serviceType: messageType
    });
    service.advertise(serviceListener);
  }


  /**
   * 調用 action
   * @param topic
   * @param messageType
   * @param goalParams  action goalParams
   * @param listeners actionListener 消息回調,可選 `feedbackListener`, `statusListener`, `resultListener`
   * @return client - ActionClient 對象實例,可用於取消action `client.cancel()`,以及註銷訂閱 `client.dispose()`
   */
  action = (topic, messageType, goalParams, listeners) => {
    if (!listeners) {
      listeners = {};
    }
    let feedbackListener = listeners.feedbackListener;
    let statusListener = listeners.statusListener;
    let resultListener = listeners.resultListener;

    //create actionClient
    let client = new ROSLIB.ActionClient({
      ros: instance,
      serverName: topic,
      actionName: messageType
    });

    // Create a goal.
    let goal = new ROSLIB.Goal({
      actionClient: client,
      goalMessage: goalParams
    });

    //subscribe actionlisteners

    if (feedbackListener && typeof feedbackListener == 'function') {
      goal.on('feedback', function (feedback) {
        feedbackListener(feedback);
      });
    }

    if (statusListener && typeof statusListener == 'function') {
      goal.on('status', function (status) {
        statusListener(status);
      })
    }

    if (resultListener && typeof resultListener == 'function') {
      goal.on('result', function (result) {
        resultListener(result)
      });
    }

    goal.send();

    return client;
  }


}

參考:

  1. https://github.com/TonyRobotics/gauss
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章