Crea tu servidor de Inteligencia Artificial con una computadora antigua

Por: Julio César Sandria Reynoso
Maestro en Inteligencia Artificial
6 de octubre de 2026

Guía Técnica para la configuración y puesta en marcha de un servidor de Inteligencia Artificial con Ubuntu Server, Ollama y NVIDIA en una computadora antigua.

Este documento detalla el proceso completo de configuración, instalación, optimización y prueba de un servidor de Inteligencia Artificial local desplegado sobre Ubuntu Server 24.04.5 LTS, aprovechando hardware dedicado e integración mediante API remota y scripts en Python.

1. Especificaciones del Hardware del Servidor

La computadora usada como servidor de inteligencia artificial en el Instituto de Robótica de Xalapa cuenta con el siguiente perfil técnico optimizado para cargas de trabajo locales:

ComponenteDetalle TécnicoEstado / Nota de rendimiento
Procesador (CPU)Intel(R) Pentium(R) CPU G4400 @ 3.30GHz (2 núcleos / 2 hilos, Skylake)Sin soporte para instrucciones AVX/AVX2. Operación orientada a gestión y soporte de RAM.
Memoria RAM32 GB DDR4 Synchronous 2667 MHz (2 módulos de 16 GB)Excelente capacidad para almacenar modelos de lenguaje de tamaño intermedio.
Tarjeta Gráfica (GPU)NVIDIA GeForce GTX 750 Ti (Arquitectura Maxwell, GM107, 2 GB VRAM)Controlador propietario instalado con éxito. Soporte funcional para operaciones base de CUDA.
AlmacenamientoSSD ADATA SP580 (120 GB) + Disco mecánico adicional de 500 GBEspacio suficiente para sistema operativo, dependencias y almacenamiento de modelos LLM.
RedRealtek PCI Express Gigabit EthernetConectividad estable para servicio local de IA y peticiones en red.

Cabe mencionar que el equipo usado fue ampliado con memoria RAM y la reinstalación de la tarjeta gráfica que tuvo años atrás y que no se usó al preparar el artículo precedente: Instalación de una IA Generativa con Ubuntu y Ollama.

2. Configuración del Entorno Gráfico y Controladores NVIDIA

Para habilitar el soporte de hardware en la tarjeta gráfica NVIDIA GTX 750 Ti, se superaron incidencias iniciales de comunicación con el kernel mediante una purga limpia e instalación del controlador estable.

Resultado Exitoso: Al ejecutar el comando nvidia-smi, el sistema reportó correctamente la versión de controlador 580.178.04 y CUDA 13.0 vinculada a la GeForce GTX 750 Ti.

# Purgar instalaciones previas conflictivas
sudo apt purge nvidia* -y
sudo apt autoremove -y

# Instalar el controlador propietario estable
sudo apt install nvidia-driver-535 -y
sudo reboot

3. Instalación y Configuración del Servicio Ollama

Ollama fue instalado y configurado como un demonio del sistema mediante systemd para garantizar su ejecución automática en segundo plano y su disponibilidad ante reinicios.

# Descarga e instalación automatizada de Ollama
curl -fsSL https://ollama.com/install.sh | sh

# Creación del archivo de servicio systemd (/etc/systemd/system/ollama.service)
[Unit]
Description=Ollama Service
After=network-online.target

[Service]
ExecStart=/usr/local/bin/ollama serve
User=ollama
Group=ollama
Restart=always
RestartSec=3
Environment="PATH=$PATH"

[Install]
WantedBy=default.target

4. Exposición de la API en la Red Local

Para permitir que otros equipos de la red local se comuniquen con el servidor de IA, se configuró la variable de entorno OLLAMA_HOST modificando el servicio systemd:

sudo systemctl edit ollama.service

# Contenido de la anulación (override.conf):
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"

# Recargar y reiniciar el servicio
sudo systemctl daemon-reload
sudo systemctl restart ollama

5. Desarrollo de Clientes y Ejemplos de Programación en Python

Se configuró un entorno de desarrollo en la computadora cliente (macOS) utilizando entornos virtuales (venv) y la librería oficial ollama para consumir el modelo qwen2.5:1.5b desplegado en el servidor.

