|
Accessing COG Variables Through MSRS Anonymous |
17 year
|
I'm trying to create a simple ball following program in Microsoft Robotics Studio using a Lego NXT in conjunction with RoboRealm's image processing. I figure the best way to do this is to use the example Red Object Tracking Module and use the X and Y variables from the Center of Gravity measurement on the red ball. Depending on the values of X and Y, I'll have the NXT steer in the corresponding direction. I figure once I get this program working, I can use it as an example to branch off to bigger and better things.
However, I'm not sure how to access the variables taken from RoboRealm measurements. I have the RoboRealm service start successfully in my manifest file as follows:
------------------------------------------------------------------
<dssp:PartnerList>
<dssp:Partner>
<dssp:Name>realm:RoboRealm</dssp:Name>
</dssp:Partner>
</dssp:PartnerList>
</ServiceRecordType>
<!-- Start RoboRealm -->
<ServiceRecordType>
<dssp:Contract>http://www.roborealm.com/2007/05/interface.html</dssp:Contract>
<dssp:PartnerList>
<dssp:Partner>
<dssp:Service>RoboRealm.Config.xml</dssp:Service>
<dssp:Name>dssp:StateService</dssp:Name>
</dssp:Partner>
</dssp:PartnerList>
<Name>realm:RoboRealm</Name>
</ServiceRecordType>
------------------------------------------------------------------
And in BallFollower.cs I partner the RoboRealm service in order to access it.
------------------------------------------------------------------
using realm = RoboRealm.Proxy;
|...
|...
|...
[Partner("Realm", Contract = realm.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting)]
private realm.InterfaceOperations realmPort = new realm.InterfaceOperations();
private realm.InterfaceOperations realmNotify = new realm.InterfaceOperations();
------------------------------------------------------------------
Finally, I listen for variable updates:
------------------------------------------------------------------
realmPort.Subscribe(realmNotify);
Activate(Arbiter.Receive<realm.UpdateVariable>(true, realmNotify, realmVariableUpdate));
------------------------------------------------------------------
I assume if X, Y, or any variable change then my function realmVariableUpdate will be called. In that function is where the code for determining steering would go. However, that function never gets called. Is there a problem with my code? I have added the RoboRealm.Interface.Y2007.M05.proxy as a reference, and I can view the processed image through the Service Directory. So I know RoboRealm and my manifest are working correctly.
Do you notice anything wrong with my code? Is there a better way to go about this? The only part I'm not sure about is how to access the variables from RoboRealm in MSRS. Any help would be greatly appreciated!
PS- Sorry for the length of this post, but these forums are always really helpful, and I wanted to ensure I was explaining myself adequately.
|
|
|
Tja [3 posts] |
17 year
|
Dear anonymous,
I have been trying the same thing and it's working for me now. At first I tried, like you, to listen for UpdateVariable notifications. But I suspect (please correct me if I'm wrong) that this operation is used to include new variables into roborealm. Instead I poll for the values of eg. COG_X and COG_Y. These are contained within the "Variables" member of the InterfaceState. My solution, I doubt whether it is the most elegant one, is post a Get message on the roboRealm port every say 100 milliseconds. The response to this message is the InterfaceState from which I derive the most recent values of COG_X and COG_Y.
Regards
Tja
|
|
|
Anonymous |
17 year
|
I'm going to try that today. Meanwhile, I emailed the developers after nobody answered this question, and this is the response I received:
---------------------------------------------
Hi,
Yes, you 'theoretically' should be able to subscribe to the RoboRealm
service and receive updates when the variables change ... but we've not
yet added that in to the MSRS code. What version of MSRS are you using?
We plan to make quite a few updates by the end of next week that will
enable that.
STeven.
---------------------------------------------
That was last Friday, so those updates should be coming soon. Meanwhile, I'm going to try your method.
|
|
|
Anonymous |
17 year
|
Tja,
Could you possibly post a quick code example? I've been trying to use your method, but I keep getting errors. Can you show me how you actually post the get message and then access the variables? Hopefully RoboRealm will release an update and show us the best way to go about this soon, but until then, any help you can give me would be greatly appreciated!
~ Kevin
|
|
|
Tja [3 posts] |
17 year
|
Dear Kevin,
Ok, that mail explains a lot. Basically, the intended asynchronouos approach (listening for UpdateVariable notifications) is better than the way I did it, but here it goes:
The code that I wrote is based on the service tutorials 2 and 5 of MSRS. Since the asynchronuous approach is not working you need to actively poll for the Variables member of Interface. Assume that the service I wrote is named NXTCam. The first thing I did is adding a Variables member to my service:
NXTCamTypes.cs :
.
.
using rbr = RoboRealm.Proxy;
.
.
private List<rbr.VariableInstance> _vars;
public List<rbr.VariableInstance> Vars
{
get { return _vars; }
set { _vars = value; }
}
plus an operation that gets the variables:
public class GetNewVariables : Update<GetNewVariablesRequest, PortSet<DefaultUpdateResponseType, Fault>>
{
public GetNewVariables()
: base(new GetNewVariablesRequest())
{ }
}
public class GetNewVariablesRequest
{
public GetNewVariablesRequest()
{ }
}
In the NXTCam.cs I implemented a clock (this part is copied straight from service tutorial 2) and on each "tick" of the clock I post a GetNewVariables message to the service main port. Finally, wihtin the GetNewVariablesHandler a Get message is posted to the roborealm interface retrieving the InterfaceState:
.
private Port<DateTime> _timerPort = new Port<DateTime>();
.
void TimerHandler(DateTime signal)
{
_mainPort.Post(new GetNewVariables());
Activate(
Arbiter.Receive(false, TimeoutPort(100),
delegate(DateTime time)
{
_timerPort.Post(time);
}
)
);
}
[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
public IEnumerator<ITask> GetNewVariablesHandler(GetNewVariables getNewVariables)
{
rbr.InterfaceState state = new rbr.InterfaceState();
Fault error = null;
yield return Arbiter.Choice(
_roboRealmPort.Get(GetRequestType.Instance),
delegate(rbr.InterfaceState response)
{
state = response;
},
delegate(Fault fault)
{
LogError(null, "Unable to retrieve RoboRealmState", fault);
}
);
if (state != null)
{
NxtcamState initState = new NxtcamState();
initState.Vars = state.Variables;
updateScreen(initState.Vars);
PartnerType partner = FindPartner("RoboRealm");
if (partner != null)
{
initState.RoboRealm = partner.Service;
}
Replace replace = new Replace();
replace.Body = initState;
_mainPort.Post(replace);
}
yield break;
}
}
I did not post all the code here, but I guess setting up the connections is kind of straight forward (it looks really similar to the handler function). Currently I am redesigning the handler, but I guess I'll wait to the next release of roborealm (I really like both roborealm and MSRS).
|
|
|
Update? Anonymous |
17 year
|
It looks like they've released the update. However, the code I posted above (in the first post) still doesn't work. It never enters the realmVariableUpdate function. Am I doing something wrong? Also, what is the syntax for actually obtaining a specific variable from RoboRealm?
|
|
|
Tja [3 posts] |
17 year
|
Actually, it will never use the VariableUpdate function. The code I posted is a workaround that is based on a polling mechanism. The function that is used to obtain the Variables member of the roborealm Interface is the Get operation. The response of this message is the state of the roborealm interface. From the state you can access the Variables member and from the Variables member you can access "COG_X" by searching for the variable that has that name.
|
|
|
Anonymous |
17 year
|
Yes, with your code it will never enter the realmVariableUpdate function. But I think they released the update we were talking about (http://www.roborealm.com/downloads/version_log.php). With that update, my code should work without having to poll RoboRealm every so often. Am I wrong about the update, and if not, how do I use the update to my advantage?
~ Kevin
|
|
|
Anonymous |
17 year
|
Hi All,
Sorry for the delay but we just updated the 1.0 MSRS code (1.5 to follow sometime next week) to include the routine that you are looking for. The UpdateVariable routine was not to be used for subscription. This routine has been removed to avoid confusion. Instead a QueryVariable or QueryVariables (multiple variables) has been included to perform this duty. We've include an example below that has been extracted from another program and thus you will need to place all the pieces in the right spots. If there is something missing please let us know. We will be releasing the orchestration code that this snippet is included in sometime later but we wanted to post what we had right now to help avoid unnecessary development.
Note that the variables and image update at the same time. This is due to the fact that variables are normally changed in RoboRealm based on a new image .. thus by default they are in sync.
Also note that the new version of 1.0 can now accept images from MSRS, process them, and send the results back. This entire sequence will be documented sometime soon.
Again, this update is only for 1.0 and not 1.5.
Good luck!
STeven.
using realm = RoboRealm.Proxy;
[Partner("realm", Contract = realm.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]
private realm.InterfaceOperations _realmPort = new realm.InterfaceOperations();
private realm.InterfaceOperations _realmNotify = new realm.InterfaceOperations();
protected override void Start()
{
... your other start code
_realmPort.Subscribe(_realmNotify);
}
public IEnumerator<ITask> GetVariable()
{
realm.QueryVariablesRequest req = new realm.QueryVariablesRequest();
req._names = new List<String>();
// following are the variable to query. CASE does matter!!
req._names.Add("left_motor");
req._names.Add("right_motor");
if (req != null)
{
yield return Arbiter.Choice(
_realmPort.QueryVariables(req),
delegate(realm.QueryVariablesResponse res)
{
// check to see if the variables contain any values ...
if ((res._values[0] != null) && (res._values[1] != null))
{
// we're converting the motor power from 0,255 to -1, 1
leftWheelPower = (float)(Convert.ToInt32(res._values[0]) - 128.0f) / 128.0f;
rightWheelPower = (float)(Convert.ToInt32(res._values[1]) - 128.0f) / 128.0f;
// only send the motor command if the values have changed
if ((lastLeftWheelPower != leftWheelPower) || (lastRightWheelPower != lastRightWheelPower))
{
// spawn something to actually set the motors
//SpawnIterator(SetMotor);
lastLeftWheelPower = leftWheelPower;
lastRightWheelPower = rightWheelPower;
}
}
},
delegate(Fault f)
{
LogError(LogGroups.Console, "Could not query variable!", f);
});
}
}
|
|
|
Anonymous |
17 year
|
Hi again,
My mistake, the new version of MSRS v1.0 is NOT yet released. For those of you that would like to try the above code the following link can be used for downloading the latest version for MSRS 1.0
http://www.roborealm.com/downloads/MSRS_1.0.zip
The main link on the MSRS page will be updated soon.
Thanks,
STeven.
|
|
|
Anonymous |
17 year
|
Ahh, that's so good to know. Also, thanks for the code example, that will be infinitely helpful. I'll be waiting patiently for the 1.5 release. I suppose I could install 1.0, but last time I had both 1.0 and 1.5 installed, unpredictable results occurred.
Anyway, thanks again for letting us know about the update, and the code example. You saved me from hours of looking over my code and becoming paranoid that nothing I'm doing works. I might love you, STeven.
~ Kevin
|
|
|
Anonymous |
17 year
|
Just as an FYI, we now have updated the MSRS 1.5 version to include the needed routines to grab variables from your own MSRS programs. Included in that package is also a GetVariableExample which shows how to grab variables from RoboRealm within the MSRS from your own orchestration programs.
Kevin, thanks for the love! ;-)
STeven.
|
|
|
grabbing from MSRS Anonymous |
17 year
|
How do I use and process images from the simulated webcam in MSRS?
What I want to do is shift between a simluated camera and a real one, to compare processing. Is this possible.
Any code example would be greatly appriciated.
THANKS!!!!
Peter
|
|
|
Anonymous |
17 year
|
Peter,
We just uploaded a newer MSRS_v1.5.zip file that contains a SimulatedRoborealm example that shows how to grab image from the simulator and process it using RoboRealm. It then feeds back the motor coordinates into the simulator to steer the robot. We currently have it configured to steer a Lego NXT towards a yellow cone and then move away for another trial. We will be doing more of a writeup on how to install and get this running but thought that we'd send you a preview before the actual release since you asked.
Attached is the robofile we are using that will need to be loaded in RR prior to running simulatedroborealm in C# express. The program should start the simulator and start communicating with RoboRealm.
Note that you will need to download RR again AND overwrite the current MSRS RoboRealm interface as that needed some tweaks to get it to work correctly.
Good luck and watch for that writeup by tomorrow sometime.
STeven.
program.robo
|
|
|
Anonymous |
17 year
|
Hey everyone, it's Kevin again. I've been really busy working on some other robotics stuff, but I just got a chance today to look at the updated RoboRealm. Everything included is pretty much exactly what I was looking for! The GetVariableExample is an awesome addition, and I really appreciate everybody's support.
However, I'm having a problem getting the project to work. I've downloaded the new RoboRealm and MSRS files, and uninstalled both MSRS and RoboRealm a few times. When I open the file for the first time, the reference to RoboRealm can not be found. If I remove that reference and add it again, it finds it fine.
But my main concern is that when I try to run the project, I get the following errors:
C:\Microsoft Robotics Studio 1.5 (CTP May 2007)\samples\Platforms\RoboRealm\GetVariableExample\GetVariableExample.cs(65,19): error CS0234: The type or namespace name 'ExecuteProgramRequest' does not exist in the namespace 'RoboRealm.Proxy' (are you missing an assembly reference?)
C:\Microsoft Robotics Studio 1.5 (CTP May 2007)\samples\Platforms\RoboRealm\GetVariableExample\GetVariableExample.cs(65,61): error CS0234: The type or namespace name 'ExecuteProgramRequest' does not exist in the namespace 'RoboRealm.Proxy' (are you missing an assembly reference?)
C:\Microsoft Robotics Studio 1.5 (CTP May 2007)\samples\Platforms\RoboRealm\GetVariableExample\GetVariableExample.cs(70,24): error CS0117: 'RoboRealm.Proxy.InterfaceOperations' does not contain a definition for 'ExecuteProgram'
C:\Microsoft Robotics Studio 1.5 (CTP May 2007)\samples\Platforms\RoboRealm\GetVariableExample\GetVariableExample.cs(98,19): error CS0234: The type or namespace name 'QueryVariablesRequest' does not exist in the namespace 'RoboRealm.Proxy' (are you missing an assembly reference?)
C:\Microsoft Robotics Studio 1.5 (CTP May 2007)\samples\Platforms\RoboRealm\GetVariableExample\GetVariableExample.cs(98,57): error CS0234: The type or namespace name 'QueryVariablesRequest' does not exist in the namespace 'RoboRealm.Proxy' (are you missing an assembly reference?)
C:\Microsoft Robotics Studio 1.5 (CTP May 2007)\samples\Platforms\RoboRealm\GetVariableExample\GetVariableExample.cs(106,32): error CS0117: 'RoboRealm.Proxy.InterfaceOperations' does not contain a definition for 'QueryVariables'
C:\Microsoft Robotics Studio 1.5 (CTP May 2007)\samples\Platforms\RoboRealm\GetVariableExample\GetVariableExample.cs(107,36): error CS0234: The type or namespace name 'QueryVariablesResponse' does not exist in the namespace 'RoboRealm.Proxy' (are you missing an assembly reference?)
So for some reason my RoboRealm does not contain any of the references for ExecuteProgram or QueryVariables. Am I doing something wrong? I've followed the steps and I seem to have all of the files in the correct directories, but for some reason I can't get it to work. I feel like I'm so close to having everything working!
Has anybody else seen this problem, or is it just me doing something wrong? Hopefully I'll be able to figure it out by tomorrow. Again, thanks for everybody's help!
~ Kevin
|
|
|
Anonymous |
17 year
|
Kevin,
It looks like it is picking up the older version of the RoboRealm MSRS interface. ExecuteProgram and the other missing references were not in the previous version. Try opening up the Interface project using C#, compile and run that. That should hopefully update all the internal references. Then try to run GetVariableExample once again.
STeven.
|
|
|
Anonymous |
17 year
|
Thanks so much (again)! Everything works perfectly. I'm not sure why my MSRS wasn't using the new version of RoboRealm, but oh well, it works now!
One last (hopefully) question though, am I supposed to have RoboRealm already open before I run the program? If I just run the program, it launches RoboRealm and the correct program request, but never enters the UpdateFrame handler. However, if I step through the program using breakpoints, it works exactly as expected. Also, if I open RoboRealm and then run the program, it works fine. Is that how it's supposed to behave? It works fine as long as I open RoboRealm or step through the program, but shouldn't it launch RoboRealm itself and receive the UpdateFrame as well?
As always, I appreciate your help!
~ Kevin
|
|