FeatureModel method updateFeature throws an Uncatchable Exception: DefenseCheckException

Hello!

I use the FeatureModel method updateFeature in a daemon thread which starts in the constructor, but every now and then it throws a DefenseCheckException which is not caught in my try/catch.
I originally had it to run only in a non-looping thread, but then it tried to set the Feature before the installation was properly loaded, and it never really got set.
My code looks something like this:

private void setFeature(Pose pose) {
	Pose featurePose = null;
	try {
		featurePose = featureContributionModel.getFeature(FEATURE_NAME).getPose();
		System.out.println(featurePose.toString() + " and " + pose.toString());
	} catch (Exception e) {
		e.printStackTrace();
		featurePose = null;
	}
	if (pose == null) {
		if (featurePose == null) {
			return;
		}
		featureContributionModel.removeFeature(FEATURE_NAME);
		System.out.println("Removed feature: " + featurePose.toString());
		return;
	} else if (featurePose == null) {
		featureContributionModel.addFeature(FEATURE_NAME, FEATURE_NAME, pose);
		System.out.println("Added feature: " + pose.toString());
		return;
	} else if (!pose.epsilonEquals(featurePose, 0.00001, Length.Unit.MM, 0.00001, Angle.Unit.RAD)) {
		featureContributionModel.updateFeature(FEATURE_NAME, pose);
		System.out.println("Updated feature: " + pose.toString());
	}
}

private class MyThread extends Thread {
	private volatile boolean stop = false;
	public MyThread(){
		super(MY_THREAD_GROUP,"MyThread");
	}