Programa 1: Respuesta en Streaming en Tiempo Real

import ollama

client = ollama.Client(host='http://192.168.1.50:11434')

stream = client.chat(
    model='qwen2.5:1.5b',
    messages=[
        {
            'role': 'user',
            'content': 'Escribe una historia corta sobre un robot curioso.',
        },
    ],
    stream=True,
)

print('IA: ', end='', flush=True)
for chunk in stream:
    print(chunk['message']['content'], end='', flush=True)

print()

Programa 2: Uso de Prompt de Sistema (Roles)

import ollama

client = ollama.Client(host='http://192.168.1.50:11434')

stream = client.chat(
    model='qwen2.5:1.5b',
    messages=[
        {
            'role': 'system',
            'content': 'Eres un profesor experto en robótica industrial. Responde siempre de forma técnica, concisa y orientada a la enseñanza.',
        },
        {
            'role': 'user',
            'content': 'Explícame brevemente qué es la cinemática directa.',
        },
    ],
    stream=True,
)

print('IA: ', end='', flush=True)
for chunk in stream:
    print(chunk['message']['content'], end='', flush=True)

print()

Programa 3: Chat Continuo con Historial y Streaming

import ollama

client = ollama.Client(host='http://192.168.1.50:11434')

mensajes = [
    {
        'role': 'system',
        'content': 'Eres un profesor experto en robótica industrial y optimización. Responde de forma técnica y concisa.'
    }
]

print("Iniciando chat continuo con Ollama. Escribe 'salir' para terminar.\n")

while True:
    texto_usuario = input("Tú: ")
    if texto_usuario.lower() in ['salir', 'exit', 'quit']:
        break

    mensajes.append({'role': 'user', 'content': texto_usuario})

    stream = client.chat(
        model='qwen2.5:1.5b',
        messages=mensajes,
        stream=True
    )

    print("IA: ", end='', flush=True)
    respuesta_completa = ""

    for chunk in stream:
        contenido = chunk['message']['content']
        print(contenido, end='', flush=True)
        respuesta_completa += contenido

    print("\n")
    mensajes.append({'role': 'assistant', 'content': respuesta_completa})

6. Monitoreo Avanzado y Análisis Comparativo del Sistema con btop

Para garantizar la estabilidad y comprobar la correcta distribución de la carga de trabajo entre la CPU, la RAM y la tarjeta gráfica, se utilizó la herramienta btop. A continuación se detalla el comportamiento del servidor bajo dos escenarios distintos de operación.

Instalación de btop en Ubuntu Server

# Actualizar repositorios e instalar btop
sudo apt update
sudo apt install btop -y

# Ejecutar el monitor
btop

Análisis Escenario A: Servidor en Reposo o con Peticiones Ligeras

Durante la operación normal o al recibir peticiones estándar de chat, el modelo qwen2.5:1.5b permanece residente en la memoria RAM (ocupando aproximadamente 1.3 GiB de forma estable en el proceso llama-server). El uso de la CPU se mantiene bajo y la tarjeta gráfica registra un uso mínimo.

Imagen 1: Captura de btop mostrando el servidor en estado de reposo, baja carga con llama-server usando ~1.3 GB de RAM y CPU en reposo

Análisis Escenario B: Servidor bajo Carga Masiva (Procesamiento de Textos Extensos)

Para comprobar la respuesta del servidor bajo una carga pesada, se ejecutó un script en el equipo cliente que envía un bloque de texto masivo para calcular la matriz de atención y el contexto (*KV Cache*).

Programa de Prueba con Bloque de Texto Extenso

import ollama

client = ollama.Client(host='http://192.168.1.50:11434')

# Creamos un bloque de texto grande para forzar el uso de memoria de contexto
bloque_texto = (
    "La robótica móvil autónoma y los sistemas de optimización combinatoria "
    "requieren algoritmos eficientes de navegación y búsqueda de rutas como A* "
    "y Dijkstra, integrando mapeo SLAM y sensores LiDAR en entornos dinámicos. "
) * 150

print("Enviando documento extenso al servidor de IA...")

