diff --git a/electron_demo/car/README.md b/electron_demo/car/README.md new file mode 100644 index 00000000..e198338b --- /dev/null +++ b/electron_demo/car/README.md @@ -0,0 +1,284 @@ +# ROS2 Car Control Demo with Electron and rclnodejs + +This demo showcases how to use **rclnodejs** with **Electron** to create an interactive car control application. The demo features a virtual joystick that publishes ROS2 velocity commands and a car visualization that responds to those commands in real-time. + +## ๐Ÿš— Features + +### Joystick Control Panel + +- **Directional Controls**: Up/Down/Left/Right buttons for car movement +- **Stop Button**: Emergency stop functionality +- **Keyboard Support**: WASD and arrow keys for control +- **Real-time Status**: Display current command and velocity values + +### Car Visualization + +- **Real-time Movement**: Car moves and rotates based on received commands +- **Position Tracking**: Shows current position (North/South/East/West/Center) +- **Visual Feedback**: Color-coded movement indicators +- **Command Counter**: Tracks total number of commands received + +### ROS2 Integration + +- **Topic**: `cmd_vel` (geometry_msgs/Twist) +- **Publisher**: Sends velocity commands +- **Subscriber**: Receives and displays velocity commands +- **Node Name**: `car_control_node` + +## ๐Ÿ”ง Prerequisites + +Before running this demo, ensure you have: + +1. **ROS2 installed** (Humble, Jazzy, Kilted, or Rolling) +2. **Node.js** (version 16 or higher) +3. **rclnodejs built** and working + +### ROS2 Setup + +```bash +# Source your ROS2 installation +source /opt/ros//setup.bash + +# Verify ROS2 is working +ros2 topic list +``` + +### Build rclnodejs + +From the main rclnodejs directory: + +```bash +npm install +npm run build +``` + +## ๐Ÿš€ Installation & Running + +1. **Navigate to the demo directory:** + + ```bash + cd electron_car_demo + ``` + +2. **Install dependencies:** + + ```bash + npm install + ``` + +3. **Rebuild native modules for Electron:** + + ```bash + npm run rebuild + ``` + +4. **Start the demo:** + ```bash + # Make sure ROS2 is sourced first + source /opt/ros//setup.bash + npm start + ``` + +![demo screenshot](./car-control-electron.gif) + +## ๐ŸŽฎ How to Use + +### Control Methods + +#### Mouse Controls + +- Click the directional buttons (โ†‘โ†“โ†โ†’) on the joystick +- Click the red **STOP** button to halt movement + +#### Keyboard Controls + +- **W** or **โ†‘**: Move forward +- **S** or **โ†“**: Move backward +- **A** or **โ†**: Turn left +- **D** or **โ†’**: Turn right +- **Space** or **Esc**: Stop + +### Understanding the Interface + +#### Left Panel - Joystick Control + +- **Command**: Shows the current command being sent +- **Linear X**: Forward/backward velocity (m/s) +- **Angular Z**: Rotation velocity (rad/s) +- **Topic**: ROS2 topic name (`cmd_vel`) + +#### Right Panel - Car Visualization + +- **Received Commands**: Total count of commands received +- **Last Command**: Most recent command processed +- **Car Position**: Current position in the visualization area + +## ๐Ÿ” Technical Details + +### ROS2 Message Format + +The demo uses `geometry_msgs/Twist` messages with the following structure: + +```javascript +{ + linear: { + x: 1.0, // Forward/backward velocity (m/s) + y: 0.0, // Left/right velocity (typically 0 for cars) + z: 0.0 // Up/down velocity (typically 0 for ground vehicles) + }, + angular: { + x: 0.0, // Roll rate (typically 0 for cars) + y: 0.0, // Pitch rate (typically 0 for cars) + z: 1.0 // Yaw rate (turning left/right in rad/s) + } +} +``` + +### Command Mapping + +| Command | Linear X | Angular Z | Description | +| -------- | -------- | --------- | ---------------------- | +| Forward | +1.0 | 0.0 | Move forward at 1 m/s | +| Backward | -1.0 | 0.0 | Move backward at 1 m/s | +| Left | 0.0 | +1.0 | Turn left at 1 rad/s | +| Right | 0.0 | -1.0 | Turn right at 1 rad/s | +| Stop | 0.0 | 0.0 | Stop all movement | + +### Architecture + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Renderer โ”‚ โ”‚ Main Process โ”‚ โ”‚ ROS2 Network โ”‚ +โ”‚ (UI/Browser) โ”‚ โ”‚ (Node.js) โ”‚ โ”‚ โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ โ€ข Joystick UI โ”‚โ”€โ”€โ”€โ–ถโ”‚ โ€ข rclnodejs Node โ”‚โ”€โ”€โ”€โ–ถโ”‚ โ€ข cmd_vel Topic โ”‚ +โ”‚ โ€ข Car Display โ”‚โ—€โ”€โ”€โ”€โ”‚ โ€ข Publisher โ”‚ โ”‚ โ€ข Other Nodes โ”‚ +โ”‚ โ€ข Status Panel โ”‚ โ”‚ โ€ข Subscriber โ”‚โ—€โ”€โ”€โ”€โ”‚ โ€ข Robot/Sim โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +## ๐Ÿงช Testing with ROS2 Tools + +You can test the demo using standard ROS2 command-line tools: + +### Listen to Published Commands + +```bash +# In a new terminal (with ROS2 sourced) +ros2 topic echo /cmd_vel +``` + +### Send Commands from Command Line + +```bash +# Send a forward command +ros2 topic pub /cmd_vel geometry_msgs/Twist "linear: {x: 1.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}" + +# Send a turn left command +ros2 topic pub /cmd_vel geometry_msgs/Twist "linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.0}" + +# Stop command +ros2 topic pub /cmd_vel geometry_msgs/Twist "linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}" +``` + +### Check Active Topics + +```bash +ros2 topic list +ros2 topic info /cmd_vel +ros2 topic hz /cmd_vel +``` + +## ๐Ÿค– Integration with Real Robots + +This demo can be easily connected to real robots or simulators: + +### TurtleBot3 (Example) + +```bash +# Launch TurtleBot3 simulation +ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py + +# The demo will automatically control the robot via cmd_vel topic +``` + +### Custom Robot + +Ensure your robot subscribes to the `/cmd_vel` topic with `geometry_msgs/Twist` messages. + +## ๐Ÿ› ๏ธ Customization + +### Modify Velocity Values + +Edit the `speed` and `turnSpeed` constants in `main.js`: + +```javascript +const speed = 1.0; // Linear velocity (m/s) +const turnSpeed = 1.0; // Angular velocity (rad/s) +``` + +### Change Topic Name + +Modify the topic name in `main.js`: + +```javascript +// Change 'cmd_vel' to your desired topic name +carControlPublisher = carControlNode.createPublisher( + 'geometry_msgs/msg/Twist', + 'your_topic_name' +); +``` + +### Add More Commands + +Extend the joystick commands by modifying the switch statement in `main.js` and adding corresponding UI elements. + +## ๐Ÿ› Troubleshooting + +### Common Issues + +1. **"Failed to initialize ROS2" Error** + + - Ensure ROS2 is properly sourced before running npm start + - Check that rclnodejs is built correctly + +2. **Native Module Rebuild Issues** + + ```bash + npm run rebuild + # or manually: + ./node_modules/.bin/electron-rebuild + ``` + +3. **Topic Not Appearing** + + - Verify ROS2 daemon is running: `ros2 daemon status` + - Check topic list: `ros2 topic list` + +4. **Car Not Moving in UI** + - Check browser console for JavaScript errors + - Verify IPC communication between main and renderer processes + +### Debug Mode + +Add debug logging by modifying `main.js`: + +```javascript +// Enable debug logging +console.log('Publishing command:', command, twist); +``` + +## ๐Ÿ“š Learning Resources + +- [rclnodejs Documentation](https://github.com/RobotWebTools/rclnodejs) +- [ROS2 Tutorials](https://docs.ros.org/en/rolling/Tutorials.html) +- [Electron Documentation](https://www.electronjs.org/docs) +- [geometry_msgs/Twist Documentation](https://docs.ros.org/en/rolling/p/geometry_msgs/interfaces/msg/Twist.html) + +## ๐Ÿ“„ License + +This demo is licensed under the Apache License 2.0, same as the main rclnodejs project. + +## ๐Ÿค Contributing + +Feel free to submit issues and enhancement requests! This demo serves as both a functional example and a starting point for more complex ROS2 Electron applications. diff --git a/electron_demo/car/car-control-electron.gif b/electron_demo/car/car-control-electron.gif new file mode 100644 index 00000000..8e0d1bb8 Binary files /dev/null and b/electron_demo/car/car-control-electron.gif differ diff --git a/electron_demo/car/index.html b/electron_demo/car/index.html new file mode 100644 index 00000000..b80bbec3 --- /dev/null +++ b/electron_demo/car/index.html @@ -0,0 +1,292 @@ + + + + + + + ROS2 Car Control Demo + + + + +
+

