OpenSteer port for MonkeyBrains

I understand that the main thrust of the discussion here is about a general agent framework, but I just wanted to follow up on the porting (and possible further development) of OpenSteer, and I think this is the best place to do so.

@sevarac said: @shoga

The nice thing with having steering implemented as agent behaviours is that we can easily try, test and replace or evolve them.

I’m sorry if this is a silly question (I’m still learning about software engineering practices) but isn’t the downside of this approach that the steering library would be coupled with the agent system? I was thinking that it would be nice to have a steering library that could be used with the AI engine, but could also be used on its own. It seems that many games could benefit from steering behaviours but wouldn’t need fully-fledged AI. (Say a fast-paced top-down shooter in which the enemies only have one goal - attack - and no complex decisions to make).

I also wanted to take the opportunity to mention @Momoko_Fan and @Sploreg - I’ve been exploring the jME codebase and community, and it seems that you guys might be in a good position to give some additional advice on how best to either add additional steering behaviours to jME or create and integrate a java steering library.

I’ve also discussed this with my course director at university, and we’ve agreed that I can work on steering behaviours for my MSc too. This means that I can hopefully contribute something in this area to jME long-term, whether the GSoC proposal is successful or not.

I took the liberty of splitting your topic @shoga :slight_smile: We wanted to move this project to its own board where it can have multiple discussion topics, and now seemed like the right time.

I’ll just open a can of mentions to @sevarac , @Momoko_Fan and @sploreg to make sure there’s no mixup.

You make a good point about the coupling with the agent system, I’m curious myself.

1 Like

Decoupling is usually best done by defining an API that has as few operations as possible, and the understanding that one side implements and the other side consumes that API.

The “as few operations as possible” part is important because it eases the burden of implementation - a complicated API tends to be implemented incorrectly (see JDBC for an example, Hibernate’s Session interface is even worse).
Of course, the fewer operations you have, the harder it is to guarantee sufficient control. You know you found a good place for an API if you find that you can condense a whole lot of functionality behind a very narrow API.

Sometimes an API can’t be made as narrow or easy as one would wish. In that case, liberally add unit tests so API implementors know when their work is done. Set up a hall of shame that exhibits the number of failing tests for each implementation (and explain that if there are multiple implementations, unit test coverage is one of the things users will select their libraries from). Make sure that the unit tests cover each and every case that might be relevant to a caller.

Steering doesn’t have to be coupled with AI. The AI can feed it information, but the steering is simple enough where it shouldn’t affect whatever AI is going on.

I haven’t looked at OpenSteer in a while but I assume the API is decent. Steering is pretty easy to implement so a viable option would be to port it to java. Or it could be used directly with native bindings. Going the native route means that the AI will have to adhere to the lib’s rules and API, which probably isn’t a bad thing.

When I use steering I often have to combine their rules in code to get the desired result, sort of a custom approach. That’s why I have stuck writing it myself in java. Of course my code is specific for my purposes and isn’t for everyone. I don’t know if it is more work to bind OpenSteer natively or to copy it into java.

If this is a port, why not 1to1 just use the api the native version uses with only essential modifications, that way all old manuals / documentation can be reused 1 to 1.

Good idea Empire.

It looks like a lot of the code in OpenSteer is support code: vectors, terrain, color, camera, etc. So it could be as easy as just copying the classes in the ‘plugins’ dir. Meh, actually looking at it I’m not sure how clean or modular the code is. Which is what I found ended up happening when I was implementing specific steering. However I did pull it apart enough where different forces could be generated and added together so you could at least chain and combine various steering behaviours together.

I’m kinda thinking out loud as I scan the code, sorry if I jump around.

I guess the issue for me is that it doesn’t have to be just a port. This is related to my degree, so I’m happy to develop opensteer further rather than just port it. I’m on my phone now, but I’ll follow this up with a more detailed post later…

@Sploreg said: I haven't looked at OpenSteer in a while but I assume the API is decent. Steering is pretty easy to implement so a viable option would be to port it to java. Or it could be used directly with native bindings.

If a port is desired:

The web page has applets.
These can be reverse engineered using JD or something similar. Not for the purpose of copying the code (that would be a copyright infringement), but to see how a Java design should look like, and to port the C++ stuff to java. Assuming such a port is desired.

