diff --git a/.github/workflows/justina-colombia.yml b/.github/workflows/justina-colombia.yml
new file mode 100644
index 000000000..f1853be14
--- /dev/null
+++ b/.github/workflows/justina-colombia.yml
@@ -0,0 +1,48 @@
+name: Validate JUSTINA Colombia proposal
+
+on:
+ pull_request:
+ paths:
+ - "catkin_ws/Justina.workspace"
+ - "dockers/justina-colombia/**"
+ - ".github/workflows/justina-colombia.yml"
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ validate:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Verify ROS workspace distribution
+ shell: bash
+ run: grep -Fq '' catkin_ws/Justina.workspace
+
+ - name: Verify Colombia locale override
+ shell: bash
+ run: grep -Fq 'LC_ALL=es_CO.UTF-8' dockers/justina-colombia/Dockerfile
+
+ - name: Check shell scripts
+ shell: bash
+ run: |
+ bash -n dockers/justina-colombia/container-entrypoint.sh
+ bash -n dockers/justina-colombia/build-workspace.sh
+ shellcheck dockers/justina-colombia/container-entrypoint.sh
+ shellcheck dockers/justina-colombia/build-workspace.sh
+
+ - name: Reject unsafe legacy patterns
+ shell: bash
+ run: |
+ ! grep -RE -- '--privileged|apt-key|nvidia-docker|chown[[:space:]]+-R[[:space:]]+/home|rm[[:space:]]+-rf[[:space:]]+/opt/ros' \
+ dockers/justina-colombia/Dockerfile \
+ dockers/justina-colombia/compose.yaml \
+ dockers/justina-colombia/container-entrypoint.sh
+
+ - name: Validate Compose configuration
+ working-directory: dockers/justina-colombia
+ env:
+ JUSTINA_REPO_PATH: ${{ github.workspace }}
+ run: docker compose config
diff --git a/.gitignore b/.gitignore
index 1e1913d8d..5a35bc5cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,8 @@
*.swn
catkin_ws/devel/
catkin_ws/build/
+catkin_ws/logs/
+catkin_ws/.catkin_tools/
catkin_ws/src/CMakeLists.txt
catkin_ws/src/hri/justina_gui/src/justina_gui-release/*
!catkin_ws/src/hri/justina_gui/src/justina_gui-release/ui_MainWindow.h
@@ -81,3 +83,6 @@ catkin_ws/src/vision/obj_reco_plastic_tray/\.kdev4/
catkin_ws/src/src\.kdev4
catkin_ws/src/\.kdev4/
+
+# Local container configuration
+dockers/justina-colombia/.env
diff --git a/catkin_ws/Justina.workspace b/catkin_ws/Justina.workspace
index e1eaf93b6..849213875 100644
--- a/catkin_ws/Justina.workspace
+++ b/catkin_ws/Justina.workspace
@@ -1,6 +1,6 @@
-
+
src
diff --git a/catkin_ws/src/hardware/head/package.xml b/catkin_ws/src/hardware/head/package.xml
index 0c083837b..f0f512e9e 100644
--- a/catkin_ws/src/hardware/head/package.xml
+++ b/catkin_ws/src/hardware/head/package.xml
@@ -41,11 +41,15 @@
catkin
geometry_msgs
+ hardware_tools
+ message_generation
roscpp
rospy
std_msgs
sensor_msgs
geometry_msgs
+ hardware_tools
+ message_runtime
roscpp
rospy
std_msgs
diff --git a/dockers/justina-colombia/.env.example b/dockers/justina-colombia/.env.example
new file mode 100644
index 000000000..45ba24820
--- /dev/null
+++ b/dockers/justina-colombia/.env.example
@@ -0,0 +1,11 @@
+# Ruta absoluta al clon local de RobotJustina/JUSTINA.
+JUSTINA_REPO_PATH=/ruta/a/JUSTINA
+
+# Imagen conservadora por defecto. Puede apuntar a un registro interno.
+ROS_BASE_IMAGE=ros:kinetic-ros-base-xenial
+
+# Use los identificadores del usuario anfitrión para evitar archivos propiedad de root.
+USER_UID=1000
+USER_GID=1000
+
+ROS_MASTER_URI=http://localhost:11311
diff --git a/dockers/justina-colombia/Dockerfile b/dockers/justina-colombia/Dockerfile
new file mode 100644
index 000000000..e600d5622
--- /dev/null
+++ b/dockers/justina-colombia/Dockerfile
@@ -0,0 +1,66 @@
+ARG ROS_BASE_IMAGE=ros:kinetic-ros-base-xenial
+FROM ${ROS_BASE_IMAGE}
+
+ARG DEBIAN_FRONTEND=noninteractive
+ARG USERNAME=justina
+ARG USER_UID=1000
+ARG USER_GID=1000
+
+ENV TZ=America/Bogota \
+ LANG=es_CO.UTF-8 \
+ LANGUAGE=es_CO:es \
+ LC_ALL=es_CO.UTF-8 \
+ LC_TIME=es_CO.UTF-8 \
+ ROS_DISTRO=kinetic \
+ JUSTINA_WS=/workspace/JUSTINA/catkin_ws
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ bash-completion \
+ build-essential \
+ ca-certificates \
+ git \
+ libjack-jackd2-dev \
+ libopencv-dev \
+ libpcl-dev \
+ locales \
+ python-catkin-tools \
+ python-rosdep \
+ qtbase5-dev \
+ ros-kinetic-amcl \
+ ros-kinetic-desktop-full \
+ ros-kinetic-dynamixel-sdk \
+ ros-kinetic-fake-localization \
+ ros-kinetic-gmapping \
+ ros-kinetic-joy \
+ ros-kinetic-laser-geometry \
+ ros-kinetic-map-server \
+ ros-kinetic-pcl-ros \
+ ros-kinetic-pointcloud-to-laserscan \
+ ros-kinetic-serial \
+ ros-kinetic-sound-play \
+ ros-kinetic-tf \
+ ros-kinetic-tf2-bullet \
+ ros-kinetic-tf-conversions \
+ ros-kinetic-urg-node \
+ sudo \
+ tzdata \
+ && locale-gen es_CO.UTF-8 \
+ && update-locale LANG=es_CO.UTF-8 LANGUAGE=es_CO:es LC_TIME=es_CO.UTF-8 \
+ && ln -snf /usr/share/zoneinfo/America/Bogota /etc/localtime \
+ && echo America/Bogota > /etc/timezone \
+ && groupadd --gid "${USER_GID}" "${USERNAME}" \
+ && useradd --uid "${USER_UID}" --gid "${USER_GID}" --create-home --shell /bin/bash "${USERNAME}" \
+ && echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/${USERNAME}" \
+ && chmod 0440 "/etc/sudoers.d/${USERNAME}" \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY container-entrypoint.sh /usr/local/bin/container-entrypoint
+COPY build-workspace.sh /usr/local/bin/build-justina-workspace
+RUN chmod 0755 /usr/local/bin/container-entrypoint /usr/local/bin/build-justina-workspace
+
+USER justina
+WORKDIR /workspace/JUSTINA
+
+ENTRYPOINT ["/usr/local/bin/container-entrypoint"]
+CMD ["bash"]
diff --git a/dockers/justina-colombia/README.md b/dockers/justina-colombia/README.md
new file mode 100644
index 000000000..23f941f60
--- /dev/null
+++ b/dockers/justina-colombia/README.md
@@ -0,0 +1,82 @@
+# Propuesta de contenedor JUSTINA para Colombia
+
+Esta propuesta conserva Ubuntu 16.04 y ROS Kinetic dentro de un contenedor. No
+ejecuta los instaladores heredados ni modifica paquetes del equipo anfitrión.
+
+## Alcance
+
+- Usa la imagen legada `ros:kinetic-ros-base-xenial` e instala el entorno
+ completo `ros-kinetic-desktop-full`.
+- Declara explícitamente la plataforma `linux/amd64`.
+- Configura `America/Bogota` y `es_CO.UTF-8`.
+- Monta el clon de JUSTINA en `/workspace/JUSTINA`.
+- Ejecuta como usuario sin privilegios.
+- No incluye CUDA, cámaras, USB ni acceso privilegiado por defecto.
+
+La imagen depende de componentes sin soporte. Debe usarse para recuperación,
+evaluación y migración, no como plataforma nueva de producción.
+Si la imagen pública deja de estar disponible, configure `ROS_BASE_IMAGE` para
+usar una copia aprobada en un registro interno.
+
+## Uso
+
+1. Entre a `dockers/justina-colombia`.
+2. Cree la configuración local:
+
+ ```bash
+ cd dockers/justina-colombia
+ cp .env.example .env
+ ```
+
+3. Cambie `JUSTINA_REPO_PATH` en `.env` por la ruta absoluta del repositorio.
+4. Construya y abra el entorno:
+
+ ```bash
+ docker compose build
+ docker compose run --rm justina
+ ```
+
+5. Dentro del contenedor, prepare dependencias y compile el workspace:
+
+ ```bash
+ build-justina-workspace
+ ```
+
+El comando incluye distribuciones ROS fuera de soporte al actualizar `rosdep`,
+instala las dependencias declaradas, limpia resultados anteriores y compila.
+Omite `libopenni-sensor-primesense-dev` porque ya no está disponible en los
+repositorios de Ubuntu Xenial. Los módulos compilan con `libopenni`, pero usar
+un sensor PrimeSense antiguo requiere instalar su controlador manualmente.
+
+En Windows, después de aplicar la propuesta, valide los archivos con:
+
+```powershell
+.\dockers\justina-colombia\validate-proposal.ps1 -RepositoryPath .
+```
+
+## Issue #13
+
+El archivo `catkin_ws/Justina.workspace` declara ROS Indigo, mientras los scripts
+del repositorio instalan ROS Kinetic. Esta propuesta actualiza esa metadata a
+Kinetic.
+
+## Hardware y GPU
+
+No habilite `--privileged` como solución general. Agregue dispositivos concretos
+solo después de identificarlos, por ejemplo `/dev/video0` o un puerto serial.
+
+Para GPU, instale NVIDIA Container Toolkit en el anfitrión y cree una variante
+separada de Compose. CUDA 8 y las GPU modernas pueden ser incompatibles.
+
+## Validación antes de revisión
+
+```bash
+docker compose config
+docker build --check .
+shellcheck container-entrypoint.sh
+grep -Fq '' ../../catkin_ws/Justina.workspace
+```
+
+Estas validaciones requieren Docker Compose v2 y un anfitrión Linux. Docker
+Desktop para Windows puede inspeccionar el archivo, pero `network_mode: host` y
+el montaje de X11 están diseñados para Linux.
diff --git a/dockers/justina-colombia/build-workspace.sh b/dockers/justina-colombia/build-workspace.sh
new file mode 100644
index 000000000..02b7a3576
--- /dev/null
+++ b/dockers/justina-colombia/build-workspace.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+source "/opt/ros/${ROS_DISTRO}/setup.bash"
+
+if [[ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]]; then
+ sudo rosdep init
+fi
+
+rosdep update --include-eol-distros
+rosdep install \
+ --from-paths "${JUSTINA_WS}/src" \
+ --ignore-src \
+ --rosdistro "${ROS_DISTRO}" \
+ --skip-keys "libopenni-sensor-primesense-dev" \
+ -r \
+ -y
+
+cd "${JUSTINA_WS}"
+catkin clean -y
+catkin build
diff --git a/dockers/justina-colombia/compose.yaml b/dockers/justina-colombia/compose.yaml
new file mode 100644
index 000000000..10b963937
--- /dev/null
+++ b/dockers/justina-colombia/compose.yaml
@@ -0,0 +1,23 @@
+services:
+ justina:
+ platform: linux/amd64
+ build:
+ context: .
+ dockerfile: Dockerfile
+ args:
+ ROS_BASE_IMAGE: "${ROS_BASE_IMAGE:-ros:kinetic-ros-base-xenial}"
+ USER_UID: "${USER_UID:-1000}"
+ USER_GID: "${USER_GID:-1000}"
+ image: justina-colombia:kinetic
+ container_name: justina-colombia
+ environment:
+ DISPLAY: "${DISPLAY:-}"
+ ROS_MASTER_URI: "${ROS_MASTER_URI:-http://localhost:11311}"
+ TZ: America/Bogota
+ network_mode: host
+ stdin_open: true
+ tty: true
+ volumes:
+ - "${JUSTINA_REPO_PATH:?Defina JUSTINA_REPO_PATH}:/workspace/JUSTINA"
+ - "/tmp/.X11-unix:/tmp/.X11-unix:rw"
+ working_dir: /workspace/JUSTINA
diff --git a/dockers/justina-colombia/container-entrypoint.sh b/dockers/justina-colombia/container-entrypoint.sh
new file mode 100644
index 000000000..c333e9636
--- /dev/null
+++ b/dockers/justina-colombia/container-entrypoint.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+source "/opt/ros/${ROS_DISTRO}/setup.bash"
+
+if [[ -f "${JUSTINA_WS}/devel/setup.bash" ]]; then
+ source "${JUSTINA_WS}/devel/setup.bash"
+fi
+
+exec "$@"
diff --git a/dockers/justina-colombia/validate-proposal.ps1 b/dockers/justina-colombia/validate-proposal.ps1
new file mode 100644
index 000000000..0a8f31fc6
--- /dev/null
+++ b/dockers/justina-colombia/validate-proposal.ps1
@@ -0,0 +1,57 @@
+[CmdletBinding()]
+param(
+ [string]$RepositoryPath = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
+)
+
+$ErrorActionPreference = 'Stop'
+$proposalDirectory = $PSScriptRoot
+$workspaceFile = Join-Path $RepositoryPath 'catkin_ws\Justina.workspace'
+$composeFile = Join-Path $proposalDirectory 'compose.yaml'
+$dockerfile = Join-Path $proposalDirectory 'Dockerfile'
+
+if (-not (Test-Path -LiteralPath $workspaceFile -PathType Leaf)) {
+ throw "No se encontró el workspace: $workspaceFile"
+}
+
+[xml]$workspace = Get-Content -Raw -LiteralPath $workspaceFile
+$distribution = $workspace.Workspace.Distribution.name
+if ($distribution -ne 'kinetic') {
+ throw "Se esperaba ROS Kinetic en Justina.workspace; se encontró: $distribution"
+}
+
+$dockerfileContent = Get-Content -Raw -LiteralPath $dockerfile
+if ($dockerfileContent -notmatch 'LC_ALL=es_CO\.UTF-8') {
+ throw 'El Dockerfile no configura LC_ALL=es_CO.UTF-8.'
+}
+
+$unsafePatterns = @('--privileged', 'apt-key', 'nvidia-docker', 'chown\s+-R\s+/home', 'rm\s+-rf\s+/opt/ros')
+$implementationFiles = @(
+ $composeFile,
+ $dockerfile,
+ (Join-Path $proposalDirectory 'container-entrypoint.sh'),
+ (Join-Path $proposalDirectory 'build-workspace.sh')
+)
+foreach ($pattern in $unsafePatterns) {
+ if (Select-String -Path $implementationFiles -Pattern $pattern) {
+ throw "Se encontró un patrón heredado no permitido: $pattern"
+ }
+}
+
+$previousRepoPath = $env:JUSTINA_REPO_PATH
+try {
+ $env:JUSTINA_REPO_PATH = $RepositoryPath
+ if (Get-Command docker-compose -ErrorAction SilentlyContinue) {
+ & docker-compose -f $composeFile config | Out-Null
+ }
+ else {
+ & docker compose -f $composeFile config | Out-Null
+ }
+ if ($LASTEXITCODE -ne 0) {
+ throw 'La validación de Docker Compose falló.'
+ }
+}
+finally {
+ $env:JUSTINA_REPO_PATH = $previousRepoPath
+}
+
+Write-Host 'Validación de la propuesta JUSTINA Colombia: correcta.'