๐Ÿš— ROS2 Car Control Demo with Joystick

+ +
+ +
+
๐Ÿ•น๏ธ Joystick Control
+
+ + + + + +
+ +
+
+ Command: + None +
+
+ Linear X: + 0.0 m/s +
+
+ Angular Z: + 0.0 rad/s +
+
+ Topic: + cmd_vel +
+
+
+ + +
+
๐Ÿš— Car Visualization
+
+
+
+ +
+
+ Received Commands: + 0 +
+
+ Last Command: + None +
+
+ Car Position: + Center +
+
+
+
+ +
+

๐Ÿ“‹ Instructions

+
    +
  • โ†‘ Forward: Move the car forward (positive linear.x)
  • +
  • โ†“ Backward: Move the car backward (negative linear.x)
  • +
  • โ† Left: Turn the car left (positive angular.z)
  • +
  • โ†’ Right: Turn the car right (negative angular.z)
  • +
  • STOP: Stop all movement
  • +
  • ROS2 Topic: Commands are published to cmd_vel using geometry_msgs/Twist
  • +
  • Demo: The car visualization responds to the same ROS2 messages that are being published
  • +
+
+
+ + + + + diff --git a/electron_demo/car/main.js b/electron_demo/car/main.js new file mode 100644 index 00000000..fbe76708 --- /dev/null +++ b/electron_demo/car/main.js @@ -0,0 +1,142 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const { app, BrowserWindow, ipcMain } = require('electron'); +const rclnodejs = require('rclnodejs'); + +let mainWindow; +let carControlNode; +let carControlPublisher; + +function createWindow() { + // Create the browser window. + mainWindow = new BrowserWindow({ + width: 1000, + height: 800, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + }, + title: 'ROS2 Car Control Demo', + }); + + mainWindow.loadFile('index.html'); +} + +// Initialize ROS2 node for car control +async function initializeROS() { + try { + await rclnodejs.init(); + + // Create node for car control + carControlNode = rclnodejs.createNode('car_control_node'); + + // Create publisher for car velocity commands (using geometry_msgs/Twist) + carControlPublisher = carControlNode.createPublisher( + 'geometry_msgs/msg/Twist', + 'cmd_vel' + ); + + // Create subscription to listen to our own commands (for demo purposes) + carControlNode.createSubscription( + 'geometry_msgs/msg/Twist', + 'cmd_vel', + (msg) => { + // Send velocity data to renderer process + if (mainWindow) { + mainWindow.webContents.send('velocity-received', { + linear: { + x: msg.linear.x, + y: msg.linear.y, + z: msg.linear.z, + }, + angular: { + x: msg.angular.x, + y: msg.angular.y, + z: msg.angular.z, + }, + }); + } + } + ); + + rclnodejs.spin(carControlNode); + console.log('ROS2 car control node initialized successfully'); + } catch (error) { + console.error('Failed to initialize ROS2:', error); + } +} + +// Handle joystick commands from renderer process +ipcMain.on('joystick-command', (event, command) => { + if (carControlPublisher) { + // Create Twist message based on joystick command + const twist = { + linear: { x: 0.0, y: 0.0, z: 0.0 }, + angular: { x: 0.0, y: 0.0, z: 0.0 }, + }; + + // Map joystick commands to robot movement + const speed = 1.0; // m/s + const turnSpeed = 1.0; // rad/s + + switch (command) { + case 'forward': + twist.linear.x = speed; + break; + case 'backward': + twist.linear.x = -speed; + break; + case 'left': + twist.angular.z = turnSpeed; + break; + case 'right': + twist.angular.z = -turnSpeed; + break; + case 'stop': + // All values remain 0.0 + break; + } + + // Publish the command + carControlPublisher.publish(twist); + console.log(`Published command: ${command}`, twist); + } +}); + +// This method will be called when Electron has finished +// initialization and is ready to create browser windows. +app.whenReady().then(async () => { + createWindow(); + await initializeROS(); + + app.on('activate', function () { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); + +// Quit when all windows are closed, except on macOS. +app.on('window-all-closed', function () { + if (process.platform !== 'darwin') { + if (carControlNode) { + rclnodejs.shutdown(); + } + app.quit(); + } +}); + +// Handle app termination +app.on('before-quit', () => { + if (carControlNode) { + rclnodejs.shutdown(); + } +}); diff --git a/electron_demo/car/package.json b/electron_demo/car/package.json new file mode 100644 index 00000000..94bdb278 --- /dev/null +++ b/electron_demo/car/package.json @@ -0,0 +1,26 @@ +{ + "name": "rclnodejs-electron-car-demo", + "version": "1.0.0", + "description": "An Electron application demonstrating car control with joystick using rclnodejs", + "main": "main.js", + "scripts": { + "start": "electron .", + "rebuild": "electron-rebuild" + }, + "keywords": [ + "Electron", + "rclnodejs", + "demo", + "car", + "joystick", + "control" + ], + "license": "Apache-2.0", + "dependencies": { + "rclnodejs": "^1.0.0" + }, + "devDependencies": { + "@electron/rebuild": "^3.6.0", + "electron": "^31.0.0" + } +} diff --git a/electron_demo/car/renderer.js b/electron_demo/car/renderer.js new file mode 100644 index 00000000..2ddcbcfe --- /dev/null +++ b/electron_demo/car/renderer.js @@ -0,0 +1,275 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const { ipcRenderer } = require('electron'); + +// DOM elements +let currentCommandEl, linearXEl, angularZEl, topicNameEl; +let commandCountEl, lastReceivedCommandEl, carPositionEl; +let carEl; + +// State variables +let commandCount = 0; +let carPosition = { x: 150, y: 150 }; // Center of 300x300 area +let carRotation = 0; + +// Initialize when DOM is loaded +document.addEventListener('DOMContentLoaded', function () { + initializeElements(); + setupEventListeners(); + setupROSListeners(); +}); + +function initializeElements() { + // Control panel elements + currentCommandEl = document.getElementById('current-command'); + linearXEl = document.getElementById('linear-x'); + angularZEl = document.getElementById('angular-z'); + topicNameEl = document.getElementById('topic-name'); + + // Car display elements + commandCountEl = document.getElementById('command-count'); + lastReceivedCommandEl = document.getElementById('last-received-command'); + carPositionEl = document.getElementById('car-position'); + carEl = document.getElementById('car'); +} + +function setupEventListeners() { + // Joystick button event listeners + document + .getElementById('btn-forward') + .addEventListener('click', () => sendCommand('forward')); + document + .getElementById('btn-backward') + .addEventListener('click', () => sendCommand('backward')); + document + .getElementById('btn-left') + .addEventListener('click', () => sendCommand('left')); + document + .getElementById('btn-right') + .addEventListener('click', () => sendCommand('right')); + document + .getElementById('btn-stop') + .addEventListener('click', () => sendCommand('stop')); + + // Keyboard controls + document.addEventListener('keydown', handleKeyPress); + document.addEventListener('keyup', handleKeyRelease); +} + +function setupROSListeners() { + // Listen for velocity messages from main process + ipcRenderer.on('velocity-received', (event, velocity) => { + handleVelocityReceived(velocity); + }); +} + +function sendCommand(command) { + // Send command to main process + ipcRenderer.send('joystick-command', command); + + // Update UI immediately + updateCommandDisplay(command, getVelocityForCommand(command)); +} + +function getVelocityForCommand(command) { + const speed = 1.0; + const turnSpeed = 1.0; + + switch (command) { + case 'forward': + return { + linear: { x: speed, y: 0, z: 0 }, + angular: { x: 0, y: 0, z: 0 }, + }; + case 'backward': + return { + linear: { x: -speed, y: 0, z: 0 }, + angular: { x: 0, y: 0, z: 0 }, + }; + case 'left': + return { + linear: { x: 0, y: 0, z: 0 }, + angular: { x: 0, y: 0, z: turnSpeed }, + }; + case 'right': + return { + linear: { x: 0, y: 0, z: 0 }, + angular: { x: 0, y: 0, z: -turnSpeed }, + }; + case 'stop': + default: + return { linear: { x: 0, y: 0, z: 0 }, angular: { x: 0, y: 0, z: 0 } }; + } +} + +function updateCommandDisplay(command, velocity) { + currentCommandEl.textContent = + command.charAt(0).toUpperCase() + command.slice(1); + linearXEl.textContent = velocity.linear.x.toFixed(1); + angularZEl.textContent = velocity.angular.z.toFixed(1); +} + +function handleVelocityReceived(velocity) { + commandCount++; + + // Determine command type from velocity + let commandType = 'stop'; + if (velocity.linear.x > 0) commandType = 'forward'; + else if (velocity.linear.x < 0) commandType = 'backward'; + else if (velocity.angular.z > 0) commandType = 'left'; + else if (velocity.angular.z < 0) commandType = 'right'; + + // Update car display + updateCarDisplay(commandType, velocity); + + // Update status + commandCountEl.textContent = commandCount; + lastReceivedCommandEl.textContent = + commandType.charAt(0).toUpperCase() + commandType.slice(1); +} + +function updateCarDisplay(command, velocity) { + // Move car based on command + const moveDistance = 20; + const rotationAngle = 15; + + switch (command) { + case 'forward': + carPosition.y = Math.max(30, carPosition.y - moveDistance); + break; + case 'backward': + carPosition.y = Math.min(270, carPosition.y + moveDistance); + break; + case 'left': + carRotation += rotationAngle; + carPosition.x = Math.max(30, carPosition.x - moveDistance); + break; + case 'right': + carRotation -= rotationAngle; + carPosition.x = Math.min(270, carPosition.x + moveDistance); + break; + case 'stop': + // No movement + break; + } + + // Apply transformations to car element + carEl.style.left = `${carPosition.x}px`; + carEl.style.top = `${carPosition.y}px`; + carEl.style.transform = `translate(-50%, -50%) rotate(${carRotation}deg)`; + + // Update position display + const positionDesc = getPositionDescription(carPosition.x, carPosition.y); + carPositionEl.textContent = positionDesc; + + // Add visual feedback + addMovementFeedback(command); +} + +function getPositionDescription(x, y) { + const centerX = 150; + const centerY = 150; + + if (Math.abs(x - centerX) < 30 && Math.abs(y - centerY) < 30) { + return 'Center'; + } + + let desc = ''; + if (y < centerY - 30) desc += 'North '; + else if (y > centerY + 30) desc += 'South '; + + if (x < centerX - 30) desc += 'West'; + else if (x > centerX + 30) desc += 'East'; + + return desc.trim() || 'Center'; +} + +function addMovementFeedback(command) { + // Add temporary visual feedback + carEl.style.boxShadow = getCommandColor(command); + + setTimeout(() => { + carEl.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)'; + }, 200); +} + +function getCommandColor(command) { + switch (command) { + case 'forward': + return '0 0 15px #00ff00'; + case 'backward': + return '0 0 15px #ff0000'; + case 'left': + return '0 0 15px #0000ff'; + case 'right': + return '0 0 15px #ffff00'; + case 'stop': + return '0 0 15px #ff00ff'; + default: + return '0 2px 5px rgba(0,0,0,0.2)'; + } +} + +// Keyboard controls +function handleKeyPress(event) { + switch (event.key.toLowerCase()) { + case 'w': + case 'arrowup': + event.preventDefault(); + sendCommand('forward'); + break; + case 's': + case 'arrowdown': + event.preventDefault(); + sendCommand('backward'); + break; + case 'a': + case 'arrowleft': + event.preventDefault(); + sendCommand('left'); + break; + case 'd': + case 'arrowright': + event.preventDefault(); + sendCommand('right'); + break; + case ' ': + case 'escape': + event.preventDefault(); + sendCommand('stop'); + break; + } +} + +function handleKeyRelease(event) { + // Auto-stop after key release (optional behavior) + // Uncomment the following lines if you want auto-stop on key release + /* + if (['w', 's', 'a', 'd', 'arrowup', 'arrowdown', 'arrowleft', 'arrowright'].includes(event.key.toLowerCase())) { + setTimeout(() => sendCommand('stop'), 100); + } + */ +} + +// Reset car position (for demo purposes) +function resetCarPosition() { + carPosition = { x: 150, y: 150 }; + carRotation = 0; + updateCarDisplay('stop', { + linear: { x: 0, y: 0, z: 0 }, + angular: { x: 0, y: 0, z: 0 }, + }); +} + +// Add reset button functionality (if needed) +document.addEventListener('dblclick', resetCarPosition); diff --git a/electron_demo/README.md b/electron_demo/topics/README.md similarity index 99% rename from electron_demo/README.md rename to electron_demo/topics/README.md index 0f2c0517..833a6026 100644 --- a/electron_demo/README.md +++ b/electron_demo/topics/README.md @@ -22,6 +22,7 @@ git clone https://github.com/RobotWebTools/rclnodejs.git ``` 2. Go into the demo. + ```bash cd rclnodejs/electron_demo ``` @@ -29,17 +30,20 @@ cd rclnodejs/electron_demo 3. [SOURCE THE ROS 2 SETUP FILE](https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html#source-the-setup-files) 4. Install dependencies + ```bash npm install ``` 5. Rebuild rclnodejs for Electron + ```bash # Every time you run "npm install", run this: ./node_modules/.bin/electron-rebuild ``` 6. Run the app + ``` npm start ``` @@ -51,4 +55,3 @@ If it works, you can see the demo as: - [electronjs.org/docs](https://electronjs.org/docs) - all of Electron's documentation. - [Native Node Modules](https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules) - Use a native node module. - diff --git a/electron_demo/electron-demo.gif b/electron_demo/topics/electron-demo.gif similarity index 100% rename from electron_demo/electron-demo.gif rename to electron_demo/topics/electron-demo.gif diff --git a/electron_demo/index.html b/electron_demo/topics/index.html similarity index 100% rename from electron_demo/index.html rename to electron_demo/topics/index.html diff --git a/electron_demo/main.js b/electron_demo/topics/main.js similarity index 93% rename from electron_demo/main.js rename to electron_demo/topics/main.js index ab147435..2ae89d19 100644 --- a/electron_demo/main.js +++ b/electron_demo/topics/main.js @@ -10,8 +10,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { app, BrowserWindow } = require('electron') -let rclnodejs = require("rclnodejs"); +const { app, BrowserWindow } = require('electron'); +let rclnodejs = require('rclnodejs'); const { ipcMain } = require('electron'); function createWindow() { @@ -24,7 +24,7 @@ function createWindow() { // https://stackoverflow.com/questions/44391448/electron-require-is-not-defined nodeIntegration: true, contextIsolation: false, - } + }, }); mainWindow.loadFile('index.html'); @@ -62,5 +62,5 @@ app.whenReady().then(() => { // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', function () { - if (process.platform !== 'darwin') app.quit() + if (process.platform !== 'darwin') app.quit(); }); diff --git a/electron_demo/package.json b/electron_demo/topics/package.json similarity index 100% rename from electron_demo/package.json rename to electron_demo/topics/package.json diff --git a/electron_demo/renderer.js b/electron_demo/topics/renderer.js similarity index 100% rename from electron_demo/renderer.js rename to electron_demo/topics/renderer.js