Skip to content

Support for NVIDIA NuRec 25.07 (CARLA-NuRec 0.2). #9132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
* Added API function `world.set_annotations_traverse_translucency` and implemented functionality to configure, whether depth and semantic + instance segmentation traverse translucent materials or not.
* Fixed `frame`, `timestamp` and `transform` of `SensorData` not matching to the actually sent image for camera sensors.
* Added "geolocation_to_transform" function to the Map object in the PythonAPI
* Add support for NVIDIA NuRec 25.07 (CARLA-NuRec 0.2)

## CARLA 0.9.15

Expand Down
11 changes: 0 additions & 11 deletions PythonAPI/examples/nvidia/grpc_proto/__init__.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ command_exists() {



# Function to check if Hugging Face dataset exists
# Function to check if HuggingFace dataset exists
check_hf_dataset() {
local dataset_path="PhysicalAI-Autonomous-Vehicles-NuRec"
if [ -d "$dataset_path" ]; then
Expand All @@ -25,25 +25,58 @@ check_NuRec_container() {
return 1
}

# Function to validate Hugging Face PAT format (basic check)
# Function to validate HuggingFace PAT format (basic check)
validate_hf_pat() {
if [[ ! $1 =~ ^hf_[a-zA-Z0-9]{32,}$ ]]; then
echo "Error: Invalid Hugging Face PAT format" >&2
echo "Error: Invalid HuggingFace PAT format" >&2
return 1
fi
return 0
}

# Function to get and validate Hugging Face PAT
# Function to get and validate HuggingFace PAT
get_hf_pat() {
# Get Hugging Face PAT
read -s -p "Please enter your Hugging Face Personal Access Token. If you don't have one, visit: https://huggingface.co/settings/tokens. Enter your token: " hf_pat
echo
# Color codes
local RED='\033[0;31m'
local GREEN='\033[0;32m'
local YELLOW='\033[1;33m'
local BLUE='\033[0;34m'
local PURPLE='\033[0;35m'
local CYAN='\033[0;36m'
local WHITE='\033[1;37m'
local NC='\033[0m' # No Color

echo "" >&2
echo -e "${CYAN}============================================================${NC}" >&2
echo -e "${WHITE} 🔑 ${YELLOW}HUGGINGFACE AUTHENTICATION REQUIRED${WHITE} 🔑${NC}" >&2
echo -e "${CYAN}============================================================${NC}" >&2
echo "" >&2
echo -e "${WHITE}To download the dataset, you need a ${YELLOW}HuggingFace Personal Access Token${WHITE}.${NC}" >&2
echo "" >&2
echo -e "${BLUE}📍 If you don't have a token yet:${NC}" >&2
echo -e "${WHITE} 1. Visit: ${CYAN}https://huggingface.co/settings/tokens${NC}" >&2
echo -e "${WHITE} 2. Click ${YELLOW}'New token'${NC}" >&2
echo -e "${WHITE} 3. Choose ${GREEN}'Read'${WHITE} permissions${NC}" >&2
echo -e "${WHITE} 4. Copy the generated token${NC}" >&2
echo "" >&2
echo -e "${YELLOW}⚠️ Your input will be hidden for security${NC}" >&2
echo "" >&2

# Get HuggingFace PAT
echo -ne "${PURPLE}🔐 Enter your HuggingFace Personal Access Token: ${NC}" >&2
read -s hf_pat
echo >&2
echo "" >&2

# Validate Hugging Face PAT
# Validate HuggingFace PAT
if ! validate_hf_pat "$hf_pat"; then
echo -e "${RED}❌ Invalid token format. Please try again.${NC}" >&2
echo "" >&2
return 1
fi

echo -e "${GREEN}✅ Token validated successfully!${NC}" >&2
echo "" >&2
echo "$hf_pat"
return 0
}
Expand Down Expand Up @@ -135,23 +168,29 @@ done

# Download NuRec GRPC Container
echo "Checking NuRec GRPC container..."
if check_NuRec_container "docker.io/carlasimulator/nvidia-nurec-grpc:0.1.0"; then
if check_NuRec_container "docker.io/carlasimulator/nvidia-nurec-grpc:0.2.0"; then
echo "NuRec GRPC container already exists, skipping download."
else
echo "Initiating NuRec GRPC Container Downloads..."
docker pull docker.io/carlasimulator/nvidia-nurec-grpc:0.1.0
docker pull docker.io/carlasimulator/nvidia-nurec-grpc:0.2.0
if [ $? -ne 0 ]; then
echo "Error: Failed to download NuRec GRPC Container"
exit 1
fi
fi

# Download the dataset from Hugging Face
echo "Checking Hugging Face dataset..."
# Download the dataset from HuggingFace
echo "Checking HuggingFace dataset..."
if check_hf_dataset; then
echo "Hugging Face dataset already exists, skipping download."
echo "HuggingFace dataset already exists, skipping download."
else
# Get and validate Hugging Face PAT
echo "Installing HuggingFace CLI..."
pip3 install --upgrade huggingface_hub || {
echo "Error: Failed to install HuggingFace CLI"
exit 1
}

# Get and validate HuggingFace PAT
hf_pat=$(get_hf_pat)
if [ $? -ne 0 ]; then
exit 1
Expand All @@ -160,30 +199,24 @@ else
# Strip any newlines or whitespace from the token
hf_pat=$(echo "$hf_pat" | tr -d '\n\r' | xargs)

# Create the Hugging Face URL with embedded token
hf_url="https://user:${hf_pat}@huggingface.co/datasets/nvidia/PhysicalAI-Autonomous-Vehicles-NuRec/"

echo "Downloading the dataset from Hugging Face..."
git lfs install

# Set git configuration to avoid prompts
export GIT_TERMINAL_PROMPT=0 # Disable git prompts

# Clone the repository using the URL with embedded token
echo "Cloning dataset with authentication..."
git clone "$hf_url"
echo "Downloading the dataset from HuggingFace using CLI..."

clone_result=$?
unset GIT_TERMINAL_PROMPT
# Login to HuggingFace using the token
echo "$hf_pat" | hf auth login --token "$hf_pat" || {
echo "Error: Failed to authenticate with HuggingFace"
exit 1
}

if [ $clone_result -ne 0 ]; then
echo "Error: Failed to download the NuRec dataset from Hugging Face"
# Download the dataset using HuggingFace CLI
echo "Downloading dataset with HuggingFace CLI..."
hf download nvidia/PhysicalAI-Autonomous-Vehicles-NuRec --repo-type dataset --local-dir PhysicalAI-Autonomous-Vehicles-NuRec || {
echo "Error: Failed to download the NuRec dataset from HuggingFace"
exit 1
fi
}
fi

# Set the NuRec image path
NUREC_IMAGE="docker.io/carlasimulator/nvidia-nurec-grpc:0.1.0"
NUREC_IMAGE="docker.io/carlasimulator/nvidia-nurec-grpc:0.2.0"
export NUREC_IMAGE
echo "NUREC_IMAGE: $NUREC_IMAGE"

Expand Down Expand Up @@ -228,7 +261,7 @@ pip3 install pygame numpy nvidia-nvjpeg-cu12 imageio|| {
# Install Carla Wheel
echo "Installing Carla Wheel..."

WHEEL=$(ls ../../carla/dist/carla-0.9.16-cp310-cp310-*.whl | head -n 1)
WHEEL=$(ls ../../../carla/dist/carla-0.9.16-cp310-cp310-*.whl | head -n 1)
python -m pip install ${WHEEL} || {
echo "Error: Failed to install Carla Wheel"
exit 1
Expand All @@ -243,12 +276,12 @@ pip3 install -r requirements.txt || {

# Install and setup GRPC Protos
echo "Setting up GRPC Protos..."
pip3 install -r grpc_proto/requirements.txt || {
pip3 install -r nre/grpc/requirements.txt || {
echo "Error: Failed to install GRPC requirements"
exit 1
}

python3 grpc_proto/update_generated.py || {
python3 nre/grpc/update_generated.py || {
echo "Error: Failed to update generated GRPC files"
exit 1
}
Expand All @@ -257,3 +290,21 @@ python3 grpc_proto/update_generated.py || {
chmod +x "$0"

echo "Setup completed successfully!"
echo ""
echo "🔔 IMPORTANT: Environment Variable Notice"
echo "=============================================="
echo "The NUREC_IMAGE environment variable has been added to your ~/.bashrc file"
echo "and will be available in new terminal sessions."
echo ""
echo "To use it in your CURRENT terminal session, run one of these commands:"
echo ""
echo " Option 1 (Reload bashrc):"
echo " source ~/.bashrc"
echo ""
echo " Option 2 (Export manually for this session):"
echo " export NUREC_IMAGE=\"$NUREC_IMAGE\""
echo ""
echo " Option 3 (Start a new terminal session)"
echo ""
echo "You can verify the variable is set by running:"
echo " echo \$NUREC_IMAGE"
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ After generating the Python files, you can import and use them in your Python co

```python
# Import the generated modules
import grpc_proto.common_pb2 as common_pb2
import grpc_proto.sensorsim_pb2 as sensorsim_pb2
import grpc_proto.sensorsim_pb2_grpc as sensorsim_pb2_grpc
import nre.grpc.protos.common_pb2 as common_pb2
import nre.grpc.protos.sensorsim_pb2 as sensorsim_pb2
import nre.grpc.protos.sensorsim_pb2_grpc as sensorsim_pb2_grpc

# Create a gRPC channel and stub
import grpc
Expand Down Expand Up @@ -73,7 +73,7 @@ The NuRec gRPC API provides the following main services:
When modifying the .proto files, always regenerate the Python code:

```bash
python PythonAPI/examples/nvidia/grpc/update_generated.py
python PythonAPI/examples/nvidia/nre/grpc/update_generated.py
```

## Support
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// SPDX-FileCopyrightText: © 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// SPDX-License-Identifier: MIT

// Copyright (c) 2025 NVIDIA CORPORATION. All rights reserved.
syntax = "proto3";

package common;
package nre.grpc.protos.common;

////////////////////////////////////////////////////////////////////////////////
// Common types
Expand Down Expand Up @@ -78,4 +75,3 @@ message SessionRequestStatus {} // empty; reserved name in case we want to exten
message AvailableScenesReturn {
repeated string scene_ids = 1;
}

Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// SPDX-FileCopyrightText: © 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// SPDX-License-Identifier: MIT

// Copyright (c) 2025 NVIDIA CORPORATION. All rights reserved.
syntax = "proto3";

package sensorsim;
package nre.grpc.protos.sensorsim;

import "common.proto";
import "nre/grpc/protos/common.proto";

////////////////////////////////////////////////////////////////////////////////
// Sensor simulator <-> Runtime
Expand All @@ -15,12 +12,12 @@ import "common.proto";
service SensorsimService {
rpc render_rgb (RGBRenderRequest) returns (RGBRenderReturn);
rpc render_lidar (LidarRenderRequest) returns (LidarRenderReturn);
rpc get_version (common.Empty) returns (common.VersionId);
rpc get_available_scenes (common.Empty) returns (common.AvailableScenesReturn);
rpc get_version (nre.grpc.protos.common.Empty) returns (nre.grpc.protos.common.VersionId);
rpc get_available_scenes (nre.grpc.protos.common.Empty) returns (nre.grpc.protos.common.AvailableScenesReturn);
rpc get_available_cameras (AvailableCamerasRequest) returns (AvailableCamerasReturn);
rpc shut_down (common.Empty) returns (common.Empty);
rpc shut_down (nre.grpc.protos.common.Empty) returns (nre.grpc.protos.common.Empty);
rpc get_available_trajectories (AvailableTrajectoriesRequest) returns (AvailableTrajectoriesReturn);
rpc get_available_ego_masks (common.Empty) returns (AvailableEgoMasksReturn);
rpc get_available_ego_masks (nre.grpc.protos.common.Empty) returns (AvailableEgoMasksReturn);
}

message EgoMaskId {
Expand All @@ -46,6 +43,11 @@ enum ShutterType {
GLOBAL = 5; //Instantaneous global shutter (no rolling shutter)
}

message LinearCde {
double linear_c = 1;
double linear_d = 2;
double linear_e = 3;
}

message FthetaCameraParam {
enum PolynomialType {
Expand All @@ -64,6 +66,8 @@ message FthetaCameraParam {
repeated double angle_to_pixeldist_poly = 5;

double max_angle = 6;

LinearCde linear_cde = 7;
}

//TODO: implentation of OpenCV pinhole camera model parameters
Expand Down Expand Up @@ -130,8 +134,8 @@ message CameraSpec {
message PosePair {
// represents poses at start and end of the frame
// TODO: replace with common.Trajectory (more general)
common.Pose start_pose = 1;
common.Pose end_pose = 2;
nre.grpc.protos.common.Pose start_pose = 1;
nre.grpc.protos.common.Pose end_pose = 2;
}

message DynamicObject {
Expand Down Expand Up @@ -183,7 +187,7 @@ message AvailableCamerasRequest {
message AvailableCamerasReturn {
message AvailableCamera {
CameraSpec intrinsics = 1;
common.Pose rig_to_camera = 2; // should be camera_to_rig -> silently breaks things, deprecate and create duplicate? or just fix and let people know
nre.grpc.protos.common.Pose rig_to_camera = 2; // should be camera_to_rig -> silently breaks things, deprecate and create duplicate? or just fix and let people know

string logical_id = 3;
uint32 trajectory_idx = 4;
Expand All @@ -199,7 +203,7 @@ message AvailableTrajectoriesRequest {
message AvailableTrajectoriesReturn {
message AvailableTrajectory {
uint32 trajectory_idx = 1;
common.Trajectory trajectory = 2;
nre.grpc.protos.common.Trajectory trajectory = 2;
}

repeated AvailableTrajectory available_trajectories = 1;
Expand Down Expand Up @@ -241,4 +245,4 @@ message LidarRenderRequest {
PosePair sensor_pose = 5;

repeated DynamicObject dynamic_objects = 6;
}
}
Loading