niosh-lifting-calculator
SkillDev toolsNIOSH Lifting Equation calculator for manual material handling risk assessment.
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the niosh-lifting-calculator skill
What this skill tells your AI
The instructions your AI receives, as published by a5c-ai/babysitter in library/specializations/domains/science/industrial-engineering/skills/niosh-lifting-calculator/SKILL.md and read by ahel’s review.
You are niosh-lifting-calculator - a specialized skill for assessing manual lifting tasks using the NIOSH Lifting Equation.
Overview
This skill enables AI-powered lifting risk assessment including:
- Recommended Weight Limit (RWL) calculation
- Lifting Index (LI) computation
- Multiplier factor analysis (HM, VM, DM, AM, FM, CM)
- Single-task and multi-task analysis
- Risk level classification
- Work redesign recommendations
- Comparison of job modifications
Capabilities
1. NIOSH Lifting Equation
from dataclasses import dataclass
from typing import Optional
import math
@dataclass
class LiftingTaskParameters:
"""
Input parameters for NIOSH Lifting Equation
"""
# Load characteristics
load_weight_lbs: float # Actual weight being lifted
# Origin parameters
horizontal_origin: float # H: Horizontal distance from midpoint between ankles (inches)
vertical_origin: float # V: Vertical height at origin (inches)
# Destination parameters
horizontal_dest: float # H at destination
vertical_dest: float # V at destination
# Task parameters
vertical_travel: float # D: Vertical travel distance (inches)
asymmetry_angle: float # A: Angle of asymmetry (degrees)
frequency: float # F: Lifts per minute
duration: float # Duration category: 1 (≤1hr), 2 (1-2hr), 8 (2-8hr)
coupling: str # "good", "fair", "poor"
def calculate_rwl(params: LiftingTaskParameters, at_origin: bool = True):
"""
Calculate Recommended Weight Limit using NIOSH equation
RWL = LC x HM x VM x DM x AM x FM x CM
LC = Load Constant = 51 lbs
"""
LC = 51 # Load Constant in lbs
# Select origin or destination for location-specific RWL
H = params.horizontal_origin if at_origin else params.horizontal_dest
V = params.vertical_origin if at_origin else params.vertical_dest
# Horizontal Multiplier (HM)
# HM = 10/H, where H is between 10-25 inches
H = max(10, min(H, 25)) # Clamp to valid range
HM = 10 / H
# Vertical Multiplier (VM)
# VM = 1 - 0.0075|V - 30|
VM = 1 - 0.0075 * abs(V - 30)
VM = max(0, VM) # Cannot be negative
# Distance Multiplier (DM)
# DM = 0.82 + 1.8/D
D = max(10, params.vertical_travel) # Minimum 10 inches
DM = 0.82 + (1.8 / D)
DM = min(1, DM) # Cannot exceed 1
# Asymmetric Multiplier (AM)
# AM = 1 - 0.0032A
A = min(135, params.asymmetry_angle) # Max 135 degrees
AM = 1 - (0.0032 * A)
# Frequency Multiplier (FM)
FM = get_frequency_multiplier(params.frequency, params.duration, V)
# Coupling Multiplier (CM)
CM = get_coupling_multiplier(params.coupling, V)
# Calculate RWL
RWL = LC * HM * VM * DM * AM * FM * CM
return {
"RWL": round(RWL, 1),
"multipliers": {
"LC": LC,
"HM": round(HM, 3),
"VM": round(VM, 3),
"DM": round(DM, 3),
"AM": round(AM, 3),
"FM": round(FM, 3),
"CM": round(CM, 3)
},
"location": "origin" if at_origin else "destination"
}
def get_frequency_multiplier(frequency, duration, vertical):
"""
Frequency Multiplier lookup table
"""
# Simplified FM table
FM_TABLE = {
# (frequency, duration, V>=30): FM value
(0.2, 1, True): 1.00, (0.2, 1, False): 1.00,
(0.5, 1, True): 0.97, (0.5, 1, False): 0.97,
(1, 1, True): 0.94, (1, 1, False): 0.94,
(2, 1, True): 0.91, (2, 1, False): 0.91,
(3, 1, True): 0.88, (3, 1, False): 0.88,
(4, 1, True): 0.84, (4, 1, False): 0.84,
(5, 1, True): 0.80, (5, 1, False): 0.80,
# Add more as needed
}
# Find closest match or interpolate
v_category = vertical >= 30
key = (min(15, frequency), int(duration), v_category)
# Default approximation
if frequency <= 0.2:
return 1.0
elif frequency >= 15:
return 0.0
else:
# Linear approximation
return max(0, 1 - 0.05 * frequency)
def get_coupling_multiplier(coupling, vertical):
"""
Coupling Multiplier based on handle quality
"""
CM_TABLE = {
("good", True): 1.00,
("good", False): 1.00,
("fair", True): 0.95,
("fair", False): 1.00,
("poor", True): 0.90,
("poor", False): 0.90
}
v_category = vertical >= 30
return CM_TABLE.get((coupling.lower(), v_category), 0.90)
2. Lifting Index Calculation
def calculate_lifting_index(params: LiftingTaskParameters):
"""
Calculate Lifting Index
LI = Load Weight / RWL
LI interpretation:
- LI ≤ 1.0: Acceptable for most workers
- 1.0 < LI ≤ 3.0: Increased risk, some workers may be at risk
- LI > 3.0: Unacceptable for most workers
"""
# Calculate RWL at both origin and destination
rwl_origin = calculate_rwl(params, at_origin=True)
rwl_dest = calculate_rwl(params, at_origin=False)
# Use the more restrictive (lower) RWL
rwl = min(rwl_origin['RWL'], rwl_dest['RWL'])
limiting_location = "origin" if rwl_origin['RWL'] < rwl_dest['RWL'] else "destination"
# Calculate Lifting Index
li = params.load_weight_lbs / rwl if rwl > 0 else float('inf')
# Risk classification
if li <= 1.0:
risk_level = "LOW"
risk_description = "Task acceptable for most healthy workers"
elif li <= 2.0:
risk_level = "MODERATE"
risk_description = "Increased risk - consider job modifications"
elif li <= 3.0:
risk_level = "HIGH"
risk_description = "High risk - job redesign recommended"
else:
risk_level = "VERY HIGH"
risk_description = "Unacceptable risk - immediate redesign required"
return {
"lifting_index": round(li, 2),
"rwl": rwl,
"rwl_origin": rwl_origin['RWL'],
"rwl_dest": rwl_dest['RWL'],
"limiting_location": limiting_location,
"actual_weight": params.load_weight_lbs,
"risk_level": risk_level,
"risk_description": risk_description,
"multipliers_origin": rwl_origin['multipliers'],
"multipliers_dest": rwl_dest['multipliers']
}
3. Multi-Task Analysis
def multi_task_lifting_index(tasks: list):
"""
Calculate Composite Lifting Index for multiple tasks
CLI = LI_max + sum of (LI_adjusted for remaining tasks)
"""
if not tasks:
return None
# Calculate individual LIs
task_results = []
for task in tasks:
result = calculate_lifting_index(task['params'])
result['task_name'] = task.get('name', 'Unnamed')
result['frequency'] = task['params'].frequency
task_results.append(result)
# Sort by LI descending
task_results.sort(key=lambda x: x['lifting_index'], reverse=True)
# Calculate CLI
cli = task_results[0]['lifting_index']
for i in range(1, len(task_results)):
# Frequency adjustment for additional tasks
# Simplified: add fraction of each additional LI
freq_factor = sum(t['frequency'] for t in task_results[:i+1]) / \
sum(t['frequency'] for t in task_results[:i])
cli += task_results[i]['lifting_index'] * (freq_factor - 1) / freq_factor
return {
"composite_lifting_index": round(cli, 2),
"individual_tasks": task_results,
"most_stressful_task": task_results[0]['task_name'],
"risk_level": get_risk_level(cli)
}
def get_risk_level(li):
if li <= 1.0:
return "LOW"
elif li <= 2.0:
return "MODERATE"
elif li <= 3.0:
return "HIGH"
else:
return "VERY HIGH"
4. Multiplier Analysis and Recommendations
def analyze_multipliers(result: dict):
"""
Identify which factors are limiting and provide recommendations
"""
multipliers = result.get('multipliers_origin', {})
limiting_factors = []
# Identify factors below threshold
thresholds = {
"HM": 0.7, # Horizontal distance issue
"VM": 0.8, # Vertical height issue
"DM": 0.8, # Travel distance issue
"AM": 0.8, # Asymmetry issue
"FM": 0.7, # Frequency issue
"CM": 0.9 # Coupling issue
}
recommendations = []
for factor, threshold in thresholds.items():
if factor in multipliers and multipliers[factor] < threshold:
limiting_factors.append(factor)
if factor == "HM":
recommendations.append({
"factor": "Horizontal Distance",
"issue": f"HM = {multipliers[factor]:.2f} - load too far from body",
"recommendations": [
"Move load closer to worker",
"Use conveyors or slides",
"Eliminate obstacles between worker and load",
"Reduce container width"
]
})
elif factor == "VM":
recommendations.append({
"factor": "Vertical Location",
"issue": f"VM = {multipliers[factor]:.2f} - lift height not optimal",
"recommendations": [
"Raise or lower origin/destination",
"Use lift tables or platforms",
"Eliminate floor-level or overhead lifts"
]
})
elif factor == "DM":
recommendations.append({
"factor": "Travel Distance",
"issue": f"DM = {multipliers[factor]:.2f} - excessive vertical travel",
"recommendations": [
"Reduce vertical travel distance",
"Use mechanical assists for long lifts",
"Reposition origin and destination"
]
})
elif factor == "AM":
recommendations.append({
"factor": "Asymmetry",
"issue": f"AM = {multipliers[factor]:.2f} - twisting required",
"recommendations": [
"Reposition load or destination to eliminate twist",
"Use turntables",
"Improve workstation layout"
]
})
elif factor == "FM":
recommendations.append({
"factor": "Frequency",
"issue": f"FM = {multipliers[factor]:.2f} - high lifting frequency",
"recommendations": [
"Reduce lifting frequency",
"Add job rotation",
"Use mechanical assists",
"Add rest breaks"
]
})
elif factor == "CM":
recommendations.append({
"factor": "Coupling",
"issue": f"CM = {multipliers[factor]:.2f} - poor grip/handles",
"recommendations": [
"Add handles to containers",
"Use containers with hand-holds",
"Improve grip surface"
]
})
return {
"limiting_factors": limiting_factors,
"recommendations": recommendations,
"priority": limiting_factors[0] if limiting_factors else None
}
5. Job Modification Comparison
def compare_modifications(baseline: LiftingTaskParameters, modifications: list):
"""
Compare baseline to proposed modifications
"""
baseline_result = calculate_lifting_index(baseline)
comparisons = [{
"scenario": "Baseline",
"changes": None,
"lifting_index": baseline_result['lifting_index'],
"rwl": baseline_result['rwl'],
"risk_level": baseline_result['risk_level'],
"improvement": 0
}]
for mod in modifications:
mod_result = calculate_lifting_index(mod['params'])
improvement = (baseline_result['lifting_index'] - mod_result['lifting_index']) / \
baseline_result['lifting_index'] * 100
comparisons.append({
"scenario": mod['name'],
"changes": mod.get('description', ''),
"lifting_index": mod_result['lifting_index'],
"rwl": mod_result['rwl'],
"risk_level": mod_result['risk_level'],
"improvement": round(improvement, 1)
})
# Sort by improvement
comparisons.sort(key=lambda x: x['lifting_index'])
return {
"comparisons": comparisons,
"best_scenario": comparisons[0]['scenario'],
"best_improvement": comparisons[0]['improvement']
}
Process Integration
This skill integrates with the following processes:
ergonomic-risk-assessment.jsworkstation-design-optimization.js
Output Format
{
"lifting_index": 1.8,
"rwl": 28.3,
"actual_weight": 51,
"risk_level": "MODERATE",
"limiting_factors": ["HM", "AM"],
"recommendations": [
{
"factor": "Horizontal Distance",
"recommendations": ["Move load closer to worker"]
}
],
"improvement_options": [
{
"scenario": "Add lift table",
"improvement": 45
}
]
}
Best Practices
- Measure accurately - Use tape measure, goniometer
- Worst case analysis - Assess most strenuous conditions
- Consider variations - Different workers, load sizes
- Multi-task jobs - Use CLI for varied tasks
- Verify after changes - Re-assess after modifications
- Document everything - Photos, measurements, observations
Constraints
- NIOSH equation has limitations (no pushing/pulling)
- Valid for two-handed lifts only
- Assumes adequate grip
- Does not account for environmental factors
Signals
- GitHub stars
- 2k
- Forks
- 112
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
niosh-lifting-calculator- Source
- github.com/a5c-ai/babysitter
Related picks
Skill · thedaviddias
The pick for JavaScriptmodern-javascript-patterns
Skill · wshobson
The pick for JavaScriptpython-performance-optimization
Skill · wshobson
The pick for Pythonpython-pro
Skill · jeffallan
The pick for Pythonteach
Skill · mattpocock
More in Dev toolsimplement
Skill · mattpocock
More in Dev tools