Attempting to find relative positions to an object

Hello,

What I am trying to do currently is get the position relative to a model, and then use that to make a bullet ray query. I understand how to get the position of the model itself, but I would also like to get the position 100 units in front of it. If not, is there a standard way of getting these positions? I’ve tried making my own, but I think it is not working correctly (and seems overcomplicated for something like this). Thanks for the help!

What I have right now:

Functions from conversions module:

from math import cos, sin, sqrt, pi
# getting x and y coords for a point with length from (0, 0) and total angle of the object's angle,
# plus the angle of the ray relative to the object 
# (0, 45, 10 gives a ray 45 degrees to the left of an object looking in the y direction)
def getBeamPosition(objectangle, rayangle, length):
    totalangle = objectangle + rayangle
    totalangle = convAngle(totalangle)
    totalangle = math.radians(totalangle)
    horizontal = length * cos(totalangle)
    vertical = length * sin(totalangle)
    return [horizontal, vertical]

# converts the angle from Panda's system to a 0-360 degree measure, working anticlockwise
def convAngle(angle):
    if angle >= 0:
        angle = 360 - angle
    else:
        angle *= -1
    return angle

def Pythag(a, b):
    return sqrt(a**2 + b**2)

In main script:

        rayPositions = []
        rayResults = []
        # chassisNP is a BulletRigidBodyNode in the shape of a cuboid to act as the hitbox for the car body
        carLoc = self.test_car.chassisNP.getPos(render)
        carRot = self.test_car.chassisNP.getHpr(render)
        print(carLoc)
        ## This is the intended setup, with 8 rays going around the chassis to determine how far away it is from a wall in these directions
        # for i in range(0, 360, 45):
        #     beamLengthStartComponents = conversions.getBeamPosition(carRot[0], i, self.test_car.angleRadius[i])
        #     beamStart = carLoc + Point3(beamLengthStartComponents[0], beamLengthStartComponents[1], 0.2)
        #
        #     beamLengthEndComponents = conversions.getBeamPosition(carRot[0], i, 1000)
        #     beamEnd = carLoc + Point3(beamLengthEndComponents[0], beamLengthEndComponents[1], 0.2)
        #     rayPositions.append([beamStart, beamEnd])

        beamLengthStartComponents = conversions.getBeamPosition(carRot[0], 0, self.test_car.angleRadius[0])
        beamStart = carLoc + Point3(beamLengthStartComponents[0], beamLengthStartComponents[1], 0.2)

        beamLengthEndComponents = conversions.getBeamPosition(carRot[0], 0, 1000)
        beamEnd = carLoc + Point3(beamLengthEndComponents[0], beamLengthEndComponents[1], 0.2)
        rayPositions.append([beamStart, beamEnd])

        for count, i in enumerate(rayPositions):
            rayResults.append(self.world.rayTestClosest(i[0], i[1]))
            print(rayResults[count].getHitPos())
            distanceVector = rayResults[count].getHitPos() - carLoc
            print(conversions.Pythag(distanceVector[0], distanceVector[1]))
            # Purely to seperate the prints from one frame to the next
            print("------")

You may be looking for wrtReparentTo which is actually really fancy math underneath:

https://docs.panda3d.org/1.10/python/reference/panda3d.core.NodePath?highlight=reparentto#panda3d.core.NodePath.wrtReparentTo

I’m not sure this is what I need, since I don’t want it physically moved on the tree. What I’d like to do is use the rays (Bullet3D Ray Tests) to get the distance to the walls around the object (the car for this project), and save those distances. I could possibly use wrtReparentTo to take an object and move it to the points I want relative to the car, and then reparent (or use a relative GetPos if I’m thinking about it correctly) to get the coordinates for the world, but the only thing that crosses my mind about it is that it seems expensive to move an object to 16 different locations every frame, unless I’m just plain wrong there.

I actually wrote a very preliminary version of path-avoidance recently with Bullet, but to get distances I’m just using .length() compared between two positions:

v_dist_1 = (vehicle_1.get_pos() - vehicle_2.get_pos(base.render)).length()

So, I figure you could use the ray test hit position and then compare that to the ray origin.

One simple way to place a NodePath relative to another is to provide the “other” as a parameter when calling “setPos”.

Specifically, the various “set -Pos/Hpr/Scale/etc.” methods, as well as their “get” counterparts, all accept a NodePath as an optional first parameter. If this parameter is included, then they act relative to that NodePath.

So, to place a NodePath ten units directly in front of another (presuming that you’re using the y-axis as the “forward” axis), you might do something like this:

self.nodePathToPlace.setPos(self.anotherNodePath, 0, 10, 0)

You can then get the position of the NodePath as per usual.

Alternatively, there are the “getRelativePoint”/“getRelativeVector” methods. (I’ve never really figured out the difference, or why they should differ, to be honest.)

These, if I have if correctly, allow you to convert a point/vector in one reference frame to another. Specifically, you call them from a NodePath that has the reference frame that you intend to use, and pass in a NodePath that has the reference frame that you want to convert from.

So, a point in the reference frame of “render” with a position 10 units forward from another NodePath might–I think–be retrieved like this: (Again presuming that you’re using the y-axis as the forward-vector.)

render.getRelativePoint(self.anotherNodePath, Vec3(0, 10, 0))

This might not be a problem, actually. I’d suggest trying it before you discard the option!

getRelativePoint works exactly as I need it. Thank you!

For anyone that runs into this problem, this line will get the closest hit 1000 units in front of an object, and take the hits coordinates.

# chassisNP is the node I'm getting the position for, with 1.1 being the front of the hitbox, 
# and adding a small amount of height to try to prevent the start of the ray
# from clipping into what is beneath it at the point it is projected from and missing the floor.
firstFrontObjectCoords = self.world.rayTestClosest(render.getRelativePoint(self.test_car.chassisNP, Vec3(0, 1.1, 0.2)), render.getRelativePoint(self.test_car.chassisNP, Vec3(0, 1001.1, 0.2))).getHitPos()
# Then to get the distance from the front of the car
distanceToFrontObject = render.getRelativePoint(self.test_car.chassisNP, Vec3(0, 1.1, 0.2)) - firstFrontObjectCoords).length()
1 Like