Conversation
insertions Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
luca-della-vedova
left a comment
There was a problem hiding this comment.
A few minor comments on cleanups but there is one on functionality about using commands in the SDF Loader that is a bit more substantial
| .insert(PowerSource::label(), power_source_value); | ||
| } | ||
| // Only allow overwriting RobotProperties that are not present | ||
| let Ok((mobility, power_source, power_dissipation)) = robot_properties.get(desc) |
There was a problem hiding this comment.
I might be wrong but I can't figure out if this would ever fail. The query only looks for optional components so I suspect it would actually always succeed, if any component is missing it will be set to None itself.
The only case this could possibly fail is if the entity doesn't exist but that's probably not going to happen since it comes from another query.
Is this intentional? What are you trying to test here?
There was a problem hiding this comment.
Ah I'm trying to figure out if any combination of RobotProperty was already present in the description, and only overwrite components that are not present. So it was intentional to query for optional RobotProperty components for all model descriptions.
But on second thought if a particular component is present in a saved JSON and another is not, the latter is likely meant to be disabled. I'll remove the Option and check for present RobotProperty components as a group.
There was a problem hiding this comment.
19e9e93, turned it into a QueryFilter instead since we don't need the actual values
There was a problem hiding this comment.
Note, IsStatic has to be optional else slotcar parameters may not be inserted at all, even if there's no existing params
| // Use commands instead of direct access to world as we | ||
| // want this to be queued up after robot data has been | ||
| // inserted into model descriptions during loading | ||
| world | ||
| .entity_mut(e) | ||
| .commands() | ||
| .entity(e) |
There was a problem hiding this comment.
This looks a bit odd. What the SDF loader does is serialize the whole content of the world into a bevy::Scene then later we will spawn the Scene.
I think the scene is later spawned through write_to_world_with and that only spawns entities and components, not commands.
So I wonder, are you sure the command here is being applied?
There was a problem hiding this comment.
So this is the main change that fixes the "saved robot properties are being overwritten by the SDF loader" bug for me. If I undo this change cargo test would fail, and after some logging it turned out the original and destination JSONs are different, with RobotProperty being overwritten. This is what I think is happening without commands():
load.rsinserts theRobotcomponent into relevant model description entities. This would prepare the linked systems to insert appropriateRobotProperty(here) andRobotPropertyKind(here) components.- Later in the model loading workflow, the SDF loader iterates through all SDF parts (links/visual/etc.) and inserts the slotcar components into those descendant entities instantly with direct world access. This is because within the SDF loader we don't know what the affiliated descriptions are, since they're not in the same
Worldas where everything else is. - The insert_slotcar_components system searches for non-description entities with these
RobotPropertyKindcomponents, and insert them into the appropriate affiliated description entities. This is done by writing aChangeevent with the updatedRobotserialized properties. - The ChangePlugin updates
ModelProperty<Robot>in the next cycle, and eventually propagates to the affiliated model instances via the update_model_instances system.
TLDR I think steps (1) to (3) take place in cycle N, and step (4) takes place in cycle N+1. This means the inserted components in (1) are not known to insert_slotcar_components in step (3) and will be overwritten. By using commands() we're essentially forcing step 3. to only find slotcar models with robot properties in cycle N+1, and be able to query components from step 1. to check if properties are already present.
There was a problem hiding this comment.
My assertion here is that the world you see here is not the App's world, but a brand new one that is immediately serialized into a scene, and in this process only entities and components are saved, the commands are effectively dropped.
I tested this by actually removing the whole statement that uses a command to add components altogether and verified that the unit test still passes. This makes me think that our unit test doesn't actually verify that this statement is working
There was a problem hiding this comment.
Thanks for pointing that out, I just tried opening the demo map and the tinyRobots do not have the properties inserted in. Let me think of a more reliable fix!
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
9426a00 to
116d038
Compare
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
|
Some changes from the last review (significant enough for a PR title change):
|
|
I believe with these changes it should also close #382 |
|
Since properties are optional I played a bit with enabling / disabling them but that doesn't really seem to work. Specifically: If I open the demo site, disable a robot property (i.e. More puzzlingly, if I open the demo site, change a property value (i.e. power dissipation), then disable the property, save and reload I get this weird state that the property can't actually be enabled again: Screencast.From.2025-10-08.20-24-16.mp4 |
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
Thanks for finding this bug! Fixed in 15bff39. It happens for multi-kind RobotProperty as their |
I only used |
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
|
Ah thanks for providing more context, can I double check that when you disabled the properties, you disabled all of them? If the robot properties map loaded from file is completely empty, it will behave as if we're loading the demo map, i.e. the editor will insert all the slotcar related properties. After testing a little bit, any other combination aside from a completely empty properties map should yield the correct data. I think we should keep this behavior (insert slotcar components if they're found + there are no pre-existing robot properties), but one way to ensure a non-empty properties map in this scenario is to set In any case, I've added the |
luca-della-vedova
left a comment
There was a problem hiding this comment.
Understood on the behavior, I left some inline reviews, behavior wise lgtm
Signed-off-by: Xiyu Oh <xiyu@openrobotics.org>
luca-della-vedova
left a comment
There was a problem hiding this comment.
Thanks for iterating! LGTM
The current
RobotProperty/RobotPropertyKind/ModelPropertyDataimplementation exist largely within thewidgetmodule in the site editor. This should not be the case, especially if we want to operate in headless mode. With this PR we move non-UI related logic into their own submodules within thesitemod.Also added a fix for the headless roundtrip test failing CI (example #345), which occurs because
slotcarproperties are overwriting existingRobotProperty/RobotPropertyKindimported from file. This is caused by usingcommands.entity()to insert these components during load, but usingworld.entity_mut()when inserting SDF/slotcarparameters, so the sequence was messed up. Added some checks ininsert_slotcar_componentsto make sure that we're not overwriting existingRobotPropertyimported from loading.