Electric handcart

Mit Rehmus entwickelten wir batterie-elektrische, modulare Arbeitsmaschinen für den Einsatz in der Agrarindustrie.

Ideation Process​

Die ersten Schritte bei der Entwicklung eines multifunktionalen Geräts bestehen aus einer intensiven Phase der Ideenfindung, Skizzierung und Experimentierung. Ziel ist es, die idealen Interaktionen und Funktionen in Kombination mit der Form zu erforschen. Gemeinsam mit dem Kunden definieren wir die zentralen Prinzipien und Ziele, um sicherzustellen, dass wir verstehen, wie das Gerät in Zukunft verwendet, wahrgenommen und erweitert werden soll. Diese Erkenntnisse fließen in eine Reihe von Designstudien ein, in denen Form, Funktion und Modularität zu einem kohärenten Ganzen verschmelzen und die Grundlage für die spätere Produktentwicklung bilden.

Control concepts

Defined form examinations

Software Preview
Renderd Image

Function concept for the e-Spreader

3D Design Process

Sobald die Formkommunikation etabliert und die praktischen Interaktionspunkte klar definiert sind, geht der Designprozess in die 3D-Phase über. In dieser Phase nimmt das Konzept durch detaillierte CAD-Modellierung konkrete Gestalt an. Wir verfeinern die Gesamtform, um Proportionen, Ergonomie und visuelle Ausgewogenheit zu bewerten und gleichzeitig zu testen, wie sich das Design unter realen Bedingungen verhält. Dazu gehören unter anderem die Bewertung der Herstellbarkeit aller Baugruppen, die Ermittlung der optimalen Materialstärken und die Definition von Standardteilen. Der Übergang in die 3D-Phase schlägt eine Brücke zwischen der kreativen Absicht und den semantischen Kommunikationszielen und dem Engineering und setzt durch diesen Prozess konzeptionelle Ideen in produktionsreife Formen um.