stream = client.chat(
    model='qwen2.5:1.5b',
    messages=[
        {
            'role': 'system',
            'content': 'Eres un asistente técnico analítico. Resume y extrae los conceptos principales del texto proporcionado.'
        },
        {
            'role': 'user',
            'content': f'Por favor, analiza a detalle el siguiente documento:\n\n{bloque_texto}'
        }
    ],
    stream=True
)

print("IA: ", end='', flush=True)
for chunk in stream:
    print(chunk['message']['content'], end='', flush=True)

print("\n\nProceso finalizado.")

Al ejecutar este script, el comportamiento de los recursos en btop cambia drásticamente:

  • Uso del CPU al 100% (C0 y C1): Los dos núcleos del Intel Pentium G4400 se saturan por completo realizando los cálculos secuenciales del modelo.
  • Proceso Activo (llama-server): El consumo de CPU del proceso asciende al 99.0%, absorbiendo toda la capacidad de procesamiento disponible.
  • Actividad Gráfica (GPU): El uso de la GPU se incrementa (alrededor del 38%), mientras que la ocupación de la VRAM se mantiene en 1.1 GiB / 2.0 GiB, apoyando parcialmente en el procesamiento.
  • Temperatura: La temperatura de la CPU experimenta un incremento controlado (por ejemplo, a 47 °C), manteniéndose en un rango totalmente seguro.
Imagen 2: Captura de btop mostrando el servidor bajo carga masiva con CPU al 100%, proceso llama-server al 99% de CPU y GPU activa

7. Preguntas Frecuentes y Análisis de Arquitectura (Hardware y Rendimiento)

Pregunta: ¿Valió la pena ampliarle la RAM a la computadora de 8GB a 32GB si en reposo modelos ligeros como qwen2.5:1.5b apenas consumen 1.3 GB? ¿Y qué hay de la tarjeta gráfica GTX 750 Ti que se consideraba tecnología antigua?

Respuesta Técnica: Sí, ampliar la RAM a 32 GB y conservar la GTX 750 Ti fue una excelente decisión de arquitectura por los siguientes motivos:

  • Escalabilidad de Modelos: Aunque un modelo de 1.5B parámetros es ligero, modelos de mayor tamaño (como 7B u 8B) requieren entre 4.5 GB y 5.5 GB solo para cargar sus pesos. Con 8 GB totales, el sistema operativo (Ubuntu Server) se quedaría sin margen y generaría errores críticos por falta de memoria o paginación en disco (*Swap*). Con 32 GB hay total holgura.
  • Gestión del KV Cache y Contextos Largos: Al procesar documentos masivos, código fuente extenso o historiales de chat kilométricos, la memoria temporal para la matriz de atención (*KV Cache*) crece de manera importante, la cual es absorbida sin problemas por la RAM.
  • El Rol Real de la GTX 750 Ti: Aunque sus 2 GB de VRAM limitan la capacidad de alojar modelos completos (lo que obliga a delegar el cálculo pesado a la CPU al 100%), la tarjeta gráfica no está de adorno. Funciona como un coprocesador acelerador (registrando picos de uso del 38% bajo carga) para resolver operaciones matriciales específicas, además de gestionar la salida gráfica de forma independiente sin consumir la valiosa RAM del sistema.

8. Estrategia de Acceso Multiusuario y Herramientas Cliente en Red Local

Pregunta: Ya tenemos este servidor en un entorno escolar y daremos acceso a entre 2 y 5 colaboradores máximo. ¿Qué herramientas podemos instalar en las computadoras para que accedan al servidor y utilicen la IA configurada para analizar archivos y correr comandos de forma automatizada?

