Issue detecting wall with Sonic Sensor

This is where you talk about the NXJ software itself, installation issues, and programming talk.

Moderators: roger, 99jonathan, imaqine

Issue detecting wall with Sonic Sensor

Postby Ydoow » Tue Feb 12, 2013 12:32 am

I'm making a small robot, 2 wheels and 1 Sonic Sensor connected to the end of a motor, to give myself practice/experience with obstacle avoidance and decision making.
As it stands, my code seems needlessly spread out among classes. I'm not an experienced programmer yet, but I'm trying to "future proof" my project thinking that I may add a lot more to the code as time goes on and separating it all now is better than later.

What should happen: The robot should approach some obstacle like a wall. Once closer than 20 (cm?) it should stop. Then it will turn left, scan for distance: if distance is greater than 50(cm?) move forward. Else, then Turn 180 degrees (a right turn from the original stopped position), scan for distance: if distance is greater than 50 move forward. Else, turn 90 degrees right (180 degrees from original stopped position), scan for distance: if distance is greater than 50 move forward.
(If that is false, the robot just sits in place "broken" so to speak. I'm okay with that for now)

What actually happens: The robot approaches a wall, and when closer than 20 it stops. It turns left, then always turns 180 around. Then always turns right, then always stops and sits there. Waving my hand in and out from the sensor afterward has no effect.
It seemingly is unable to detect any walls during the turning portion, however is able to detect walls while in motion at the start of the program.

Class description/explanation:
The SonicSensor class (_ss) implements FeatureListener and is registered with the RangeFeatureDetector. I use this to constantly check distances up to length 100 (is this cm?)
It calls a secondary method 'getDistance()' I created, which simply calls the UltrasonicSensor's getDistance() method but with a 50ms Thread.sleep before returning the value.


MotionLogic (_ml) is where the project makes the decisions utilizing data from other classes. The method call 'checkDistance' decides if the robot is too close and needs to stop.

Code: Select all
public class SonicSensor implements FeatureListener{

   private UltrasonicSensor _us;
   private FeatureDetector _fd;
   private MotionLogic _ml;

   public SonicSensor(UltrasonicSensor us, FeatureDetector fd, MotionLogic ml)
   {
      _us = us;
      _fd = fd;
      _fd.addListener(this);
      _ml = ml;
   }

   @Override
   public void featureDetected(Feature feature, FeatureDetector detector)
   { _ml.checkDistance(getDistance()); }  //checks distance, and sets _distance value in MotionLogic iff object is detected in front
       
   public int getDistance()
   {
      int d = _us.getDistance();
      try { Thread.sleep(50); }
      catch(InterruptedException ex) {}
      return d;
   }
}


The next code is from MotionLogic, I'm leaving out the constructor as it's lengthy.

MotionControls (_mc) is full of methods that define the robot's movements, a couple of calls are made to that in the following.

checkDistance(int distance) decides if the robot is too close and should take action. If it is, it calls the method avoid()
This part works properly with the robot. It does stop when it gets too close to a wall. Meaning it makes a correct evaluation of distance, and in fact calls 'avoid()' and executes the first line (at least) of 'avoid()'

The lines following that don't seem to give the desired effect.


Code: Select all
public class MotionLogic {
   
   public void checkDistance(int distance) //_fd will not start report unless an object is detected.
                                   //That is, if nothing is within range, it will not trigger checkDistance()
   {
      _distance = distance;   
      if(_distance < 20) { avoid(); }
      else        { _mc.forward(); }
   }
   
   public void avoid()
   {
      _mc.stop(); //stop wheels
      _fd.enableDetection(false); //prevents call to checkDistance(). _range will still be updated
      
      _mc.turnLeftInPlace90();
         if(_ss.getDistance() > 50) { _fd.enableDetection(true); return; } //restarts checkDistance call and breaks method.
         
      _mc.turnRightInPlace180(); //equivalent of a right turn from original position
         if(_ss.getDistance() > 50) { _fd.enableDetection(true); return; }
      
      _mc.turnRightInPlace90(); //equivalent of 180 turn from original position
         if(_ss.getDistance() > 50) { _fd.enableDetection(true); return; }
         
         //Need a final alternative if the first 3 fail?
   }
   
   public void setRange(int range) //I guess I'll keep this so other classes can manipulate this value. Perhaps to 'trick' this class.
   {                        //_mc has getRange() accessor for most other purposes though.
      _distance = range;
   }
}


I disabled the RangeFeatureDetector while the code is turning the robot. My thought is that having it constantly detect objects could cause conflicts like trying to call avoid() twice or something.
I set this up so I don't need it though. The second method in SonicSensor 'getDistance' isn't (as far as I understand it) a part of the RangeFeatureDetector and can be called at any time.

Remember how I said "Waving my hand in and out from the sensor afterward has no effect." at the top? Well if I switch my > symbols, waving my hand in and out from the sensor will cause the robot to begin moving forward again after doing all his turns and coming to a halt. It does NOT change any of the previous outcomes of the program.

To determine this wasn't an issue with disabling/enabling the FeatureDetector, I tried adding a _mc.forward() method call inside the if() brackets.
This would mean that even the last one should be called (it came from a direction with no object behind him) and detect no object, returning a distance of 255 (distance() returns 255 if nothing is seen). Regardless if FeatureDetector became broken from the disabling, or it won't trigger checkDistance() because it can't see anything, the robot should move forward.
But it does not.

So the issue seems to be with the SonicSensor returning a proper distance. Or in the distance() method returning values I'm not anticipating.
But then again, this works just fine in checkDistance()

What's worse, I actually had this working before, but after making a bunch of changes to other classes, I started getting the issue I'm describing now.
I quite honestly have no idea what the code was like before, I made a lot of changes. But I really, truly, honestly made no changes to the code in avoid() which is why I'm so surprised and frustrated that it's giving me problems now :evil:

I hope my short novel gave you enough information to help me :lol:
Ydoow
New User
 
Posts: 4
Joined: Sun Jun 03, 2012 3:33 pm

Re: Issue detecting wall with Sonic Sensor

Postby gloomyandy » Tue Feb 12, 2013 9:10 am

First off you should consider using some form of source code control system or backups so that you can always go back to older versions.

Secondly are you sure that your code to disable distance checking is actually working I see no evidence that it is from the code above.

Thirdly you probably need to do more work on sorting out what is going wrong. It is too hard to help with only part of the story. You may want to consider adding logging code using smething like the leJOS RConsole classes to help you work out what is happening.

Andy
User avatar
gloomyandy
leJOS Team Member
 
Posts: 3004
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK


Return to NXJ Software

Who is online

Users browsing this forum: No registered users and 0 guests

more stuff