Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslib with Angular 10

I am trying to use roslibjs inside angular 10. I run the following commands to install roslib and it's type definition

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

I do the following in the component.ts file at the top of the file

import * as ROSLIB from 'roslib';

ros: any;
ex_publisher:any;

Inside the constructor I call this and it works

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

But I don't know how to subscribe or publish to a topic

Normally I would do something similar to this but it doesn't know anything about publisher

      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
      
    });

What is the best way of bringing in the roslib script. Also if I want to share the ros connection among all components how should I set this up in Angular 10?

Thanks

like image 289
JTR Avatar asked Dec 21 '25 00:12

JTR


1 Answers

So here you ask two questions (and I will answer boths).

First question : how to use roslibjs ? And second question how to share a ressource (like the roslibjs connection) to multiple compoment in an angular application ? Let me answer to the the second question first :

How to share a resource lkike the roslibjs connection between multiple Angular components ?

One of the fundamentals concept in angular is the concept of "Service" which is strongly coupled to the concept of Dependency Injection. So please read this section of the angular doc to understand.

But to explain what is a service, imagine that this is a Class that "Angular" will give to all componenents that will require them.

So for me the best solution is to create a ROSLibService that will be given to all components that need to interact with ROS. (I will show a sample later).

How to use ROSLibJS in an Angular application ?

Installation :

Use the classic

npm -i roslib
npm -D @types/roslib

Then add roslib to the allowedCommonJsDependencies of the angular.json file.

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

Here is an example of an angular service that I use to share ROSLib between my components.

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);});        
  }
}

It is very important to create your topic when the connection is established (because subscription is perfomed in the topic's constructor by the roslibjs).

Then, you can write a simple angular component that display your "/chat" topic like this :

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;
        });
    } 
}

Be carefull : Angular 12 use Webpack 5, and there is an incompatibilty between roslibjs and webpack5. See this issue to understand.

like image 94
Adrien BARRAL Avatar answered Dec 23 '25 15:12

Adrien BARRAL