`; } function createAnnotationHTML(hotspot) { return `
${hotspot.title}
${hotspot.text}
`; } function switchModel(modelConfig, modelViewer) { // Store initial camera position before switching (only first time) if (!modelViewer.hasAttribute('data-initial-orbit')) { const initialOrbit = modelViewer.getAttribute('camera-orbit') || '45deg 71deg auto'; modelViewer.setAttribute('data-initial-orbit', initialOrbit); const initialTarget = modelViewer.getAttribute('camera-target') || 'auto auto auto'; modelViewer.setAttribute('data-initial-target', initialTarget); const initialFov = modelViewer.getAttribute('field-of-view') || '35'; modelViewer.setAttribute('data-initial-fov', initialFov); } // Store current camera state BEFORE switching models const currentOrbit = modelViewer.cameraOrbit; const currentTarget = modelViewer.cameraTarget; const currentFov = modelViewer.fieldOfView; // Update model source modelViewer.setAttribute('src', modelConfig.url); modelViewer.setAttribute('data-base_model_url', modelConfig.url); // Remove existing hotspots const existingHotspots = modelViewer.querySelectorAll('[slot^="hotspot"]'); existingHotspots.forEach(hotspot => hotspot.remove()); // Remove existing annotation descriptions const existingDescriptions = modelViewer.querySelector('.vsd-viewer-descriptions'); if (existingDescriptions) { existingDescriptions.innerHTML = ''; } // Add new hotspots and annotations if (modelConfig.hotspots && modelConfig.hotspots.length > 0) { modelConfig.hotspots.forEach(hotspot => { // Create and insert hotspot element const hotspotDiv = document.createElement('div'); hotspotDiv.innerHTML = createHotspotHTML(hotspot); const hotspotElement = hotspotDiv.firstElementChild; modelViewer.appendChild(hotspotElement); // Add annotation description if (existingDescriptions) { const annotationDiv = document.createElement('div'); annotationDiv.innerHTML = createAnnotationHTML(hotspot); existingDescriptions.appendChild(annotationDiv.firstElementChild); } }); // Wait for model to load, then restore camera position modelViewer.addEventListener('load', () => { // Restore the camera position from before the switch modelViewer.cameraOrbit = currentOrbit; modelViewer.cameraTarget = currentTarget; modelViewer.fieldOfView = currentFov; // Re-attach handlers triggerVisodyInit(modelViewer); }, { once: true }); } else { // No hotspots, but still restore camera modelViewer.addEventListener('load', () => { modelViewer.cameraOrbit = currentOrbit; modelViewer.cameraTarget = currentTarget; modelViewer.fieldOfView = currentFov; }, { once: true }); } } function triggerVisodyInit(modelViewer) { const event = new Event('visody:reinit', { bubbles: true }); modelViewer.dispatchEvent(event); if (window.Visody && typeof window.Visody.initHotspots === 'function') { window.Visody.initHotspots(modelViewer); } if (window.jQuery) { jQuery(modelViewer).trigger('visody:init'); } attachHotspotHandlers(modelViewer); } function attachHotspotHandlers(modelViewer) { const hotspotButtons = modelViewer.querySelectorAll('.vsd-viewer-hotspot-button'); const descriptions = modelViewer.querySelectorAll('.vsd-viewer-annotation-description'); // Store initial camera position for reset const initialOrbit = modelViewer.getAttribute('data-initial-orbit') || modelViewer.getAttribute('camera-orbit') || '45deg 71deg auto'; const initialTarget = modelViewer.getAttribute('data-initial-target') || modelViewer.getAttribute('camera-target') || 'auto auto auto'; const initialFov = modelViewer.getAttribute('data-initial-fov') || modelViewer.fieldOfView || '35deg'; hotspotButtons.forEach(button => { // Remove any existing listeners to avoid duplicates const newButton = button.cloneNode(true); button.parentNode.replaceChild(newButton, button); newButton.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); const ref = this.getAttribute('data-ref'); const orbit = this.getAttribute('data-orbit'); const target = this.getAttribute('data-target'); const fieldOfView = this.getAttribute('data-view'); const animationName = this.getAttribute('data-animation'); const animationAutoplay = this.getAttribute('data-animation-autoplay'); const isActive = this.classList.contains('active'); if (isActive) { // Stop any playing animation if (modelViewer.paused === false) { modelViewer.pause(); } // Reset camera to initial position modelViewer.cameraOrbit = initialOrbit; modelViewer.cameraTarget = initialTarget; modelViewer.fieldOfView = initialFov; // Hide annotation const targetDescription = Array.from(descriptions).find( desc => desc.getAttribute('data-ref') === ref ); if (targetDescription) { targetDescription.classList.remove('active'); } // Deactivate button this.classList.remove('active'); } else { // ACTIVATE: Show annotation, move camera, play animation // First, stop any playing animation from previous hotspot if (modelViewer.paused === false) { modelViewer.pause(); } // Reset camera to initial position before moving to new hotspot modelViewer.cameraOrbit = initialOrbit; modelViewer.cameraTarget = initialTarget; modelViewer.fieldOfView = initialFov; // Small delay to let camera reset setTimeout(() => { // Now move to new position if (orbit) { modelViewer.cameraOrbit = orbit; } if (target) { modelViewer.cameraTarget = target; } if (fieldOfView) { modelViewer.fieldOfView = fieldOfView + 'deg'; } }, 50); // Hide all other annotations and deactivate all other buttons descriptions.forEach(desc => desc.classList.remove('active')); hotspotButtons.forEach(btn => btn.classList.remove('active')); // Handle animation if (animationName) { // Wait for model to load if needed if (modelViewer.loaded) { playAnimation(modelViewer, animationName, animationAutoplay); } else { modelViewer.addEventListener('load', () => { playAnimation(modelViewer, animationName, animationAutoplay); }, { once: true }); } } // Show this annotation const targetDescription = Array.from(descriptions).find( desc => desc.getAttribute('data-ref') === ref ); if (targetDescription) { targetDescription.classList.add('active'); } // Activate button this.classList.add('active'); } }); }); } function playAnimation(modelViewer, animationName, autoplay) { // Check if model has animations if (!modelViewer.availableAnimations || modelViewer.availableAnimations.length === 0) { console.warn('No animations available on this model'); return; } // Check if the requested animation exists if (modelViewer.availableAnimations.includes(animationName)) { modelViewer.animationName = animationName; if (autoplay === '1') { modelViewer.play({ repetitions: 1 }); } } else { console.warn(`Animation "${animationName}" not found in model`); } } // Initialize on page load document.addEventListener('DOMContentLoaded', function() { const modelViewer = document.querySelector('model-viewer'); if (!modelViewer) { console.error('Model viewer not found!'); return; } // Button container const buttonContainer = document.createElement('div'); buttonContainer.classList.add('button-container'); // Buttons for each model models.forEach((model, index) => { const button = document.createElement('button'); button.textContent = model.name; button.classList.add('model-switch-btn'); // Set first button as active if (index === 0) { button.classList.add('model-btn-activated'); } button.addEventListener('click', function() { switchModel(model, modelViewer); // Update button styles - remove active class from all, add to clicked document.querySelectorAll('.model-switch-btn').forEach(btn => { btn.classList.remove('model-btn-activated'); }); this.classList.add('model-btn-activated'); }); buttonContainer.appendChild(button); }); // Insert buttons above the viewer const viewerWrapper = document.querySelector('.vsd-model-viewer-wrapper'); if (viewerWrapper) { viewerWrapper.parentNode.insertBefore(buttonContainer, viewerWrapper); } else { modelViewer.parentNode.insertBefore(buttonContainer, modelViewer); } // Wait for model to load before attaching handlers if (modelViewer.loaded) { attachHotspotHandlers(modelViewer); } else { modelViewer.addEventListener('load', () => { attachHotspotHandlers(modelViewer); }, { once: true }); } });
Control handle
Da dies der wichtigste Interaktionspunkt des gesamten Produkts ist, muss die Bewegung des Rehmus-Transporters so natürlich wie möglich sein. Der Benutzer muss intuitiv verstehen, welche Bewegung des Sticks welche Bewegung des Transporters auslöst.

Modular and flexible

Das Rehmus-System ist modular aufgebaut und lässt sich daher leicht mit neuen Anbaugeräten erweitern. So kann der Benutzer für jede Aufgabe das richtige Zusatzgerät auswählen und ein Hauptwerkzeug über Jahre hinweg nutzen. Rehmus arbeitet eng mit den Anwendern zusammen, um zukünftige Anbaugeräte zu planen und zu entwickeln, sodass das System weiter wachsen und sich an neue Anforderungen anpassen kann. Dies führt zu einem breiteren Anwendungsspektrum und hält das Produkt offen für weitere Verbesserungen.

e-Cleaner

e-Loader

grain spreader

e-Spreader

milk taxi

Mit Kabine und großem

feed mixer

Reuchlinstr. 10
D – 10553 Berlin
+49 / 30 / 47 98 39 50
info[at]lippert-studios.com

Imprint
© LIPPERT STUDIOS