typescript - Roslib cu Angular 10


Încerc să folosesc roslibjs în interiorul Angular 10. Am rulat următoarele comenzi pentru a instala roslib și definiția sa de tip

npm i roslib
npm i @types/roslib --save-dev

Fac următoarele în fișierul component.ts, în partea de sus a fișierului

import * as ROSLIB from 'roslib';

ros: any;
ex_publisher:any;

În interiorul constructorului apelez asta și funcționează

    this.ros = new ROSLIB.Ros({
      url : 'ws://localhost:9090'
    });

Dar nu știu cum să mă abonez sau să public într-un subiect

De obicei aș face ceva similar cu asta, dar nu știe nimic despre editor

      this.ex_publisher = new ROSLIB.Topic({
      ros : this.ros,
      name : 'test/testname',
      messageType : 'std_msgs/String'
    });

    this.ros = new ROSLIB.Ros({
      url : 'ws://localhost:9090'
    });

    this.ros.on('connection', function() {
      console.log("connected to ROS");
      console.log("sending test message over ROS");      
      
      this.ex_publisher.data  = 'hello'; // error here doesn't know about data
      this.ex_publisher.publish(); // error here also
      
    });

Care este cea mai bună metodă de a integra scriptul roslib. De asemenea, dacă vreau să împart conexiunea ROS între toate componentele, cum ar trebui să configurez acest lucru în Angular 10?

Mulțumesc

Răspuns #1

Deci aici pui două întrebări (și voi răspunde la ambele).

Prima întrebare: cum se folosește roslibjs? Și a doua întrebare: cum se poate partaja o resursă (cum ar fi conexiunea roslibjs) între mai multe componente într-o aplicație Angular? Permiteți-mi să răspund mai întâi la a doua întrebare:

Cum să partajați un resource precum conexiunea roslibjs între mai multe componente Angular?

Unul dintre conceptele fundamentale în Angular este conceptul de „Serviciu”, care este strâns legat de conceptul de Injecție de Dependență. Așadar, vă rugăm să citiți această secțiune din documentația Angular pentru a înțelege.

Dar pentru a explica ce este un serviciu, imaginează-ți că acesta este o Clasă pe care „Angular” o va oferi tuturor componentelor care o vor solicita.

Deci, pentru mine, cea mai bună soluție este să creez un ROSLibService care va fi oferit tuturor componentelor care trebuie să interacționeze cu ROS. (Voi arăta un exemplu mai târziu).

Cum să folosești ROSLibJS într-o aplicație Angular?

Instalare :

Folosește clasicul

npm -i roslib
npm -D @types/roslib

Apoi adaugă roslib la allowedCommonJsDependencies din fișierul angular.json.

 "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            ....
            "allowedCommonJsDependencies": ["roslib"]
          },

Iată un exemplu de serviciu Angular pe care îl folosesc pentru a partaja ROSLib între componentele mele.

import { Injectable } from '@angular/core';
import * as ROSLIB from 'roslib';
import { Subject, Observable } from 'rxjs';

// Here you define the type (as in your .msg, but in Typescript)
export interface String {
   data: string;
}

@Injectable({
  providedIn: 'root'
})
export class RoslibService {
  private _ros: ROSLIB.Ros;
  private _connected = new Subject<boolean>();
  private _chat = new Subject<String>();

  private _topic?: ROSLIB.Topic;

  constructor() {
    this._connected.next(false);

    this._ros = new ROSLIB.Ros({});
    this._ros.connect('ws://127.0.0.1:9090');
    this._ros.on('connection', (event: any) => {
      this._connected.next(true);
      this.subscribeToTopics();
    })
    // TODO : Manage the events "disconnect" and "error".
  }

  get connected(): Observable<boolean>{
    return this._connected.asObservable();
  }

  get chat(): Observable<String>{
    return this._chat.asObservable();
  }    

  private subscribeToTopics(){
    this._topic = new ROSLIB.Topic({ros: this._ros, name: '/chat', messageType: 'std_msgs/String'});
    this._topic.subscribe((msg: String)=>{ this._chat.next(msg);});        
  }
}

Este foarte important să creați subiectul atunci când conexiunea este stabilită (deoarece abonamentul se face în constructorul subiectului de către roslibjs).

Apoi, poți scrie un component angular simplu care afișează subiectul tău "/chat" astfel:

import { Component } from '@angular/core';
import { String, RoslibService } from './roslib.service';
    
@Component({
    selector: 'app-root',
    template: `
        <h1>Roslib JS tester</h1>
        <p>Connected : {{this.connected}}</p>
        <p>Message : {{this.message}}</p>`,
      styleUrls: [''],
    })
export class AppComponent {
    title = 'ng-roslib';
    
    connected = false;
    message = '';
    
    constructor(private roslibService: RoslibService) {
        this.roslibService.chat.subscribe((msg: String)=>{
          this.message = msg.data;
        });
        this.roslibService.connected.subscribe((connected: boolean)=>{
          this.connected = connected;
        });
    } 
}

Fii atent: Angular 12 folosește Webpack 5, și există o incompatibilitate între roslibjs și webpack5. Vezi această problemă pentru a înțelege.