User Tools

Site Tools


turtlebot:adventures:sensing101_hints

Sensing 101 Hints

Bumper Events

The button callback code should be pretty self-explanatory. The main thing is to create your own subscriber, then to use rostopic echo and rostopic type to understand the structure of the bumper events enough to create a properly modified version of the button callback function (the direct link to the Turtlebot github code also provides this information and defines some constants that might be of interest). This code should then be re-used and modified for the next learning task.

Bumper Events for Safe Forward Motion

What this requires is two variables to be added to your goforward class. One for the safety state in the finite machine, and one to keep track of the bumpers that are hit. Call the first one safety and the second one bhit.

Use the bits in bhit to keep track of which bumpers were hit. The first bit can be the left bumper, the second bit the middle bumper, and the third bit the right bumper. The bits toggle based on the event message for the bumpers.

The safety state then should have three states, let's order them as 0, 1, and 2. In state 0, the robot should be moving forward so long as (bhit is equal to 0). Having any bumper be hit (so that bhit > 0) should immediately trigger state 1. If the bumpers cease to be hit when in state 1 (bhit equals 0 again) should trigger state 2. Pausing fully without hits in state 2 should then return to state 0. Some of this logic gets implemented in the bumper callback function (the hit part), some of it is in the infinite loop for the robot forward motion (the finite state machine logic).

Drawing a state diagram for the finite state machine should clarify what is involved. Try to get it working for a single sensor (say the bump sensor), then work it out for two sensors (bump and wheel drop). If you do so, then you should see that the main logic is predicated on a boolean value that checks the hit and drop statuses (you can even go crazy and add in the cliff sensor status).

Gyro-Based Forward Motion

The adventure here is to try to keep the orientation of the robot constant. It is not quite the same as going straight since that means following a very specific line. Nevertheless, if the orientation is able to stay constant, the if the desired line is not followed then a parallel line will be followed that is very close to the original desired line. For us that will be close enough (when eyeballing it).

The main trick here is the implementation since the error feedback has already been described. If a subscriber with callback is defined for the Odometry topic, then one has access to the current pose. The pose data has an orientation quaternion that should be converted to a complex number within the callback. In fact, all of the error feedback math should be implemented within the callback. Even building up the twist command and its publication to the Navigation message subscriber. The python code in the construction should then just call the ROS spin command to relinquish control and let the callbacks do their magic. The spin command is basically a “wait until it is time to exit” command.

Some turtlebots are actually quite decent at driving straight, while some will veer quite quickly. If you have a turtlebot that's good at driving straight and you want to see the controller in action, you'll have to give it a little nudge when it is running to perturb it away from its forward motion. It should turn back properly.

Gyro-Based Turning

The solution is quite similar to the drive straight one above, but the twist should not include forward motion. That means the linear parts won't be set, only the angular parts. Also, rather than set the desired orientation to be at 0 degrees (which is the same as $1+j0$), you should set it to turn 90 degrees (which is $0 + j$). If you want to turn to some other angle, then set $z_{des} = e^{j \theta_{des}}$ and you'll be good to go.

Gyro-Based Square Drawing

This one combines the above two and uses a finite state machine to alternate between them. The finite state machine should have four states it seems. One state is for forward driving and uses the gostraight feedback control algorithm above modified to regulate the forward velocity. Another is for pure turning and uses the turninplace feedback control algorithm. What about the other two?

Well, I think they should be to transition from forward driving state to the turning (and vice-versa). that means the system would really be state 1, prepare for straight driving and identify goal; state 2, perform straight driving to a specified goal; state 3, prepare for turning by identifying goal; state 4, perform turning to a specified orientation. When state 4 terminates, then it goes back to state 1. A combination of a while loop with a finite state machine (operating at a certain rate) and a series of odometry subscribers with different callbacks should be employed.

Prior to the drive straight, one needs to grab the current robot position, figure out the relative forward location that it needs to go to, then define all the proper variables for use in the callback. Once defined, the system can transition to the drive straight. Here, there needs to be a feedback controller to do that. In addition to ensuring straight progress via turn feedback control, the forward velocity should also have some feedback based on how close it is to the goal. Once it is “close enough” to the goal then it should transition to the next state (which should be turn in place preparation).

Likewise, prior to the turn in place, one needs to grab the current robot pose, figure out the relative orientation that it needs to go to in absolute odometry terms, then define the proper variables for use in the callback. Here, nothing special beyond what was already done in the turninplace adventure is needed except to recognize when to terminate this finite state and move to the next one.

If you do the above, the Turtlebot may drive in a square forever unless you keep track of the amount of times you've driven forward and turned. If you do so, then you can figure out an additional terminating condition that could be triggered to end the square maneuver. This would be extra, but good to figure out.

When you want to grab the current state (pose) of the Turtlebot but don't want to have to create a subscriber, then it is possible to simply request the information using wait_for_message:

  msg = rospy.wait_for_message("my_topic", MyType)

The msg variable (or whatever you call it) will have the data associated to the topic. Mind you it may wait a bit for the latest data to be made available (depending on the message and its publication frequency).

Also, when you want to stop subscribing to something, there is a function called unregister that will do the trick. You need to have the subscriber object available to you though. The way to do that is to save the subscriber when you start it. As an example, for kobuki_button code one would do:

  subButtons = rospy.Subscriber("/mobile_base/events/button",ButtonEvent,self.ButtonEventCallback)

  ... some code here ...
  
  subButtons.unregister()

Once the topic has been unregistered, the callback will no longer be called. More generaly the subscriber will have been killed. To start appears to require re-instantiating a new subscriber and overwriting the subButtons object with the newly created one.


Sensing 101

turtlebot/adventures/sensing101_hints.txt · Last modified: 2024/08/20 21:38 by 127.0.0.1