Respuesta Técnica: Para un grupo reducido de 2 a 5 usuarios concurrentes conectados al servidor Ollama (http://192.168.1.50:11434), existen excelentes alternativas dependiendo del flujo de trabajo:

  • Open WebUI (Interfaz tipo ChatGPT centralizada): Se despliega fácilmente mediante Docker en el servidor Ubuntu. Permite crear cuentas individuales para cada colaborador con historiales privados, soporte para carga y análisis de archivos (PDFs, documentos, código) mediante RAG, y acceso directo desde el navegador web de cada computadora (ej. http://192.168.1.50:3000) sin requerir hardware pesado local.
  • AnythingLLM (Especializado en bases documentales): Excelente para indexar directorios completos de archivos institucionales o académicos y consultar información de forma privada y estructurada.
  • Continue.dev (Para automatización de código y comandos): Extensión de código abierto para editores como VS Code que permite a los colaboradores modificar código, explicar scripts y generar comandos de terminal directamente desde su entorno de desarrollo, utilizando la potencia del servidor central.

9. Referencias Bibliográficas y Documentación Técnica

  • Ollama Documentation & API Guides: Documentación oficial sobre la API REST y configuración de red. Disponible en: Ollama FAQ & Configuration Guide.
  • Open WebUI Project Guide: Guía de despliegue mediante contenedores y gestión multiusuario. Disponible en: Open WebUI Documentation.
  • Continue.dev Open-Source Assistant: Documentación técnica sobre asistentes de código y editores locales. Disponible en: Continue Docs.
  • NVIDIA Driver & CUDA Documentation: Guías de controladores y plataforma de computación acelerada. Disponible en: NVIDIA CUDA Platform.

10. Conclusiones y Validación

El servidor rsa-userver24-xps se encuentra completamente operativo. La arquitectura implementada permite:

  • Ejecutar modelos de lenguaje eficientes como qwen2.5:1.5b utilizando los recursos optimizados del servidor.
  • Monitorear y comparar el rendimiento del hardware bajo distintas cargas mediante btop y nvidia-smi.
  • Atender peticiones descentralizadas desde múltiples equipos de la red local mediante la API REST y scripts avanzados en Python con streaming, roles, historial y pruebas de rendimiento.
  • Escalar el acceso a múltiples colaboradores mediante interfaces web y herramientas de asistencia técnica e integración documental.

Uso de módulo WiFi Esp8266 con Arduino UNO e IoT en Thingsboard

/* AmbiSensor - Sensor Ambiental (simulación) - IoT (Internet of Things)
   Julio César Sandria Reynoso - Mayo 2026
   Este programa genera aleatoriamente datos ambientales de
   Temperatura, Humedad, CO2 e Iluminación, y los envía a
   un servidor en la nube para poder ver los datos en tiempo
   real desde cualquier dispositivo 
  Hardware: Arduino UNO, Módulo WiFi Esp8266, Fuente de poder para protoboard,
  protoboard, 2 resistencias de 1K, cables dupont.
*/

// Incluimos la librería WiFiEspAT que es más reciente que WiFiEsp
#include <WiFiEspAT.h>

// Si usamos Arduino Mega o Leonardo USAR_MEGA = true
// Si usamos Arduino Uno o Nano USAR_MEGA = false
// const bool USAR_MEGA = true; // true = Arduino Mega | false = Arduino Uno

// Configuración dinámica de puertos Serial según la placa
// usando directivas del precompilador
#if defined(ARDUINO_AVR_MEGA2560) || defined(__AVR_ATmega2560__)
  // Si Arduino IDE detecta un Arduino Mega o Leonardo
  // Conecta pin 18 (TX1) a pin RX del Esp, con divisor de voltaje a 3.3V
  // Conecta pin 19 (RX1) a pin TX del Esp
  #define EspSerial Serial1
#else
  #include <SoftwareSerial.h>
  // En Arduino Uno o Nano:
  // Conecta pin 2 (RX) a pin TX del Esp
  // Conecta pin 3 (TX) a pin RX del Esp, con divisor de voltaje a 3.3V
  SoftwareSerial softSerial(2, 3); 
  #define EspSerial softSerial
#endif

// Credenciales Wi-Fi
const char* ssid     = "nombre-red-wifi";
const char* password = "clave-red-wifi";

// Configuración del servidor ThingsBoard
const char* server   = "thingsboard.cloud";
const int port       = 80;
const char* token    = "TOKEN";

// Variables de ambiente
float temp = 25;          // En grados Celcius
float humedad = 62;       // En porcentaje (%)
int co2 = 450;            // En ppm (partes por millón)
int luz = 780;            // En luxes o valor analógico (0-1023)

void setup() {
  Serial.begin(9600);
  Serial.println("Iniciando programa AmbiSensor - Sensor Ambiental...");

  // Inicializar la comunicación serial con el módulo WiFi Esp8266
  EspSerial.begin(9600); // Velocidades preferentes 115200 (Mega) o 9600 (Uno)

  Serial.println("Inicializando modulo Wi-Fi...");
  WiFi.init(&EspSerial);

  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("No se encontró el módulo Wi-Fi AT");
    while (true); // Detener el programa si no hay módulo
  }

  // Conectar a la red Wi-Fi
  Serial.print("Conectando a Wi-Fi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\n¡Conectado a la red!");
}

void loop() {
  // Asegurar que seguimos conectados antes de enviar datos
  if (WiFi.status() == WL_CONNECTED) {
    
    WiFiClient client;
    
    // Abrir conexión TCP con el servidor
    if (client.connect(server, port)) {
      Serial.println("Conectado al servidor de ThingsBoard");

      // *** AQUÍ SE DEBEN TOMAR LECTURAS DE LOS SENSORES REALES ***
      // Para este ejemplo, vamos simulando lecturas aleatorias
      temp += 2-random(5);        // En grados Celcius
      humedad += 2-random(5);     // En porcentaje (%)
      co2 += 7-random(15);        // En ppm (partes por millón)
      luz += 7-random(15);        // En luxes o valor analógico (0-1023)

      // 2. Preparar un JSON con múltiples variables
      // El formato final será: 
      // {"temperature":24.5,"humidity":62.5,"co2":450,"light":780}
      String sDatos = "{";
      sDatos += "\"temperature\":" + String(temp) + ",";
      sDatos += "\"humidity\":" + String(humedad) + ",";
      sDatos += "\"co2\":" + String(co2) + ",";
      sDatos += "\"light\":" + String(luz);
      sDatos += "}";

      // 3. Enviar la petición HTTP POST
      client.print("POST /api/v1/");
      client.print(token);
      client.println("/telemetry HTTP/1.1");
      
      // Encabezados
      client.print("Host: ");
      client.println(server);
      client.println("Content-Type: application/json");
      client.print("Content-Length: ");
      client.println(sDatos.length());
      client.println("Connection: close"); // Buena práctica para liberar memoria en el servidor
      
      // Línea en blanco obligatoria
      client.println(); 
      
      // Cuerpo de los datos (sDatos)
      client.print(sDatos);
      client.println();

      Serial.println("Datos enviados: " + sDatos);

      // 4. Leer la respuesta del servidor (para asegurarnos 
      // del 200 OK, que significa datos recibidos correctamente)
      unsigned long timeout = millis();
      while (client.available() == 0) {
        if (millis() - timeout > 5000) {
          Serial.println(">>> ¡Timeout!");
          client.stop();
          return;
        }
      }

      // Imprimir solo la primera línea (donde viene el código 200) 
      // para no saturar el monitor
      if (client.available()) {
        String status_line = client.readStringUntil('\r');
        Serial.println("Status: " + status_line);
      }

      // Cerrar la conexión
      client.stop();
    } else {
      Serial.println("Error: No se pudo conectar al servidor");
    }
  } else {
    Serial.println("Wi-Fi desconectado. Intentando reconectar...");
  }

  // Esperar 10 segundos antes del siguiente envío
  delay(10000);
}

Instalación de ROS 2 y Webots en Ubuntu 22.04 LTS

Por Julio César Sandria Reynoso
30 de abril de 2026

Introducción

En este artículo se describe la instalación de ROS 2 y Webots en Ubuntu 22.04 LTS en una computadora con arranque dual (dual boot) que ya tiene Windows 11 instalado. El Dual Boot es la opción más robusta para simulaciones pesadas porque permite que Ubuntu acceda al 100% del hardware (CPU, RAM y, sobre todo, la GPU) sin las capas de abstracción de una máquina virtual.

A continuación se muestra la hoja de ruta para instalar Ubuntu 22.04 LTS junto a Windows 11 de forma segura:

1. Preparación en Windows 11 (Crítico)

Antes de tocar cualquier partición, se debe preparar el terreno para evitar bloqueos del sistema.

  • Desactivar «Inicio Rápido» (Fast Boot): Windows bloquea el disco duro al apagarse si esto está activo, impidiendo que Ubuntu escriba en él.
    • Panel de Control > Hardware y sonido > Opciones de energía > Elegir el comportamiento de los botones de inicio.
  • Desactivar BitLocker: Si Windows 11 tiene el cifrado de disco BitLocker activado, se debe desactivar o tener a mano la clave de recuperación de 48 dígitos. De lo contrario, no se podrá redimensionar la partición.
  • Hacer espacio: Hacer clic derecho en el botón de Inicio > Administración de discos. Reducir el volumen de la unidad C: para dejar al menos 60-100 GB de «Espacio no asignado» para Ubuntu, ROS 2 y simulaciones de Webots.

2. Crear el medio de instalación

  1. Descargar el archivo ISO oficial de Ubuntu 22.04.x LTS.
  2. Usar una herramienta como Rufus o BalenaEtcher para «quemar» el ISO en una memoria USB de al menos 8 GB.

3. Configuración de la BIOS/UEFI

Reiniciar la computadora y entrar al BIOS (usualmente presionando F2, F12, Del o Esc al arrancar).

  • Secure Boot: En la mayoría de las computadoras desktop o laptops modernas, se puede dejarlo activado, pero si se tienen problemas para arrancar el USB, probar desactivarlo.
  • SATA Mode: Asegurarse de que esté en AHCI (si está en RAID, Ubuntu podría no ver el disco duro o SSD). Cuidado: cambiar esto puede requerir configurar Windows para arrancar en AHCI primero.

4. El proceso de instalación de Ubuntu

Arrancar la computadora desde la USB (Boot Menu) y selecciona «Install Ubuntu». Siguiendo estos pasos clave:

  1. Red y Actualizaciones: Conectar a Wi-Fi y marca la casilla «Instalar programas de terceros para hardware de gráficos y Wi-Fi». Esto es vital para que los drivers de NVIDIA (si los hay) funcionen con Webots.
  2. Tipo de instalación: Aquí viene lo más importante. Seleccionar «Instalar Ubuntu junto a Windows Boot Manager».
    • Si no aparece esta opción, elegir «Más opciones» para asignar manualmente el espacio no asignado creado en el paso 1.
  3. Particionado (si se elige Manual): Crear una partición root (punto de montaje /) con el resto del espacio (mínimo 50 GB). Formato: ext4.
  4. Finalizar: Seguir las instrucciones de ubicación y usuario.

5. Post-Instalación: El menú GRUB

Al reiniciar la computadora, se deberá ver una pantalla negra con letras blancas (el GRUB) que permite elegir entre Ubuntu y Windows Boot Manager.

6. Configuración para ROS 2 + Webots

Una vez en Ubuntu, lo primero que se debe hacer es optimizar el sistema para la simulación:

  1. Drivers de Video: Ir a «Software y actualizaciones» > «Más controladores» y asegurarse de usar el driver NVIDIA (Proprietary, tested). Sin esto, Webots irá muy lento.

7. Instalación de ROS 2 Humble

A continuación se detalla los comandos para que, una vez que se inicie sesión en Ubuntu 22.04, se deje listo para realizar simulaciones con ROS 2.

Abrir una terminal (Ctrl + Alt + T) y ejecutar estos bloques de comandos:

7.1. Configurar los Repositorios y las Claves

Primero, autorizar a Ubuntu para que confíe en los servidores de ROS 2.

$ sudo apt update
$ sudo apt install curl gnupg2 lsb-release -y
$ sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

7.2. Instalar ROS 2 Humble (Desktop)

Instalar la versión completa que incluye Rviz2.

$ sudo apt update
$ sudo apt install ros-humble-desktop ros-dev-tools -y

7.3. Instalar Webots y el Driver de ROS 2

Cyberbotics mantiene un repositorio propio, pero la forma más estable de integrarlo con ROS 2 es instalando el paquete oficial del puente:

$ sudo apt install ros-humble-webots-ros2 -y

Nota: Este comando instalará automáticamente una versión compatible de Webots si no se tiene.

7.4. Configurar el Entorno (Automático)

Para no tener que escribir source /opt/ros/humble/setup.bash cada vez que se abre una terminal, se añade a la configuración personal:

$ echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
$ source ~/.bashrc

7.5. Verificación de Seguridad

Para confirmar que todo está en orden, intentar correr el ejemplo oficial de un robot móvil en un entorno simulado:

$ ros2 launch webots_ros2_universal_robot multirobot_launch.py

Al ejecutar este comando te preguntará si instalar Webots, a lo que debes responder ´Y´. Una vez que se instale se deberá abrir una ventana como la siguiente:

Finalmente, con esto queda listo tu entorno para realizar pruebas con ROS 2 y Webots en Ubuntu 22.04 LTS.

Separar caracteres en Arduino

Fecha de publicado: 26-Jul-2018. Fecha de actualización: 19-Oct-2024.

Programa en Arduino para separar caracteres…

String split = "133,215,365";

void setup() {
  Serial.begin(9600);
}

void loop() {
int parte1 = getValue(split,',',0).toInt();
Serial.print(parte1);
delay(1000);
}

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

Actualización (19-oct-2024).

Inicialmente publiqué este código rápidamente porque lo usé en un proyecto en Arduino y quería guardarlo para poder reusarlo en otra ocasión. Ahora le hice algunos cambios para hacerlo más comprensible y agrego una explicación del mismo.

La idea es que en algún momento podemos recibir en Arduino una cadena (String) con valores separados con un caracter, una coma por ejemplo, y necesitamos obtener cada uno de los valores de la cadena.

La función String getValue(String data, char separator, int index), recibe el String data, el cual es recorrido caracter por caracter hasta encontrar el separador indicado por el caracter separator, y regresa la subcadena indicada por el número entero index. Considerando la numeración como en los arreglos, la primera subcadena tiene el índice cero, la segunda 1, y así sucesivamente.

Si se trata de acceder un índice que sobrepasa el número de subcadenas que hay, la función getValue() regresa una cadena vacía. El usuario debe tomar en cuenta esto al usar esta función en sus propios proyectos.

// Programa en C++ para Arduino
// Por: Julio César Sandria Reynoso
// Obtiene las partes de una cadena separada por el caracter indicado
String split = "123,45,67890";
char separador = ',';

void setup() { 
  Serial.begin(9600);
  Serial.print("Cadena a separar: ");
  Serial.println(split);
  
  String parte0 = getValue(split,separador,0);
  Serial.print("parte0 = ");
  Serial.println(parte0);
  
  String parte1 = getValue(split,separador,1);
  Serial.print("parte1 = ");
  Serial.println(parte1);
  
  String parte2 = getValue(split,separador,2);
  Serial.print("parte2 = ");
  Serial.println(parte2);
  
  String parte3 = getValue(split,separador,3);
  Serial.print("parte3 = ");
  Serial.println(parte3);
} 

void loop() { 

} 

String getValue(String data, char separator, int index) { 
  int found = 0;
  int strIndex[] = {0, -1}; 
  int maxIndex = data.length()-1; 
  for(int i=0; i<=maxIndex && found<=index; i++){ 
    if(data.charAt(i)==separator || i==maxIndex) {
      found++; 
      strIndex[0] = strIndex[1]+1; 
      strIndex[1] = (i == maxIndex) ? i+1 : i; 
    } 
  } 
  return found>index ? 
         data.substring(strIndex[0], strIndex[1]) : ""; 
}

La ejecución de este programa muestra en el monitor serial la siguiente salida:

Cadena a separar: 123,45,67890
parte0 = 123
parte1 = 45
parte2 = 67890
parte3 = 

Si quieres aprender sobre robótica con Arduino, programación o algo más relacionado con computación o tecnologías de información, pide informes en el Instituto de Robótica de Xalapa (www.irox.mx).

Mtro. Julio C. Sandria R.

Cursos

En el Instituto de Robótica de Xalapa se imparten cursos y talleres de robótica en verano y permanentes para niños, jóvenes y adultos, tales como:

  • Cursos de Robótica para Niños y Jóvenes
  • Cursos de Arduino
  • Cursos de robótica con Arduino
  • Cursos de robótica con Lego Mindstorms NXT y EV3
  • Cursos de Raspberry Pi

El iRoX cuenta con amplia experiencia en la formación de niños y jóvenes, así como en la participación en eventos y concursos de robótica.

Cursos y talleres 2017

Más información en el sitio web del iRoX: www.iRoX.mx.