[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Billiards-devel] Programming experiments with Billiards
From: |
Tadej Janež |
Subject: |
Re: [Billiards-devel] Programming experiments with Billiards |
Date: |
Thu, 14 Jan 2010 12:25:37 +0100 |
Hello Dimitris,
firstly, a big thank you for a quick and comprehensive reply!
On Tue, 2010-01-12 at 15:09 +0200, Dimitris Papavasiliou wrote:
> what you want to do makes sense and should be possible relatively
> easily. In fact, it was what Billiards was designed for. There will
> be some scripting involved though. How much Lua do you know?
None at all, but I find it quite similar to Python (which I use almost
all the time) so I didn't have much difficulties reading and changing
your code. I could even say that I like it so far.
> The initial setting you describe would be a bit of a problem right
> now. It's fairly easily done by hacking the internals of Billiards
> but not by just *adding* some code as it should be done. During the
> development of Billiards I needed to perform some experimentation in
> order to determine whether the physics simulator actually produced the
> correct results (to my surprise, it actually did without requiring any
> special tweaking). So I created an experimentation mode which
> featured only one white ball on a Carom table. You could then easily
> perform squirt experiments etc. That's all I needed back then but it
> seems now that I'll have to expand experimentation mode so that you
> can somehow describe which balls you want at startup and where you
> want them placed. I should be able to make the necessary changes soon
> so I'll send you a patch and instructions on how to do what you want
> then. In the meantime, let's focus on the rest. (You can start
> Billiards in experimentaion mode btw with the -Oexperiment flag).
In the mean time I set up Billiards as a CVS Project in Eclipse IDE and
started experimenting with your code. I followed the changes you made
for 'options.experiment' and created my own 'option.experiment2', which
creates the initial setting I want. It's a quick hack, so if you can
provide a better solution, I'm all for it.
> Now regarding the second point: sidespin, folllow and elevation should
> be easy to setup but "shot force" is not really. The problem is that
> it's difficult to even define what this "shot force" would be. During
> the short time that collision between the cue tip and ball takes place
> a force is exerted on the ball by the tip but as all impact forces
> it's hard to determine what it is and it's not constant anyway. This
> is in the "simple" case where the tip or ball does not flex, which of
> course does happen. So in short you can apply a force to the ball at
> a specific offset and elevation instead of actually whacking it with
> the cue but this would probably not produce the desired results. If
> however all you need is to be able to perform a set of shots with the
> same force or with "more" or "less" force there are things you can
> do.
Ok, I see, thanks for explaining that.
> Now if you want to change some of this, presumably the shot parameters
> the best way to go about it would be this:
>
> local oldreset
>
> oldreset = billiards.aiming.reset
>
> billiards.aiming.reset = function ()
> -- First call the old function to setup the default
> -- behavior we don't want to change.
>
> oldreset()
>
> -- Now change what we don't like.
>
> bodies.cue.elevation = math.pi/4
> bodies.cue.sidespin = billiards.ballradius * 0.3
> bodies.cue.follow = -0.003
>
> end
Ok, perfect. This is what I needed.
Now, I tried setting observer's position with something like:
bodies.observer.longitude = -1.42
bodies.observer.latitude = -0.71
bodies.observer.radius = 0.4
bodies.observer.elevation = math.pi / 2 -
bodies.cue.elevation -
math.rad (5)
but it didn't work. Basically, I want to change observer's direction
like you do with holding down the left mouse in the looking mode.
> You may be wondering where to put that code but we'll get to that
> later. Now setting up the shot is another matter. The whole world in
> Billiards (actually as small as a room with no walls and a pool table)
> is set up of nodes connected in a graph, sort of like a tree. The
> whole graph is traversed (several times actually per frame) and
> certain actions are performed by each node according to its nature.
> For example a node representing a physical body might perform
> collision detection and physical simulation for this frame, a node
> representing a visible surface (of a ball conveniently enough) might
> draw itself on the screen. Now there also happens to be a node
> representing a "slider" that is a joint between two bodies which
> allows them to slide against each other along a certain axis. This
> node actually links the cue stick with your hand (which is not drawn)
> and can also be powered, as if by a motor, which in the real world
> would be your right arm. So this joint is called joints.arm and the
> parameters of its motor are set like so:
>
> joints.arm.motor = {v, F_max}
>
>
> What this actually means is that you want the motor to power the
> bodies it's linked to in such a way that their relative velocity along
> the joint's axis becomes v and in order to do this it can exert a
> force on the bodies no larger than F_max. In our case, since the hand
> is considered fixed, this means that your right arm can push the stick
> with no more than F_max newtons of force in order for the tip to reach
> and maintain a velocity of v m/s. The stick needs to be accelerated
> to that velocity though so the larger the force the sooner it will
> speed up to v. So if you use the same motor parameters and the same
> initial position for the stick relative to the ball (this latter comes
> into play because, if F_max is too low the stick might hit the ball
> before it has the time to reach the target velocity), if therefore
> both these conditions hold then the stick will contact the ball with
> the same velocity and provide identical (more or less, hopefully more
> more than less) results between shots. Raising v and making F_max
> large enough to reach it should result in more energy being
> transferred between the balls and cue. Incidentally there's a hook
> called billiards.cuecollision I believe which calls its functions
> right before the cue collides with a ball. You can use that to
> measure the velocity of the cue stick at that moment to make sure it
> is what you want it to be. The cue is described by the node
> bodies.cue and its velocity can be read at bodies.cue.velocity so you
> can write:
>
> billiards.cuecollision.cuespeed = function()
> print (math.length (bodies.cue.velocity))
> end
Ok, this works, but I modified it to:
billiards.cuecollision.cuespeed = function ()
print (string.format ("Cue velocity: {%f, %f, %f}",
bodies.cue.velocity[1],
bodies.cue.velocity[2],
bodies.cue.velocity[3]));
end
since I don't know that math.length function does.
I made an interesting observation about billiards.cuecollision.cuespeed.
It is almost always called 3 times and the first time it reports
unusually low numbers:
('f' pressed)
Cue velocity: {-0.000003, 0.000000, -0.000003}
Cue velocity: {-0.000003, 0.000000, -0.000003}
Cue velocity: {-0.000003, 0.000000, -0.000003}
('f' released)
('f' pressed)
Cue velocity: {-5.776280, 0.000000, -5.776280}
Cue velocity: {-5.776280, 0.000000, -5.776280}
Cue velocity: {-5.776280, 0.000000, -5.776280}
('f' released)
('f' pressed)
Cue velocity: {-4.332211, 0.000000, -4.332211}
Cue velocity: {-4.332211, 0.000000, -4.332211}
Cue velocity: {-4.332211, 0.000000, -4.332211}
('f' released)
> So what you would presumably want would be to be able to hit a key and
> have the stick launch to reach a certain speed before hitting the
> ball. You need to bind some code to a key and you can use a node to
> do that. There's a node called an event node. When this is traversed
> it queries the windowing system for input events and fires hooks for
> each one. So you need to define such a node and link it to the tree
> somewhere (where exactly is not important as long as you don't, by
> chance, overwrite one of my nodes). Do it like this:
>
> graph.launcher = frames.event {
> keypress = function (self, key)
> if key == 'f' then
> -- Substitute suitable values here.
> joints.arm.motor = {v, F_max}
> end
> end
> }
Ok, this works as you say.
However, running simulatins/experiments this way still requires manual
human input. Is it possible to somehow do this automatically?
For example: currently, I still have to click on the white ball to go
from looking mode to aiming mode and when I'm in the aiming mode, I have
to press 'f' to launch the stick.
I would like to do those 2 things from the code and be able to run 100s
of experiments without human input.
> Moving on to the third point. You only want the final positions so
> you need to measure them once the shot is over. There is no
> "finished" event and hook but there are "waiting" and "looking"
> events. (You start waiting as soon as you strike the cue ball and
> when these come to a rest you start looking once more to decide upon
> your next shot). You could use hooks for both these events to detect
> a transition between them or alternatively I could introduce a
> "finished" event which would be as simple. But I suppose the best way
> to go would be to bind the logging to a key so that you have more
> control over it. You can consult the lua manual to find out how to
> open a file and write to it. I'll just provide some sample code to
> print it on the terminal:
>
> graph.logger = frames.event {
> keypress = function (self, key)
> if key == 'l' then
> for i, ball in bodies.balls do
> print (string.format ("%d: {%f, %f, %f}\n", i,
> ball.position[1],
> ball.position[2],
> ball.position[3]));
> end
> end
> end
> }
Ok, perfect! Doing this automatically in the billiards.looking hook is
enough for me.
> As you can see bodies.balls is actually a table with all the ball
> nodes inside. You traverse this and for each ball node you print it
> position vector. Simple enough I believe. After the shot is over and
> logged you need to reset the balls to their initial positions probably
> and this can be done by setting their postion in much the same way as
> you printed it:
>
> bodies.balls[1].position = {x_w, y_w, billiards.ballradius}
> bodies.balls[2].position = {x_b, y_b, billiards.ballradius}
>
> You can put this code right after the logging takes place if you want.
> This is more or less it for now.
Ok, thanks.
One more thing, is there a hook which is triggered when the ball goes in
the hole?
I would like to use this to set up automatic logging to only log the
outcomes, where the non-cue ball goes in the hole.
> One thing that remains to be mentioned is where to put all this code.
> You can actually specify additional script files for Billiards (or
> rather Techne) to run with the -c switch. So put all your code in a
> script file called, say experiment.lua and put this in say ~/foo. You
> can then run it like this:
>
> billiards -c ~/foo/experiment.lua
Ok, perfect.
> I should also say that all the code above has either been copied from
> Billiards' source or written on-the-fly and hasn't been tested at
> all, as I can't run Billiards at work. It might therefore not work as
> advertised and probably won't as I haven't done anything to Billiards
> for a while. It should get you started nevertheless. I advise you to
> look through Billiards' source as well. Most of it will probably not
> make much sense but you should get a general idea of how it works and
> it's not that much anyway. I'll try to implement my suggestions
> myself when I make the changes I mentioned earlier but this might take
> a few days. Give it a shot on your own until then and let me know if
> you need further clarifications, explanations, help or whatever.
Thanks again for all your help!
Tadej
--
Tadej Janež <address@hidden>
Fakulteta za računalništvo in informatiko
- [Billiards-devel] Programming experiments with Billiards, Tadej Janež, 2010/01/11
- Re: [Billiards-devel] Programming experiments with Billiards, Dimitris Papavasiliou, 2010/01/14
- Re: [Billiards-devel] Programming experiments with Billiards,
Tadej Janež <=
- Message not available
- Message not available
- Re: [Billiards-devel] Programming experiments with Billiards, Dimitris Papavasiliou, 2010/01/15
- Re: [Billiards-devel] Programming experiments with Billiards, Tadej Janež, 2010/01/19
- Re: [Billiards-devel] Programming experiments with Billiards, Dimitris Papavasiliou, 2010/01/19
- Re: [Billiards-devel] Programming experiments with Billiards, Tadej Janež, 2010/01/19
- Re: [Billiards-devel] Programming experiments with Billiards, Dimitris Papavasiliou, 2010/01/19
- Re: [Billiards-devel] Programming experiments with Billiards, Tadej Janež, 2010/01/20
- Re: [Billiards-devel] Programming experiments with Billiards, Dimitris Papavasiliou, 2010/01/21