Hello all,
I’m experiencing a couple of strange behaviors when implementing child program nodes from a parent one and when loading previously saved programs.
What I want to implement is a parent program node, from which I can add or remove specific child nodes thanks to dedicated check boxes. The check box is selected, a specific child node is added; the check box is not selected, this child node is removed. Ideally, I would like to control where the child nodes are located in the hierarchy, preserving the coherence of the hierarchy when one specific child node is removed.
I actually implemented this mechanism successfully but, as soon as I’m saving the program and loading it again, it crashes, showing me that I am developing it in a bad way.
First test
I have developed a first URCap, implementing a parent program node including a child node, which is a standard “Wait” node. The parent program node includes 2 check boxes, which are in this test not doing much.
The node hierarchy is created through the program node contribution:
TreeNode root = this.apiProvider.getProgramAPI().getProgramModel().getRootTreeNode(this);
WaitNode waitNode = this.programNodeFactory.createWaitNode();
Time oneSecondWait = this.programAPI.getValueFactoryProvider().getSimpleValueFactory().createTime(1, Time.Unit.S);
TimeWaitNodeConfig config = waitNode.getConfigFactory().createTimeConfig(oneSecondWait, ErrorHandler.AUTO_CORRECT);
this.programAPI.getProgramModel().getRootTreeNode(this).addChild(waitNode.setConfig(config));
When clicking on one of the check boxes, the data model is modified (within the context implemented by the UndoRedoManager) and the following line is executed (and only this one):
TreeNode root = this.apiProvider.getProgramAPI().getProgramModel().getRootTreeNode(this);
When starting the program from scratch, no problem. When saving the program and loading it again, when interacting when one of the check boxes, a new “Wait” node appears. I don’t understand this behavior. How come this new node appears?
Strangely enough, if I’m saving the program with one of the check boxes selected and loading it again, the check box is of course selected, and the additional node appears anyway if I am deselecting it. What is the reason behind that?
Second test
In the second test, the child node A is a standard “Wait” node with a 2s duration and the child node B is a standard “Wait” node with a 3s duration. Taking into account the different samples, the node hierarchy is created within the constructor. When the user is clicking on one of the check boxes, the sub tree is cleared (i just copied/pasted the clearSubtree() method from the samples) and the function creating the hierarchy is executed again.
public void setAddChildAState(final boolean state)
{
this.apiProvider.getProgramAPI().getUndoRedoManager().recordChanges(new UndoableChanges()
{
@Override
public void executeChanges()
{
model.setAddChildAState(state);
// clear subtree
clearSubtree();
// create sub tree again
createSubtree();
}
});
}
The node hierarchy is created as in the first test, adding child nodes relatively to data model values.
Here, no problem at all. I have the same behavior whether I am starting the program from scratch or I am loading a previously saved program. I’m clearing the whole sub-tree, not taking into account additional nodes eventually added by the user, but I guess I can solve that with a CustomAPI and the ProgramNodeVisitor.
Third and last test
Now, instead of standard “Wait” nodes, I want to add nodes of my own. For the sake of testing from something, which is initially working, I actually added to my URCap the GripperOpenNode from the “Pick and Place” sample. It is the same code as before, but instead of initializing my node hierarchy with a standard “Wait” node, the one with the 1s duration, I am initializing it with the GripperOpenNode.
TreeNode root = this.apiProvider.getProgramAPI().getProgramModel().getRootTreeNode(this);
WaitNode waitNode2 = this.programNodeFactory.createWaitNode();
Time oneSecondWait2 = this.programAPI.getValueFactoryProvider().getSimpleValueFactory().createTime(2, Time.Unit.S);
TimeWaitNodeConfig config2 = waitNode2.getConfigFactory().createTimeConfig(oneSecondWait2, ErrorHandler.AUTO_CORRECT);
WaitNode waitNode3 = this.programNodeFactory.createWaitNode();
Time oneSecondWait3 = this.programAPI.getValueFactoryProvider().getSimpleValueFactory().createTime(3, Time.Unit.S);
TimeWaitNodeConfig config3 = waitNode3.getConfigFactory().createTimeConfig(oneSecondWait3, ErrorHandler.AUTO_CORRECT);
root.addChild(this.programNodeFactory.createURCapProgramNode(GripperOpenProgramNodeService.class));
if (this.model.getAddChildAState())
this.programAPI.getProgramModel().getRootTreeNode(this).addChild(waitNode2.setConfig(config2));
if (this.model.getAddChildBState())
this.programAPI.getProgramModel().getRootTreeNode(this).addChild(waitNode3.setConfig(config3));
Once again, starting the program from scratch, everything is going well. When loading the program and beginning to interact with the check boxes, a crash occurs. I don’t manage to know why it is happening. I tried to catch this exception without success for now.
If I’m saving the program with one of the check boxes selected, the program crashes as soon as I am clicking on the “Parent” node.
1 remark here. If I’m executing the URCap from the first test, not implementing an initial “Wait” node with a 1s duration but with a GripperOpenNode, the same crash as the third test occurs.
I am of course developing it in a wrong way but where is the mistake? I tried as well to implement it thanks to TreeNodes and playing with the insertChildBefore() and insertChildAfter() methods - ideally, that’s how I would like to implement it - but the same bug occurs. I am working with the sdk 1.5.0. I don’t want to work with templates, as in the “Pick and place” sample, as the overall goal is to have more than 2 check boxes / child nodes. It will quickly be non-maintainable.
I implemented that the 3 tests as URCaps that can be compiled and installed, if anyone is interested to get the whole implementation.
com.dti.test1.tar.gz (48.8 KB)
com.dti.test2.tar.gz (48.8 KB)
com.dti.test3.tar.gz (59.1 KB)
Any fresh ideas/fixes/new tests appreciated. Thank you very much in advance!