sticky
Problems with VPL Hands On Lab - Real iRobot won't turn RRS feed

  • Question

  • Hello,

    I have just seen the thread by Klint Killerman  (http://social.msdn.microsoft.com/Forums/en-US/roboticsvisualprogramminglanguage/thread/39eef78a-467d-4688-b55d-6bc414268822#39eef78a-467d-4688-b55d-6bc414268822)  and we are having exactly the same problem. I am reopening it as suggested on the last message of the thread.

     

    We are working with VPL Hands On Lab 7 which works fine in the Create simulation. However when using the real Create (with Bluetooth) the robot stops running the program after any turn. For example, if the command is Rotate Degrees with 45 degrees, it rotates 30 degrees (we see this both looking at the robot and on the debugging window) and stops. The turning around command rotates about 120 degrees, short of the 180 requested. No more commands can be issued. No errors appear. The drive forward and backwards commands work fine though, and we can do the learning part and repeating those actions, if no rotating commands are involved.  

     

    The difference, as Klint pointed out, is that the rotation commands to the Generic Differential Drive are followed by a Wait op (called Wait for drive completion on the diagram), while the drive forward/backward aren’t. It looks like the thing gets stuck waiting for the completion of the Generic Differential Drive.

     

    Again, this works fine with the simulated Create.

    We have tried this using both the iRobot.Drive.manifest.xml and the iRobot.DriveBumper.manifest.xml

    We are using an up to date version of MRDS 4 on windows 7 and communicating with a BAM bluetooth device. 

    Thanks for any answer!


    Wednesday, May 15, 2013 1:38 PM

Answers

  • Hi,

    The bug is caused by the fact that the real irobot service doesn't post a response. It only sends a notification.

    The simulation service posts a response as well as sends a notification.

    You can fix it by modifying the Drive handlers in \mrds\samples\Platforms\iRobot\iRobotServices\RoombaDrive.cs to post responses back to the response port as shown below.

    Be sure to use the user version of the service in your vpl after the fix.

     

     #region Internal Drive Handlers
            /// <summary>
            /// Internal drive distance operation handler
            /// </summary>
            /// <param name="driveDistance"></param>
            /// <returns></returns>
            public virtual IEnumerator<ITask> InternalDriveDistanceHandler(drive.DriveDistance driveDistance)
            {
                switch (driveDistance.Body.DriveDistanceStage)
                {
                    case drive.DriveStage.InitialRequest:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.DriveDistance;
                        SpawnIterator<drive.DriveDistance>(driveDistance, InternalDriveDistanceImpl);
                        break;
    
                    case drive.DriveStage.Started:                    
                        SendNotification<drive.DriveDistance>(_subMgrPort, driveDistance.Body);
                        break;
    
                    case drive.DriveStage.Completed:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        driveDistance.ResponsePort.Post(DefaultUpdateResponseType.Instance);
                        SendNotification<drive.DriveDistance>(_subMgrPort, driveDistance.Body);
                        break;
    
                    case drive.DriveStage.Canceled:                    
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        driveDistance.ResponsePort.Post(Fault.FromException(new Exception("Drive Distance Cancelled")));
                        SendNotification<drive.DriveDistance>(_subMgrPort, driveDistance.Body);
                        break;
    
                }
    
                yield break;
            }
    
            /// <summary>
            /// Internal rotate degrees handler
            /// </summary>
            /// <param name="rotateDegrees"></param>
            /// <returns></returns>
            public virtual IEnumerator<ITask> InternalRotateDegreesHandler(drive.RotateDegrees rotateDegrees)
            {
                switch (rotateDegrees.Body.RotateDegreesStage)
                {
                    case drive.DriveStage.InitialRequest:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.RotateDegrees;
                        SpawnIterator<drive.RotateDegrees>(rotateDegrees, InternalRotateDegreesImpl);
                        break;
    
                    case drive.DriveStage.Started:
                        SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                        break;
    
                    case drive.DriveStage.Completed:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        rotateDegrees.ResponsePort.Post(DefaultUpdateResponseType.Instance);
                        SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                        break;
    
                    case drive.DriveStage.Canceled:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        rotateDegrees.ResponsePort.Post(Fault.FromException(new Exception("Rotate Degrees Cancelled")));
                        SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                        break;
                }
    
                yield break;
            }

     

     

     

    Thursday, June 6, 2013 9:24 PM
    Moderator

All replies

  • To add to the description above:

    - the DriveSquare sample (VPL hands on lab 4) works fine.

    - However the DriveInTriangle (samples/VPL examples/DriveInTriangle) doesn't (same problem: the robot stops as soon as it gets a rotateDegrees request.

    Of the two samples, only the latter uses Wait for Drive completion op. 

    Thursday, May 16, 2013 3:03 PM
  • Thank you for the additional information.

    I am able to reproduce the issue.

    I am taking a look at it and will get back to you soon.

    Saturday, May 18, 2013 2:09 AM
    Moderator
  • Hi, 

    do you have any news re our question? It is important for us to understand what is going on with that sample. Thanks! 

    Monday, May 27, 2013 6:31 PM
  • Hi,

    The bug is caused by the fact that the real irobot service doesn't post a response. It only sends a notification.

    The simulation service posts a response as well as sends a notification.

    You can fix it by modifying the Drive handlers in \mrds\samples\Platforms\iRobot\iRobotServices\RoombaDrive.cs to post responses back to the response port as shown below.

    Be sure to use the user version of the service in your vpl after the fix.

     

     #region Internal Drive Handlers
            /// <summary>
            /// Internal drive distance operation handler
            /// </summary>
            /// <param name="driveDistance"></param>
            /// <returns></returns>
            public virtual IEnumerator<ITask> InternalDriveDistanceHandler(drive.DriveDistance driveDistance)
            {
                switch (driveDistance.Body.DriveDistanceStage)
                {
                    case drive.DriveStage.InitialRequest:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.DriveDistance;
                        SpawnIterator<drive.DriveDistance>(driveDistance, InternalDriveDistanceImpl);
                        break;
    
                    case drive.DriveStage.Started:                    
                        SendNotification<drive.DriveDistance>(_subMgrPort, driveDistance.Body);
                        break;
    
                    case drive.DriveStage.Completed:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        driveDistance.ResponsePort.Post(DefaultUpdateResponseType.Instance);
                        SendNotification<drive.DriveDistance>(_subMgrPort, driveDistance.Body);
                        break;
    
                    case drive.DriveStage.Canceled:                    
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        driveDistance.ResponsePort.Post(Fault.FromException(new Exception("Drive Distance Cancelled")));
                        SendNotification<drive.DriveDistance>(_subMgrPort, driveDistance.Body);
                        break;
    
                }
    
                yield break;
            }
    
            /// <summary>
            /// Internal rotate degrees handler
            /// </summary>
            /// <param name="rotateDegrees"></param>
            /// <returns></returns>
            public virtual IEnumerator<ITask> InternalRotateDegreesHandler(drive.RotateDegrees rotateDegrees)
            {
                switch (rotateDegrees.Body.RotateDegreesStage)
                {
                    case drive.DriveStage.InitialRequest:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.RotateDegrees;
                        SpawnIterator<drive.RotateDegrees>(rotateDegrees, InternalRotateDegreesImpl);
                        break;
    
                    case drive.DriveStage.Started:
                        SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                        break;
    
                    case drive.DriveStage.Completed:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        rotateDegrees.ResponsePort.Post(DefaultUpdateResponseType.Instance);
                        SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                        break;
    
                    case drive.DriveStage.Canceled:
                        _driveState._internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                        rotateDegrees.ResponsePort.Post(Fault.FromException(new Exception("Rotate Degrees Cancelled")));
                        SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                        break;
                }
    
                yield break;
            }

     

     

     

    Thursday, June 6, 2013 9:24 PM
    Moderator
  • Thanks for the answer.
    I made the changes you suggest to \mrds\samples\Platforms\iRobot\iRobotServices\RoombaDrive.cs but see no difference in the real robot's behavior. 

    I am using the \samples\VplExamples\DriveInTriangle sample.

    You say "Be sure to use the user version of the service in your vpl after the fix."  In VPL I use the manifest iRobot.Drive.User.Manifest for the GenericDrive.
    Is there anything else I should do? I have a sense I am missing some other change(s). 

    Thanks!
    Thursday, June 13, 2013 12:57 AM
  • I cannot repro (with Harsha's changes). Could you try adding some logging in the handlers in the RoombaDrive service so we can better diagnose what's going on? Could you also try wiring Faults from GenericDiffDrive to an alert dialog (or temporarily to WaitForDriveCompletion) in VPL so we can see if there's a fault we're just not seeing?
    Thursday, June 13, 2013 1:48 AM
    Moderator
  • I will, but can you confirm that in order to incorporate Harsha's changes all I have to do is: 

    - change the code in \mrds\samples\Platforms\iRobot\iRobotServices\  as he says

    - import iRobot.Drive.User.Manifest for the GenericDrive in  \samples\VplExamples\DriveInTriangle sample

    Do I need to change anything else (apart from the logging you suggest) to incorporate his change? I am confused about that.Once I am sure that is correct, I will add logging as you suggest.

    Thanks! 

    Thursday, June 13, 2013 2:03 AM
  • Yep, just making the code changes above, rebuilding the service, and referencing the newly built version (with "(User)" in the name) should do it.
    Thursday, June 13, 2013 7:15 PM
    Moderator
  • Ok! It works now. Thanks so much!
    Tuesday, June 18, 2013 8:39 PM