Help on piecewise linear trajectory implementation

Hi all,

I need to pick your brain on a possibly simple problem.

In my problem, given a list of n waypoints the final implementation should move the actor from one waypoint to the next.

Implementation of this behavior is straightforward using sequences and lerpposintervals. However, there is a small catch: at each waypoint the actor should smoothly turn towards the next waypoint while stationary. A step-by-step example:

Given waypoints A,B,C:
1-Position actor at A,
2-Turn actor (smoothly) to face B,
3-Move actor to B,
4-Turn actor (smoothly) to face C,
5-Move actor to C.

I played a bit with pathfollow idea but the turn of the actor at the end of each waypoint towards the next one is instantaneous which is a no-no for me.

I tried to create a sequence like:

curr_quat = self.actor_np.getQuat()
self.actor_np.lookAt(waypoint_np[1])
dest_quat = self.actor_np.getQuat()
self.actor_np.setQuat(curr_quat)
sequence.append(LerpQuatInterval(self.actor_np, 1, dest_quat))
sequence.append(LerpPosInterval(self.actor_np, 8, waypoint_np[1]))

This works for a single waypoint. It does not work with multiple waypoints though since at each waypoint dest_quat must be recalculated.

I have a couple of ideas to do this but I do not want to reinvent the wheel if this has been done or discussed before.

Thank you,

UB

dummy = render.attachNewNode("dummy")
for i in range(len(waypoints) - 1):
	thisWP = waypoints[i]
	nextWp = waypoints[i + 1]
	
	dummy.setPos(thisWP)
	dummy.lookAt(nextWP)
	
	targetQuat = dummy.getQuat()
	sequence.append(LerpQuatInterval(actor, 1, targetQuat))
	sequence.append(LerpPosInterval(actor, 8, nextWP))
dummy.remove()
sequence.start()

Just a quick idea that came to my mind while reading your post. In fact, this could as well be done using the actor node alone, without the need for dummy nodes, but I think this way the code is cleaner because you avoid storing and restoring the actor’s position and orientation. Anyway, the important part is to do the lookAt from the correct position.

Thank you for the reply.

Caching the quats is a good idea. I was thinking about it too.

I implemented a slightly different version the idea being intact:

sequence = Sequence()
mat = self.actor_np.getMat()
for wp in wp_list:
  self.actor_np.lookAt(wp)
  quat = self.actor_np.getQuat()
  sequence.append(LerpQuatInterval(self.actor_np, 1, quat))
  sequence.append(LerpPosInterval(self.actor_np, 8, wp))
  self.actor_np.setPos(wp)
self.actor_np.setMat(mat)
sequence.start()  

This approach works.

I was also thinking about:

1- Exploiting the ability of passing python functors as parameters to Lerp objects. But this seems messier to do since I need to deal with function closures, etc.

2- Subclassing LerpQuatInterval as LerpLookAtInterval to add the ability to turn towards a given node or position. It should be feasible but I need to go through the CLerp code. If I can get a reference to the priv_initialize() from inside Python layer it should be pretty straightforward.

I strongly believe that a LerpLookAtInterval like class would be a great addition.

I am open to suggestions.

Thank you,

UB