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
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 :
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With