Most of the C++ code on the SF repository seems to be for displaying the resultant behaviour. Plus an in-memory “database” (spatially-indexed data structure, I think) so that finding the nearest neighbours (other agents and obstacles) is efficient.
Nothing of this looks like rocket science, I guess the most interesting part of steering is which kinds of local rules generate what kinds of emergent behaviour, so a game designer who wants to model a flock of birds can select the rules that will do that.

Maybe the API is just two single-function interfaces.
One for a proximity database object, one for steering behaviours.
Hm. Wait. Probably a different API for each steering behaviour. No need to make that unified. The steering behaviours just need the proximity DB as input, but what other inputs they need and what effects or return values they have could be left to the choice of the steering behaviour implementer - I suppose some steering behaviours need more data than others.

@Sploreg said: Steering doesn't have to be coupled with AI. The AI can feed it information, but the steering is simple enough where it shouldn't affect whatever AI is going on.

yes, this is the way I imagined it should be: steering behaviours shouldn’t know or care where the info is coming from.

@toolforger said: The "as few operations as possible" part is important because it eases the burden of implementation - a complicated API tends to be implemented incorrectly (see JDBC for an example, Hibernate's Session interface is even worse).

Absolutely. I’ve seen some bizarre things done with JDBC because of this very issue! Although I think, as you suggested in a later post, that in the case of steering it should be quite easy to keep this simple, because it’s really just about passing in the locations of targets and obstacles etc.

If I’m planning to do this as a Google Summer of Code proposal, I think there’s no reason why I couldn’t aim for something more ambitious than a port. As @sploreg pointed out, combining behaviours (both effectively and efficiently) presents some extra challenges. So I think it might be better to propose a java steering library based on OpenSteer, rather than a port. Does this sound like a reasonable approach?

Also, I really appreciate all the feedback so far, thanks!

1 Like

@shoga

I’m sorry if this is a silly question (I’m still learning about software engineering practices) but isn’t the downside of this approach that the steering library would be coupled with the agent system? I was thinking that it would be nice to have a steering library that could be used with the AI engine, but could also be used on its own.

The steering library can be entirely decoupled from agent system. As a matter of fact this is the essence of this ide: use agent Behaviours as the wrapper for some existing steering implementation, which does not need to be changed at all. The wrapper should also provide the JME hooks that the steering behaviour needs.
The role of the agent and behaviour system is to provide better structure of the game model at higher conceptual level. And entire agent system should be extremly lightweight and out of the way.

Check out the base behaviour class JMEAI/Behaviour.java at master · sevarac/JMEAI · GitHub

And take the entire working demo GitHub - sevarac/JMEAI
There are 3 agents, one player, and two bots, and one bot is controlled using neural network.
Demo game is in the demo package.
So take any steering behaviour you like, and wrap it in SomeNewBehaviour extends Behaviour { … }
Create agent, add that new behaviour to agent, and add agent to the game.

Cheers
Zoran

2 Likes
@Sploreg said: When I use steering I often have to combine their rules in code to get the desired result, sort of a custom approach.

Do you think that a steering library should include combinations of behaviours? There are probably some fairly common combinations that might be worth including (flee and avoid obstacles, for example). Or perhaps it would be more useful to provide documentation and examples of how to combine behaviours?

Do you think that a steering library should include combinations of behaviours?

I would absolutely say this should be the case, but this could mean two things:

  1. Methods to combine multiple input vectors into one output vector (e.g. averaging, weighted, choose the strongest etc etc)

  2. It could be pre-made “recipes” - that is specific steering behaviours and combination methods to produce a desired emergent higher level behaviour - e.g. a weighted average of flocking, obstacle avoid and goto behaviours to make a flock follow a path.

I think certainly 1) should be the case, though 2) might need only be in examples. However, it’s tricky to draw the line - an obstacle avoiding goto behaviour is quite atomic, and likely to see much reuse, wheras as the flocking/avoiding/goto above might not be. From experience I can say that tuning combinations of behaviours to achieve desired behaviour can be non-trivial however (and may be application specific).

