Exploring the Power of Roslib with Angular 10

Trying to incorporate roslibjs within an Angular 10 project has been a bit challenging for me. After installing roslib and its type definition using the commands below:

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

In my component.ts file, I have imported ROSLIB at the top of the file as follows:

import * as ROSLIB from 'roslib';

ros: any;
ex_publisher:any;

I successfully initialize it within the constructor like this:

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

However, when it comes to subscribing or publishing to a topic, I am encountering some difficulties.

I attempted something similar to this snippet but faced issues with the 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
      
    });

I would appreciate guidance on how to properly incorporate the roslib script and set up a shared ros connection among all components in Angular 10.

Thank you.

Answer №1

When posing two inquiries, I am prepared to provide answers for both.

The initial query is: how does one utilize roslibjs? The subsequent question concerns sharing a resource, such as the roslibjs connection, across multiple components within an Angular application. Allow me to address the latter question first:

How can a resource like the roslibjs connection be shared between various Angular components?

An essential concept in Angular revolves around the idea of a "Service," closely linked with Dependency Injection. Refer to this section in the Angular documentation for further insights.

To elaborate on what a service entails, envision it as a Class that Angular provides to all components necessitating its functionalities.

In my view, the optimal approach involves creating a ROSLibService assigned to all components requiring interaction with ROS. (A demonstration will follow later).

How do you integrate ROSLibJS into an Angular application?

Installation steps:

Begin by executing the standard command:

npm -i roslib
npm -D @types/roslib

Subsequently, include roslib in the allowedCommonJsDependencies list within the angular.json file.

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

Below is a sample Angular service that aids in distributing ROSLib among various components.

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

// Define the type akin to your .msg file 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();
    })
    // Handle events like "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);});        
  }
}

Note the significance of establishing the topic when the connection is initialized since subscription occurs during the topic's construction via roslibjs.

Following that, you can devise a simple Angular component displaying your "/chat" topic as illustrated below:

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

Please exercise caution: Angular 12 employs Webpack 5, resulting in an incompatibility issue between roslibjs and webpack5. Refer to this matter for better comprehension.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular fails to retrieve the data from an Object

I have both backend and frontend applications. When I attempt to retrieve information about the 'Probe' object, I can see its fields: https://i.stack.imgur.com/TJQqI.png However, when I try to access this information in Angular, I receive an und ...

What is preventing me from accessing a JavaScript object property when using a reactive statement in Svelte 3?

Recently, while working on a project with Svelte 3, I encountered this interesting piece of code: REPL: <script lang="ts"> const players = { men: { john: "high", bob: "low", }, }; // const pl ...

Security concern found in React application during npm installation

As I delve into the Academind React course, I followed the instructions to download and unzip the starting setup zip file. I opened it with vscode and ran "npm install" in the terminal. However, I encountered an issue with vulnerabilities. I attempted to ...

My private module is being overlooked by npm and is consistently returning a 404 error when trying to access the

Has anyone encountered this issue before? I have a private module that I want to add to my app. I've referenced it as a tarball on Gemfury, and although it works fine locally, when I try to run "npm install" on my Joyent box, I get the error below. I ...

Iterate through an array containing objects that may have optional properties, ensuring to loop through the entire

I need help iterating through an array of objects with a specific interface structure: export interface Incident { ID: string; userName1?: string; userName2?: string; userPhoneNumber?: string; crashSeverity: number; crashTime: number; } Here ...

Encountered an ENOENT error message when attempting to configure Nativescript 8 installation

Currently, I am in the process of creating a fresh NS8 project. However, my computer also has an NS6.5 project stored in a separate folder. Whenever I attempt to execute npm install -g nativescript in this new directory, it results in the following error: ...

I'm curious to know the location where gulp-front-matter is storing my front matter information

I'm currently experimenting with the npm package in order to remove certain front matter from a markdown file and then retrieve the stripped markdown content. This leads me to my inquiry regarding the code snippet provided by the module documentation: ...

Search for specific item within an array of objects

Working on an Angular project, I am attempting to remove an object from an array. To achieve this, I need to filter the array and then update the storage (specifically, capacitor/storage) with the modified array. Here is my function: deleteArticle(id: str ...

What type of grant should I choose for this flow?

After developing an application with a springboot backend and Angular frontend, I am now looking to enhance security using oauth2.0 (with Okta as the authorization server). However, I am unsure about the correct flow to follow for implementing this. Should ...

Do you find this unattractive? What are some ways to improve this unsightly JavaScript statement?

This code seems messy, how can I better structure this switch statement? function renderDataTypeIcon(dataType: string) { let iconName; switch (dataType) { case "STRING": //TODO - ENUM iconName = "text"; break; ...

How to Generate a JPG File from a Leaflet Map in Angular 4 using Typescript

I am developing a custom application using Angular4 that involves integrating leaflet maps. One of the requirements is to export the current view of a map as a JPG image, capturing only the map with markers and polylines - similar to taking a screenshot. ...

Execute npm commands with Python subprocess

I'm currently working on automating the generation of documentation using YUIDOC. However, I'm facing a challenge due to my server-side framework heavily relying on Python. I am attempting to automate the process within a Python script. While I h ...

Angluar's pipe filter failing to provide unique outcomes

My application utilizes the same service data on both a Parent and Child page. While attempting to filter the data for unique values based on a specific column using ngx-filter-pipe module, I am encountering an issue where all values are still being retur ...

Encountering difficulties redirecting to the homepage following Facebook login

After successfully logging in with Facebook, I am having trouble redirecting to my home page. The token is stored in localStorage, but it remains on the login page without redirecting. loginWithFB() { this.facebook.login(['public_profile', &a ...

Retrieve the value of [routerLinkActive] in the component's class

Recently, I've been working on a tab component called TabComponent and it includes the following HTML template: <a [routerLink]='link' [routerLinkActive]="[is-active]">link label</a> <button>Close tab</button> The c ...

Vercel is encountering difficulty locating a module or type declaration during the construction of a Next.js application

Currently, I'm facing an issue while trying to deploy a Next.js app to Vercel. The package react-swipeable appears to have its own type declarations but the build fails with the following error: Running "npm run build" ... > next build ... Failed t ...

"Unsuccessful API request leads to empty ngFor loop due to ngIf condition not being

I have been struggling to display the fetched data in my Angular 6 project. I have tried using ngIf and ngFor but nothing seems to work. My goal is to show data from movies on the HTML page, but for some reason, the data appears to be empty. Despite tryin ...

Is there a way to make Firebase Cloud Functions utilize ESLint?

Is there a specific command to activate ESLint for my cloud functions? Just to provide some context, I executed firebase init and completed the setup process, but it ended up using ESLint instead of TSLint which was unexpected. After that, I ran firebase ...

Angular component nesting involves placing one component within another component in

When a component is nested inside another, what is that called? For example: <agm-map [latitude]="lat" [longitude]="lng"> <agm-marker [latitude]="lat" [longitude]="lng"></agm-marker> </agm-map> Can you explain how this nesting w ...

How to retrieve the type of a computed keyof T as a generic type within TypeScript

I am working with two different interfaces: interface PersonRequirements{ user:string, password:string, id:number } export interface Requirement<R> { name: keyof R & string, save: () => any,/* I want this return type to be ...