	@Override
	public void run(){
		while (!stop) {
			// ... Bunch of other things
			try {
				Pose newFeaturePose = getFeaturePose();
				setFeature(newFeaturePose);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

Every now and then at start and even poweroff/restart, I get a printout of valid poses and then this unhandled exception, killing the thread (Even though I’m try/catch it):

12:36:32.847 ERROR - Caught an unhandled exception {thread: AWT-EventQueue-0 , loggerClass: gui.tools.URDialogCreator}
com.ur.lang.Defense$DefenseCheckException: Expect subject to NOT be null
        at com.ur.lang.Defense.notNull(Defense.java:33) ~[?:?]
        at com.ur.lang.Defense.notNull(Defense.java:28) ~[?:?]
        at com.ur.monitor.model.JointPositionVector.set(JointPositionVector.java:61) ~[?:?]
        at gui.program.position.LegacyPosition.set(LegacyPosition.java:79) ~[?:?]
        at gui.program.position.LegacyPosition.set(LegacyPosition.java:92) ~[?:?]
        at gui.polyscope.setup.treenodes.geom.GeomPoseNode.setSpatialPose(GeomPoseNode.java:278) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl.doUpdateFeature_aroundBody8(FeatureContributionModelImpl.java:109) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl$AjcClosure9.run(FeatureContributionModelImpl.java:1) ~[?:?]
        at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:149) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.InterceptionUtils$1.proceed(InterceptionUtils.java:18) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.AbstractArgumentInterceptor.invoke(AbstractArgumentInterceptor.java:43) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.InterceptionUtils.intercept(InterceptionUtils.java:15) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.StringNotNullOrEmptyAspect.aroundAnnotatedMethod(StringNotNullOrEmptyAspect.java:18) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl.doUpdateFeature_aroundBody10(FeatureContributionModelImpl.java:103) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl$AjcClosure11.run(FeatureContributionModelImpl.java:1) ~[?:?]
        at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:149) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.InterceptionUtils$1.proceed(InterceptionUtils.java:18) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.AbstractArgumentInterceptor.invoke(AbstractArgumentInterceptor.java:43) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.InterceptionUtils.intercept(InterceptionUtils.java:15) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.NotNullArgumentAspect.aroundAnnotatedMethod(NotNullArgumentAspect.java:18) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl.doUpdateFeature(FeatureContributionModelImpl.java:103) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl.updateFeature_aroundBody2(FeatureContributionModelImpl.java:82) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl$AjcClosure3.run(FeatureContributionModelImpl.java:1) ~[?:?]
        at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:149) ~[?:?]
        at com.ur.polyscope.valueobjects.aspects.UncaughtExceptionAspect.aroundMethod(UncaughtExceptionAspect.java:27) ~[?:?]
        at com.ur.polyscope.geomfeature.urcaps.domain.feature.FeatureContributionModelImpl.updateFeature(FeatureContributionModelImpl.java:80) ~[?:?]
        at com.Oviso.Ovi.impl.OviInstallationNodeContribution.setFeature(OviInstallationNodeContribution.java:1520) ~[?:?]
        at com.Oviso.Ovi.impl.OviInstallationNodeContribution.access$1600(OviInstallationNodeContribution.java:62) ~[?:?]
        at com.Oviso.Ovi.impl.OviInstallationNodeContribution$MyThread.run(OviInstallationNodeContribution.java:3522) ~[?:?]

So to problem solve I just removed the if statement for the update part so that it always tries to update continuously.

	} else {
	// if (!pose.epsilonEquals(featurePose, 0.01, Length.Unit.MM, 0.02, Angle.Unit.DEG)) {
		try{
			featureContributionModel.updateFeature(FEATURE_NAME, pose);
			System.out.println("Updated feature: " + pose.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

Should get a FeatureNotFoundException in the catch if the feature instance has been changed since I did the get, since Pose for sure isn’t null, but I still get the same DefenseCheckException, only now I get it continously.
As I said, mostly it happens on power on and off.

Either way, workaround exists: Replace updateFeature with remove and add. Very ugly, but it’s the only way I could find that always works.

1 Like

I have found the same exception and I have noticed that it is thrown when the pose could not be reached. I think the null subject in the description refers to the joint position vector which could not be generated.

I think this has been solved in the latest polyscope, with support for editing features poses directly and also features at unreachable poses. Please check it out. Release Notes 5.9

1 Like

Hello @Savoia I’m getting the same exception in Polyscope 5.11.10. The DefenseCheckException appears and can’t be caught by any try-catch code.
Deleting and creating the feature instead of updating it directly is possible but does not look nice and smooth. In addition the feature is not being updated on the Move screen: one has to switch to Features and back to Move to get it properly refreshed.
@Ebbe any comments and suggestions here?

Hi @csaba,
Is the pose within reach?
Do you call it from the Swing Gui thread and is the exception consistent?
Ebbe

Hi @Ebbe thanks for the quick response. The error message is consistent. The pose is p[0, 0, -z, 0, 0, 0] located under the robot base (z is the position of a linear actuator where the robot is mounted on) so it’s usually out of reach.
The function call is surrounded by EventQueue.invokeLater so it should be always called from the swing gui thread.
Interesting is that addFeature does not throw the exception for the same pose; the feature can be created but not updated. We have also observed that the log screen (Ctrl-Alt-F9) shows several error messages regarding inverse kinematics not found.
Best regards
Csaba

Thanks @csaba, that sounds like a bug. Is removing and adding a possible workaround for now?

1 Like

Hi @ebbe yes, removing and adding the feature seems to be a possible workaround for now.

1 Like

Hi @Ebbe , has this feature update bug been fixed?

Hi @mike.irlbeck,

Not to my knowledge. So you should utilize the workaround.

Ebbe

Hey @Ebbe. Any update to this? I have had an occasional issue with the “work around”, where it will add a “_1” to the name of my frame; I assume because it thinks the name is already taken.

Hey @iRobot,

I am sorry to hear so. There is currently no plans to fix it😥 How you done anything to separate it in time , so PolyScope is done with removing the old feature before adding the new one?

Maybe two different invokeLater calls or a SwingWorker for creating the new one later?

Ebbe