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.