This suggests some further work - e.g. tools to help tune behaviour. This could take the form of perhaps a premade gui with sliders and checkboxes etc you can easily hook into your characters, so you can vary behaviour and combinations easily in realtime.

Of course this is the weakness of reactive agent designs in general - there will always be some things they can’t do, and there is always the risk of large sets of hard-to-debug rules. At this point I think it’s worth considering some meta layer of reasoning atop of steering. Which reminds me of my old thesis which I said I’d get online - I’ll try and remember to do this tonight.

Important update: We are now accepting student applications! You can go to the GSoC site to login and submit your application right now. The earlier the better, because you can come back to your application and edit it after receiving feedback from the mentors.

Yea steering behavious need to be able to be chained together, otherwise it is just copying and pasting code around and rewriting routines.
Different behaviours require different parameters, so the API could be a little messy. Maybe there can be two different classes of behaviours, one with awareness of obstacles and one without. Or the system could just be plumed together with that information already there.

@erlend_sh
thanks for the reminder! I’m already signed up, and I should have a proposal submitted in a day or two. I think that combining behaviours is going to be the hardest part of this. How concrete do my implementation plans have to be at the application stage? There are a few different approaches to combining behaviours, and it’s hard to say which one I’ll end up taking. Is it enough to describe the possibilities and say that I’ll investigate which is best as part of the project?

@shoga said: @erlend_sh Is it enough to describe the possibilities and say that I'll investigate which is best as part of the project?
That should suffice. You can keep it fairly high concept; we'll provide comments if we want more info.
Do you think that a steering library should include combinations of behaviours? There are probably some fairly common combinations that might be worth including (flee and avoid obstacles, for example).

Definitely. The way I see it, we can have simple and complex behaviours, where complex behaviours consists of few simple (or other complex) behaviours, and act as the controller for its sub-behaviours. Its a typical approach in agent systems. The controller behaviour may implement various strategies/tactics for controlling its sub-behaviours.

Better late than never, I’ve updated my online stuff. You can read about my work on steering here:

(and my other work, should you be interested or have too much time on your hands :wink:

In particular, some of my MEng thesis might be interesting - the lit. review section for an overview on reactive control/steering, and p32 onward describes the atomic behaviours (combinations of steering behaviour) I found useful. Their parameters are also listed which might help by serving as an example of what an API might need to provide for steering.

You’ll note in this work I combined the steering behaviours (to make the above atomic behaviours) using simple FSMs, they’re all documented in there from p33 on. Some are robocup specific, but in general they give an idea how one might specify steering combinations. Of course, I’m biased - you may dislike my presentation :slight_smile:

I appreciate it’s not very software-engineering-y :slight_smile: In my defence I’m not a software engineer (which is what’s needed for a good API or library), I’m a computer scientist, so of course it’s more about the science.

3 Likes

thanks, @sevarac and @the_accidental for some more great advice on combining behaviours. I can tell this is going to be the most interesting part of the project, because there are a few different approaches, each with benefits and drawbacks…

Very nice, @the_accidental .

Don’t worry about engineering, that can be combined - the science makes a library powerful, the engineering makes it usable, that’s the idea.

From a software engineering perspective, separating practical reasoning from social reasoning makes sense.
Environments tend to be far more static (rocks don’t change behaviour that often), plus social reasoning can be recursive (my expections about that person can be influence by that person’s expectations about me).
So it’s a split I’d do instinctively (i.e. based on experience with design in general, not based on experience with agent systems, so it may still be grossly wrong). That’s probably not the same reasons that led you to your approach - which is good, because the more approaches converge on a similar design, the more likely there’s a viable design at the end.

The proof of the pudding is in the eating, of course.
I.e. good research notwithstanding, the approach might still turn out to be unfeasible with good engineering practices. I do not think that failure is a likely outcome actually, but until the approach has been tried and designed, we can’t be sure.

Your web server is very slow. Downloading the 1-MB PDF takes a minute (less than 9k per second), that’s gross.
Also, the DNS records for the servers involved are misconfigured (PTR records are wrong).
I’m not sure what’s going on, wordpress.com should be competent but this doesn’t look like it.

One of the links on your page is behind a paywall, so not everyone will be able or willing to follow it.