Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing model descriptions and instances #242

Merged
merged 89 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
ce017cb
Scenarios V2
reuben-thomas Jun 27, 2024
f00141d
Use groups
reuben-thomas Jul 1, 2024
6167ec1
Add scale and static to instances
reuben-thomas Jul 1, 2024
03cace2
fix description names
reuben-thomas Jul 2, 2024
0010b9f
Added convert function for model instance
reuben-thomas Jul 2, 2024
243b2b4
Merge remote-tracking branch 'upstream/main' into scenarios
reuben-thomas Jul 2, 2024
8386209
add from group list
reuben-thomas Jul 8, 2024
9f30004
redefine description, instances, scenarios
reuben-thomas Jul 10, 2024
1215fa9
scenario panel prototype
reuben-thomas Jul 11, 2024
1c25265
senario menu
reuben-thomas Jul 12, 2024
7adb5c6
improve scenario selector ui
reuben-thomas Jul 16, 2024
ce9f345
functional scenario switching
reuben-thomas Jul 17, 2024
97f8dbf
additions
reuben-thomas Jul 17, 2024
537ff76
Description inspector prototype
reuben-thomas Jul 18, 2024
b3f232d
organize instance and group properties
reuben-thomas Jul 19, 2024
c284a64
model description inspector plugin
reuben-thomas Jul 23, 2024
8cf25e7
Add differential drive
reuben-thomas Jul 23, 2024
9c96e32
deletions
reuben-thomas Jul 24, 2024
f6124a2
remove task view
reuben-thomas Jul 24, 2024
e84dc58
edit scenarios
reuben-thomas Jul 25, 2024
6d0a7e8
fix description deletions, instances without parent
reuben-thomas Jul 25, 2024
63fb8b9
scenarios: fix undos, allow for different instance types
reuben-thomas Jul 26, 2024
443a3fe
fix misplaced cfg(feature)
reuben-thomas Jul 26, 2024
ecb9bb7
fix base tasks
reuben-thomas Jul 27, 2024
5a8ef05
fix styling
reuben-thomas Jul 27, 2024
c896ea8
move all scenario viewer from mapf
reuben-thomas Jul 29, 2024
f7a24be
fixes, address comment
reuben-thomas Jul 31, 2024
69ea1df
Add instances to creation
reuben-thomas Jul 31, 2024
9963a8f
model selection
reuben-thomas Jul 31, 2024
a944432
add collision radius
reuben-thomas Jul 31, 2024
94ccc5c
allow ignore for occupancy calculation
reuben-thomas Jul 31, 2024
4b413a2
delete scenarios
reuben-thomas Aug 1, 2024
d95be3b
add saving
reuben-thomas Aug 2, 2024
42f25c2
Merge branch 'main' into scenarios
xiyuoh Oct 10, 2024
4729bef
Reduce unnecessary diff
xiyuoh Oct 11, 2024
afddc82
Remove description entity from model instances supported highlighting…
xiyuoh Oct 14, 2024
bb13ee0
Cleanup creation with place_object()
xiyuoh Oct 17, 2024
8ffcfe6
Limit model instance creation to spawn with existing model descriptio…
xiyuoh Oct 17, 2024
1d8aa7d
Avoid duplicate variable names
xiyuoh Oct 29, 2024
af5a2d5
Simplify printouts
xiyuoh Oct 29, 2024
c6eebf4
Remove unnecessary Without in deletion and minor corrections in scenario
xiyuoh Oct 29, 2024
e2b365c
Switch model instances to spawn 2d
xiyuoh Oct 30, 2024
f0fa12c
Clarify wait for units (assuming seconds)
xiyuoh Oct 30, 2024
ad5ba6e
Align delete scenario button
xiyuoh Oct 30, 2024
d331a79
Cleanup
xiyuoh Nov 4, 2024
5786bae
Do not display scenarios that do not belong to this site
xiyuoh Nov 4, 2024
7b01c91
Remove unnecessary diffs/code and duplicate variable names
xiyuoh Nov 12, 2024
d450cd7
Spawning model descriptions via fuel
xiyuoh Nov 13, 2024
83f3d85
Style
xiyuoh Nov 13, 2024
de9b60e
Tidy up inspect differential drive
xiyuoh Nov 14, 2024
90a60ba
Display Description for instance entities only instead of not-descrip…
xiyuoh Nov 14, 2024
acb39b9
Modify Task implementation
xiyuoh Nov 14, 2024
1c2cdcf
Merge branch 'main' into xiyu/scenarios
xiyuoh Nov 15, 2024
057e186
Use deletion filter for instance removal
xiyuoh Nov 15, 2024
94b54a9
Fix style - macro not derived for WaitFor task
xiyuoh Nov 15, 2024
6ad0ea7
Trigger model instance visibility update when creating new levels
xiyuoh Nov 15, 2024
8c19eed
Remove unnecessary Eq
xiyuoh Nov 15, 2024
5aed94f
Search for ignore parent entities when calculating grid
xiyuoh Dec 10, 2024
3a6ad1d
Remove unused imports
xiyuoh Dec 10, 2024
cc29375
Update wasm-bindgen dependency
xiyuoh Dec 11, 2024
01fca32
Consistent capitalization
xiyuoh Dec 11, 2024
4252c38
Save DifferentialDrive and MobileRobotMarker properties
xiyuoh Dec 19, 2024
bbc373c
Save model instance Tasks
xiyuoh Dec 19, 2024
d97232d
Cleanup todo comments
xiyuoh Dec 19, 2024
766fd62
Merge branch 'main' into xiyu/scenarios
xiyuoh Dec 19, 2024
48c94e9
Merge branch 'main' into xiyu/scenarios
xiyuoh Dec 20, 2024
347d546
Fix OptionalModelProperties and move model loading to the end of gene…
xiyuoh Dec 20, 2024
73076af
Load robot from legacy file
xiyuoh Dec 23, 2024
6663e1a
Clearer name
xiyuoh Dec 23, 2024
8cc2670
Merge branch 'main' into xiyu/scenarios
xiyuoh Dec 26, 2024
d6b643a
Remove duplicate asset source inspector
xiyuoh Dec 27, 2024
2fab67d
Fix description asset source updates not working
xiyuoh Dec 27, 2024
57436ed
Support location hovering
xiyuoh Dec 27, 2024
a2e2ef5
Improvements from review comments
xiyuoh Dec 27, 2024
7ef079c
Take out .expect()
xiyuoh Dec 27, 2024
5e5e16d
Only read latest ChangeCurrentScenario event
xiyuoh Dec 27, 2024
eb49604
Avoid redundant lookup
xiyuoh Dec 30, 2024
4816d02
Raise error if affiliated description of an instance is not found whi…
xiyuoh Dec 30, 2024
1bb13d0
Use workflows for instance spawning
xiyuoh Dec 30, 2024
812c183
Remove expect from scenario format
xiyuoh Dec 30, 2024
a850590
Check if SiteParent exists when loading models and remove ChangeCurre…
xiyuoh Dec 30, 2024
5ce02a1
Replace luca with openrmf
xiyuoh Dec 30, 2024
661ecb9
Remove unused things
xiyuoh Dec 30, 2024
f527790
Remove unused model loading and preview
xiyuoh Dec 30, 2024
8c09224
Change BTreeMap to is_empty and minor cleanup
xiyuoh Dec 31, 2024
c8e1fb2
Remove unused InspectAssetSource
xiyuoh Dec 31, 2024
19483c4
Use BTreeMap::is_empty
xiyuoh Dec 31, 2024
1478654
Merge branch 'main' into xiyu/scenarios
xiyuoh Jan 2, 2025
6067fef
Review improvements
xiyuoh Jan 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions rmf_site_editor/src/interaction/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,12 @@ impl Cursor {
) {
self.remove_preview(commands);
self.preview_model = if let Some(model_instance) = model_instance {
if let Some(mut spawn_instance) =
model_loader.spawn_model_instance(self.frame, model_instance.clone(), None)
{
Some(spawn_instance.insert(Pending).id())
} else {
None
}
Some(
mxgrey marked this conversation as resolved.
Show resolved Hide resolved
model_loader
.spawn_model_instance(self.frame, model_instance.clone())
.insert(Pending)
.id(),
)
} else {
None
};
Expand Down
8 changes: 3 additions & 5 deletions rmf_site_editor/src/interaction/select/place_object_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,9 @@ pub fn on_placement_chosen_2d(
let mut state = access.pull().or_broken_state()?;

state.object.pose = placement.into();
if let Some(mut model_instance) =
model_loader.spawn_model_instance(state.level, state.object, None)
{
model_instance.insert(Category::Model);
}
model_loader
.spawn_model_instance(state.level, state.object)
.insert(Category::Model);

Ok(())
}
67 changes: 27 additions & 40 deletions rmf_site_editor/src/site/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,50 +367,37 @@ fn generate_site_entities(
.convert(&id_to_entity)
.for_site(site_id)?;

if let Some(model_description) = model_instance.description.0 {
let source = model_description_to_source.get(&model_description);
if let Some(mut loaded_instance) =
model_loader.spawn_model_instance(site_id, model_instance.clone(), source)
{
let model_instance_entity = loaded_instance
.insert((Category::Model, SiteID(*model_instance_id)))
.id();
id_to_entity.insert(*model_instance_id, model_instance_entity);
consider_id(*model_instance_id);

if let Some(instances) = model_description_dependents.get_mut(&model_description) {
instances.insert(model_instance_entity);
} else {
error!(
"Model description missing for instance {}. This should \
let model_instance_entity = model_loader
.spawn_model_instance(site_id, model_instance.clone())
.insert((Category::Model, SiteID(*model_instance_id)))
.id();
id_to_entity.insert(*model_instance_id, model_instance_entity);
consider_id(*model_instance_id);

if let Some(instances) = model_instance
.description
.0
.map(|e| model_description_dependents.get_mut(&e))
.flatten()
{
instances.insert(model_instance_entity);
} else {
error!(
"Model description missing for instance {}. This should \
not happen, please report this bug to the maintainers of \
mxgrey marked this conversation as resolved.
Show resolved Hide resolved
rmf_site_editor.",
model_instance.name.0,
);
}
model_instance.name.0,
);
}

// Insert optional model properties
for optional_property in &model_instance.optional_properties.0 {
match optional_property {
OptionalModelProperty::Tasks(tasks) => {
commands.entity(model_instance_entity).insert(tasks.clone())
}
_ => continue,
};
// Insert optional model properties
for optional_property in &model_instance.optional_properties.0 {
match optional_property {
OptionalModelProperty::Tasks(tasks) => {
commands.entity(model_instance_entity).insert(tasks.clone())
}
} else {
error!(
"Unable to access the asset source for model instance [{}]! \
Failed to load model instance.",
model_instance_id
);
}
} else {
error!(
"Model instance [{}] is not affiliated with any model description! \
Failed to load model instance.",
model_instance_id
);
_ => continue,
};
}
}

Expand Down
104 changes: 77 additions & 27 deletions rmf_site_editor/src/site/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub fn get_all_for_source(source: &AssetSource) -> SmallVec<[AssetSource; 6]> {

pub type ModelLoadingResult = Result<ModelLoadingSuccess, ModelLoadingError>;

pub type InstanceSpawningResult = Result<ModelLoadingSuccess, InstanceSpawningError>;

#[derive(Resource)]
/// Services that deal with model loading
// TODO(luca) revisit pub / private-ness of struct and fields
Expand All @@ -78,6 +80,7 @@ struct ModelLoadingServices {
check_scene_is_spawned: Service<Entity, Entity>,
/// System that tries to load a model and returns a result.
pub load_model: Service<ModelLoadingRequest, ModelLoadingResult>,
pub spawn_instance: Service<InstanceSpawningRequest, InstanceSpawningResult>,
}

#[derive(Default)]
Expand Down Expand Up @@ -319,13 +322,29 @@ fn handle_model_loading_errors(
result
}

fn instance_spawn_request_into_model_load_request(
In(request): In<InstanceSpawningRequest>,
descriptions: Query<&ModelProperty<AssetSource>>,
) -> Result<ModelLoadingRequest, InstanceSpawningError> {
let Some(affiliation) = request.affiliation.0 else {
return Err(InstanceSpawningError::NoAffiliation);
};

let Ok(source) = descriptions.get(affiliation) else {
return Err(InstanceSpawningError::AffiliationMissing);
};

Ok(ModelLoadingRequest {
parent: request.parent,
source: source.0.clone(),
})
}

/// `SystemParam` used to request for model loading operations
#[derive(SystemParam)]
pub struct ModelLoader<'w, 's> {
services: Res<'w, ModelLoadingServices>,
commands: Commands<'w, 's>,
model_descriptions:
Query<'w, 's, &'static ModelProperty<AssetSource>, (With<ModelMarker>, With<Group>)>,
model_instances: Query<
'w,
's,
Expand All @@ -343,29 +362,16 @@ impl<'w, 's> ModelLoader<'w, 's> {
})
}

/// Spawn a new model instance and begin a workflow to load its asset source.
/// Spawn a new model instance and begin a workflow to load its asset source
/// from the affiliated model description.
/// This is only for brand new models does not support reacting to the load finishing.
pub fn spawn_model_instance(
mxgrey marked this conversation as resolved.
Show resolved Hide resolved
&mut self,
parent: Entity,
model_instance: ModelInstance<Entity>,
source: Option<&AssetSource>,
) -> Option<EntityCommands<'w, 's, '_>> {
let model_description_source = model_instance
.description
.0
.map(|e| {
self.model_descriptions
.get(e)
.ok()
.map(|property| property.0.clone())
})
.flatten();

source.or(model_description_source.as_ref()).map(|s| {
self.spawn_model_instance_impulse(parent, model_instance, s.clone(), move |impulse| {
impulse.detach();
})
instance: ModelInstance<Entity>,
) -> EntityCommands<'w, 's, '_> {
self.spawn_model_instance_impulse(parent, instance, move |impulse| {
impulse.detach();
})
}

Expand All @@ -389,13 +395,19 @@ impl<'w, 's> ModelLoader<'w, 's> {
pub fn spawn_model_instance_impulse(
&mut self,
parent: Entity,
model: ModelInstance<Entity>,
source: AssetSource,
impulse: impl FnOnce(Impulse<ModelLoadingResult, ()>),
instance: ModelInstance<Entity>,
impulse: impl FnOnce(Impulse<InstanceSpawningResult, ()>),
) -> EntityCommands<'w, 's, '_> {
let id = self.commands.spawn(model).set_parent(parent).id();
let loading_impulse = self.update_asset_source_impulse(id, source);
(impulse)(loading_impulse);
let affiliation = instance.description.clone();
let id = self.commands.spawn(instance).set_parent(parent).id();
let spawning_impulse = self.commands.request(
InstanceSpawningRequest::new(id, affiliation),
self.services
.spawn_instance
.clone()
.instruct(SpawnModelLabel(id).preempt()),
);
(impulse)(spawning_impulse);
self.commands.entity(id)
}

Expand Down Expand Up @@ -541,9 +553,25 @@ impl ModelLoadingServices {
.connect(scope.terminate)
});

// Model instance spawning workflow
let spawn_instance = app.world.spawn_workflow(|scope, builder| {
scope
.input
.chain(builder)
.then(instance_spawn_request_into_model_load_request.into_blocking_callback())
.connect_on_err(scope.terminate)
.then(load_model)
.map_block(|res| match res {
Ok(success) => Ok(success),
Err(err) => Err(InstanceSpawningError::ModelError(err)),
mxgrey marked this conversation as resolved.
Show resolved Hide resolved
})
.connect(scope.terminate)
});

Self {
load_model,
check_scene_is_spawned,
spawn_instance,
}
}
}
Expand Down Expand Up @@ -615,6 +643,28 @@ pub enum ModelLoadingErrorKind {
FailedLoadingDependency(String),
}

#[derive(Clone, Debug)]
pub struct InstanceSpawningRequest {
pub parent: Entity,
pub affiliation: Affiliation<Entity>,
}

impl InstanceSpawningRequest {
pub fn new(parent: Entity, affiliation: Affiliation<Entity>) -> Self {
Self {
parent,
affiliation,
}
}
}

#[derive(Clone, Debug)]
pub enum InstanceSpawningError {
NoAffiliation,
AffiliationMissing,
ModelError(ModelLoadingError),
}

pub fn update_model_scales(
changed_scales: Query<(&Scale, &ModelScene), Or<(Changed<Scale>, Changed<ModelScene>)>>,
mut transforms: Query<&mut Transform>,
Expand Down
Loading