求助大神一个关于机器人编程的问题。Microsoft robotics developer studio 和 C#
我在学习机器人编程的时候遇到一个难题了。情况是这样的,Microsoft 有个软件叫做 Microsoft robotics developer studio (MRDs), 然后在这个软件里面有一些例子代码(sample code)可以让我们学习,他们的官方也提供这些教程讲解这些东西。然后我花费了很多时间之后,终于可以让模拟环境(simulation environment)运行起来。这样就可以不用买真实的机器也可以自学和改进编程。
原本的code是只能控制前进,后退,左转,右转,还有停下。我在原有的code那边又加了一个按键,就是path(路径)。因为我想让机器人走一个固定的路径,而不是让我们去控制机器人前后左右的移动。
那么在产生弄这个的时候,我用了2种办法。
第一种办法就是通过设置时间,然后在这个固定的时间之类,机器人完成一定的路径。这个办法的缺点就是没有办法精确机器人走多远和旋转的角度(可能有计算的方法,但是暂时我不知道,而且感觉处理器的负担也很大,因为要一直计算着时间。)
第二种办法,就是我现在正在尝试的,那就是设置固定的距离,速度, 还有旋转的角度。
这个办法的好处就是精确,但问题是,我只能够执行其中一个命令。当我把这走动的距离跟旋转的角度放到loop里面的时候,他只会执行最后一个命令,第一个命令会被直接覆盖掉。
我的问题就是,如果能够解决这个问题?只需要按一下按键,那么机器人就会走你编辑的路径。
在此先谢过大家的帮忙了。谢谢。
以下是我代码(只有最后一部分是我加进去的,其余的是原本 Microsoft 的例子代码):
//-----------------------------------------------------------------------
// This file is part of Microsoft Robotics Developer Studio Code Samples.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// $File: RoboticsTutorial4.cs $ $Revision: 22 $
//-----------------------------------------------------------------------
using Microsoft.Ccr.Core;
using Microsoft.Ccr.Adapters.WinForms;
using Microsoft.Dss.Core;
using Microsoft.Dss.Core.Attributes;
using Microsoft.Dss.ServiceModel.Dssp;
using Microsoft.Dss.ServiceModel.DsspServiceBase;
using System;
using System.Collections.Generic;
using System.Security.Permissions;
using xml = System.Xml;
using drive = Microsoft.Robotics.Services.Drive.Proxy;
using W3C.Soap;
using Microsoft.Robotics.Services.RoboticsTutorial4.Properties;
using Microsoft.Robotics.Services.Drive.Proxy;
using
namespace Microsoft.Robotics.Services.RoboticsTutorial4
{
[DisplayName("(User) Robotics Tutorial 4 (C#): Drive-By-Wire")]
[Description("This tutorial demonstrates how to create a service that partners with abstract, base definitions of hardware services.")]
[DssServiceDescription("http://msdn.)]
[Contract(Contract.Identifier)]
public class RoboticsTutorial4 : DsspServiceBase
{
[ServiceState]
private RoboticsTutorial4State _state = new RoboticsTutorial4State();
[ServicePort("/RoboticsTutorial4", AllowMultipleInstances=false)]
private RoboticsTutorial4Operations _mainPort = new RoboticsTutorial4Operations();
[Partner("Drive", Contract = drive.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting)]
private drive.DriveOperations _drivePort = new drive.DriveOperations();
private drive.DriveOperations _driveNotify = new drive.DriveOperations();
public RoboticsTutorial4(DsspServiceCreationPort creationPort) :
base(creationPort)
{
}
#region CODECLIP 02-1
protected override void Start()
{
base.Start();
WinFormsServicePort.Post(new RunForm(StartForm));
#region CODECLIP 01-5
_drivePort.Subscribe(_driveNotify);
Activate(Arbiter.Receive<drive.Update>(true, _driveNotify, NotifyDriveUpdate));
#endregion
}
#endregion
#region CODECLIP 02-2
private System.Windows.Forms.Form StartForm()
{
RoboticsTutorial4Form form = new RoboticsTutorial4Form(_mainPort);
Invoke(delegate()
{
PartnerType partner = FindPartner("Drive");
Uri uri = new Uri(partner.Service);
form.Text = string.Format(
Resources.Culture,
Resources.Title,
uri.AbsolutePath
);
}
);
return form;
}
#endregion
#region CODECLIP 02-3
private void Invoke(System.Windows.Forms.MethodInvoker mi)
{
WinFormsServicePort.Post(new FormInvoke(mi));
}
#endregion
/// <summary>
/// Replace Handler
/// </summary>
[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
public virtual IEnumerator<ITask> ReplaceHandler(Replace replace)
{
_state = replace.Body;
replace.ResponsePort.Post(DefaultReplaceResponseType.Instance);
yield break;
}
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
//stop
public virtual IEnumerator<ITask> StopHandler(Stop stop)
{
drive.SetDrivePowerRequest request = new drive.SetDrivePowerRequest();
request.LeftWheelPower = 0;
request.RightWheelPower = 0;
yield return Arbiter.Choice(
_drivePort.SetDrivePower(request),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to stop", fault);
}
);
}
//forward
#region CODECLIP 01-3
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
//forward
public virtual IEnumerator<ITask> ForwardHandler(Forward forward)
{
if (!_state.MotorEnabled)
{
yield return EnableMotor();
}
// movement speed
// This sample sets the power to 75%.
// Depending on your robotic hardware,
// you may wish to change these values.
drive.SetDrivePowerRequest request = new drive.SetDrivePowerRequest();
request.LeftWheelPower = 0.5;
request.RightWheelPower = 0.5;
yield return Arbiter.Choice(
_drivePort.SetDrivePower(request),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to drive forwards", fault);
}
);
}
#endregion
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
// backup speed
public virtual IEnumerator<ITask> BackwardHandler(Backward backward)
{
if (!_state.MotorEnabled)
{
yield return EnableMotor();
}
drive.SetDrivePowerRequest request = new drive.SetDrivePowerRequest();
request.LeftWheelPower = -0.6;
request.RightWheelPower = -0.6;
yield return Arbiter.Choice(
_drivePort.SetDrivePower(request),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to drive backwards", fault);
}
);
}
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
// left turn speed
public virtual IEnumerator<ITask> TurnLeftHandler(TurnLeft turnLeft)
{
if (!_state.MotorEnabled)
{
yield return EnableMotor();
}
drive.SetDrivePowerRequest request = new drive.SetDrivePowerRequest();
request.LeftWheelPower = -0.5;
request.RightWheelPower = 0.5;
yield return Arbiter.Choice(
_drivePort.SetDrivePower(request),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to turn left", fault);
}
);
}
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
// right turn speed
public virtual IEnumerator<ITask> TurnRightHandler(TurnRight forward)
{
if (!_state.MotorEnabled)
{
yield return EnableMotor();
}
drive.SetDrivePowerRequest request = new drive.SetDrivePowerRequest();
request.LeftWheelPower = 0.5;
request.RightWheelPower = -0.5;
yield return Arbiter.Choice(
_drivePort.SetDrivePower(request),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to turn right", fault);
}
);
}
#region CODECLIP 01-4
private Choice EnableMotor()
{
drive.EnableDriveRequest request = new drive.EnableDriveRequest();
request.Enable = true;
return Arbiter.Choice(
_drivePort.EnableDrive(request),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to enable motor", fault);
}
);
}
#endregion
#region CODECLIP 01-6
private void NotifyDriveUpdate(drive.Update update)
{
RoboticsTutorial4State state = new RoboticsTutorial4State();
state.MotorEnabled = update.Body.IsEnabled;
_mainPort.Post(new Replace(state));
}
#endregion
// Here is where I had change the code.
#region Test Code (Creating Path)
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
public virtual IEnumerator<ITask> PathHandler(StartPath path)
{
if (!_state.MotorEnabled)
{
yield return EnableMotor();
}
for(int i=1; i<3; i++)
{
if(i == 1)
{
drive.DriveDistanceRequest distance = new drive.DriveDistanceRequest();
distance.Power = 1;
distance.Distance = 1;
yield return Arbiter.Choice(
_drivePort.DriveDistance(distance),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to turn left", fault);
}
);
}
else if(i == 2)
{
drive.RotateDegreesRequest rotate = new drive.RotateDegreesRequest();
rotate.Power = 1;
rotate.Degrees = 90;
yield return Arbiter.Choice(
_drivePort.RotateDegrees(rotate),
delegate(DefaultUpdateResponseType response) { },
delegate(Fault fault)
{
LogError(null, "Unable to turn left", fault);
}
);
}
}
}
#endregion
}
}