Skip to content

Commit

Permalink
Add nexus_workcell_editor (#36)
Browse files Browse the repository at this point in the history
* Add nexus_workcell_editor

Signed-off-by: Yadunund <[email protected]>

* Fix demo workcell

Signed-off-by: Luca Della Vedova <[email protected]>

* Test pin libm

Signed-off-by: Luca Della Vedova <[email protected]>

* Revert "Test pin libm"

This reverts commit 1055ce0.

Signed-off-by: Luca Della Vedova <[email protected]>

---------

Signed-off-by: Yadunund <[email protected]>
Signed-off-by: Luca Della Vedova <[email protected]>
Co-authored-by: Luca Della Vedova <[email protected]>
  • Loading branch information
Yadunund and luca-della-vedova authored Oct 28, 2024
1 parent d8715f0 commit 728fd0d
Show file tree
Hide file tree
Showing 13 changed files with 630 additions and 2 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/nexus_workcell_editor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: workcell_editor
on:
pull_request:
push:
branches: [ main ]
defaults:
run:
shell: bash
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
docker_image: ['ros:iron-ros-base']
container:
image: ${{ matrix.docker_image }}
timeout-minutes: 30
steps:
- name: Deps
run: |
apt update && apt install -y git curl libclang-dev libasound2-dev libudev-dev libgtk-3-dev python3-pip python3-vcstool
- name: Setup Rust
uses: dtolnay/[email protected]
with:
components: clippy, rustfmt
- name: Install colcon cargo
run: |
cargo install --debug cargo-ament-build # --debug is faster to install
pip install git+https://github.com/colcon/colcon-cargo.git
pip install git+https://github.com/colcon/colcon-ros-cargo.git
- uses: actions/checkout@v2
- name: vcs
run: |
git clone https://github.com/ros2-rust/ros2_rust.git -b 0.4.0
vcs import . < ros2_rust/ros2_rust_iron.repos
- name: rosdep
run: |
rosdep update
rosdep install --from-paths . -yir
- name: build
run: /ros_entrypoint.sh colcon build --packages-up-to nexus_workcell_editor
7 changes: 7 additions & 0 deletions .github/workflows/style.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ jobs:
run: |
sudo apt update && sudo apt install -y pycodestyle curl
pycodestyle nexus_network_configuration/
- name: Setup Rust
uses: dtolnay/[email protected]
with:
components: clippy, rustfmt
- name: rustfmt
run: |
rustfmt --check --edition 2021 nexus_workcell_editor/src/main.rs
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# NEXUS
![](https://github.com/osrf/nexus/workflows/style/badge.svg)
![](https://github.com/osrf/nexus/workflows/integration_tests/badge.svg)
[![style](https://github.com/osrf/nexus/actions/workflows/style.yaml/badge.svg)](https://github.com/osrf/nexus/actions/workflows/style.yaml)
[![integration_tests](https://github.com/osrf/nexus/actions/workflows/nexus_integration_tests.yaml/badge.svg)](https://github.com/osrf/nexus/actions/workflows/nexus_integration_tests.yaml)
[![workcell_editor](https://github.com/osrf/nexus/actions/workflows/nexus_workcell_editor.yaml/badge.svg)](https://github.com/osrf/nexus/actions/workflows/nexus_workcell_editor.yaml)

![](./docs/media/nexus_architecture.png)

Expand Down
2 changes: 2 additions & 0 deletions nexus_workcell_editor/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target/
Cargo.lock
7 changes: 7 additions & 0 deletions nexus_workcell_editor/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package nexus_workcell_editor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Forthcoming
------------------
* Provides the ``nexus_workcell_editor`` application to graphically design a workcell using individual components and calibrate the poses of these components.
21 changes: 21 additions & 0 deletions nexus_workcell_editor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "nexus_workcell_editor"
version = "0.0.1"
edition = "2021"

[[bin]]
path = "src/main.rs"
name = "nexus_workcell_editor"

[dependencies]
bevy = "0.12"
bevy_egui = "0.23"
# TODO(luca) Just use the version used by site editor once released
bevy_impulse = { git = "https://github.com/open-rmf/bevy_impulse", branch = "main" }
clap = { version = "4.0.10", features = ["color", "derive", "help", "usage", "suggestions"] }
crossbeam-channel = "0.5.8"
# TODO(luca) back to main when PR is merged
rmf_site_editor = { git = "https://github.com/open-rmf/rmf_site", rev = "f4bed77" }
rmf_site_format = { git = "https://github.com/open-rmf/rmf_site", rev = "f4bed77" }
rclrs = "0.4.0"
nexus_calibration_msgs = "*"
28 changes: 28 additions & 0 deletions nexus_workcell_editor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# nexus_workcell_editor

A GUI for assembling workcells from components that is built off [rmf_site](https://github.com/open-rmf/rmf_site).

## Setup

Install rustup from the Rust website: https://www.rust-lang.org/tools/install

```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

Follow instructions [here](https://github.com/ros2-rust/ros2_rust) to setup ros2_rust.

## Build
```
# source the ros distro and ros2_rust workspace.
cd ~/ws_nexus
colcon build
```

## Run
```bash
cd ~/ws_nexus
source ~/ws_nexus/install/setup.bash
ros2 run nexus_workcell_editor nexus_workcell_editor
```

22 changes: 22 additions & 0 deletions nexus_workcell_editor/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<package format="3">
<name>nexus_workcell_editor</name>
<version>0.1.1</version>
<description>A GUI to assemble workcells</description>
<maintainer email="[email protected]">Yadunund</maintainer>
<license>Apache License 2.0</license>

<build_depend>cargo</build_depend>

<depend>gtk3</depend>
<depend>libudev-dev</depend>
<depend>libasound2-dev</depend>
<depend>nexus_calibration_msgs</depend>
<depend>rclrs</depend>

<test_depend>abb_irb910sc_support</test_depend>
<test_depend>nexus_assets</test_depend>

<export>
<build_type>ament_cargo</build_type>
</export>
</package>
126 changes: 126 additions & 0 deletions nexus_workcell_editor/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (C) 2024 Johnson & Johnson
*
* 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.
*
*/

use bevy::render::{
render_resource::{AddressMode, SamplerDescriptor},
settings::{WgpuFeatures, WgpuSettings},
RenderPlugin,
};
use bevy::{log::LogPlugin, pbr::DirectionalLightShadowMap, prelude::*};
use bevy_egui::EguiPlugin;

use clap::Parser;

use librmf_site_editor::{
aabb::AabbUpdatePlugin, animate::AnimationPlugin, asset_loaders::AssetLoadersPlugin,
interaction::InteractionPlugin, issue::IssuePlugin, keyboard::*, log::LogHistoryPlugin,
occupancy::OccupancyPlugin, site::SitePlugin, site_asset_io::SiteAssetIoPlugin,
view_menu::ViewMenuPlugin, widgets::*, wireframe::SiteWireframePlugin,
workcell::WorkcellEditorPlugin, workspace::*, AppState, CommandLineArgs,
};

pub mod main_menu;
use main_menu::{Autoload, MainMenuPlugin};

pub mod ros_context;
use ros_context::RosContextPlugin;

pub mod workcell_calibration;
use workcell_calibration::WorkcellCalibrationPlugin;

fn main() {
info!("Starting nexus_workcell_editor");

let mut app = App::new();

#[cfg(not(target_arch = "wasm32"))]
{
let command_line_args: Vec<String> = std::env::args().collect();
let command_line_args = CommandLineArgs::parse_from(command_line_args);
if let Some(path) = command_line_args.filename {
app.insert_resource(Autoload::file(
path.into(),
command_line_args.import.map(Into::into),
));
}
}

let mut plugins = DefaultPlugins.build();
plugins = plugins.set(WindowPlugin {
primary_window: Some(Window {
title: "RMF Site Editor".to_owned(),
#[cfg(not(target_arch = "wasm32"))]
resolution: (1600., 900.).into(),
#[cfg(target_arch = "wasm32")]
canvas: Some(String::from("#rmf_site_editor_canvas")),
#[cfg(target_arch = "wasm32")]
fit_canvas_to_parent: true,
..default()
}),
..default()
});
app.add_plugins((
SiteAssetIoPlugin,
plugins
.disable::<LogPlugin>()
.set(ImagePlugin {
default_sampler: SamplerDescriptor {
address_mode_u: AddressMode::Repeat,
address_mode_v: AddressMode::Repeat,
address_mode_w: AddressMode::Repeat,
..Default::default()
}
.into(),
})
.set(RenderPlugin {
render_creation: WgpuSettings {
#[cfg(not(target_arch = "wasm32"))]
features: WgpuFeatures::POLYGON_MODE_LINE,
..default()
}
.into(),
..default()
}),
));

app.insert_resource(DirectionalLightShadowMap { size: 2048 })
.add_state::<AppState>()
.add_plugins((
AssetLoadersPlugin,
LogHistoryPlugin,
AabbUpdatePlugin,
EguiPlugin,
KeyboardInputPlugin,
MainMenuPlugin,
WorkcellEditorPlugin,
SitePlugin,
InteractionPlugin::default(),
StandardUiPlugin::default(),
AnimationPlugin,
OccupancyPlugin,
WorkspacePlugin,
SiteWireframePlugin,
))
.add_plugins((
IssuePlugin,
ViewMenuPlugin,
RosContextPlugin,
WorkcellCalibrationPlugin,
bevy_impulse::ImpulsePlugin::default(),
))
.run();
}
124 changes: 124 additions & 0 deletions nexus_workcell_editor/src/main_menu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright (C) 2024 Johnson & Johnson
*
* 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.
*
*/

use bevy::{app::AppExit, prelude::*, tasks::Task, window::PrimaryWindow};
use bevy_egui::{egui, EguiContexts};
use librmf_site_editor::{
workspace::{WorkspaceData, WorkspaceLoader},
AppState,
};
use rmf_site_format;
use std::path::PathBuf;

#[derive(Resource)]
pub struct Autoload {
pub filename: Option<PathBuf>,
pub import: Option<PathBuf>,
pub importing: Option<Task<Option<(Entity, rmf_site_format::Site)>>>,
}

impl Autoload {
pub fn file(filename: PathBuf, import: Option<PathBuf>) -> Self {
Autoload {
filename: Some(filename),
import,
importing: None,
}
}
}

pub fn demo_workcell() -> Vec<u8> {
return include_str!("../test/test.workcell.json")
.as_bytes()
.to_vec();
}

fn egui_ui(
mut egui_context: EguiContexts,
mut _exit: EventWriter<AppExit>,
mut workspace_loader: WorkspaceLoader,
mut _app_state: ResMut<State<AppState>>,
autoload: Option<ResMut<Autoload>>,
primary_windows: Query<Entity, With<PrimaryWindow>>,
) {
if let Some(mut autoload) = autoload {
#[cfg(not(target_arch = "wasm32"))]
{
if let Some(filename) = autoload.filename.clone() {
workspace_loader.load_from_path(filename);
}
autoload.filename = None;
}
return;
}

let Some(ctx) = primary_windows
.get_single()
.ok()
.and_then(|w| egui_context.try_ctx_for_window_mut(w))
else {
return;
};
egui::Window::new("Welcome!")
.collapsible(false)
.resizable(false)
.title_bar(false)
.anchor(egui::Align2::CENTER_CENTER, egui::vec2(0., 0.))
.show(ctx, |ui| {
ui.heading("Welcome to The NEXUS Workcell Editor!");
ui.add_space(10.);

ui.horizontal(|ui| {
if ui.button("New workcell").clicked() {
workspace_loader.load_from_data(WorkspaceData::Workcell(
rmf_site_format::Workcell::default()
.to_string()
.unwrap()
.into(),
));
}

if ui.button("Load workcell").clicked() {
workspace_loader.load_from_dialog();
}

if ui.button("Demo workcell").clicked() {
workspace_loader.load_from_data(WorkspaceData::Workcell(demo_workcell()));
}
});

#[cfg(not(target_arch = "wasm32"))]
{
ui.add_space(20.);
ui.horizontal(|ui| {
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
if ui.button("Exit").clicked() {
_exit.send(AppExit);
}
});
});
}
});
}

pub struct MainMenuPlugin;

impl Plugin for MainMenuPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, egui_ui.run_if(in_state(AppState::MainMenu)));
}
}
Loading

0 comments on commit 728fd0d

Please sign in to comment.