diff --git a/.gitignore b/.gitignore
index 36ea87ed9..f63c2ba4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,15 @@
# Python
__pycache__/
+
+# RMA experiment runtime/build artifacts. Curated small reports live in results/rma/.
+build/
+build-*/
+*.pt
+*.pth
+*.onnx
+*.engine
+*.plan
+events.out.tfevents.*
dist/
.eggs/
*.egg-info/
diff --git a/README.md b/README.md
index 2fbfad7e6..7d608d776 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,10 @@ Contract-driven infrastructure for robot learning across physics backends and ha
Languages: English | 简体中文
+> **Fork experiment: Go2 RMA locomotion.** See the [experiment portfolio](docs/rma/README.md)
+> for teacher/student code, reproducible evaluation data, learning curves and C++ mock deployment.
+> Current forward-speed tracking has not reached the target; failures and reproduction limits are documented.
+
diff --git a/README_zh.md b/README_zh.md
index 4654bd779..158c83643 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -6,6 +6,9 @@
语言:简体中文 | English
+> **本 fork 的 Go2 RMA 运动控制实验**:[查看项目展示与实验记录](docs/rma/README.md)。
+> 包含教师/学生代码、真实评估数据、训练曲线和 C++ mock 部署;当前前进速度跟踪尚未达标。
+
diff --git a/deploy_cpp/CMakeLists.txt b/deploy_cpp/CMakeLists.txt
new file mode 100644
index 000000000..27273da76
--- /dev/null
+++ b/deploy_cpp/CMakeLists.txt
@@ -0,0 +1,43 @@
+cmake_minimum_required(VERSION 3.20)
+project(unilab_rma_deploy LANGUAGES CXX)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+option(WITH_TENSORRT "Build TensorRT 10 policy inference" OFF)
+option(ENABLE_TSAN "Enable thread sanitizer on supported Unix compilers" OFF)
+find_package(Threads REQUIRED)
+add_executable(control_loop src/main_control_loop.cpp)
+add_executable(test_double_buffer tests/test_double_buffer.cpp)
+add_executable(test_control_mapping tests/test_control_mapping.cpp)
+foreach(target control_loop test_double_buffer test_control_mapping)
+ target_include_directories(${target} PRIVATE include)
+ target_link_libraries(${target} PRIVATE Threads::Threads)
+ if(MSVC)
+ target_compile_options(${target} PRIVATE /W4 /EHsc)
+ else()
+ target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic)
+ if(ENABLE_TSAN)
+ target_compile_options(${target} PRIVATE -fsanitize=thread -g)
+ target_link_options(${target} PRIVATE -fsanitize=thread)
+ endif()
+ endif()
+endforeach()
+if(WITH_TENSORRT)
+ find_package(CUDAToolkit REQUIRED)
+ find_path(TENSORRT_INCLUDE NvInfer.h HINTS ${TENSORRT_ROOT}/include REQUIRED)
+ find_library(TENSORRT_LIBRARY nvinfer HINTS ${TENSORRT_ROOT}/lib ${TENSORRT_ROOT}/lib64 REQUIRED)
+ target_compile_definitions(control_loop PRIVATE WITH_TENSORRT)
+ target_include_directories(control_loop PRIVATE ${TENSORRT_INCLUDE})
+ target_link_libraries(control_loop PRIVATE ${TENSORRT_LIBRARY} CUDA::cudart)
+ add_executable(policy_worker src/policy_worker.cpp)
+ target_include_directories(policy_worker PRIVATE include ${TENSORRT_INCLUDE})
+ target_link_libraries(policy_worker PRIVATE ${TENSORRT_LIBRARY} CUDA::cudart)
+ if(MSVC)
+ target_compile_options(policy_worker PRIVATE /W4 /EHsc)
+ else()
+ target_compile_options(policy_worker PRIVATE -Wall -Wextra -Wpedantic)
+ endif()
+endif()
+enable_testing()
+add_test(NAME double_buffer_consistency COMMAND test_double_buffer)
+add_test(NAME mock_control_loop COMMAND control_loop --seconds 1)
+add_test(NAME policy_actuator_mapping COMMAND test_control_mapping)
diff --git a/deploy_cpp/include/ControlMapping.hpp b/deploy_cpp/include/ControlMapping.hpp
new file mode 100644
index 000000000..c4ea953e6
--- /dev/null
+++ b/deploy_cpp/include/ControlMapping.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include
+
+namespace rma {
+// Policy/observations: FL FR RL RR. Scene actuator storage: FR FL RR RL.
+// Per leg: hip, thigh, calf. Verify the scene contract before hardware use.
+inline constexpr std::array policyToActuator{3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8};
+
+inline std::array actuatorTargets(
+ const std::array& home,
+ const std::array& policyAction,
+ float scale = 0.25f) {
+ std::array target{};
+ for (int joint = 0; joint < 12; ++joint) {
+ const int actuator = policyToActuator[joint];
+ target[actuator] = home[actuator] + scale * policyAction[joint];
+ }
+ return target;
+}
+} // namespace rma
diff --git a/deploy_cpp/include/DoubleBuffer.hpp b/deploy_cpp/include/DoubleBuffer.hpp
new file mode 100644
index 000000000..9d475c208
--- /dev/null
+++ b/deploy_cpp/include/DoubleBuffer.hpp
@@ -0,0 +1,54 @@
+#pragma once
+#include
+#include
+#include
+
+// Single producer / single consumer, latest-value mailbox, exactly two payload slots.
+// Publication alone is insufficient: slot ownership prevents payload data races.
+// Nonblocking try operations: caller retains last valid value on read failure.
+template class DoubleBuffer {
+ static_assert(std::is_trivially_copyable_v, "Payload must be trivially copyable");
+ static_assert(std::atomic::is_always_lock_free, "Requires lock-free atomic");
+ enum { Free=0, Writing=1, Ready=2, Reading=3 };
+ struct alignas(64) Slot {
+ std::atomic state{Free};
+ T value{};
+ };
+ std::array slots_{};
+ std::atomic published_{-1};
+public:
+ bool tryWrite(const T& value) noexcept {
+ const int previous=published_.load(std::memory_order_acquire);
+ const int first=previous<0?0:1-previous;
+ for(int attempt=0;attempt<2;++attempt){
+ const int index=attempt==0?first:1-first;
+ auto& slot=slots_[index];
+ int state=slot.state.load(std::memory_order_acquire);
+ if(state!=Free && state!=Ready) continue;
+ if(!slot.state.compare_exchange_strong(state,Writing,
+ std::memory_order_acq_rel,std::memory_order_relaxed)) continue;
+ slot.value=value;
+ // Announce while Writing, then release the payload. A reader of an
+ // old index cannot consume a recycled slot before its publication;
+ // Ready acquire also orders the publication before its next read.
+ published_.store(index,std::memory_order_release);
+ slot.state.store(Ready,std::memory_order_release);
+ return true;
+ }
+ return false;
+ }
+ bool tryRead(T& value) noexcept {
+ const int index=published_.load(std::memory_order_acquire);
+ if(index<0) return false;
+ auto& slot=slots_[index];
+ int state=Ready;
+ if(!slot.state.compare_exchange_strong(state,Reading,
+ std::memory_order_acq_rel,std::memory_order_relaxed)) return false;
+ value=slot.value;
+ slot.state.store(Free,std::memory_order_release);
+ return true;
+ }
+ DoubleBuffer()=default;
+ DoubleBuffer(const DoubleBuffer&)=delete;
+ DoubleBuffer& operator=(const DoubleBuffer&)=delete;
+};
diff --git a/deploy_cpp/include/TensorRTPolicy.hpp b/deploy_cpp/include/TensorRTPolicy.hpp
new file mode 100644
index 000000000..a6adfdf0b
--- /dev/null
+++ b/deploy_cpp/include/TensorRTPolicy.hpp
@@ -0,0 +1,80 @@
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+class TensorRTPolicy {
+ struct Logger : nvinfer1::ILogger {
+ void log(Severity severity,const char* msg) noexcept override {
+ if(severity<=Severity::kERROR) std::fprintf(stderr,"TensorRT: %s\n",msg);
+ }
+ } logger_;
+ std::unique_ptr runtime_;
+ std::unique_ptr engine_;
+ std::unique_ptr context_;
+ cudaStream_t stream_{};
+ void *obs_{},*history_{},*action_{};
+ static void check(cudaError_t result){
+ if(result!=cudaSuccess) throw std::runtime_error(cudaGetErrorString(result));
+ }
+ void cleanup() noexcept {
+ if(stream_) cudaStreamSynchronize(stream_);
+ if(obs_) cudaFree(obs_);
+ if(history_) cudaFree(history_);
+ if(action_) cudaFree(action_);
+ if(stream_) cudaStreamDestroy(stream_);
+ }
+ void require(const char* name,nvinfer1::TensorIOMode mode,std::initializer_list shape){
+ if(engine_->getTensorIOMode(name)!=mode || engine_->getTensorDataType(name)!=nvinfer1::DataType::kFLOAT ||
+ engine_->getTensorLocation(name)!=nvinfer1::TensorLocation::kDEVICE)
+ throw std::runtime_error(std::string("Engine IO type/mode mismatch: ")+name);
+ const auto dims=engine_->getTensorShape(name);
+ if(dims.nbDims!=static_cast(shape.size())) throw std::runtime_error("Engine rank mismatch");
+ int i=0;
+ for(int d:shape) if(dims.d[i++]!=d) throw std::runtime_error("Engine shape mismatch");
+ }
+public:
+ explicit TensorRTPolicy(const std::string& path){
+ try {
+ std::ifstream file(path,std::ios::binary);
+ if(!file) throw std::runtime_error("Cannot open TensorRT engine");
+ std::vector bytes((std::istreambuf_iterator(file)),{});
+ runtime_.reset(nvinfer1::createInferRuntime(logger_));
+ if(!runtime_) throw std::runtime_error("Cannot create TensorRT runtime");
+ engine_.reset(runtime_->deserializeCudaEngine(bytes.data(),bytes.size()));
+ if(!engine_) throw std::runtime_error("Cannot deserialize engine");
+ if(engine_->getNbIOTensors()!=3) throw std::runtime_error("Expected exactly 3 IO tensors");
+ require("observation",nvinfer1::TensorIOMode::kINPUT,{1,49});
+ require("history",nvinfer1::TensorIOMode::kINPUT,{1,50,49});
+ require("action",nvinfer1::TensorIOMode::kOUTPUT,{1,12});
+ context_.reset(engine_->createExecutionContext());
+ if(!context_) throw std::runtime_error("Cannot create execution context");
+ check(cudaStreamCreate(&stream_));
+ check(cudaMalloc(&obs_,49*sizeof(float)));
+ check(cudaMalloc(&history_,2450*sizeof(float)));
+ check(cudaMalloc(&action_,12*sizeof(float)));
+ if(!context_->setTensorAddress("observation",obs_) ||
+ !context_->setTensorAddress("history",history_) ||
+ !context_->setTensorAddress("action",action_)) throw std::runtime_error("Cannot bind IO");
+ } catch(...) { cleanup(); throw; }
+ }
+ ~TensorRTPolicy(){ cleanup(); }
+ void infer(const std::array& obs,const std::array& history,
+ std::array& action){
+ check(cudaMemcpyAsync(obs_,obs.data(),sizeof(obs),cudaMemcpyHostToDevice,stream_));
+ check(cudaMemcpyAsync(history_,history.data(),sizeof(history),cudaMemcpyHostToDevice,stream_));
+ if(!context_->enqueueV3(stream_)) throw std::runtime_error("enqueueV3 failed");
+ check(cudaMemcpyAsync(action.data(),action_,sizeof(action),cudaMemcpyDeviceToHost,stream_));
+ check(cudaStreamSynchronize(stream_));
+ }
+ TensorRTPolicy(const TensorRTPolicy&)=delete;
+ TensorRTPolicy& operator=(const TensorRTPolicy&)=delete;
+};
diff --git a/deploy_cpp/src/main_control_loop.cpp b/deploy_cpp/src/main_control_loop.cpp
new file mode 100644
index 000000000..194c3dea0
--- /dev/null
+++ b/deploy_cpp/src/main_control_loop.cpp
@@ -0,0 +1,195 @@
+// Timing/IO framework. MOCK ROBOT ONLY: no Unitree SDK commands are sent.
+// C++17, TensorRT 10 optional, static FP32 IO with optional internal FP16 engine.
+#include "DoubleBuffer.hpp"
+#include "ControlMapping.hpp"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef WITH_TENSORRT
+#include "TensorRTPolicy.hpp"
+#endif
+
+using Clock=std::chrono::steady_clock;
+std::int64_t nowNs(){return std::chrono::duration_cast(Clock::now().time_since_epoch()).count();}
+struct Sensor {
+ // q,dq in joint order FL FR RL RR; q0 is supplied in actuator order FR FL RR RL.
+ std::array q{},dq{};
+ std::array gyro{},gravity{0,0,-1},command{};
+ std::int64_t stamp{};
+};
+struct Command {
+ std::array target{};
+ std::int64_t stamp{};
+ std::uint64_t sequence{};
+};
+struct ControlConfig {
+ std::array q0{},kp{},kd{},limit{};
+ ControlConfig(){kp.fill(35);kd.fill(.5);limit.fill(10);}
+ void load(const std::string& path){
+ std::ifstream f(path);
+ if(!f) throw std::runtime_error("Cannot read control config");
+ for(int i=0;i<12;++i){
+ if(!(f>>q0[i]>>kp[i]>>kd[i]>>limit[i]) || !std::isfinite(q0[i]) ||
+ !std::isfinite(kp[i]) || !std::isfinite(kd[i]) || !std::isfinite(limit[i]) ||
+ kp[i]<0 || kd[i]<0 || limit[i]<=0) throw std::runtime_error("Invalid control config row");
+ }
+ std::string extra;
+ if(f>>extra) throw std::runtime_error("Control config must contain exactly 12 rows of q0 kp kd torque_limit");
+ }
+};
+// Joint -> actuator index, based on copied YAML; verify against materialized scene before real use.
+constexpr auto jointToAct=rma::policyToActuator;
+
+int main(int argc,char** argv){
+ try {
+ int seconds=5;
+ std::string enginePath, configPath;
+ for(int i=1;i3600) throw std::runtime_error("seconds must be 1..3600");
+ ControlConfig cfg;
+ if(!configPath.empty()) cfg.load(configPath);
+ if(!enginePath.empty() && configPath.empty()) throw std::runtime_error("Engine requires matching home/PD config");
+#ifdef WITH_TENSORRT
+ std::unique_ptr policy;
+ if(!enginePath.empty()){
+ policy=std::make_unique(enginePath);
+ // Trigger lazy CUDA/kernel initialization before timed control starts.
+ std::array warmObs{};
+ std::array warmHistory{};
+ std::array warmAction{};
+ policy->infer(warmObs,warmHistory,warmAction);
+ for(float a:warmAction) if(!std::isfinite(a)) throw std::runtime_error("Non-finite warm-up action");
+ std::cout<<"TensorRT engine loaded; IO checked; warm-up complete\n";
+ }
+#else
+ if(!enginePath.empty()) throw std::runtime_error("Rebuild with WITH_TENSORRT=ON");
+#endif
+ std::cout<<"MOCK ROBOT ONLY; "<<(enginePath.empty()?"zero-action mock policy":"TensorRT policy")
+ <<"; 50 Hz policy / 1000 Hz PD requested\n";
+ DoubleBuffer sensors;
+ DoubleBuffer commands;
+ std::atomic stop{false};
+ std::atomic fastTicks{0},slowTicks{0},stale{0},fastMiss{0},slowMiss{0};
+ // Thread-owned statistics; main reads them only after both joins.
+ std::uint64_t commandsPublished=0,commandsConsumed=0;
+ float maxActionAbs=0.f,maxTargetOffset=0.f,maxTorqueAbs=0.f;
+#ifdef WITH_TENSORRT
+ std::uint64_t inferenceCalls=0;
+ double inferenceTotalMs=0.,inferenceMaxMs=0.;
+#endif
+ std::string failure; // Written only by slow thread; read after join.
+ const auto end=Clock::now()+std::chrono::seconds(seconds);
+ std::thread fast([&]{
+ Sensor s;
+ for(int j=0;j<12;++j) s.q[j]=cfg.q0[jointToAct[j]];
+ Command active;
+ auto deadline=Clock::now();
+ while(!stop.load(std::memory_order_acquire) && Clock::now()active.sequence){
+ active=candidate;
+ ++commandsConsumed;
+ }
+ const bool fresh=active.sequence>0 && s.stamp>=active.stamp && s.stamp-active.stamp<100000000;
+ if(!fresh) ++stale;
+ for(int j=0;j<12;++j){
+ const int a=jointToAct[j];
+ float torque=fresh?cfg.kp[a]*(active.target[a]-s.q[j])-cfg.kd[a]*s.dq[j]:0.f;
+ torque=std::clamp(torque,-cfg.limit[a],cfg.limit[a]);
+ maxTorqueAbs=std::max(maxTorqueAbs,std::abs(torque));
+ // Mock plant, no gravity/contact. Replace with timestamped SDK sensor/command IO.
+ s.dq[j]+=(torque-.2f*s.dq[j])/.2f*.001f;
+ s.q[j]+=s.dq[j]*.001f;
+ }
+ ++fastTicks;
+ deadline+=std::chrono::milliseconds(1);
+ if(Clock::now()>deadline){++fastMiss;deadline=Clock::now();}
+ std::this_thread::sleep_until(deadline);
+ }
+ stop.store(true,std::memory_order_release);
+ });
+ std::thread slow([&]{
+ try {
+ std::array history{};
+ std::array previous{};
+ auto deadline=Clock::now();
+ std::uint64_t sequence=0;
+ float phase=0.f;
+ while(!stop.load(std::memory_order_acquire)){
+ Sensor s;
+ if(sensors.tryRead(s) && nowNs()-s.stamp<20000000){
+ std::array obs{};
+ for(int i=0;i<3;++i){obs[i]=s.gyro[i];obs[3+i]=s.gravity[i];obs[42+i]=s.command[i];}
+ for(int j=0;j<12;++j){obs[6+j]=s.q[j]-cfg.q0[jointToAct[j]];obs[18+j]=s.dq[j];obs[30+j]=previous[j];}
+ // Reset phase on process start. Real runtime must match environment phase resets.
+ constexpr float offsets[4]={0,.5f,.5f,0};
+ for(int i=0;i<4;++i) obs[45+i]=std::fmod(phase+offsets[i],1.f);
+ // Shift left explicitly; no overlapping std::copy ranges.
+ for(int i=0;i<2450-49;++i) history[i]=history[i+49];
+ std::copy(obs.begin(),obs.end(),history.end()-49);
+ std::array action{};
+#ifdef WITH_TENSORRT
+ if(policy){
+ const auto started=Clock::now();
+ policy->infer(obs,history,action);
+ const double elapsed=std::chrono::duration(Clock::now()-started).count();
+ ++inferenceCalls;
+ inferenceTotalMs+=elapsed;
+ inferenceMaxMs=std::max(inferenceMaxMs,elapsed);
+ }
+#endif
+ Command cmd;
+ cmd.stamp=s.stamp; // Sensor age includes inference latency.
+ cmd.sequence=++sequence;
+ for(int i=0;i<12;++i){
+ if(!std::isfinite(action[i])) throw std::runtime_error("Non-finite model action");
+ action[i]=std::clamp(action[i],-1.f,1.f);
+ maxActionAbs=std::max(maxActionAbs,std::abs(action[i]));
+ }
+ cmd.target=rma::actuatorTargets(cfg.q0,action);
+ for(int i=0;i<12;++i){
+ maxTargetOffset=std::max(maxTargetOffset,std::abs(cmd.target[i]-cfg.q0[i]));
+ }
+ if(commands.tryWrite(cmd)){
+ previous=action;
+ ++commandsPublished;
+ }
+ phase=std::fmod(phase+.04f,1.f); // Same float32 0.02s * 2Hz update as training.
+ ++slowTicks;
+ }
+ deadline+=std::chrono::milliseconds(20);
+ if(Clock::now()>deadline){++slowMiss;deadline=Clock::now();}
+ std::this_thread::sleep_until(deadline);
+ }
+ } catch(const std::exception& e){failure=e.what();stop.store(true,std::memory_order_release);}
+ });
+ fast.join();slow.join();
+ std::cout<<"PD ticks="<0) std::cout<<"TensorRT calls="<
+#include
+#include
+#include
+
+int main(int argc,char** argv){
+ static_assert(sizeof(float)==4 && std::numeric_limits::is_iec559,
+ "The worker protocol requires IEEE754 float32");
+ try {
+ if(argc!=3 || std::string(argv[1])!="--engine")
+ throw std::runtime_error("Usage: policy_worker --engine file.engine");
+ const std::uint32_t endian=1;
+ if(*reinterpret_cast(&endian)!=1)
+ throw std::runtime_error("The worker protocol requires little endian");
+ TensorRTPolicy policy(argv[2]);
+ std::array obs{};
+ std::array history{};
+ std::array action{};
+ policy.infer(obs,history,action); // Finish CUDA initialization before handshake.
+ for(float value:action) if(!std::isfinite(value))
+ throw std::runtime_error("Non-finite warm-up output");
+ const std::array dimensions{49,50,12};
+ std::cout.write("RMA1",4);
+ std::cout.write(reinterpret_cast(dimensions.data()),sizeof(dimensions));
+ std::cout.flush();
+ while(true){
+ std::cin.read(reinterpret_cast(obs.data()),sizeof(obs));
+ if(std::cin.gcount()==0 && std::cin.eof()) break;
+ if(!std::cin) throw std::runtime_error("Incomplete observation frame");
+ std::cin.read(reinterpret_cast(history.data()),sizeof(history));
+ if(!std::cin) throw std::runtime_error("Incomplete history frame");
+ for(float value:obs) if(!std::isfinite(value))
+ throw std::runtime_error("Non-finite observation input");
+ for(float value:history) if(!std::isfinite(value))
+ throw std::runtime_error("Non-finite history input");
+ policy.infer(obs,history,action);
+ for(float value:action) if(!std::isfinite(value))
+ throw std::runtime_error("Non-finite action output");
+ std::cout.write(reinterpret_cast(action.data()),sizeof(action));
+ std::cout.flush();
+ if(!std::cout) throw std::runtime_error("Cannot write action frame");
+ }
+ return 0;
+ } catch(const std::exception& error){
+ std::cerr<<"TensorRT worker: "<
+#include
+#include
+
+int main() {
+ // Independent expected destinations; nonuniform home values expose swaps.
+ constexpr std::array expected{3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8};
+ std::array home{};
+ for (int index = 0; index < 12; ++index) home[index] = 0.1f * index;
+ for (int joint = 0; joint < 12; ++joint) {
+ std::array action{};
+ action[joint] = 1.0f;
+ const auto target = rma::actuatorTargets(home, action);
+ for (int actuator = 0; actuator < 12; ++actuator) {
+ const float wanted = home[actuator] + (actuator == expected[joint] ? 0.25f : 0.0f);
+ if (std::abs(target[actuator] - wanted) > 1e-6f) {
+ std::cerr << "Wrong target for policy joint " << joint
+ << ", actuator " << actuator << '\n';
+ return 1;
+ }
+ }
+ }
+ std::cout << "All 12 one-hot policy actions reach the expected actuator\n";
+ return 0;
+}
diff --git a/deploy_cpp/tests/test_double_buffer.cpp b/deploy_cpp/tests/test_double_buffer.cpp
new file mode 100644
index 000000000..6d03ac6c9
--- /dev/null
+++ b/deploy_cpp/tests/test_double_buffer.cpp
@@ -0,0 +1,39 @@
+#include "DoubleBuffer.hpp"
+#include
+#include
+#include
+#include
+#include
+struct Payload {std::uint64_t sequence{};std::array values{};};
+int main(){
+ DoubleBuffer buffer;
+ Payload first;
+ if(buffer.tryRead(first)) return 1;
+ std::atomic done{false};
+ std::atomic errors{0};
+ std::uint64_t count=0;
+ std::thread writer([&]{
+ for(std::uint64_t i=1;i<=200000;++i){
+ Payload p;p.sequence=i;p.values.fill(i);
+ while(!buffer.tryWrite(p)) std::this_thread::yield();
+ }
+ done.store(true,std::memory_order_release);
+ });
+ std::thread reader([&]{
+ std::uint64_t last=0;
+ auto verify=[&](const Payload& p){
+ if(p.sequence<=last) ++errors;
+ for(auto v:p.values) if(v!=p.sequence) ++errors;
+ last=p.sequence;++count;
+ };
+ while(!done.load(std::memory_order_acquire)){
+ Payload p;
+ if(buffer.tryRead(p)) verify(p);
+ }
+ Payload p;
+ if(buffer.tryRead(p)) verify(p);
+ });
+ writer.join();reader.join();
+ std::cout<<"snapshots="<0?0:1;
+}
diff --git a/docs/rma/EXPERIMENT_WORKFLOW.md b/docs/rma/EXPERIMENT_WORKFLOW.md
new file mode 100644
index 000000000..25a919034
--- /dev/null
+++ b/docs/rma/EXPERIMENT_WORKFLOW.md
@@ -0,0 +1,151 @@
+# 从一次评估到一份可复查的实验记录
+
+当前步骤与完整命令导航见 [项目工作流](PROJECT_WORKFLOW.md)。
+
+## 先分清三种“完成”
+
+组件验证:RMA 接口、历史缓冲、导出接口、C++ mock 等已有测试。
+框架兼容:本地运行副本是 1.3.3,GitHub fork 基线是 1.3.4,整仓类型检查尚未通过。
+任务效果:已有教师未达到 0.5 m/s 前进指令。配置能运行,不意味着策略已经学会任务。
+
+后续完整接入应先固定一套源码版本,在独立环境里匹配依赖和资产,完成整仓门禁,
+再做真实环境的训练、评估、ONNX/TensorRT 数值与任务效果验证。
+不要把新 fork 整个覆盖到现有可运行目录,也不要在现有环境盲目升级所有依赖。
+目前仍以原可运行目录的教师作为诊断对象;本次仅增量更新评估追踪与部署映射代码。
+
+## 第一件事:给现有模型记录数据
+
+这是评估,不更新网络权重。训练入口和奖励配置不需要为记录数据而修改。
+`--trace-dir` 是可选开关;不开启时不导入追踪器、不创建文件、不读取逐环境奖励。
+开启后仅评估阶段多出文件写入和 CPU 拷贝,不能承诺记录本身零开销。
+
+在已经匹配好依赖和资产的原运行目录中执行:
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python scripts/evaluate_rma.py \
+ --policy teacher \
+ --checkpoint runs/rma/teacher_forward_v1.pt \
+ --task go2_joystick_flat/rma_forward \
+ --num-envs 8 --steps 1000 --seed 123 \
+ --command 0.5 0 0 --diagnostics \
+ --trace-dir runs/rma/evaluations/EXP-002/seed123 \
+ --trace-warmup-steps 100
+```
+
+每次都会在指定父目录下创建独立的 `eval_` 子目录,重复运行不覆盖旧记录。
+终端 JSON 的 `trace.directory` 给出本次的准确绝对路径。
+
+| 文件 | 保存什么 |
+|---|---|
+| `transitions.csv` | 每一步、每个环境一行:目标/实际速度、12 维动作、关节相对角度/角速度、奖励分项、回合编号及终止标记 |
+| `run_config.json` | 命令参数、checkpoint SHA256、可获取的 Git 信息、关键源码 SHA256、实际控制周期、关节顺序和 scale/offset |
+| `task_source_snapshot/*.yaml` | 当次运行目录的任务源配置,包含可用的消融任务;不是完整物化 Hydra 配置,也不包含资产或依赖 |
+| `summary.json` | 原评估结果,以及动作范围、动作接近边界比例、全程和启动窗口外的速度误差 |
+
+1000 步 × 8 环境应得到 8000 行数据,另加一行 CSV 表头。
+`before_*` 对应动作执行前的状态,`after_*` 对应执行后的终止状态;结束回合时不会误记重置后的姿态。
+`episode_id` 与 `episode_step` 将各环境的不同回合分开。
+
+`reward_rate/` 是**已经乘奖励权重、还没有乘控制 dt** 的分项。
+`reward` 才是该环境这一步实际返回的总奖励。不要直接把分项 rate 与 reward 比大小。
+当前任务使用 dt 缩放时,分项 rate 之和乘 dt 才能与该步 reward 核对;不能跨不同权重直接比较总奖励。
+
+`normalized_action_near_bound_fraction` 统计 `|action| >= 0.95` 的比例。
+它只是 tanh 动作接近输出边界的指标,不能证明电机扭矩饱和。
+
+启动窗口外的指标逐回合排除前 100 步;0.02 s 控制周期时对应前 2 s。
+这只是约定的分析窗口,不保证系统已经进入稳态;全程指标同时保留。
+不足该窗口的回合没有有效样本时,指标为 `null`,不伪造为零误差。
+
+## 第二件事:画图,再对照看数据
+
+将下面的路径换成上一条命令输出的实际 `trace.directory`:
+
+```bash
+uv run --no-sync python scripts/plot_evaluation_trace.py \
+ /home/abc/my_unilab/runs/rma/evaluations/EXP-002/seed123/eval_
+```
+
+生成 `plots/velocity_tracking.png`、`action_distribution.png`、`reward_components.png`。
+速度图显示各环境均值及跨环境标准差;包含重置,不把标准差称作置信区间。
+CSV 保留各个环境和回合,可进一步检查平均值是否掩盖个别异常。
+
+本次已经生成的第一份真实记录位于
+`/home/abc/my_unilab/runs/rma/evaluations/EXP-002/seed123/eval_hhlzyanz/`。
+仓库中另发布了 [压缩数据与图](../../results/rma/diagnostics/EXP-002/seed123/);
+无需仿真环境即可对发布副本运行下面的命令重新画图:
+
+```bash
+uv run --no-sync python scripts/plot_evaluation_trace.py \
+ results/rma/diagnostics/EXP-002/seed123
+```
+
+| 先看什么 | 怎么判断 | 还不能推出什么 |
+|---|---|---|
+| 指令列 | `command_vx_m_s` 是否一直为 0.5,vy/wz 是否为 0 | 期望值正确不代表动力学/控制正确 |
+| 速度列与误差 | `before_vx_m_s` 是否接近 0.5,侧向和转向是否偏离 | 只看总奖励不能代替速度指标 |
+| 动作分布 | 是否几乎不变化、偏置很大、频繁接近 ±1 | 任一现象都不是根因的充分证明 |
+| 奖励分项 | 哪些项贡献大,跟踪项是否与速度一致 | 分项大不自动说明权重必须减小 |
+| 控制映射 | `action_target_joint_order` 与 `joint_observation_order` 是否正确对应 | 两种顺序不同不一定是错误,框架可能已正确映射 |
+
+当前源配置的观测关节和运行时动作目标均按 FL/FR/RL/RR,场景执行器存储按 FR/FL/RR/RL。
+追踪文件保存**运行时解析出来的**关节名、索引、scale 与 offset,而不是拿观测顺序猜动作顺序。
+在没有 clip/encoder bias 修正的简化情形,关节目标是 `offset + scale * action`,当前配置 scale 为 0.25。
+这里记录的是配置映射和观测,不是实际驱动器写入目标/扭矩;进一步确认执行效果需要专门记录那些信号。
+不能因为腿编号顺序不一样就直接交换策略输出。
+
+本次追踪发现旧 ONNX 元数据将动作顺序误写成执行器存储顺序,旧 C++ mock 也直接按相同索引相加。
+现已修正输出边界的 12 维映射并新增非零 one-hot 测试;`last_action` 仍保持策略原顺序。
+旧 JSON 中的 `action_actuator_order` 不能再作为物理存储顺序使用;重新导出后同时记录
+`action_joint_order`、`scene_actuator_order` 和 `action_to_actuator_indices`。
+此错误影响独立 C++ 路径,不是 Python/UniLab 教师原地踏步的已确认原因。
+
+## 第三件事:只选一个变量做新实验
+
+先用同一模型完成种子 123、456、789 的诊断,再选择最有证据支持的假设。
+例如怀疑摆腿辅助奖励干扰前进:复制当前前进任务为新的实验配置,只改
+`reward.swing_feet_z.weight` 一项,记录旧值和新值。
+新数值应在实验前选定并记录,不能在多个候选中挑最好结果后只公开那一次。
+
+这是下一次重新训练时的配置变化;仅给旧 checkpoint 换奖励做评估不会让它学会新动作。
+训练初始化、指令范围、PPO 参数、控制器、训练预算和评估协议保持一致。
+新模型使用新文件名,保留旧模型;同样协议下比较实际速度与 RMSE。
+不要同一轮又加训练量、又改奖励、又换控制器,那样无法判断是谁产生作用。
+
+首个独立消融现已准备为 [EXP-003](../../experiments/rma/EXP-003_no_pose_penalty.md):
+仅将 `similar_to_default.weight` 从 -0.1 设为 0.0,从头训练并使用新输出文件。
+完整命令、日志位置和评估协议见该记录。现已完成训练及三个种子评估,未观察到实质前进改善。
+随后控制诊断发现当前 1.3.3 运行副本的快速目标写入有顺序错位;先处理控制路径再开始下一次训练。
+
+## GitHub:数据、Issue、PR 各自放什么
+
+| 位置 | 职责 | 更新频率 |
+|---|---|---|
+| 本地 `runs/rma/...` | 自动保存完整 CSV、checkpoint、运行配置 | 每次运行自动产生;不把所有大文件上传 Git |
+| `experiments/rma/EXP-xxx.md` | 假设、唯一变化、命令、数据位置、结果、结论 | 每个有明确问题的实验一份,使用 TEMPLATE.md |
+| `results/rma/` | 精选小数据、摘要和曲线,支持复查 | 整理有价值的结果后提交 |
+| Issue #1 | “原地踏步”这个问题的调查过程,链接数据/实验/提交 | 有新证据或新结论时追加评论 |
+| PR #2 | 当前实验分支相对 main 的代码变化、测试和审查 | 提交并 push 后代码差异自动更新;变更范围/验证结论变化时更新说明 |
+
+在 Issue #1 的 Add a comment 中写进展,再点 Comment 即可。
+不需要每次实验都在 Issue 和 PR 粘贴两份相同日志。
+同一问题的后续证据继续放 Issue #1;独立新问题才单独开 Issue。
+PR 是代码变更的审查入口,不是每次实验都新建或反复粘贴日志的地方。
+现在 PR #2 的内容在实验分支,尚未合入 main,查看文件时要选对分支。
+
+一条适合 Issue 的评论模板:
+
+```text
+实验:EXP-002,检查原地踏步
+假设:待诊断;本次不改算法和奖励
+模型:teacher_forward_v1.pt,SHA256 见 run_config.json
+协议:0.5/0/0,8 环境 × 1000 步,种子 123/456/789
+唯一变化:仅开启评估追踪
+数据/配置/代码:填写已提交的链接;本地绝对路径只是自己定位用
+结果:填写每个种子的平均 vx、vx RMSE、动作边界比例及关键分项
+结论:证据支持什么,仍不能确定什么
+下一步:只测试哪个变量,以及为什么
+```
+
+“期望它学会走路”是目标;“测量到多少、改了什么、能排除什么”才是实验记录。
diff --git a/docs/rma/PROJECT_WORKFLOW.md b/docs/rma/PROJECT_WORKFLOW.md
new file mode 100644
index 000000000..1ac17268b
--- /dev/null
+++ b/docs/rma/PROJECT_WORKFLOW.md
@@ -0,0 +1,158 @@
+# 项目导航:现在做什么,完成后做什么
+
+更新日期:2026-10-23。所有 shell 命令在 WSL Ubuntu 执行,工作目录为
+`/home/abc/my_unilab`,使用该目录现有 uv 环境;不要覆盖 `.venv` 或全部同步 fork。
+
+## 当前停在哪一步
+
+EXP-003 已训练 3000 次更新,并完成三个评估种子。平均前向速度约 0.013 m/s,
+没有完成 0.5 m/s 的指令跟踪。三组评估数据和三类图均已产生。
+**目标写入现已修复并验证,下一步从头训练修复后的 std=0.5 基线。**
+随后再比较只收紧 std 的实验组;完整操作与修改教程见
+[EXP-004 控制修复](../../experiments/rma/EXP-004_control_mapping.md) 与
+[EXP-005 跟踪宽度](../../experiments/rma/EXP-005_tracking_width.md)。
+不要重新执行已有正式训练来生成图片,也不要同时改动作缩放、奖励和训练预算。
+
+短诊断(1 环境 × 500 步)实测目录:
+`/home/abc/my_unilab/runs/rma/control_diagnostics/EXP-003/eval_2ffou4yp`。
+目标映射残差最大约 0.47117 rad;前左/前右大腿目标与实际角度 RMSE 约 0.364/0.305 rad。
+修复前,1.3.3 快速路径误差 0.0300000 rad、控制诊断残差 0.47117 rad。
+修复后,12 个非零关节目标 × 2 环境(含部分重置)的映射检查最大误差 0;
+500 步策略诊断映射残差 0。修复代码已备份,未触碰旧模型。
+单变量配置对照已解析,且两组各 1 次更新的入口冒烟通过;
+正式修复后基线与 std 实验尚未训练。细节及修改教学见 EXP-004/EXP-005。
+
+## 现在可执行的命令
+
+### 1. 看已有三类图:不运行仿真,不训练
+
+以下循环已执行,重复执行只重新生成这些图片。每个种子三张,共九张:
+
+```bash
+cd /home/abc/my_unilab
+for trace in runs/rma/evaluations/EXP-003/20261023_151848/seed*/eval_*; do
+ uv run --no-sync python scripts/plot_evaluation_trace.py "$trace" || break
+done
+cd /home/abc/my_unilab/runs/rma/evaluations/EXP-003/20261023_151848/seed123/eval_kwg2tw0_/plots
+explorer.exe .
+```
+
+查看完后执行 `cd /home/abc/my_unilab` 回到项目根目录。
+
+| 图 | 要回答的问题 | 当前不能推出的结论 |
+|---|---|---|
+| velocity_tracking.png | 实际 vx 是否接近 0.5,vy/wz 是否偏离? | 速度小不直接证明训练预算不足 |
+| action_distribution.png | 12 个动作是否变化、偏置、频繁到边界? | 动作到边界不等于扭矩饱和 |
+| reward_components.png | 各加权奖励分项是否与任务行为一致? | 改奖励后总 reward 更高不一定走得更好 |
+
+### 2. 看控制图:已运行,可按需复现
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python scripts/diagnose_rma_control.py \
+ --checkpoint runs/rma/teacher_forward_no_pose_v1.pt \
+ --task go2_joystick_flat/rma_forward_no_pose \
+ --steps 500 --seed 123 --command 0.5 0 0 \
+ --output-dir runs/rma/control_diagnostics/EXP-003
+```
+
+每次生成新的 `eval_`,不改权重。终端给出准确目录。
+看 `control_tracking.png`:蓝线为实际写入的目标,橙线为一步后的关节角度;
+`control_signals.csv` 保存逐关节信号,`control_summary.json` 保存误差。
+`mapping_residual_rad` 比较按语义关节重排后的实际缓冲与 processed target 减 encoder bias,
+应接近浮点数值误差。先消除映射残差,再解释姿态跟踪误差。
+`pd_demand_estimate_nm` 仅为控制边界处的代数估计,未包含物理子步或被动阻尼,
+当前公开 backend API 没有实测执行器扭矩,不能据此宣称扭矩饱和。
+
+### 3. 下一项工程任务:控制路径修复与回归
+
+更新:修复和验收已完成,备份、源码差异与运行命令见 EXP-004。
+需要复查时执行 `uv run --no-sync python scripts/check_rma_mapping.py`。
+这会写入测试用控制缓冲但不推进物理仿真,并在每个检查后恢复缓冲。
+
+## 完整工作流:每次只进入当前满足条件的一行
+
+| 阶段 | 做什么 | 完成标准与下一步 |
+|---|---|---|
+| 0 环境与接口 | 冒烟训练、形状与 reset 测试;确认运行源码版本、资产、dt、动作顺序 | 能运行且控制语义正确,才进入正式训练 |
+| 1 教师基线 | 固定任务、种子和预算,从头 PPO,保存独立输出 | 得到模型和训练日志;进入定量评估 |
+| 2 固定评估 | 同一模型、0.5/0/0、三个种子、8 环境 × 1000 步,保存 trace | 每种子有 summary/CSV/config;进入离线绘图 |
+| 3 看图与诊断 | 速度、动作、奖励三图;必要时目标与实际角度图 | 本轮映射修复已验证;现在进入修复后的新基线训练 |
+| 4 单变量实验 | 写假设、只改一个变量;新文件名、从头训练、同协议评估 | 记录改善或无改善;控制修复应独立编号,不能混入奖励消融 |
+| 5 好教师 → 学生 | 冻结教师与 Actor,用历史估计隐变量 | 学生任务指标接近合格教师,检查 latent/action 误差;低 MSE 单独不足 |
+| 6 ONNX | Adaptation + Actor 导出,验证数值误差 | 图结构、IO、顺序、历史重置和数值检查通过 |
+| 7 TensorRT/C++ 闭环 | 先对齐推理输出,再用相同观测与关节映射控制仿真 | 数值、任务表现、延迟和过期指令处理逐项验收;mock 通过不等于闭环通过 |
+| 8 跨引擎 Sim2Sim | 保持 IO/控制合同,换物理后端独立评估 | 报告差异和泛化结果;之后另行准备真机 |
+
+### 阶段 1/4:未来新实验训练模板(现在不要执行长训)
+
+映射修复验收后,先用相同基础任务建立新的控制修复基线;下面设置保持已有预算,
+不是速度或温度保证。模型名 `teacher_mapping_v1.pt` 必须尚不存在。
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python scripts/train_rma.py \
+ --phase teacher --task go2_joystick_flat/rma_forward \
+ --output runs/rma/teacher_mapping_v1.pt \
+ --num-envs 64 --iterations 3000 --device cuda
+```
+
+不传 `--checkpoint` 表示新初始化。传入只加载权重,不恢复 optimizer/RNG,不能称精确续训。
+新输出不能覆盖旧模型。训练日志自动在 `teacher_mapping_v1_logs//`:
+`metrics.csv`、`run_config.json`、`tensorboard/`。训练不开可视化。
+另一个终端可开 TensorBoard,若已有服务直接访问它,换端口只用于确实需要的新服务:
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python -m tensorboard.main \
+ --logdir /home/abc/my_unilab/runs/rma --host 127.0.0.1 --port 6007
+```
+
+浏览器打开 `http://127.0.0.1:6007`。训练 reward 曲线用于看优化过程;
+实验结论以固定评估的实际速度/误差等任务指标为准。
+
+### 阶段 2:训练完成后的标准评估模板
+
+模型和任务要对应;用同一任务比较不同模型时明确区分训练环境与评估环境。
+
+```bash
+cd /home/abc/my_unilab
+for seed in 123 456 789; do
+ uv run --no-sync python scripts/evaluate_rma.py \
+ --policy teacher --checkpoint runs/rma/teacher_mapping_v1.pt \
+ --task go2_joystick_flat/rma_forward \
+ --num-envs 8 --steps 1000 --seed "$seed" \
+ --command 0.5 0 0 --diagnostics \
+ --trace-dir "runs/rma/evaluations/mapping_v1/seed${seed}" || break
+done
+```
+
+之后对终端输出的每个 trace.directory 执行画图脚本。要肉眼看已有模型时单独执行:
+
+```bash
+uv run --no-sync python scripts/evaluate_rma.py \
+ --policy teacher --checkpoint runs/rma/teacher_forward_no_pose_v1.pt \
+ --task go2_joystick_flat/rma_forward_no_pose \
+ --num-envs 1 --steps 500 --seed 123 --command 0.5 0 0 \
+ --render --render-speed 0.5
+```
+
+这只是播放当前失败模型,不能修复它。
+
+### 阶段 5—8:先满足前置条件
+
+学生/导出命令和 TensorRT/C++ 说明见 [复现指南](REPRODUCING.md)、
+[RMA 主页](README.md) 及 `deploy_cpp/` 中的实现。当前已有冒烟链路记录,
+无需反复导出失败策略。先获得合格教师,再以新学生输出名训练并固定评估。
+选择迭代数必须依据学生任务指标,不以一次 latent MSE 下降决定完成。
+
+## 每次实验结束后写四句话
+
+在 `experiments/rma/EXP-xxx.md` 中写:问题是什么;唯一改变是什么;
+固定协议下测到什么;证据支持什么、下一步只检查什么。
+本地 runs 保存完整大数据;results 保存可复查的小摘要与精选图;
+Issue #1 记录问题的新证据并链接实验;PR #2 审查代码和验证结果,
+不必在两处粘贴相同日志。
+
+当前核心检查:47 项 RMA 测试通过;整仓门禁仍有既有类型检查问题。
+测试通过不代表机器人已经会走路;该分支保持 Draft。
diff --git a/docs/rma/README.md b/docs/rma/README.md
new file mode 100644
index 000000000..18d1926b3
--- /dev/null
+++ b/docs/rma/README.md
@@ -0,0 +1,120 @@
+# Go2 RMA Locomotion Lab
+
+基于 UniLab 的 Go2 强化学习运动控制实验:教师 PPO、历史观测适应、模型导出与 C++ 模拟部署。
+
+> 当前状态:工程组件已有测试与运行记录;教师尚未学会稳定跟踪 0.5 m/s 前进指令。
+> 本仓库保留失败结果和可复现的诊断,不声称完成鲁棒行走、真机部署或跨物理引擎泛化。
+
+## 这个项目解决什么问题
+
+目标是研究如何让四足机器人按速度指令运动,以及如何通过历史观测估计摩擦、负载相关的隐变量。
+当前第一项任务是定位“策略原地踏步但没有向前移动”的原因。
+
+**不知道下一步做什么时,先看 [项目工作流与当前步骤](PROJECT_WORKFLOW.md)。**
+当前运行副本的目标映射已修复;先建立修复后基线,再执行
+[std 单变量实验与修改教程](../../experiments/rma/EXP-005_tracking_width.md)。
+
+```mermaid
+flowchart LR
+ P["训练特权参数:摩擦、负载"] --> E["教师 Encoder"]
+ E --> Z["隐变量 z:8 维"]
+ H["过去 50 步观测:50 × 49"] --> A["学生 Adaptation MLP"]
+ A --> ZH["估计隐变量 z_hat:8 维"]
+ O["当前观测:49 维"] --> ACT["共享 Actor"]
+ Z --> ACT
+ ZH --> ACT
+ ACT --> U["12 维动作"]
+```
+
+教师评估使用真实特权参数,学生使用历史估计隐变量;两条路径是分别选择的。
+部署图只保留 Adaptation + Actor,教师 Encoder 与 Critic 不进入部署图。
+
+本分支在 UniLab fork 中加入增量实验层,保留 `unilab` 导入,不修改上游项目的归属。
+训练脚本使用项目内的独立 PPO 实现,不是官方 RSL-RL 的训练入口。
+
+## 已观察到的结果
+
+所有评估固定机体系指令 `(0.5, 0, 0)`,每个种子使用 8 个环境、每环境 1000 个控制步。
+
+| 模型 | 评估种子 | 平均前向速度 (m/s) | 前向 RMSE (m/s) | 提前终止次数 |
+|---|---:|---:|---:|---:|
+| 原始教师 | 123 | -0.006058 | 0.510957 | 0 |
+| 原始教师 | 456 | -0.011667 | 0.517436 | 1 |
+| 原始教师 | 789 | -0.004922 | 0.511072 | 1 |
+| 前进配置教师 v1 | 123 | 0.015686 | 0.489772 | 2 |
+| 前进配置教师 v1 | 456 | 0.013730 | 0.490668 | 0 |
+| 前进配置教师 v1 | 789 | 0.012254 | 0.491959 | 0 |
+
+前进配置 v1 已完成 3000 次更新、4,608,000 次环境转移,初始化种子为 42。
+三个评估种子不是三个独立训练种子,表格不构成跨训练种子的显著性结论。
+不同配置使用不同奖励权重,因此不能直接用总奖励比较任务效果。
+提前终止次数不是经独立检测标注的跌倒率。
+
+
+
+
+
+原始数值、训练记录及分析见 [results](../../results/rma/) 和 [实验记录](../../experiments/rma/)。
+曲线展示奖励而非实际速度;当前训练器尚未逐步记录前向速度曲线。
+
+## 代码结构
+
+```text
+rsl_rl/unilab_rma/ 教师/学生网络、PPO、GAE、历史缓冲与 UniLab 适配
+scripts/ 训练、评估、导出与结果汇总
+legged_gym/ Go2 接口常量,并非重新实现 legged_gym
+src/unilab/... RMA 事件与任务配置;原有 UniLab 框架保持上游归属
+deploy_cpp/ TensorRT 接口、双缓冲与 50/1000Hz mock 控制框架
+tests/rma/ 算法与接口测试
+experiments/ 问题、假设、对照设计与结论
+results/ 精选 JSON、CSV、配置记录与图表
+docs/ 使用说明、接口契约与复现边界
+```
+
+## 复现与依赖
+
+完整说明见 [复现指南](REPRODUCING.md) 和 [验证记录](VALIDATION.md)。
+逐步记录、画图与 Issue/PR 的分工见 [实验操作指南](EXPERIMENT_WORKFLOW.md)。
+
+已发布的实测数据基于本地 UniLab 1.3.3 工作副本、MuJoCo CPU 物理环境和 PyTorch。
+本 fork 基线为 UniLab 1.3.4,基线 commit 与关键文件差异见 [provenance.json](../../results/rma/provenance.json)。
+原始运行副本未携带 Git 历史,且部分配置/运行时文件与 fork 不同;因此不能把旧实测冒充为当前分支端到端验证。
+不建议为了运行本仓库直接升级已经验证过的仿真环境。
+
+核心测试与结果图表可以独立运行;真实 Go2 训练仍需要完整 UniLab、依赖与机器人资产。
+在匹配的环境中执行:
+
+```bash
+cd /path/to/this/UniLab
+uv run --no-sync python -m unittest discover -s tests/rma -p 'test_*.py'
+```
+
+评估已存在的前进配置教师:
+
+```bash
+uv run --no-sync python scripts/evaluate_rma.py \
+ --policy teacher --checkpoint runs/rma/teacher_forward_v1.pt \
+ --task go2_joystick_flat/rma_forward \
+ --num-envs 8 --steps 1000 --seed 123 \
+ --command 0.5 0 0 --diagnostics
+```
+
+在上述命令追加 `--render` 可看画面,追加 `--render-speed 0.5` 可慢放。
+训练默认不打开可视化。实验模型权重和已安装运行环境不包含在本仓库中。
+以上是已有完整 1.3.3 运行环境的评估入口;1.3.4 环境接入必须单独完成兼容性验证。
+
+## 接下来如何改进
+
+1. 保留当前基线,补齐逐步速度、动作饱和和 PPO 更新诊断。
+2. 在一致训练预算下分别检验指令范围、摆腿奖励和速度跟踪权重。
+3. 教师速度跟踪通过后,比较学生自身 rollout 与教师表现。
+4. 将 ONNX / TensorRT 的数值一致性与任务表现分别验收。
+
+本仓库当前不是自动课程调度器;现有 `rma_forward` 是静态前进任务配置。
+详细设计见 [下一项实验](../../experiments/rma/EXP-002_diagnosis_plan.md)。
+
+## 来源与贡献范围
+
+UniLab 是上游仿真与任务框架;本项目贡献范围为 RMA 增量实现、实验配置、诊断、导出/模拟部署及实验分析。
+上游来源、许可证与本地源码快照的限制见 [来源说明](THIRD_PARTY_NOTICES.md)。
+AI 工具参与了代码和文档辅助;已验证范围和未验证项以测试记录及实验数据为准。
diff --git a/docs/rma/REPRODUCING.md b/docs/rma/REPRODUCING.md
new file mode 100644
index 000000000..756b01564
--- /dev/null
+++ b/docs/rma/REPRODUCING.md
@@ -0,0 +1,63 @@
+# RMA 实验复现与验证范围
+
+## 先区分两个代码版本
+
+旧实测来自没有 Git 历史的本地 UniLab 1.3.3 工作副本。
+本分支从用户 fork 的 `c19b8810059e3c495dc5394a5652d3c82c00f70f`(1.3.4)开始,导入 RMA 增量代码。
+`results/rma/provenance.json` 保存了运行依赖、来源文件哈希和关键框架文件差异。
+存在差异时,不应把旧模型成绩标成当前 Git commit 上重跑的结果。
+
+## 复现表格和图表
+
+在有 PyTorch 和 matplotlib 的 Python 环境中,从项目根目录执行:
+
+```bash
+uv run --no-sync python scripts/report_rma.py
+```
+
+输入是 `results/rma/baseline/seed*.json`、`results/rma/forward_v1/seed*.json`
+和 `results/rma/forward_v1/training_metrics.csv`。
+输出是 `results/rma/evaluation_summary.csv` 与 `results/rma/figures/*.png`。
+训练图使用真实的 3000 行 CSV,平滑线为包含启动区间的尾随 100 次更新均值。
+没有填补不存在的模型速度曲线,也没有生成虚构视频。
+
+## 核心算法/接口测试与 C++ mock
+
+```bash
+uv run --no-sync python -m unittest discover -s tests/rma -p 'test_*.py'
+cmake -S deploy_cpp -B build/rma -DCMAKE_BUILD_TYPE=Release
+cmake --build build/rma -j2
+ctest --test-dir build/rma --output-on-failure
+```
+
+这些测试验证算法接口、历史缓冲、概率/终止处理、导出接口和并发 mock。
+它们不能证明 Go2 速度跟踪、真机安全、硬实时或 TensorRT 在目标设备上的精度与延迟。
+
+## 真实评估协议
+
+保留原 checkpoint,固定 `(0.5, 0, 0)`,每个种子运行 8 环境 × 1000 个控制步,
+种子为 123、456、789,模型权重不变。完整参数见 EXP-001。
+历史 JSON 仅记录总转移数 8000,未单独保存环境数和步数;8 × 1000 来自实验命令记录。
+报告脚本核对教师策略、种子、目标命令及总转移数,不能仅凭总转移数证明环境数和步数。
+后续评估应同时保存环境数、控制步数与完整命令,不能给历史 JSON 补造缺失字段。
+加入 `--diagnostics` 才输出各轴速度、各轴 RMSE 与奖励分项。
+统计包含启动和重置过程;下一阶段应提前约定稳态统计窗口,并同时保留全程指标。
+日志若使用 `tee` 保存,会混有启动文字,不是纯 JSON 文件。
+
+当前静态配置继承的上游基础奖励定义在 1.3.3 与 1.3.4 有变化。
+历史配置快照应与原运行环境一起用于追溯,不能单独覆盖新版本的全部框架文件。
+重新运行当前分支得到的结果,应另起实验编号,并保存当前 commit 和完整配置。
+
+## 训练与 checkpoint 语义
+
+3000 次更新 × 64 环境 × 24 rollout 长度 = 4,608,000 次环境转移。
+策略/更新 CUDA 不等于物理仿真也在 GPU;本次物理环境为 CPU。
+当前 `--checkpoint` 只恢复网络权重,未恢复 optimizer/RNG/环境状态,属于 warm-start。
+当前保存行为每 20 次覆盖同一路径;旧运行没有保存全部历史 checkpoint,无法补算其历史速度曲线。
+
+## 环境和资产
+
+机器人资源通过上游资产流程获取,路径与 home keyframe 必须匹配。
+不要将 `.venv`、mesh、完整运行目录或大模型文件直接加入 Git。
+本分支没有发布训练权重;checkpoint SHA256 用于之后核对同一模型。
+环境安装方式以 fork 上游说明为准;复现旧数据需匹配 provenance 中记录的版本及配置。
diff --git a/docs/rma/THIRD_PARTY_NOTICES.md b/docs/rma/THIRD_PARTY_NOTICES.md
new file mode 100644
index 000000000..93021e5ba
--- /dev/null
+++ b/docs/rma/THIRD_PARTY_NOTICES.md
@@ -0,0 +1,14 @@
+# 来源与贡献范围
+
+- 上游框架:UniLab,仓库 `https://github.com/unilabsim/UniLab`。
+- 用户 fork:`https://github.com/gongbaojiding-1123/UniLab`。
+- 原有 UniLab 源码、许可证和归属保持不变;许可证见仓库根目录 `LICENSE`。
+- RMA 增量:`rsl_rl/unilab_rma`、RMA 脚本与配置、`deploy_cpp`、相关测试与本组实验文档。
+- `legged_gym/go2_config.py` 只声明接口常量,不是完整 legged_gym 的移植。
+- 当前训练器是本项目独立 PPO;不能将其结果归属于官方 RSL-RL 的默认实现。
+- RMA 的教师隐变量/历史适应思路属于已有研究,本项目不宣称发明该方法。
+- 机器人资源、TensorRT/CUDA、PyTorch 等依赖仍遵循其各自许可,未随实验结果重新分发。
+- 代码和文档使用了 AI 辅助,结果数据来自已保存的训练 CSV 与用户提供的评估输出。
+
+原运行目录未携带 Git 历史,无法证明它与某个上游 commit 完全一致。
+本分支保留关键文件差异记录,不通过猜测补填上游 commit。
diff --git a/docs/rma/VALIDATION.md b/docs/rma/VALIDATION.md
new file mode 100644
index 000000000..0be17cb15
--- /dev/null
+++ b/docs/rma/VALIDATION.md
@@ -0,0 +1,64 @@
+# RMA 分支验证记录
+
+日期:2026-10-23。
+
+本轮新增:47 项 RMA unittest 通过;已有 EXP-003 三组 CSV 成功生成九张图。
+1 环境 × 500 步新增控制诊断与原评估器的 transitions.csv 逐字节一致。
+独立无步进写入检查确认当前 1.3.3 快速路径目标映射错误,普通路径误差为零。
+EXP-004 定点修复后 24 个非零目标映射检查和 500 步真实诊断均为零映射误差;
+EXP-005 两组各 1 次更新 CPU 冒烟通过,正式训练尚未进行。最终 `make test-all` 再次运行:ruff/mypy 通过,
+仍被未修改框架文件中的 10 个 Pyright 错误、3 个警告阻塞。
+
+## 已通过
+
+- 导入本地 RMA 增量层及精选实验数据;数据汇总严格匹配 6 份 JSON 和 3000 行训练 CSV。
+- `uv run --no-sync python scripts/report_rma.py`:生成汇总 CSV 与两张静态图;图表已人工查看。
+- `uv run --no-sync python -m unittest discover -s tests/rma -p 'test_*.py'`:41 项通过,包含追踪开关不改变动作、终止状态对齐、控制映射、单变量配置及旧模型防覆盖检查。
+- `cmake -S deploy_cpp -B build/rma -DCMAKE_BUILD_TYPE=Release`:配置成功。
+- `cmake --build build/rma -j2`:构建成功。
+- `ctest --test-dir build/rma --output-on-failure`:3/3 通过(并发一致性、mock 控制和 12 个非零 one-hot 动作的执行器映射)。
+- `make check` 中的 ruff format/check、`mypy src/unilab`:通过。
+
+核心测试与报告脚本使用现有 WSL Python 环境。C++ 为 GNU 11.4.0、CMake 生成的 Release 构建。
+没有追加 Go2 长训,没有更改用户运行目录的原模型或基线仿真配置。
+新增独立任务 `rma_forward_no_pose`,只关闭默认站姿偏离惩罚;Hydra 完整解析对比只差这一项。
+在原 1.3.3 运行目录中完成 2 环境 × 24 步 × 1 次更新的 CPU 训练冒烟测试,checkpoint 与日志保存成功。
+随后 2 环境 × 3 步追踪评估成功;惩罚分项为 0,新任务 YAML 已存入快照,原基线模型 SHA256 不变。
+随后用户已完成正式 3000 次更新与三个种子评估,未发现实质前进改善,见 EXP-003 记录。
+
+原 1.3.3 运行目录中已执行一次真实追踪评估:`teacher_forward_v1.pt`、种子 123、8 环境 × 1000 步,
+生成 8000 行 CSV、独立 JSON 与三张图。全程速度/RMSE 与此前该模型同种子的报告一致。
+逐行验证分项 rate 之和乘 0.02 与实际 reward 的最大误差约 `7.98e-09`。
+完整压缩 CSV、摘要、配置记录及图见 `results/rma/diagnostics/EXP-002/seed123/`。
+这只验证 1.3.3 中的新增评估入口,不等于 1.3.4 真实训练完成兼容。
+
+使用旧学生权重重新导出 ONNX,12 组输入数值检查通过,最大误差 `2.682209e-07`。
+导出元数据已区分策略关节顺序与场景执行器存储顺序;C++ 输出边界已按映射散射。
+ONNX 权重图本身未加排列;尚未用真实机器人或 TensorRT 机器人闭环验证本次修正。
+
+## 完整门禁尚未通过
+
+在本 fork 1.3.4 源码上,复用了已有 1.3.3 的 WSL 环境运行完整门禁:
+
+```bash
+UV_PROJECT_ENVIRONMENT=/home/abc/my_unilab/.venv UV_NO_SYNC=1 make check
+UV_PROJECT_ENVIRONMENT=/home/abc/my_unilab/.venv UV_NO_SYNC=1 make test-all
+```
+
+Pyright 报告上游现有框架文件的 10 项错误和 3 项警告,包括缺失的 packed-reset/capability API、
+未解析导入与可选值检查。报错位置没有被本次改动修改。
+依赖/源码版本不一致是已观察到的限制,尚未证明这是所有错误的唯一原因。
+`make test-all` 因前置类型检查未通过而未到达后续全仓测试阶段,不能报告成全仓测试通过。
+未为通过门禁而升级正在使用的训练环境或更改上游框架代码。
+
+若创建 PR,应保持 Draft;本地核心验证不替代完整门禁和当前 head 的远端 CI。
+1.3.4 分支下的真实 Go2 训练、旧 checkpoint 行为兼容、TensorRT/真机与跨引擎测试未在本次执行。
+
+## 历史数据边界
+
+发布的运动指标是已有本地 1.3.3 运行副本产生的结果,不是当前 1.3.4 分支重跑的结果。
+`results/rma/forward_v1/config_snapshot` 是训练完成后从仍在使用的工作副本采集的配置,
+并非训练开始时自动保存的不可变快照;不能据此补造完整历史溯源。
+发布副本的 `base.yaml` 仅清除了行尾空白,未修改 YAML 参数;原运行文件的哈希另有记录。
+原运行配置、CSV 与来源 SHA256 记录见 `results/rma/provenance.json`;
+checkpoint SHA256 见 `results/rma/forward_v1/checkpoint_metadata.json`。
diff --git a/experiments/rma/EXP-000_teacher_full_baseline.md b/experiments/rma/EXP-000_teacher_full_baseline.md
new file mode 100644
index 000000000..1572cffe3
--- /dev/null
+++ b/experiments/rma/EXP-000_teacher_full_baseline.md
@@ -0,0 +1,54 @@
+# EXP-000:旧教师固定前进指令评估
+
+记录整理:2026-10-22。原始评估目录日期:2026-10-21。
+本记录由已有 JSON 整理,本次没有重新训练或重新评估。
+
+## 问题与设置
+
+- 模型:旧 `teacher_full.pt`,教师策略;不是新前进配置模型。
+- 目标指令:机体系 `(0.5 m/s, 0 m/s, 0 rad/s)`。
+- 每次 8 环境 × 1000 策略步,共 8000 次环境转移。
+- 三个评估种子:123、456、789。它们不是三个训练种子。
+- 原始 JSON 中未保存完整训练配置、训练 commit 或 checkpoint 校验和;本记录不补造这些信息。
+
+## 原始数据
+
+实际 WSL 目录:
+`/home/abc/my_unilab/runs/rma/circling_diagnosis/verified_20261021_225308/`
+
+仓库中发布的对应数据:
+
+- `results/rma/baseline/seed123.json`
+- `results/rma/baseline/seed456.json`
+- `results/rma/baseline/seed789.json`
+
+| 评估种子 | 平均 vx (m/s) | 前向 RMSE (m/s) | 平面速度 RMSE (m/s) | 提前终止次数 |
+|---|---:|---:|---:|---:|
+| 123 | -0.006058 | 0.510957 | 0.514638 | 0 |
+| 456 | -0.011667 | 0.517436 | 0.522385 | 1 |
+| 789 | -0.004922 | 0.511072 | 0.515623 | 1 |
+
+表格数值仅为展示做了四舍五入,原始 JSON 保留精度。
+统计包含启动与重置后的过渡过程;不是单独截取的稳态数据。
+提前终止次数不等于经独立接触检测标注的跌倒次数。
+
+种子 123 的乘权重、尚未乘控制 dt 的奖励分项:
+
+- `tracking_lin_vel`:0.360382。
+- `swing_feet_z`:1.272840。
+- `similar_to_default`:-0.183316。
+
+## 结论与局限
+
+事实:该模型在这三组测试中,平均前向速度接近零,未实现目标速度跟踪。
+辅助摆腿奖励的贡献较高,值得检查是否存在“原地踏步也获得收益”的路径。
+奖励分项大小本身不证明这是唯一原因,也不直接给出哪个奖励权重应设为多少。
+没有由此证明 PPO 公式错误、需要更换仿真器或需要修改部署线程。
+
+## 下一步
+
+1. 核对后续新模型实际使用的任务与配置。
+2. 用相同固定指令、种子、环境数与步数评估新模型;保留新日志和本基线。
+3. 若仍不前进,按 `EXP-002_diagnosis_plan.md` 设计单因素对照及控制链路诊断。
+
+后续前进配置结果现已收集,见 `EXP-001_forward_v1.md`。
diff --git a/experiments/rma/EXP-001_forward_v1.md b/experiments/rma/EXP-001_forward_v1.md
new file mode 100644
index 000000000..15b62d76d
--- /dev/null
+++ b/experiments/rma/EXP-001_forward_v1.md
@@ -0,0 +1,49 @@
+# EXP-001:前进配置教师仍未跟踪目标速度
+
+日期:2026-10-22。状态:训练与三个种子的评估已完成,运动目标未达成。
+
+## 假设与改动
+
+原始教师在固定前进指令下几乎不前进。初始假设是辅助摆腿奖励与任务范围可能影响学习。
+本次将 vx 指令收窄到 `[0.3, 0.6]`、vy/wz 置零,速度跟踪权重由 1 改为 2,摆腿奖励权重由 4 改为 0.25。
+这是组合实验,不能将结果归因于单独某一项改动。
+
+## 训练证据
+
+运行配置记录确认:
+
+- 教师 PPO,从头训练,初始化种子 42。
+- 环境 64,采样长度 24,更新 3000 次,环境转移 4,608,000 次。
+- 策略/更新设备 CUDA,物理环境设备 CPU,后端 MuJoCo。
+- 模型 `teacher_forward_v1.pt`;训练运行配置、CSV 与 checkpoint 元数据另存于 `results/rma/forward_v1/`。
+
+3000 是优化迭代次数,不是环境交互总步数。已完成这一预算,但这不等于证明预算足以收敛。
+每 500 次更新的平均每步奖励约为 0.02093、0.02190、0.02167、0.02149、0.02197、0.02147。
+曲线在早期提高后长期处于平台,没有支持继续无条件加训必然成功的趋势。
+
+## 测试协议
+
+教师策略、固定机体系指令 `(0.5, 0, 0)`,每种子 8 环境 × 1000 控制步。
+三个评估种子为 123、456、789,模型权重相同。统计包含启动和回合重置后的过渡过程。
+
+| 种子 | 平均 vx (m/s) | 前向 RMSE (m/s) | 平面速度 RMSE (m/s) | 提前终止次数 |
+|---|---:|---:|---:|---:|
+| 123 | 0.015686 | 0.489772 | 0.493154 | 2 |
+| 456 | 0.013730 | 0.490668 | 0.493155 | 0 |
+| 789 | 0.012254 | 0.491959 | 0.494027 | 0 |
+
+## 结论
+
+- 目标 0.5 m/s 下,三个条件的平均前向速度都只有约 0.014 m/s,尚未学会任务要求的前进。
+- 相比旧模型有小幅变化,但不能把小幅改善描述为已经学会走路。
+- 仅凭最终 checkpoint 不能区分“预算不够”和“局部最优/探索或控制问题”。
+- 降低摆腿奖励并增加跟踪奖励后问题仍存在;不能继续将唯一原因认定为摆腿奖励过强。
+- 原始、新配置的奖励权重不同,总 reward 不可直接横向比较。
+- 三个评估种子不能替代多个训练种子,也不支持统计显著性结论。
+
+## 下一步
+
+先看已有训练 CSV 的趋势,并设计逐步速度、策略输出范围和控制链路诊断。
+在采样预算相同的前提下做单因素对照,或采用预先约定的延长预算对照。
+当前 `--checkpoint` 只加载权重,没有恢复 optimizer/RNG,不能把它描述为精确续训。
+不自动追加长训、不覆盖原模型,不把失败结果隐藏掉。
diff --git a/experiments/rma/EXP-002_diagnosis_plan.md b/experiments/rma/EXP-002_diagnosis_plan.md
new file mode 100644
index 000000000..9083bbc2b
--- /dev/null
+++ b/experiments/rma/EXP-002_diagnosis_plan.md
@@ -0,0 +1,60 @@
+# EXP-002:先诊断平台,再选择对照实验
+
+状态:评估追踪工具已实现;不新增训练,不含预测值冒充实测。实际验收范围见验证记录。
+
+## 2026-10-22 的第一份诊断数据
+
+原 1.3.3 运行目录,保持 `teacher_forward_v1.pt` 权重、任务和固定指令不变:
+8 环境 × 1000 步,种子 123,仅增加追踪,得到 8000 条真实转移。
+数据、哈希和图在 [seed123](../../results/rma/diagnostics/EXP-002/seed123/)。
+
+- 全程平均 vx `0.01568594 m/s`,前向 RMSE `0.48977159 m/s`,与此前同种子评估一致。
+- 逐回合排除前 100 步后保留 6441 条转移,平均 vx `0.00541195 m/s`,RMSE `0.49605151 m/s`。
+- `FR_hip_joint` 的归一化动作 `|a| >= 0.95` 比例为 `0.749125`;`RR_thigh_joint` 为 `0.952375`。
+- 逐行核对 weighted reward rates × dt 与实际 reward,最大误差约 `7.98e-09`。
+
+证据支持:目标指令保持 0.5,速度跟踪很差;部分策略输出长期接近 tanh 边界。
+证据尚不足以证明扭矩饱和、某个奖励项有错、或换一个权重即可学会行走。
+目前只完成这个追踪种子,不把它写成三个诊断种子或新训练的结果。
+
+另发现部署侧将策略输出顺序误当成执行器存储顺序;已修正导出元数据和 C++ 输出边界。
+仿真中的策略目标顺序为 FL/FR/RL/RR,场景执行器存储为 FR/FL/RR/RL,UniLab 自己负责映射。
+这不是原 Python 教师不前进的已确认原因,不能把部署修正记为行走性能提升。
+
+## 证据
+
+EXP-001 已完成 3000 更新、4.608M 环境转移,前向速度约 0.014 m/s。
+训练 CSV 的每 500 更新均值约为 0.02093、0.02190、0.02167、0.02149、0.02197、0.02147。
+约 500 次以后奖励长期平台,现有结果不能支持“继续挂机一定会学会”。
+也不能据此反向断言 4.608M 对所有配置都足够。
+
+## 第一项可审查的交付:诊断
+
+不改变奖励/控制/优化参数,评估通过 `--trace-dir` 可启用以下记录:
+
+- 每步、每环境 vx/vy/wz、目标值、done 与回合步数。
+- 每关节归一化动作分布与接近边界的比例;若要定位 PD,另记录目标/实测角和扭矩。
+- 同时报告全程误差与预先定义的启动窗口外误差。
+
+验收:不启用记录时动作与原评估一致;记录字段、单位和坐标系明确;重置不跨回合串联。
+当前指标没有提供扭矩饱和证据,不得把“疑似饱和”写成已确认问题。
+数据路径、列含义、画图和 Issue 评论示例见 [操作指南](../../docs/rma/EXPERIMENT_WORKFLOW.md)。
+
+## 后续对照候选
+
+| 候选 | 保持不变 | 唯一变化 | 目的 |
+|---|---|---|---|
+| 预算对照 | 配置、初始化种子、环境数、优化设置 | 总训练预算,并保存中间模型 | 检查延长训练是否改善任务指标 |
+| 指令消融 | 原奖励、控制器与 PPO | 指令收窄为前进 | 检查任务范围影响 |
+| 辅助奖励消融 | 前进指令和其他项 | 摆腿奖励权重 | 检查辅助奖励影响 |
+| 跟踪奖励消融 | 其余项 | 速度跟踪权重 | 检查任务激励影响 |
+
+不同时执行所有候选;先根据诊断选择最有信息量的一项。
+训练预算对照需要连续轨迹或明确标记 warm-start;当前入口不是完整恢复。
+每次保存配置快照、commit、种子、训练总转移数、checkpoint 哈希和相同协议下的评估。
+
+## 判断标准
+
+主要指标是固定指令下的实际速度与前向 RMSE;侧向/转向误差和提前终止作为辅助指标。
+多个独立训练种子用于检验训练稳定性,不能用三个评估种子替代。
+当前还没有通过指标;任何新增阈值需在实验前约定,并明确是本项目标准。
diff --git a/experiments/rma/EXP-003_no_pose_penalty.md b/experiments/rma/EXP-003_no_pose_penalty.md
new file mode 100644
index 000000000..e14fa28bc
--- /dev/null
+++ b/experiments/rma/EXP-003_no_pose_penalty.md
@@ -0,0 +1,86 @@
+# EXP-003:关闭默认站姿偏离惩罚的单变量对照
+
+状态:已完成 3000 次更新与三个种子评估,未发现实质前进改善;继续排查控制路径。
+
+入口验证:原 1.3.3 运行目录中,2 环境、1 次更新、CPU 冒烟训练已完成并保存日志和模型。
+对应文件 `runs/rma/smoke_no_pose_20261022_2305.pt`,日志目录
+`runs/rma/smoke_no_pose_20261022_2305_logs/20261022_230512_v5z9y6n2/`。
+这 48 条训练转移用于检查链路,不作为正式对照组或行走性能证据。
+随后用同一实验任务完成 2 环境 × 3 步评估,惩罚分项为 0,原基线模型 SHA256 不变。
+
+## 假设与唯一变化
+
+问题:已有 `teacher_forward_v1.pt` 在 0.5 m/s 指令下几乎不前进。
+假设:默认站姿偏离惩罚可能抑制学习有效步态;这是待检验的解释,不是已确认根因。
+
+基线任务 `go2_joystick_flat/rma_forward` 的 `reward.similar_to_default.weight` 为 -0.1。
+实验任务 `go2_joystick_flat/rma_forward_no_pose` 继承基线,只将该值改为 0.0。
+Hydra 完整解析后的配置测试要求除这一项外完全一致。
+基线配置文件保持原值;不要为了本实验直接修改 `base.yaml`。
+
+## 训练协议
+
+从头训练,初始化种子 42,64 环境,采样长度 24,更新 3000 次,总转移 4,608,000。
+与基线使用同一设备设置 CUDA,其余 PPO、网络、控制、随机化与指令设置不变。
+不传 `--checkpoint`;该选项会加载旧权重,改变实验起点。
+当前入口也不恢复 optimizer/RNG,因此不能把加载权重称为精确续训。
+
+在原可运行 WSL 目录执行:
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python scripts/train_rma.py \
+ --phase teacher \
+ --task go2_joystick_flat/rma_forward_no_pose \
+ --output runs/rma/teacher_forward_no_pose_v1.pt \
+ --num-envs 64 --iterations 3000 --device cuda
+```
+
+原基线:`/home/abc/my_unilab/runs/rma/teacher_forward_v1.pt`。
+新模型:`/home/abc/my_unilab/runs/rma/teacher_forward_no_pose_v1.pt`。
+新训练日志:`/home/abc/my_unilab/runs/rma/teacher_forward_no_pose_v1_logs//`,
+包含 `metrics.csv`、`run_config.json` 与 `tensorboard/`。
+入口会拒绝已经存在的输出路径;重复正式实验请使用新文件名。
+同一次训练中周期性更新本次的新 checkpoint 属于正常保存行为。
+
+## 评估协议
+
+正式训练完成后再执行;评估同样选择实验任务,确保环境与奖励配置对应。
+
+```bash
+for seed in 123 456 789; do
+ uv run --no-sync python scripts/evaluate_rma.py \
+ --policy teacher \
+ --checkpoint runs/rma/teacher_forward_no_pose_v1.pt \
+ --task go2_joystick_flat/rma_forward_no_pose \
+ --num-envs 8 --steps 1000 --seed "$seed" \
+ --command 0.5 0 0 --diagnostics \
+ --trace-dir "runs/rma/evaluations/EXP-003/seed${seed}" || break
+done
+```
+
+主要指标是平均前向速度与前向 RMSE;侧向/转向误差、提前终止及动作范围辅助判断。
+两组总奖励不可直接比较:取消负项,即使运动不变也可能提高 reward。
+第一轮只匹配基线的一个训练种子,结论限于初步诊断;多个评估种子不能替代独立训练种子。
+若无改善应记录结果,不同时再调整动作缩放或训练预算。
+
+## 实测结果(2026-10-23)
+
+原始评估目录:`runs/rma/evaluations/EXP-003/20261023_151848/`,每种子 8000 转移。
+
+| 评估种子 | 平均 vx (m/s) | vx RMSE (m/s) | 提前终止 |
+|---|---:|---:|---:|
+| 123 | 0.01392659 | 0.48912616 | 0 |
+| 456 | 0.01327861 | 0.48960597 | 0 |
+| 789 | 0.01269397 | 0.49064972 | 0 |
+
+与原前进教师约 0.012—0.016 m/s 相近,取消姿态惩罚未带来实质前进。
+这只是一个训练种子的对照;不能据此证明该奖励在所有条件下无效。
+三组图已由原始 CSV 生成,每个 eval 目录下的 plots 含速度、动作、奖励三图。
+
+后续 1 环境 × 500 步控制诊断(`runs/rma/control_diagnostics/EXP-003/eval_2ffou4yp`)
+目标映射残差最大 0.47117 rad。当前运行副本快速路径直接复制自然关节顺序目标,
+忽略不同的执行器顺序。无步进非零目标检查:快速写入最大误差 0.0300000 rad,
+普通写入为零。该问题是当前控制链路缺陷的证据,不代表已解释全部行走失败。
+本轮未改控制器、未改奖励或重训。先修复并验收目标写入,再另起实验建立新基线。
+当前 public backend 不提供实测执行器扭矩,代数 PD 需求估计不能证明扭矩饱和。
diff --git a/experiments/rma/EXP-004_control_mapping.md b/experiments/rma/EXP-004_control_mapping.md
new file mode 100644
index 000000000..9dd688b13
--- /dev/null
+++ b/experiments/rma/EXP-004_control_mapping.md
@@ -0,0 +1,49 @@
+# EXP-004:修复目标写入,重建训练基线
+
+状态:1.3.3 运行副本已修复目标映射,真实短诊断通过;正式训练尚未执行。
+
+## 问题与范围
+
+自然关节顺序为 FL/FR/RL/RR,后端执行器存储顺序为 FR/FL/RR/RL。
+原 `Entity.set_full_width_joint_position_target` 直接 `control.copy_(target)`,
+未做重排。普通 `set_joint_position_target` 已正确解析关节到执行器。
+
+把 GitHub 1.3.4 已有的 full-width 映射实现与懒加载索引缓存定点移植到当前
+`/home/abc/my_unilab/src/unilab/base/entity.py`;没有覆盖整个框架或升级依赖。
+源补丁见 [mapping.patch](patches/unilab_1_3_3_full_width_mapping.patch)。
+该实现缓存解析后的索引,没有每步读取 XML、文件或 CPU 往返;
+正确的重排有计算开销,本轮未做吞吐基准,不承诺与错误直接复制路径完全同速。
+
+原文件备份:`runs/rma/backups/EXP-004_mapping_20261023_171400/entity.py`。
+修改前 SHA256:`546487c77ea7ab8e288ac63eb7dddea08fad6de845f256a436e2151724b7e1d6`。
+修改后 SHA256:`54f5126f62e71acfce6c87c051fbc5e2411264f396dd39161bb7376556810d4d`。
+这些是运行副本的文件哈希,不是 GitHub 1.3.4 文件哈希。
+
+## 验收
+
+无物理步进的不同非零目标检查:快速/普通路径映射最大误差现均为 0(修复前快速路径为 0.0300000 rad)。
+同一个旧教师、种子 123、500 步的真实控制诊断:
+`runs/rma/control_diagnostics/EXP-004_mapping/eval_k8559ph8`,
+`max_abs_mapping_residual_rad = 0.0`(修复前为 0.47117)。
+该检查读取实际控制缓冲,不通过修改观测顺序掩盖错误。
+
+旧策略是在错误映射下训练的,修复后直接播放的表现不能代表修复后训练的效果。
+没有以旧模型不跌倒或突然走起来作为本修复的验收标准。
+两组新初始化的教师入口冒烟测试见 EXP-005;它们不构成学习成功证据。
+
+## 下一步只做这件事
+
+从头训练修复后的原前进任务,保留 pose 惩罚 -0.1、std 0.5、scale 0.25、
+初始化种子 42、64 环境、3000 次更新,不加载旧 checkpoint。
+这次是工程修复后的新基线,不与 EXP-003 混为一个奖励对照。
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python scripts/train_rma.py \
+ --phase teacher --task go2_joystick_flat/rma_forward \
+ --output runs/rma/teacher_mapping_v1.pt \
+ --num-envs 64 --iterations 3000 --device cuda
+```
+
+评估与后续 std 实验的完整命令见 [EXP-005](EXP-005_tracking_width.md)。
+大训练仍由用户自行启动;本轮仅执行短检查,没有启动后台长训。
diff --git a/experiments/rma/EXP-005_tracking_width.md b/experiments/rma/EXP-005_tracking_width.md
new file mode 100644
index 000000000..b9207a87e
--- /dev/null
+++ b/experiments/rma/EXP-005_tracking_width.md
@@ -0,0 +1,158 @@
+# EXP-005:只收紧前向速度跟踪宽度
+
+状态:配置已安装到当前运行副本,单变量解析检查与短训练入口已验证;
+两组正式 3000 次更新尚未执行,尚无性能结论。
+
+## 先理解这个变量
+
+把奖励理解成“速度答卷的评分标准”:偏离目标多少,就扣掉多少分。
+当前 1.3.3 实现 `track_lin_vel_xy_exp` 返回:
+
+`r_tracking = exp(-((vx_command-vx)^2 + (vy_command-vy)^2) / std^2)`。
+
+实验仅将 std 从 0.5 改为 0.35 m/s,weight 保持 2.0。
+下面是尚未乘 weight/dt 的单个分项,假设 vy 误差为 0:
+
+| vx 误差 (m/s) | std=0.5 | std=0.35 |
+|---|---:|---:|
+| 0 | 1.0000 | 1.0000 |
+| 0.1 | 0.9608 | 0.9216 |
+| 0.2 | 0.8521 | 0.7214 |
+| 0.5 | 0.3679 | 0.1299 |
+
+候选假设:更严格的速度奖励能改善跟踪。
+相反结果也可能发生:误差大时奖励很小,策略更难获得有区分度的信号。
+所以 std 小不是天然更好。这不是 PPO 的动作采样标准差,也不是动作缩放或奖励权重。
+
+## 前置条件与两组定义
+
+两组均使用 EXP-004 修复后的相同源码,从头初始化、种子 42、64 环境 × 24 rollout ×
+3000 updates = 4,608,000 transitions,设备均 CUDA(物理仍为 CPU MuJoCo)。
+基线重新使用原前进任务,pose 惩罚为 -0.1;不继承 EXP-003 的 no_pose 配置。
+本次不叠加新的奖励权重、学习率、scale 或训练预算调整。
+
+| 组 | task | std | 新输出文件 |
+|---|---|---:|---|
+| 修复后基线 | go2_joystick_flat/rma_forward | 0.5 | teacher_mapping_v1.pt |
+| 收紧宽度 | go2_joystick_flat/rma_forward_tight_tracking | 0.35 | teacher_mapping_std035_v1.pt |
+
+旧的 teacher_forward_v1 / teacher_forward_no_pose_v1 在错误映射下训练,
+不作为本次 std 对照的基线。不要通过加载旧权重伪装成从头训练。
+一个训练种子的结果只用于初步比较,三个评估种子不是三次独立训练。
+
+## 到底改哪个文件
+
+当前训练机器的文件:
+`/home/abc/my_unilab/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_tight_tracking.yaml`。
+
+```yaml
+# @package _global_
+defaults:
+ - /task/go2_joystick_flat/rma_forward
+ - _self_
+
+reward:
+ tracking_lin_vel:
+ params:
+ std: 0.35
+```
+
+`defaults` 继承基线,`_self_` 让本文件最后覆盖它。
+只写 std,其他参数继承;不要修改 base.yaml,也不要在 train_rma.py 中改 reward。
+训练和评估通过 `--task` 选择配置;改 YAML 不会修改已保存网络的行为。
+
+以后学习修改时,在 WSL 执行:
+
+```bash
+nano /home/abc/my_unilab/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_tight_tracking.yaml
+```
+
+只修改 `std: 0.35` 这一行;Ctrl+O、Enter 保存,Ctrl+X 退出。
+本轮先保持 0.35 不变。下一轮若换成 0.4,先保存旧配置、另起实验编号和模型名,
+不能悄悄修改本轮协议后继续把结果标成 EXP-005。标准实验配置和命令应提交 Git。
+
+### 验证有没有误改第二个变量
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python scripts/inspect_rma_task.py \
+ --task go2_joystick_flat/rma_forward_tight_tracking \
+ --compare-with go2_joystick_flat/rma_forward \
+ --expect-only reward.tracking_lin_vel.params.std
+```
+
+应看到 changes 只有 std:before=0.5、after=0.35。多改了一项或完全没改都会返回非零状态。
+这个命令不训练、不创建物理环境;只解析实际 Hydra 配置。
+已实测的比较结果保存在 `runs/rma/experiments/EXP-005/config_comparison.json`。
+
+## 训练:两组依次运行,不同时占用电脑
+
+1. 先运行 EXP-004 的修复后基线训练,并完成下面评估。
+2. 基线有明确评估记录后,仍想测试这个假设,再运行实验组。
+
+```bash
+cd /home/abc/my_unilab
+uv run --no-sync python scripts/train_rma.py \
+ --phase teacher --task go2_joystick_flat/rma_forward_tight_tracking \
+ --output runs/rma/teacher_mapping_std035_v1.pt \
+ --num-envs 64 --iterations 3000 --device cuda
+```
+
+两组正式训练都不加 `--checkpoint`,均从头训练。输出已存在时脚本会拒绝覆盖;
+重做实验应明确改输出名,不能删除旧模型来掩盖重跑。
+日志分别在 `teacher_mapping_v1_logs//` 与
+`teacher_mapping_std035_v1_logs//`,包括 metrics.csv / tensorboard。
+不要在高温下继续长训;本轮没有启动这两组长训练。
+
+## 每组训练完成后:用共同任务评估
+
+为避免不同奖励定义误导总 reward,正式比较统一在原前进任务评估:
+即实验组网络也选择 `--task go2_joystick_flat/rma_forward`。
+这种做法不会改变网络,且两组的评估奖励、指令、动力学一致。
+主要比较实测速度与 RMSE,而非只比较各自的训练 reward。
+
+基线训练结束后执行;实验组训练完再把 model 一行改为 `teacher_mapping_std035_v1`:
+
+```bash
+cd /home/abc/my_unilab
+model=teacher_mapping_v1
+for seed in 123 456 789; do
+ uv run --no-sync python scripts/evaluate_rma.py \
+ --policy teacher --checkpoint "runs/rma/${model}.pt" \
+ --task go2_joystick_flat/rma_forward \
+ --num-envs 8 --steps 1000 --seed "$seed" \
+ --command 0.5 0 0 --diagnostics \
+ --trace-dir "runs/rma/evaluations/EXP-005/${model}/seed${seed}" || break
+done
+```
+
+结果:终端 JSON + 每次独立 trace 目录中的 summary.json / transitions.csv / run_config.json。
+逐项比较 `diagnostics.mean_measured_velocity[0]`、
+`diagnostics.tracking_rmse_by_axis[0]`、侧向/转向误差及提前终止。
+`terminations` 不是独立测量的跌倒率。
+每回合排除前 100 步的 trace 窗口另行对照,同时保留全程指标。
+训练任务源码应在改动前存档;trace 快照表示评估时配置,不能用它倒推以前训练配置。
+
+画图:对评估输出的实际 trace.directory 执行:
+
+```bash
+uv run --no-sync python scripts/plot_evaluation_trace.py /实际的/trace.directory
+```
+
+## 两个版本不要混用
+
+本记录和上述命令针对当前 1.3.3 的 `std`,运行副本安装的源文件来自
+`experiments/rma/runtime_1_3_3/rma_forward_tight_tracking.yaml`。
+GitHub 1.3.4 的同名任务使用 `tracking_sigma`,公式为 exp(-error/tracking_sigma):
+新宽度 0.35 对应分母 0.1225,且该版本的原基线分母是 0.5,等效 std 约 0.7071。
+因此 1.3.4 的 .5 → .1225 与本记录的 std .5 → .35 不是同一个基线变化;
+1.3.4 测试仅保护该版本单字段变更,不算本轮运行数据。
+不要把两个版本完整覆盖或混为同一实验。新版本需独立编号、重新建基线。
+
+## 本轮已经执行与尚未执行
+
+- 已修复并备份控制映射,残差验证为 0。
+- 已解析实际 1.3.3 配置,确认仅 std .5 → .35;reward weight 等其他项一致。
+- 两组各 2 环境 × 1 次更新的 CPU 短训练用于接口验证,模型名为
+ `smoke_mapping_baseline_20261023.pt` 与 `smoke_tight_std_20261023.pt`。
+- 正式新基线和 std 对照未运行,没有效果结论;不预填成功数值。
diff --git a/experiments/rma/EXP-006_sim2sim_nominal.md b/experiments/rma/EXP-006_sim2sim_nominal.md
new file mode 100644
index 000000000..6132ea860
--- /dev/null
+++ b/experiments/rma/EXP-006_sim2sim_nominal.md
@@ -0,0 +1,72 @@
+# EXP-006:冻结学生策略的 MuJoCo / Genesis 对照
+
+- 日期:2026-10-24。
+- 状态:完成单环境、单种子、1000 步的名义条件评估;仍需诊断速度波动。
+- 问题:Go2 在 Genesis 可以前进,但肉眼观察到踉跄。
+- 目标:先核对观测、控制与 reset 约定,再比较两个物理引擎的速度跟踪。
+- 模型:`student_mapping_v1_500.pt` 与对应 ONNX;本实验不训练、不改变权重。
+- 本次是接口修正后的对照,不是单变量奖励消融。多项接口修正同时存在,不能将结果归因于其中一项。
+
+## 协议与需要保留的约定
+
+两端使用 `--sim2sim-nominal`:home 初始姿态、零初始速度、观测噪声关闭,
+机器人滑动摩擦系数 1.0、附加负载 0 kg、执行器 kp=35、kd=0;
+被动关节阻尼 0.5 与执行器 kd 是不同参数。控制周期 0.02 s。
+单环境,seed=123,1000 步,指令为前向 0.5 m/s、侧向 0、偏航角速度 0。
+MuJoCo 初始回合计数清零;两端本次均在第 1000 步超时。
+
+既有模型的重力输入来自负的 MJCF IMU site `framezaxis`,即世界坐标表达的 site z 轴取负。
+本次 Genesis 保持该训练定义;不能直接替换成常见的机体坐标重力投影,否则改变冻结模型输入。
+速度比较均使用动作执行后的 IMU 位置速度,Genesis 包含 IMU 偏移的角速度叉乘修正。
+
+## 结果
+
+来源:[comparison.json](../../results/rma/sim2sim/EXP-006/comparison.json)。
+RMSE 按全程逐步误差计算,不是平均速度与指令之差。
+
+| 指标 | MuJoCo | Genesis |
+| --- | ---: | ---: |
+| 平均前向速度,m/s | 0.552057 | 0.486771 |
+| 前向速度 RMSE,m/s | 0.101833 | 0.165540 |
+| 平面速度 RMSE,m/s | 0.112781 | 0.174903 |
+| 平均侧向速度,m/s | 0.023105 | 0.027043 |
+| 平均偏航角速度,rad/s | -0.086434 | 0.038306 |
+| 跌倒或异常终止 | 0 | 0 |
+| 右后小腿动作接近边界比例 | 41.7% | 44.9% |
+
+### 速度跟踪
+
+
+
+Genesis 平均前向速度接近指令,但约 3 s、9.5–10 s、11.5–12 s 存在明显降速。
+平均达标不能代替逐步跟踪和 RMSE 检查。
+
+### 动作分布
+
+
+
+这里统计归一化动作 `|action| >= 0.95` 的比例,不能据此宣称机械限位或电机力矩饱和。
+右后小腿是值得进一步检查的关节,但现有数据不能证明它导致降速。
+
+### 姿态与高度
+
+
+
+本次没有跌倒,但存在姿态与高度起伏。
+
+## 结论与边界
+
+支持:冻结策略已在另一物理引擎完成一次前进闭环,当前 Genesis 速度跟踪误差比 MuJoCo 大。
+不支持:已证明任意初始状态下鲁棒、已定位踉跄根因、已达到真机部署验收。
+home reset 且无噪声时,更换随机种子大多重复同一条件;不能把它当作充分的鲁棒性测试。
+接触求解与积分仍有引擎差异,不能宣称两端动力学完全一致。
+
+## 下一项最小工作
+
+保持模型、奖励和控制参数不变,优先检查降速时段的足端接触、关节目标/实际角度、
+执行器力矩及限幅。区分后端实际读数和 PD 代数估计,再决定是否开展单变量实验。
+
+本次完整原始数据保留在 WSL:
+`/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123`。
+GitHub 精选证据、来源说明与复查方式见
+[结果目录](../../results/rma/sim2sim/EXP-006/README.md)。
diff --git a/experiments/rma/TEMPLATE.md b/experiments/rma/TEMPLATE.md
new file mode 100644
index 000000000..b78b99c89
--- /dev/null
+++ b/experiments/rma/TEMPLATE.md
@@ -0,0 +1,15 @@
+# 实验编号:
+
+- 日期 / 状态:
+- 问题与已有证据:
+- 可被推翻的假设:
+- 相对哪个基线,只改变哪一项:
+- 代码 commit / 未提交补丁:
+- 完整配置快照 / 依赖信息:
+- 训练命令 / 初始化种子 / 总环境转移数 / 设备:
+- 日志目录 / checkpoint / SHA256:
+- 评估指令 / 种子 / 环境数 / 步数 / 统计窗口:
+- 实验前约定的主要指标:
+- 逐种子结果 / 原始数据 / 图表 / 视频:
+- 结论支持什么、不支持什么:
+- 下一项最小实验:
diff --git a/experiments/rma/patches/unilab_1_3_3_full_width_mapping.patch b/experiments/rma/patches/unilab_1_3_3_full_width_mapping.patch
new file mode 100644
index 000000000..880bfd5e6
--- /dev/null
+++ b/experiments/rma/patches/unilab_1_3_3_full_width_mapping.patch
@@ -0,0 +1,80 @@
+--- a/src/unilab/base/entity.py
++++ b/src/unilab/base/entity.py
+@@ -1515,6 +1515,11 @@
+ self._actuator_target_joint_names,
+ self._joint_to_actuator_local,
+ ) = self._materialize_joint_actuator_mapping(backend, actuator_ids)
++ self._full_width_control_index_host: np.ndarray | None = None
++ self._full_width_natural_index_host: np.ndarray | None = None
++ self._full_width_control_index_tensor: torch.Tensor | None = None
++ self._full_width_natural_index_tensor: torch.Tensor | None = None
++ self._full_width_index_device: torch.device | None = None
+ if control_buffer is not None:
+ expected_control_shape = (backend.num_envs, backend.num_actuators)
+ if control_buffer.shape != expected_control_shape:
+@@ -2519,19 +2524,60 @@
+ f"Entity '{self.name}' capability 'joint position target' is unavailable "
+ f"for passive joints on backend '{self._backend_type}': {passive_names}"
+ )
+- control = self._require_tensor_control_buffer_public()
+ if target.dtype != torch.float32:
+ raise TypeError("full-width joint position target must be float32")
++ control = self._require_tensor_control_buffer_public()
+ if target.device != control.device:
+ raise ValueError(
+ f"full-width joint position target must live on {control.device}, got {target.device}"
+ )
+- if tuple(target.shape) != tuple(control.shape):
++ if tuple(target.shape) != (control.shape[0], joint_count):
+ raise ValueError(
+ f"full-width joint position target has shape {tuple(target.shape)}; "
+- f"expected {tuple(control.shape)}"
+- )
+- control.copy_(target)
++ f"expected {(control.shape[0], joint_count)} in natural joint order"
++ )
++ if self._actuator_ids is None:
++ raise self._capability_error(
++ "actuator control write", "actuator_names were not declared in EntityCfg"
++ )
++ control_index, natural_index = self._full_width_control_indices(
++ control, joint_to_actuator, joint_count
++ )
++ control[:, control_index] = target.index_select(1, natural_index)
++
++
++ def _full_width_control_indices(
++ self,
++ control: torch.Tensor,
++ joint_to_actuator: np.ndarray,
++ joint_count: int,
++ ) -> tuple[torch.Tensor, torch.Tensor]:
++ assert self._actuator_ids is not None
++ if self._full_width_control_index_host is None:
++ backend_to_natural = np.full(control.shape[1], -1, dtype=np.intp)
++ backend_to_natural[self._actuator_ids[joint_to_actuator]] = np.arange(
++ joint_count, dtype=np.intp
++ )
++ self._full_width_control_index_host = np.flatnonzero(backend_to_natural >= 0)
++ self._full_width_natural_index_host = backend_to_natural[
++ self._full_width_control_index_host
++ ]
++ if (
++ self._full_width_control_index_tensor is None
++ or self._full_width_natural_index_tensor is None
++ or self._full_width_index_device != control.device
++ ):
++ self._full_width_control_index_tensor = torch.from_numpy(
++ self._full_width_control_index_host
++ ).to(device=control.device)
++ self._full_width_natural_index_tensor = torch.from_numpy(
++ self._full_width_natural_index_host
++ ).to(device=control.device)
++ self._full_width_index_device = control.device
++ return (
++ self._full_width_control_index_tensor,
++ self._full_width_natural_index_tensor,
++ )
+
+ def _require_tensor_control_buffer_public(self) -> torch.Tensor:
+ control = self.data.control_buffer
diff --git a/experiments/rma/runtime_1_3_3/rma_forward_tight_tracking.yaml b/experiments/rma/runtime_1_3_3/rma_forward_tight_tracking.yaml
new file mode 100644
index 000000000..9b1bbc63a
--- /dev/null
+++ b/experiments/rma/runtime_1_3_3/rma_forward_tight_tracking.yaml
@@ -0,0 +1,11 @@
+# @package _global_
+# EXP-005: working 1.3.3 runtime ONLY. Baseline std=0.5 -> std=0.35.
+# Inherit rma_forward, not rma_forward_no_pose: keep pose penalty at -0.1.
+defaults:
+ - /task/go2_joystick_flat/rma_forward
+ - _self_
+
+reward:
+ tracking_lin_vel:
+ params:
+ std: 0.35
diff --git a/legged_gym/go2_config.py b/legged_gym/go2_config.py
new file mode 100644
index 000000000..e17cc1ccb
--- /dev/null
+++ b/legged_gym/go2_config.py
@@ -0,0 +1,10 @@
+"""RMA contract only; canonical simulation config remains in unilab/conf YAML."""
+
+OBS_DIM = 49
+CRITIC_DIM = 52
+PRIVILEGED_DIM = 2
+HISTORY_LENGTH = 50
+LATENT_DIM = 8
+NUM_ACTIONS = 12
+POLICY_PERIOD_S = 0.02
+ACTION_SCALE = 0.25
diff --git a/requirements-rma-export.txt b/requirements-rma-export.txt
new file mode 100644
index 000000000..baf3d05bc
--- /dev/null
+++ b/requirements-rma-export.txt
@@ -0,0 +1,4 @@
+# Install inside the original, working UniLab environment.
+onnx>=1.16,<2
+onnxruntime<1.20; python_version < '3.11'
+onnxruntime>=1.20; python_version >= '3.11'
diff --git a/results/rma/baseline/seed123.json b/results/rma/baseline/seed123.json
new file mode 100644
index 000000000..446ec94a6
--- /dev/null
+++ b/results/rma/baseline/seed123.json
@@ -0,0 +1,61 @@
+{
+ "policy": "teacher",
+ "seed": 123,
+ "completed_episodes": 8,
+ "mean_completed_episode_return": 22.94372197985649,
+ "mean_completed_episode_length_steps": 636.25,
+ "mean_step_reward": 0.03588731563591864,
+ "planar_velocity_rmse_m_per_s": 0.5146384602254557,
+ "unfinished_episodes": 8,
+ "mean_unfinished_episode_return": 12.943596839904785,
+ "student_latent_mse_vs_teacher": null,
+ "student_action_rmse_vs_teacher": null,
+ "terminations": 0,
+ "total_transitions": 8000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ -0.006058229419679051,
+ 0.005980759545039106,
+ 0.014841998879314587
+ ],
+ "tracking_rmse_by_axis": [
+ 0.5109570487642697,
+ 0.061446229894282584,
+ 0.11541315228345941
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.06477700540811179,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 0.3603822733908892,
+ "tracking_ang_vel": 0.1920580652654171,
+ "lin_vel_z": -0.011202149931981695,
+ "ang_vel_xy": -0.023651930230640574,
+ "base_height": -0.004054067645105533,
+ "action_rate": -0.008745710445419946,
+ "similar_to_default": -0.18331554384529591,
+ "contact": 0.2000549937337637,
+ "swing_feet_z": 1.2728398969173431
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ }
+}
diff --git a/results/rma/baseline/seed456.json b/results/rma/baseline/seed456.json
new file mode 100644
index 000000000..3b134fb90
--- /dev/null
+++ b/results/rma/baseline/seed456.json
@@ -0,0 +1,61 @@
+{
+ "policy": "teacher",
+ "seed": 456,
+ "completed_episodes": 9,
+ "mean_completed_episode_return": 17.958606203397114,
+ "mean_completed_episode_length_steps": 509.6666666666667,
+ "mean_step_reward": 0.035673840930336154,
+ "planar_velocity_rmse_m_per_s": 0.5223854549035621,
+ "unfinished_episodes": 8,
+ "mean_unfinished_episode_return": 15.470402717590332,
+ "student_latent_mse_vs_teacher": null,
+ "student_action_rmse_vs_teacher": null,
+ "terminations": 1,
+ "total_transitions": 8000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ -0.011666606367917325,
+ 0.014149421059863528,
+ 0.018934832205886893
+ ],
+ "tracking_rmse_by_axis": [
+ 0.5174359250308406,
+ 0.07174000046007187,
+ 0.143143680448307
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.06684632264653795,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 0.3547401953712106,
+ "tracking_ang_vel": 0.19153448170423507,
+ "lin_vel_z": -0.014624936374981188,
+ "ang_vel_xy": -0.025369600676742265,
+ "base_height": -0.006269701974932105,
+ "action_rate": -0.008777687560716459,
+ "similar_to_default": -0.18115082198753954,
+ "contact": 0.20040749409794809,
+ "swing_feet_z": 1.2732026720046996
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ }
+}
diff --git a/results/rma/baseline/seed789.json b/results/rma/baseline/seed789.json
new file mode 100644
index 000000000..6706f4473
--- /dev/null
+++ b/results/rma/baseline/seed789.json
@@ -0,0 +1,61 @@
+{
+ "policy": "teacher",
+ "seed": 789,
+ "completed_episodes": 8,
+ "mean_completed_episode_return": 17.56580749154091,
+ "mean_completed_episode_length_steps": 496.875,
+ "mean_step_reward": 0.03569934609872871,
+ "planar_velocity_rmse_m_per_s": 0.5156226711943084,
+ "unfinished_episodes": 8,
+ "mean_unfinished_episode_return": 18.13353729248047,
+ "student_latent_mse_vs_teacher": null,
+ "student_action_rmse_vs_teacher": null,
+ "terminations": 1,
+ "total_transitions": 8000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ -0.004921973013823731,
+ 0.005795657981586174,
+ -0.0007342302818937725
+ ],
+ "tracking_rmse_by_axis": [
+ 0.5110722221933418,
+ 0.06835146357993736,
+ 0.15672107160305368
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.07771462473009702,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 0.36330923438072205,
+ "tracking_ang_vel": 0.1901205448284745,
+ "lin_vel_z": -0.013487572537051164,
+ "ang_vel_xy": -0.028084615291387307,
+ "base_height": -0.004377204851363786,
+ "action_rate": -0.008941495961428927,
+ "similar_to_default": -0.18495080276578665,
+ "contact": 0.19976249381899833,
+ "swing_feet_z": 1.2716167651414871
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ }
+}
diff --git a/results/rma/diagnostics/EXP-002/seed123/plots/action_distribution.png b/results/rma/diagnostics/EXP-002/seed123/plots/action_distribution.png
new file mode 100644
index 000000000..0916f7887
Binary files /dev/null and b/results/rma/diagnostics/EXP-002/seed123/plots/action_distribution.png differ
diff --git a/results/rma/diagnostics/EXP-002/seed123/plots/reward_components.png b/results/rma/diagnostics/EXP-002/seed123/plots/reward_components.png
new file mode 100644
index 000000000..1e0b7b634
Binary files /dev/null and b/results/rma/diagnostics/EXP-002/seed123/plots/reward_components.png differ
diff --git a/results/rma/diagnostics/EXP-002/seed123/plots/velocity_tracking.png b/results/rma/diagnostics/EXP-002/seed123/plots/velocity_tracking.png
new file mode 100644
index 000000000..ce2d9e86a
Binary files /dev/null and b/results/rma/diagnostics/EXP-002/seed123/plots/velocity_tracking.png differ
diff --git a/results/rma/diagnostics/EXP-002/seed123/provenance.json b/results/rma/diagnostics/EXP-002/seed123/provenance.json
new file mode 100644
index 000000000..2d397f158
--- /dev/null
+++ b/results/rma/diagnostics/EXP-002/seed123/provenance.json
@@ -0,0 +1,12 @@
+{
+ "evaluation_only": true,
+ "source_runtime": "existing local UniLab 1.3.3, NOT the 1.3.4 fork runtime",
+ "source_trace_directory": "/home/abc/my_unilab/runs/rma/evaluations/EXP-002/seed123/eval_hhlzyanz",
+ "rows": 8000,
+ "uncompressed_transitions_sha256": "cb49a7842ac278a026e50b68e32ded5a5049a4906388d5c93d071c9d5a52798b",
+ "source_run_config_sha256": "218ec48c5d484046f280ac4588f688527ec37ba201212f9d5ad84ea898e50a06",
+ "summary_directory_normalization": "absolute trace.directory made relative to source runtime",
+ "per_transition_max_abs_reward_minus_sum_weighted_rates_times_dt": 7.981434464732207e-09,
+ "mapping_note": "runtime target order FL FR RL RR; scene storage order FR FL RR RL",
+ "validation_scope": "one evaluation seed; no new training or real robot/TensorRT control execution"
+}
diff --git a/results/rma/diagnostics/EXP-002/seed123/run_configuration.json b/results/rma/diagnostics/EXP-002/seed123/run_configuration.json
new file mode 100644
index 000000000..5bcc66452
--- /dev/null
+++ b/results/rma/diagnostics/EXP-002/seed123/run_configuration.json
@@ -0,0 +1,207 @@
+{
+ "format": "unilab-rma-evaluation-trace-v1",
+ "created_at_utc": "2026-10-22T14:05:09.081075+00:00",
+ "arguments": {
+ "checkpoint": "runs/rma/teacher_forward_v1.pt",
+ "policy": "teacher",
+ "steps": 1000,
+ "num_envs": 8,
+ "seed": 123,
+ "device": "cpu",
+ "task": "go2_joystick_flat/rma_forward",
+ "command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "diagnostics": true,
+ "trace_dir": "runs/rma/evaluations/EXP-002/seed123",
+ "trace_warmup_steps": 100,
+ "backend": "pytorch",
+ "engine": null,
+ "tensorrt_worker": "/home/abc/my_unilab/build/deploy_trt/policy_worker",
+ "render": false,
+ "render_speed": 1.0
+ },
+ "git_commit": null,
+ "git_dirty": null,
+ "checkpoint_sha256": "5454f899a358932d7208aaf52e82937e1db51f3f71609f1a79204bcc2f6a8fb9",
+ "control_period_s": 0.02,
+ "warmup_steps_per_episode": 100,
+ "velocity_frame": "body; clean critic [49:51] and gyro z [2]",
+ "transition_alignment": "before = s_t; action = a_t; after = terminal s_(t+1), before any reset. Commands at both endpoints are retained; reward belongs to this transition. Full/window summaries use before velocity and command, matching --diagnostics.",
+ "reward_terms": "Per-environment weighted rates from public get_active_iterable_terms(); before control-dt scaling. reward is the actual returned scalar. Do not compare rates directly with reward or across changed weights.",
+ "action_near_bound_definition": "abs(normalized policy action) >= 0.95; NOT torque saturation",
+ "control_contract": {
+ "action_type": "JointPositionAction",
+ "joint_observation_order": [
+ "FL_hip_joint",
+ "FL_thigh_joint",
+ "FL_calf_joint",
+ "FR_hip_joint",
+ "FR_thigh_joint",
+ "FR_calf_joint",
+ "RL_hip_joint",
+ "RL_thigh_joint",
+ "RL_calf_joint",
+ "RR_hip_joint",
+ "RR_thigh_joint",
+ "RR_calf_joint"
+ ],
+ "action_target_joint_order": [
+ "FL_hip_joint",
+ "FL_thigh_joint",
+ "FL_calf_joint",
+ "FR_hip_joint",
+ "FR_thigh_joint",
+ "FR_calf_joint",
+ "RL_hip_joint",
+ "RL_thigh_joint",
+ "RL_calf_joint",
+ "RR_hip_joint",
+ "RR_thigh_joint",
+ "RR_calf_joint"
+ ],
+ "action_target_joint_indices": [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11
+ ],
+ "scale": 0.25,
+ "offset_rad": [
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ],
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ],
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ],
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ],
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ],
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ],
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ],
+ [
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 0.800000011920929,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5,
+ 0.0,
+ 1.0,
+ -1.5
+ ]
+ ],
+ "clip_config": null,
+ "note": "Resolved position-action affine mapping: target = offset + scale * action, before configured clipping and encoder-bias compensation. This is configuration evidence, not a measurement of actuator torque or proof of correct physical response."
+ },
+ "runtime_source_sha256": {
+ "scripts/evaluate_rma.py": "6a0ab5072dcc52a434be29a0b1ec212cdcff22edee9651d78f61b3a300b004ff",
+ "rsl_rl/unilab_rma/evaluation_trace.py": "54ddd1806811fd63c0c6df58010a484a4da4a4b7ecc176014186f6c7bcf42209",
+ "rsl_rl/unilab_rma/env_adapter.py": "3b29df75056b3303162020b64b037b100f45597de072339909cd3f72e1f831fc",
+ "src/unilab/envs/mdp/actions/actions.py": "631a2c5853b9bfee35f92faebfb5a6e8d9abd5308f701b86ca72ac97af108daa",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/base.yaml": "1f91628cc0201affda56c1b7363469224100ad5d59c2421826d44cc58d399dce",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/mujoco.yaml": "57d4fa8552601cdc151f5dc3e9dee48dbb0281e25f6e4138225414ec9450ddc9",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma.yaml": "f8fa2851e1ee6e0d4a078d5e027367244e245c5ec990d4d56b8da731143da3d1",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward.yaml": "ae040ad352f95f15e45fa100552a804e36dcf0ebd5e41fab4982dc385289450c"
+ }
+}
diff --git a/results/rma/diagnostics/EXP-002/seed123/summary.json b/results/rma/diagnostics/EXP-002/seed123/summary.json
new file mode 100644
index 000000000..bbdc155bf
--- /dev/null
+++ b/results/rma/diagnostics/EXP-002/seed123/summary.json
@@ -0,0 +1,172 @@
+{
+ "policy": "teacher",
+ "seed": 123,
+ "completed_episodes": 9,
+ "mean_completed_episode_return": 11.619225793414646,
+ "mean_completed_episode_length_steps": 629.2222222222222,
+ "mean_step_reward": 0.01859980582818389,
+ "planar_velocity_rmse_m_per_s": 0.49315400810945587,
+ "unfinished_episodes": 8,
+ "mean_unfinished_episode_return": 5.528181076049805,
+ "student_latent_mse_vs_teacher": null,
+ "student_action_rmse_vs_teacher": null,
+ "terminations": 2,
+ "total_transitions": 8000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "task": "go2_joystick_flat/rma_forward",
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ 0.015685936529645686,
+ -0.007749902041240091,
+ 0.03442901849853064
+ ],
+ "tracking_rmse_by_axis": [
+ 0.4897715884761797,
+ 0.057659923685617856,
+ 0.130251946827097
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.06008052522769907,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 0.7773760445713996,
+ "tracking_ang_vel": 0.1921130729392171,
+ "lin_vel_z": -0.00598462969110642,
+ "ang_vel_xy": -0.015748580647712514,
+ "base_height": -0.02333792574959807,
+ "action_rate": -0.0035400085798974034,
+ "similar_to_default": -0.22660776471346616,
+ "contact": 0.17592749336361885,
+ "swing_feet_z": 0.059792615115642544
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ },
+ "trace": {
+ "directory": "runs/rma/evaluations/EXP-002/seed123/eval_hhlzyanz",
+ "full": {
+ "transitions": 8000,
+ "mean_measured_velocity": [
+ 0.015685936529645686,
+ -0.007749902041240091,
+ 0.03442901849853064
+ ],
+ "tracking_rmse_by_axis": [
+ 0.4897715884761797,
+ 0.057659923685617856,
+ 0.130251946827097
+ ]
+ },
+ "after_startup_window": {
+ "transitions": 6441,
+ "mean_measured_velocity": [
+ 0.005411946213178311,
+ -0.008237274517975087,
+ 0.029306703015956937
+ ],
+ "tracking_rmse_by_axis": [
+ 0.49605150579501395,
+ 0.04753374617814368,
+ 0.1140356219251169
+ ]
+ },
+ "action_target_joint_order": [
+ "FL_hip_joint",
+ "FL_thigh_joint",
+ "FL_calf_joint",
+ "FR_hip_joint",
+ "FR_thigh_joint",
+ "FR_calf_joint",
+ "RL_hip_joint",
+ "RL_thigh_joint",
+ "RL_calf_joint",
+ "RR_hip_joint",
+ "RR_thigh_joint",
+ "RR_calf_joint"
+ ],
+ "normalized_action_min": [
+ -0.9993775486946106,
+ -0.9668697118759155,
+ -0.9999176263809204,
+ -0.9999958872795105,
+ -0.995573103427887,
+ -0.9999606013298035,
+ -0.9598953723907471,
+ -0.9964564442634583,
+ -0.9709935784339905,
+ -0.9979996085166931,
+ -0.9999731779098511,
+ -0.9999999403953552
+ ],
+ "normalized_action_max": [
+ 0.9999996423721313,
+ 0.999978244304657,
+ 0.9993966817855835,
+ 0.9999985098838806,
+ 1.0,
+ 0.9991804361343384,
+ 0.9746895432472229,
+ 0.9953311681747437,
+ 0.9999371767044067,
+ 0.999275803565979,
+ 0.9999285340309143,
+ 0.9995235204696655
+ ],
+ "normalized_action_rms": [
+ 0.7247534918404762,
+ 0.5432697781967367,
+ 0.7470075142745547,
+ 0.9609439729510459,
+ 0.8531229726316407,
+ 0.7976436916930699,
+ 0.500297835338496,
+ 0.6434645464779805,
+ 0.599723134410426,
+ 0.6020377576120008,
+ 0.9777176011108335,
+ 0.7660410524218811
+ ],
+ "normalized_action_near_bound_fraction": [
+ 0.079375,
+ 0.04075,
+ 0.131375,
+ 0.749125,
+ 0.25975,
+ 0.3745,
+ 0.001875,
+ 0.030125,
+ 0.0745,
+ 0.00625,
+ 0.952375,
+ 0.0805
+ ],
+ "mean_weighted_reward_rates_before_dt": {
+ "tracking_lin_vel": 0.7773760459618643,
+ "tracking_ang_vel": 0.19211307309247833,
+ "lin_vel_z": -0.005984629674967392,
+ "ang_vel_xy": -0.015748580673659234,
+ "base_height": -0.023337925799274715,
+ "action_rate": -0.003540008571808016,
+ "similar_to_default": -0.22660776428505777,
+ "contact": 0.17592749336827546,
+ "swing_feet_z": 0.059792615123093126
+ }
+ }
+}
diff --git a/results/rma/diagnostics/EXP-002/seed123/transitions.csv.gz b/results/rma/diagnostics/EXP-002/seed123/transitions.csv.gz
new file mode 100644
index 000000000..c05299a36
Binary files /dev/null and b/results/rma/diagnostics/EXP-002/seed123/transitions.csv.gz differ
diff --git a/results/rma/evaluation_summary.csv b/results/rma/evaluation_summary.csv
new file mode 100644
index 000000000..94c3ebbc7
--- /dev/null
+++ b/results/rma/evaluation_summary.csv
@@ -0,0 +1,7 @@
+model,seed,target_vx_m_s,mean_vx_m_s,vx_rmse_m_s,planar_rmse_m_s,terminations,total_transitions
+baseline,123,0.5,-0.006058229419679051,0.5109570487642697,0.5146384602254557,0,8000
+baseline,456,0.5,-0.011666606367917325,0.5174359250308406,0.5223854549035621,1,8000
+baseline,789,0.5,-0.004921973013823731,0.5110722221933418,0.5156226711943084,1,8000
+forward_v1,123,0.5,0.015685936529645686,0.4897715884761797,0.49315400810945587,2,8000
+forward_v1,456,0.5,0.013729549131713991,0.49066846115678453,0.49315459737476025,0,8000
+forward_v1,789,0.5,0.012253768285125432,0.49195942077463545,0.49402653605180963,0,8000
diff --git a/results/rma/figures/forward_v1_training.png b/results/rma/figures/forward_v1_training.png
new file mode 100644
index 000000000..5c444d76b
Binary files /dev/null and b/results/rma/figures/forward_v1_training.png differ
diff --git a/results/rma/figures/velocity_comparison.png b/results/rma/figures/velocity_comparison.png
new file mode 100644
index 000000000..802b5113a
Binary files /dev/null and b/results/rma/figures/velocity_comparison.png differ
diff --git a/results/rma/forward_v1/checkpoint_metadata.json b/results/rma/forward_v1/checkpoint_metadata.json
new file mode 100644
index 000000000..6bdfb3205
--- /dev/null
+++ b/results/rma/forward_v1/checkpoint_metadata.json
@@ -0,0 +1,20 @@
+{
+ "checkpoint": "teacher_forward_v1.pt",
+ "sha256": "5454f899a358932d7208aaf52e82937e1db51f3f71609f1a79204bcc2f6a8fb9",
+ "format": "unilab-rma-v1",
+ "phase": "teacher",
+ "completed_iterations": 3000,
+ "model_config": {
+ "obs_dim": 49,
+ "critic_dim": 52,
+ "privileged_dim": 2,
+ "history_length": 50,
+ "latent_dim": 8,
+ "action_dim": 12,
+ "hidden": [
+ 256,
+ 128
+ ]
+ },
+ "weights_included": false
+}
diff --git a/results/rma/forward_v1/config_snapshot/base.yaml b/results/rma/forward_v1/config_snapshot/base.yaml
new file mode 100644
index 000000000..4886ea6ee
--- /dev/null
+++ b/results/rma/forward_v1/config_snapshot/base.yaml
@@ -0,0 +1,239 @@
+# @package _global_
+# Canonical Go2 flat Manager-Based task declaration. Backend owner leaves inherit
+# this file and only override backend/algo tuning or explicitly disabled terms.
+env:
+ scene:
+ model_file: src/unilab/assets/robots/go2/scene_flat.xml
+ default_keyframe_name: home
+ entities:
+ robot:
+ root_body_name: base
+ body_names: [FL_calf]
+ joint_names:
+ - FL_hip_joint
+ - FL_thigh_joint
+ - FL_calf_joint
+ - FR_hip_joint
+ - FR_thigh_joint
+ - FR_calf_joint
+ - RL_hip_joint
+ - RL_thigh_joint
+ - RL_calf_joint
+ - RR_hip_joint
+ - RR_thigh_joint
+ - RR_calf_joint
+ actuator_names:
+ - FR_hip
+ - FR_thigh
+ - FR_calf
+ - FL_hip
+ - FL_thigh
+ - FL_calf
+ - RR_hip
+ - RR_thigh
+ - RR_calf
+ - RL_hip
+ - RL_thigh
+ - RL_calf
+ sim_dt: 0.01
+ ctrl_dt: 0.02
+ max_episode_seconds: 20.0
+ observations:
+ policy:
+ terms:
+ base_ang_vel:
+ func: unilab.envs.mdp.builtin_sensor
+ params:
+ sensor_name: gyro
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ projected_gravity:
+ func: unilab.envs.mdp.projected_gravity_from_sensor
+ params:
+ sensor_name: upvector
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ joint_pos:
+ func: unilab.envs.mdp.joint_pos_rel
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ joint_vel:
+ func: unilab.envs.mdp.joint_vel_rel
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ actions:
+ func: unilab.envs.mdp.last_action
+ command:
+ func: unilab.envs.mdp.generated_commands
+ params:
+ command_name: twist
+ gait_phase:
+ func: unilab.tasks.locomotion.common.manager_terms.quadruped_gait_phase
+ params:
+ frequency: 2.0
+ critic:
+ terms:
+ base_ang_vel:
+ func: unilab.envs.mdp.builtin_sensor
+ params:
+ sensor_name: gyro
+ projected_gravity:
+ func: unilab.envs.mdp.projected_gravity_from_sensor
+ params:
+ sensor_name: upvector
+ joint_pos:
+ func: unilab.envs.mdp.joint_pos_rel
+ joint_vel:
+ func: unilab.envs.mdp.joint_vel_rel
+ actions:
+ func: unilab.envs.mdp.last_action
+ command:
+ func: unilab.envs.mdp.generated_commands
+ params:
+ command_name: twist
+ gait_phase:
+ func: unilab.tasks.locomotion.common.manager_terms.quadruped_gait_phase
+ params:
+ frequency: 2.0
+ base_lin_vel:
+ func: unilab.envs.mdp.builtin_sensor
+ params:
+ sensor_name: local_linvel
+ actions:
+ joint_pos:
+ _target_: unilab.envs.mdp.JointPositionActionCfg
+ entity_name: robot
+ actuator_names: [".*"]
+ scale: 0.25
+ use_default_offset: true
+ commands:
+ twist:
+ _target_: unilab.envs.mdp.UniformVelocityCommandCfg
+ entity_name: robot
+ resampling_time_range: [20.0, 20.0]
+ heading_command: false
+ heading_control_stiffness: 0.5
+ rel_standing_envs: 0.0
+ rel_heading_envs: 0.0
+ rel_world_envs: 0.0
+ rel_forward_envs: 0.0
+ init_velocity_prob: 0.0
+ ranges:
+ lin_vel_x: [-0.6, 1.0]
+ lin_vel_y: [-0.4, 0.4]
+ ang_vel_z: [-0.8, 0.8]
+ events:
+ reset_scene_to_default:
+ func: unilab.envs.mdp.reset_scene_to_default
+ mode: reset
+ reset_root_state_uniform:
+ func: unilab.envs.mdp.reset_root_state_uniform
+ mode: reset
+ params:
+ pose_range:
+ x: [-0.5, 0.5]
+ y: [-0.5, 0.5]
+ z: [0.0, 0.0]
+ roll: [0.0, 0.0]
+ pitch: [0.0, 0.0]
+ yaw: [-3.141592653589793, 3.141592653589793]
+ velocity_range:
+ x: [-0.5, 0.5]
+ y: [-0.5, 0.5]
+ z: [-0.5, 0.5]
+ roll: [-0.5, 0.5]
+ pitch: [-0.5, 0.5]
+ yaw: [-0.5, 0.5]
+ randomize_leg_mass:
+ func: unilab.envs.mdp.randomize_rigid_body_mass
+ mode: reset
+ params:
+ asset_cfg:
+ _target_: unilab.managers.SceneEntityCfg
+ name: robot
+ body_names: [FL_calf]
+ operation: add
+ distribution: uniform
+ mass_distribution_params: [10.0, 15.0]
+ recompute_inertia: false
+ pd_gains:
+ func: unilab.envs.mdp.pd_gains
+ mode: reset
+ params:
+ kp_range: [31.5, 38.5]
+ kd_range: [0.45, 0.55]
+ operation: abs
+ terminations:
+ time_out:
+ func: unilab.envs.mdp.time_out
+ time_out: true
+ bad_orientation:
+ func: unilab.envs.mdp.bad_orientation
+ params:
+ limit_angle: 1.0471975511965976
+ policy_observation_group: policy
+ critic_observation_group: critic
+
+reward:
+ tracking_lin_vel:
+ func: unilab.tasks.locomotion.common.manager_terms.track_lin_vel_xy_exp
+ weight: 1.0
+ params:
+ std: 0.5
+ command_name: twist
+ tracking_ang_vel:
+ func: unilab.tasks.locomotion.common.manager_terms.track_ang_vel_z_exp
+ weight: 0.2
+ params:
+ std: 0.5
+ command_name: twist
+ lin_vel_z:
+ func: unilab.tasks.locomotion.common.manager_terms.lin_vel_z_l2
+ weight: -5.0
+ ang_vel_xy:
+ func: unilab.tasks.locomotion.common.manager_terms.ang_vel_xy_l2
+ weight: -0.1
+ base_height:
+ func: unilab.tasks.locomotion.common.manager_terms.base_height_l2
+ weight: -100.0
+ params:
+ target_height: 0.3
+ action_rate:
+ func: unilab.envs.mdp.action_rate_l2
+ weight: -0.005
+ similar_to_default:
+ func: unilab.tasks.locomotion.common.manager_terms.joint_deviation_l1
+ weight: -0.1
+ contact:
+ func: unilab.tasks.locomotion.common.manager_terms.feet_phase_contact
+ weight: 0.24
+ params:
+ frequency: 2.0
+ sensor_names:
+ - FL_foot_contact
+ - FR_foot_contact
+ - RL_foot_contact
+ - RR_foot_contact
+ contact_threshold: 0.1
+ stance_threshold: 0.6
+ swing_feet_z:
+ func: unilab.tasks.locomotion.common.manager_terms.feet_phase_swing_height
+ weight: 4.0
+ params:
+ frequency: 2.0
+ sensor_names: [FL_pos, FR_pos, RL_pos, RR_pos]
+ target_height: 0.1
+ kernel: 0.01
+ swing_start: 0.6
diff --git a/results/rma/forward_v1/config_snapshot/composed_unresolved.yaml b/results/rma/forward_v1/config_snapshot/composed_unresolved.yaml
new file mode 100644
index 000000000..47b6f3486
--- /dev/null
+++ b/results/rma/forward_v1/config_snapshot/composed_unresolved.yaml
@@ -0,0 +1,438 @@
+algo:
+ algo: ppo
+ algo_log_name: rsl_rl_ppo
+ seed: 1
+ num_envs: 1024
+ num_steps_per_env: 24
+ max_iterations: 151
+ save_interval: 100
+ obs_groups:
+ actor:
+ - policy
+ critic:
+ - critic
+ experiment_name: test
+ run_name: ''
+ resume: false
+ load_run: '-1'
+ checkpoint: -1
+ resume_path: null
+ actor:
+ class_name: rsl_rl.models.MLPModel
+ hidden_dims:
+ - 512
+ - 256
+ - 128
+ activation: elu
+ obs_normalization: true
+ distribution_cfg:
+ class_name: rsl_rl.modules.distribution.GaussianDistribution
+ init_std: 0.5
+ std_type: scalar
+ critic:
+ class_name: rsl_rl.models.MLPModel
+ hidden_dims:
+ - 512
+ - 256
+ - 128
+ activation: elu
+ obs_normalization: true
+ algorithm:
+ class_name: rsl_rl.algorithms:PPO
+ value_loss_coef: 1.0
+ use_clipped_value_loss: true
+ clip_param: 0.2
+ entropy_coef: 0.001
+ num_learning_epochs: 5
+ num_mini_batches: 4
+ learning_rate: 0.0003
+ schedule: adaptive
+ gamma: 0.99
+ lam: 0.95
+ desired_kl: 0.01
+ max_grad_norm: 1.0
+training:
+ task_name: Go2JoystickFlat
+ dp_collector_cpu_ids: null
+ device: null
+ logger: tensorboard
+ log_interval: 1
+ wandb_project: unilab
+ wandb_entity: null
+ wandb_group: null
+ wandb_job_type: null
+ wandb_name: null
+ wandb_tags: []
+ wandb_notes: null
+ wandb_mode: null
+ sim_backend: mujoco
+ nan_guard:
+ enabled: true
+ buffer_size: 100
+ max_envs_to_dump: 5
+ output_dir: null
+ play_only: false
+ no_play: false
+ sim2sim_strict: true
+ play_render_mode: auto
+ play_env_num: 16
+ render_spacing: 1.0
+ play_steps: 200
+ cam_distance: 6.0
+ cam_elevation: -20.0
+ cam_azimuth: 90.0
+ cam_lookat: null
+ cam_tracking: false
+ cam_tracking_env_idx: 0
+ cam_tracking_extra_envs: 2
+ log_root: null
+ num_timesteps: null
+ log_dir: null
+interactive:
+ action_mode: zero
+ policy_obs_mode: auto
+ show_target_bodies: false
+ show_reward_debug: false
+ target_show_axes: false
+ target_body_names: ''
+ target_max_bodies: 0
+ target_marker_radius: 0.02
+ target_axis_length: 0.08
+ target_marker_alpha: 0.75
+ reward_debug_show_velocity: false
+ reward_debug_lin_vel_scale: 0.08
+ reward_debug_ang_vel_scale: 0.05
+ reward_debug_show_connectors: false
+ reward_debug_show_global_anchor: false
+ camera_follow_body: true
+ camera_focus_body_name: ''
+ camera_height_offset: 0.15
+ camera_distance: null
+ camera_elevation: null
+ camera_azimuth: null
+ use_env_visual_model: true
+ speed: 1.0
+ start_paused: false
+ keyboard: false
+ keyboard_step_lin: 0.1
+ keyboard_step_ang: 0.2
+viser:
+ port: 8080
+ env_idx: 0
+ display_mode: all
+ max_envs: 16
+env:
+ scene:
+ model_file: src/unilab/assets/robots/go2/scene_flat.xml
+ default_keyframe_name: home
+ entities:
+ robot:
+ root_body_name: base
+ body_names:
+ - FL_calf
+ - base
+ joint_names:
+ - FL_hip_joint
+ - FL_thigh_joint
+ - FL_calf_joint
+ - FR_hip_joint
+ - FR_thigh_joint
+ - FR_calf_joint
+ - RL_hip_joint
+ - RL_thigh_joint
+ - RL_calf_joint
+ - RR_hip_joint
+ - RR_thigh_joint
+ - RR_calf_joint
+ actuator_names:
+ - FR_hip
+ - FR_thigh
+ - FR_calf
+ - FL_hip
+ - FL_thigh
+ - FL_calf
+ - RR_hip
+ - RR_thigh
+ - RR_calf
+ - RL_hip
+ - RL_thigh
+ - RL_calf
+ geom_names: []
+ sim_dt: 0.01
+ ctrl_dt: 0.02
+ max_episode_seconds: 20.0
+ observations:
+ policy:
+ terms:
+ base_ang_vel:
+ func: unilab.envs.mdp.builtin_sensor
+ params:
+ sensor_name: gyro
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ projected_gravity:
+ func: unilab.envs.mdp.projected_gravity_from_sensor
+ params:
+ sensor_name: upvector
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ joint_pos:
+ func: unilab.envs.mdp.joint_pos_rel
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ joint_vel:
+ func: unilab.envs.mdp.joint_vel_rel
+ noise:
+ _target_: unilab.managers._noise.UniformNoiseCfg
+ n_min: -0.2
+ n_max: 0.2
+ operation: add
+ actions:
+ func: unilab.envs.mdp.last_action
+ command:
+ func: unilab.envs.mdp.generated_commands
+ params:
+ command_name: twist
+ gait_phase:
+ func: unilab.tasks.locomotion.common.manager_terms.quadruped_gait_phase
+ params:
+ frequency: 2.0
+ critic:
+ terms:
+ base_ang_vel:
+ func: unilab.envs.mdp.builtin_sensor
+ params:
+ sensor_name: gyro
+ projected_gravity:
+ func: unilab.envs.mdp.projected_gravity_from_sensor
+ params:
+ sensor_name: upvector
+ joint_pos:
+ func: unilab.envs.mdp.joint_pos_rel
+ joint_vel:
+ func: unilab.envs.mdp.joint_vel_rel
+ actions:
+ func: unilab.envs.mdp.last_action
+ command:
+ func: unilab.envs.mdp.generated_commands
+ params:
+ command_name: twist
+ gait_phase:
+ func: unilab.tasks.locomotion.common.manager_terms.quadruped_gait_phase
+ params:
+ frequency: 2.0
+ base_lin_vel:
+ func: unilab.envs.mdp.builtin_sensor
+ params:
+ sensor_name: local_linvel
+ privileged:
+ terms:
+ parameters:
+ func: unilab.envs.mdp.rma.privileged_parameters
+ actions:
+ joint_pos:
+ _target_: unilab.envs.mdp.JointPositionActionCfg
+ entity_name: robot
+ actuator_names:
+ - .*
+ scale: 0.25
+ use_default_offset: true
+ commands:
+ twist:
+ _target_: unilab.envs.mdp.UniformVelocityCommandCfg
+ entity_name: robot
+ resampling_time_range:
+ - 20.0
+ - 20.0
+ heading_command: false
+ heading_control_stiffness: 0.5
+ rel_standing_envs: 0.0
+ rel_heading_envs: 0.0
+ rel_world_envs: 0.0
+ rel_forward_envs: 0.0
+ init_velocity_prob: 0.0
+ ranges:
+ lin_vel_x:
+ - 0.3
+ - 0.6
+ lin_vel_y:
+ - 0.0
+ - 0.0
+ ang_vel_z:
+ - 0.0
+ - 0.0
+ events:
+ reset_scene_to_default:
+ func: unilab.envs.mdp.reset_scene_to_default
+ mode: reset
+ reset_root_state_uniform:
+ func: unilab.envs.mdp.reset_root_state_uniform
+ mode: reset
+ params:
+ pose_range:
+ x:
+ - -0.5
+ - 0.5
+ 'y':
+ - -0.5
+ - 0.5
+ z:
+ - 0.0
+ - 0.0
+ roll:
+ - 0.0
+ - 0.0
+ pitch:
+ - 0.0
+ - 0.0
+ yaw:
+ - -3.141592653589793
+ - 3.141592653589793
+ velocity_range:
+ x:
+ - -0.5
+ - 0.5
+ 'y':
+ - -0.5
+ - 0.5
+ z:
+ - -0.5
+ - 0.5
+ roll:
+ - -0.5
+ - 0.5
+ pitch:
+ - -0.5
+ - 0.5
+ yaw:
+ - -0.5
+ - 0.5
+ randomize_leg_mass: null
+ pd_gains:
+ func: unilab.envs.mdp.pd_gains
+ mode: reset
+ params:
+ kp_range:
+ - 31.5
+ - 38.5
+ kd_range:
+ - 0.45
+ - 0.55
+ operation: abs
+ rma_base_load:
+ func: unilab.envs.mdp.rma.RMABaseMass
+ mode: reset
+ params:
+ asset_cfg:
+ _target_: unilab.managers.SceneEntityCfg
+ name: robot
+ body_names:
+ - base
+ operation: add
+ distribution: uniform
+ mass_distribution_params:
+ - 0.0
+ - 5.0
+ recompute_inertia: false
+ rma_friction:
+ func: unilab.envs.mdp.rma.RMAFriction
+ mode: reset
+ params:
+ asset_cfg:
+ _target_: unilab.managers.SceneEntityCfg
+ name: robot
+ geom_names:
+ - .*
+ ranges:
+ - 0.4
+ - 1.25
+ axes:
+ - 0
+ shared_random: true
+ operation: abs
+ terminations:
+ time_out:
+ func: unilab.envs.mdp.time_out
+ time_out: true
+ bad_orientation:
+ func: unilab.envs.mdp.bad_orientation
+ params:
+ limit_angle: 1.0471975511965976
+ policy_observation_group: policy
+ critic_observation_group: critic
+ auto_reset: false
+reward:
+ tracking_lin_vel:
+ func: unilab.tasks.locomotion.common.manager_terms.track_lin_vel_xy_exp
+ weight: 2.0
+ params:
+ std: 0.5
+ command_name: twist
+ tracking_ang_vel:
+ func: unilab.tasks.locomotion.common.manager_terms.track_ang_vel_z_exp
+ weight: 0.2
+ params:
+ std: 0.5
+ command_name: twist
+ lin_vel_z:
+ func: unilab.tasks.locomotion.common.manager_terms.lin_vel_z_l2
+ weight: -5.0
+ ang_vel_xy:
+ func: unilab.tasks.locomotion.common.manager_terms.ang_vel_xy_l2
+ weight: -0.1
+ base_height:
+ func: unilab.tasks.locomotion.common.manager_terms.base_height_l2
+ weight: -100.0
+ params:
+ target_height: 0.3
+ action_rate:
+ func: unilab.envs.mdp.action_rate_l2
+ weight: -0.005
+ similar_to_default:
+ func: unilab.tasks.locomotion.common.manager_terms.joint_deviation_l1
+ weight: -0.1
+ contact:
+ func: unilab.tasks.locomotion.common.manager_terms.feet_phase_contact
+ weight: 0.24
+ params:
+ frequency: 2.0
+ sensor_names:
+ - FL_foot_contact
+ - FR_foot_contact
+ - RL_foot_contact
+ - RR_foot_contact
+ contact_threshold: 0.1
+ stance_threshold: 0.6
+ swing_feet_z:
+ func: unilab.tasks.locomotion.common.manager_terms.feet_phase_swing_height
+ weight: 0.25
+ params:
+ frequency: 2.0
+ sensor_names:
+ - FL_pos
+ - FR_pos
+ - RL_pos
+ - RR_pos
+ target_height: 0.1
+ kernel: 0.01
+ swing_start: 0.6
+play_profile:
+ enabled: true
+ env:
+ render_spacing: 2.0
+rma:
+ obs_dim: 49
+ critic_dim: 52
+ privileged_dim: 2
+ history_length: 50
+ latent_dim: 8
+ action_dim: 12
diff --git a/results/rma/forward_v1/config_snapshot/mujoco.yaml b/results/rma/forward_v1/config_snapshot/mujoco.yaml
new file mode 100644
index 000000000..eb743cfa1
--- /dev/null
+++ b/results/rma/forward_v1/config_snapshot/mujoco.yaml
@@ -0,0 +1,29 @@
+# @package _global_
+defaults:
+ - /task/go2_joystick_flat/base
+ - _self_
+
+training:
+ task_name: Go2JoystickFlat
+ sim_backend: mujoco
+algo:
+ num_envs: 1024
+ max_iterations: 151
+ obs_groups:
+ actor:
+ - actor
+ critic:
+ - critic
+ actor:
+ obs_normalization: true
+ distribution_cfg:
+ init_std: 0.5
+ critic:
+ obs_normalization: true
+ algorithm:
+ learning_rate: 3.0e-4
+ entropy_coef: 1.0e-3
+play_profile:
+ enabled: true
+ env:
+ render_spacing: 2.0
diff --git a/results/rma/forward_v1/config_snapshot/rma.yaml b/results/rma/forward_v1/config_snapshot/rma.yaml
new file mode 100644
index 000000000..24bc7c893
--- /dev/null
+++ b/results/rma/forward_v1/config_snapshot/rma.yaml
@@ -0,0 +1,60 @@
+# @package _global_
+defaults:
+ - /task/go2_joystick_flat/mujoco
+ - _self_
+
+# Existing non-RMA configs remain unchanged. train_rma.py composes this overlay.
+env:
+ policy_observation_group: policy
+ critic_observation_group: critic
+ scene:
+ entities:
+ robot:
+ body_names: [FL_calf, base]
+ # train_rma.py fills exact named robot geoms from the restored XML assets.
+ geom_names: []
+ observations:
+ privileged:
+ terms:
+ parameters:
+ func: unilab.envs.mdp.rma.privileged_parameters
+ events:
+ randomize_leg_mass: null
+ rma_base_load:
+ func: unilab.envs.mdp.rma.RMABaseMass
+ mode: reset
+ params:
+ asset_cfg:
+ _target_: unilab.managers.SceneEntityCfg
+ name: robot
+ body_names: [base]
+ operation: add
+ distribution: uniform
+ mass_distribution_params: [0.0, 5.0]
+ recompute_inertia: false
+ rma_friction:
+ func: unilab.envs.mdp.rma.RMAFriction
+ mode: reset
+ params:
+ asset_cfg:
+ _target_: unilab.managers.SceneEntityCfg
+ name: robot
+ geom_names: ['.*']
+ ranges: [0.4, 1.25]
+ axes: [0]
+ shared_random: true
+ operation: abs
+ auto_reset: false
+
+algo:
+ obs_groups:
+ actor: [policy]
+ critic: [critic]
+
+rma:
+ obs_dim: 49
+ critic_dim: 52
+ privileged_dim: 2
+ history_length: 50
+ latent_dim: 8
+ action_dim: 12
diff --git a/results/rma/forward_v1/config_snapshot/rma_forward.yaml b/results/rma/forward_v1/config_snapshot/rma_forward.yaml
new file mode 100644
index 000000000..26f3e85d4
--- /dev/null
+++ b/results/rma/forward_v1/config_snapshot/rma_forward.yaml
@@ -0,0 +1,20 @@
+# @package _global_
+# Experimental forward-walking curriculum. Original rma task is unchanged.
+# Same policy I/O, dynamics, action scale and randomization as the RMA baseline.
+defaults:
+ - /task/go2_joystick_flat/rma
+ - _self_
+
+env:
+ commands:
+ twist:
+ ranges:
+ lin_vel_x: [0.3, 0.6]
+ lin_vel_y: [0.0, 0.0]
+ ang_vel_z: [0.0, 0.0]
+
+reward:
+ tracking_lin_vel:
+ weight: 2.0
+ swing_feet_z:
+ weight: 0.25
diff --git a/results/rma/forward_v1/run_configuration.json b/results/rma/forward_v1/run_configuration.json
new file mode 100644
index 000000000..c68aba78f
--- /dev/null
+++ b/results/rma/forward_v1/run_configuration.json
@@ -0,0 +1,35 @@
+{
+ "arguments": {
+ "phase": "teacher",
+ "checkpoint": null,
+ "output": "runs/rma/teacher_forward_v1.pt",
+ "iterations": 3000,
+ "num_envs": 64,
+ "device": "cuda",
+ "task": "go2_joystick_flat/rma_forward",
+ "log_dir": null
+ },
+ "model_config": {
+ "obs_dim": 49,
+ "critic_dim": 52,
+ "privileged_dim": 2,
+ "history_length": 50,
+ "latent_dim": 8,
+ "action_dim": 12,
+ "hidden": [
+ 256,
+ 128
+ ]
+ },
+ "horizon": 24,
+ "seed": 42,
+ "torch_version": "2.14.0+cu130",
+ "requested_policy_device": "cuda",
+ "environment_device": "cpu",
+ "sim_backend": "mujoco",
+ "output": "runs/rma/teacher_forward_v1.pt",
+ "phase": "teacher",
+ "log_directory": "runs/rma/teacher_forward_v1_logs/20261022_180845_or3cyhd9",
+ "iteration_numbering": "one-based completed updates",
+ "publication_note": "Only absolute output/log paths were made relative; other fields unchanged."
+}
diff --git a/results/rma/forward_v1/seed123.json b/results/rma/forward_v1/seed123.json
new file mode 100644
index 000000000..56212557d
--- /dev/null
+++ b/results/rma/forward_v1/seed123.json
@@ -0,0 +1,62 @@
+{
+ "policy": "teacher",
+ "seed": 123,
+ "completed_episodes": 9,
+ "mean_completed_episode_return": 11.619225793414646,
+ "mean_completed_episode_length_steps": 629.2222222222222,
+ "mean_step_reward": 0.01859980582818389,
+ "planar_velocity_rmse_m_per_s": 0.49315400810945587,
+ "unfinished_episodes": 8,
+ "mean_unfinished_episode_return": 5.528181076049805,
+ "student_latent_mse_vs_teacher": null,
+ "student_action_rmse_vs_teacher": null,
+ "terminations": 2,
+ "total_transitions": 8000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "task": "go2_joystick_flat/rma_forward",
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ 0.015685936529645686,
+ -0.007749902041240091,
+ 0.03442901849853064
+ ],
+ "tracking_rmse_by_axis": [
+ 0.4897715884761797,
+ 0.057659923685617856,
+ 0.130251946827097
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.06008052522769907,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 0.7773760445713996,
+ "tracking_ang_vel": 0.1921130729392171,
+ "lin_vel_z": -0.00598462969110642,
+ "ang_vel_xy": -0.015748580647712514,
+ "base_height": -0.02333792574959807,
+ "action_rate": -0.0035400085798974034,
+ "similar_to_default": -0.22660776471346616,
+ "contact": 0.17592749336361885,
+ "swing_feet_z": 0.059792615115642544
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ }
+}
diff --git a/results/rma/forward_v1/seed456.json b/results/rma/forward_v1/seed456.json
new file mode 100644
index 000000000..e2f5101d8
--- /dev/null
+++ b/results/rma/forward_v1/seed456.json
@@ -0,0 +1,62 @@
+{
+ "policy": "teacher",
+ "seed": 456,
+ "completed_episodes": 8,
+ "mean_completed_episode_return": 10.60306566953659,
+ "mean_completed_episode_length_steps": 564.875,
+ "mean_step_reward": 0.01878373809804907,
+ "planar_velocity_rmse_m_per_s": 0.49315459737476025,
+ "unfinished_episodes": 8,
+ "mean_unfinished_episode_return": 8.180676460266113,
+ "student_latent_mse_vs_teacher": null,
+ "student_action_rmse_vs_teacher": null,
+ "terminations": 0,
+ "total_transitions": 8000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "task": "go2_joystick_flat/rma_forward",
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ 0.013729549131713991,
+ -0.005043574669553379,
+ 0.03246544610648264
+ ],
+ "tracking_rmse_by_axis": [
+ 0.49066846115678453,
+ 0.049456221048872574,
+ 0.10843041134148648
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.05812633585727597,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 0.7757972832918167,
+ "tracking_ang_vel": 0.19275773064047097,
+ "lin_vel_z": -0.003971626499741433,
+ "ang_vel_xy": -0.013042655649791414,
+ "base_height": -0.01996231985324994,
+ "action_rate": -0.0032092234268966424,
+ "similar_to_default": -0.2258007121682167,
+ "contact": 0.1770824935734272,
+ "swing_feet_z": 0.059535964109003546
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ }
+}
diff --git a/results/rma/forward_v1/seed789.json b/results/rma/forward_v1/seed789.json
new file mode 100644
index 000000000..38c5e78bb
--- /dev/null
+++ b/results/rma/forward_v1/seed789.json
@@ -0,0 +1,62 @@
+{
+ "policy": "teacher",
+ "seed": 789,
+ "completed_episodes": 8,
+ "mean_completed_episode_return": 11.019422739744186,
+ "mean_completed_episode_length_steps": 589.125,
+ "mean_step_reward": 0.01871223668009043,
+ "planar_velocity_rmse_m_per_s": 0.49402653605180963,
+ "unfinished_episodes": 8,
+ "mean_unfinished_episode_return": 7.692810535430908,
+ "student_latent_mse_vs_teacher": null,
+ "student_action_rmse_vs_teacher": null,
+ "terminations": 0,
+ "total_transitions": 8000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "task": "go2_joystick_flat/rma_forward",
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ 0.012253768285125432,
+ -0.004161755626676729,
+ 0.028055764691391885
+ ],
+ "tracking_rmse_by_axis": [
+ 0.49195942077463545,
+ 0.045145834817094645,
+ 0.0914933536134219
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.04815842404206481,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 0.7709526063203812,
+ "tracking_ang_vel": 0.19463158410787582,
+ "lin_vel_z": -0.0030863634385796105,
+ "ang_vel_xy": -0.013372091561352136,
+ "base_height": -0.01578838027827442,
+ "action_rate": -0.0033247425880035737,
+ "similar_to_default": -0.2310179681405425,
+ "contact": 0.17744999327510597,
+ "swing_feet_z": 0.059167224429547784
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ }
+}
diff --git a/results/rma/forward_v1/training_metrics.csv b/results/rma/forward_v1/training_metrics.csv
new file mode 100644
index 000000000..a374bea88
--- /dev/null
+++ b/results/rma/forward_v1/training_metrics.csv
@@ -0,0 +1,3001 @@
+iteration,total_transitions,wall_seconds,loss,latent_mse,mean_step_reward,completed_episodes,mean_episode_return,mean_episode_length_steps
+1,1536,3.2522542199999975,-0.025882015470415354,,0.014498504810035229,0,,
+2,3072,3.6435674160000247,-0.0328177085146308,,0.016203831881284714,3,0.25823495944496244,29.333333333333332
+3,4608,4.084997976000011,-0.027580543731649716,,0.017774151638150215,0,,
+4,6144,4.496730044000003,-0.027191085120042164,,0.017490658909082413,2,1.7950451342039742,76.0
+5,7680,4.840439076000024,-0.029279989609494805,,0.017255768179893494,2,1.1876684898743406,110.0
+6,9216,5.212554463000004,-0.0278665104880929,,0.017532503232359886,2,1.8876645493437536,142.0
+7,10752,5.649522939000008,-0.03073542487497131,,0.018166881054639816,1,3.4441616372205317,161.0
+8,12288,6.038026889999998,-0.03334922740856806,,0.018084608018398285,2,3.420376234455034,175.5
+9,13824,6.404181952000016,-0.03191496655344963,,0.018718218430876732,1,4.489935368299484,214.0
+10,15360,6.872561998000009,-0.030399676971137525,,0.018926221877336502,4,2.7358372668386437,226.75
+11,16896,7.230633514000004,-0.0321266849214832,,0.018563320860266685,4,4.5671460070007015,249.0
+12,18432,7.583762081000003,-0.02751326112387081,,0.018566768616437912,2,3.076213157561142,274.0
+13,19968,7.917890934000013,-0.03026767512783408,,0.019033964723348618,2,7.454601365432609,301.5
+14,21504,8.369831703000017,-0.029834096770112714,,0.0189520176500082,2,6.085074896458536,320.0
+15,23040,8.805210062000015,-0.028738457631940644,,0.01896834932267666,2,6.483256942941807,351.5
+16,24576,9.226724461000003,-0.030438910564407708,,0.01908291131258011,1,9.242124523036182,369.0
+17,26112,9.592131236,-0.02529847132973373,,0.019695473834872246,0,,
+18,27648,9.972356478000023,-0.02832814649057885,,0.019240880385041237,0,,
+19,29184,10.368942197000024,-0.028499001373226442,,0.020024996250867844,3,8.131867818534374,451.6666666666667
+20,30720,10.728940592000015,-0.029956893095125756,,0.019237719476222992,1,5.548048143275082,474.0
+21,32256,11.080577083999998,-0.02611147950713833,,0.01983330398797989,3,7.380170662150097,496.6666666666667
+22,33792,11.423150726000017,-0.02958536649433275,,0.019951511174440384,0,,
+23,35328,11.744928924000021,-0.030744403429950277,,0.019223367795348167,3,10.817750405753031,544.6666666666666
+24,36864,12.092627800000002,-0.02612942859220008,,0.020390456542372704,4,10.51162948802812,560.25
+25,38400,12.480931107000004,-0.025494240721066794,,0.02004692703485489,1,13.619132720981725,598.0
+26,39936,12.849211773999997,-0.0315705265228947,,0.019632326439023018,0,,
+27,41472,13.232013464000005,-0.02640599029449125,,0.019323553889989853,4,12.837270502524916,636.75
+28,43008,13.577199000999997,-0.028532874397933485,,0.01983479969203472,1,1.1646048659458756,90.0
+29,44544,13.927196951000013,-0.03122281647908191,,0.020153943449258804,0,,
+30,46080,14.290833954000021,-0.02745949619760116,,0.019816648215055466,0,,
+31,47616,14.665303138000013,-0.022686696456124384,,0.019180692732334137,2,7.53703859844245,414.5
+32,49152,15.00856549400001,-0.029654346189151207,,0.01999291405081749,0,,
+33,50688,15.358751059000014,-0.03244308785069734,,0.01959344372153282,1,10.134420030983165,773.0
+34,52224,15.705427079000003,-0.032599925389513375,,0.01977076381444931,2,12.69964810856618,802.5
+35,53760,16.050525671000003,-0.03047234620898962,,0.019848603755235672,2,13.45924243767513,826.5
+36,55296,16.472982797000014,-0.03136301209839682,,0.01995924487709999,1,20.34855109662749,846.0
+37,56832,16.880417667000017,-0.03312521427093695,,0.019924508407711983,1,20.272855379385874,872.0
+38,58368,17.314079966999998,-0.0333625544483463,,0.020115531980991364,3,16.314835826439474,908.3333333333334
+39,59904,17.66603306800002,-0.02875259987389048,,0.02037673257291317,2,16.872258569754194,924.0
+40,61440,18.068428107000017,-0.030750129682322342,,0.01985771209001541,2,19.215568640327547,947.0
+41,62976,18.520340773000015,-0.029627465022106964,,0.02010502479970455,0,,
+42,64512,18.92360258300002,-0.0279771463945508,,0.020187638700008392,0,,
+43,66048,19.355959813,-0.03307891752726088,,0.019929153844714165,2,22.420659915427677,1000.0
+44,67584,19.793447887000013,-0.030174193888281783,,0.02049630880355835,1,23.249864644370973,1000.0
+45,69120,20.211507685000015,-0.03615182009525597,,0.01998692750930786,2,18.62720274325693,1000.0
+46,70656,20.65416997600002,-0.032974894950166346,,0.02042362093925476,0,,
+47,72192,21.044358723000016,-0.029317311057820917,,0.02048589661717415,2,17.893711004056968,1000.0
+48,73728,21.44398346700001,-0.0304014274229606,,0.02042463794350624,2,23.958520652726293,1000.0
+49,75264,21.837136927000017,-0.033240280424555145,,0.01989736407995224,2,18.497712533921003,1000.0
+50,76800,22.225093578000013,-0.03172565899634113,,0.020863309502601624,1,22.847558140056208,1000.0
+51,78336,22.667885695000024,-0.031115632023041448,,0.02053861692547798,3,19.05749732069671,1000.0
+52,79872,23.077338887000025,-0.03354545802188416,,0.020769331604242325,4,17.554391203448176,1000.0
+53,81408,23.503982148000006,-0.028546288485328357,,0.02186167612671852,3,15.415160223298395,1000.0
+54,82944,23.92410860000001,-0.03147919680923224,,0.022066399455070496,1,28.40085370570887,1000.0
+55,84480,24.354338071,-0.030677496052036683,,0.020345058292150497,3,22.505630883815076,1000.0
+56,86016,24.768122333000008,-0.019480936446537575,,0.019824093207716942,3,15.846151731481465,723.0
+57,87552,25.140176656000023,-0.02520006918348372,,0.020147642120718956,3,18.688652349209104,803.0
+58,89088,25.53093619500001,-0.019131180178374053,,0.01967690885066986,2,9.469881461176556,650.5
+59,90624,25.87837060000001,-0.028692012932151557,,0.0184724573045969,4,11.079520298895659,625.25
+60,92160,26.190730236000007,-0.01961037654740115,,0.018320024013519287,2,15.78928597184131,784.5
+61,93696,26.573386712,-0.018087401093604665,,0.01930605247616768,7,13.650167155811298,718.7142857142857
+62,95232,26.93381135300001,-0.022842624317854644,,0.019454609602689743,4,17.414476559701143,914.0
+63,96768,27.278626830999997,-0.020882010599598287,,0.017006149515509605,6,6.607916995339717,414.0
+64,98304,27.65966272900002,-0.02423127684742212,,0.01850956119596958,4,6.606543214613339,381.0
+65,99840,28.02701899500002,-0.027825890171031157,,0.01801762357354164,6,16.331133083168726,702.3333333333334
+66,101376,28.462545896000023,-0.02288786705272893,,0.01874805986881256,5,7.665760504384525,459.0
+67,102912,28.82229473800001,-0.030872748838737606,,0.017494529485702515,2,8.486864365171641,562.5
+68,104448,29.198602824000005,-0.019944796649118263,,0.016664572060108185,5,12.666289860126563,594.8
+69,105984,29.549815745000018,-0.029125802715619407,,0.017388630658388138,4,9.878164662892232,379.5
+70,107520,29.961821211,-0.02760792354432245,,0.018205592408776283,2,2.6864348421804607,163.5
+71,109056,30.357638726000005,-0.032219061239932976,,0.018051233142614365,0,,
+72,110592,30.781063843,-0.032041109865531325,,0.01785503886640072,2,6.825786749483086,466.0
+73,112128,31.16154196400001,-0.028552090881081918,,0.01858949474990368,1,8.170705631840974,503.0
+74,113664,31.528411197999986,-0.03384578075880806,,0.018570784479379654,0,,
+75,115200,31.869968096000008,-0.03257088100848098,,0.01922410912811756,1,13.074383969651535,1000.0
+76,116736,32.23339341900001,-0.030502440982187788,,0.01834879070520401,1,26.035860254312865,1000.0
+77,118272,32.62689023100003,-0.03558524032123387,,0.01836870238184929,0,,
+78,119808,32.94653257400003,-0.029999604875532288,,0.01881636120378971,0,,
+79,121344,33.297629504000014,-0.035308116332938275,,0.019344210624694824,0,,
+80,122880,33.67680500600002,-0.03308827175448338,,0.018903091549873352,1,15.850320303114131,1000.0
+81,124416,34.05323781199999,-0.03097088464225332,,0.018473586067557335,0,,
+82,125952,34.395593252,-0.03081582245261719,,0.019638556987047195,0,,
+83,127488,34.80656553100002,-0.03450494171120226,,0.01950996182858944,0,,
+84,129024,35.12980933000003,-0.032738672383129594,,0.01893245428800583,0,,
+85,130560,35.507097926,-0.033434762091686325,,0.01921948976814747,1,24.71466609183699,1000.0
+86,132096,35.837119822999995,-0.035475062827269234,,0.019602671265602112,0,,
+87,133632,36.147101424,-0.033628877042792736,,0.01855332963168621,0,,
+88,135168,36.49335854300003,-0.02901544994674623,,0.018747571855783463,0,,
+89,136704,36.843290566000036,-0.02997169380541891,,0.019141748547554016,1,12.661105649545789,1000.0
+90,138240,37.191482439,-0.029311929565543928,,0.019273195415735245,0,,
+91,139776,37.53080337200001,-0.03119332854015132,,0.019313398748636246,2,22.404967435111757,1000.0
+92,141312,37.859846540999996,-0.03047881800060471,,0.0186971016228199,0,,
+93,142848,38.20183522100004,-0.03183776607426504,,0.01910259947180748,2,22.231667291373014,1000.0
+94,144384,38.59376079699999,-0.0324632580159232,,0.0193228330463171,3,20.908055047970265,1000.0
+95,145920,38.966063029000026,-0.029910281486809253,,0.01892286352813244,1,14.736179365077987,1000.0
+96,147456,39.29637640600001,-0.0306000128077964,,0.019094951450824738,2,16.05765994801186,1000.0
+97,148992,39.65364839399999,-0.03132363602053374,,0.01920369639992714,1,22.95952385291457,1000.0
+98,150528,40.04875038899999,-0.028821862248393396,,0.01844269596040249,2,14.883640163985547,1000.0
+99,152064,40.41855985999999,-0.03203556602820754,,0.019337352365255356,0,,
+100,153600,40.84488573400003,-0.023521971531833212,,0.019127152860164642,2,16.326056283258367,1000.0
+101,155136,41.24483089899999,-0.029316284942130247,,0.019090553745627403,1,14.682086161570624,1000.0
+102,156672,41.661676067,-0.02916737230649839,,0.01960517093539238,4,17.538388875284,1000.0
+103,158208,41.989989680000036,-0.02559976854051153,,0.019737010821700096,3,22.220322050969116,1000.0
+104,159744,42.32362380600003,-0.029755310520219305,,0.020056867972016335,4,18.050034016981954,1000.0
+105,161280,42.70432635099999,-0.027269652082274356,,0.02019646018743515,5,19.632536544138567,1000.0
+106,162816,43.043936892999994,-0.030436281735698383,,0.020242393016815186,4,16.300831795844715,1000.0
+107,164352,43.39556001899999,-0.02959196277273198,,0.02050222083926201,7,16.470169199638935,1000.0
+108,165888,43.75819582800003,-0.03353021725391348,,0.02002652734518051,1,24.1862611285178,1000.0
+109,167424,44.10339954899999,-0.03130154044677814,,0.020995652303099632,2,23.602093877561856,1000.0
+110,168960,44.493548119999986,-0.025455215418090423,,0.020010579377412796,5,21.444957188353875,1000.0
+111,170496,44.851147311999995,-0.031471576541662216,,0.019746989011764526,4,22.007219604594866,1000.0
+112,172032,45.191148744,-0.03115332800274094,,0.02007073163986206,1,28.005336295813322,1000.0
+113,173568,45.58377858200001,-0.02757519846782088,,0.019568881019949913,0,,
+114,175104,45.91668987,-0.02711739546308915,,0.01988331787288189,3,19.117944889857124,1000.0
+115,176640,46.23735000000002,-0.024039750499650837,,0.019730089232325554,0,,
+116,178176,46.596852797000025,-0.027716660654793182,,0.01915479451417923,1,2.195130279404111,163.0
+117,179712,46.92622916100001,-0.03254872955537091,,0.02000647783279419,2,25.153845233726315,1000.0
+118,181248,47.23500779600002,-0.03200036796430747,,0.019339753314852715,0,,
+119,182784,47.59120814799999,-0.028632242737027507,,0.01940014399588108,0,,
+120,184320,47.959614241000025,-0.023212975488665202,,0.018749983981251717,0,,
+121,185856,48.35240348100004,-0.027890703408047557,,0.018846359103918076,1,5.184735917719081,349.0
+122,187392,48.745932261000036,-0.02890265438084801,,0.019280610606074333,1,16.486819677753374,1000.0
+123,188928,49.06113129100001,-0.029029397216315072,,0.01911855861544609,0,,
+124,190464,49.38280311700001,-0.03026180761711051,,0.019272737205028534,0,,
+125,192000,49.723589454000006,-0.02736079616006464,,0.019196391105651855,0,,
+126,193536,50.03144918800004,-0.030384133484524987,,0.01975592039525509,0,,
+127,195072,50.35443423000001,-0.029633441062954565,,0.019082654267549515,1,12.45873148064129,1000.0
+128,196608,50.744047136000034,-0.02684731745781998,,0.019472038373351097,0,,
+129,198144,51.062395356999986,-0.030245406196142237,,0.019663913175463676,0,,
+130,199680,51.406170124,-0.024763648010169465,,0.01907537132501602,1,13.357465492445044,1000.0
+131,201216,51.79692217700003,-0.019537961537328858,,0.01976119540631771,1,11.868621138157323,484.0
+132,202752,52.167836238000035,-0.02893933137723555,,0.019601572304964066,1,16.954848382156342,1000.0
+133,204288,52.58146202000003,-0.023045343261522553,,0.019535616040229797,1,12.581348427338526,1000.0
+134,205824,52.93449536599999,-0.022338230178381005,,0.01894417405128479,2,16.61303873808356,863.5
+135,207360,53.27542412300002,-0.032917102643599115,,0.019239012151956558,3,18.717900554688338,973.0
+136,208896,53.633576060000024,-0.023584343198065957,,0.018750052899122238,3,17.88539277672923,905.0
+137,210432,54.01710464499999,-0.02260271179645012,,0.018599752336740494,5,15.401984447950962,859.4
+138,211968,54.350364703,-0.02161963014708211,,0.01916826330125332,1,3.2071925412165,144.0
+139,213504,54.745781368000024,-0.02493286122723172,,0.018720312044024467,2,23.914006709645037,965.5
+140,215040,55.12395042599999,-0.03249306418001652,,0.019884299486875534,3,12.065897239294523,911.0
+141,216576,55.50369149000002,-0.024792085704393684,,0.019284529611468315,1,19.88381901977118,1000.0
+142,218112,55.842528076000036,-0.02356282537803054,,0.018750615417957306,1,23.814691384555772,1000.0
+143,219648,56.17380405600002,-0.022983750398270785,,0.018985215574502945,1,11.894796363543719,761.0
+144,221184,56.60558024500003,-0.030271416374792654,,0.018943829461932182,6,24.6151695830049,1000.0
+145,222720,56.95340744400002,-0.025122477727321287,,0.018447697162628174,1,19.099390192423016,1000.0
+146,224256,57.29290329800003,-0.02824924890883267,,0.01823337748646736,5,15.938278964417986,855.6
+147,225792,57.63410339999999,-0.030344422332321604,,0.019570093601942062,3,18.334130694003154,1000.0
+148,227328,57.99978089600003,-0.031121926754713057,,0.019720790907740593,3,22.231990124409396,1000.0
+149,228864,58.34470772300003,-0.03111969956662506,,0.019891034811735153,4,17.821670886012726,1000.0
+150,230400,58.699388669,-0.03409297904775788,,0.01968606375157833,1,22.725562167353928,1000.0
+151,231936,59.03369430699999,-0.0299727474572137,,0.02019418403506279,3,16.874089777624857,1000.0
+152,233472,59.384236265,-0.02884246923495084,,0.0205547995865345,3,21.159509716089815,1000.0
+153,235008,59.724324481000025,-0.034040417366971575,,0.020431432873010635,1,14.265779418405145,1000.0
+154,236544,60.110214098,-0.028560767501282194,,0.020156927406787872,1,28.045839056489058,1000.0
+155,238080,60.46338210400003,-0.030278152405905225,,0.02039063163101673,1,17.446480344515294,1000.0
+156,239616,60.86232744399999,-0.032094665818537274,,0.02086031436920166,2,14.383526892401278,1000.0
+157,241152,61.239244953999986,-0.029273028757112723,,0.020120713859796524,1,14.356290773372166,1000.0
+158,242688,61.626713490000014,-0.029213958039569356,,0.020726971328258514,0,,
+159,244224,62.03612031899999,-0.030965018520752587,,0.02112710289657116,2,17.95953571028076,1000.0
+160,245760,62.459192021999996,-0.03293865152324239,,0.02116493135690689,0,,
+161,247296,62.91675488400003,-0.027494875978057585,,0.02099957875907421,0,,
+162,248832,63.33938052800002,-0.030043975232789913,,0.021404720842838287,1,19.682227275450714,1000.0
+163,250368,63.70930163800003,-0.02844975348950053,,0.021391168236732483,1,13.456407553516328,1000.0
+164,251904,64.030985846,-0.0280323789610217,,0.02134142443537712,0,,
+165,253440,64.40627859100002,-0.026884377437333264,,0.021534781903028488,0,,
+166,254976,64.84242526400001,-0.02818320131627843,,0.021550696343183517,0,,
+167,256512,65.212846122,-0.021128465072251856,,0.021009888499975204,0,,
+168,258048,65.57452402600003,-0.02420233089166383,,0.021687138825654984,1,17.388633033144288,1000.0
+169,259584,65.94048670200002,-0.026835671703641612,,0.021209456026554108,0,,
+170,261120,66.28999112599999,-0.030944299515491974,,0.021686268970370293,0,,
+171,262656,66.68440399099998,-0.028275557797557364,,0.02165321633219719,0,,
+172,264192,67.06556426300003,-0.0270944110234268,,0.021913427859544754,2,25.22596169868484,1000.0
+173,265728,67.40377823000003,-0.028535087344547114,,0.021571915596723557,0,,
+174,267264,67.802105506,-0.02947985736342768,,0.021592285484075546,1,14.871542762732133,1000.0
+175,268800,68.137855928,-0.031149084819480775,,0.021936839446425438,0,,
+176,270336,68.48198280099999,-0.024834037366478393,,0.021813631057739258,3,15.91255980078131,1000.0
+177,271872,68.83902179100002,-0.025914063661669692,,0.022573847323656082,2,22.47814663342433,1000.0
+178,273408,69.16910317900002,-0.023292140565657368,,0.022558152675628662,4,20.38791131504695,1000.0
+179,274944,69.51655012900002,-0.022225004993379115,,0.022835899144411087,3,18.985809153295122,1000.0
+180,276480,69.85398643300002,-0.015083246383195121,,0.02244018018245697,2,12.690565547789447,544.0
+181,278016,70.214425481,-0.02738487026654184,,0.022607050836086273,4,20.762294733023737,1000.0
+182,279552,70.56991189200002,-0.028657849334801238,,0.023658931255340576,1,18.014985226793215,1000.0
+183,281088,70.92306454400003,-0.024075931512440245,,0.022419840097427368,1,18.290231049526483,1000.0
+184,282624,71.255430077,-0.014415049878880381,,0.0230316873639822,2,9.389439662278164,564.5
+185,284160,71.59829379600004,-0.027864980689870814,,0.0230483990162611,2,28.231628684152383,1000.0
+186,285696,71.96747062200004,-0.02644415581986929,,0.023140525445342064,5,16.842914702068082,1000.0
+187,287232,72.31343238299999,-0.029576720444795986,,0.02303304150700569,2,20.83475388190709,1000.0
+188,288768,72.70552219300001,-0.027475654877101383,,0.023541828617453575,5,23.078859692043626,1000.0
+189,290304,73.048447305,-0.032551357619619616,,0.023038368672132492,3,27.4070581527,1000.0
+190,291840,73.41627696200001,-0.030194123240653424,,0.02309255860745907,4,25.128864103811793,1000.0
+191,293376,73.75531701700001,-0.03233979252011825,,0.02277691289782524,3,23.79897132543071,1000.0
+192,294912,74.15116763800003,-0.03146033665786187,,0.02247200906276703,0,,
+193,296448,74.57470697400001,-0.029571962162541845,,0.022383183240890503,4,23.20214743062388,1000.0
+194,297984,75.01235520399999,-0.028236607400079567,,0.022788837552070618,2,15.75709869727143,1000.0
+195,299520,75.38430666400004,-0.02578979336346189,,0.022889351472258568,2,14.559440991142765,1000.0
+196,301056,75.792901925,-0.026967821072321384,,0.023006847128272057,0,,
+197,302592,76.18234682700003,-0.029658432754998406,,0.023145847022533417,2,21.74538846150972,1000.0
+198,304128,76.593469484,-0.026542617621210716,,0.023265890777111053,1,27.30340315401554,1000.0
+199,305664,76.97350606199998,-0.030328414170071483,,0.02327047847211361,1,27.517719814553857,1000.0
+200,307200,77.357935749,-0.02930246878725787,,0.023260455578565598,1,20.633997191675007,1000.0
+201,308736,77.70384707500003,-0.020631104292503248,,0.023196008056402206,1,25.74634758825414,1000.0
+202,310272,78.08682138600003,-0.014067459153011441,,0.0227688979357481,1,21.043590580578893,709.0
+203,311808,78.462505693,-0.02433082164109995,,0.02291174791753292,0,,
+204,313344,78.94530882900003,-0.02853975794860162,,0.022496875375509262,1,24.748743205331266,1000.0
+205,314880,79.48089885200002,-0.022575295165491602,,0.023035338148474693,1,29.595950667746365,1000.0
+206,316416,80.007727658,-0.021809652626203994,,0.02194679155945778,2,6.626813990733353,334.0
+207,317952,80.44896099799999,-0.02123580242235524,,0.021683592349290848,3,13.046617745344216,556.3333333333334
+208,319488,80.79368817400004,-0.016493236964258053,,0.02080148458480835,4,13.067092327983119,567.25
+209,321024,81.194552018,-0.01771004855205926,,0.02176116406917572,0,,
+210,322560,81.534399363,-0.017824134354790053,,0.020342672243714333,4,14.917078874859726,737.25
+211,324096,81.85909011200002,-0.013917245661529402,,0.021037042140960693,1,20.15838119154796,791.0
+212,325632,82.19603047500001,-0.02439011335372925,,0.020865216851234436,1,20.0797896462027,834.0
+213,327168,82.598012496,-0.023630990747672817,,0.020745685324072838,2,22.887458827986848,791.5
+214,328704,82.928519878,-0.0199433272665677,,0.02166346274316311,2,15.597206976264715,937.5
+215,330240,83.30298189300001,-0.02350485067969809,,0.020733531564474106,1,7.585549881099723,268.0
+216,331776,83.69053244,-0.023011815066759787,,0.020242592319846153,2,9.390197229629848,386.5
+217,333312,84.07584476000002,-0.03109710969341298,,0.021578654646873474,0,,
+218,334848,84.49667300500002,-0.027634153398685156,,0.021208863705396652,1,22.2739543071948,1000.0
+219,336384,84.844847337,-0.02881126441061497,,0.021262355148792267,2,29.110327043570578,1000.0
+220,337920,85.27368551800001,-0.024345045109900335,,0.02178889513015747,0,,
+221,339456,85.75191337300001,-0.027396008853490153,,0.021214298903942108,1,26.4884784668684,1000.0
+222,340992,86.21439896300004,-0.022919036090994875,,0.020796021446585655,3,17.528212444585126,1000.0
+223,342528,86.61197485200003,-0.02506786760641262,,0.021072736009955406,2,22.341612830525264,1000.0
+224,344064,86.96902984900001,-0.026637617560724417,,0.02095147594809532,0,,
+225,345600,87.32805147900004,-0.025857106636976823,,0.02117931842803955,0,,
+226,347136,87.68817697,-0.028124228989084562,,0.02176128886640072,2,23.326637876220047,1000.0
+227,348672,88.07205836800003,-0.030241134002183874,,0.02133447490632534,4,21.44679640501272,1000.0
+228,350208,88.52029122000002,-0.024807729634145896,,0.02103962004184723,1,16.767670825589448,1000.0
+229,351744,88.95896875899999,-0.02864787297633787,,0.02151031792163849,2,27.64601449528709,1000.0
+230,353280,89.46582537000003,-0.0269794680022945,,0.020766114816069603,4,21.784899680817034,1000.0
+231,354816,89.91273938500004,-0.027088572022815546,,0.021208470687270164,2,19.40996341512073,1000.0
+232,356352,90.39544683099999,-0.027370863625158868,,0.021526267752051353,5,21.56613508379087,1000.0
+233,357888,90.78392797900003,-0.022132095081421235,,0.021631887182593346,1,18.382313170470297,1000.0
+234,359424,91.14507781900002,-0.025674312352202834,,0.020885374397039413,0,,
+235,360960,91.51833201100001,-0.02722432538866997,,0.021304499357938766,3,20.872160304958623,1000.0
+236,362496,91.90346558600001,-0.026374020466270544,,0.021851342171430588,2,19.143228547705803,1000.0
+237,364032,92.27719338,-0.026562156171227494,,0.021055545657873154,1,29.912868263199925,1000.0
+238,365568,92.63059592100004,-0.029042909160489218,,0.021218037232756615,0,,
+239,367104,92.978874365,-0.028419353114441038,,0.02154974639415741,3,21.585632796981372,1000.0
+240,368640,93.32534982400003,-0.024782676389440893,,0.02101709321141243,0,,
+241,370176,93.73091477,-0.022317665521404705,,0.021447163075208664,1,14.490358232986182,1000.0
+242,371712,94.11997144699998,-0.023793055059892747,,0.02147650346159935,1,14.081336422124878,1000.0
+243,373248,94.53646026600003,-0.024275779935608928,,0.02179829403758049,0,,
+244,374784,94.898189212,-0.026661697231854003,,0.021403849124908447,1,18.82817113865167,1000.0
+245,376320,95.27596279600002,-0.02223334137427931,,0.02211763709783554,0,,
+246,377856,95.61659853400002,-0.026305618804569046,,0.021655669435858727,0,,
+247,379392,95.96242454400002,-0.029903167858719826,,0.021759718656539917,2,18.791643474949524,1000.0
+248,380928,96.40312241400002,-0.023026271119791393,,0.022374629974365234,2,19.541493069613352,1000.0
+249,382464,96.809118305,-0.02644130550324917,,0.02193756401538849,1,17.424278143793344,1000.0
+250,384000,97.21135311399999,-0.02494747640254597,,0.02211916446685791,4,24.811097223806428,1000.0
+251,385536,97.59798174400001,-0.02425493985065259,,0.021759696304798126,0,,
+252,387072,97.9572967,-0.028186834250421573,,0.021717777475714684,4,18.785904393036617,1000.0
+253,388608,98.37934674800002,-0.022493340036210913,,0.02212332747876644,1,22.196730942465365,1000.0
+254,390144,98.78119144799999,-0.02496986250237872,,0.021808264777064323,2,27.483090810943395,1000.0
+255,391680,99.145160575,-0.022952844326694807,,0.021639756858348846,3,27.04701858960713,1000.0
+256,393216,99.495092895,-0.022409765562042595,,0.02154366672039032,0,,
+257,394752,99.87544292800001,-0.012720392008001605,,0.020728424191474915,2,14.30724858737085,530.0
+258,396288,100.34352589200003,-0.025193705906470618,,0.021736999973654747,2,16.07485487370286,1000.0
+259,397824,100.825914084,-0.02495718584395945,,0.021964602172374725,1,29.91877873521298,1000.0
+260,399360,101.23255187100003,-0.029070947637956125,,0.022355135530233383,0,,
+261,400896,101.642988901,-0.019216900086030365,,0.021596616134047508,2,26.215410066070035,1000.0
+262,402432,102.00918308100003,-0.02583340307707355,,0.021494265645742416,1,13.132002266356722,1000.0
+263,403968,102.380983456,-0.02614899454638362,,0.02178976684808731,2,18.107559977506753,1000.0
+264,405504,102.74210903899998,-0.024429214489646255,,0.021565251052379608,2,13.375779699999839,1000.0
+265,407040,103.076022655,-0.025787920125488504,,0.021849479526281357,1,25.432103065773845,1000.0
+266,408576,103.42011810800003,-0.02533052849272887,,0.02175336889922619,0,,
+267,410112,103.75263694100002,-0.02416542188730091,,0.022173559293150902,0,,
+268,411648,104.092767356,-0.025983025110326706,,0.022458946332335472,2,20.577494188793935,1000.0
+269,413184,104.50502019900003,-0.029796746219896402,,0.021973133087158203,5,22.896094832289965,1000.0
+270,414720,104.88632738700002,-0.023505641783898076,,0.02193291485309601,0,,
+271,416256,105.272950183,-0.02286416234758993,,0.02207082509994507,4,20.92029271836509,1000.0
+272,417792,105.70128796000003,-0.0258414251729846,,0.022295407950878143,3,27.215946643147618,1000.0
+273,419328,106.058444272,-0.02647089967310118,,0.021756267175078392,2,19.030524814268574,1000.0
+274,420864,106.52086907100002,-0.025567268118417513,,0.021909844130277634,4,23.941139789647423,1000.0
+275,422400,106.931756127,-0.028328110401829084,,0.021870873868465424,1,20.112682023551315,1000.0
+276,423936,107.385628352,-0.014419361980011066,,0.021176770329475403,2,19.949444759404287,1000.0
+277,425472,107.80865022500004,-0.022712456749286503,,0.021429715678095818,3,13.955270594451576,691.6666666666666
+278,427008,108.267647563,-0.023937792949921762,,0.021904151886701584,1,19.25009670923464,1000.0
+279,428544,108.710032348,-0.026247821313639483,,0.021069956943392754,1,16.196827535168268,1000.0
+280,430080,109.057691759,-0.013545768587694814,,0.021413594484329224,1,19.25787055748515,1000.0
+281,431616,109.454867785,-0.021322665712796153,,0.02171584963798523,2,22.91547128953971,1000.0
+282,433152,109.81804625999999,-0.012574569306646783,,0.020982231944799423,1,25.673384968191385,1000.0
+283,434688,110.169774864,-0.012365633187194665,,0.020706236362457275,2,18.66543018282391,759.5
+284,436224,110.67852039700003,-0.024379148825149362,,0.02135038934648037,1,18.978735852404498,1000.0
+285,437760,111.04904855700002,-0.022403675738799696,,0.021489594131708145,1,28.089820181950927,1000.0
+286,439296,111.55308193800002,-0.011937550858904918,,0.021117646247148514,1,21.021396541735157,830.0
+287,440832,112.07835241300003,-0.01815985606517643,,0.020761873573064804,1,27.914258162956685,944.0
+288,442368,112.58536164099999,-0.021467008853020768,,0.01998995989561081,3,18.547362940463547,839.3333333333334
+289,443904,113.00196983800001,-0.010239550574139382,,0.020299779251217842,3,15.043605678443177,801.0
+290,445440,113.40740944000001,-0.018167980352882297,,0.02048358879983425,2,14.669289746787399,690.5
+291,446976,113.77142097100003,-0.018538047675974667,,0.020886769518256187,2,19.886007808323484,1000.0
+292,448512,114.13726418000002,-0.02948019313820017,,0.02072998695075512,2,19.928811489255168,1000.0
+293,450048,114.552998583,-0.02804335773301621,,0.02001766487956047,3,20.181631648447365,1000.0
+294,451584,114.90516536700002,-0.01884917289329072,,0.020284485071897507,1,17.453887191601098,1000.0
+295,453120,115.27338874300003,-0.0211638182362852,,0.020109638571739197,0,,
+296,454656,115.621059164,-0.02467228164896369,,0.02031633071601391,0,,
+297,456192,115.97911435699999,-0.0218061667556564,,0.02016393467783928,1,29.7922482797876,1000.0
+298,457728,116.373346849,-0.014416352535287539,,0.01985318399965763,2,19.17213713633828,849.5
+299,459264,116.75161859100004,-0.014570787129923702,,0.01953677088022232,3,19.61537269995703,890.3333333333334
+300,460800,117.08372264800002,-0.022754776518559082,,0.02033388987183571,0,,
+301,462336,117.42676021700001,-0.024039024921754994,,0.020212411880493164,1,28.775130244903266,1000.0
+302,463872,117.78245992499998,-0.023193801947248478,,0.020145082846283913,0,,
+303,465408,118.16305725499998,-0.02532155452645384,,0.01965910568833351,2,21.2008696901612,1000.0
+304,466944,118.67937273700002,-0.0212146838932919,,0.02009858749806881,1,17.32789821899496,1000.0
+305,468480,119.12029996200002,-0.026060599802682795,,0.019906647503376007,2,16.62919144972693,1000.0
+306,470016,119.55593154900001,-0.02141315701107184,,0.020183440297842026,2,22.633081948268227,1000.0
+307,471552,119.899376999,-0.02212486759138604,,0.019921600818634033,0,,
+308,473088,120.28640628500003,-0.022850967679793634,,0.020146433264017105,0,,
+309,474624,120.697942213,-0.02084512187478443,,0.020357001572847366,1,25.625916222576052,1000.0
+310,476160,121.057545971,-0.017832755832932888,,0.02024117112159729,2,22.714410494547337,1000.0
+311,477696,121.441538248,-0.02014525664659838,,0.020468290895223618,3,18.58353911677841,1000.0
+312,479232,121.805965278,-0.020852590938253947,,0.020434729754924774,1,18.05297466274351,1000.0
+313,480768,122.17571001400003,-0.02197982374733935,,0.020243115723133087,3,16.3637782734974,1000.0
+314,482304,122.60002377000004,-0.017079748209410658,,0.02062632516026497,3,24.45801863959059,1000.0
+315,483840,122.98161079400003,-0.016947854267588505,,0.02087220549583435,2,22.700633901229594,1000.0
+316,485376,123.392950249,-0.01960120090904335,,0.02015908621251583,2,19.302565657300875,1000.0
+317,486912,123.763251559,-0.020928469529220214,,0.020321769639849663,0,,
+318,488448,124.12385548099999,-0.022192029053500543,,0.020097848027944565,4,16.561906773684314,1000.0
+319,489984,124.50800775100001,-0.02278424579029282,,0.0206641536206007,1,18.074304312933236,1000.0
+320,491520,124.87016736799998,-0.016532748891040682,,0.021106159314513206,2,17.432060117367655,1000.0
+321,493056,125.203087093,-0.01928151804022491,,0.020863106474280357,0,,
+322,494592,125.546454566,-0.01962040993773068,,0.02048425003886223,2,23.429652438499033,1000.0
+323,496128,125.89694888099999,-0.024071060575079174,,0.02047724276781082,1,25.25993577693589,1000.0
+324,497664,126.30907857700001,-0.017651694411567102,,0.02048422396183014,2,21.03769714588998,1000.0
+325,499200,126.712210898,-0.0204640840102608,,0.02041887864470482,1,22.476429876405746,1000.0
+326,500736,127.073787818,-0.019370097767872116,,0.02039000205695629,1,19.159685026854277,1000.0
+327,502272,127.473680094,-0.022110205454130966,,0.02023622766137123,1,20.846783507149667,1000.0
+328,503808,127.840688648,-0.017889941631195446,,0.02049405872821808,1,16.44213089440018,1000.0
+329,505344,128.206723908,-0.021336955743997046,,0.02041575312614441,1,15.755329405888915,1000.0
+330,506880,128.59724706400002,-0.017347283692409596,,0.02064015343785286,3,22.89821154003342,1000.0
+331,508416,128.945634942,-0.017721767358792325,,0.021083440631628036,3,19.024463957563665,1000.0
+332,509952,129.34985919,-0.020486515977730355,,0.020382706075906754,2,19.052154346369207,1000.0
+333,511488,129.77455621,-0.01798951279682418,,0.020442552864551544,4,21.040921285224613,1000.0
+334,513024,130.156517416,-0.021746898566683135,,0.02071722224354744,0,,
+335,514560,130.58959642700003,-0.022551078415320565,,0.020805466920137405,3,19.182242005985852,1000.0
+336,516096,130.947771716,-0.017561402327070635,,0.021290678530931473,1,17.714647865854204,1000.0
+337,517632,131.300199242,-0.019484649505466224,,0.02094852738082409,0,,
+338,519168,131.663475499,-0.014739250834099948,,0.020761869847774506,1,25.615495377220213,1000.0
+339,520704,131.99939600900004,-0.01642265796350936,,0.021007321774959564,0,,
+340,522240,132.38321393100003,-0.017175268994954727,,0.021361013874411583,3,17.126411428907886,1000.0
+341,523776,132.761697952,-0.014968363335356116,,0.021619796752929688,2,26.836353878170485,1000.0
+342,525312,133.109978015,-0.02016927661218991,,0.021234750747680664,0,,
+343,526848,133.46112947600002,-0.017312588969555995,,0.02121102809906006,1,18.355981971137226,1000.0
+344,528384,133.82131557200003,-0.021141336190824707,,0.021310795098543167,2,16.013261132407933,1000.0
+345,529920,134.209038611,-0.015900499753964445,,0.02145853266119957,0,,
+346,531456,134.621790871,-0.017884847319995362,,0.02183203026652336,1,20.47883519716561,1000.0
+347,532992,134.995943671,-0.01508059042195479,,0.021739576011896133,3,23.955072192125954,1000.0
+348,534528,135.33146742200003,-0.015640106323796015,,0.02189001254737377,1,18.06109262444079,1000.0
+349,536064,135.660038932,-0.006308078160509467,,0.021293342113494873,0,,
+350,537600,135.99881726100003,-0.013802763866260647,,0.020840585231781006,2,17.071575463342015,717.0
+351,539136,136.355586413,-0.013838575198315084,,0.02177828550338745,2,16.833830822142772,880.0
+352,540672,136.72373344900004,-0.015458017773926257,,0.021700521931052208,3,23.757085816721276,1000.0
+353,542208,137.05897237500002,-0.014853866072371602,,0.021607637405395508,1,13.364057068363763,1000.0
+354,543744,137.389228326,-0.016303850182642538,,0.021685592830181122,2,23.39951490412932,1000.0
+355,545280,137.771229395,-0.018819558907610674,,0.02212544158101082,3,22.743518454410758,1000.0
+356,546816,138.15276938899999,-0.00795702428246538,,0.02150975912809372,3,24.201356940941576,911.0
+357,548352,138.572584133,-0.018313043160984914,,0.021576732397079468,3,15.595549924997613,1000.0
+358,549888,138.96410452,-0.01647061371865372,,0.02171310782432556,1,15.009671459440142,1000.0
+359,551424,139.33991173400003,-0.01097962591641893,,0.02200223319232464,0,,
+360,552960,139.71982230300003,-0.015345164760947227,,0.022234534844756126,4,20.090912870771717,1000.0
+361,554496,140.09459444300003,-0.016751553242405254,,0.022181645035743713,1,23.748358888551593,1000.0
+362,556032,140.556633736,-0.01262038859228293,,0.02216459810733795,1,23.822097331285477,1000.0
+363,557568,140.928720571,-0.016172732009241977,,0.02166719362139702,0,,
+364,559104,141.34590293200003,-0.014067333370136718,,0.021243903785943985,5,13.701618609915021,752.4
+365,560640,141.710518962,-0.016231257934123278,,0.02156939171254635,0,,
+366,562176,142.066484363,-0.01522733677799503,,0.021544454619288445,4,14.164373553168844,818.5
+367,563712,142.443395913,-0.008810278129143019,,0.022128190845251083,1,21.938540403032675,966.0
+368,565248,142.80353728000003,-0.008527923522827526,,0.02201496809720993,0,,
+369,566784,143.14950426,-0.01611044827538232,,0.0222596637904644,2,9.212709518498741,456.5
+370,568320,143.542361693,-0.01202804750452439,,0.022066377103328705,2,19.366067346767522,1000.0
+371,569856,143.89071793500003,-0.014567190517360966,,0.021782081574201584,2,9.379627135116607,400.0
+372,571392,144.24354158600002,-0.005793883364337186,,0.021799013018608093,5,17.979607933200896,831.4
+373,572928,144.65490414400003,-0.012664675642736257,,0.02215878665447235,3,21.081620087847114,1000.0
+374,574464,144.98428290500001,-0.01408138923967878,,0.022313378751277924,0,,
+375,576000,145.40516642000003,-0.014038543255689243,,0.022670172154903412,4,20.712381080564228,1000.0
+376,577536,145.78254911000002,-0.014791663301487764,,0.022495074197649956,0,,
+377,579072,146.14179742500002,-0.012822932781030734,,0.02197292074561119,3,17.295910778688267,774.3333333333334
+378,580608,146.54988228700003,-0.008651287341490389,,0.022092854604125023,2,17.372900211368687,635.0
+379,582144,146.93673939700003,-0.00851782774552703,,0.022663814947009087,1,11.053420103155077,515.0
+380,583680,147.293178854,-0.014025019342079758,,0.02259794995188713,1,27.836465164087713,1000.0
+381,585216,147.629478439,-0.010842407882834474,,0.02231302484869957,1,23.419949223287404,1000.0
+382,586752,147.965694846,-0.015212413614305358,,0.023005759343504906,2,20.510167743079364,1000.0
+383,588288,148.30211548000003,-0.012164941461135944,,0.022331057116389275,1,30.43571476917714,1000.0
+384,589824,148.66974414300003,-0.014804679714143277,,0.022303259000182152,1,24.553333273157477,1000.0
+385,591360,149.00929915100002,-0.011805239257713158,,0.02197439968585968,0,,
+386,592896,149.36562256800002,-0.017969361195961635,,0.022130824625492096,2,22.623204690229613,1000.0
+387,594432,149.72759139500002,-0.01717133242636919,,0.02220330759882927,1,30.174668176099658,1000.0
+388,595968,150.07611805000002,-0.015216381801292301,,0.022380292415618896,1,27.02164924889803,1000.0
+389,597504,150.477184414,-0.014286093693226577,,0.021956775337457657,2,20.658188242814504,1000.0
+390,599040,150.85092897500002,-0.02177169097897907,,0.021801505237817764,0,,
+391,600576,151.29684163,-0.01685349109272162,,0.02193099819123745,1,25.508057560771704,1000.0
+392,602112,151.71575131800003,-0.008993920156111319,,0.021472660824656487,2,21.01171452831477,1000.0
+393,603648,152.132378166,-0.011511399829760193,,0.02204146608710289,2,11.942867334233597,843.0
+394,605184,152.55825999600003,-0.012618682626634837,,0.022267639636993408,4,23.63014047840261,1000.0
+395,606720,152.901360159,-0.01569861195360621,,0.02214053086936474,0,,
+396,608256,153.247606068,-0.012656564498320222,,0.02251984179019928,2,24.584485380910337,1000.0
+397,609792,153.63787165300002,-0.015353330434300006,,0.022240743041038513,2,18.2794487811625,1000.0
+398,611328,153.98698043100003,-0.010592308888832728,,0.02243361435830593,3,21.023333394899964,1000.0
+399,612864,154.34658130700004,-0.014241646571705738,,0.022472422569990158,1,25.226612476632,1000.0
+400,614400,154.847802384,-0.015371122040475409,,0.02231767401099205,1,30.224228592589498,1000.0
+401,615936,155.331904246,-0.01306476870086044,,0.02247743308544159,2,22.27859262493439,1000.0
+402,617472,155.78281450300003,-0.015630578684310118,,0.022528868168592453,2,19.860003130685072,1000.0
+403,619008,156.19982288600002,-0.005865139064068595,,0.02249073050916195,1,17.35717020824086,1000.0
+404,620544,156.70290780400003,-0.014837797948469717,,0.02223072573542595,0,,
+405,622080,157.136347384,-0.0075495096233983835,,0.02242475561797619,1,15.115478216670454,1000.0
+406,623616,157.57293765900002,-0.008812677642951409,,0.022822294384241104,1,17.04149085190147,1000.0
+407,625152,157.95748604000002,-0.013301451969891787,,0.02253374271094799,1,23.454470071941614,1000.0
+408,626688,158.377614728,-0.013895663130097092,,0.02259022556245327,2,24.062486159964465,1000.0
+409,628224,158.83119090300002,-0.01315293114942809,,0.02299681305885315,0,,
+410,629760,159.224329268,-0.015501416257272164,,0.02284615859389305,2,26.43938916036859,1000.0
+411,631296,159.68567045800003,-0.014166302715117733,,0.022707728669047356,1,17.19402844691649,1000.0
+412,632832,160.112307755,-0.014335857440407078,,0.022862054407596588,1,25.788945690263063,1000.0
+413,634368,160.59046225400002,-0.01328585099739333,,0.022930443286895752,5,19.36623435523361,1000.0
+414,635904,161.03323666000003,-0.016407852216313284,,0.02365514263510704,3,22.404407304207172,1000.0
+415,637440,161.524416215,-0.01570071284659207,,0.023111751303076744,2,25.529437609249726,1000.0
+416,638976,162.04005585299998,-0.012037637930673858,,0.023095622658729553,2,22.17666137870401,1000.0
+417,640512,162.60071689000003,-0.015282709461947283,,0.022915050387382507,2,28.306081126909703,1000.0
+418,642048,163.092903146,-0.01193611619528383,,0.022815674543380737,2,22.099896589992568,1000.0
+419,643584,163.58481085000003,-0.010838307657589514,,0.022831812500953674,2,22.909644667524844,1000.0
+420,645120,163.970468231,-0.01694710728091498,,0.02240174077451229,2,28.48181321658194,1000.0
+421,646656,164.439167277,-0.013498883337403338,,0.022348355501890182,0,,
+422,648192,164.880351106,-0.01555365912305812,,0.022204918786883354,1,25.63651599921286,1000.0
+423,649728,165.32804845300004,-0.01806271846095721,,0.022162435576319695,2,22.39786005660426,1000.0
+424,651264,165.76429712300003,-0.014535827469080687,,0.0220927931368351,2,20.31779477163218,1000.0
+425,652800,166.101024609,-0.016368317774807413,,0.022071722894906998,0,,
+426,654336,166.495934549,-0.01647087118277947,,0.022095097228884697,1,19.742535122670233,1000.0
+427,655872,166.84103287500002,-0.020876633181857566,,0.022198732942342758,0,,
+428,657408,167.18185203,-0.010914760765930016,,0.022197086364030838,2,24.705165739171207,1000.0
+429,658944,167.611581405,-0.013853149876619378,,0.022174522280693054,1,28.654918045271188,1000.0
+430,660480,168.006017226,-0.014675779966637492,,0.02197495475411415,1,17.84246952459216,1000.0
+431,662016,168.369893707,-0.012621433404274286,,0.02188895456492901,2,14.729715851368383,1000.0
+432,663552,168.77413363000002,-0.015566782016927997,,0.021894514560699463,0,,
+433,665088,169.117928518,-0.013845660320172707,,0.0221322700381279,1,21.24468824127689,1000.0
+434,666624,169.476225104,-0.017016880493611098,,0.02207069657742977,3,15.979068722071437,1000.0
+435,668160,169.84868656900002,-0.01775950936911007,,0.022379111498594284,2,28.33093707333319,1000.0
+436,669696,170.242913776,-0.015246482069293658,,0.022089852020144463,3,26.425042456326384,1000.0
+437,671232,170.67593912000004,-0.007494718721136451,,0.02166612073779106,1,26.503411695361137,1000.0
+438,672768,171.026155858,-0.011451094970107078,,0.02145516127347946,3,16.073468163337868,707.3333333333334
+439,674304,171.398671194,-0.009146497258916498,,0.022149309515953064,2,19.89346846943954,1000.0
+440,675840,171.788432605,-0.005078969833751519,,0.021937496960163116,3,24.884670914616436,1000.0
+441,677376,172.14537060900003,-0.016689101637651523,,0.02181432768702507,1,30.174726523226127,1000.0
+442,678912,172.52621713,-0.012600112225239475,,0.021535441279411316,0,,
+443,680448,172.917564043,-0.014984970555330317,,0.02124926447868347,4,22.255695840227418,1000.0
+444,681984,173.25723566500002,-0.015469546848908066,,0.0217716246843338,0,,
+445,683520,173.651618916,-0.011947313044220208,,0.02138584852218628,1,22.090897128684446,1000.0
+446,685056,174.05793579000002,-0.013507787433142463,,0.021446511149406433,0,,
+447,686592,174.47215641200003,-0.006803114013746381,,0.02112678252160549,2,10.271136402443517,546.5
+448,688128,174.88605615500003,-0.013854488792518774,,0.02168823406100273,1,15.014778356999159,1000.0
+449,689664,175.226244234,-0.009125318649845818,,0.02153867296874523,2,23.240281007485464,1000.0
+450,691200,175.57629098000004,-0.011683473813657958,,0.021702704951167107,1,31.386841622181237,1000.0
+451,692736,175.953184758,-0.010463405633345246,,0.02144019864499569,0,,
+452,694272,176.302567536,-0.009884775693838796,,0.021338801831007004,2,23.638392688240856,1000.0
+453,695808,176.686793907,-0.008732402635117372,,0.02193392440676689,1,30.48754425905645,1000.0
+454,697344,177.035386128,-0.012411450874060393,,0.0216897614300251,3,22.909863893291913,1000.0
+455,698880,177.39909238600004,-0.015048133659486969,,0.021498432382941246,3,29.237875703101356,1000.0
+456,700416,177.77204920900002,-0.014709113057081898,,0.02176310122013092,3,18.72058711356173,1000.0
+457,701952,178.13045535199998,-0.01287880439000825,,0.02158108353614807,2,24.31462622259278,1000.0
+458,703488,178.49503384100004,-0.007726991378391782,,0.021437719464302063,4,20.538099136203527,1000.0
+459,705024,178.868647418,-0.010426337520281473,,0.02128767967224121,0,,
+460,706560,179.229747081,-0.008889883042623599,,0.0209832601249218,3,13.583038656312661,709.3333333333334
+461,708096,179.593618421,-0.005873149679973722,,0.021460479125380516,2,19.03754422510974,1000.0
+462,709632,179.944393125,-0.010331629247715076,,0.02124476432800293,2,18.3552726325579,1000.0
+463,711168,180.26984550300003,-0.00798524459823966,,0.021041756495833397,1,14.798983583692461,1000.0
+464,712704,180.63621036499998,-0.0010598807130008936,,0.021570708602666855,1,10.458721564733423,456.0
+465,714240,180.96385570600003,-0.009333500545471907,,0.02169935405254364,3,19.573887319110025,1000.0
+466,715776,181.295203643,-0.007955789015007516,,0.021596726030111313,1,18.68555470276624,1000.0
+467,717312,181.642973672,-0.016566829352329174,,0.021871134638786316,1,19.295945318881422,740.0
+468,718848,181.97003982600003,-0.009570892970077693,,0.02207961305975914,1,19.665015680948272,1000.0
+469,720384,182.30752607500003,-0.00939507398288697,,0.021898865699768066,2,20.580610182369128,1000.0
+470,721920,182.69901621300002,-0.012324071528079608,,0.021616030484437943,0,,
+471,723456,183.04556528600003,-0.012139246379956604,,0.02203555405139923,1,16.37994360551238,1000.0
+472,724992,183.38243786300004,-0.014129764803995689,,0.02178649604320526,2,15.453419406549074,1000.0
+473,726528,183.72207682799998,-0.013151344905296961,,0.022184288129210472,1,17.980832734610885,1000.0
+474,728064,184.05976606800002,-0.011489918750400344,,0.02177269756793976,0,,
+475,729600,184.443055047,-0.014322439425935347,,0.02187667414546013,1,20.968067033565603,1000.0
+476,731136,184.882390554,-0.016519230130749445,,0.022186964750289917,3,20.729512317435972,1000.0
+477,732672,185.27590526500003,-0.01242182154674083,,0.02218843251466751,2,20.316897461249027,1000.0
+478,734208,185.67414175500002,-0.0032186796423047783,,0.02231406234204769,1,19.919521542615257,1000.0
+479,735744,186.017339014,-0.015817135587955514,,0.02208971232175827,1,31.134997493587434,1000.0
+480,737280,186.40685539400002,-0.009975236242947478,,0.02164377085864544,4,27.153979331371374,1000.0
+481,738816,186.801484252,-0.005020296682293216,,0.021565984934568405,3,17.415035992336925,731.0
+482,740352,187.140984884,-0.009537480259314179,,0.021697383373975754,2,14.35067812568741,1000.0
+483,741888,187.46438410700003,-0.010603925834099451,,0.02112346887588501,2,15.71938659134321,831.5
+484,743424,187.81218040500002,-0.006093632150441408,,0.021648546680808067,1,2.052950284909457,92.0
+485,744960,188.23666169700002,-0.007693804466786484,,0.022052224725484848,3,20.162565010522183,1000.0
+486,746496,188.62955561200002,-0.012096195140232642,,0.022220617160201073,0,,
+487,748032,188.97140822600002,-0.011043565394356848,,0.021869808435440063,0,,
+488,749568,189.338004338,-0.009503832552582026,,0.02193807065486908,0,,
+489,751104,189.69263640700004,-0.012132602169488867,,0.021789049729704857,3,21.457485548220575,1000.0
+490,752640,190.016567719,-0.012393868699048956,,0.02216344140470028,0,,
+491,754176,190.354045669,-0.011170916825843353,,0.021785786375403404,3,24.516616611275822,1000.0
+492,755712,190.711369265,-0.012794411710153024,,0.02133171260356903,0,,
+493,757248,191.01914078900003,-0.010743078744659821,,0.021473944187164307,0,,
+494,758784,191.357371595,-0.010801665686691801,,0.021296877413988113,2,25.60053292149678,1000.0
+495,760320,191.72528378,-0.015833875630050898,,0.02142486535012722,2,25.491485277190804,1000.0
+496,761856,192.044661499,-0.01124379625543952,,0.021820491179823875,1,19.49982523266226,1000.0
+497,763392,192.43520865500003,-0.016717852155367533,,0.021839763969182968,4,22.426150106737623,1000.0
+498,764928,192.848300497,-0.010025707438277702,,0.021802416071295738,3,23.933958315484535,1000.0
+499,766464,193.164235127,-0.010009788411358992,,0.021568212658166885,0,,
+500,768000,193.511846824,-0.013989065525432427,,0.02232501469552517,4,16.634294304356445,1000.0
+501,769536,193.846359901,-0.007173852032671372,,0.022499054670333862,1,30.73871856369078,1000.0
+502,771072,194.169696335,-0.010034457019840678,,0.02295723184943199,3,17.123254191751283,1000.0
+503,772608,194.55866245299998,-0.008881939512987932,,0.02299315109848976,2,22.284805067116395,1000.0
+504,774144,194.90007824900002,-0.01481356507477661,,0.02286519668996334,1,22.42322354670614,1000.0
+505,775680,195.26037609099998,-0.00901481934512655,,0.022529829293489456,2,27.76231526141055,1000.0
+506,777216,195.659231989,-0.0062394345800081885,,0.02213294804096222,3,9.417310903818967,409.3333333333333
+507,778752,196.036882061,-0.013923719649513562,,0.022962113842368126,2,23.068418279173784,1000.0
+508,780288,196.46249828199998,-0.01577752814628184,,0.02256844751536846,2,24.747040930727962,1000.0
+509,781824,196.86312108,-0.009965672080094615,,0.022673478350043297,1,29.742859344929457,1000.0
+510,783360,197.275625045,-0.003063459834083915,,0.022631458938121796,0,,
+511,784896,197.64866245200002,-0.01277347548554341,,0.02260325849056244,2,17.817347258212976,1000.0
+512,786432,198.00097892800002,-0.00820303230235974,,0.02251284383237362,1,15.620432587340474,1000.0
+513,787968,198.327035812,-0.007572738127782941,,0.02269301377236843,1,20.891169383656234,1000.0
+514,789504,198.74412671299999,-0.009182559334052105,,0.022687092423439026,1,16.079101588577032,1000.0
+515,791040,199.08549360600003,-0.006089392475162944,,0.02273714914917946,0,,
+516,792576,199.42421497,-0.013896259432658552,,0.022806316614151,0,,
+517,794112,199.81597713300002,-0.012090714213748773,,0.022585958242416382,2,21.730854191700928,1000.0
+518,795648,200.15420198,-0.014470569556578994,,0.022990841418504715,2,21.704332568100654,1000.0
+519,797184,200.57811382600002,-0.011369095571960012,,0.022731661796569824,3,20.58300265731911,1000.0
+520,798720,200.92227958200002,-0.011534283434351285,,0.023005029186606407,0,,
+521,800256,201.25457054300003,-0.005465693182001511,,0.023195158690214157,2,19.16983094671741,1000.0
+522,801792,201.579057238,-0.0038040784808496633,,0.02319975756108761,3,24.4978739603733,1000.0
+523,803328,201.905810925,-0.011253402646010121,,0.022949811071157455,3,18.735277674238507,1000.0
+524,804864,202.224381969,-0.011077688486936191,,0.02318989299237728,2,20.252711835259106,1000.0
+525,806400,202.591860174,-0.012348892508695523,,0.023273121565580368,2,20.766750879585743,1000.0
+526,807936,202.926472431,-0.014357539732009173,,0.023579567670822144,2,27.933736364822835,1000.0
+527,809472,203.253893481,-0.014109882013872265,,0.02342795953154564,1,26.653127873316407,1000.0
+528,811008,203.583003881,-0.007314883110423883,,0.023603376001119614,0,,
+529,812544,203.90085025300002,-0.01046603643335402,,0.023482201620936394,0,,
+530,814080,204.229157511,-0.007878813209633033,,0.02371358498930931,1,22.54113459191285,1000.0
+531,815616,204.616395089,-0.006769985690092047,,0.023635923862457275,2,20.955068942217622,1000.0
+532,817152,204.992290171,-0.004869656745965282,,0.023685656487941742,1,14.290206321049482,1000.0
+533,818688,205.32784425000003,-0.008824376272968948,,0.024075031280517578,2,17.255883299047127,1000.0
+534,820224,205.68831599,-0.006862160656601191,,0.02413167431950569,0,,
+535,821760,206.021927982,-0.009378665452823043,,0.023934781551361084,2,24.67673666338669,1000.0
+536,823296,206.409916031,-0.011571113299578429,,0.02391679584980011,1,29.985964524094015,1000.0
+537,824832,206.84754305600003,-0.01228684118638436,,0.023559410125017166,1,30.73312694579363,1000.0
+538,826368,207.23414321700002,-0.008828897479300697,,0.023375947028398514,3,21.010886028564226,1000.0
+539,827904,207.58399767300003,-0.010316696343943476,,0.023439541459083557,3,21.75942273705732,1000.0
+540,829440,207.90419709700004,-0.009878146943325799,,0.02347629889845848,2,23.659905890119262,1000.0
+541,830976,208.234942227,-0.009010848418499032,,0.023645441979169846,1,26.072627884335816,1000.0
+542,832512,208.62344403300003,-0.009996947521964708,,0.023213963955640793,2,27.823707848787308,1000.0
+543,834048,208.98954594800003,-0.010438356501981615,,0.023250706493854523,3,27.775115029886365,1000.0
+544,835584,209.306772182,-0.01626868904568255,,0.022937171161174774,1,24.951795160770416,1000.0
+545,837120,209.669191311,-0.0018361364180843034,,0.02323349379003048,2,28.505302367790136,1000.0
+546,838656,210.001278235,-0.013448198962335785,,0.022968217730522156,0,,
+547,840192,210.35708117,-0.008750340373565754,,0.0228543933480978,3,25.990705930938322,1000.0
+548,841728,210.79719852500003,-0.006930372569089135,,0.022962063550949097,3,23.844043800801348,1000.0
+549,843264,211.145958224,-0.009430165992428859,,0.023255180567502975,2,26.174149069032865,1000.0
+550,844800,211.485528694,-0.011488788233449062,,0.023208221420645714,1,14.732836473733187,1000.0
+551,846336,211.82128381100003,-0.010237569579233725,,0.02300398051738739,1,20.234142696484923,1000.0
+552,847872,212.14521654300003,-0.008948577381670476,,0.0230599045753479,0,,
+553,849408,212.49906174000003,-0.009383902155483763,,0.023004313930869102,2,19.724447811953723,1000.0
+554,850944,212.935882314,-0.0082088361804684,,0.02351699396967888,1,28.91481783753261,1000.0
+555,852480,213.29716658499999,-0.0025681469899912677,,0.022753437981009483,2,20.167246312310454,933.0
+556,854016,213.629188294,-0.008658256381750107,,0.023334939032793045,1,13.66291964519769,1000.0
+557,855552,213.953869953,-0.005171544539431731,,0.022492168471217155,1,26.300938311964273,955.0
+558,857088,214.26265566700002,-0.007716701893756787,,0.022780533879995346,0,,
+559,858624,214.61804075,-0.0011859771485129992,,0.02221342921257019,3,17.41001421007483,763.3333333333334
+560,860160,214.97079878000002,-0.0036226955242455007,,0.021290384232997894,4,21.400607365940232,914.5
+561,861696,215.305532112,-0.008140409520516792,,0.02221044711768627,1,23.18998666200787,1000.0
+562,863232,215.666713349,-0.0017375257797539235,,0.02158091962337494,2,19.3748105802224,653.5
+563,864768,215.99402966,0.0032632109398643178,,0.0206968542188406,4,18.05002052350028,862.5
+564,866304,216.332643923,-0.008677226646492878,,0.02102816477417946,4,18.866046518611256,778.25
+565,867840,216.723098368,-0.0028193725583453974,,0.02109665796160698,3,19.075815578456968,1000.0
+566,869376,217.135516389,-0.0099382765746365,,0.02052878960967064,3,19.132679100109574,740.3333333333334
+567,870912,217.51589759100003,-0.006765972993647059,,0.021029260009527206,1,26.136738760396838,1000.0
+568,872448,217.89325507000004,-0.01061375228067239,,0.020745709538459778,1,13.92591614741832,1000.0
+569,873984,218.240116647,-0.007932937983423472,,0.02061900869011879,0,,
+570,875520,218.58660075100002,-0.0030929909863819677,,0.02055608108639717,1,23.389327575452626,790.0
+571,877056,218.921086015,-0.001841844990849495,,0.020822446793317795,0,,
+572,878592,219.26390041100004,-0.0098281293331335,,0.01908610761165619,3,20.83860565760794,898.6666666666666
+573,880128,219.61724661500003,-0.005866179925700029,,0.019960295408964157,3,14.067742074180083,737.3333333333334
+574,881664,220.00139352800002,-0.009761778792987267,,0.020238911733031273,3,25.30966763815377,953.3333333333334
+575,883200,220.34449063899999,-0.00931305562456449,,0.02051725797355175,1,29.244641764089465,1000.0
+576,884736,220.69926789500002,-0.0032944461485991876,,0.019597383216023445,1,7.635476131923497,499.0
+577,886272,221.03092370200002,-0.011409102799370885,,0.01959490031003952,3,18.85233397009627,970.3333333333334
+578,887808,221.44769225000002,-0.006083997835715612,,0.020189382135868073,2,17.322909218928544,798.0
+579,889344,221.849766576,-0.013420595709855357,,0.02066698856651783,1,16.377298870240338,1000.0
+580,890880,222.19305617,-0.010406060315047701,,0.02040458470582962,1,14.98164602171164,1000.0
+581,892416,222.55119159400002,-0.010849679276968041,,0.02032969892024994,1,28.579327140934765,1000.0
+582,893952,222.88717776000001,-0.0066881791843722265,,0.02067251317203045,1,17.74380491580814,1000.0
+583,895488,223.20161885400003,-0.005038441174353162,,0.02102707326412201,2,19.064343534526415,1000.0
+584,897024,223.526721514,-0.007429425573597352,,0.020861556753516197,0,,
+585,898560,223.84381460200004,-0.01124289520084858,,0.020952655002474785,2,20.764984311477747,1000.0
+586,900096,224.161129751,-0.00872649746015668,,0.020817534998059273,1,23.767870903015137,1000.0
+587,901632,224.50735421700003,-0.010453917256866892,,0.0209212563931942,2,24.41363137040753,1000.0
+588,903168,224.847887838,-0.011109254540254672,,0.02092706970870495,0,,
+589,904704,225.176606448,-0.011853871246178945,,0.020539037883281708,1,30.400031302589923,1000.0
+590,906240,225.53136945000003,-0.012734349506596724,,0.020895084366202354,3,26.46703144609152,1000.0
+591,907776,225.86384249900001,-0.004499144479632377,,0.02112627774477005,0,,
+592,909312,226.18921537399999,-0.004228258489941557,,0.02075554057955742,1,14.223113407730125,1000.0
+593,910848,226.527464139,-0.0077104295293490095,,0.021166067570447922,1,14.314054035581648,1000.0
+594,912384,226.88997932000004,-0.007877902686595916,,0.02106320858001709,1,23.254317340208218,1000.0
+595,913920,227.28098054400002,-0.0028373980584243935,,0.02068391814827919,1,-0.10455032112076879,67.0
+596,915456,227.655553234,-0.006805444446702798,,0.021261749789118767,1,17.620247423648834,1000.0
+597,916992,228.03536106600004,-0.012147209669152895,,0.02142690122127533,2,20.076763906050473,1000.0
+598,918528,228.388423378,-0.008040111294637125,,0.02158825658261776,0,,
+599,920064,228.762656164,-0.004680429243793091,,0.02190261147916317,1,21.9524802218657,1000.0
+600,921600,229.08684697200002,-0.008224476501345635,,0.02197461575269699,1,13.386176097672433,1000.0
+601,923136,229.44577837700004,-0.009671677369624376,,0.021694734692573547,2,20.80116323166294,1000.0
+602,924672,229.80053387400002,-0.008527683559805155,,0.021970637142658234,4,17.590241834812332,1000.0
+603,926208,230.108388522,-0.009288399076710144,,0.022059103474020958,0,,
+604,927744,230.45322635200003,-0.0072188313739995165,,0.021518774330615997,2,26.69509197305888,1000.0
+605,929280,230.82820256099998,-0.009098818525671959,,0.022388745099306107,6,18.255858638420857,1000.0
+606,930816,231.157696313,-0.010684480471536518,,0.022251127287745476,3,18.898621093598194,1000.0
+607,932352,231.500211135,-0.002477787621319294,,0.02183542773127556,3,23.478790048412822,945.0
+608,933888,231.89201316400002,-0.006206791133930286,,0.022261053323745728,3,18.934559385951918,1000.0
+609,935424,232.21596173999998,-0.008185550477355719,,0.021742170676589012,1,16.17693645542022,1000.0
+610,936960,232.58171298300002,-0.0058593355429669225,,0.02144639752805233,1,16.205692396266386,1000.0
+611,938496,232.92613749800003,-0.008733896538615227,,0.02141617238521576,0,,
+612,940032,233.25261098900003,-0.0018953419756144285,,0.02146609127521515,2,16.785590309475083,683.0
+613,941568,233.602929777,-0.0072381799574941395,,0.021241702139377594,0,,
+614,943104,233.961517537,-0.009320744375387827,,0.020933788269758224,5,19.460816439823247,1000.0
+615,944640,234.302982168,0.0029300129351516563,,0.02109828218817711,1,28.00726506509818,994.0
+616,946176,234.682196953,-0.013159071157375971,,0.020441336557269096,4,18.3385645205708,797.75
+617,947712,235.030016325,-0.0040763379695514836,,0.020848115906119347,2,19.494742528535426,753.5
+618,949248,235.38657256900004,-0.010131447079281012,,0.02051747404038906,2,17.22419064171845,727.5
+619,950784,235.778965124,-0.006212512062241634,,0.02029946818947792,6,16.319737031240948,845.6666666666666
+620,952320,236.087778273,-0.01130727439497908,,0.02111273817718029,1,30.51458350138273,1000.0
+621,953856,236.455790978,-0.0015371773857623338,,0.020535700023174286,3,16.936178157300066,732.3333333333334
+622,955392,236.831801857,-0.0043263564041505255,,0.02061058208346367,1,16.43316462263465,1000.0
+623,956928,237.16326555999999,-0.009924630029127001,,0.02065279334783554,1,10.579672969295643,430.0
+624,958464,237.65239673800002,-0.009029438672587275,,0.020685039460659027,0,,
+625,960000,238.05881505,0.000430360979711016,,0.020409997552633286,3,16.832998276067276,816.6666666666666
+626,961536,238.438919029,-0.0036645548573384684,,0.019332382827997208,2,16.047220191103406,642.5
+627,963072,238.860181306,-0.006731746330236395,,0.019416090101003647,3,19.994699173839763,839.6666666666666
+628,964608,239.217804299,-0.009539784320319692,,0.019818181172013283,1,20.160322843352333,979.0
+629,966144,239.58853690499998,-0.006249373514826099,,0.019419915974140167,2,11.107088317978196,654.5
+630,967680,239.94578160400002,-0.002857765353595217,,0.0187637098133564,2,12.01577672251733,644.5
+631,969216,240.274028378,-0.005525123576323191,,0.019472500309348106,0,,
+632,970752,240.64905868000002,-0.014298545320828755,,0.019611336290836334,3,19.551850456298173,807.0
+633,972288,241.01690504,0.00044736219570040703,,0.01974405162036419,2,16.298152821022086,877.5
+634,973824,241.34597021300002,-0.002532382340480884,,0.01962183229625225,1,15.132069343118928,801.0
+635,975360,241.71093956400003,-0.006538088045393427,,0.019804572686553,0,,
+636,976896,242.079757555,-0.002727333502843976,,0.019667794927954674,1,25.751242340542376,1000.0
+637,978432,242.39108002500004,-0.010603215188408892,,0.019485605880618095,2,21.752215385669842,1000.0
+638,979968,242.847109486,-0.010522205910334984,,0.019470609724521637,1,13.395251060370356,519.0
+639,981504,243.194749158,-0.005904153920710087,,0.0198768712580204,2,12.98683116515167,751.0
+640,983040,243.52544581000004,-0.010337370571990807,,0.020159875974059105,0,,
+641,984576,243.851198693,-0.00803830816100041,,0.02047705464065075,0,,
+642,986112,244.18350662600002,-0.006752977178742488,,0.020198293030261993,1,23.541486752219498,1000.0
+643,987648,244.509708506,-0.008685737786193689,,0.020496558398008347,1,21.69985924672801,1000.0
+644,989184,244.87903989000003,-0.005219532875344157,,0.020780231803655624,2,23.23758698545862,1000.0
+645,990720,245.198216821,-0.005712929864724477,,0.02070309780538082,0,,
+646,992256,245.53102927,-0.003705295609931151,,0.02049192599952221,2,25.675379732623696,1000.0
+647,993792,245.935696955,-0.0005652343543867271,,0.020488232374191284,3,15.86650360977122,1000.0
+648,995328,246.277630984,-0.0069729438206801815,,0.020717047154903412,2,19.10419447417371,1000.0
+649,996864,246.655985178,-0.008045568503439427,,0.020621974021196365,4,17.817841863958165,1000.0
+650,998400,246.98939114100003,-0.005760237171004216,,0.02092062309384346,1,14.698457549093291,1000.0
+651,999936,247.31269214099999,-0.002165361571436127,,0.021265601739287376,0,,
+652,1001472,247.641360714,-0.008348656306043267,,0.021637164056301117,1,17.751024435972795,1000.0
+653,1003008,247.960896109,-0.0062486174671600265,,0.021205363795161247,0,,
+654,1004544,248.291934106,-0.006102895348643263,,0.021414272487163544,1,15.891377152875066,1000.0
+655,1006080,248.727424883,-0.0009867825234929721,,0.02104606106877327,1,25.8144468665123,1000.0
+656,1007616,249.11745742000002,-0.006552215075741211,,0.020374123007059097,3,20.68768681655638,974.0
+657,1009152,249.50948472400003,-0.009530962227533262,,0.020868714898824692,3,16.61328442953527,1000.0
+658,1010688,249.889600124,-0.010659240527699392,,0.021358557045459747,2,25.283770794572774,1000.0
+659,1012224,250.23731367400003,-0.00870685038777689,,0.020753275603055954,0,,
+660,1013760,250.62862893000002,-0.011917345179244875,,0.020810987800359726,3,18.90071203307404,1000.0
+661,1015296,251.03790781300003,-0.0033921535902967054,,0.02072221226990223,4,21.442421495565213,1000.0
+662,1016832,251.371166208,-0.010800433872888485,,0.02121884934604168,1,14.204773782927077,579.0
+663,1018368,251.77437207800003,-0.009678279003128409,,0.02135053090751171,4,17.368637787702028,1000.0
+664,1019904,252.109104229,-0.006593383258829514,,0.021788645535707474,1,20.339321893407032,1000.0
+665,1021440,252.44475826600004,-0.0012111203434566657,,0.021737094968557358,0,,
+666,1022976,252.824170695,-0.000328405387699604,,0.021557718515396118,1,14.737456699134782,1000.0
+667,1024512,253.16752422,-0.009526247205212713,,0.02185356616973877,2,15.237314643105492,1000.0
+668,1026048,253.631643211,-0.002966289253284534,,0.02201453596353531,4,20.7411181894131,1000.0
+669,1027584,254.028413176,-0.011571057140827179,,0.021588828414678574,2,24.803036702272948,1000.0
+670,1029120,254.404165183,-0.007379655788342158,,0.02222738228738308,1,15.184404037543572,1000.0
+671,1030656,254.84599295,-0.011707431357353925,,0.022016985341906548,1,15.814521007239819,1000.0
+672,1032192,255.20325172200003,-0.0034000793161491553,,0.021922659128904343,2,23.4442893556552,1000.0
+673,1033728,255.627390507,0.00023597949184477328,,0.021863525733351707,2,17.133991256006993,1000.0
+674,1035264,255.97641178199999,-0.0034669826583315928,,0.021620703861117363,2,20.376917957677506,766.0
+675,1036800,256.54075681999996,-0.006103924413522085,,0.02205314114689827,2,19.702239417936653,1000.0
+676,1038336,257.010572947,-0.006761465625216564,,0.02231903374195099,1,22.291333608329296,1000.0
+677,1039872,257.40037204199996,-0.004545558259511987,,0.022576769813895226,0,,
+678,1041408,257.763402552,-0.006540283684929212,,0.02240951918065548,1,28.34286127705127,1000.0
+679,1042944,258.100408197,-0.004536339299132427,,0.022225214168429375,2,24.246790362871252,1000.0
+680,1044480,258.450055337,-0.009755018819123506,,0.022430798038840294,1,19.191341166384518,1000.0
+681,1046016,258.83271951100005,-0.00883461213670671,,0.022287290543317795,1,27.89817936439067,1000.0
+682,1047552,259.17255129800003,-0.0033958835216859975,,0.022121643647551537,1,24.65230003290344,924.0
+683,1049088,259.529574864,-0.006035973581795891,,0.022338639944791794,0,,
+684,1050624,259.94783907400006,-0.010034743944803875,,0.02205335907638073,1,20.92137905396521,1000.0
+685,1052160,260.335815688,-0.011066961366062363,,0.02239198610186577,2,22.971639573283028,1000.0
+686,1053696,260.74917500000004,-0.003735006848971049,,0.022503232583403587,0,,
+687,1055232,261.079297933,-0.004911245002100865,,0.022152787074446678,1,21.795339236035943,1000.0
+688,1056768,261.41607090800005,-0.010361427379151186,,0.022156238555908203,1,16.213601590599865,1000.0
+689,1058304,261.79957493300003,-0.007652638417979082,,0.022319771349430084,3,18.026552465899538,1000.0
+690,1059840,262.155090504,-0.01140738041140139,,0.02285701595246792,3,23.76919060324629,1000.0
+691,1061376,262.55785192999997,-0.006949168645466367,,0.022506799548864365,3,24.774585614834603,1000.0
+692,1062912,262.93981568900006,-0.0033670283233126004,,0.02257440611720085,1,24.445134157314897,1000.0
+693,1064448,263.275672517,-0.003261634629840652,,0.021955545991659164,1,21.393742295564152,756.0
+694,1065984,263.62668207800004,-0.00802093418315053,,0.02247581258416176,0,,
+695,1067520,263.97370317499997,-0.004203634026149909,,0.02213769406080246,1,19.649656050256453,1000.0
+696,1069056,264.29202002299996,-0.0015291894475619,,0.021932831034064293,0,,
+697,1070592,264.702031024,-0.0073815922873715556,,0.02175135910511017,2,22.746444635442458,1000.0
+698,1072128,265.078025499,-0.0055235624002913635,,0.02249017171561718,2,18.879089990106877,1000.0
+699,1073664,265.43130979399996,-0.01258271507297953,,0.022363781929016113,3,22.627646846541513,1000.0
+700,1075200,265.78909702400006,0.0007272637138764064,,0.022027701139450073,2,18.22764637094224,1000.0
+701,1076736,266.113956199,-0.0063517052059372265,,0.022404475137591362,1,8.714581339736469,369.0
+702,1078272,266.444199098,-0.0025842970547576747,,0.02139183133840561,5,22.557610742887483,971.8
+703,1079808,266.85512955900003,-0.011591526167467236,,0.021669261157512665,4,22.822207549746963,983.5
+704,1081344,267.17044456400004,-0.013590201161180933,,0.02223089337348938,1,21.350615513511002,1000.0
+705,1082880,267.51525466400005,-0.010965456285824378,,0.02200397104024887,3,20.977438073139638,1000.0
+706,1084416,267.847095027,-0.009902659570798278,,0.02226589247584343,0,,
+707,1085952,268.164350175,-0.0035049673169851303,,0.022312870249152184,0,,
+708,1087488,268.47729550200006,-0.009286141643921534,,0.022268064320087433,2,17.742773447185755,1000.0
+709,1089024,268.858200625,-0.0063995071686804295,,0.02271082065999508,1,16.860878526233137,1000.0
+710,1090560,269.17191613,-0.007288263024141391,,0.022553756833076477,3,21.864379490415256,1000.0
+711,1092096,269.496942192,-0.004836036264896393,,0.022616080939769745,2,26.524529203481507,1000.0
+712,1093632,269.824252968,-0.01196896769106388,,0.022607726976275444,1,27.526609398424625,1000.0
+713,1095168,270.14452500799996,-0.010551017615944147,,0.022464830428361893,1,18.88682820368558,1000.0
+714,1096704,270.480974438,-0.007378654306133588,,0.02287166938185692,2,16.83144730317872,1000.0
+715,1098240,270.95103038800005,-0.005153098019460837,,0.022674521431326866,3,23.16194686968811,1000.0
+716,1099776,271.325414983,-0.00912646531748275,,0.02261440083384514,1,26.06473327986896,1000.0
+717,1101312,271.724461303,-0.01088834290082256,,0.022408267483115196,3,23.9687746426013,1000.0
+718,1102848,272.06513036399997,-0.01229376409513255,,0.02234870195388794,0,,
+719,1104384,272.401745389,-0.009813669696450233,,0.022601578384637833,1,30.78368166834116,1000.0
+720,1105920,272.78281885,-0.013048505534728368,,0.022414814680814743,1,23.611567029962316,1000.0
+721,1107456,273.14453903699996,-0.009763711644336582,,0.022428449243307114,1,14.708144591189921,1000.0
+722,1108992,273.473426121,-0.004437514953315258,,0.022377729415893555,2,21.58020614273846,1000.0
+723,1110528,273.80225249,-0.009133718224863212,,0.022329997271299362,0,,
+724,1112064,274.14866845200004,-0.0002669221566369136,,0.022225212305784225,1,24.26125851087272,1000.0
+725,1113600,274.514177182,-0.006819236061225335,,0.022134199738502502,1,17.021822047652677,1000.0
+726,1115136,274.921431191,-0.00676103268439571,,0.02231842838227749,1,30.80601403862238,1000.0
+727,1116672,275.306557475,-0.010500369934986035,,0.02237023413181305,0,,
+728,1118208,275.65611648699996,0.0014395595528185368,,0.02245723269879818,0,,
+729,1119744,276.00408484800005,0.0003998308287312587,,0.02177843451499939,1,23.914993116632104,1000.0
+730,1121280,276.345448423,-1.3958197087049484e-06,,0.021714886650443077,4,20.53827188446303,868.25
+731,1122816,276.683691792,-0.00928487665951252,,0.022066136822104454,2,18.650891180499457,1000.0
+732,1124352,277.037234507,-0.004492747938881317,,0.021846897900104523,3,23.247592706931755,1000.0
+733,1125888,277.369564159,-0.004458557597051064,,0.02149832248687744,3,23.78854803655607,930.3333333333334
+734,1127424,277.79095917100005,-0.0063453565041224165,,0.022037014365196228,2,19.14056731807068,935.0
+735,1128960,278.20030516099996,-0.004981604994585117,,0.02194272354245186,1,22.806339513976127,1000.0
+736,1130496,278.596365095,-0.006804267580931386,,0.022010883316397667,0,,
+737,1132032,279.022318218,-0.003153533209115267,,0.02146412432193756,2,12.730890846898546,573.0
+738,1133568,279.45193688000006,-0.009781462978571654,,0.02175856940448284,0,,
+739,1135104,279.82640253500006,-0.010203145739311973,,0.021591443568468094,2,28.04132008884335,1000.0
+740,1136640,280.228062496,-0.007370221304396788,,0.02205749973654747,2,26.549799542408437,1000.0
+741,1138176,280.630746877,-0.009693740649769704,,0.022322501987218857,2,16.583466455573216,1000.0
+742,1139712,281.027018236,-0.0070519879149893916,,0.022016342729330063,2,18.03742829419207,1000.0
+743,1141248,281.39468397300004,-0.010223475952322284,,0.021789809688925743,0,,
+744,1142784,281.822325116,-0.009176666258523862,,0.021801484748721123,7,20.21170968356143,1000.0
+745,1144320,282.21327690300006,-0.00039932415820658206,,0.022464394569396973,2,23.173954676487483,1000.0
+746,1145856,282.61892645800003,-0.0051122930056105055,,0.02238214761018753,3,21.6081570055491,1000.0
+747,1147392,282.978198422,-0.01633766038964192,,0.022605784237384796,1,27.10989599802997,1000.0
+748,1148928,283.334997153,-0.003978706554820141,,0.022348806262016296,0,,
+749,1150464,283.67743430200005,-0.002409950985262791,,0.022168155759572983,0,,
+750,1152000,284.019810171,-0.007246837842588624,,0.022182367742061615,2,25.19890104327351,1000.0
+751,1153536,284.354837996,-0.01544133061543107,,0.022289827466011047,2,18.12921176647069,1000.0
+752,1155072,284.73532140099996,-0.009174638614058494,,0.022329233586788177,2,23.34692823642399,1000.0
+753,1156608,285.134266692,-0.011253775656223297,,0.022343367338180542,1,25.029725327622145,1000.0
+754,1158144,285.484511514,-0.003018911462277174,,0.022187892347574234,3,20.97160705473895,861.0
+755,1159680,285.832939326,-0.007698342499012748,,0.022450795397162437,2,21.6342973682913,1000.0
+756,1161216,286.166758188,-0.012827324323977034,,0.02217349037528038,0,,
+757,1162752,286.60464536100005,-0.0034682388417422772,,0.02205524407327175,4,21.109069074271247,1000.0
+758,1164288,286.9741721810001,-0.005759746907278896,,0.022186702117323875,2,15.98710831347853,1000.0
+759,1165824,287.309149616,-0.004277580045163631,,0.022384896874427795,1,20.08294700225815,1000.0
+760,1167360,287.638478577,-0.0026546130422502754,,0.021789908409118652,1,1.8996619419194758,112.0
+761,1168896,287.97241039100004,-0.007399786962196231,,0.02205386757850647,1,25.816469544079155,1000.0
+762,1170432,288.3249828180001,-0.0030266251880675553,,0.021431054919958115,3,16.73647096908341,793.6666666666666
+763,1171968,288.69105205000005,-0.008451720078786215,,0.022177428007125854,0,,
+764,1173504,289.05794357800005,-0.0045250467645625275,,0.02239212952554226,2,17.292981541948393,1000.0
+765,1175040,289.4407286200001,-0.015116855377952258,,0.022382788360118866,1,18.25761838350445,1000.0
+766,1176576,289.840958752,-0.0045705563699205715,,0.022695697844028473,0,,
+767,1178112,290.227029003,-0.012682154883320133,,0.022783054038882256,1,28.3942772957962,1000.0
+768,1179648,290.6024282100001,-0.010608111554756761,,0.02292654477059841,1,21.546850820770487,1000.0
+769,1181184,291.011057164,-0.0023497691688438255,,0.022709324955940247,0,,
+770,1182720,291.37858868,-0.003832039919992288,,0.022508904337882996,0,,
+771,1184256,291.78850901400006,0.0002795390784740448,,0.022104492411017418,2,24.70350940199569,1000.0
+772,1185792,292.1899056640001,-0.00026001461471120515,,0.022226538509130478,4,22.890781335911015,916.0
+773,1187328,292.6278401750001,-0.008540309437861045,,0.022364718839526176,1,24.865245049470104,1000.0
+774,1188864,293.13447018400007,-0.008169706864282488,,0.02201615646481514,4,23.420010536559857,1000.0
+775,1190400,293.622310296,-0.004524903697893023,,0.022243797779083252,2,26.357446373440325,1000.0
+776,1191936,294.01521856400007,-0.00550090156806012,,0.021994315087795258,2,23.111908652819693,1000.0
+777,1193472,294.365653642,-0.010176951081181567,,0.02220642939209938,0,,
+778,1195008,294.75007816000004,-0.004079934426893791,,0.0219973586499691,0,,
+779,1196544,295.12521799600006,-0.009516138536855578,,0.021909888833761215,2,16.350335285183974,1000.0
+780,1198080,295.51310502800004,-0.010099189371491473,,0.022135812789201736,1,29.560217157471925,1000.0
+781,1199616,295.94957048800006,-0.006484749944259723,,0.02195723168551922,2,27.47170287783956,1000.0
+782,1201152,296.299582557,-0.010554237104952336,,0.021821988746523857,3,20.45300114698087,1000.0
+783,1202688,296.691390854,-0.007177583174780011,,0.022168388590216637,1,17.319963379763067,1000.0
+784,1204224,297.13521234300003,-0.009415648706878225,,0.02212849073112011,1,14.700791428796947,1000.0
+785,1205760,297.54857586,-0.0046395229175686835,,0.022238146513700485,3,15.850021662306972,1000.0
+786,1207296,297.96852979000005,-0.008183034447332224,,0.022281061857938766,4,25.389388833049452,1000.0
+787,1208832,298.31202732500003,-0.006320475942144791,,0.022214021533727646,1,18.872129735536873,1000.0
+788,1210368,298.6811736540001,-0.00273471682642897,,0.022057533264160156,3,20.523620149431128,1000.0
+789,1211904,299.0445745740001,-0.009294568685193856,,0.022362396121025085,0,,
+790,1213440,299.37991972400005,-0.00583864925429225,,0.02237197756767273,0,,
+791,1214976,299.75144785300006,-0.00731554130713145,,0.022433994337916374,1,29.12277858890593,1000.0
+792,1216512,300.11998129200003,-0.004759296930084626,,0.022501861676573753,1,24.372198629193008,1000.0
+793,1218048,300.471958773,-0.004346755271156629,,0.022342100739479065,3,22.38546120429722,1000.0
+794,1219584,300.849044404,-0.008360666378090778,,0.022684244439005852,2,25.21138639433775,1000.0
+795,1221120,301.234758953,-0.008209211332723499,,0.02238653227686882,1,18.77004288416356,1000.0
+796,1222656,301.59032755300007,-0.011781595585246881,,0.022484388202428818,2,22.710580250713974,1000.0
+797,1224192,302.02417724200006,4.651757578055064e-05,,0.02258354239165783,1,14.48688760586083,1000.0
+798,1225728,302.41744224600006,-0.00691088765549163,,0.02263818494975567,2,24.954657902941108,1000.0
+799,1227264,302.899207467,-0.009548010242482027,,0.022411927580833435,2,19.956741291563958,1000.0
+800,1228800,303.30797434300007,-0.00942447455599904,,0.022629698738455772,2,18.570274719881127,1000.0
+801,1230336,303.7852393830001,-0.005329666007310152,,0.02261042408645153,1,20.933711054734886,1000.0
+802,1231872,304.25307173400006,-0.006238728621974587,,0.022800583392381668,1,14.107142649707384,1000.0
+803,1233408,304.714936876,-0.0023026418251295886,,0.022939413785934448,1,22.26908487919718,1000.0
+804,1234944,305.1378317010001,-0.002441247304280599,,0.022428443655371666,3,25.372182826007094,1000.0
+805,1236480,305.47985934300004,-0.004648952496548494,,0.021804219111800194,2,21.50954037992051,732.0
+806,1238016,305.859439888,-0.009988050224880378,,0.022268470376729965,1,18.38327301107347,1000.0
+807,1239552,306.19391722500006,-0.01017085659938554,,0.022329095751047134,1,30.050505705177784,1000.0
+808,1241088,306.526441094,0.0005176341782013575,,0.022016379982233047,0,,
+809,1242624,306.92447010800004,-0.008342563764502604,,0.021769877523183823,2,28.220631183008663,941.5
+810,1244160,307.275627567,-0.005160895393540462,,0.02149883471429348,1,17.371578857302666,1000.0
+811,1245696,307.610279946,-0.003774348646402359,,0.02108144573867321,2,24.360826988355257,862.5
+812,1247232,307.983129986,-0.010997345329572757,,0.021580737084150314,1,20.662749907001853,1000.0
+813,1248768,308.36897924000004,-0.006302619104584058,,0.021665018051862717,1,25.63028814084828,1000.0
+814,1250304,308.7782202530001,-0.006753914089252551,,0.021641649305820465,3,19.768545358092524,1000.0
+815,1251840,309.13005799100006,-0.009438580321148037,,0.021639039739966393,2,19.827900906762807,1000.0
+816,1253376,309.462696637,-0.008213568354646365,,0.02205200120806694,3,18.791515490816284,1000.0
+817,1254912,309.7843956380001,0.0023000767454504968,,0.021639268845319748,1,17.80834163632244,1000.0
+818,1256448,310.1037635480001,-0.009789919822166364,,0.0221643578261137,2,24.459071197314188,855.0
+819,1257984,310.4122376700001,-0.003909809018174807,,0.021459173411130905,1,24.660457057179883,884.0
+820,1259520,310.742045456,-0.01025844548518459,,0.02183154784142971,1,18.029683572240174,1000.0
+821,1261056,311.096870729,-0.006948749519263705,,0.022163022309541702,1,22.084895233623683,1000.0
+822,1262592,311.4166198390001,-0.004604580765590072,,0.02212146483361721,2,21.393829623732017,1000.0
+823,1264128,311.7472730410001,0.00547048697868983,,0.022089660167694092,1,13.550304609932937,1000.0
+824,1265664,312.160389977,-0.009125499178965886,,0.022237997502088547,2,23.352819590829313,1000.0
+825,1267200,312.49321708800005,-0.007108863194783529,,0.02203870378434658,1,30.408786656334996,1000.0
+826,1268736,312.855238826,-0.004160248984893163,,0.02158587984740734,1,25.99647140968591,1000.0
+827,1270272,313.20395926000003,-0.009227021938810746,,0.021838925778865814,5,18.06032453533262,1000.0
+828,1271808,313.533641516,-0.006893256943052014,,0.02268005907535553,2,18.752198959700763,1000.0
+829,1273344,313.848982169,-0.008668716096629699,,0.0230865478515625,1,13.317949650343508,1000.0
+830,1274880,314.18787958400003,-0.006955327155689399,,0.023063084110617638,1,24.75308311264962,1000.0
+831,1276416,314.56950909600005,-0.0076676257109890384,,0.023023804649710655,0,,
+832,1277952,314.981719807,-0.0033264910181363423,,0.023084010928869247,0,,
+833,1279488,315.37560233400006,-0.0008799793664366007,,0.02255098521709442,2,25.78752531670034,1000.0
+834,1281024,315.75092682,-0.0015744115536411604,,0.022280890494585037,2,25.06981099600671,982.5
+835,1282560,316.11622729600003,-0.00407277491564552,,0.02240348421037197,2,29.259966038982384,1000.0
+836,1284096,316.459898338,0.0012244798863927523,,0.0219239741563797,1,15.653683063574135,1000.0
+837,1285632,316.8319310410001,-0.0030025802242259186,,0.021924931555986404,3,22.004340438094612,960.3333333333334
+838,1287168,317.170291229,-0.006401961001877983,,0.022267086431384087,1,22.720745134633034,1000.0
+839,1288704,317.496429926,-0.010088783161093792,,0.022588081657886505,1,13.964765119017102,1000.0
+840,1290240,317.86404513,-0.007379410959159335,,0.022280868142843246,3,20.54328767520686,1000.0
+841,1291776,318.20174016300007,-0.012224610599999627,,0.022441525012254715,1,31.303993757348508,1000.0
+842,1293312,318.588726628,-0.0028388666765143474,,0.022534608840942383,2,23.493088313698536,1000.0
+843,1294848,319.009108704,-0.007799499590570728,,0.022186776623129845,1,14.37972004734911,1000.0
+844,1296384,319.44948548600007,-0.004991396640737851,,0.022619467228651047,1,24.514723734930158,1000.0
+845,1297920,319.8716799580001,-0.005630491410071651,,0.02252899669110775,2,20.718155680806376,1000.0
+846,1299456,320.246032592,-0.008502945490181445,,0.022378068417310715,1,15.332328526768833,1000.0
+847,1300992,320.5935396880001,-0.004328085823605458,,0.022431587800383568,3,23.55750816804357,1000.0
+848,1302528,320.964000383,-0.012834149381766717,,0.02272319793701172,0,,
+849,1304064,321.28981225100006,-0.007369636961569389,,0.022536208853125572,1,29.78462203219533,1000.0
+850,1305600,321.640928821,-0.00831509508813421,,0.02248537167906761,2,17.367463203001535,1000.0
+851,1307136,321.9928842400001,-0.0047056694359829026,,0.022373244166374207,1,25.571607768535614,1000.0
+852,1308672,322.35802596400003,-0.0030458602122962475,,0.022498231381177902,1,27.61347101442516,1000.0
+853,1310208,322.76074008800003,-0.003875557209054629,,0.02226984314620495,1,25.093566258554347,1000.0
+854,1311744,323.1443031670001,-0.005838411456594864,,0.0224917009472847,1,16.854651010711677,1000.0
+855,1313280,323.530660023,-0.003299934882670641,,0.022431135177612305,3,20.923037085526932,1000.0
+856,1314816,323.931049187,-0.005731774028390646,,0.02287493459880352,1,16.780373598448932,1000.0
+857,1316352,324.275741282,-0.003889633094271024,,0.023220418021082878,3,20.980862241471186,1000.0
+858,1317888,324.636435205,-0.009848782513290643,,0.02299056015908718,2,22.405672103865072,1000.0
+859,1319424,325.0403305450001,-0.007104789869238933,,0.023161549121141434,2,26.862532314145938,1000.0
+860,1320960,325.4049947760001,-0.00952353027338783,,0.022886045277118683,1,23.138854924123734,1000.0
+861,1322496,325.78119369600006,-0.008374714447806278,,0.02270500361919403,1,22.697962197940797,1000.0
+862,1324032,326.16085747700004,-0.0027674440294504165,,0.02249421738088131,2,20.07704156037653,1000.0
+863,1325568,326.508021954,-0.004277931122730175,,0.02246183156967163,0,,
+864,1327104,326.87640280200003,-0.008501146826893092,,0.02271387353539467,2,21.172236328246072,1000.0
+865,1328640,327.2181402130001,-0.008979463670402765,,0.02282009646296501,2,27.363277153111994,1000.0
+866,1330176,327.539393741,-0.011682914989069104,,0.023020640015602112,1,19.33842273335904,1000.0
+867,1331712,327.868319575,-0.00683433103064696,,0.02298603765666485,2,15.646430954278912,1000.0
+868,1333248,328.22031000800007,-0.004261350709324082,,0.023074200376868248,0,,
+869,1334784,328.639952945,-0.012638182332739233,,0.022519459947943687,5,28.119039943465033,1000.0
+870,1336320,329.1060120110001,-0.010995958341906469,,0.022359009832143784,2,26.69610315421596,1000.0
+871,1337856,329.47306811500005,-0.0017993563786149025,,0.02268730103969574,1,28.564671309664845,1000.0
+872,1339392,329.820012775,-0.007357943166668216,,0.022621555253863335,1,17.355163536034524,1000.0
+873,1340928,330.221330564,-0.005646178560952345,,0.02276325598359108,0,,
+874,1342464,330.541148764,-0.0016288738387326398,,0.0225476436316967,0,,
+875,1344000,330.88547185100003,-0.007869845970223348,,0.022264456376433372,2,21.525734976516105,1000.0
+876,1345536,331.223733841,-0.009469166537746787,,0.022623581811785698,3,19.497493303458516,1000.0
+877,1347072,331.53415047,-0.008270853416373332,,0.02294258028268814,1,27.9254577527754,1000.0
+878,1348608,331.850827061,-0.0066981487597028416,,0.022862499579787254,2,22.49043939926196,1000.0
+879,1350144,332.2042244400001,-0.010864456975832581,,0.022510221228003502,3,24.63241396122612,1000.0
+880,1351680,332.5576115580001,-0.01073026591911912,,0.02244296297430992,1,20.86528915259987,1000.0
+881,1353216,332.99515874400004,-0.00804370054975152,,0.0225941464304924,0,,
+882,1354752,333.39992549300007,-0.009182108441988628,,0.022163938730955124,4,21.811107311339583,1000.0
+883,1356288,333.77011667700003,0.005422411517550548,,0.022199969738721848,2,13.676468178658979,533.5
+884,1357824,334.1618655010001,-0.004082272822658221,,0.022253302857279778,1,14.183342708041891,1000.0
+885,1359360,334.538170152,-0.007868458982557058,,0.022195618599653244,1,30.64965755585581,1000.0
+886,1360896,334.89066034100006,-0.010385433429231246,,0.02208844944834709,1,21.689958860340994,1000.0
+887,1362432,335.231720891,-0.005589516119410594,,0.0219181589782238,3,15.998305944687067,1000.0
+888,1363968,335.53941607700006,-0.009852303331717849,,0.022104747593402863,0,,
+889,1365504,335.87486098400007,-0.012398324487730861,,0.02181675098836422,3,25.48400940691742,1000.0
+890,1367040,336.267061163,-0.004901065630838275,,0.022084102034568787,1,23.73223487404175,1000.0
+891,1368576,336.65533849200006,-0.011886471416801214,,0.02202886901795864,0,,
+892,1370112,337.09913682600006,-0.0024621739673117795,,0.02198502980172634,2,18.82239566289354,1000.0
+893,1371648,337.433751582,-0.0034512095463772614,,0.02195781096816063,1,23.984251166693866,1000.0
+894,1373184,337.769082946,-0.0035014376044273376,,0.0222126804292202,2,19.513823724293616,1000.0
+895,1374720,338.11330218700004,-0.008582062879577279,,0.02202242985367775,0,,
+896,1376256,338.467302397,-0.00834695560236772,,0.021948248147964478,2,23.54670710040955,1000.0
+897,1377792,338.814907629,-0.00693892619262139,,0.021467797458171844,3,29.92623653076589,1000.0
+898,1379328,339.184021886,-0.011250731364513437,,0.02093346416950226,2,23.43354754865868,885.5
+899,1380864,339.55413530600003,-0.0011627647404869397,,0.02043651044368744,4,19.62311095293262,931.75
+900,1382400,339.93408210300004,0.0010275795590132474,,0.02088344655930996,2,28.587317317607813,999.0
+901,1383936,340.331826147,-0.0023895042637983956,,0.02087988518178463,2,18.528610898531042,1000.0
+902,1385472,340.783699501,0.01445434099684159,,0.021073468029499054,0,,
+903,1387008,341.217043719,-0.002113165349389116,,0.021199628710746765,2,19.03305602958426,878.0
+904,1388544,341.597112037,-0.00804460368429621,,0.02140849083662033,2,15.496948718093336,1000.0
+905,1390080,341.96072118100005,-0.007327277027070522,,0.021529167890548706,1,24.745419850572944,1000.0
+906,1391616,342.4409809,-0.008644873835146427,,0.02108195424079895,2,25.702905443729833,1000.0
+907,1393152,342.87209953600006,-0.008465560541177789,,0.020915549248456955,1,30.97109852358699,1000.0
+908,1394688,343.266275004,-0.001974831490466992,,0.020826082676649094,1,25.494882136466913,1000.0
+909,1396224,343.62439252,-0.0019442265853285789,,0.02045097015798092,1,22.01388995628804,1000.0
+910,1397760,344.047738159,-0.007076652037600676,,0.020365864038467407,3,21.185834474046715,1000.0
+911,1399296,344.44098512900007,0.0016322511869172255,,0.020278312265872955,3,14.003391272892864,776.3333333333334
+912,1400832,344.787677303,-0.001874612799535195,,0.02077024057507515,1,16.732717755250633,1000.0
+913,1402368,345.208935719,-0.004646239709109068,,0.020723167806863785,1,19.375535430153832,1000.0
+914,1403904,345.59237528000006,-0.005047750814507405,,0.02038988657295704,0,,
+915,1405440,346.03745811600004,-0.0015532763209193945,,0.019502993673086166,2,13.223909927241039,532.0
+916,1406976,346.451671753,-0.00032908894742528596,,0.019961534067988396,1,30.915847051306628,1000.0
+917,1408512,346.841324039,0.006452777298788229,,0.01920592412352562,3,14.361762424892126,792.6666666666666
+918,1410048,347.320743988,-0.005881733944018682,,0.02063900977373123,4,22.414042722288286,956.0
+919,1411584,347.7443086410001,-0.0074037581992646056,,0.020713241770863533,1,26.499253435526043,1000.0
+920,1413120,348.209047423,-0.006820870004594326,,0.020748935639858246,2,17.590738369559404,1000.0
+921,1414656,348.591012171,-0.007191849562029044,,0.020401081070303917,2,19.63779909949517,1000.0
+922,1416192,349.02008204800006,-0.0025672215037047864,,0.020405776798725128,0,,
+923,1417728,349.4275207200001,0.0037345466824869316,,0.020170122385025024,3,17.421843469530966,858.0
+924,1419264,349.773510954,-0.011995057684058945,,0.02018534205853939,2,18.82022520317696,1000.0
+925,1420800,350.150137245,-0.0002617915937056144,,0.019901422783732414,1,15.805045956978574,1000.0
+926,1422336,350.5487184440001,-0.001927123311907053,,0.019974805414676666,2,22.384358973009512,962.5
+927,1423872,350.91726977400003,-0.007450814017405113,,0.019727079197764397,3,17.1082783229261,720.6666666666666
+928,1425408,351.305592683,-0.012489213639249404,,0.020788192749023438,1,14.686918376130052,1000.0
+929,1426944,351.670033182,0.00274434561530749,,0.02098315767943859,2,18.916042278520763,1000.0
+930,1428480,352.1311346230001,-0.0014026539400219917,,0.02103862725198269,2,19.984777703793952,1000.0
+931,1430016,352.5749060620001,-0.013019274935747187,,0.02161107212305069,1,18.673541458090767,1000.0
+932,1431552,352.94217577300003,0.0007092107553035021,,0.02183431386947632,0,,
+933,1433088,353.3396034550001,0.005287616606801748,,0.021505199372768402,0,,
+934,1434624,353.73926522600004,0.0006836946122348309,,0.02164938859641552,3,17.39623222919181,829.0
+935,1436160,354.0889049670001,-0.0045405063157280285,,0.021972622722387314,1,17.86145320534706,1000.0
+936,1437696,354.50245764,-0.008386942045763134,,0.02177516184747219,1,16.121421817224473,1000.0
+937,1439232,354.892801479,-0.00850946685920159,,0.02183167263865471,0,,
+938,1440768,355.2751195420001,-0.011766624233374993,,0.021649852395057678,1,15.220447331550531,1000.0
+939,1442304,355.629969308,-0.004901891387999058,,0.02195969969034195,2,22.105894866457675,1000.0
+940,1443840,355.96312696200005,-0.007153973945726951,,0.021973714232444763,3,20.01495213911403,1000.0
+941,1445376,356.32117416200003,-0.007454251808424791,,0.022354062646627426,3,18.904210519278422,1000.0
+942,1446912,356.659767137,-0.01105267540551722,,0.021982213482260704,1,24.823414713144302,1000.0
+943,1448448,356.9987177290001,-0.0059435715898871425,,0.021780163049697876,1,29.665568164549768,1000.0
+944,1449984,357.40523232500004,-0.003582711595421036,,0.021888813003897667,2,23.24511055793846,1000.0
+945,1451520,357.744233183,-0.0004979637606690328,,0.021543871611356735,2,14.82753911492182,695.0
+946,1453056,358.17136687000004,-0.008206344566618402,,0.021805260330438614,1,18.084983692038804,1000.0
+947,1454592,358.637028053,-0.00915429051965475,,0.021826162934303284,2,17.86129399429774,1000.0
+948,1456128,359.10021268900005,-0.0048338673387964565,,0.021818485110998154,1,16.243413561431225,1000.0
+949,1457664,359.52675517600005,-0.002070816233754158,,0.02182806096971035,1,21.93718011677265,1000.0
+950,1459200,360.02286738500004,-0.004723920673131943,,0.021538857370615005,1,24.35518228984438,1000.0
+951,1460736,360.48661629900005,-0.010457841617365678,,0.02151636779308319,2,15.151192645309493,779.0
+952,1462272,360.90824288,-0.007760585565119982,,0.021816996857523918,4,21.291654150234535,1000.0
+953,1463808,361.39785737700004,-0.002854115391770999,,0.022066444158554077,2,13.680682491190964,1000.0
+954,1465344,361.78575117,-0.003089087409898639,,0.022026602178812027,0,,
+955,1466880,362.176843447,-0.008062378348161777,,0.021591614931821823,0,,
+956,1468416,362.58564190900006,-0.00546802186096708,,0.021473398432135582,0,,
+957,1469952,362.99211695300005,-0.009022533521056175,,0.021484499797225,2,21.16501259081997,1000.0
+958,1471488,363.49735954000005,-0.006778479771067699,,0.02157728746533394,2,17.644570399541408,1000.0
+959,1473024,363.912528414,-0.009317091759294271,,0.02157924883067608,4,24.74134057003539,1000.0
+960,1474560,364.369837696,-0.008174906640003124,,0.021155904978513718,2,22.929022277938202,1000.0
+961,1476096,364.76996278600006,-0.007870592611531417,,0.021248657256364822,2,24.708221867738757,868.0
+962,1477632,365.192977625,-0.011945737060159445,,0.021317755803465843,3,18.936417944574107,1000.0
+963,1479168,365.68604517200004,-0.006109912383059661,,0.02165120840072632,1,13.339010792784393,1000.0
+964,1480704,366.159048128,-0.013268650695681571,,0.021787375211715698,0,,
+965,1482240,366.658904698,-0.00583567318196098,,0.021169565618038177,4,21.77975036180578,1000.0
+966,1483776,367.134504289,-0.00725867737395068,,0.021513134241104126,2,19.929945746203884,1000.0
+967,1485312,367.69149482600005,0.0019109531460950772,,0.021822702139616013,2,19.90239942795597,1000.0
+968,1486848,368.1846509090001,-0.01180105940438807,,0.021714216098189354,1,29.156739596743137,1000.0
+969,1488384,368.67718036400004,-0.011507850978523493,,0.021848782896995544,2,25.288018438383006,1000.0
+970,1489920,369.125192762,-0.009614483189458648,,0.022106772288680077,1,23.02800478693098,1000.0
+971,1491456,369.65590057300005,-0.002958998673905929,,0.022079389542341232,0,,
+972,1492992,370.13578509700005,-0.00030304815930624803,,0.022031819447875023,2,30.51284668687731,1000.0
+973,1494528,370.6017542640001,-0.003322573471814394,,0.022004051133990288,0,,
+974,1496064,371.00956402300005,-0.0019424871075898408,,0.021846970543265343,0,,
+975,1497600,371.5037460970001,-0.012398155964910984,,0.021806081756949425,3,22.060963092837483,1000.0
+976,1499136,371.95109489800006,-0.009027859894558787,,0.02198946475982666,1,27.44174163416028,1000.0
+977,1500672,372.41541006400007,-0.0001222916878759861,,0.021898716688156128,0,,
+978,1502208,372.863679497,-0.006774114072322845,,0.02199871465563774,1,13.593184492085129,1000.0
+979,1503744,373.3223520050001,-0.006395448589076599,,0.02215486578643322,0,,
+980,1505280,373.7169414670001,-0.010917459661141039,,0.02226100116968155,3,23.708171060929697,1000.0
+981,1506816,374.116014724,-0.00414970014244318,,0.022092949599027634,1,29.19740763353184,1000.0
+982,1508352,374.5664011570001,-0.007631191471591592,,0.02242214046418667,3,20.118506931622203,1000.0
+983,1509888,374.9780816140001,-0.0103283422999084,,0.02306041680276394,2,16.18808029324282,1000.0
+984,1511424,375.40596943900005,-0.007052217423915863,,0.02261871099472046,2,18.63505690312013,1000.0
+985,1512960,375.79156063900007,-0.0022862485299507775,,0.022810563445091248,0,,
+986,1514496,376.171209125,-0.005943403905257582,,0.0226513110101223,2,22.26414271676913,1000.0
+987,1516032,376.612301076,-0.010149454651400446,,0.02249738574028015,3,23.50045307353139,1000.0
+988,1517568,377.060644186,-0.006970249333729347,,0.022413082420825958,0,,
+989,1519104,377.5369052440001,-0.001364259049296379,,0.022739943116903305,2,16.368311509490013,1000.0
+990,1520640,377.98902406800005,-0.004791407566517592,,0.022089071571826935,3,27.3377669856806,975.3333333333334
+991,1522176,378.39495139300004,0.0005260404199361801,,0.02273697406053543,0,,
+992,1523712,378.78196197700004,-0.0018992741592228413,,0.02280334196984768,2,19.84222193027381,1000.0
+993,1525248,379.2142727930001,-0.0009309572633355856,,0.022670850157737732,1,26.396943034604192,1000.0
+994,1526784,379.64541719300007,-0.007891923282295465,,0.022404050454497337,4,18.31088923237985,961.75
+995,1528320,380.05863472,-0.006634041589374344,,0.022900082170963287,2,17.63988891430199,1000.0
+996,1529856,380.48496411200006,-0.0035951741660634677,,0.022990217432379723,0,,
+997,1531392,380.9690487390001,-0.004892859499280652,,0.022101638838648796,1,19.896451152511872,687.0
+998,1532928,381.510413748,-0.002753807231783867,,0.02260958030819893,1,15.966200094902888,1000.0
+999,1534464,381.9227792490001,-0.002827990831186374,,0.02242172881960869,1,25.48289066646248,1000.0
+1000,1536000,382.38270947700005,-0.0035824333472798267,,0.021956849843263626,3,18.637866337628413,825.6666666666666
+1001,1537536,382.789637393,0.002106239553540945,,0.022399690002202988,4,19.374202069360763,1000.0
+1002,1539072,383.1507953580001,-0.005811756197363138,,0.02212895080447197,1,24.267102274112403,1000.0
+1003,1540608,383.599991894,-0.006256835597256819,,0.022103291004896164,4,23.22874817266711,971.75
+1004,1542144,384.0065087710001,-0.005397735442966223,,0.022562459111213684,3,19.617315488130163,1000.0
+1005,1543680,384.3689174760001,-0.00701185263072451,,0.022347494959831238,1,7.8081315299496055,343.0
+1006,1545216,384.73095665200003,-0.004351012858872612,,0.021769296377897263,3,14.298412191836784,662.0
+1007,1546752,385.16552726500004,-0.008707387465983629,,0.022919781506061554,3,19.017907809466124,1000.0
+1008,1548288,385.58771321100005,-0.0010422184752921263,,0.022860627621412277,2,12.10482124943519,544.5
+1009,1549824,386.0231189670001,0.0015325915378828843,,0.023251336067914963,2,20.318743991694646,1000.0
+1010,1551360,386.46234512600006,-0.0017005144618451595,,0.022824984043836594,1,30.983292365912348,1000.0
+1011,1552896,386.857202949,-0.0027568672007570664,,0.021940525621175766,2,28.03832454577787,967.5
+1012,1554432,387.217025658,-0.0013889664163192113,,0.022551216185092926,1,21.26995235402137,1000.0
+1013,1555968,387.6194663890001,-0.002361498012517889,,0.0228300578892231,0,,
+1014,1557504,388.01884560300005,-0.00010898426795999208,,0.0224753525108099,1,23.333885381929576,1000.0
+1015,1559040,388.384574584,0.0019572954314450424,,0.02219618484377861,1,26.808287610299885,962.0
+1016,1560576,388.7405643750001,-0.005660443007946015,,0.022204335778951645,0,,
+1017,1562112,389.123183316,-0.006887128297239542,,0.02235450968146324,2,26.148348179180175,1000.0
+1018,1563648,389.5228263900001,-0.007969416429599125,,0.022547226399183273,1,18.678018100035843,1000.0
+1019,1565184,389.878484714,-0.005482700125624736,,0.022516675293445587,1,24.349641960579902,1000.0
+1020,1566720,390.214754909,0.005088603310286999,,0.022350016981363297,0,,
+1021,1568256,390.568267771,-0.007941256525615852,,0.021276261657476425,1,30.57711411267519,1000.0
+1022,1569792,390.92313527300007,-0.00017221169546246528,,0.021097904071211815,3,17.758639447856694,793.3333333333334
+1023,1571328,391.32569670600003,-0.009556507660696904,,0.02150493487715721,3,25.623966568460066,990.3333333333334
+1024,1572864,391.72978671,-0.007171951094642281,,0.021833069622516632,1,18.936264287680387,1000.0
+1025,1574400,392.16465462400004,0.00024403231218457223,,0.021725714206695557,2,18.118094883393496,1000.0
+1026,1575936,392.6250826920001,-0.005839394964277744,,0.021532809361815453,1,23.710912310518324,1000.0
+1027,1577472,393.03479367400007,-0.0040417172014713286,,0.02157377451658249,0,,
+1028,1579008,393.44968035500005,-0.007561583677306772,,0.021159349009394646,2,22.193127975042444,1000.0
+1029,1580544,393.81908927100005,-0.0006188432686030865,,0.021700052544474602,3,20.86977624784534,1000.0
+1030,1582080,394.19139530200005,-0.004011531810586651,,0.021711885929107666,1,26.545108351972885,1000.0
+1031,1583616,394.53886919600006,-0.0025220255367457865,,0.021150000393390656,2,15.578767735220026,795.0
+1032,1585152,394.90007876800007,-0.0066342000849545,,0.02215990424156189,1,13.540222831536084,1000.0
+1033,1586688,395.295695204,-0.009142823920895656,,0.022284314036369324,1,30.26874079927802,1000.0
+1034,1588224,395.698074784,-0.007852020704497894,,0.022202953696250916,1,25.744859003461897,1000.0
+1035,1589760,396.06359650900004,-0.005004013578097026,,0.022097622975707054,1,18.03863469325006,1000.0
+1036,1591296,396.475510322,0.0006176875283320745,,0.022022288292646408,4,18.998894606280373,1000.0
+1037,1592832,396.87934581,0.004701548628509045,,0.02277783304452896,0,,
+1038,1594368,397.27201201,-0.011954824688533943,,0.022304877638816833,0,,
+1039,1595904,397.64985301,-0.007481334389497837,,0.022066477686166763,1,18.188300353474915,1000.0
+1040,1597440,398.0102732270001,-0.002279751530538003,,0.02243972383439541,2,26.08731983206235,1000.0
+1041,1598976,398.36742896300007,-0.0015608718308309714,,0.022642072290182114,1,15.747305656783283,1000.0
+1042,1600512,398.76006830100005,-0.0076562501955777405,,0.0224904865026474,3,22.280492435675114,1000.0
+1043,1602048,399.11717916300006,0.0009670966770499945,,0.022207846865057945,4,28.58951387621346,1000.0
+1044,1603584,399.518824642,-0.0004521951079368591,,0.021981125697493553,3,18.927227251930162,1000.0
+1045,1605120,399.89670990700006,0.008803991926833987,,0.021223779767751694,4,15.728775800176663,760.5
+1046,1606656,400.28176463700004,-0.0025191526083896557,,0.02196459472179413,1,28.203757815063,1000.0
+1047,1608192,400.64599119,-0.006370681306968133,,0.022151976823806763,0,,
+1048,1609728,401.031179792,-0.0004815276556958755,,0.0218593031167984,4,24.282025851134676,1000.0
+1049,1611264,401.446617617,-0.011686229286715389,,0.021964892745018005,2,19.920585543499328,1000.0
+1050,1612800,401.821517147,-0.0017162517799685399,,0.0219191312789917,1,19.10396120045334,1000.0
+1051,1614336,402.21429787400007,-0.005507376790046692,,0.02176215872168541,2,17.670144155155867,1000.0
+1052,1615872,402.6679130030001,-0.00611183731816709,,0.021638348698616028,2,23.578542900737375,1000.0
+1053,1617408,403.114610844,-0.000993150332942605,,0.022130778059363365,1,16.43378616438713,1000.0
+1054,1618944,403.57599051400007,-0.002803012930477659,,0.02168215438723564,1,24.604481514543295,1000.0
+1055,1620480,403.9508656390001,0.0006030381967624029,,0.021860038861632347,0,,
+1056,1622016,404.3556986650001,-0.006648645177483559,,0.021949438378214836,1,16.71425243036356,1000.0
+1057,1623552,404.748054057,-0.005796454598506292,,0.0220348984003067,1,19.708416605833918,1000.0
+1058,1625088,405.17354396100006,-0.007416551948214571,,0.0222333874553442,0,,
+1059,1626624,405.60059089800006,-0.005417652024577061,,0.022330861538648605,2,24.05056311073713,1000.0
+1060,1628160,406.0043357750001,-0.0137040580312411,,0.022280611097812653,1,31.206120285205543,1000.0
+1061,1629696,406.45924863000005,-0.004933202561611931,,0.022019749507308006,1,18.872290653176606,1000.0
+1062,1631232,406.86133623800004,-0.00568405301310122,,0.02221313863992691,0,,
+1063,1632768,407.2811533050001,-0.000290269140775005,,0.02210969105362892,3,21.32005580623324,1000.0
+1064,1634304,407.758220025,-0.0034382957033813,,0.021803010255098343,3,18.90165138671485,956.6666666666666
+1065,1635840,408.171445146,-0.009114003491898377,,0.022237353026866913,3,20.149874657392502,1000.0
+1066,1637376,408.562011449,-0.0011709074800213177,,0.022099433466792107,2,10.444419381616171,651.0
+1067,1638912,408.97483141500004,-0.007115564836810032,,0.022380392998456955,1,15.18294030171819,1000.0
+1068,1640448,409.402758566,0.0002946446028848489,,0.02261826954782009,1,25.203893145546317,1000.0
+1069,1641984,409.840367389,-0.003164198777327935,,0.02239786460995674,1,15.360209838487208,1000.0
+1070,1643520,410.23243804900005,-0.0021589804130295914,,0.022449001669883728,2,28.00669222162105,1000.0
+1071,1645056,410.64959270400004,-9.444612078368664e-05,,0.02234850823879242,1,30.69958664244041,1000.0
+1072,1646592,411.01457054700006,-0.00860277758911252,,0.022468483075499535,1,31.405481999740005,1000.0
+1073,1648128,411.41303106600003,-0.009209449465076128,,0.02188163809478283,2,30.281280932947993,1000.0
+1074,1649664,411.7748546270001,-0.007617437435934941,,0.021855682134628296,1,21.45244766131509,1000.0
+1075,1651200,412.115796661,-0.003274943307042122,,0.022008342668414116,1,24.158453391864896,1000.0
+1076,1652736,412.527188304,-0.006256289066125949,,0.02188124507665634,1,22.882510002702475,1000.0
+1077,1654272,412.892160277,-0.006744799483567476,,0.02175714448094368,3,21.039444214276347,1000.0
+1078,1655808,413.290059283,-0.010081592310840885,,0.02183791995048523,2,19.230444186832756,1000.0
+1079,1657344,413.6998758330001,-0.00035258997231721876,,0.022148307412862778,0,,
+1080,1658880,414.13838010100005,0.0017622344351063172,,0.022230040282011032,0,,
+1081,1660416,414.631334573,0.003555824172993501,,0.021566636860370636,1,26.926408070139587,1000.0
+1082,1661952,415.0280045420001,-0.006620704693098863,,0.021379930898547173,3,18.268544733330298,757.3333333333334
+1083,1663488,415.4278462660001,0.0006007144693285227,,0.021164782345294952,3,23.25740788729551,936.3333333333334
+1084,1665024,415.8097415000001,0.0009226497417936723,,0.021557753905653954,4,21.972291318204952,1000.0
+1085,1666560,416.16444728600004,-0.0030349499545991422,,0.021787350997328758,1,17.119252259493805,1000.0
+1086,1668096,416.5418141370001,-0.0024598403212924796,,0.021678492426872253,3,18.071724136748042,1000.0
+1087,1669632,416.946952271,-0.0031267360628892977,,0.021985746920108795,4,19.46262914437102,1000.0
+1088,1671168,417.33458848600003,0.0025814680072168508,,0.022266287356615067,1,23.134861833183095,1000.0
+1089,1672704,417.71649526300007,-0.004923543365051349,,0.02239834889769554,0,,
+1090,1674240,418.09168530400007,0.0008610237234582504,,0.021516945213079453,6,18.196416466884937,844.8333333333334
+1091,1675776,418.464438941,-0.003416300502916177,,0.022678596898913383,1,18.364073228556663,1000.0
+1092,1677312,418.87321662500005,-0.00676006255671382,,0.02232252061367035,2,16.584888020472135,1000.0
+1093,1678848,419.25188487,-0.006963481924807032,,0.022556772455573082,1,30.73382653668523,1000.0
+1094,1680384,419.67068620300006,-0.0021022139117121696,,0.02248992584645748,2,18.181249778252095,1000.0
+1095,1681920,420.0092056010001,-0.004461098229512572,,0.022686995565891266,0,,
+1096,1683456,420.35058769,-0.011230336253841717,,0.022777220234274864,0,,
+1097,1684992,420.71494525,-0.006047949101775885,,0.022522781044244766,1,29.695854222751223,1000.0
+1098,1686528,421.047198514,-0.0070403886027634146,,0.022592246532440186,0,,
+1099,1688064,421.4196144020001,-0.006807488234092792,,0.02242613583803177,1,30.753543010912836,1000.0
+1100,1689600,421.7846953310001,-0.000644518838574489,,0.022147253155708313,2,28.907091117929667,1000.0
+1101,1691136,422.1278802730001,0.006242705617720882,,0.02166113816201687,1,20.29691647645086,1000.0
+1102,1692672,422.4756769070001,0.0038879932990918556,,0.020922567695379257,2,17.08791545405984,588.0
+1103,1694208,422.8358187040001,-0.0074125814562042555,,0.021370982751250267,2,13.812669619335793,727.0
+1104,1695744,423.18322180300004,0.0050561570407201845,,0.021678999066352844,0,,
+1105,1697280,423.59411044500007,0.00018192495529850323,,0.02132726088166237,5,20.65634705869015,895.0
+1106,1698816,423.96834031700007,-0.007258724592005213,,0.022138535976409912,3,17.497125195572153,1000.0
+1107,1700352,424.322713572,-0.004712217720225453,,0.021994516253471375,2,23.16968104825355,1000.0
+1108,1701888,424.7412906200001,0.002517850324511528,,0.021123569458723068,3,17.3370281610017,878.6666666666666
+1109,1703424,425.16182312,0.0009948476838568846,,0.021581998094916344,2,21.258037633728236,1000.0
+1110,1704960,425.603414844,0.0032783818741639456,,0.022310208529233932,0,,
+1111,1706496,426.01490761900004,-0.00020877526452143987,,0.02158670499920845,2,24.616999112651683,992.0
+1112,1708032,426.422454723,-0.005761263348783056,,0.021271836012601852,1,23.973432453349233,1000.0
+1113,1709568,426.8008643290001,-0.004543878852079312,,0.021500369533896446,0,,
+1114,1711104,427.20102827200003,-0.005377016464869181,,0.021784722805023193,2,22.543175697384868,1000.0
+1115,1712640,427.62937066000006,-0.0036013018650313216,,0.021509665995836258,2,23.917371190618724,1000.0
+1116,1714176,428.017809907,-0.00010204285693665346,,0.022002894431352615,0,,
+1117,1715712,428.4091858820001,-0.004013704524065058,,0.021755024790763855,1,16.278932037996128,1000.0
+1118,1717248,428.82143031,-0.00996737137126426,,0.02223200723528862,1,16.30180402379483,1000.0
+1119,1718784,429.213617097,0.0011666234272221724,,0.022009214386343956,1,13.479243917216081,1000.0
+1120,1720320,429.68471745700003,-0.005230621714144945,,0.02206799015402794,3,22.288561792423327,876.3333333333334
+1121,1721856,430.10414056600007,-0.004712364822626114,,0.021911820396780968,0,,
+1122,1723392,430.535083308,0.00277627424026529,,0.021307049319148064,2,19.441172739258036,956.0
+1123,1724928,430.896811919,-0.0029969541045526665,,0.021829020231962204,2,20.603354994906113,1000.0
+1124,1726464,431.298993826,-0.0051459260284900665,,0.021774515509605408,0,,
+1125,1728000,431.69796603400005,-0.004478243722890814,,0.021900249645113945,4,19.910450062263408,1000.0
+1126,1729536,432.05285894300005,-0.009052650770172477,,0.021842002868652344,1,15.870603241957724,1000.0
+1127,1731072,432.399987572,-0.0029050960671156644,,0.021659573540091515,0,,
+1128,1732608,432.77170471500006,-0.0018737940738598506,,0.021034426987171173,5,23.81178127131425,1000.0
+1129,1734144,433.1227726430001,-0.0004120592027902603,,0.02101973071694374,2,22.0619400824653,813.5
+1130,1735680,433.515572283,-0.009500869084149599,,0.021505337208509445,1,18.83395803719759,1000.0
+1131,1737216,433.8706089550001,-0.005302547384053469,,0.021433338522911072,2,23.06749554350972,1000.0
+1132,1738752,434.23011126100005,-0.008010105229914188,,0.02138444408774376,4,21.05943452657084,1000.0
+1133,1740288,434.57605687,-0.005381035432219505,,0.022022541612386703,1,18.088262593839318,1000.0
+1134,1741824,434.94004033,-0.005120169588675102,,0.0217970609664917,2,25.80330769275315,1000.0
+1135,1743360,435.3086200040001,-0.006408073240891099,,0.02170770987868309,0,,
+1136,1744896,435.7335805590001,-0.0039637329988181595,,0.0215801652520895,2,21.744256148289423,1000.0
+1137,1746432,436.1498607660001,-0.009422250014419356,,0.022225921973586082,0,,
+1138,1747968,436.5479697310001,-0.009593301452696323,,0.0220456775277853,0,,
+1139,1749504,436.949198442,-0.0061882130801677706,,0.02232312224805355,1,13.608084540814161,1000.0
+1140,1751040,437.3038523580001,-0.009861765553553899,,0.022432994097471237,1,23.488687565550208,1000.0
+1141,1752576,437.6846489730001,-0.007171851272384326,,0.02221554145216942,0,,
+1142,1754112,438.0429444040001,-0.009568610896045963,,0.022055968642234802,2,28.368123184423894,1000.0
+1143,1755648,438.436925813,-0.0016472281577686468,,0.02179655432701111,2,15.81923584965989,1000.0
+1144,1757184,438.7749523780001,-0.005319897085428238,,0.022219529375433922,1,21.886586953885853,1000.0
+1145,1758720,439.1602078650001,-0.005210518992195527,,0.022156378254294395,1,26.356943290680647,1000.0
+1146,1760256,439.612287336,-0.0012873879012962183,,0.021978463977575302,1,24.676587400957942,1000.0
+1147,1761792,440.028156586,-0.0031656827467183273,,0.021689025685191154,5,23.197451836732217,1000.0
+1148,1763328,440.44635566700003,-0.0033438397571444512,,0.021427113562822342,4,19.869534129305976,920.25
+1149,1764864,440.807464032,0.0029685471517344316,,0.022354289889335632,1,13.688001523958519,1000.0
+1150,1766400,441.205713059,-0.006070224319895109,,0.02154592052102089,4,23.484045520192012,1000.0
+1151,1767936,441.597867877,-0.005813537786404292,,0.021290045231580734,1,23.39046400762163,1000.0
+1152,1769472,441.94656898100004,-0.007461135927587748,,0.021495133638381958,0,,
+1153,1771008,442.365573004,-0.0018575760070234538,,0.021103112027049065,2,19.475907766027376,1000.0
+1154,1772544,442.78729732,-0.0012071995375057061,,0.021470291540026665,1,18.44829781516455,1000.0
+1155,1774080,443.24930134,-0.012158104466895263,,0.02143249660730362,1,18.94516331795603,1000.0
+1156,1775616,443.68326134100005,-0.006503898929804563,,0.021353846415877342,2,21.434772286273073,1000.0
+1157,1777152,444.01600057300004,-0.007175584059829513,,0.0213015116751194,1,19.59771605115384,1000.0
+1158,1778688,444.372215223,-0.0047323715252180895,,0.021545138210058212,1,13.990536489174701,1000.0
+1159,1780224,444.74333743400007,-0.004960245545953512,,0.02155700884759426,1,23.65452708862722,1000.0
+1160,1781760,445.107235326,-0.005984781263396144,,0.02140313945710659,1,22.847478677518666,1000.0
+1161,1783296,445.5388919960001,-0.0011705233715474605,,0.02113877236843109,2,17.823274047812447,1000.0
+1162,1784832,445.87975530000006,-0.0027400939414898556,,0.02086031436920166,0,,
+1163,1786368,446.2231783210001,-0.002120949700474739,,0.020960994064807892,1,11.924353169859387,658.0
+1164,1787904,446.669050998,-0.0044360714964568615,,0.021030139178037643,2,20.39491584105417,1000.0
+1165,1789440,447.16140219600004,-0.006198928505182266,,0.021416977047920227,2,21.580989728914574,1000.0
+1166,1790976,447.67359366000005,-0.007825166980425517,,0.02179868146777153,1,21.50712092826143,1000.0
+1167,1792512,448.1503842750001,-0.001461150124669075,,0.021150968968868256,3,24.74054578288148,1000.0
+1168,1794048,448.63052492400004,-0.004788408459474643,,0.02135758474469185,1,27.545407248660922,1000.0
+1169,1795584,449.019637202,-0.002345865483706196,,0.021285196766257286,3,22.54187999595888,1000.0
+1170,1797120,449.444455855,-0.0045971673602859175,,0.02113967202603817,4,18.467076922228443,1000.0
+1171,1798656,449.84352556600004,-0.012171760248020292,,0.021512284874916077,1,13.559219259419478,1000.0
+1172,1800192,450.19451639500005,-0.008837679121643304,,0.02159038558602333,0,,
+1173,1801728,450.6321122610001,-0.003210961539298296,,0.021469712257385254,5,23.321697082160973,1000.0
+1174,1803264,451.05169153400004,-0.0057646023575216535,,0.021892940625548363,1,28.88694805651903,1000.0
+1175,1804800,451.46691644300006,-0.008827933141340812,,0.021433135494589806,1,30.726496431045234,1000.0
+1176,1806336,451.93384389900007,-0.010673326533287763,,0.021018531173467636,2,23.512621524976566,1000.0
+1177,1807872,452.33360742900004,-0.0018057561945170164,,0.021076736971735954,1,30.282103445380926,1000.0
+1178,1809408,452.74102050600004,-0.006495144870132208,,0.020893609151244164,0,,
+1179,1810944,453.115787393,-0.005566033612315853,,0.02101893723011017,0,,
+1180,1812480,453.5017743630001,-0.013251929264515638,,0.021099906414747238,0,,
+1181,1814016,453.871211218,-0.002799351622040073,,0.020850103348493576,1,24.337294219993055,1000.0
+1182,1815552,454.203789915,-0.007278463027129571,,0.020816266536712646,1,24.835141701623797,1000.0
+1183,1817088,454.550651346,0.0008291213773190976,,0.020622799172997475,0,,
+1184,1818624,454.956033629,0.005121279430265228,,0.020491909235715866,2,19.66059951414354,1000.0
+1185,1820160,455.42286561000003,-0.004201373023291429,,0.020215049386024475,4,18.945788792014355,845.0
+1186,1821696,455.86509059900004,-0.011451980487133065,,0.02069086581468582,1,14.570538120926358,1000.0
+1187,1823232,456.223511703,-0.005960239438960949,,0.020617276430130005,0,,
+1188,1824768,456.61044411600005,-0.003469689656049013,,0.020740531384944916,4,23.33423583387048,1000.0
+1189,1826304,456.97683615000005,-0.01566232880577445,,0.021081730723381042,3,19.213505058161292,1000.0
+1190,1827840,457.339647895,-0.006371468678116799,,0.021026533097028732,4,24.01578569447156,1000.0
+1191,1829376,457.7736929590001,-0.0008835394556323688,,0.02123454213142395,2,14.948855451133568,1000.0
+1192,1830912,458.2009042960001,-0.004218878985072175,,0.020868239924311638,2,15.038624364417046,1000.0
+1193,1832448,458.61789037200003,-0.0026541228871792555,,0.02002866566181183,2,18.961622099450324,705.5
+1194,1833984,459.03014645300004,-0.011515466837833326,,0.020937591791152954,1,19.64987453853246,1000.0
+1195,1835520,459.40321925500007,-0.010590735372776787,,0.02084179036319256,1,21.594307566061616,1000.0
+1196,1837056,459.78188696100005,-0.007187188835814595,,0.020664473995566368,1,17.25839937850833,1000.0
+1197,1838592,460.151478462,-0.006085568449149529,,0.02079649642109871,1,18.065420968458056,1000.0
+1198,1840128,460.5137902800001,-0.0073668470761428274,,0.020780209451913834,2,19.421884504059562,1000.0
+1199,1841664,460.86820174900004,-0.00980141549371183,,0.02095710299909115,1,20.64628205820918,1000.0
+1200,1843200,461.2249521680001,-0.0005487526456514994,,0.02086693048477173,1,27.36772701703012,1000.0
+1201,1844736,461.6227843590001,-0.007345991240193446,,0.02082819677889347,1,21.50693709636107,1000.0
+1202,1846272,461.97446869500004,-0.004101252524803082,,0.02080092951655388,1,16.095435354858637,1000.0
+1203,1847808,462.32830780100005,-0.003736737339446942,,0.02103624865412712,2,17.976528574188706,1000.0
+1204,1849344,462.70219388400005,-0.001610437563310067,,0.021058339625597,0,,
+1205,1850880,463.162428835,-0.006321122559408347,,0.020747382193803787,1,21.88356163026765,1000.0
+1206,1852416,463.662173554,-0.00831074162075917,,0.020863763988018036,2,18.37348132621264,1000.0
+1207,1853952,464.09484155300004,0.0006929534332205852,,0.020815618336200714,2,18.543493235949427,1000.0
+1208,1855488,464.5436616190001,-0.00014359907557566962,,0.020546702668070793,3,20.419209762321163,1000.0
+1209,1857024,464.9424022950001,-0.004693015975256761,,0.021392321214079857,3,18.475998898230802,758.3333333333334
+1210,1858560,465.383926406,-0.009389068838208914,,0.021244710311293602,0,,
+1211,1860096,465.795227544,-0.01263258100176851,,0.021032055839896202,2,22.410411826800555,1000.0
+1212,1861632,466.14582166,-0.011147026314089696,,0.02099013328552246,4,19.60422392981127,1000.0
+1213,1863168,466.483575515,-0.003453283167133729,,0.021141383796930313,1,23.772820642217994,1000.0
+1214,1864704,466.82251652900004,-0.0036912265854577224,,0.021587669849395752,0,,
+1215,1866240,467.19033886500006,-0.01092130426938335,,0.02047399803996086,6,24.29189527166697,1000.0
+1216,1867776,467.588123761,-0.0058675702350835,,0.02044346183538437,1,13.607837285031565,1000.0
+1217,1869312,467.94488231900004,-0.0035461646659920615,,0.020417500287294388,1,16.60466451907996,1000.0
+1218,1870848,468.28357133500003,-0.003746757749468088,,0.020467428490519524,0,,
+1219,1872384,468.643952934,-0.005062882509082556,,0.02025286667048931,1,21.026992158964276,1000.0
+1220,1873920,469.038892563,-0.015510177131121357,,0.02048531547188759,0,,
+1221,1875456,469.46615529200005,-0.004318955571701129,,0.020404376089572906,0,,
+1222,1876992,469.8770588980001,-0.0026882124443848928,,0.020122619345784187,1,17.967602109187283,1000.0
+1223,1878528,470.202345435,-0.005006784976770481,,0.02012985572218895,0,,
+1224,1880064,470.54798003400003,-0.003720338207979997,,0.019981443881988525,1,15.818321906263009,1000.0
+1225,1881600,470.9222997620001,-0.005321773110578457,,0.020286977291107178,2,23.139187312917784,1000.0
+1226,1883136,471.2850749920001,-0.0007646487094461918,,0.02045736089348793,1,17.725960018113256,1000.0
+1227,1884672,471.69711689200005,-0.0062443090602755545,,0.020376509055495262,3,19.193415483110584,1000.0
+1228,1886208,472.06959917100005,-0.006965272780507803,,0.020649906247854233,1,25.328704487765208,1000.0
+1229,1887744,472.4036791760001,-0.0048335284305115545,,0.020893555134534836,0,,
+1230,1889280,472.7857048210001,-0.0032619623467326163,,0.02068537101149559,5,22.003087598539423,1000.0
+1231,1890816,473.152962173,-0.007880173902958632,,0.020811624825000763,4,22.592683561815647,1000.0
+1232,1892352,473.52949270400006,-0.004519199052204688,,0.020634714514017105,2,20.11978334141895,1000.0
+1233,1893888,473.95219177800004,-0.0029383705308039985,,0.020940542221069336,3,19.76297224299439,1000.0
+1234,1895424,474.30737597100006,-0.006908083598439892,,0.02106131613254547,3,20.475553698643733,1000.0
+1235,1896960,474.64538537600004,-0.0026282029536863166,,0.021068867295980453,0,,
+1236,1898496,474.992454405,0.003548584304129084,,0.020547382533550262,2,16.527135784504935,1000.0
+1237,1900032,475.32113046000006,-0.005603737694521745,,0.020871281623840332,1,17.713549996726215,1000.0
+1238,1901568,475.70987749000005,-0.004040722890446584,,0.021025754511356354,0,,
+1239,1903104,476.04254534200004,0.007648747088387609,,0.020968129858374596,1,17.432246530195698,1000.0
+1240,1904640,476.370771043,0.018009994396318993,,0.02010822482407093,3,21.20524209101374,882.6666666666666
+1241,1906176,476.719251945,-0.0010650939773768186,,0.02154254913330078,0,,
+1242,1907712,477.047255867,-0.002964652298639218,,0.021213993430137634,1,26.663961332291365,1000.0
+1243,1909248,477.41603850800004,0.0024433510998884836,,0.02097533643245697,1,30.00318135600537,1000.0
+1244,1910784,477.7874340540001,-0.006031060110156735,,0.02101706527173519,1,14.187896435963921,1000.0
+1245,1912320,478.12665947200003,-0.010172527128209671,,0.021021416410803795,2,22.04350920266006,1000.0
+1246,1913856,478.4959216110001,-0.0049100236967206,,0.021394502371549606,0,,
+1247,1915392,478.874541937,-0.006245972278217475,,0.021106328815221786,3,21.71974585639934,1000.0
+1248,1916928,479.379924682,-0.005493352267270287,,0.02159663289785385,2,20.669589718047064,1000.0
+1249,1918464,479.82509181600005,-0.008714888182779153,,0.021548068150877953,0,,
+1250,1920000,480.28743015400005,-0.000548647902905941,,0.021032821387052536,5,22.233360021398404,1000.0
+1251,1921536,480.77498090100005,-0.004504482230792443,,0.02143930457532406,1,18.873949523316696,1000.0
+1252,1923072,481.16251832,-0.011488307174295187,,0.0217108353972435,0,,
+1253,1924608,481.604623143,-0.0016527104501922925,,0.021420907229185104,4,18.06763179897098,1000.0
+1254,1926144,482.03832915400005,0.00015452733884255092,,0.021353647112846375,2,19.365590693196282,1000.0
+1255,1927680,482.44672201900005,-0.004003734700381756,,0.021561406552791595,0,,
+1256,1929216,482.8914111260001,0.00013624268273512523,,0.021382151171565056,2,17.97444788692519,1000.0
+1257,1930752,483.30647644400005,0.0015036169439554214,,0.02178267203271389,4,16.00453221279895,1000.0
+1258,1932288,483.765340969,-0.003225871765365203,,0.0221334770321846,1,15.519482708536088,1000.0
+1259,1933824,484.1732401290001,-0.004199013843511542,,0.021748675033450127,1,19.131840178277344,1000.0
+1260,1935360,484.58683060500005,-0.007707016899560889,,0.021622976288199425,0,,
+1261,1936896,485.04700050200006,-0.0053134342965980375,,0.021876487880945206,1,23.369609895162284,1000.0
+1262,1938432,485.432078865,-0.001549719568962852,,0.021637996658682823,0,,
+1263,1939968,485.8575583300001,-0.00794678955959777,,0.021818634122610092,0,,
+1264,1941504,486.2826299740001,-0.004581320549671849,,0.021645504981279373,1,16.945568468421698,1000.0
+1265,1943040,486.68163462300004,-0.006260061947007974,,0.022101718932390213,1,18.669422173174098,1000.0
+1266,1944576,487.05915627900004,-0.003156639821827412,,0.02184256725013256,0,,
+1267,1946112,487.48648181,-0.006946561237176259,,0.022081956267356873,2,26.778479858883657,1000.0
+1268,1947648,487.94020683400004,-0.005609095996866624,,0.021883897483348846,2,27.094250763300806,1000.0
+1269,1949184,488.33492802800004,0.0009418241369227568,,0.021987635642290115,2,17.621147037832998,1000.0
+1270,1950720,488.7676020050001,-0.0014616815683742364,,0.0221211276948452,1,26.005525214597583,1000.0
+1271,1952256,489.1956087450001,-0.009149862608561913,,0.0220792293548584,1,21.57131729600951,1000.0
+1272,1953792,489.6157841070001,-0.0027426470691959064,,0.022260015830397606,5,20.293361028283833,1000.0
+1273,1955328,490.06072141100003,-0.0072965608288844425,,0.022444751113653183,4,20.682596954982728,1000.0
+1274,1956864,490.42123684600006,-0.006523331611727675,,0.022328531369566917,1,27.360351284965873,1000.0
+1275,1958400,490.8879515650001,-0.002019753245015939,,0.022139107808470726,4,24.396764371864265,1000.0
+1276,1959936,491.3801329820001,-0.006204370874911547,,0.02189536951482296,2,18.742633874178864,1000.0
+1277,1961472,491.8454283440001,-0.004153085608656208,,0.02225126326084137,0,,
+1278,1963008,492.20695701500006,-0.0003880609137316545,,0.022134756669402122,2,21.6848416258581,1000.0
+1279,1964544,492.5706412090001,-0.0014880206435918808,,0.021682217717170715,1,27.738575467839837,1000.0
+1280,1966080,492.938472874,-0.007804990870257219,,0.021607529371976852,0,,
+1281,1967616,493.350530572,0.00022545385484894117,,0.021374037489295006,2,20.162962303322274,1000.0
+1282,1969152,493.7725889740001,-0.005758861095334093,,0.021733995527029037,2,21.46872467920184,1000.0
+1283,1970688,494.1422594510001,0.00044985742618640264,,0.021924704313278198,1,24.609815170057118,1000.0
+1284,1972224,494.53827506900006,-0.004652651616682609,,0.022086963057518005,1,20.85755082848482,1000.0
+1285,1973760,494.915210041,-0.0034063215833157303,,0.021618008613586426,1,16.352928888984025,1000.0
+1286,1975296,495.298918607,-0.0013769214196751515,,0.021670138463377953,2,26.69818651280366,1000.0
+1287,1976832,495.74420458400004,-0.0006602516397833825,,0.021661818027496338,0,,
+1288,1978368,496.12684267300006,-0.0014266757139315208,,0.021557137370109558,1,28.40094889467582,1000.0
+1289,1979904,496.567533174,-0.005250168001900117,,0.02175302617251873,2,21.54137371532852,1000.0
+1290,1981440,496.956322237,-0.0011147375063349804,,0.02178611233830452,2,24.39350888726767,1000.0
+1291,1982976,497.31351686900007,-0.002454360652094086,,0.02245187759399414,1,21.58751347742509,1000.0
+1292,1984512,497.70892335100007,-0.00019729463383555412,,0.02183458022773266,4,22.94384006175096,1000.0
+1293,1986048,498.049465875,0.0017513059079647063,,0.022113313898444176,1,27.677918003872037,1000.0
+1294,1987584,498.38724783200007,-0.0033879379741847517,,0.021733414381742477,2,16.954790593648795,1000.0
+1295,1989120,498.7377660640001,-0.005421806126832962,,0.022000765427947044,4,20.142369861976476,1000.0
+1296,1990656,499.07106941100005,-0.004110026856263479,,0.022341419011354446,0,,
+1297,1992192,499.384646749,-0.002289133208493392,,0.022258779034018517,0,,
+1298,1993728,499.794669966,-0.006214917171746492,,0.022112101316452026,5,21.718941678106784,1000.0
+1299,1995264,500.1293446100001,0.0038940323516726493,,0.022619640454649925,1,18.65307447500527,1000.0
+1300,1996800,500.4722657980001,0.007056911739831169,,0.022267833352088928,1,19.025497646071017,1000.0
+1301,1998336,500.86134512,0.016300021608670553,,0.021705834195017815,2,14.012712172290776,776.0
+1302,1999872,501.20416615700003,-4.624944801131884e-05,,0.021701013669371605,2,22.70781596453162,822.0
+1303,2001408,501.544272526,-0.00020990824947754542,,0.021770164370536804,0,,
+1304,2002944,501.93728222900006,0.002732554543763399,,0.02117091231048107,1,15.168710961937904,530.0
+1305,2004480,502.32396577500003,0.0015134364056090513,,0.021784504875540733,0,,
+1306,2006016,502.7545249750001,-0.0045874448803563915,,0.021450644358992577,1,22.55512648494914,1000.0
+1307,2007552,503.1734964430001,0.0029989019346733886,,0.021670076996088028,1,24.077652072533965,1000.0
+1308,2009088,503.61156901800007,0.008825637524326642,,0.021188553422689438,1,1.1971333904657513,68.0
+1309,2010624,503.98562424400006,0.012393938346455495,,0.02108038030564785,2,23.475058208452538,1000.0
+1310,2012160,504.331779277,-0.0008793576930960019,,0.02110634371638298,5,18.486196056590416,874.4
+1311,2013696,504.721451676,0.0014013641669104496,,0.021640701219439507,1,14.317067230585963,1000.0
+1312,2015232,505.073524154,0.00411842226361235,,0.0212140791118145,0,,
+1313,2016768,505.421004466,-0.003311786133175095,,0.020994264632463455,4,25.816607523564016,997.25
+1314,2018304,505.823459889,0.008420857228338718,,0.020852357149124146,4,20.40703114835196,901.75
+1315,2019840,506.17744793300005,-0.0027034017257392406,,0.0216506477445364,4,20.598557461664313,1000.0
+1316,2021376,506.555456919,0.0009224814362823963,,0.022030865773558617,2,20.957552453910466,1000.0
+1317,2022912,506.92841127400004,0.007441783448060354,,0.021758779883384705,1,17.26317456457764,1000.0
+1318,2024448,507.25952907600004,-0.002386602262655894,,0.021909242495894432,2,20.46306042908691,1000.0
+1319,2025984,507.6877491700001,-0.004111252833778659,,0.021550891920924187,1,6.212834227946587,224.0
+1320,2027520,508.042293739,-0.00127330565204223,,0.02197941020131111,1,17.98592511191964,1000.0
+1321,2029056,508.379475082,0.0012291274343927702,,0.022297978401184082,1,15.618099581508432,1000.0
+1322,2030592,508.74823085800006,-0.007119040361916026,,0.022207185626029968,0,,
+1323,2032128,509.112459952,-0.0023171504959464072,,0.021858520805835724,2,21.515240388107486,1000.0
+1324,2033664,509.4537171630001,0.001146186205248038,,0.02183651551604271,1,27.843223702162504,1000.0
+1325,2035200,509.83817580000004,-0.006820225218931834,,0.02094031684100628,2,22.453556329244748,939.5
+1326,2036736,510.178156243,0.013840441623081763,,0.020482152700424194,3,16.353094548995916,720.3333333333334
+1327,2038272,510.530708399,-0.0013252630674590667,,0.021355710923671722,2,9.347355198580772,532.5
+1328,2039808,510.89537606400006,-0.00515031237155199,,0.02139218896627426,2,15.249936835374683,1000.0
+1329,2041344,511.2214706750001,0.003089703821266691,,0.02170151099562645,0,,
+1330,2042880,511.5588613350001,-0.0011304846964776516,,0.0209331214427948,2,20.5221739821136,884.0
+1331,2044416,511.921609386,-0.0007614348704616229,,0.021772436797618866,0,,
+1332,2045952,512.2545121180001,0.0017675260392328103,,0.022018607705831528,1,27.34679689211771,1000.0
+1333,2047488,512.5943343710001,0.003078068963562449,,0.02136882394552231,3,24.696203521452844,1000.0
+1334,2049024,512.949267715,0.0006452401789526145,,0.021435998380184174,4,16.550832651526434,881.5
+1335,2050560,513.309921701,-0.0005198048738141854,,0.021581610664725304,1,9.684433835325763,340.0
+1336,2052096,513.7520379160001,-0.002952265366911888,,0.021884379908442497,1,19.952627240447327,1000.0
+1337,2053632,514.185094678,-0.0028499625933667023,,0.021596908569335938,4,21.071060237445636,1000.0
+1338,2055168,514.582942646,0.005117291118949652,,0.021683573722839355,0,,
+1339,2056704,514.9169139210001,0.006514099892228842,,0.02104697935283184,1,15.390289580100216,540.0
+1340,2058240,515.256069903,-0.0068068048761536675,,0.02148331329226494,5,24.961305722012185,1000.0
+1341,2059776,515.6279255970001,-0.0012889356662829717,,0.02193295583128929,1,13.956240432569757,1000.0
+1342,2061312,516.0119014,-0.001470415387302637,,0.021574079990386963,2,15.624478645273484,1000.0
+1343,2062848,516.342116713,-0.0009912547344962757,,0.021704718470573425,0,,
+1344,2064384,516.694472903,-0.006694224150851369,,0.022106587886810303,2,21.088659951812588,1000.0
+1345,2065920,517.04908803,-0.0030597192235291004,,0.0218280591070652,1,29.538174338056706,1000.0
+1346,2067456,517.3973124830001,-0.0024680844508111477,,0.021430879831314087,0,,
+1347,2068992,517.793629472,0.002187071709583203,,0.021423429250717163,1,18.579012255650014,659.0
+1348,2070528,518.174218943,0.005226297272990147,,0.021699920296669006,0,,
+1349,2072064,518.53104555,0.0020071607393523055,,0.02161221019923687,1,21.943999471026473,1000.0
+1350,2073600,518.8767542200001,0.005932406708598137,,0.021641384810209274,3,18.538137306032393,1000.0
+1351,2075136,519.218614342,-0.0025440883201857407,,0.02197319269180298,2,20.227017478086054,1000.0
+1352,2076672,519.5560374720001,0.0018173966401567063,,0.02190069854259491,2,20.05990915838629,1000.0
+1353,2078208,519.921192138,-0.006889644296218952,,0.021947257220745087,1,15.394009003182873,1000.0
+1354,2079744,520.281284452,-0.00731999147683382,,0.02208138257265091,0,,
+1355,2081280,520.628939736,-0.0019029613429059585,,0.022015485912561417,3,21.43852097079313,1000.0
+1356,2082816,520.9792630420001,0.0035636575582126775,,0.02204318344593048,5,26.748155193170533,1000.0
+1357,2084352,521.3088507470001,-0.001608323771506548,,0.022373244166374207,2,15.314148739504162,1000.0
+1358,2085888,521.683609529,0.005873717150340478,,0.02239980362355709,2,24.71271939034341,1000.0
+1359,2087424,522.040279852,0.001441410385693113,,0.021884536370635033,2,17.6969135463587,1000.0
+1360,2088960,522.3700229110001,0.007375333861758312,,0.02147514745593071,1,18.322087281383574,645.0
+1361,2090496,522.732313566,0.008290426588306825,,0.021544378250837326,1,21.319767221575603,1000.0
+1362,2092032,523.0676561470001,0.0014596359804272651,,0.021885555237531662,1,2.523428558371961,120.0
+1363,2093568,523.4009285090001,-0.00460997320090731,,0.021795926615595818,0,,
+1364,2095104,523.799531848,-0.003302083754291137,,0.0218639075756073,1,15.502972245274577,1000.0
+1365,2096640,524.2378759200001,-0.000517433291922013,,0.021787669509649277,1,21.011879250989296,1000.0
+1366,2098176,524.651407704,-0.0007690041946868102,,0.022525569424033165,0,,
+1367,2099712,525.061910613,0.0033988487906754018,,0.02197204902768135,3,25.527078195125796,1000.0
+1368,2101248,525.442475617,-0.004313567591210207,,0.02127952128648758,3,16.105903523624875,1000.0
+1369,2102784,525.856524811,-0.0015353580005466939,,0.022525541484355927,2,12.238890059583355,649.5
+1370,2104320,526.195757628,-0.007163804490119219,,0.02264709770679474,2,21.15547127899481,1000.0
+1371,2105856,526.549251256,-0.0007626245729625225,,0.02266044169664383,0,,
+1372,2107392,526.8972672130001,-0.0006238271482288838,,0.021338460966944695,4,20.537276822462445,823.0
+1373,2108928,527.247244644,0.004394930880516767,,0.02228483185172081,2,14.235620056744665,633.5
+1374,2110464,527.6016773810001,-0.00031113314131895703,,0.022448470816016197,0,,
+1375,2112000,527.9805529370001,0.006573139596730471,,0.022024713456630707,3,19.94082528783474,1000.0
+1376,2113536,528.332283758,0.004146097724636396,,0.022105634212493896,2,24.273176027694717,1000.0
+1377,2115072,528.707195789,-0.0041466770072778065,,0.02214115858078003,1,18.090763686806895,1000.0
+1378,2116608,529.106827545,-0.0007619295890132586,,0.021509259939193726,4,16.118532806023723,887.0
+1379,2118144,529.4587163250001,0.0032132285957535106,,0.021635835990309715,4,17.964327023597434,841.5
+1380,2119680,529.841403357,0.004424614769717058,,0.022218849509954453,1,7.320091559318826,267.0
+1381,2121216,530.1839141920001,0.00814165137708187,,0.02189192920923233,4,21.0169138967467,803.25
+1382,2122752,530.513274777,0.0011702347857256731,,0.022250622510910034,3,23.104429585703958,1000.0
+1383,2124288,530.8311954110001,-0.0002964814193546772,,0.022182118147611618,1,22.883691841736436,1000.0
+1384,2125824,531.180072911,0.0027767971778909365,,0.02161926031112671,3,17.904116899784032,797.3333333333334
+1385,2127360,531.5070095970001,0.00292417846309642,,0.021596048027276993,2,20.845071911171544,849.0
+1386,2128896,531.878797273,0.001061458388964335,,0.022046996280550957,1,22.717503704945557,1000.0
+1387,2130432,532.211334814,-0.0014360169880092144,,0.02213011309504509,0,,
+1388,2131968,532.603464966,-0.002367795103540023,,0.021689951419830322,1,26.60421520343516,989.0
+1389,2133504,532.960170886,0.004579586380471786,,0.02201070636510849,0,,
+1390,2135040,533.307035043,-0.0012762388369689385,,0.021679764613509178,1,26.57458903430961,1000.0
+1391,2136576,533.666796298,0.0055901175054411095,,0.02116083912551403,1,9.25051167618949,389.0
+1392,2138112,534.0459134710001,-0.001418246515095234,,0.021926140412688255,3,24.518603813291218,1000.0
+1393,2139648,534.42388222,0.0060538026659439,,0.021947329863905907,2,23.247664258640725,1000.0
+1394,2141184,534.7956282380001,0.0013868571259081364,,0.021856456995010376,2,19.235091510461643,1000.0
+1395,2142720,535.191754216,0.006697212889169653,,0.022482890635728836,1,16.414227212429978,1000.0
+1396,2144256,535.5849633810001,0.0007843926238516966,,0.022241761907935143,0,,
+1397,2145792,535.996352367,0.006758560333400965,,0.02194724977016449,2,20.575492910691537,1000.0
+1398,2147328,536.330648898,-0.007477290059129397,,0.022059237584471703,2,21.631731482979376,1000.0
+1399,2148864,536.6880685,0.0013228930532932282,,0.02240561693906784,0,,
+1400,2150400,537.042481339,-0.0020637847172717255,,0.022106479853391647,2,16.589005273854127,1000.0
+1401,2151936,537.382622015,-0.0032195915778477986,,0.022334596142172813,2,21.369115624169353,1000.0
+1402,2153472,537.7470079770001,-0.0003920679911971092,,0.02224108576774597,1,25.07715918845497,1000.0
+1403,2155008,538.112583911,0.001441625567773978,,0.02254553884267807,1,20.190819819341414,1000.0
+1404,2156544,538.43686,0.004961945799489816,,0.022616710513830185,0,,
+1405,2158080,538.774491474,0.006945656565949321,,0.022288281470537186,0,,
+1406,2159616,539.126988276,0.0033123464944461983,,0.022148314863443375,3,16.605195507174358,713.6666666666666
+1407,2161152,539.461205135,0.0008228432387113571,,0.022397605702280998,0,,
+1408,2162688,539.897475943,-0.005210043769329787,,0.022036787122488022,1,23.26422290597111,1000.0
+1409,2164224,540.286110977,0.0005282725207507611,,0.021538514643907547,4,16.723756099730963,916.0
+1410,2165760,540.641985503,0.00511653123733898,,0.022136718034744263,2,23.722346108290367,1000.0
+1411,2167296,540.981626023,0.0008824880545337995,,0.022051997482776642,2,23.495343677757774,1000.0
+1412,2168832,541.301103235,-0.0006662689149379731,,0.02169061079621315,0,,
+1413,2170368,541.64340904,0.007211463712155819,,0.02099430188536644,2,18.0311647245544,724.0
+1414,2171904,542.026513643,-0.005164979149897894,,0.0218966044485569,3,21.218798289230715,1000.0
+1415,2173440,542.345526306,-0.0016265736427158116,,0.022033659741282463,1,22.028251867042854,1000.0
+1416,2174976,542.683616841,-0.0012828200745085875,,0.022061452269554138,1,24.85025807050988,901.0
+1417,2176512,543.038337382,-0.00026849166800578436,,0.02133532427251339,2,17.802867481281282,1000.0
+1418,2178048,543.381904165,0.010989316056172054,,0.021055124700069427,5,21.145394422905518,793.4
+1419,2179584,543.7512890620001,-0.004413531130800645,,0.021813450381159782,1,21.1687094559893,1000.0
+1420,2181120,544.1470177870001,-0.0014363210337857404,,0.021565478295087814,6,20.021150872450864,1000.0
+1421,2182656,544.4768570890001,-0.003022412055482467,,0.0220622718334198,1,22.841532382648438,1000.0
+1422,2184192,544.847254803,0.006323495724548896,,0.022152496501803398,0,,
+1423,2185728,545.20384261,-0.0029050858536114293,,0.021314432844519615,5,22.65670564544853,1000.0
+1424,2187264,545.6102486020001,0.00290724594766895,,0.021963056176900864,1,18.575521292630583,1000.0
+1425,2188800,546.0534901560001,-0.0014381389133632182,,0.021795835345983505,1,28.334828024730086,1000.0
+1426,2190336,546.462588166,-0.0004820177642007669,,0.02124193124473095,4,19.982322755502537,850.5
+1427,2191872,546.906331471,-0.0028120562123755614,,0.022043442353606224,3,24.3010506623347,1000.0
+1428,2193408,547.2258353330001,0.006072603538632393,,0.021932370960712433,0,,
+1429,2194944,547.552926272,0.0013239647106577954,,0.021782655268907547,0,,
+1430,2196480,547.940281352,-0.006796770046154658,,0.021701490506529808,1,18.639661450870335,1000.0
+1431,2198016,548.285737112,0.00840997053310275,,0.02185640297830105,0,,
+1432,2199552,548.640262214,0.000668964379777511,,0.021726667881011963,1,21.6880496077938,1000.0
+1433,2201088,549.018981854,0.007992878369987012,,0.02164982259273529,2,22.070610609313007,1000.0
+1434,2202624,549.369874999,-0.0008691065013408661,,0.021445848047733307,2,26.65407372172922,1000.0
+1435,2204160,549.732881578,5.707239421705405e-05,,0.022056153044104576,3,16.91283608728554,1000.0
+1436,2205696,550.101767019,0.0013118301207820575,,0.022293053567409515,0,,
+1437,2207232,550.4355008150001,0.005930316836262743,,0.022367946803569794,1,12.401354790083133,558.0
+1438,2208768,550.8514598940001,0.006245643614480893,,0.022252902388572693,2,19.10462348087458,1000.0
+1439,2210304,551.203138105,0.001542382873594761,,0.021912403404712677,1,22.70904216519557,1000.0
+1440,2211840,551.528895347,-0.0031229855803151926,,0.0223850067704916,1,21.346117651555687,1000.0
+1441,2213376,551.919332915,0.006613352103158832,,0.022645972669124603,1,20.912875457666814,1000.0
+1442,2214912,552.2447546530001,0.00010583894327282905,,0.022222667932510376,0,,
+1443,2216448,552.575519567,-0.002346316957846284,,0.02243180200457573,2,22.924379361327738,1000.0
+1444,2217984,552.896941101,0.0020956149014333884,,0.02231607586145401,0,,
+1445,2219520,553.2269541510001,0.006070676445960999,,0.022464275360107422,1,17.027542459778488,1000.0
+1446,2221056,553.6111366150001,-0.00018019179503122966,,0.022498732432723045,0,,
+1447,2222592,553.984178205,0.0038063451026876765,,0.02218463271856308,1,18.798594544641674,1000.0
+1448,2224128,554.325010119,0.0031065980282922586,,0.02146497368812561,3,20.1885036797806,845.0
+1449,2225664,554.66992207,0.017089598843206964,,0.02178221568465233,1,16.23468515172135,681.0
+1450,2227200,555.012861304,0.00017327792011201382,,0.022119848057627678,2,18.533124883950222,1000.0
+1451,2228736,555.3515209860001,-0.0005183115291098754,,0.021587412804365158,2,15.389416425838135,1000.0
+1452,2230272,555.693949213,0.004797714824477831,,0.02171117067337036,2,23.358963778824545,1000.0
+1453,2231808,556.0780352740001,0.0007477087900042533,,0.02180137299001217,2,19.319027079443913,1000.0
+1454,2233344,556.4181457640001,-0.005638448925067981,,0.02160831168293953,0,,
+1455,2234880,556.8564624290001,0.0028487101352463167,,0.021534597501158714,2,28.667166385799646,1000.0
+1456,2236416,557.2495148620001,0.005149384091297785,,0.02170850895345211,2,21.95820154825924,1000.0
+1457,2237952,557.702440818,0.001121077345063289,,0.02160518988966942,1,30.65433265361935,1000.0
+1458,2239488,558.094778689,-0.001500496066485842,,0.021185997873544693,3,16.430817156331614,1000.0
+1459,2241024,558.4643624610001,-0.0016378226379553478,,0.021548738703131676,4,21.716362378327176,1000.0
+1460,2242560,558.848665473,0.0014137660153210163,,0.020999975502490997,2,17.11662135098595,723.0
+1461,2244096,559.18884848,-0.003260980204989513,,0.02176806330680847,1,24.046247711405158,1000.0
+1462,2245632,559.542864577,-0.0010162367795904478,,0.020785978063941002,5,20.905686714174227,1000.0
+1463,2247168,559.9286565790001,0.00608591747780641,,0.02039976231753826,1,16.728685774025507,1000.0
+1464,2248704,560.2837409780001,0.0035833291709423064,,0.02034800499677658,5,16.578526367153973,731.6
+1465,2250240,560.6316223900001,-0.001808065144966046,,0.020854411646723747,5,19.0765543930931,815.6
+1466,2251776,560.97708975,0.003917472080017129,,0.02178565412759781,1,29.205718360841274,1000.0
+1467,2253312,561.3570979790001,-0.0015512077137827874,,0.02118123695254326,2,25.63847776618786,1000.0
+1468,2254848,561.7152826590001,0.0050363132419685526,,0.021284237504005432,0,,
+1469,2256384,562.089462052,0.00437830351293087,,0.02098444104194641,4,17.630521361745195,776.75
+1470,2257920,562.423556595,0.001245732419192791,,0.021512683480978012,0,,
+1471,2259456,562.817462653,0.005714846681803465,,0.02122998610138893,1,14.748614035313949,1000.0
+1472,2260992,563.164342819,0.0018473976602156957,,0.02154449373483658,0,,
+1473,2262528,563.508204499,0.005315846173713604,,0.021696409210562706,0,,
+1474,2264064,563.8983241130001,0.0001555343313763539,,0.02182040363550186,2,19.693470333819278,1000.0
+1475,2265600,564.244083336,0.0003879252510766188,,0.021545328199863434,3,25.397239574580453,1000.0
+1476,2267136,564.597202345,-0.0037067036610096693,,0.021557262167334557,0,,
+1477,2268672,564.965659674,0.006045195522407691,,0.021063437685370445,2,25.891490878129844,1000.0
+1478,2270208,565.285758953,-0.0015679271581272283,,0.021265655755996704,1,20.643515083938837,1000.0
+1479,2271744,565.609927306,0.00413673659786582,,0.02133954130113125,0,,
+1480,2273280,565.986505251,-0.0034186199307441713,,0.021100863814353943,2,19.89322687149979,1000.0
+1481,2274816,566.3151816200001,-0.004622591100633145,,0.02114812657237053,2,27.87056792387739,1000.0
+1482,2276352,566.662372384,0.007338336948305368,,0.02149663120508194,0,,
+1483,2277888,567.016657299,0.009560061898082495,,0.02110871486365795,1,3.6031722049228847,211.0
+1484,2279424,567.426597722,0.0017984599495927494,,0.020916234701871872,2,16.410383572161663,1000.0
+1485,2280960,567.846778202,-0.002209398802369833,,0.021299943327903748,0,,
+1486,2282496,568.238558902,0.0036002120468765497,,0.020704006776213646,2,14.359972104604822,522.5
+1487,2284032,568.5659484930001,-0.005302385458101829,,0.020603902637958527,0,,
+1488,2285568,568.8961837630001,-0.0034299696640421947,,0.02113061212003231,0,,
+1489,2287104,569.228152185,0.0037885448895394803,,0.021267861127853394,2,17.53633170662215,1000.0
+1490,2288640,569.5778837080001,0.003174109322329362,,0.021301250904798508,3,19.955321188201196,1000.0
+1491,2290176,569.970443572,-0.0010174648215373358,,0.021641157567501068,0,,
+1492,2291712,570.368423248,0.003956755964706341,,0.021821431815624237,3,18.20386258699,1000.0
+1493,2293248,570.715066354,-0.003670001837114493,,0.021789904683828354,2,17.535466684028506,1000.0
+1494,2294784,571.066557189,-0.0029821176392336684,,0.021830467507243156,1,19.58818911993876,1000.0
+1495,2296320,571.426858335,0.0019434007816016674,,0.022270729765295982,2,15.816015121643431,1000.0
+1496,2297856,571.848327445,0.007131856928269068,,0.022375941276550293,0,,
+1497,2299392,572.222573473,0.0019858867240448792,,0.021940693259239197,3,24.3030432809998,1000.0
+1498,2300928,572.563503212,0.00039295867706338566,,0.02200189046561718,2,17.541296135575976,1000.0
+1499,2302464,572.926071761,-0.0011396364929775397,,0.021942518651485443,0,,
+1500,2304000,573.26885079,-0.00011646606338520845,,0.021333809942007065,3,21.0440135402993,1000.0
+1501,2305536,573.622795882,0.0031158373380700747,,0.02153729274868965,4,21.305099632634665,1000.0
+1502,2307072,574.0174379780001,0.004324875896175703,,0.02171177975833416,3,13.962737821935056,682.0
+1503,2308608,574.400819985,0.0009876587428152561,,0.02175639197230339,3,17.039558046342183,1000.0
+1504,2310144,574.7473393270001,-0.0008387540777524313,,0.021885929629206657,1,23.59134379157331,1000.0
+1505,2311680,575.1203950920001,-0.00046607706074913344,,0.021939240396022797,3,24.512816720758565,1000.0
+1506,2313216,575.451313434,0.0002742187740902106,,0.02123226225376129,3,24.214613060738582,1000.0
+1507,2314752,575.82329671,0.007974608335644007,,0.02044120989739895,5,23.87125428059371,983.6
+1508,2316288,576.179799474,0.0055446863019218045,,0.021287832409143448,1,15.513188128650654,1000.0
+1509,2317824,576.521173072,0.005925181570152442,,0.020996717736124992,3,15.731078087798474,687.3333333333334
+1510,2319360,576.8915493750001,0.008364555146545171,,0.021367549896240234,1,19.13137824740261,1000.0
+1511,2320896,577.225447421,0.0016650877892971038,,0.021170273423194885,2,25.12075891130371,1000.0
+1512,2322432,577.559572195,0.01164855429281791,,0.02145857736468315,0,,
+1513,2323968,578.011277263,0.0015165157460918029,,0.02106834203004837,1,30.002617459744215,1000.0
+1514,2325504,578.383875621,0.0037136740051209927,,0.02110641822218895,0,,
+1515,2327040,578.809259825,-0.0030671463813632728,,0.020838921889662743,1,21.3377919185441,1000.0
+1516,2328576,579.206176108,0.008220279154678186,,0.021143920719623566,0,,
+1517,2330112,579.5437373780001,0.0036702963523566725,,0.021122895181179047,3,22.27392679604236,1000.0
+1518,2331648,579.910090363,0.002718203142285347,,0.022035546600818634,0,,
+1519,2333184,580.2838267870001,-0.0015904578690727551,,0.0215594545006752,2,23.187977233785205,1000.0
+1520,2334720,580.6189124910001,0.0022946868867923815,,0.021825995296239853,1,16.852015218464658,1000.0
+1521,2336256,581.0231656450001,0.002041786257177591,,0.02228909358382225,0,,
+1522,2337792,581.3647365080001,0.0004442934257288774,,0.02196432463824749,2,15.978198932076339,1000.0
+1523,2339328,581.709922615,0.006801611961175998,,0.022501833736896515,2,30.309452020563185,1000.0
+1524,2340864,582.11522184,0.0016918537362168233,,0.021817870438098907,0,,
+1525,2342400,582.444661022,0.001307765208184719,,0.021694345399737358,1,14.070768276811577,1000.0
+1526,2343936,582.810318499,0.002077221249540647,,0.021884232759475708,1,14.544502679491416,1000.0
+1527,2345472,583.210235845,0.00844760686159134,,0.022191356867551804,0,,
+1528,2347008,583.57007737,-0.0018073847517371179,,0.02198370359838009,2,20.889655271195807,1000.0
+1529,2348544,583.92831031,0.005095986649394035,,0.022055990993976593,0,,
+1530,2350080,584.2783633920001,0.011129019937167564,,0.021800260990858078,0,,
+1531,2351616,584.6168292790001,-0.006586731318384409,,0.02159777842462063,4,24.469580961595057,1000.0
+1532,2353152,584.981785722,0.0024949070687095326,,0.021548423916101456,1,14.209181773476303,1000.0
+1533,2354688,585.3142215370001,0.0003643471437195937,,0.02248523198068142,1,28.156496400479227,1000.0
+1534,2356224,585.6580409850001,0.0032177045630911987,,0.021975714713335037,3,20.091393276466988,1000.0
+1535,2357760,586.0430368560001,0.001481437465796868,,0.021884262561798096,2,22.293204931542277,1000.0
+1536,2359296,586.3785705060001,-0.0017773687839508056,,0.02199721150100231,2,22.667686348606367,1000.0
+1537,2360832,586.721406182,0.0007930762755374113,,0.021754592657089233,0,,
+1538,2362368,587.082056437,0.005560950500269731,,0.02173629403114319,1,14.307117840042338,1000.0
+1539,2363904,587.443487129,-0.002614660623172919,,0.021497447043657303,3,17.4665280758248,1000.0
+1540,2365440,587.771247171,-0.004304472294946512,,0.021873321384191513,1,23.086039386224,1000.0
+1541,2366976,588.16008773,0.003881177119910717,,0.022206168621778488,0,,
+1542,2368512,588.503355404,0.002245973702520132,,0.02245042286813259,2,15.50598716858076,1000.0
+1543,2370048,588.91946365,0.0009784990300734837,,0.022193362936377525,7,22.766169749682636,1000.0
+1544,2371584,589.310106926,0.00260462968920668,,0.022292938083410263,1,17.73485012166202,1000.0
+1545,2373120,589.7215408330001,0.0021701651935776074,,0.022323807701468468,3,23.00145311684658,1000.0
+1546,2374656,590.1055308690001,0.008703227620571852,,0.022992461919784546,1,18.265774100087583,1000.0
+1547,2376192,590.444734528,0.0010585371249665816,,0.022626876831054688,3,23.148394100057583,1000.0
+1548,2377728,590.8471970500001,1.4338968321681023e-05,,0.022729117423295975,4,15.106711136264494,1000.0
+1549,2379264,591.184144015,-0.004022392847885688,,0.022771235555410385,2,25.874822095152922,1000.0
+1550,2380800,591.5371879090001,0.006828237511217594,,0.022408802062273026,2,26.46337129099993,1000.0
+1551,2382336,591.93715721,0.001185374427586794,,0.022307731211185455,2,21.87727195560001,1000.0
+1552,2383872,592.304356676,0.0028049416529635587,,0.02226356230676174,3,25.180302922031842,1000.0
+1553,2385408,592.6342177060001,0.001978538619975249,,0.02211250364780426,0,,
+1554,2386944,593.002277431,0.0030066837867101033,,0.022199522703886032,0,,
+1555,2388480,593.334030674,0.005088142553965251,,0.02198227494955063,1,15.63767343503423,1000.0
+1556,2390016,593.7182648510001,0.005230827505389849,,0.022104045376181602,0,,
+1557,2391552,594.111917014,0.002532763717075189,,0.02123171091079712,2,17.778300505073275,640.5
+1558,2393088,594.454873429,0.0005135105301936467,,0.021809956058859825,1,26.69889852916822,1000.0
+1559,2394624,594.8245684000001,-0.0003279661759734154,,0.0214694794267416,2,24.982080331188627,1000.0
+1560,2396160,595.163040755,0.0035375598818063736,,0.02189674787223339,2,23.455832144711167,1000.0
+1561,2397696,595.493267909,0.011237566048900286,,0.021726777777075768,0,,
+1562,2399232,595.851563066,0.008302681582669417,,0.022281896322965622,1,27.529890826437622,1000.0
+1563,2400768,596.228310179,0.004456089809536934,,0.021608665585517883,2,25.389394602680113,1000.0
+1564,2402304,596.573350039,0.005070869531482458,,0.021330054849386215,1,25.558660831302404,1000.0
+1565,2403840,596.9000548930001,0.004273252499600252,,0.02099696919322014,1,21.21133743831888,1000.0
+1566,2405376,597.2255802750001,0.0021414078151186307,,0.021471798419952393,1,20.922985343262553,1000.0
+1567,2406912,597.557705422,0.0010475103743374347,,0.02110125496983528,0,,
+1568,2408448,597.936504411,0.006601738448565205,,0.021174617111682892,1,22.508351719006896,1000.0
+1569,2409984,598.2775344280001,0.0007055381157745918,,0.021398454904556274,1,30.16989998338977,1000.0
+1570,2411520,598.616102695,0.007749485162397225,,0.021130889654159546,1,13.889082822017372,1000.0
+1571,2413056,599.058904265,0.01160410496716698,,0.020872965455055237,0,,
+1572,2414592,599.40383718,0.01330659786860148,,0.021005965769290924,2,18.05956575323944,731.0
+1573,2416128,599.838938521,0.002417055517435074,,0.021104520186781883,3,20.732380241854116,1000.0
+1574,2417664,600.259103922,0.005154082210113605,,0.021405350416898727,1,30.608026383444667,1000.0
+1575,2419200,600.657315949,-0.001994557057817777,,0.021003566682338715,2,20.77075786201749,1000.0
+1576,2420736,601.024608324,-0.00017674574628472327,,0.020930631086230278,2,16.309775595611427,1000.0
+1577,2422272,601.357849596,0.00931500179382662,,0.021790478378534317,2,17.942659237945918,1000.0
+1578,2423808,601.678159906,0.005466567445546388,,0.02124599739909172,2,25.297066671482753,1000.0
+1579,2425344,602.0624717750001,0.01121565888946255,,0.020805954933166504,1,9.497150326729752,344.0
+1580,2426880,602.392364047,-0.0004483126103878021,,0.021563930436968803,2,18.588504520623246,1000.0
+1581,2428416,602.770418498,0.0009410584655900797,,0.02079315483570099,2,26.185564564715605,1000.0
+1582,2429952,603.1463926700001,0.007311723536501328,,0.020790021866559982,2,13.181327714642975,546.5
+1583,2431488,603.5270749470001,0.0071978922622899216,,0.021324649453163147,2,21.372567889862694,1000.0
+1584,2433024,603.921677259,0.005562494229525328,,0.020996224135160446,4,20.399502905114787,1000.0
+1585,2434560,604.305591736,0.008499169194449981,,0.020973658189177513,3,18.63395971086963,1000.0
+1586,2436096,604.6800040720001,0.012727627561738094,,0.021004613488912582,2,14.592444830341265,659.0
+1587,2437632,605.071997104,-0.0011507794881860415,,0.021411245688796043,2,27.969397182634566,1000.0
+1588,2439168,605.393967627,-0.00033405773962537447,,0.021489616483449936,1,14.336800643242896,1000.0
+1589,2440704,605.738762445,-0.0002696974202990532,,0.021555593237280846,4,22.053425832709763,1000.0
+1590,2442240,606.120502064,0.0019064823165535927,,0.02165611833333969,5,19.68302765964763,1000.0
+1591,2443776,606.495235236,-0.0004554037315150102,,0.021968603134155273,1,18.251219684258103,1000.0
+1592,2445312,606.843415273,0.0014377654840548833,,0.02178821712732315,3,21.440033393912017,1000.0
+1593,2446848,607.212759493,0.0055433589654664195,,0.02162083052098751,0,,
+1594,2448384,607.530138372,0.011456574810047944,,0.02148713730275631,3,16.01560590493803,686.0
+1595,2449920,607.897539172,0.007069367387642463,,0.021981384605169296,0,,
+1596,2451456,608.245911061,0.004546145877490441,,0.021792639046907425,1,17.34886160539463,1000.0
+1597,2452992,608.5579406850001,0.0016601422801613807,,0.022079473361372948,0,,
+1598,2454528,608.88977235,0.004015021988501151,,0.022073794156312943,1,14.851823952631094,1000.0
+1599,2456064,609.215696971,0.0029755089432001113,,0.022281287238001823,1,18.38502977997996,1000.0
+1600,2457600,609.554296782,0.0018353712434569995,,0.02215922251343727,3,24.923662526882254,1000.0
+1601,2459136,609.927264623,0.0073435149776438875,,0.022137684747576714,0,,
+1602,2460672,610.302413974,0.01104952801639835,,0.021609771996736526,2,28.31782402098179,1000.0
+1603,2462208,610.6847289030001,0.0012245131966968378,,0.021641310304403305,1,22.968260613270104,1000.0
+1604,2463744,611.1387508580001,0.002804650055865447,,0.021564733237028122,0,,
+1605,2465280,611.512474548,0.006533868610858917,,0.021465500816702843,2,14.379757266957313,1000.0
+1606,2466816,611.870627742,0.001859969614694516,,0.022036008536815643,1,13.166639566770755,1000.0
+1607,2468352,612.257638841,0.0035334667811791104,,0.021870583295822144,0,,
+1608,2469888,612.60117104,0.0042977211065590385,,0.021986037492752075,1,14.517024556756951,1000.0
+1609,2471424,612.96833358,0.00011810610691706339,,0.021718867123126984,1,15.034565616748296,1000.0
+1610,2472960,613.305172305,0.006119117295990388,,0.022090554237365723,0,,
+1611,2474496,613.6379413760001,-0.0013813743988672891,,0.02166653983294964,2,18.485771104344167,1000.0
+1612,2476032,614.007743483,0.004903901399423679,,0.021969705820083618,0,,
+1613,2477568,614.3573661930001,0.008481286621342102,,0.021616308018565178,1,15.668346049496904,1000.0
+1614,2479104,614.69204018,0.008009356694916885,,0.021864891052246094,1,26.202322806464508,1000.0
+1615,2480640,615.128690751,0.005775596480816603,,0.02216857299208641,3,24.83071952701236,1000.0
+1616,2482176,615.527908336,0.005383547147115072,,0.02191990427672863,0,,
+1617,2483712,615.898132493,0.009404590881119172,,0.021924128755927086,3,20.180157884101693,1000.0
+1618,2485248,616.2642808930001,0.0006344044270614783,,0.021725617349147797,2,28.791811781935394,1000.0
+1619,2486784,616.587833499,0.0031480343701938787,,0.021756764501333237,1,19.03969441947993,1000.0
+1620,2488320,616.912945538,-0.0027698953325549763,,0.021433670073747635,1,19.47071710973978,1000.0
+1621,2489856,617.245834362,0.006554094205300013,,0.020899295806884766,2,12.37988695083186,520.0
+1622,2491392,617.586522853,0.004430110907802979,,0.02155870944261551,3,16.417587833828293,1000.0
+1623,2492928,617.938432099,0.0058956425016125046,,0.021685589104890823,2,25.129609736730345,1000.0
+1624,2494464,618.291785109,0.0003362892506023248,,0.02144443988800049,1,24.782860508770682,1000.0
+1625,2496000,618.6234405470001,0.0008959654408196608,,0.02107033133506775,2,27.984739699750207,1000.0
+1626,2497536,618.966030608,0.004622982380290826,,0.020814305171370506,4,26.146902912820224,1000.0
+1627,2499072,619.2996085430001,0.0036072533577680586,,0.019411688670516014,3,23.99949242155223,1000.0
+1628,2500608,619.656268298,0.009419038705527783,,0.020632361993193626,3,20.880344408234425,992.6666666666666
+1629,2502144,620.053849518,0.0104042482872804,,0.020990822464227676,1,15.639887880999595,1000.0
+1630,2503680,620.4237160140001,0.00747935085867842,,0.019910793751478195,4,21.900905397196766,969.25
+1631,2505216,620.759664831,0.008998432693382104,,0.020677193999290466,2,18.242379294533748,1000.0
+1632,2506752,621.18273935,0.010677168890833855,,0.020015424117445946,5,23.366024281922726,1000.0
+1633,2508288,621.574464452,0.008372087217867374,,0.0198771171271801,1,20.25659376103431,1000.0
+1634,2509824,622.0113323080001,0.005439697920034329,,0.019929420202970505,2,16.503146261704387,1000.0
+1635,2511360,622.379648738,0.0071209687429169815,,0.020492199808359146,1,25.989445285173133,1000.0
+1636,2512896,622.7097534100001,0.003994390647858381,,0.020213454961776733,1,19.065510447137058,1000.0
+1637,2514432,623.048562781,0.0071921447602411115,,0.019961407408118248,0,,
+1638,2515968,623.4127209220001,0.005358745188762744,,0.0204900112003088,1,27.825157801620662,1000.0
+1639,2517504,623.7322944040001,0.005385348138709863,,0.02026934176683426,0,,
+1640,2519040,624.120434389,0.005541067042698463,,0.020273951813578606,2,17.146767089143395,1000.0
+1641,2520576,624.473479656,0.00294598750770092,,0.021029308438301086,0,,
+1642,2522112,624.823303204,0.006252995195488135,,0.020423103123903275,3,25.318228810656972,1000.0
+1643,2523648,625.207452363,0.0010049424755076567,,0.021025508642196655,0,,
+1644,2525184,625.603012837,0.006311893463134766,,0.020396310836076736,2,18.402482337434776,1000.0
+1645,2526720,625.9709714610001,0.017438514499614637,,0.020902467891573906,1,15.905490584438667,1000.0
+1646,2528256,626.3244848950001,0.0014925613688925902,,0.020787067711353302,0,,
+1647,2529792,626.6483113410001,-0.0007522977888584137,,0.020663201808929443,2,18.643064113915898,1000.0
+1648,2531328,626.969568622,0.011837480620791515,,0.020699914544820786,1,25.626953162718564,1000.0
+1649,2532864,627.2885250960001,0.00983743475129207,,0.020610908046364784,0,,
+1650,2534400,627.6092196120001,0.002023175979653994,,0.020731637254357338,1,16.631832778686658,1000.0
+1651,2535936,627.955818504,0.006534508801996708,,0.020732644945383072,1,22.963899028487504,1000.0
+1652,2537472,628.324906356,0.006471040938049555,,0.02006685733795166,1,10.147177869454026,344.0
+1653,2539008,628.668176766,0.012067806192984183,,0.019963862374424934,3,16.13241189008113,849.0
+1654,2540544,628.9882319410001,0.0050955278488496935,,0.02043982967734337,0,,
+1655,2542080,629.3059338600001,0.017404466370741525,,0.02044779434800148,1,17.323018658789806,1000.0
+1656,2543616,629.6415178670001,0.009203409031033515,,0.020166100934147835,3,24.436334897764027,1000.0
+1657,2545152,630.00392475,0.006213851707677047,,0.020188454538583755,1,18.75093649455812,1000.0
+1658,2546688,630.3393279640001,-0.0032952678389847278,,0.020144788548350334,1,15.248148933518678,1000.0
+1659,2548224,630.681799652,0.0020031300373375416,,0.01992904394865036,3,16.30776272415339,1000.0
+1660,2549760,631.028130456,0.0006310799159109593,,0.020629776641726494,2,25.085848727612756,1000.0
+1661,2551296,631.3667036930001,0.004368914943188429,,0.02039712481200695,0,,
+1662,2552832,631.8248351880001,0.004302571651836237,,0.020185736939311028,1,23.40408315975219,1000.0
+1663,2554368,632.244565274,0.003134532552212477,,0.020240014418959618,2,18.49008718918776,1000.0
+1664,2555904,632.6412480810001,0.0027810698995987576,,0.020063932985067368,3,18.238051894896973,1000.0
+1665,2557440,632.990231557,0.0021355364782114825,,0.020154017955064774,2,24.721711032558233,1000.0
+1666,2558976,633.3118972230001,0.008205729381491741,,0.02097722887992859,0,,
+1667,2560512,633.643051924,0.006030694767832756,,0.021212831139564514,2,13.50079977279529,1000.0
+1668,2562048,634.041740127,0.0011343383851150671,,0.020790189504623413,7,19.789142209371285,1000.0
+1669,2563584,634.379538868,0.0037702215525011224,,0.022054418921470642,3,20.81858130649198,1000.0
+1670,2565120,634.721957095,0.011913986100504795,,0.021612808108329773,1,28.467082585208118,1000.0
+1671,2566656,635.07145733,0.009404983495672543,,0.0210808664560318,2,14.067340390465688,554.0
+1672,2568192,635.411497935,0.006443979684263468,,0.021002043038606644,3,21.498520866734907,1000.0
+1673,2569728,635.778888102,0.00573491125057141,,0.021233927458524704,4,16.199376305215992,1000.0
+1674,2571264,636.193452955,0.0008134752201537291,,0.021815527230501175,2,17.67071475321427,1000.0
+1675,2572800,636.579121578,0.008984652596215408,,0.021149767562747,1,21.201993610244244,1000.0
+1676,2574336,636.964923384,0.0052733996883034704,,0.02167820744216442,2,24.21675644913921,1000.0
+1677,2575872,637.3005073610001,0.009745115817834934,,0.0215955451130867,1,24.00593695999123,1000.0
+1678,2577408,637.6449897560001,0.008375601035853227,,0.021201562136411667,1,22.52340437658131,1000.0
+1679,2578944,638.000542591,0.009111105464398861,,0.02091105282306671,1,12.295613287948072,466.0
+1680,2580480,638.346508144,0.010493489416937033,,0.020983567461371422,0,,
+1681,2582016,638.679301265,0.006643259183814128,,0.021030191332101822,0,,
+1682,2583552,639.015284109,0.008280246704816818,,0.0204973965883255,2,25.063770664390177,1000.0
+1683,2585088,639.3500711180001,0.0012066687767704328,,0.02086198888719082,1,29.386377320159227,1000.0
+1684,2586624,639.67281772,0.0016107703559100628,,0.02070850506424904,2,17.561906065791845,1000.0
+1685,2588160,640.042878703,0.003407913943131765,,0.021162904798984528,2,18.324676566116977,1000.0
+1686,2589696,640.412633646,0.003662286388377349,,0.020910969004034996,0,,
+1687,2591232,640.740523302,0.011298671985665957,,0.02038857527077198,1,29.99342318624258,1000.0
+1688,2592768,641.1657817920001,0.011658358822266261,,0.01987152174115181,4,16.47527151106624,805.25
+1689,2594304,641.556233842,0.015189953334629535,,0.020873986184597015,1,14.452059733332135,1000.0
+1690,2595840,641.9003932930001,0.005378991800049941,,0.021241649985313416,0,,
+1691,2597376,642.287783996,0.0043329375175138315,,0.021063540130853653,1,28.316598201170564,1000.0
+1692,2598912,642.6651743150001,0.0019757260568439962,,0.02125369757413864,0,,
+1693,2600448,643.0852615040001,0.006582181341946125,,0.021178578957915306,1,24.08957610372454,1000.0
+1694,2601984,643.478068513,0.011151402567823729,,0.020752666518092155,2,15.758168855099939,1000.0
+1695,2603520,643.817754594,0.004914639331400394,,0.02108820341527462,2,19.6364727007458,1000.0
+1696,2605056,644.18334442,0.006057564355432987,,0.021326761692762375,0,,
+1697,2606592,644.518730029,0.011746392647425333,,0.021252527832984924,2,15.470446631981758,1000.0
+1698,2608128,644.867278099,0.013846133649349213,,0.021643929183483124,2,9.218112835253123,543.0
+1699,2609664,645.238451887,0.008518833325554927,,0.02166523039340973,1,21.083320724312216,1000.0
+1700,2611200,645.5892132070001,0.0028075509083767733,,0.0214848592877388,2,19.51025440005469,1000.0
+1701,2612736,645.9588855530001,0.010740046637753646,,0.021431390196084976,2,13.117794885649346,524.0
+1702,2614272,646.345229966,0.006334893840054671,,0.021228646859526634,2,22.392661781050265,1000.0
+1703,2615808,646.680158459,0.005972919861475626,,0.021649828180670738,0,,
+1704,2617344,647.0435066800001,0.009530857608964046,,0.02151332050561905,1,23.180377792101353,1000.0
+1705,2618880,647.441308174,0.0029075673781335356,,0.021451568230986595,3,16.88266540177089,1000.0
+1706,2620416,647.806192095,0.004607183299958706,,0.02216224931180477,2,16.049043419770896,1000.0
+1707,2621952,648.2231426860001,0.006921814723561208,,0.021292775869369507,2,28.47638891171664,1000.0
+1708,2623488,648.5734090230001,0.009721609018743037,,0.021425485610961914,1,27.744669917970896,1000.0
+1709,2625024,648.9553491700001,0.0076739756080011524,,0.02141464315354824,4,25.966590261552483,1000.0
+1710,2626560,649.38528454,0.015560629560301702,,0.021617785096168518,2,15.816558312857524,1000.0
+1711,2628096,649.7377227100001,0.01169277982165416,,0.021480156108736992,3,23.23838621020938,1000.0
+1712,2629632,650.130949656,0.013053148953864972,,0.021540237590670586,2,22.16558433813043,968.5
+1713,2631168,650.471891369,0.006447371033330759,,0.02178562432527542,2,17.1655149643193,1000.0
+1714,2632704,650.8134022490001,-0.0019916178037722907,,0.02190670371055603,3,17.978678032251384,1000.0
+1715,2634240,651.202561113,0.008775610383599997,,0.02189530059695244,5,22.135764930048026,1000.0
+1716,2635776,651.541833374,0.01543937080229322,,0.021943366155028343,1,19.712814931408502,1000.0
+1717,2637312,651.88384897,0.007655338384211063,,0.02168620191514492,2,23.820560200547334,1000.0
+1718,2638848,652.257800843,0.0041599818505346775,,0.021762091666460037,0,,
+1719,2640384,652.614864379,0.011115307671328385,,0.02179758809506893,2,17.427832134417258,1000.0
+1720,2641920,652.944990121,0.008533238588521877,,0.02201688103377819,1,15.106794484192505,1000.0
+1721,2643456,653.345745233,0.00879989800353845,,0.02233787439763546,0,,
+1722,2644992,653.741484959,0.011007749661803245,,0.02240932546555996,0,,
+1723,2646528,654.223902327,0.01245018777747949,,0.022370418533682823,1,17.38712317496538,1000.0
+1724,2648064,654.595543164,0.008391128852963448,,0.022593844681978226,1,18.72256720182486,1000.0
+1725,2649600,654.960358037,0.014824216129879157,,0.021708514541387558,4,23.97749774431577,972.25
+1726,2651136,655.338776627,0.006607181392610073,,0.022582506760954857,0,,
+1727,2652672,655.680482155,0.00431963074952364,,0.022091012448072433,2,16.115864153340226,1000.0
+1728,2654208,656.0495426260001,0.01767991781234741,,0.022115906700491905,1,25.120794691029005,1000.0
+1729,2655744,656.412073104,0.00881265103816986,,0.021700438112020493,1,25.53407801222056,1000.0
+1730,2657280,656.766674379,0.010342157570024331,,0.021131029352545738,2,21.067219118354842,999.0
+1731,2658816,657.153454861,0.004194528423249721,,0.021355729550123215,1,22.513363084639423,1000.0
+1732,2660352,657.558115337,0.006854648236185312,,0.021465357393026352,0,,
+1733,2661888,657.8895921980001,0.01043701395392418,,0.02131006494164467,1,24.102892650756985,1000.0
+1734,2663424,658.298970387,0.008185903448611498,,0.021393630653619766,1,18.068702063523233,1000.0
+1735,2664960,658.671057108,0.0100954823816816,,0.021360596641898155,0,,
+1736,2666496,659.025571718,0.00780817000195384,,0.021339386701583862,3,22.811171995320667,1000.0
+1737,2668032,659.351178986,0.005138329199204842,,0.021640969440340996,0,,
+1738,2669568,659.702540898,0.001117109941939513,,0.02146173268556595,1,25.063175588846207,1000.0
+1739,2671104,660.075174024,0.009943429753184319,,0.020668433979153633,2,21.90873092279071,791.5
+1740,2672640,660.4265356450001,0.007784578142066797,,0.02098350040614605,3,15.756941861046167,718.6666666666666
+1741,2674176,660.766223673,0.010107084084302187,,0.0214853435754776,0,,
+1742,2675712,661.110837237,0.007534683837244908,,0.02116374298930168,4,19.99092917595408,1000.0
+1743,2677248,661.450048312,0.0035164322704076766,,0.021610846742987633,1,20.19623485673219,1000.0
+1744,2678784,661.851681526,0.0054264160804450515,,0.021726038306951523,1,23.58133026305586,1000.0
+1745,2680320,662.2357218000001,0.010469100003441175,,0.02180953323841095,0,,
+1746,2681856,662.6191609370001,0.008399712760001421,,0.02170264534652233,2,21.2040900355787,1000.0
+1747,2683392,663.007474211,0.0025811489981909593,,0.022133946418762207,3,18.795990342584748,1000.0
+1748,2684928,663.367435965,0.012595761194825172,,0.02227751538157463,2,21.859662489965558,1000.0
+1749,2686464,663.747300362,0.007182573806494475,,0.022345416247844696,1,14.519096779986285,1000.0
+1750,2688000,664.189700083,0.015678519600381455,,0.02221807837486267,1,23.369504682719707,1000.0
+1751,2689536,664.610276643,0.012317480985075235,,0.021472154185175896,4,27.95199084050546,1000.0
+1752,2691072,665.0995586590001,0.01667452057202657,,0.021756647154688835,2,24.34552637086017,1000.0
+1753,2692608,665.6210285880001,0.0074997202803691225,,0.021149490028619766,4,24.299610994348768,1000.0
+1754,2694144,666.0728865660001,0.019271920466174684,,0.021270036697387695,2,18.962055110139772,1000.0
+1755,2695680,666.4681999730001,0.00740028585617741,,0.021424002945423126,3,21.887237112037838,1000.0
+1756,2697216,666.885743451,0.010218488425016404,,0.021704530343413353,1,19.336498497985303,1000.0
+1757,2698752,667.2536542050001,0.0049884547169009846,,0.021383285522460938,4,21.90077604856924,1000.0
+1758,2700288,667.602725778,0.006340061997373899,,0.021497037261724472,1,17.321901406045072,1000.0
+1759,2701824,667.996855735,0.0016769818651179472,,0.021070554852485657,2,19.471592212619726,1000.0
+1760,2703360,668.3968908730001,0.011238923606773218,,0.021586423739790916,1,19.832691687974147,1000.0
+1761,2704896,668.761831591,0.014465794898569584,,0.021391507238149643,1,13.328903295681812,1000.0
+1762,2706432,669.1566330320001,0.005877307802438736,,0.02177569270133972,1,24.412790055386722,1000.0
+1763,2707968,669.5027091540001,0.012251150545974572,,0.0220978744328022,0,,
+1764,2709504,669.9682338370001,0.01325118684520324,,0.021696552634239197,0,,
+1765,2711040,670.367095003,0.004682505130767822,,0.02185976505279541,2,28.37717945408076,1000.0
+1766,2712576,670.70807686,0.0023502614349126816,,0.022134777158498764,0,,
+1767,2714112,671.0669863500001,0.00829757001871864,,0.02200888842344284,4,22.166429673758103,1000.0
+1768,2715648,671.403410748,0.009793122795720895,,0.02239760011434555,0,,
+1769,2717184,671.7530425450001,0.014000151616831621,,0.02221730351448059,2,18.32761101529468,1000.0
+1770,2718720,672.1622867780001,0.007030961693574985,,0.021994348615407944,1,17.130247651599348,1000.0
+1771,2720256,672.500964082,0.01866854956994454,,0.022223880514502525,2,17.096792124211788,1000.0
+1772,2721792,672.842619474,0.006071878162523111,,0.02214796468615532,1,14.936453345697373,1000.0
+1773,2723328,673.180231421,0.013670059821257989,,0.022905176505446434,1,16.812274150783196,1000.0
+1774,2724864,673.5103841050001,0.0004907706752419472,,0.022825686261057854,0,,
+1775,2726400,673.847505383,0.00869470148657759,,0.022454116493463516,0,,
+1776,2727936,674.244922933,0.012811161143084367,,0.022688444703817368,1,15.287782564526424,1000.0
+1777,2729472,674.583086986,0.01099322633817792,,0.022521834820508957,1,20.723434813320637,1000.0
+1778,2731008,674.931095127,0.009262061926225822,,0.022659434005618095,2,27.93699685455067,1000.0
+1779,2732544,675.274571928,0.0057218497308592,,0.022299787029623985,0,,
+1780,2734080,675.64220233,0.015523114024351041,,0.022207140922546387,1,23.047406677156687,1000.0
+1781,2735616,676.118787796,0.006759661032507817,,0.02219930663704872,4,19.224837639485486,1000.0
+1782,2737152,676.5813438700001,0.006149942241609097,,0.022344455122947693,1,29.975604271516204,1000.0
+1783,2738688,676.9857322400001,0.0226517832527558,,0.022097311913967133,1,24.888438996858895,1000.0
+1784,2740224,677.36584784,0.020676034906258186,,0.021511312574148178,4,18.19868504020269,789.0
+1785,2741760,677.716435527,0.01106174299493432,,0.022448888048529625,2,29.70221187453717,1000.0
+1786,2743296,678.099248065,0.0038032517458001774,,0.021784087643027306,0,,
+1787,2744832,678.473595085,0.014110736393680176,,0.021668052300810814,2,10.142571274016518,524.0
+1788,2746368,678.812680332,0.006379520986229181,,0.021889712661504745,2,21.18335503723938,1000.0
+1789,2747904,679.220136849,0.006882568231473366,,0.02158038318157196,3,24.086527805038106,1000.0
+1790,2749440,679.580110327,0.015893823311974604,,0.021822279319167137,2,18.71512142539723,1000.0
+1791,2750976,679.92090524,0.014466090376178424,,0.02171451970934868,0,,
+1792,2752512,680.339473758,0.006558065457890431,,0.021514270454645157,1,20.100970650091767,1000.0
+1793,2754048,680.750922636,0.011664238882561524,,0.021906612440943718,6,19.443891554585814,1000.0
+1794,2755584,681.1983564770001,0.006848657503724098,,0.022266810759902,4,14.750144908874063,762.0
+1795,2757120,681.56876466,0.012501218045751253,,0.021856144070625305,2,22.54960686195409,1000.0
+1796,2758656,681.905846803,0.007858895075817903,,0.022082535549998283,2,26.77371152024716,1000.0
+1797,2760192,682.3409449090001,0.005005118561287721,,0.021973922848701477,3,22.36072901461739,1000.0
+1798,2761728,682.730155111,0.021195414693405232,,0.022100944072008133,2,21.711534143658355,1000.0
+1799,2763264,683.088504712,0.02181298385063807,,0.021862581372261047,2,24.12675992870936,1000.0
+1800,2764800,683.424766182,0.00961311546464761,,0.021971097216010094,1,20.935233407304622,1000.0
+1801,2766336,683.7682225140001,0.013725083942214647,,0.021579410880804062,2,23.001066546712536,1000.0
+1802,2767872,684.1291247500001,0.008685995017488797,,0.02140132151544094,1,27.9352476275526,1000.0
+1803,2769408,684.4658251200001,0.005566611917068561,,0.021253010258078575,1,24.00337335851509,1000.0
+1804,2770944,684.817379745,0.00711590244124333,,0.021077081561088562,1,27.965305813529994,1000.0
+1805,2772480,685.19041427,0.009444085446496804,,0.021229756996035576,0,,
+1806,2774016,685.5499694250001,0.009952944982796908,,0.02069247141480446,1,0.9714278582250699,54.0
+1807,2775552,685.896195131,0.008628923632204532,,0.020870905369520187,2,23.25495626492193,1000.0
+1808,2777088,686.2806158430001,0.005898942922552427,,0.02070634439587593,1,24.691229014424607,1000.0
+1809,2778624,686.668793842,0.009953638010968765,,0.021141644567251205,3,22.938047064157825,1000.0
+1810,2780160,687.1306226190001,0.012317714840173721,,0.02095721662044525,2,16.233431529602967,1000.0
+1811,2781696,687.5302913620001,0.005312444424877564,,0.021026765927672386,0,,
+1812,2783232,687.9438199580001,0.011423159235467514,,0.020793434232473373,1,21.287957384251058,1000.0
+1813,2784768,688.339425129,0.025431672018021344,,0.02000012807548046,4,19.830778748291777,924.75
+1814,2786304,688.687894322,0.011255595181137324,,0.020648576319217682,1,24.485850885510445,1000.0
+1815,2787840,689.050829836,0.009782726938525835,,0.020887723192572594,0,,
+1816,2789376,689.417335521,0.006498235215743383,,0.02080412581562996,0,,
+1817,2790912,689.7520310460001,0.01325019020587206,,0.020762233063578606,0,,
+1818,2792448,690.121247553,0.007973316808541615,,0.020581018179655075,1,19.729005424655043,1000.0
+1819,2793984,690.504040465,0.008917009457945824,,0.020877813920378685,1,14.64403082150966,1000.0
+1820,2795520,690.857721136,0.0068723072297871115,,0.020766329020261765,1,27.617191039025784,1000.0
+1821,2797056,691.250197292,0.013174641349663337,,0.020770598202943802,0,,
+1822,2798592,691.605718087,0.009851280103127162,,0.020510897040367126,2,25.796752829337493,1000.0
+1823,2800128,691.971839053,0.0006412274514635403,,0.021005645394325256,4,18.574168460909277,1000.0
+1824,2801664,692.364953427,0.013207599675903717,,0.02159770391881466,0,,
+1825,2803200,692.704968705,0.009778037760406732,,0.021085409447550774,3,24.896831657039,1000.0
+1826,2804736,693.071923479,0.007452566207696994,,0.02087528072297573,1,18.658936428953893,1000.0
+1827,2806272,693.466386647,0.009613875858485698,,0.021363787353038788,1,20.023721620207652,1000.0
+1828,2807808,693.8138597740001,0.007370168715715409,,0.020708676427602768,0,,
+1829,2809344,694.2159838590001,0.006927420354137818,,0.02062181383371353,2,24.292891270451946,1000.0
+1830,2810880,694.579661328,0.004332737562557061,,0.020614704117178917,3,17.78723335894756,1000.0
+1831,2812416,694.95618528,0.010761888604611159,,0.0209491029381752,2,20.332067918614484,1000.0
+1832,2813952,695.3250661210001,0.004995339146504799,,0.020770128816366196,2,21.375194587744772,1000.0
+1833,2815488,695.662350808,0.008135613395522039,,0.020832521840929985,0,,
+1834,2817024,696.0144645930001,0.007225631643086672,,0.020395508036017418,4,21.993698570877314,1000.0
+1835,2818560,696.451210609,0.016225661803036927,,0.020549578592181206,3,21.68987698298103,1000.0
+1836,2820096,696.8375819160001,0.005116585828363896,,0.02093416079878807,3,18.103318352523882,1000.0
+1837,2821632,697.2394539620001,0.008331764085839192,,0.020934611558914185,2,23.64039706310723,1000.0
+1838,2823168,697.5912383140001,0.013872169610112905,,0.020800234749913216,2,25.07020167732844,1000.0
+1839,2824704,698.028356194,0.0041125772520899774,,0.021529747173190117,3,17.12403937118749,1000.0
+1840,2826240,698.490167667,0.007208653477331003,,0.02102242037653923,4,20.52453099572449,1000.0
+1841,2827776,698.9661971930001,0.007282821399470171,,0.021129515022039413,1,17.664790765498765,1000.0
+1842,2829312,699.343729936,0.0047454020629326505,,0.020701516419649124,2,21.92534903914202,1000.0
+1843,2830848,699.6970559360001,0.013305253318200509,,0.020924564450979233,1,8.276815802440979,323.0
+1844,2832384,700.0601431380001,0.015786195204903684,,0.021501129493117332,2,14.635495611117221,1000.0
+1845,2833920,700.4751202770001,0.01236102965970834,,0.021293675526976585,0,,
+1846,2835456,700.833159559,0.014856665177891653,,0.021151814609766006,0,,
+1847,2836992,701.201064846,0.01570450762907664,,0.02115505002439022,0,,
+1848,2838528,701.54042298,0.012855402131875356,,0.021125448867678642,2,27.91492940345779,1000.0
+1849,2840064,701.8691523880001,0.008990169440706571,,0.021120553836226463,1,18.484323696698993,1000.0
+1850,2841600,702.2638925020001,0.013731935992836952,,0.020836573094129562,4,23.073715413513128,1000.0
+1851,2843136,702.583680922,0.005478261318057775,,0.021210556849837303,0,,
+1852,2844672,702.970352659,0.004082191549241543,,0.021358508616685867,2,17.30271611380158,1000.0
+1853,2846208,703.374549753,0.005950647375235955,,0.021058108657598495,1,29.533345131203532,1000.0
+1854,2847744,703.71858123,0.0069998617594440775,,0.0212953370064497,1,16.038383980398066,1000.0
+1855,2849280,704.118141409,0.006712783873081207,,0.02105649933218956,3,19.277553885321442,1000.0
+1856,2850816,704.466732995,0.01229124516248703,,0.02148696407675743,1,19.098268219502643,1000.0
+1857,2852352,704.783867471,0.010229435252646605,,0.0214996337890625,0,,
+1858,2853888,705.121165775,0.009920175994435947,,0.021190477535128593,0,,
+1859,2855424,705.467777835,0.009681254687408606,,0.02107834815979004,1,16.3542825205368,1000.0
+1860,2856960,705.788693701,0.017657837582131228,,0.021261265501379967,0,,
+1861,2858496,706.1737323250001,0.020821432676166297,,0.021275311708450317,2,16.72814586025197,1000.0
+1862,2860032,706.511144265,0.01552291763946414,,0.021629659458994865,0,,
+1863,2861568,706.830175714,0.010198913328349591,,0.020680511370301247,1,27.048742417246103,1000.0
+1864,2863104,707.2499438450001,0.009694791429986556,,0.021169280633330345,2,22.514724009204656,1000.0
+1865,2864640,707.587742247,0.003760291108240684,,0.021502269431948662,3,25.77237105493744,1000.0
+1866,2866176,707.910825425,0.0025780545237163704,,0.021990634500980377,0,,
+1867,2867712,708.3103931200001,0.014069042541086674,,0.021384786814451218,4,18.14017949765548,1000.0
+1868,2869248,708.662409562,0.010815391472230354,,0.021699106320738792,1,18.476174119859934,1000.0
+1869,2870784,709.073436282,0.021886056133856375,,0.021770719438791275,1,-0.07820819935295731,50.0
+1870,2872320,709.471050999,0.010815739911049605,,0.02181915007531643,0,,
+1871,2873856,709.874668249,0.01256969477981329,,0.02174563705921173,2,20.196719621308148,1000.0
+1872,2875392,710.263934339,0.0030845060013234616,,0.02200506627559662,3,18.647393540168803,1000.0
+1873,2876928,710.6108274400001,0.009919963466624418,,0.02155381441116333,2,21.70433187345043,1000.0
+1874,2878464,710.932269152,0.011855863593518734,,0.02197335660457611,1,14.546062672277912,1000.0
+1875,2880000,711.29065487,0.009480751492083073,,0.021767448633909225,0,,
+1876,2881536,711.6601451490001,0.008252532842258612,,0.021803168579936028,4,22.226568439014954,1000.0
+1877,2883072,712.020523992,0.008042251473913591,,0.021374819800257683,3,23.53353446512483,1000.0
+1878,2884608,712.4144212900001,-0.002594537039597829,,0.021407440304756165,4,25.065432308241725,1000.0
+1879,2886144,712.767687701,0.006114952452480793,,0.02169000171124935,2,24.07888029993046,1000.0
+1880,2887680,713.115346053,0.007005997964491447,,0.02249005064368248,3,21.886599055995855,1000.0
+1881,2889216,713.4737858770001,0.007244104488442342,,0.02163681946694851,1,22.912100745365024,1000.0
+1882,2890752,713.833999791,0.01241118044902881,,0.02133844792842865,4,18.76463302061893,1000.0
+1883,2892288,714.2263410950001,0.011689527456959089,,0.02258850261569023,1,21.22198469855357,1000.0
+1884,2893824,714.571153568,0.005649698215226332,,0.021877165883779526,2,21.78463417198509,1000.0
+1885,2895360,714.908181462,0.005967243108898401,,0.022346574813127518,2,19.512982938846108,1000.0
+1886,2896896,715.2394278490001,0.007788162243862947,,0.022040586918592453,1,14.000436049886048,1000.0
+1887,2898432,715.558078767,0.004940804063032071,,0.022518973797559738,0,,
+1888,2899968,715.879139781,0.00988553169493874,,0.022234968841075897,0,,
+1889,2901504,716.274708475,0.01517825536429882,,0.022274911403656006,1,15.775974591379054,1000.0
+1890,2903040,716.628130294,0.0015190621527532736,,0.02238394320011139,2,23.41296492575202,1000.0
+1891,2904576,716.9589726610001,0.006383840863903364,,0.02280827984213829,0,,
+1892,2906112,717.33893671,0.032455174066126344,,0.022589951753616333,5,19.465014045638963,858.0
+1893,2907648,717.7303631110001,0.011265125187734763,,0.02351299673318863,0,,
+1894,2909184,718.149505418,0.014943000705291828,,0.022832978516817093,2,19.443963948637247,1000.0
+1895,2910720,718.526529231,0.012279615240792434,,0.02344740554690361,1,29.664455734193325,1000.0
+1896,2912256,718.8584053000001,0.009234616781274478,,0.023568045347929,2,22.52729803766124,1000.0
+1897,2913792,719.228427916,0.01620650083447496,,0.022838642820715904,2,17.850075681781163,1000.0
+1898,2915328,719.643793502,0.020335113226125637,,0.02287796139717102,2,22.548999833175912,896.5
+1899,2916864,720.198059442,0.01599183048432072,,0.022696729749441147,1,21.621686122147366,942.0
+1900,2918400,720.627567536,0.008908835488061111,,0.02273060753941536,1,3.8451476860791445,145.0
+1901,2919936,721.014245724,0.007168603595346212,,0.022511852905154228,0,,
+1902,2921472,721.4199656970001,0.009420228594293197,,0.02209106832742691,1,0.3093790003331378,50.0
+1903,2923008,721.8097976580001,0.007021172561993202,,0.02204759418964386,2,23.09518335724715,1000.0
+1904,2924544,722.1568752190001,0.006774653090784947,,0.021658649668097496,1,19.581518813269213,677.0
+1905,2926080,722.514655723,0.01371302204206586,,0.022180192172527313,1,23.376979258842766,1000.0
+1906,2927616,722.876663222,0.00606355524311463,,0.021193087100982666,3,24.354989103313226,1000.0
+1907,2929152,723.265185041,0.0056517806525031725,,0.021666361019015312,1,22.449109899811447,1000.0
+1908,2930688,723.646371801,0.009923925623297691,,0.02150340937077999,0,,
+1909,2932224,724.0552221380001,0.019246267868826786,,0.020521393045783043,4,20.15869450138416,854.75
+1910,2933760,724.469677204,0.009312432538717986,,0.02108512446284294,2,20.548887219745666,1000.0
+1911,2935296,724.845518865,0.017030330592145523,,0.021117087453603745,2,12.35315524978796,497.0
+1912,2936832,725.283099041,0.012305871397256852,,0.021882710978388786,2,17.37942239549011,1000.0
+1913,2938368,725.6417246760001,0.00870643484716614,,0.021488573402166367,2,8.9223701832816,532.0
+1914,2939904,726.029655064,0.013721175429721674,,0.02203969471156597,4,15.869908545850194,823.0
+1915,2941440,726.439379902,0.015163281156371037,,0.022121181711554527,2,23.54672820039559,1000.0
+1916,2942976,726.78529398,0.004195932454119126,,0.022427033632993698,0,,
+1917,2944512,727.271506585,0.006569666477541129,,0.022510826587677002,0,,
+1918,2946048,727.776097967,0.006921930859486262,,0.022516552358865738,5,19.56849268687656,1000.0
+1919,2947584,728.267875901,0.003670704085379839,,0.022508975118398666,3,20.12338320185275,1000.0
+1920,2949120,728.6640147510001,0.005688936728984117,,0.022895624861121178,2,22.548988438618835,1000.0
+1921,2950656,728.9998933950001,0.008668530359864235,,0.022605350241065025,2,22.05792532954365,1000.0
+1922,2952192,729.398244553,0.004701348549375931,,0.022009704262018204,4,12.184654648473952,619.75
+1923,2953728,729.728727269,0.005590566744407018,,0.02228843793272972,2,26.83006818278227,1000.0
+1924,2955264,730.1190056930001,0.007013566636790832,,0.022593099623918533,2,27.186946809350047,1000.0
+1925,2956800,730.525902831,0.012315216412146886,,0.021394168958067894,2,20.10687577034696,829.0
+1926,2958336,730.9668164750001,0.01844096202403307,,0.02135748416185379,4,20.60415122998529,783.75
+1927,2959872,731.4022295750001,0.013480911186585823,,0.02117730677127838,2,17.37908217869699,654.0
+1928,2961408,731.8658020710001,0.011408510183294614,,0.02133133076131344,1,24.216564470902085,1000.0
+1929,2962944,732.249630412,0.01991310917461912,,0.020238902419805527,2,14.053622879495379,588.0
+1930,2964480,732.6176379670001,0.005219918551544348,,0.02117844484746456,0,,
+1931,2966016,733.004882926,0.00581896190221111,,0.021165117621421814,2,21.436222934222315,966.5
+1932,2967552,733.37676078,0.0075531771406531336,,0.02119319513440132,1,30.758917483501136,1000.0
+1933,2969088,733.705590718,0.0073279469584425294,,0.020980462431907654,1,15.351647942792624,575.0
+1934,2970624,734.0438385470001,0.010353510299076637,,0.020850006490945816,3,20.677565991374042,1000.0
+1935,2972160,734.419728277,0.004291883483529091,,0.021364359185099602,1,16.890742234070785,1000.0
+1936,2973696,734.741494341,0.005226407169053952,,0.020957155153155327,0,,
+1937,2975232,735.0953172190001,0.008256042841821909,,0.021249689161777496,1,24.253972142003477,1000.0
+1938,2976768,735.721021341,0.004584419603149096,,0.020600490272045135,4,22.544092767115217,1000.0
+1939,2978304,736.23337173,0.0037316731177270412,,0.021457303315401077,1,13.833518521627411,1000.0
+1940,2979840,736.7340294300001,0.010293259657919407,,0.021121390163898468,1,23.663639046251774,1000.0
+1941,2981376,737.149798322,0.01278738050411145,,0.021337836980819702,0,,
+1942,2982912,737.620236052,0.009817545488476753,,0.021341262385249138,1,6.48328597494401,272.0
+1943,2984448,738.021703356,0.011132761028905709,,0.021293099969625473,0,,
+1944,2985984,738.5424864070001,0.007361207188417514,,0.021104691550135612,2,11.708007734036073,729.5
+1945,2987520,738.9968404240001,0.00473505708699425,,0.021986033767461777,0,,
+1946,2989056,739.3356891980001,0.012168994545936585,,0.021237783133983612,1,14.952039138413966,1000.0
+1947,2990592,739.710802124,0.01212318285057942,,0.022091029211878777,2,21.58818048867397,1000.0
+1948,2992128,740.1123440580001,0.017779312438021104,,0.022445116192102432,3,20.489195428749856,1000.0
+1949,2993664,740.5057662490001,0.006544029278059801,,0.022155042737722397,0,,
+1950,2995200,740.941327335,0.014442460269977649,,0.021972257643938065,2,15.682495254441164,1000.0
+1951,2996736,741.3133565720001,0.004592592393358548,,0.022188162431120872,0,,
+1952,2998272,741.701747878,0.00999103644862771,,0.02169061452150345,1,13.650761419441551,1000.0
+1953,2999808,742.2164152600001,0.007189587286363045,,0.0221521258354187,2,23.424781358335167,1000.0
+1954,3001344,742.662630709,-0.0017215181762973467,,0.02180931717157364,2,28.861675917811226,1000.0
+1955,3002880,743.1393160270001,0.002049808669835329,,0.021979141980409622,2,16.797199883731082,1000.0
+1956,3004416,743.522043789,0.0076874111468593275,,0.021712973713874817,3,19.49590459097332,1000.0
+1957,3005952,743.846913997,0.0023750764938692253,,0.021832242608070374,1,21.412921427749097,1000.0
+1958,3007488,744.214961335,0.012192034566154083,,0.021815776824951172,0,,
+1959,3009024,744.6607250630001,0.009001391070584456,,0.02182026021182537,3,21.7403691932559,1000.0
+1960,3010560,745.082831659,0.012148480241497358,,0.021612465381622314,3,23.50412518189599,1000.0
+1961,3012096,745.523048754,0.004295356944203377,,0.02155655436217785,1,22.697120122611523,1000.0
+1962,3013632,745.9791059590001,0.008574361478288968,,0.021980492398142815,1,27.684690988622606,1000.0
+1963,3015168,746.446008249,0.00238057067617774,,0.02139316312968731,3,24.835063246039983,1000.0
+1964,3016704,746.909173943,0.00905080878486236,,0.021658187732100487,3,17.654334984874975,1000.0
+1965,3018240,747.336211614,0.003818702915062507,,0.021648306399583817,4,25.91089113272028,1000.0
+1966,3019776,747.690295609,0.00586885151763757,,0.02156953513622284,1,19.299582982435822,1000.0
+1967,3021312,748.0365499190001,0.008649256887535255,,0.021299030631780624,3,21.151695670676418,1000.0
+1968,3022848,748.420965793,0.00788691807538271,,0.02107301913201809,2,18.4462677675765,1000.0
+1969,3024384,748.8349278970001,0.010747580664853255,,0.020918797701597214,3,15.041770676344944,813.6666666666666
+1970,3025920,749.2302211560001,0.005237803670267264,,0.02143719792366028,0,,
+1971,3027456,749.653379342,0.017777125599483648,,0.02201593481004238,2,26.73317475320073,1000.0
+1972,3028992,750.022957312,0.009073498286306858,,0.021488085389137268,0,,
+1973,3030528,750.423555274,0.006028841435909271,,0.022140204906463623,2,16.18816172768129,1000.0
+1974,3032064,750.8151635950001,0.010222357232123613,,0.022282995283603668,0,,
+1975,3033600,751.180644799,0.01132390641917785,,0.022073108702898026,3,24.88504891245005,1000.0
+1976,3035136,751.556823656,0.001671999910225471,,0.021248709410429,1,23.604553795419633,1000.0
+1977,3036672,752.01268941,0.007545899134129286,,0.021425580605864525,1,24.041750601842068,1000.0
+1978,3038208,752.470023493,0.0027697919867932796,,0.02159232459962368,1,17.48147450760007,1000.0
+1979,3039744,752.9378808810001,0.01021429089208444,,0.021720528602600098,1,20.540412534959614,1000.0
+1980,3041280,753.42415097,0.008954546476403872,,0.02092386782169342,3,27.539328718208708,1000.0
+1981,3042816,753.9333757310001,0.006505758998294671,,0.02124650590121746,1,14.652509412262589,1000.0
+1982,3044352,754.428131857,0.008756119726846616,,0.020631540566682816,1,28.41844786889851,1000.0
+1983,3045888,754.835842586,0.01012509282057484,,0.020937344059348106,0,,
+1984,3047424,755.261815351,0.011614161978165309,,0.02082095481455326,1,15.02646303223446,1000.0
+1985,3048960,755.645559583,0.013072031394888958,,0.0205085389316082,0,,
+1986,3050496,756.120495533,0.009427427779883146,,0.02099127136170864,2,19.18033439066494,1000.0
+1987,3052032,756.5470341700001,0.014868027406434219,,0.020722776651382446,1,13.77633957657963,1000.0
+1988,3053568,757.01583852,0.008753421188642582,,0.02093956619501114,1,27.725977488793433,1000.0
+1989,3055104,757.39471696,0.009100787186374268,,0.02095966786146164,2,22.085755518230144,1000.0
+1990,3056640,757.778697369,0.007514449674636126,,0.021123696118593216,2,23.869491323363036,1000.0
+1991,3058176,758.2088182780001,0.01734268944710493,,0.021323591470718384,0,,
+1992,3059712,758.593706246,0.005126531360050043,,0.021147891879081726,1,17.599824839737266,1000.0
+1993,3061248,758.952703924,0.015203001194943984,,0.020942550152540207,1,18.414197456557304,1000.0
+1994,3062784,759.328204207,0.012216464709490537,,0.021182984113693237,2,20.370314855594188,1000.0
+1995,3064320,759.7187472210001,0.006501372686276833,,0.021754387766122818,0,,
+1996,3065856,760.073262663,0.006576246737192075,,0.02138235792517662,3,21.278680613652494,1000.0
+1997,3067392,760.4949276440001,0.010604096514483293,,0.021249011158943176,3,21.00661025037213,1000.0
+1998,3068928,760.8355420060001,0.009118649177253246,,0.021536964923143387,1,13.818705735029653,1000.0
+1999,3070464,761.205759506,0.00661166605229179,,0.022042647004127502,1,15.10705094889272,1000.0
+2000,3072000,761.554080969,0.018101074950148663,,0.02220086008310318,0,,
+2001,3073536,761.909573089,0.010113989872237047,,0.021355193108320236,3,17.868867587763816,1000.0
+2002,3075072,762.3059330570001,0.013600466710825761,,0.021465830504894257,3,29.254930370797712,1000.0
+2003,3076608,762.663492562,0.013478936068713665,,0.021318545565009117,1,23.431495152879506,1000.0
+2004,3078144,763.0698667300001,0.014672505979736647,,0.021290158852934837,2,26.26980673801154,1000.0
+2005,3079680,763.495517678,0.007797487452626229,,0.021276941522955894,3,22.281634440645576,1000.0
+2006,3081216,763.902862163,0.004190642479807138,,0.021492211148142815,2,20.4667634437792,1000.0
+2007,3082752,764.4073513010001,0.010538091883063316,,0.02178587019443512,4,20.674757776621846,1000.0
+2008,3084288,764.856772294,0.008860547871639332,,0.02152273617684841,1,27.36112993117422,1000.0
+2009,3085824,765.261881437,0.006373254675418138,,0.020855441689491272,3,19.71116514399182,1000.0
+2010,3087360,765.645278862,0.007298604523142179,,0.020767120644450188,4,19.764575829845853,1000.0
+2011,3088896,766.058403683,0.008129310080160696,,0.021875886246562004,1,21.89414045365993,1000.0
+2012,3090432,766.508639578,0.018511970527470112,,0.02129574678838253,0,,
+2013,3091968,766.9243024140001,0.015452572020391624,,0.021256837993860245,2,16.300768244749634,1000.0
+2014,3093504,767.344002634,0.010913402649263541,,0.02144782245159149,1,29.693325935280882,1000.0
+2015,3095040,767.758133379,0.019733562010029952,,0.021275093778967857,1,30.862680887803435,1000.0
+2016,3096576,768.253764464,0.016885867280264696,,0.021538570523262024,0,,
+2017,3098112,768.722489747,0.003908286926647028,,0.02172711119055748,4,19.49084845004836,1000.0
+2018,3099648,769.1600598570001,0.012131464605530103,,0.022290438413619995,0,,
+2019,3101184,769.586757751,0.015242359632005294,,0.022015299648046494,1,21.64776757126674,1000.0
+2020,3102720,769.922810605,0.004683711472898722,,0.021808823570609093,1,15.511857438832521,1000.0
+2021,3104256,770.2950140060001,0.011091373891880115,,0.022081559523940086,2,16.83389077486936,1000.0
+2022,3105792,770.672123275,0.012930962940057118,,0.02231968566775322,2,23.11219971050741,1000.0
+2023,3107328,771.0291395510001,0.006650765053927898,,0.022525236010551453,1,14.36949553526938,1000.0
+2024,3108864,771.405986244,0.007800159603357315,,0.022692261263728142,1,21.52283205476124,1000.0
+2025,3110400,771.802884842,0.005696021703382333,,0.02224779687821865,1,19.92870072182268,1000.0
+2026,3111936,772.1467496160001,0.01078660540903608,,0.02263527177274227,0,,
+2027,3113472,772.527841727,0.010686909593641759,,0.022240635007619858,0,,
+2028,3115008,772.881104376,0.00822989825780193,,0.02221263013780117,2,16.929170131741557,1000.0
+2029,3116544,773.211435757,0.00822950763007005,,0.02260388806462288,1,17.10912373382598,1000.0
+2030,3118080,773.576628624,0.008606277375171582,,0.02236405573785305,1,28.282908245921135,1000.0
+2031,3119616,773.9212323290001,0.006958851745973031,,0.022455904632806778,3,26.167033370235004,1000.0
+2032,3121152,774.264437925,0.008545357578744492,,0.022278279066085815,1,28.222573114559054,1000.0
+2033,3122688,774.653660941,0.01192017396291097,,0.022315826267004013,0,,
+2034,3124224,775.014558616,0.006866563235719999,,0.022544948384165764,1,17.632076222915202,1000.0
+2035,3125760,775.436813172,0.013641092833131552,,0.022015783935785294,1,18.776905524078757,1000.0
+2036,3127296,775.859336737,0.015565023850649595,,0.022860050201416016,2,21.679695793660358,1000.0
+2037,3128832,776.227691972,0.01961858201151093,,0.022351210936903954,2,17.72770476154983,1000.0
+2038,3130368,776.614579348,0.006138677832980951,,0.022666705772280693,2,16.98242019157624,1000.0
+2039,3131904,776.953968573,0.006429536764820417,,0.0230911485850811,3,26.051295218484785,1000.0
+2040,3133440,777.288031344,0.012856205708036821,,0.022834982722997665,1,28.817031977698207,1000.0
+2041,3134976,777.6239526730001,0.00946186085542043,,0.02261659875512123,0,,
+2042,3136512,777.951020729,0.014116529778887828,,0.022599440068006516,0,,
+2043,3138048,778.2934818800001,0.011118281570573648,,0.02250681072473526,5,22.958798737847246,1000.0
+2044,3139584,778.712272383,0.0057697019229332605,,0.022766396403312683,2,20.535763091989793,1000.0
+2045,3141120,779.115509998,0.009644160481790702,,0.022852471098303795,1,29.7018166417256,1000.0
+2046,3142656,779.5283384420001,0.010693574820955594,,0.022883445024490356,2,22.34802391845733,1000.0
+2047,3144192,779.875323008,0.010742003781100113,,0.022356003522872925,4,24.177495804950013,1000.0
+2048,3145728,780.2695158590001,0.01320791660497586,,0.02249280735850334,2,20.05985852063168,1000.0
+2049,3147264,780.6488346550001,0.007987809119125206,,0.02243737131357193,2,18.422800398315303,1000.0
+2050,3148800,780.980073349,0.012428476723531883,,0.022536499425768852,1,15.975266852648929,1000.0
+2051,3150336,781.318850966,0.0152155845426023,,0.02272627130150795,4,19.755619978765026,1000.0
+2052,3151872,781.67427403,0.011650309525430202,,0.022539466619491577,3,23.86757484204524,1000.0
+2053,3153408,781.995490838,0.010364990122616291,,0.022769561037421227,1,24.624061771668494,1000.0
+2054,3154944,782.342437319,0.01665207017213106,,0.022346502169966698,2,21.623851338401437,1000.0
+2055,3156480,782.706291188,0.011531388945877552,,0.02238614484667778,0,,
+2056,3158016,783.024714978,0.016805174108594657,,0.021873963996767998,1,19.887811190681532,1000.0
+2057,3159552,783.353422798,0.013211898505687714,,0.022504514083266258,1,20.98892686283216,1000.0
+2058,3161088,783.692391498,0.009010832073787849,,0.022124983370304108,1,23.866383818443865,1000.0
+2059,3162624,784.024028345,0.013563130423426628,,0.022215694189071655,3,24.433320556456845,1000.0
+2060,3164160,784.3518110050001,0.011647858625898759,,0.02243126556277275,1,21.524444626644254,1000.0
+2061,3165696,784.713918246,0.010891870285073916,,0.022057056427001953,0,,
+2062,3167232,785.030021785,0.011548932020862898,,0.021834706887602806,1,24.86347306612879,1000.0
+2063,3168768,785.3938586820001,0.016744452342391015,,0.022296082228422165,4,25.684544172530877,1000.0
+2064,3170304,785.744823698,0.005843439511954785,,0.022023124620318413,1,15.51891235623043,1000.0
+2065,3171840,786.147039121,0.01170294051989913,,0.02255754917860031,1,22.10092602018267,1000.0
+2066,3173376,786.58250507,0.014460104331374169,,0.022433599457144737,0,,
+2067,3174912,786.9845237010001,0.012438412259022395,,0.02211732231080532,1,30.396548498421907,1000.0
+2068,3176448,787.334103223,0.01687734223281344,,0.022566605359315872,0,,
+2069,3177984,787.690083825,0.01197479097172618,,0.02281544916331768,2,18.575081241957378,1000.0
+2070,3179520,787.999192881,0.004919716995209456,,0.022900860756635666,0,,
+2071,3181056,788.3206592040001,0.008570434277256329,,0.022829022258520126,1,26.720918140374124,1000.0
+2072,3182592,788.6881212750001,0.0044885888695716854,,0.022997310385107994,2,19.721302876481786,1000.0
+2073,3184128,789.03178184,0.013007055968046188,,0.022884652018547058,3,23.113652746115502,1000.0
+2074,3185664,789.355225487,0.01277911892781655,,0.023118898272514343,0,,
+2075,3187200,789.7113695280001,0.019271201578279336,,0.022214144468307495,1,27.84122916124761,1000.0
+2076,3188736,790.068698444,0.020367007702589035,,0.0225782822817564,0,,
+2077,3190272,790.405733574,0.014283509676655133,,0.022300658747553825,1,24.428362858481705,1000.0
+2078,3191808,790.764581557,0.01333891972899437,,0.022382009774446487,2,27.271118664182723,1000.0
+2079,3193344,791.1213886830001,0.011383236106485128,,0.022444333881139755,2,23.449889607029036,1000.0
+2080,3194880,791.538747007,0.013511740695685148,,0.021953364834189415,2,22.930383248021826,1000.0
+2081,3196416,791.890807847,0.008123426853368679,,0.021945830434560776,3,22.269238718397293,1000.0
+2082,3197952,792.213859793,0.010788830524931351,,0.02209385484457016,1,23.117616644129157,1000.0
+2083,3199488,792.551708273,0.006705769958595435,,0.022000353783369064,0,,
+2084,3201024,792.8905431210001,0.014899756883581479,,0.022163305431604385,3,19.50296788282382,1000.0
+2085,3202560,793.2212116960001,0.012998700172950824,,0.021828647702932358,3,23.279868370077264,1000.0
+2086,3204096,793.562186876,0.0115180475016435,,0.022125324234366417,1,15.893476638593711,1000.0
+2087,3205632,793.8911497720001,0.016455422310779493,,0.0221476461738348,1,29.52729569002986,1000.0
+2088,3207168,794.227464688,0.015703724262615047,,0.021771742030978203,3,15.969713432636732,1000.0
+2089,3208704,794.586164829,0.013155304826796055,,0.022203899919986725,3,25.109956983166438,1000.0
+2090,3210240,794.9296169080001,0.012734606551627317,,0.021836047992110252,4,24.07565241199336,1000.0
+2091,3211776,795.271958004,0.007707175829758247,,0.02274668775498867,1,18.962471768725663,1000.0
+2092,3213312,795.620616993,0.008435262305041154,,0.02284412831068039,3,22.61550470860675,1000.0
+2093,3214848,795.943763396,0.009199663593123356,,0.022300124168395996,2,19.040110042551532,1000.0
+2094,3216384,796.27979738,0.016371261204282443,,0.022957075387239456,3,17.15072230497996,1000.0
+2095,3217920,796.6650768860001,0.018768851831555366,,0.023370586335659027,0,,
+2096,3219456,797.017740296,0.008567280787974595,,0.023267557844519615,2,16.339797022519633,1000.0
+2097,3220992,797.419553917,0.017511587124317884,,0.023201510310173035,0,,
+2098,3222528,797.826227881,1.2999866157770157e-05,,0.02308621071279049,2,28.856156465306412,1000.0
+2099,3224064,798.224686259,0.008746621819833914,,0.023018348962068558,0,,
+2100,3225600,798.639873553,0.018015276019771893,,0.02221880853176117,3,21.480690587700035,1000.0
+2101,3227136,798.9674449330001,0.011121705795327822,,0.022011741995811462,1,25.724412868730724,1000.0
+2102,3228672,799.311435773,0.01056519045184056,,0.022625725716352463,1,28.11274103447795,1000.0
+2103,3230208,799.67384162,0.009465785635014375,,0.022393830120563507,1,17.768121126340702,1000.0
+2104,3231744,800.001161845,0.01243554726243019,,0.022159181535243988,1,26.11919530853629,1000.0
+2105,3233280,800.344010984,0.009979522631814083,,0.021902572363615036,3,21.094826577347703,1000.0
+2106,3234816,800.7431717979999,0.01082714538400372,,0.022416679188609123,1,28.450644321739674,1000.0
+2107,3236352,801.1010756050001,0.007592528872191906,,0.021888453513383865,1,28.43843967455905,1000.0
+2108,3237888,801.422966066,0.007511288610597452,,0.021891340613365173,0,,
+2109,3239424,801.7559788750001,0.001975771940002839,,0.02155171148478985,1,23.245388588286005,1000.0
+2110,3240960,802.0866377380001,0.01582438067222635,,0.022112306207418442,0,,
+2111,3242496,802.522078433,0.00867071800554792,,0.021028857678174973,2,24.667454520240426,1000.0
+2112,3244032,802.888069862,0.012283626881738504,,0.02191685512661934,1,24.105939770583063,1000.0
+2113,3245568,803.263211999,0.012247426155954599,,0.021264400333166122,1,22.46331586036831,1000.0
+2114,3247104,803.598197212,0.015582814905792474,,0.021526318043470383,2,24.76485762395896,1000.0
+2115,3248640,803.9328916160001,0.012026361127694448,,0.021568050608038902,2,27.13885306683369,1000.0
+2116,3250176,804.253089011,0.01895747392748793,,0.021238675341010094,1,16.281324112205766,547.0
+2117,3251712,804.6061411219999,0.01971966683243712,,0.021928079426288605,1,18.926750676240772,1000.0
+2118,3253248,804.945344873,0.00696136678258578,,0.0215876754373312,1,31.576040947809815,1000.0
+2119,3254784,805.2794508979999,0.004024113745739063,,0.02161814272403717,2,21.159873760072514,1000.0
+2120,3256320,805.6042364250001,0.005605578981339931,,0.021782875061035156,0,,
+2121,3257856,805.9533772810001,0.01309959621479114,,0.021484147757291794,3,19.667728387673076,1000.0
+2122,3259392,806.289627039,0.011836393487950165,,0.02218244969844818,3,19.49525238076846,1000.0
+2123,3260928,806.637116448,0.008702065578351419,,0.022399548441171646,1,16.806321414536797,1000.0
+2124,3262464,806.9678355340001,0.017794652469456197,,0.022317564114928246,1,16.72642774146516,1000.0
+2125,3264000,807.2860225830001,0.018400878397126993,,0.021569758653640747,0,,
+2126,3265536,807.642051381,0.017028469343980154,,0.02109336107969284,5,19.699859883775936,808.0
+2127,3267072,808.0062732800001,0.010768089474489291,,0.020816074684262276,4,14.842948767298367,773.75
+2128,3268608,808.407671259,0.010692719059685865,,0.02132212184369564,1,30.43331247009337,1000.0
+2129,3270144,808.823628536,0.01411895922695597,,0.02101912721991539,2,24.905432406347245,1000.0
+2130,3271680,809.2049359470001,0.01127983359619975,,0.020692959427833557,3,23.011355770829443,1000.0
+2131,3273216,809.5334670430001,0.01715013546248277,,0.021270466968417168,2,17.451060261868406,1000.0
+2132,3274752,809.8791984360001,0.014304366676757734,,0.020636485889554024,4,24.733350080161472,1000.0
+2133,3276288,810.2217872780001,0.009474536714454493,,0.021165888756513596,1,16.506587403884623,1000.0
+2134,3277824,810.5876805250001,0.0056210913695395,,0.020884469151496887,3,17.944511862646323,1000.0
+2135,3279360,810.9486588160001,0.006186699618895849,,0.021608194336295128,3,22.755550573114306,1000.0
+2136,3280896,811.2622462580001,0.013482193928211927,,0.021049432456493378,0,,
+2137,3282432,811.596339806,0.009963112883269787,,0.02179124765098095,0,,
+2138,3283968,811.9534903269999,0.014284488776077827,,0.021125664934515953,2,21.623326643602923,1000.0
+2139,3285504,812.301992608,0.016543093013266723,,0.021004799753427505,1,18.865721660200506,1000.0
+2140,3287040,812.67325485,0.015996848667661347,,0.021009963005781174,2,18.04377274820581,835.0
+2141,3288576,813.0249017330001,0.012363033431271712,,0.021301716566085815,0,,
+2142,3290112,813.4030359270001,0.018550310625384252,,0.021725384518504143,4,20.495391083299182,1000.0
+2143,3291648,813.764706949,0.01269812397658825,,0.022263363003730774,1,2.7907483796589077,125.0
+2144,3293184,814.0867953360001,0.011714469237873951,,0.022367095574736595,1,25.203565694391727,1000.0
+2145,3294720,814.413536984,0.03021216035510103,,0.021941429004073143,1,24.606441584648564,1000.0
+2146,3296256,814.7823001350001,0.012746048501382272,,0.02141101472079754,2,24.939545259810984,1000.0
+2147,3297792,815.147684718,0.015962360675136247,,0.022689547389745712,2,19.17148574528983,1000.0
+2148,3299328,815.486278898,0.017900409487386543,,0.02262105606496334,1,30.87390331819188,1000.0
+2149,3300864,815.881944825,0.01472795515631636,,0.021941473707556725,1,16.889730257564224,1000.0
+2150,3302400,816.212482691,0.008440783185263475,,0.022031206637620926,1,15.491787023260258,1000.0
+2151,3303936,816.550084692,0.004508733314772447,,0.022394491359591484,0,,
+2152,3305472,816.9034833740001,0.020967834318677585,,0.021505704149603844,0,,
+2153,3307008,817.2260631330001,0.010297599341720342,,0.022343259304761887,2,15.375804013136076,1000.0
+2154,3308544,817.5635049040001,0.01260771978025635,,0.022456279024481773,0,,
+2155,3310080,817.9069609,0.010164582977692287,,0.02240195870399475,1,22.514593484811485,1000.0
+2156,3311616,818.2650670859999,0.015322786259154479,,0.020865803584456444,3,14.792245696434597,800.3333333333334
+2157,3313152,818.6293818560001,0.010539029569675526,,0.021637246012687683,2,27.181465851841494,1000.0
+2158,3314688,819.0231519380001,0.026343881028393905,,0.020746469497680664,2,11.579119961941615,400.0
+2159,3316224,819.4330810729999,0.01889386388162772,,0.021589821204543114,1,19.095031425822526,1000.0
+2160,3317760,819.851175551,0.011891889323790868,,0.020913273096084595,2,14.500804124749266,629.5
+2161,3319296,820.29767546,0.022085967535773913,,0.02092563733458519,3,15.549204248566335,783.6666666666666
+2162,3320832,820.776360839,0.01117832272623976,,0.0214960016310215,2,25.72046310052974,1000.0
+2163,3322368,821.1774347490001,0.020488145978500447,,0.021675681695342064,2,20.80990605725674,1000.0
+2164,3323904,821.513375117,0.015939452312886716,,0.02242247760295868,2,25.98000900889747,1000.0
+2165,3325440,821.875956555,0.01929138551155726,,0.021167173981666565,2,14.596548952278681,778.5
+2166,3326976,822.220387102,0.017621238126109044,,0.022197309881448746,0,,
+2167,3328512,822.5580758540001,0.007363995537161827,,0.02179674431681633,1,15.786122444085777,1000.0
+2168,3330048,823.000214216,0.02371368029465278,,0.022213608026504517,7,17.517254912094877,1000.0
+2169,3331584,823.3363402040001,0.00605654027312994,,0.023395180702209473,2,20.87044313340448,1000.0
+2170,3333120,823.702596431,0.0038498719222843647,,0.022758029401302338,1,24.871407008729875,1000.0
+2171,3334656,824.1323050480001,0.00818456473449866,,0.022538121789693832,2,26.87808152777143,1000.0
+2172,3336192,824.545050436,0.0065767960622906685,,0.022709548473358154,4,19.631215514265932,1000.0
+2173,3337728,824.951819023,0.013020036711047093,,0.02226337417960167,3,16.67766891454812,881.3333333333334
+2174,3339264,825.299204696,0.014550172444432973,,0.022929206490516663,2,28.597600245848298,1000.0
+2175,3340800,825.6540447030001,0.02666375810901324,,0.022678136825561523,1,22.15915272757411,1000.0
+2176,3342336,826.000078956,0.010222292567292849,,0.022340357303619385,3,21.088312446993466,1000.0
+2177,3343872,826.3501049380001,0.022942174629618724,,0.02269103191792965,4,20.332963328255573,861.25
+2178,3345408,826.7184360290001,0.018774676043540238,,0.02252003364264965,0,,
+2179,3346944,827.0703806330001,0.013196747905264298,,0.02254757285118103,0,,
+2180,3348480,827.428810346,0.004478119437893232,,0.022622521966695786,0,,
+2181,3350016,827.788980746,0.008109932454923788,,0.022299829870462418,0,,
+2182,3351552,828.1570531460001,0.004675629952301582,,0.02214779332280159,2,23.72227866546018,1000.0
+2183,3353088,828.487294417,0.012278190876046816,,0.022164328023791313,1,16.304317926056683,1000.0
+2184,3354624,828.866365423,0.009267372079193592,,0.022464586421847343,2,23.463225841638632,1000.0
+2185,3356160,829.2044803730001,0.011361943868299326,,0.02235865592956543,2,23.94031168112997,1000.0
+2186,3357696,829.5272786419999,0.009322348640610774,,0.022368591278791428,0,,
+2187,3359232,829.8672528220001,0.018849853643526635,,0.022372987121343613,0,,
+2188,3360768,830.280078116,0.01211771477634708,,0.02222466468811035,3,20.29042966310711,827.6666666666666
+2189,3362304,830.7000163490001,0.019587742537260054,,0.022832848131656647,1,24.610456874710508,1000.0
+2190,3363840,831.09267459,0.013563372443119686,,0.022545546293258667,0,,
+2191,3365376,831.423183649,0.010064719679454963,,0.022661596536636353,0,,
+2192,3366912,831.7679079129999,0.014615706106026968,,0.022385304793715477,1,15.37973764585331,1000.0
+2193,3368448,832.095433631,0.015789118160804114,,0.022003833204507828,0,,
+2194,3369984,832.424570664,0.011731566457698742,,0.021656787022948265,4,13.742212701617973,641.25
+2195,3371520,832.7877977720001,0.010221613384783269,,0.022199980914592743,1,15.447563953697681,522.0
+2196,3373056,833.1183394640001,0.015591266099363565,,0.022495515644550323,0,,
+2197,3374592,833.455222484,0.011202982316414515,,0.02199690043926239,3,20.698706989060156,903.0
+2198,3376128,833.846525631,0.01206457062313954,,0.022556859999895096,3,20.77360353929301,1000.0
+2199,3377664,834.198075079,0.007868395435313385,,0.02279449626803398,1,30.826353527605534,1000.0
+2200,3379200,834.540081839,0.005025400780141354,,0.022903427481651306,2,17.13260537595488,1000.0
+2201,3380736,834.9157739890001,0.009029252578814824,,0.022879570722579956,1,27.092294594389386,1000.0
+2202,3382272,835.3041688100001,0.0013659529077510038,,0.02239067852497101,1,25.627997118979692,1000.0
+2203,3383808,835.707822792,0.011180169756213824,,0.023026689887046814,3,20.022367670200765,1000.0
+2204,3385344,836.0551295070001,0.007306307771553596,,0.022322839125990868,2,26.664744008798152,1000.0
+2205,3386880,836.3980184170001,0.020708752951274317,,0.022884612902998924,2,21.81324382708408,1000.0
+2206,3388416,836.7579068240001,0.022211162621776262,,0.022220388054847717,3,16.70190280202466,682.6666666666666
+2207,3389952,837.087735206,0.006552702747285366,,0.02259068563580513,2,22.37539924943121,1000.0
+2208,3391488,837.45089642,0.008920142520219087,,0.02219322882592678,0,,
+2209,3393024,837.8086806330001,0.008351774606853723,,0.021675899624824524,3,23.22779272593713,1000.0
+2210,3394560,838.1647300610001,0.010191604991753896,,0.02218567579984665,4,23.653692625812255,1000.0
+2211,3396096,838.510648047,0.006885938284297784,,0.022024359554052353,1,16.644278775900602,1000.0
+2212,3397632,838.8674823510001,0.010155624337494373,,0.02179185301065445,1,25.333159552887082,1000.0
+2213,3399168,839.233472692,0.01252899964650472,,0.021898847073316574,3,20.853195364315372,1000.0
+2214,3400704,839.5782063949999,0.009678121749311685,,0.022028129547834396,3,20.364104160534527,1000.0
+2215,3402240,839.919117261,0.014889177897324165,,0.022613724693655968,4,21.735814554209355,1000.0
+2216,3403776,840.2472581580001,0.0054357885383069515,,0.02303212508559227,1,24.055125204846263,1000.0
+2217,3405312,840.610616995,0.021384623957177003,,0.023039400577545166,2,20.337762870360166,1000.0
+2218,3406848,840.9946568510001,0.0033407688761750856,,0.022950664162635803,2,20.97896602691617,1000.0
+2219,3408384,841.406118816,0.004449913961191972,,0.022582722827792168,2,27.599381383275613,1000.0
+2220,3409920,841.800431151,0.009525329681734244,,0.02249797247350216,0,,
+2221,3411456,842.204317824,0.013679903373122216,,0.022359944880008698,0,,
+2222,3412992,842.543345333,0.0077607401957114535,,0.022103946655988693,0,,
+2223,3414528,842.9081216860001,0.011969459398339191,,0.022669807076454163,1,16.036409958149306,1000.0
+2224,3416064,843.2285213040001,0.0209975177111725,,0.022086655721068382,2,22.61877968974295,822.0
+2225,3417600,843.549865482,0.003667311742901802,,0.02195696532726288,2,17.79212601413019,1000.0
+2226,3419136,843.892105264,0.005743607164671024,,0.022552136331796646,2,27.176275847945362,1000.0
+2227,3420672,844.248914981,0.013045012671500444,,0.022432800382375717,1,17.262320140202064,1000.0
+2228,3422208,844.612314056,0.010783955051253239,,0.021925730630755424,0,,
+2229,3423744,845.0385218110001,0.013058907787005107,,0.022781094536185265,1,29.466987071558833,1000.0
+2230,3425280,845.446572337,-0.0012927953774730363,,0.02210308238863945,1,24.33810255024582,1000.0
+2231,3426816,845.821068672,0.006639548608412345,,0.022746294736862183,1,17.596957557136193,1000.0
+2232,3428352,846.178868375,0.015224402739355962,,0.022922862321138382,0,,
+2233,3429888,846.596545147,0.022675925958901645,,0.0217292457818985,0,,
+2234,3431424,847.0343840649999,0.006518022405604521,,0.022138293832540512,1,17.812918528798036,1000.0
+2235,3432960,847.4233133880001,0.011821741703897715,,0.022450502961874008,2,22.17829789815005,1000.0
+2236,3434496,847.7850714550001,0.007116846150408188,,0.021983027458190918,2,25.558341916650534,1000.0
+2237,3436032,848.1890181110001,0.01259823211779197,,0.023010363802313805,1,15.483589973533526,1000.0
+2238,3437568,848.548634594,0.018214703196038802,,0.022013235837221146,1,16.034475625958294,1000.0
+2239,3439104,848.9382414360001,0.014565526756147544,,0.02251090109348297,2,21.93279256875394,1000.0
+2240,3440640,849.286587275,0.03341168770566583,,0.022934909909963608,3,24.36661396625762,912.3333333333334
+2241,3442176,849.6186431290001,0.01734728248169025,,0.022571509703993797,2,23.905465037329122,1000.0
+2242,3443712,849.9499340460001,0.013406396222611269,,0.0220485832542181,2,23.003278030606452,798.5
+2243,3445248,850.2793902100001,0.012136882605652015,,0.02222902700304985,2,24.5722620759625,1000.0
+2244,3446784,850.6193603790001,0.014107831008732318,,0.021704040467739105,4,23.544210822990863,935.0
+2245,3448320,850.990392241,0.009697575339426596,,0.022277211770415306,0,,
+2246,3449856,851.3623784110001,0.01421551164239645,,0.022284220904111862,2,19.10759490955388,1000.0
+2247,3451392,851.7100935249999,0.012228065232435862,,0.022238343954086304,4,20.396003350790124,972.75
+2248,3452928,852.146681863,0.01313865768412749,,0.02200891077518463,3,12.874079593767723,686.3333333333334
+2249,3454464,852.542551142,0.00689939068009456,,0.022838696837425232,1,17.3367495755665,1000.0
+2250,3456000,852.9639982919999,0.016113253651807706,,0.022550109773874283,0,,
+2251,3457536,853.3475907860001,0.021001651665816704,,0.02193443477153778,4,18.371935245173518,916.0
+2252,3459072,853.681828832,0.019145783688873052,,0.0227291788905859,2,19.326385497348383,1000.0
+2253,3460608,853.9942284800001,0.013562009235223134,,0.022583559155464172,1,29.191145912744105,1000.0
+2254,3462144,854.3254499359999,0.007053085292379062,,0.021860560402274132,2,24.485173055669293,1000.0
+2255,3463680,854.658331604,0.010760974573592345,,0.022521845996379852,2,20.291703545255587,1000.0
+2256,3465216,855.0286046,0.01693585803732276,,0.021954428404569626,2,18.82961167395115,1000.0
+2257,3466752,855.3752226970001,0.014944539188096921,,0.020981967449188232,5,20.651251631812194,880.4
+2258,3468288,855.6992371770001,0.01925187688320875,,0.021716749295592308,2,19.66311058832798,768.5
+2259,3469824,856.0377951930001,0.008291297064473232,,0.021343182772397995,1,17.65495046461001,1000.0
+2260,3471360,856.3863222450001,0.013875843957066536,,0.022037988528609276,4,18.59406602731906,1000.0
+2261,3472896,856.73108066,0.012250843582053979,,0.021755201742053032,0,,
+2262,3474432,857.0987261189999,0.017515547635654608,,0.021523572504520416,0,,
+2263,3475968,857.4684452939999,0.010020003902415435,,0.02166580781340599,0,,
+2264,3477504,857.832963322,0.016374181117862464,,0.02234906703233719,0,,
+2265,3479040,858.194753614,0.009010677225887775,,0.02222156524658203,1,23.339078535558656,1000.0
+2266,3480576,858.518917305,0.01576410165677468,,0.022019103169441223,1,17.897969420533627,1000.0
+2267,3482112,858.870248003,0.008735490497201681,,0.0216534361243248,3,26.272018123883754,1000.0
+2268,3483648,859.2128241450001,0.016109352620939415,,0.02204405888915062,1,29.445704649668187,1000.0
+2269,3485184,859.5358236420001,0.013133296556770802,,0.021864846348762512,1,29.797599408775568,1000.0
+2270,3486720,859.859200793,0.007651309669017792,,0.021421518176794052,0,,
+2271,3488256,860.188162158,0.004175508022308349,,0.021286875009536743,1,24.36503469431773,1000.0
+2272,3489792,860.522939003,0.014357791685809692,,0.021637601777911186,1,21.812076832167804,1000.0
+2273,3491328,860.8799104210001,0.012727130390703677,,0.021158134564757347,2,18.447390010405798,843.0
+2274,3492864,861.2272955690001,0.010899704198042552,,0.02162451669573784,0,,
+2275,3494400,861.553274617,0.010268937392781178,,0.02101748436689377,1,22.86776569392532,1000.0
+2276,3495936,861.8684196309999,0.012665171300371487,,0.021521389484405518,0,,
+2277,3497472,862.198695535,0.013077033435304959,,0.020835280418395996,2,20.459164534753654,924.0
+2278,3499008,862.531012433,0.017424944757173457,,0.021306637674570084,2,21.575655544293113,1000.0
+2279,3500544,862.905531386,0.01373966292788585,,0.021143238991498947,1,23.3818030199036,1000.0
+2280,3502080,863.2862616589999,0.013580906173835198,,0.02088714763522148,2,25.61543691175757,874.5
+2281,3503616,863.6972890779999,0.02094451431185007,,0.020811744034290314,4,21.380253919836832,1000.0
+2282,3505152,864.1001320280001,0.007576672142992417,,0.020952347666025162,1,23.21928657637909,1000.0
+2283,3506688,864.5060115100001,0.0179117275091509,,0.020516205579042435,2,15.61410668620374,961.5
+2284,3508224,864.852651413,0.008016679994761943,,0.021064095199108124,1,30.163120932877064,1000.0
+2285,3509760,865.2019190689999,0.0072729816349844136,,0.020856622606515884,2,16.357631203660276,1000.0
+2286,3511296,865.52663468,0.017638452475269635,,0.020501725375652313,3,19.998200298364583,948.6666666666666
+2287,3512832,865.831901507,0.014254485753675302,,0.020712468773126602,0,,
+2288,3514368,866.1663685310001,0.018810021877288818,,0.020672976970672607,3,16.7854902195589,687.6666666666666
+2289,3515904,866.5108128850001,0.009038242045789957,,0.02139930985867977,4,20.86500075434742,1000.0
+2290,3517440,866.8785627460001,0.0054228902173539,,0.02139902673661709,2,22.757510360097513,1000.0
+2291,3518976,867.211500754,0.011379282331715028,,0.021516604349017143,0,,
+2292,3520512,867.555893241,0.014950775479276975,,0.021000832319259644,0,,
+2293,3522048,867.886816174,0.013251159774760405,,0.021166866645216942,4,18.881074542819988,1000.0
+2294,3523584,868.224745824,0.00696489131078124,,0.021594909951090813,2,24.205231668660417,1000.0
+2295,3525120,868.619988368,0.01457498005280892,,0.021598372608423233,1,16.405944486614317,1000.0
+2296,3526656,868.996753088,0.008979212089131276,,0.021659012883901596,2,22.735762453172356,1000.0
+2297,3528192,869.3276538700001,0.009196977379421394,,0.021900873631238937,3,27.180212313930195,1000.0
+2298,3529728,869.671664913,0.0093114810064435,,0.021477818489074707,3,19.447117077147897,1000.0
+2299,3531264,870.0010294760001,0.013988764521976312,,0.021772775799036026,3,19.745023631801207,1000.0
+2300,3532800,870.3246486710001,0.006157525752981504,,0.022434893995523453,1,15.232560022268444,1000.0
+2301,3534336,870.6678025120001,0.010093330933401982,,0.021777143701910973,1,23.318812983692624,1000.0
+2302,3535872,871.050098545,0.017144711936513582,,0.021987665444612503,4,20.26365087745944,1000.0
+2303,3537408,871.3699716760001,0.009406893389920394,,0.022777777165174484,0,,
+2304,3538944,871.7064774300001,0.016080026980489492,,0.022228237241506577,1,0.7118277796544135,51.0
+2305,3540480,872.028384283,0.014624242888142664,,0.022328712046146393,0,,
+2306,3542016,872.391783146,0.006728601393600305,,0.022128980606794357,0,,
+2307,3543552,872.71687091,0.009072720600912968,,0.02213660441339016,1,15.23024130036356,1000.0
+2308,3545088,873.0668498230001,0.008896626159548759,,0.022003136575222015,2,22.96833736199187,1000.0
+2309,3546624,873.389499903,0.00928320363163948,,0.02201780490577221,2,17.45186142012244,1000.0
+2310,3548160,873.731977473,0.006257345682630936,,0.022070055827498436,2,15.243281353003113,1000.0
+2311,3549696,874.065798493,0.01629495375479261,,0.022203970700502396,0,,
+2312,3551232,874.4253931930001,0.01109266271814704,,0.02267567813396454,0,,
+2313,3552768,874.8470872700001,0.02142948651065429,,0.02237492799758911,2,25.021411378285848,1000.0
+2314,3554304,875.2627682820001,0.012023847519109647,,0.022737067192792892,1,29.172765409341082,1000.0
+2315,3555840,875.61394852,0.014622618351131678,,0.02232118509709835,1,16.195743886753917,1000.0
+2316,3557376,875.920709184,0.012382371164858342,,0.022556807845830917,0,,
+2317,3558912,876.246458732,0.014748746901750565,,0.0227239690721035,1,22.760737576521933,1000.0
+2318,3560448,876.623584906,0.008910784280548494,,0.022729352116584778,0,,
+2319,3561984,877.013244054,0.007416029429684083,,0.022791288793087006,4,21.723497123573907,1000.0
+2320,3563520,877.3498857779999,0.0052203768864274025,,0.022913426160812378,1,23.716937586199492,1000.0
+2321,3565056,877.7629537240001,0.004133906122297049,,0.02307974360883236,1,15.64005519170314,1000.0
+2322,3566592,878.145478838,0.009521330365290244,,0.02297094091773033,2,27.053796962369233,1000.0
+2323,3568128,878.5323852610001,0.008452331988761823,,0.0229423176497221,3,21.28619538907272,1000.0
+2324,3569664,878.912174426,0.012468249133477608,,0.022705867886543274,2,15.94925303873606,1000.0
+2325,3571200,879.263202295,0.008980939351022243,,0.022819986566901207,1,26.546143018640578,1000.0
+2326,3572736,879.666860444,0.02128018531948328,,0.022730495780706406,2,19.92903503612615,1000.0
+2327,3574272,880.011474929,0.013110064901411533,,0.022401634603738785,1,28.17326868698001,1000.0
+2328,3575808,880.3712182109999,0.013858527690172196,,0.022656407207250595,2,20.190679505700245,1000.0
+2329,3577344,880.702489723,0.016268507887919743,,0.022176120430231094,0,,
+2330,3578880,881.0805859840001,0.014230565354228019,,0.022019168362021446,5,17.45869553796947,814.4
+2331,3580416,881.418287844,0.0076054200219611325,,0.02303069829940796,4,23.282298579695635,1000.0
+2332,3581952,881.778491296,0.008479802465687195,,0.022887399420142174,1,19.491611583158374,1000.0
+2333,3583488,882.1261376850001,0.01226938742523392,,0.0230009313672781,0,,
+2334,3585024,882.533841604,0.00835128016769886,,0.02250206097960472,2,23.126838429656345,1000.0
+2335,3586560,882.9569822970001,0.010658011399209499,,0.022067680954933167,3,23.48315002808037,1000.0
+2336,3588096,883.3067380830001,0.006457324015597502,,0.02219916507601738,1,29.74220453388989,1000.0
+2337,3589632,883.681811201,0.013525321148335934,,0.022034352645277977,1,21.362418689765036,1000.0
+2338,3591168,884.0607244880001,0.009715836929778258,,0.022278036922216415,2,17.169085619359976,1000.0
+2339,3592704,884.438655306,0.01477178515245517,,0.022285055369138718,3,22.89617783172677,1000.0
+2340,3594240,884.8631282760001,0.01375552210956812,,0.022400876507163048,5,25.163617940549738,1000.0
+2341,3595776,885.296100248,0.015011258609592914,,0.02240891009569168,2,23.257339419273194,1000.0
+2342,3597312,885.7681411520001,0.015415086348851522,,0.02247742936015129,1,26.998565662652254,1000.0
+2343,3598848,886.2007631110001,0.00510662825157245,,0.02284463308751583,2,29.97505453613121,1000.0
+2344,3600384,886.5718426770001,0.004548404676218827,,0.022681597620248795,1,26.690502007491887,1000.0
+2345,3601920,886.9335335869999,0.016106104974945388,,0.022496089339256287,0,,
+2346,3603456,887.3520333170001,0.01329693521062533,,0.02224205993115902,1,14.594258796889335,1000.0
+2347,3604992,887.7282706080001,0.011823768075555564,,0.022455822676420212,0,,
+2348,3606528,888.1497796540001,0.010529814784725507,,0.022427357733249664,0,,
+2349,3608064,888.531896158,0.008898369098703066,,0.022262951359152794,2,16.424684589612298,1000.0
+2350,3609600,888.9659643860001,0.00934497695416212,,0.02251855656504631,2,21.163400622550398,1000.0
+2351,3611136,889.4566934350001,0.009485982234279315,,0.022303655743598938,2,22.393429046671372,1000.0
+2352,3612672,889.863445261,0.009907341996828715,,0.02239185944199562,1,27.220375050790608,1000.0
+2353,3614208,890.2926249820001,0.01635639723390341,,0.02266218326985836,0,,
+2354,3615744,890.7288597319999,0.01559973560894529,,0.02196541056036949,1,28.887511859065853,1000.0
+2355,3617280,891.257590994,0.01261954177170992,,0.022073818370699883,1,28.80889664310962,1000.0
+2356,3618816,891.678300038,0.011097100035597881,,0.021936509758234024,2,17.831627862760797,1000.0
+2357,3620352,892.0082886690001,0.014798750728368759,,0.022409548982977867,0,,
+2358,3621888,892.361648253,0.018709277113278706,,0.021519098430871964,0,,
+2359,3623424,892.7045178740001,0.01990670741846164,,0.02211061678826809,1,23.944485606916714,1000.0
+2360,3624960,893.066018982,0.028003576242675386,,0.02206334099173546,1,23.219662579940632,1000.0
+2361,3626496,893.4435125410001,0.02419842922439178,,0.02080404944717884,4,21.178869282535743,964.0
+2362,3628032,893.8177109700001,0.016354844253510237,,0.021851500496268272,1,21.162332984386012,1000.0
+2363,3629568,894.172113838,0.010547294871260722,,0.02173144742846489,2,23.211855972826015,1000.0
+2364,3631104,894.510275366,0.015705222884813946,,0.021115977317094803,2,19.59937595401425,1000.0
+2365,3632640,894.9232358380001,0.012992494460195302,,0.02190656028687954,2,22.84964508592384,1000.0
+2366,3634176,895.272966229,0.014978439485033353,,0.021958624944090843,3,21.373831204371527,1000.0
+2367,3635712,895.5971946650001,0.013431735212604205,,0.021920781582593918,0,,
+2368,3637248,895.9486570760001,0.006219280728449424,,0.021866336464881897,1,14.12468169699423,1000.0
+2369,3638784,896.359885408,0.014224187284708024,,0.021585753187537193,1,28.672143162460998,1000.0
+2370,3640320,896.779133268,0.01038552209114035,,0.0219772569835186,1,28.505460118874907,1000.0
+2371,3641856,897.2309532760002,0.020930130903919538,,0.02179749682545662,2,20.708188083895948,1000.0
+2372,3643392,897.5553959950001,0.012176067320009072,,0.021852312609553337,5,22.55025569922291,1000.0
+2373,3644928,897.883050966,0.023301316673556963,,0.02235748991370201,2,26.732593044172972,1000.0
+2374,3646464,898.200161781,0.015882414455215137,,0.020999282598495483,1,14.86747667484451,1000.0
+2375,3648000,898.5449711919999,0.013141674175858497,,0.021599899977445602,1,21.361010662512854,855.0
+2376,3649536,898.889789961,0.007031456598391135,,0.021470537409186363,3,16.22166426992044,1000.0
+2377,3651072,899.2435397,0.012756731795767943,,0.021944990381598473,2,19.93015911115799,1000.0
+2378,3652608,899.592124761,0.004253307761003574,,0.0222183745354414,1,20.73315256042406,1000.0
+2379,3654144,899.969948412,0.006305455975234508,,0.02170620858669281,2,28.54687146260403,1000.0
+2380,3655680,900.3154079740001,0.011612301475058,,0.021440919488668442,2,18.913617634156253,1000.0
+2381,3657216,900.6736296960001,0.011438819393515588,,0.021617230027914047,1,20.527587023563683,1000.0
+2382,3658752,901.1141269390001,0.01455549756065011,,0.02183520421385765,5,22.950017663277684,1000.0
+2383,3660288,901.477761855,0.011731270297120015,,0.022131165489554405,2,28.371269216528162,1000.0
+2384,3661824,901.8273867040001,0.0072899270181854565,,0.021769125014543533,1,25.216574216727167,1000.0
+2385,3663360,902.19896,0.008749898057430983,,0.021215712651610374,3,23.225282267977793,1000.0
+2386,3664896,902.543655627,0.010421871952712537,,0.02162136137485504,0,,
+2387,3666432,902.876542974,0.02026179029295842,,0.021559305489063263,0,,
+2388,3667968,903.2882662810001,0.008567307672152916,,0.021900316700339317,1,14.616408162284642,1000.0
+2389,3669504,903.6763272470001,0.016278463353713354,,0.021584466099739075,0,,
+2390,3671040,904.0884555410001,0.02193254620457689,,0.021671485155820847,1,19.405413798289374,1000.0
+2391,3672576,904.4544346860001,0.010816868239392837,,0.02159438095986843,1,30.654478572309017,1000.0
+2392,3674112,904.81440207,0.013695512587825457,,0.021894460543990135,3,19.560382835838634,1000.0
+2393,3675648,905.1728062359999,0.018153352787097295,,0.022321056574583054,1,23.198944628238678,1000.0
+2394,3677184,905.522883471,0.008375242973367373,,0.021617203950881958,1,27.293212290853262,1000.0
+2395,3678720,905.870699514,0.011519027221947909,,0.022125165909528732,0,,
+2396,3680256,906.233918707,0.010655838406334321,,0.022159209474921227,1,16.02870371111203,1000.0
+2397,3681792,906.5864978129999,0.007679732609540224,,0.02226695977151394,1,23.85389737179503,1000.0
+2398,3683328,907.033160161,0.012385096773505211,,0.02227185294032097,2,23.932137516967487,1000.0
+2399,3684864,907.4301326630001,0.007990489931156237,,0.022055037319660187,0,,
+2400,3686400,907.823144999,0.011910529993474483,,0.021761160343885422,1,17.4908625530079,1000.0
+2401,3687936,908.210362721,0.008676379329214494,,0.021749427542090416,0,,
+2402,3689472,908.5526454530001,0.020966858696192504,,0.021695710718631744,2,18.168078907299787,1000.0
+2403,3691008,908.9615691550001,0.016332581856598458,,0.022189080715179443,3,18.76406811288325,1000.0
+2404,3692544,909.3405894870001,0.02322233154748877,,0.022459726780653,1,14.34094942966476,1000.0
+2405,3694080,909.6903251750001,0.01885877860089143,,0.021876005455851555,2,24.21451964584412,1000.0
+2406,3695616,910.056123947,0.015204737645884354,,0.02171551063656807,5,19.85272722260561,914.4
+2407,3697152,910.405663528,0.013647541434814532,,0.022264746949076653,1,20.486465176101774,1000.0
+2408,3698688,910.796844004,0.014697812963277102,,0.021932316944003105,2,14.57467440320761,1000.0
+2409,3700224,911.2336193310001,0.012231728030989568,,0.022245556116104126,0,,
+2410,3701760,911.565684536,0.007229958071062962,,0.022204330191016197,1,15.413308961782604,1000.0
+2411,3703296,911.9580848470001,0.008843026589602232,,0.022289356216788292,2,27.68784987181425,1000.0
+2412,3704832,912.3404636829999,0.007100327095637719,,0.021926015615463257,0,,
+2413,3706368,912.7030182060001,0.017625877012809116,,0.021912530064582825,4,23.40781010701903,1000.0
+2414,3707904,913.0958238229999,0.0187822874635458,,0.020965244621038437,5,18.33633164742496,812.4
+2415,3709440,913.41934691,0.010576371724406878,,0.022193923592567444,2,16.27865738805849,1000.0
+2416,3710976,913.77772143,0.01142002943282326,,0.0223071426153183,1,24.986520464532077,1000.0
+2417,3712512,914.109287897,0.013582655011365812,,0.021894894540309906,0,,
+2418,3714048,914.4266682030001,0.014747061611463627,,0.021894700825214386,4,25.06558670924278,1000.0
+2419,3715584,914.750216587,0.018077111057937145,,0.02201046608388424,2,22.082492861838546,1000.0
+2420,3717120,915.11007117,0.009917101388176282,,0.022119445726275444,1,15.65283449087292,1000.0
+2421,3718656,915.461621137,0.015134411336233219,,0.02191367745399475,2,23.721254942007363,1000.0
+2422,3720192,915.7797136410001,0.010973284890254339,,0.021818526089191437,2,18.09648617572384,1000.0
+2423,3721728,916.142210717,0.00954470910752813,,0.021552419289946556,3,25.844093173897516,1000.0
+2424,3723264,916.462529477,0.01909915261591474,,0.021650146692991257,2,24.083583642874146,1000.0
+2425,3724800,916.7772509570001,0.012338436922679346,,0.021674584597349167,1,25.197951393201947,1000.0
+2426,3726336,917.145114966,0.011827077468236287,,0.02153296396136284,1,27.438843976240605,1000.0
+2427,3727872,917.4978680610001,0.010987528568754594,,0.021206965669989586,3,21.84274706259991,1000.0
+2428,3729408,917.8684458690001,0.011535500672956308,,0.021508818492293358,0,,
+2429,3730944,918.2511317029999,0.011473854693273703,,0.02125268056988716,1,24.08751749008661,1000.0
+2430,3732480,918.643307597,0.006020446680486203,,0.021413207054138184,0,,
+2431,3734016,919.004335852,0.012824966137607892,,0.021392006427049637,0,,
+2432,3735552,919.348150762,0.011297943877677123,,0.021203115582466125,1,20.845877724699676,1000.0
+2433,3737088,919.6801422750001,0.019008906402935583,,0.021418293938040733,2,22.933425350522157,1000.0
+2434,3738624,920.0160989750001,0.015643237779537838,,0.021484386175870895,2,21.86147624059231,1000.0
+2435,3740160,920.4214116649999,0.01763915360594789,,0.02158159576356411,2,22.818094742309768,1000.0
+2436,3741696,920.794752617,0.019857648325463138,,0.021039806306362152,0,,
+2437,3743232,921.17174562,0.022337140018741288,,0.02088869735598564,1,22.120006361044943,729.0
+2438,3744768,921.5164809080001,0.010426456946879626,,0.021840661764144897,2,22.350818549341056,1000.0
+2439,3746304,921.889766071,0.015925119599948325,,0.020718753337860107,2,17.51786489872029,934.5
+2440,3747840,922.2495699080001,0.018974903443207344,,0.019871175289154053,4,18.817510950029828,745.25
+2441,3749376,922.611086088,0.015333238989114761,,0.020640388131141663,0,,
+2442,3750912,923.0067299240001,0.014922610546151797,,0.020236903801560402,3,10.993944834025266,545.0
+2443,3752448,923.354380892,0.014090771569559972,,0.021128013730049133,0,,
+2444,3753984,923.6905390790001,0.01531025574853023,,0.02063356526196003,3,23.160565436817706,1000.0
+2445,3755520,924.0405422,0.01733064992974202,,0.020983664318919182,2,19.68881568382494,1000.0
+2446,3757056,924.3604076590001,0.01565600847825408,,0.020903727039694786,1,19.31666556163691,1000.0
+2447,3758592,924.6775306559999,0.008952262221525113,,0.02089039236307144,1,20.90901632863097,1000.0
+2448,3760128,925.0285043540001,0.016255808994174004,,0.02111748605966568,2,20.833633634494618,1000.0
+2449,3761664,925.3751004449999,0.015380211515973012,,0.021278953179717064,2,16.614664194523357,1000.0
+2450,3763200,925.684329024,0.012972535410275063,,0.021757066249847412,1,21.03172366239596,1000.0
+2451,3764736,926.013568882,0.01542603267977635,,0.02128906548023224,1,24.144699103664607,1000.0
+2452,3766272,926.3238222809999,0.016806241900970537,,0.021357860416173935,0,,
+2453,3767808,926.642711392,0.018165921947608393,,0.02125183865427971,1,17.754866062197834,1000.0
+2454,3769344,926.965287202,0.014642124436795712,,0.02095150761306286,0,,
+2455,3770880,927.327477488,0.009960426421215137,,0.02064782939851284,5,18.312222353369,1000.0
+2456,3772416,927.662937744,0.007744441305597623,,0.02122899889945984,5,21.524405047786423,1000.0
+2457,3773952,927.998953331,0.01116124891365568,,0.021543871611356735,1,21.62297605816275,1000.0
+2458,3775488,928.35850909,0.02560199297343691,,0.0217757485806942,2,9.272021043405402,522.0
+2459,3777024,928.739067459,0.025441576726734638,,0.020565850660204887,2,26.94599987845868,1000.0
+2460,3778560,929.146083109,0.020333014552791913,,0.02149975299835205,4,14.802270421787398,810.25
+2461,3780096,929.5493904040001,0.013988235841194789,,0.020758986473083496,1,17.193767208606005,1000.0
+2462,3781632,929.8622685619999,0.008712323568761348,,0.021208716556429863,1,15.249256924726069,1000.0
+2463,3783168,930.183182999,0.01707725375890732,,0.021480903029441833,2,19.888434587279335,1000.0
+2464,3784704,930.5006009550001,0.01818606158097585,,0.02170151099562645,2,21.937641817261465,1000.0
+2465,3786240,930.822502421,0.018303604206691186,,0.02180609665811062,3,20.888210428180173,1000.0
+2466,3787776,931.1705570370001,0.017104574665427207,,0.02137782797217369,2,22.974695571465418,1000.0
+2467,3789312,931.4971249470001,0.01554213191072146,,0.021959159523248672,1,18.224909268319607,1000.0
+2468,3790848,931.8260885180001,0.017538472761710486,,0.0217994824051857,2,19.032640615070704,1000.0
+2469,3792384,932.1448207330001,0.01844616939003269,,0.021764537319540977,1,0.7363829466048628,49.0
+2470,3793920,932.464017036,0.01736336120714744,,0.022016411647200584,0,,
+2471,3795456,932.80022765,0.018261311420549948,,0.021606063470244408,1,29.106365532497875,1000.0
+2472,3796992,933.146523947,0.00570350286240379,,0.021789420396089554,0,,
+2473,3798528,933.5324865599999,0.0179610850289464,,0.022020939737558365,0,,
+2474,3800064,933.892894087,0.02180056820313136,,0.02182193472981453,2,27.44859552825801,1000.0
+2475,3801600,934.213048446,0.014902052500595649,,0.021422822028398514,1,19.72267595148878,1000.0
+2476,3803136,934.5355346489999,0.011391268080721299,,0.021259497851133347,2,21.80971199949272,1000.0
+2477,3804672,934.8566143490001,0.019774157491823038,,0.020770080387592316,1,29.48228099104017,1000.0
+2478,3806208,935.227394701,0.00915646217763424,,0.021799838170409203,1,24.586925478302874,1000.0
+2479,3807744,935.556900184,0.011302716347078483,,0.020867016166448593,1,20.025395589414984,1000.0
+2480,3809280,935.913998572,0.006728186582525571,,0.021806880831718445,2,21.703671446302906,1000.0
+2481,3810816,936.3044686050001,0.015002772274116675,,0.020274363458156586,3,19.82024797948543,1000.0
+2482,3812352,936.6900767590001,0.019911600525180498,,0.02200968563556671,2,20.345323266345076,1000.0
+2483,3813888,937.045219323,0.01260990258306265,,0.02153472974896431,1,23.002117205411196,1000.0
+2484,3815424,937.405283527,0.011381172761321067,,0.021588046103715897,2,16.325499123195186,1000.0
+2485,3816960,937.7135789330001,0.014310982699195543,,0.021386003121733665,1,15.59490913292393,1000.0
+2486,3818496,938.048023405,0.01130864502241214,,0.021312694996595383,3,20.09325483782838,1000.0
+2487,3820032,938.3821322100001,0.015757131700714428,,0.02151854895055294,1,17.139319486217573,1000.0
+2488,3821568,938.701024693,0.013770900790890057,,0.02184467576444149,1,21.914686779025942,1000.0
+2489,3823104,939.052153687,0.010420699945340554,,0.021537287160754204,2,29.588166215922683,1000.0
+2490,3824640,939.461248273,0.016811298237492642,,0.021719982847571373,1,21.879491430940107,1000.0
+2491,3826176,939.8306320949999,0.014548742740104596,,0.02129378542304039,2,27.131845184369013,1000.0
+2492,3827712,940.240689012,0.005781765654683113,,0.02161874622106552,0,,
+2493,3829248,940.6134258430001,0.016934860249360403,,0.021410223096609116,1,15.62511750322301,1000.0
+2494,3830784,940.942210907,0.02312482049067815,,0.021797120571136475,1,17.027813370339572,1000.0
+2495,3832320,941.3240667700001,0.004631041890631119,,0.022124221548438072,0,,
+2496,3833856,941.640717052,0.014114338097472985,,0.02199419215321541,2,21.691016227123328,1000.0
+2497,3835392,941.9948962320001,0.018312718036274114,,0.022210722789168358,6,22.206801286500802,1000.0
+2498,3836928,942.326838265,0.013308623712509871,,0.022204168140888214,1,29.602315123192966,1000.0
+2499,3838464,942.6547022850001,0.007653556267420451,,0.021673914045095444,1,30.27865290583577,1000.0
+2500,3840000,943.0394165260001,0.013591353967785835,,0.021470457315444946,2,21.050378242507577,1000.0
+2501,3841536,943.4384521640001,0.01578121855854988,,0.02177414298057556,5,15.113143016467802,815.0
+2502,3843072,943.77276154,0.008828689313183228,,0.02158113569021225,2,21.82705739454832,1000.0
+2503,3844608,944.1493825250001,0.016033313423395156,,0.02159125730395317,1,13.95990794210229,1000.0
+2504,3846144,944.547154408,0.017026185554762683,,0.021076839417219162,3,15.237612118711695,691.3333333333334
+2505,3847680,944.8969805810001,0.015386237887044747,,0.021460872143507004,2,23.71858120674733,1000.0
+2506,3849216,945.262420075,0.00996111457546552,,0.021352618932724,1,20.856367709115148,1000.0
+2507,3850752,945.6308551610001,0.016614235192537307,,0.021614938974380493,4,13.84407633941737,765.5
+2508,3852288,946.0037541089999,0.00964583291982611,,0.022534236311912537,2,21.23836338467663,1000.0
+2509,3853824,946.398018811,0.008847541020562252,,0.021846463903784752,0,,
+2510,3855360,946.738456807,0.016113628322879475,,0.02177487313747406,2,15.05889908329118,1000.0
+2511,3856896,947.10675308,0.012453502975404263,,0.021954286843538284,1,18.243748397566378,1000.0
+2512,3858432,947.48021293,0.0077320455573499204,,0.022060459479689598,0,,
+2513,3859968,947.8214261940001,0.010658934495101373,,0.022219343110919,1,27.973599531687796,1000.0
+2514,3861504,948.156512638,0.009402569476515054,,0.021457914263010025,0,,
+2515,3863040,948.484972395,0.011454267924030622,,0.02217010036110878,1,20.822605367051437,1000.0
+2516,3864576,948.8301642810001,0.013344330278535684,,0.021837366744875908,1,25.020944765768945,1000.0
+2517,3866112,949.1843143550001,0.017470473951349656,,0.022003035992383957,2,18.040212261257693,1000.0
+2518,3867648,949.539743471,0.009783928499867518,,0.022328084334731102,1,27.527688179630786,1000.0
+2519,3869184,949.8771959930001,0.0178285690334936,,0.022229280322790146,1,26.418727041222155,1000.0
+2520,3870720,950.235181846,0.015367010111610095,,0.021818533539772034,1,17.93354000337422,1000.0
+2521,3872256,950.627643032,0.01523585437486569,,0.022005364298820496,1,27.741600848850794,1000.0
+2522,3873792,951.0812781569999,0.009441821525494257,,0.02162330225110054,2,20.9870434559125,1000.0
+2523,3875328,951.4877103059999,0.0323139409845074,,0.022059164941310883,3,22.1738679985671,1000.0
+2524,3876864,951.8606352529999,0.01342585552483797,,0.02201469987630844,2,28.123528306605294,1000.0
+2525,3878400,952.1904665559999,0.024410852789878847,,0.02138923481106758,3,19.734073687771645,1000.0
+2526,3879936,952.50327551,0.014024083316326142,,0.02213939279317856,0,,
+2527,3881472,952.8206328699999,0.013823437380294006,,0.02181386575102806,1,20.10043765231967,1000.0
+2528,3883008,953.1823922730001,0.008403651198993127,,0.021652234718203545,3,22.770915325459402,1000.0
+2529,3884544,953.529633154,0.008177686979373296,,0.021562805399298668,1,19.99286654777825,1000.0
+2530,3886080,953.8478412549999,0.01132055517906944,,0.021610703319311142,1,25.30979830957949,1000.0
+2531,3887616,954.201459942,0.008615826163440943,,0.021901151165366173,3,19.606806512766827,1000.0
+2532,3889152,954.5363054990002,0.013186286048342785,,0.02172059938311577,1,17.14990043255966,1000.0
+2533,3890688,954.919740705,0.013385015353560448,,0.021714001893997192,1,24.9843766707927,1000.0
+2534,3892224,955.2932143950001,0.005010024520258108,,0.021337805315852165,0,,
+2535,3893760,955.672606131,0.00846053824449579,,0.021380368620157242,1,26.80774949444458,1000.0
+2536,3895296,956.0028637650001,0.005867314680169026,,0.021137312054634094,1,30.923359655076638,1000.0
+2537,3896832,956.319161499,0.014026731656243404,,0.021340396255254745,0,,
+2538,3898368,956.646135849,0.012289102530727784,,0.020697806030511856,4,23.087160417926498,1000.0
+2539,3899904,956.9715650520001,0.011537487898021937,,0.0210590660572052,3,21.635724627180025,1000.0
+2540,3901440,957.328559127,0.012900870169202487,,0.020822934806346893,2,21.914340673654806,1000.0
+2541,3902976,957.6673586780001,0.0029918297193944456,,0.020876018330454826,2,20.041111814556643,1000.0
+2542,3904512,957.9927676830001,0.017212767247110607,,0.021003123372793198,1,14.799105242360383,1000.0
+2543,3906048,958.344248172,0.015142717647055786,,0.02137341909110546,4,20.723299200064503,1000.0
+2544,3907584,958.669824493,0.0042107875148455305,,0.02164876088500023,2,16.634451179008465,1000.0
+2545,3909120,958.990424984,0.013654490560293197,,0.021671846508979797,1,22.74895563768223,1000.0
+2546,3910656,959.3331878370001,0.012050952451924482,,0.021265316754579544,2,26.184819622314535,1000.0
+2547,3912192,959.6693579860001,0.008241964193681875,,0.02185305580496788,2,21.343496312387288,1000.0
+2548,3913728,959.9953325719999,0.014039439397553604,,0.02179918810725212,2,27.67103826114908,1000.0
+2549,3915264,960.3489577910001,0.007874137566735348,,0.021704360842704773,3,23.46502822059362,1000.0
+2550,3916800,960.695028857,0.010878300853073597,,0.02134225331246853,1,19.519625952932984,1000.0
+2551,3918336,961.023601691,0.012964393695195515,,0.02085171267390251,0,,
+2552,3919872,961.4559556590001,0.009266342936704556,,0.021190954372286797,2,23.38685616652947,1000.0
+2553,3921408,961.905206566,0.006669263603786627,,0.02153315208852291,1,22.320936614647508,1000.0
+2554,3922944,962.348480086,0.010140892552832763,,0.02141159400343895,1,13.892473495099694,1000.0
+2555,3924480,962.741457149,0.008517592586576939,,0.02140023373067379,0,,
+2556,3926016,963.057856736,0.009307853505015373,,0.021827926859259605,0,,
+2557,3927552,963.4323889870001,0.008774450576553742,,0.02146618627011776,1,15.01783593208529,1000.0
+2558,3929088,963.772387203,0.00941494076202313,,0.02183249220252037,2,25.82572133181384,1000.0
+2559,3930624,964.1151738090001,0.012837198190391063,,0.02108834683895111,1,23.59853686147835,1000.0
+2560,3932160,964.44984483,0.009902487664173046,,0.021203458309173584,2,18.912657985580154,1000.0
+2561,3933696,964.7801754830001,0.00811388473957777,,0.02151573821902275,0,,
+2562,3935232,965.135503154,0.012546768908699353,,0.021546533331274986,1,17.847528031212278,1000.0
+2563,3936768,965.511136424,0.01150816831116875,,0.021143322810530663,2,21.472775951726362,1000.0
+2564,3938304,965.868446412,0.009725845170517762,,0.02149892970919609,2,19.644336329132784,1000.0
+2565,3939840,966.2620110880001,0.010073228552937508,,0.021710600703954697,4,18.519933232222684,1000.0
+2566,3941376,966.664305652,0.010825142823159694,,0.022129148244857788,0,,
+2567,3942912,967.0377053180001,0.011319106196363766,,0.021853934973478317,3,26.51683541779251,1000.0
+2568,3944448,967.42226294,0.0025544327994187674,,0.02177610993385315,0,,
+2569,3945984,967.77963433,0.011660261172801256,,0.021768536418676376,3,20.627080149754573,1000.0
+2570,3947520,968.173151306,0.0115740733842055,,0.02124365232884884,3,17.09787372057326,816.6666666666666
+2571,3949056,968.5660780520001,0.010101386035482088,,0.021830415353178978,1,29.555239437147975,1000.0
+2572,3950592,968.9092071480001,0.01844886348893245,,0.021181171759963036,1,15.85283971123863,1000.0
+2573,3952128,969.3194036450001,0.02167299451927344,,0.021173959597945213,3,18.99518213258125,835.6666666666666
+2574,3953664,969.7245094230001,0.013607940388222535,,0.021602392196655273,2,18.426857030717656,1000.0
+2575,3955200,970.2363889700001,0.007778070401400328,,0.02146071195602417,0,,
+2576,3956736,970.6138090000001,0.012732504835973183,,0.021230444312095642,1,20.070382271893322,1000.0
+2577,3958272,970.951852858,0.01816928790261348,,0.021648120135068893,0,,
+2578,3959808,971.3559150110001,0.008613677322864532,,0.020882226526737213,1,26.470959325670265,1000.0
+2579,3961344,971.841265639,0.011368807715674242,,0.021502625197172165,0,,
+2580,3962880,972.2655185990001,0.021001369319856168,,0.021493926644325256,5,17.457491199555808,1000.0
+2581,3964416,972.7103028820001,0.006212189855674902,,0.021954335272312164,3,21.22687060867126,1000.0
+2582,3965952,973.197618952,0.011024361724654834,,0.021407967433333397,1,27.06721281411592,1000.0
+2583,3967488,973.6879788740001,0.011798135687907536,,0.02151186764240265,2,23.58161721297074,1000.0
+2584,3969024,974.149759796,0.01249652827779452,,0.02155495248734951,3,22.16538218036294,1000.0
+2585,3970560,974.597904391,0.0237088476618131,,0.02107270434498787,3,18.551451192470267,1000.0
+2586,3972096,975.008325675,0.0167156543272237,,0.022058766335248947,1,30.195478754816577,1000.0
+2587,3973632,975.4471157480001,0.014064992281297843,,0.020532218739390373,2,7.274612874723971,534.5
+2588,3975168,975.854407165,0.018764819391071795,,0.021075885742902756,3,26.095428621124785,885.0
+2589,3976704,976.318832153,0.011548768573751053,,0.02133268117904663,2,24.40550885349512,1000.0
+2590,3978240,976.7872290430001,0.011577991768717766,,0.021139098331332207,4,20.20485579170054,1000.0
+2591,3979776,977.2966627050001,0.010173567508657774,,0.02136385068297386,2,19.87287236272823,1000.0
+2592,3981312,977.7500123630001,0.01732733122383555,,0.021725788712501526,0,,
+2593,3982848,978.091255526,0.01221703269208471,,0.021383345127105713,0,,
+2594,3984384,978.518344444,0.010628576204180718,,0.02130153775215149,1,28.64551642537117,1000.0
+2595,3985920,978.8962376580001,0.010135972903420528,,0.02147027663886547,0,,
+2596,3987456,979.3091704029999,0.019026929202179115,,0.02188030444085598,1,19.037630652543157,1000.0
+2597,3988992,979.690770435,0.010238042256484428,,0.021981969475746155,0,,
+2598,3990528,980.092366446,0.012304714663575094,,0.021856889128684998,0,,
+2599,3992064,980.5043333120001,0.015611975888411204,,0.021753322333097458,2,21.99961425526999,1000.0
+2600,3993600,980.9038858140001,0.013204385805875064,,0.021384574472904205,2,18.68742408719845,877.0
+2601,3995136,981.2788499530001,0.014513406623154878,,0.02130332589149475,2,21.80397392861778,1000.0
+2602,3996672,981.630259039,0.011687329225242137,,0.021390562877058983,0,,
+2603,3998208,981.986950134,0.008582844926665226,,0.021573714911937714,1,14.962136709713377,1000.0
+2604,3999744,982.3588030330001,0.020092157119264206,,0.021445952355861664,1,28.680777662084438,1000.0
+2605,4001280,982.7197020909999,0.008585237277050814,,0.021020343527197838,2,21.901402106217574,1000.0
+2606,4002816,983.0807130219999,0.007687336982538303,,0.021610692143440247,3,20.224195501611877,1000.0
+2607,4004352,983.511209421,0.020243308693170547,,0.02122032642364502,2,17.591635711083654,1000.0
+2608,4005888,983.930972047,0.01896496266126633,,0.02123751863837242,2,19.42246482084738,920.0
+2609,4007424,984.3567367869999,0.019325690995901822,,0.020710324868559837,3,20.274618047017913,959.0
+2610,4008960,984.7091598580001,0.004644104186445475,,0.02109229378402233,0,,
+2611,4010496,985.056266744,0.016244307967523734,,0.021326027810573578,3,19.396648346136015,1000.0
+2612,4012032,985.4330366350001,0.008093668272097905,,0.021654527634382248,2,16.9660358739784,1000.0
+2613,4013568,985.774661413,0.008922965296854575,,0.021593449637293816,1,18.770339891314507,1000.0
+2614,4015104,986.112264857,0.010463937930762768,,0.021703962236642838,2,21.304804318060633,1000.0
+2615,4016640,986.447662814,0.016050880340238414,,0.02126048505306244,0,,
+2616,4018176,986.7958160940001,0.02303686986366908,,0.02161894552409649,3,15.592913055753646,781.6666666666666
+2617,4019712,987.207972366,0.003231122624129057,,0.021592004224658012,0,,
+2618,4021248,987.584347529,0.015972366183996202,,0.02134041115641594,1,16.281027207616717,1000.0
+2619,4022784,987.898607103,0.011876333318650723,,0.02070552110671997,1,29.556427044561133,989.0
+2620,4024320,988.22580755,0.02282214614873131,,0.021209437400102615,0,,
+2621,4025856,988.6203364660001,0.027160660239557426,,0.02144169621169567,2,20.51473911269568,1000.0
+2622,4027392,988.9729159760001,0.022947137989103795,,0.021019717678427696,5,22.39187502001878,1000.0
+2623,4028928,989.304541932,0.013745734343926112,,0.022288918495178223,1,17.773873274214566,1000.0
+2624,4030464,989.6467714639999,0.014542340269933144,,0.021995937451720238,1,28.06243684096262,1000.0
+2625,4032000,989.9699760560001,0.005514724335322778,,0.021110832691192627,2,23.301017250982113,1000.0
+2626,4033536,990.3062075220001,0.011463622997204463,,0.021145520731806755,3,27.126077630363095,1000.0
+2627,4035072,990.6353501970001,0.013942802076538403,,0.020533140748739243,3,14.627413499207856,785.0
+2628,4036608,990.961352014,0.01770446905866265,,0.021189697086811066,1,18.072960803983733,1000.0
+2629,4038144,991.313353479,0.01186111184457938,,0.021243032068014145,4,18.947294468351174,1000.0
+2630,4039680,991.6631999530001,0.011609991577764352,,0.021584060043096542,2,23.71289061079733,1000.0
+2631,4041216,991.9856613370001,0.009042814342925946,,0.021589461714029312,1,14.566360676428303,1000.0
+2632,4042752,992.312298207,0.0147457093000412,,0.021467462182044983,4,25.191750036436133,1000.0
+2633,4044288,992.6320338300001,0.02013855306431651,,0.02109610289335251,2,19.185585257888306,1000.0
+2634,4045824,992.955525834,0.011393988256653149,,0.02112259343266487,0,,
+2635,4047360,993.2772955849999,0.015744165455301603,,0.021484991535544395,0,,
+2636,4048896,993.627541232,0.012979425645122925,,0.02181262895464897,1,27.098458724911325,1000.0
+2637,4050432,993.9471965399999,0.018114775760720174,,0.0215179231017828,0,,
+2638,4051968,994.330498203,0.0060023576642076176,,0.020954182371497154,2,19.56434139335761,699.0
+2639,4053504,994.707361097,0.00777731320510308,,0.02085357904434204,0,,
+2640,4055040,995.0974285799999,0.015424809201310079,,0.020977508276700974,1,27.854089711792767,1000.0
+2641,4056576,995.49634497,0.009998294649024804,,0.02095845900475979,1,23.609908863902092,1000.0
+2642,4058112,995.8322555160001,0.018649145029485226,,0.0209672711789608,3,16.569408721018892,1000.0
+2643,4059648,996.145526725,0.004088353055218856,,0.021282564848661423,0,,
+2644,4061184,996.532379894,0.020426348596811295,,0.021566152572631836,1,0.04506426665466279,70.0
+2645,4062720,996.849215843,0.012759602473427853,,0.021774109452962875,1,24.251111095421948,1000.0
+2646,4064256,997.19451902,0.02532971603795886,,0.02144724689424038,2,19.270540572993923,913.0
+2647,4065792,997.5663339690001,0.010514964070171117,,0.021519524976611137,2,22.22672342939768,1000.0
+2648,4067328,997.9022242249999,0.012940882239490747,,0.02135852724313736,3,24.875931821918737,1000.0
+2649,4068864,998.232086288,0.014384984162946542,,0.021430499851703644,2,18.4746167374542,1000.0
+2650,4070400,998.61110352,0.017499265850832064,,0.02117236517369747,4,20.498415208858205,1000.0
+2651,4071936,998.938114295,0.006811643050362666,,0.020689181983470917,1,17.133818016736768,1000.0
+2652,4073472,999.3034945620001,0.013376439114411671,,0.02093239687383175,1,0.47558679059147835,107.0
+2653,4075008,999.680122896,0.019559554321070514,,0.021284177899360657,3,22.351503959856927,1000.0
+2654,4076544,1000.0392203929999,0.032032352220267055,,0.02131234109401703,1,0.5756162777543068,102.0
+2655,4078080,1000.392728426,0.011094600986689329,,0.02174212597310543,1,18.52650457189884,1000.0
+2656,4079616,1000.7543922430001,0.009240262551854055,,0.021267786622047424,2,22.782371185952798,1000.0
+2657,4081152,1001.079578839,0.01465080790221691,,0.021332893520593643,2,17.556032168969978,1000.0
+2658,4082688,1001.4083405980001,0.019829075628270704,,0.02164093218743801,2,17.631245060823858,879.5
+2659,4084224,1001.74327944,0.0173983552493155,,0.021542787551879883,0,,
+2660,4085760,1002.066542426,0.010593504086136818,,0.021250039339065552,1,17.354090524371713,1000.0
+2661,4087296,1002.4013376270001,0.017065502579013507,,0.021869178861379623,1,18.345523203723133,1000.0
+2662,4088832,1002.728358257,0.01023053436850508,,0.021812891587615013,0,,
+2663,4090368,1003.076912439,0.015982863089690606,,0.022159826010465622,3,17.61753727631488,1000.0
+2664,4091904,1003.410619569,0.009158086869865656,,0.021845385432243347,3,28.841918214263085,1000.0
+2665,4093440,1003.7536465260001,0.01077070062359174,,0.02249331772327423,2,21.16007142997114,1000.0
+2666,4094976,1004.091112943,0.010407800258447727,,0.02159794233739376,2,18.638628042535856,1000.0
+2667,4096512,1004.4479210129999,0.008617120794951916,,0.021837886422872543,1,21.400028633885086,1000.0
+2668,4098048,1004.8304055570001,0.015782677630583445,,0.021686967462301254,3,18.24918470166934,1000.0
+2669,4099584,1005.2072024729999,0.012200386760135492,,0.02185327373445034,2,22.065330756653566,1000.0
+2670,4101120,1005.628824328,0.010017107396076122,,0.022066887468099594,1,31.440466480329633,1000.0
+2671,4102656,1006.0396810410001,0.012227388502409061,,0.022076189517974854,4,20.88956185153802,1000.0
+2672,4104192,1006.406986134,0.007889392568419378,,0.022095229476690292,2,21.164582027005963,1000.0
+2673,4105728,1006.7527439419999,0.007625835885604223,,0.021978512406349182,2,20.20362334389938,1000.0
+2674,4107264,1007.234636391,0.014577495865523815,,0.021941520273685455,3,22.43593714875169,1000.0
+2675,4108800,1007.717708285,0.013856862361232439,,0.02084110490977764,2,13.482675454753917,541.0
+2676,4110336,1008.1841115880001,0.016437441917757194,,0.021302182227373123,0,,
+2677,4111872,1008.60835113,0.010424169277151426,,0.021159939467906952,0,,
+2678,4113408,1008.96218166,0.008813756114492814,,0.020876280963420868,1,18.460913324728608,1000.0
+2679,4114944,1009.3522688440002,0.016240351709226768,,0.02082822471857071,2,17.871619184908923,1000.0
+2680,4116480,1009.705944957,0.011947973320881525,,0.021142203360795975,0,,
+2681,4118016,1010.1005640029999,0.018929302133619784,,0.02052367478609085,1,11.398891964461654,420.0
+2682,4119552,1010.5473448210001,0.019588200530658167,,0.02064439281821251,1,15.958314249059185,1000.0
+2683,4121088,1010.938430967,0.015515203929195802,,0.020878907293081284,2,25.18115021730773,1000.0
+2684,4122624,1011.3100408260001,0.013999193999916315,,0.020399153232574463,1,23.95655604498461,1000.0
+2685,4124160,1011.731560095,0.01646282027165095,,0.02052316628396511,2,16.552513673494104,749.0
+2686,4125696,1012.0685910220001,0.014375576935708522,,0.020812159404158592,0,,
+2687,4127232,1012.4360518459999,0.008154411613941193,,0.020795084536075592,1,31.50231032818556,1000.0
+2688,4128768,1012.8832696810001,0.006106265354901552,,0.020712953060865402,3,19.450779015081935,1000.0
+2689,4130304,1013.243413,0.014573403199513753,,0.020899256691336632,2,25.07521114940755,1000.0
+2690,4131840,1013.6142229339999,0.008407859162737926,,0.021041378378868103,3,21.789970697369426,1000.0
+2691,4133376,1013.944293764,0.007871252919236819,,0.021125663071870804,1,16.31552253162954,1000.0
+2692,4134912,1014.275901112,0.008224808921416601,,0.021531835198402405,2,17.286278566112742,1000.0
+2693,4136448,1014.6399710750001,0.019226198084652424,,0.021101579070091248,1,22.16007126751356,1000.0
+2694,4137984,1014.989096653,0.01806661163767179,,0.021099431440234184,3,28.092087855174515,1000.0
+2695,4139520,1015.322641399,0.019851358234882356,,0.020371047779917717,2,24.039398444001563,908.5
+2696,4141056,1015.7107817960001,0.007802810054272413,,0.020855074748396873,2,18.196023972472176,1000.0
+2697,4142592,1016.0796369610001,0.010990119632333517,,0.0206370260566473,1,25.986812998424284,1000.0
+2698,4144128,1016.4777820820001,0.01393911534299453,,0.020580757409334183,1,18.13372418709332,1000.0
+2699,4145664,1016.9391048000001,0.01756758214905858,,0.020152760669589043,4,21.68182417389471,1000.0
+2700,4147200,1017.288806699,0.01576424976810813,,0.020193366333842278,1,18.663925787433982,696.0
+2701,4148736,1017.6643603480001,0.026132261535773676,,0.019881386309862137,2,18.662161298270803,882.5
+2702,4150272,1017.9800441240001,0.01526437805344661,,0.019857916980981827,0,,
+2703,4151808,1018.2958589380002,0.012986126945664485,,0.020072143524885178,0,,
+2704,4153344,1018.652345673,0.011680593962470691,,0.019827840849757195,0,,
+2705,4154880,1018.9896197500001,0.010882474388927222,,0.01953856647014618,4,23.23409179551527,1000.0
+2706,4156416,1019.296685848,0.013029607354352872,,0.01994350180029869,1,14.977682528318837,1000.0
+2707,4157952,1019.677445555,0.018068816481779017,,0.02003626711666584,1,17.25504985358566,1000.0
+2708,4159488,1020.0103834820001,0.017783904944856963,,0.020278742536902428,2,15.911587389826309,1000.0
+2709,4161024,1020.338827619,0.015175271717210611,,0.0204758420586586,1,19.865992822684348,1000.0
+2710,4162560,1020.7172040430002,0.009224998702605566,,0.020422248169779778,4,18.351764727121918,1000.0
+2711,4164096,1021.09570843,0.00811386996259292,,0.02033224329352379,0,,
+2712,4165632,1021.459899413,0.01679256862650315,,0.02062879130244255,1,30.67075050296262,1000.0
+2713,4167168,1021.828008977,0.007892829179763795,,0.02078765630722046,3,18.830570854751084,1000.0
+2714,4168704,1022.150297609,0.01788684694717328,,0.02000945433974266,1,17.53632553119678,1000.0
+2715,4170240,1022.500843426,0.01473693766941627,,0.02057141810655594,5,17.124259799998253,920.0
+2716,4171776,1022.838056938,0.01796547758082549,,0.020440736785531044,2,19.27996753086336,1000.0
+2717,4173312,1023.1550930740001,0.03434300199151039,,0.020958691835403442,2,14.414774951233994,710.5
+2718,4174848,1023.5005788700001,0.013194376882165671,,0.0211596991866827,0,,
+2719,4176384,1023.851352258,0.011249940066287914,,0.02079000510275364,2,11.90083713142667,557.0
+2720,4177920,1024.179637424,0.008959207590669394,,0.0209219790995121,0,,
+2721,4179456,1024.521746406,0.021766366685430208,,0.020971832796931267,2,19.323911722342018,1000.0
+2722,4180992,1024.857971926,0.02766971178352833,,0.020551839843392372,1,7.704604218131863,324.0
+2723,4182528,1025.174237361,0.008886993117630481,,0.020820749923586845,1,13.379941789899021,1000.0
+2724,4184064,1025.527176973,0.011649033023665349,,0.02142045460641384,1,20.95470545371063,1000.0
+2725,4185600,1025.874350528,0.015524420390526454,,0.020874258130788803,2,22.15728602191666,1000.0
+2726,4187136,1026.204884798,0.005225306500991186,,0.020867343991994858,1,27.782184643670917,1000.0
+2727,4188672,1026.540483968,0.031445043223599596,,0.02057768404483795,2,21.00063459179364,1000.0
+2728,4190208,1026.934696224,0.014565811306238175,,0.020752664655447006,1,14.109568923944607,1000.0
+2729,4191744,1027.3226313549999,0.01204348069926103,,0.02050129510462284,1,29.827127466909587,1000.0
+2730,4193280,1027.775686391,0.016363101235280435,,0.020644232630729675,3,17.184862773826655,1000.0
+2731,4194816,1028.1050946,0.01167795176928242,,0.020699528977274895,2,16.33085013681557,1000.0
+2732,4196352,1028.4245745009998,0.010725516360253096,,0.02077224664390087,1,27.094641305040568,1000.0
+2733,4197888,1028.767653192,0.007389039049545924,,0.020742012187838554,1,25.859671134036034,1000.0
+2734,4199424,1029.088553131,0.01258491287007928,,0.02026313915848732,3,20.171520901533466,1000.0
+2735,4200960,1029.449786125,0.006434647925198078,,0.02094748429954052,0,,
+2736,4202496,1029.82066919,0.01634972890218099,,0.020704135298728943,5,21.347716882114764,1000.0
+2737,4204032,1030.135210771,0.0017142198358972868,,0.02130747213959694,0,,
+2738,4205568,1030.474017524,0.011476177194466194,,0.020415838807821274,2,18.278078957489925,1000.0
+2739,4207104,1030.823270375,0.012421362070987622,,0.02070874720811844,2,20.525766332109924,1000.0
+2740,4208640,1031.1450584959998,0.0031865728087723255,,0.02129770815372467,0,,
+2741,4210176,1031.503140755,0.007301020653297504,,0.02146701142191887,4,21.798057449399494,1000.0
+2742,4211712,1031.927185675,0.007668408347914616,,0.02165074273943901,0,,
+2743,4213248,1032.2639605309998,0.005764001980423927,,0.02142205648124218,2,14.312091587169562,1000.0
+2744,4214784,1032.583121719,0.011123304907232522,,0.021126728504896164,0,,
+2745,4216320,1032.91035358,0.011624627405156691,,0.02101314626634121,0,,
+2746,4217856,1033.233671949,0.00466181319206953,,0.021282494068145752,1,23.141801471821964,1000.0
+2747,4219392,1033.6129780249998,0.0032121238298714163,,0.02163306623697281,4,20.234204224398127,1000.0
+2748,4220928,1033.950907668,0.012998075596988201,,0.021864136680960655,0,,
+2749,4222464,1034.271326046,0.005694639837990205,,0.021665647625923157,1,30.01876950636506,1000.0
+2750,4224000,1034.597790843,0.016758330445736647,,0.022063452750444412,2,17.70630889281165,1000.0
+2751,4225536,1034.91868426,0.015297421502570312,,0.021678559482097626,1,15.900706223910674,1000.0
+2752,4227072,1035.32363461,0.00833361263697346,,0.02166667953133583,3,22.578482904393848,1000.0
+2753,4228608,1035.679010056,0.018830574862658978,,0.021578948944807053,0,,
+2754,4230144,1036.016526768,0.01026000672330459,,0.02093471586704254,4,22.02507545024855,977.0
+2755,4231680,1036.347947838,0.01414102278649807,,0.021438676863908768,1,26.980609967606142,1000.0
+2756,4233216,1036.67626905,0.008178921975195408,,0.02142595313489437,0,,
+2757,4234752,1037.030233694,0.019821367133408783,,0.02030840888619423,5,21.72395718425978,1000.0
+2758,4236288,1037.3710811229998,0.023427020385861398,,0.0215231254696846,3,17.907565026311204,732.0
+2759,4237824,1037.804506368,0.016667262526849906,,0.021915366873145103,1,18.42801147000864,1000.0
+2760,4239360,1038.1975560449998,0.014757806776712339,,0.02261439524590969,1,18.682766414014623,1000.0
+2761,4240896,1038.594660861,0.009531384520232677,,0.021436331793665886,1,14.54025663988432,1000.0
+2762,4242432,1038.9145534939998,0.01354700264831384,,0.02260616421699524,0,,
+2763,4243968,1039.2512123909999,0.008556796641399463,,0.021211761981248856,2,22.793048057472333,1000.0
+2764,4245504,1039.602889414,0.012343651335686445,,0.021003007888793945,2,12.862170164531562,624.0
+2765,4247040,1039.9371439289998,0.011010919821759065,,0.02109335921704769,2,22.91466574923834,1000.0
+2766,4248576,1040.25683478,0.019653796466688314,,0.02182868868112564,0,,
+2767,4250112,1040.592597541,0.03613644012560447,,0.020993759855628014,5,15.132661055400968,811.0
+2768,4251648,1040.921983603,0.007117462965349357,,0.02214367501437664,0,,
+2769,4253184,1041.2512663969999,0.010045030837257702,,0.021556882187724113,2,22.19537478586426,1000.0
+2770,4254720,1041.63435759,0.01519436106706659,,0.021935932338237762,1,18.54611037543509,1000.0
+2771,4256256,1041.97556378,0.013990439847111702,,0.021549589931964874,2,18.31185051216744,1000.0
+2772,4257792,1042.327876187,0.021668550247947376,,0.02094295620918274,3,22.70902887126431,958.0
+2773,4259328,1042.71855149,0.01725603062659502,,0.02234678529202938,2,19.366994936484843,1000.0
+2774,4260864,1043.0452667529999,0.014980089943856,,0.021644018590450287,1,27.354757256805897,1000.0
+2775,4262400,1043.373200814,0.014954480590919654,,0.021928412839770317,2,18.678318848949857,1000.0
+2776,4263936,1043.7398294569998,0.009062676442166169,,0.022236716002225876,1,16.27602952509187,1000.0
+2777,4265472,1044.0613004919999,0.011808518754939238,,0.022531798109412193,1,17.23109073447995,1000.0
+2778,4267008,1044.3916772779999,0.015932447059700885,,0.0223417729139328,3,21.485714774540003,1000.0
+2779,4268544,1044.7107818119998,0.0150682274873058,,0.022695031017065048,1,14.528402597061358,1000.0
+2780,4270080,1045.04350495,0.014848143327981234,,0.02247961238026619,1,21.908592864405364,1000.0
+2781,4271616,1045.389869698,0.014295181973526876,,0.02229028008878231,2,26.526497706829105,1000.0
+2782,4273152,1045.767960423,0.010945690982043742,,0.02221713960170746,1,21.322347836452536,1000.0
+2783,4274688,1046.121765848,0.012294103267292182,,0.021880431100726128,3,24.957611548093457,1000.0
+2784,4276224,1046.4488962369999,0.014881967380642892,,0.022175228223204613,1,17.48768077616114,1000.0
+2785,4277760,1046.8034055849998,0.01957595112423102,,0.022399041801691055,2,18.652945618669037,844.5
+2786,4279296,1047.1291505709999,0.02764728730544448,,0.021604660898447037,1,24.33277102408465,940.0
+2787,4280832,1047.4508971169998,0.007301007211208343,,0.02184915915131569,0,,
+2788,4282368,1047.8810755519999,0.007004920703669389,,0.022168677300214767,2,20.90752313681878,1000.0
+2789,4283904,1048.319864048,0.01586565760274728,,0.02163190208375454,2,22.991251964936964,1000.0
+2790,4285440,1048.712945667,0.0320655923957626,,0.021646276116371155,2,25.854432825406548,925.0
+2791,4286976,1049.109079327,0.019934775152554114,,0.022237300872802734,1,18.561684960266575,1000.0
+2792,4288512,1049.4669285559999,0.031655379788329205,,0.021738624200224876,1,16.13784627674613,824.0
+2793,4290048,1049.840696515,0.01961358285819491,,0.021521415561437607,3,18.537507483852096,1000.0
+2794,4291584,1050.1587505759999,0.009761210655172665,,0.022274192422628403,1,14.989885808434337,1000.0
+2795,4293120,1050.4895164549998,0.011296348522106807,,0.02218487858772278,0,,
+2796,4294656,1050.818181406,0.01647276102254788,,0.022083837538957596,3,20.010524263450254,1000.0
+2797,4296192,1051.139068812,0.009999479601780574,,0.022207802161574364,0,,
+2798,4297728,1051.45807744,0.018508972382793823,,0.022030701860785484,1,29.849774539936334,1000.0
+2799,4299264,1051.849282805,0.010235654034962257,,0.021492397412657738,3,26.89108688974132,1000.0
+2800,4300800,1052.1752905839999,0.01112377659107248,,0.022119885310530663,2,22.33894753549248,1000.0
+2801,4302336,1052.5173021159999,0.007821317079166572,,0.02213125303387642,0,,
+2802,4303872,1052.8399543219998,0.011177147769679626,,0.021781109273433685,2,9.563499540090561,535.5
+2803,4305408,1053.2083539779999,0.017610613163560628,,0.02218325063586235,1,15.659775073174387,1000.0
+2804,4306944,1053.56946887,0.007649234558145205,,0.022149180993437767,2,18.45383189659333,1000.0
+2805,4308480,1053.925178557,0.016496802711238465,,0.02221078984439373,0,,
+2806,4310016,1054.286895028,0.01331284608071049,,0.02187993749976158,4,21.28745898065972,854.75
+2807,4311552,1054.613349942,0.008996662466476362,,0.02236638031899929,1,21.91124895820394,1000.0
+2808,4313088,1054.950641118,0.01841753019640843,,0.022419428452849388,3,23.589432423662704,1000.0
+2809,4314624,1055.275713868,0.022074172645807265,,0.021698875352740288,3,16.284145367564633,917.3333333333334
+2810,4316160,1055.6325842239999,0.01548451321820418,,0.021666310727596283,3,18.20513338314292,724.0
+2811,4317696,1055.9898800839999,0.008967525822420915,,0.021369894966483116,0,,
+2812,4319232,1056.318471637,0.02227696869522333,,0.02134033665060997,1,25.481955301831476,1000.0
+2813,4320768,1056.667343137,0.010725518440206845,,0.021737828850746155,3,19.441487598737393,1000.0
+2814,4322304,1057.008509239,0.011540574269990127,,0.021388597786426544,3,24.354057810851373,1000.0
+2815,4323840,1057.3378386309998,0.008540601966281732,,0.021538501605391502,2,19.08771187264938,1000.0
+2816,4325376,1057.7014955759998,0.013304391565422216,,0.021771155297756195,0,,
+2817,4326912,1058.0455687249998,0.01055702663337191,,0.021852780133485794,2,27.112429153174162,1000.0
+2818,4328448,1058.4138645639998,0.007994363270699977,,0.021779432892799377,1,17.494209163240157,1000.0
+2819,4329984,1058.8370770889999,0.01115959081798792,,0.02176094613969326,3,16.82870155623338,705.6666666666666
+2820,4331520,1059.22957463,0.011968189322700103,,0.022180072963237762,1,20.25318954512477,1000.0
+2821,4333056,1059.687750714,0.009301971426854532,,0.022020705044269562,2,24.648574097605888,1000.0
+2822,4334592,1060.088118977,0.014348651592930159,,0.022271156311035156,1,25.262682824395597,1000.0
+2823,4336128,1060.412500707,0.00952616399154067,,0.021756749600172043,1,21.060706908348948,1000.0
+2824,4337664,1060.7521193349999,0.016509501139322917,,0.021687276661396027,3,20.095162309046525,1000.0
+2825,4339200,1061.0917312259999,0.008193917696674664,,0.021712642163038254,1,30.94968018284999,1000.0
+2826,4340736,1061.419827744,0.012209159415215253,,0.02142885886132717,2,29.347848111297935,1000.0
+2827,4342272,1061.778738695,0.009124090584615866,,0.021548589691519737,1,18.080750136636198,1000.0
+2828,4343808,1062.108441635,0.008014684108396371,,0.021324612200260162,1,14.10014625202166,1000.0
+2829,4345344,1062.427239077,0.017544275304923456,,0.021472502499818802,0,,
+2830,4346880,1062.759184692,0.00782042946666479,,0.021207939833402634,2,16.03408860246418,1000.0
+2831,4348416,1063.133156889,0.005758682110657294,,0.02160348743200302,1,14.5671494678827,1000.0
+2832,4349952,1063.529591514,0.0100588608533144,,0.02120113931596279,2,25.190961118554696,1000.0
+2833,4351488,1063.956735283,0.013556607067584991,,0.021452900022268295,1,17.55129798373673,1000.0
+2834,4353024,1064.3121159989998,0.004523967082301776,,0.0212844368070364,1,16.082512322813272,1000.0
+2835,4354560,1064.6506192309998,0.011298517603427172,,0.020592181012034416,5,17.983767296210864,815.0
+2836,4356096,1065.0026744689999,0.009741692089786131,,0.021259721368551254,0,,
+2837,4357632,1065.353493012,0.020894193338851133,,0.021035168319940567,0,,
+2838,4359168,1065.746516577,0.01197596937417984,,0.021242020651698112,3,18.243884512553148,1000.0
+2839,4360704,1066.145424223,0.011321182331691186,,0.021504677832126617,0,,
+2840,4362240,1066.653929659,0.01652640433361133,,0.020988471806049347,4,21.689998355461285,902.25
+2841,4363776,1067.106049454,0.011512675819297631,,0.021358683705329895,0,,
+2842,4365312,1067.473931286,0.014335856214165688,,0.021224236115813255,2,30.329905750229955,1000.0
+2843,4366848,1067.829916474,0.019046812566618124,,0.02124108001589775,0,,
+2844,4368384,1068.164214578,0.009306436621894438,,0.020994579419493675,2,19.65512564193341,1000.0
+2845,4369920,1068.520053067,0.01357084723810355,,0.02153130993247032,0,,
+2846,4371456,1068.856834584,0.013476386635253827,,0.021504929289221764,2,24.520206335000694,1000.0
+2847,4372992,1069.2152141939998,0.017225152937074502,,0.021607782691717148,2,24.001592030981556,1000.0
+2848,4374528,1069.572716634,0.014453466422855854,,0.02143421582877636,2,23.342086110264063,1000.0
+2849,4376064,1070.013181031,0.006264688602338235,,0.021206721663475037,1,21.731029535643756,1000.0
+2850,4377600,1070.420147907,0.017281634515772262,,0.021188383921980858,4,18.549598733021412,1000.0
+2851,4379136,1070.813928954,0.016042276564985514,,0.02134872041642666,2,22.84851187642198,1000.0
+2852,4380672,1071.1292000639999,0.014953661523759366,,0.02169245481491089,3,14.12932182852334,1000.0
+2853,4382208,1071.4413178529999,0.012539075097690026,,0.021897844970226288,1,19.90272713813465,1000.0
+2854,4383744,1071.807679785,0.009915299278994401,,0.021456798538565636,1,27.144772324711084,1000.0
+2855,4385280,1072.146694032,0.013373575545847416,,0.02193712443113327,2,22.698476240213495,1000.0
+2856,4386816,1072.4781484119999,0.00786275261392196,,0.021942442283034325,2,19.599041006120387,1000.0
+2857,4388352,1072.795527071,0.016600729338824748,,0.021836623549461365,1,22.71649976633489,1000.0
+2858,4389888,1073.129424929,0.01488399701192975,,0.02186012640595436,0,,
+2859,4391424,1073.524442127,0.008155398753782113,,0.02096681296825409,3,23.0910906943415,1000.0
+2860,4392960,1073.945956217,0.010777981672435998,,0.021621908992528915,1,28.2459133209195,1000.0
+2861,4394496,1074.370578582,0.011434875490764777,,0.021684318780899048,3,20.263067652199727,1000.0
+2862,4396032,1074.753333935,0.015632425372799238,,0.021750330924987793,0,,
+2863,4397568,1075.142585368,0.013296941481530666,,0.021221883594989777,2,24.84906422777567,1000.0
+2864,4399104,1075.487524662,0.01271009367580215,,0.02168746292591095,2,20.0864031733945,1000.0
+2865,4400640,1075.8605030439999,0.015321147628128529,,0.02171918749809265,0,,
+2866,4402176,1076.215594369,0.016864892685165007,,0.02208903059363365,4,23.458518724073656,1000.0
+2867,4403712,1076.5814881869999,-0.0008602199144661426,,0.02215302549302578,0,,
+2868,4405248,1076.921354185,0.023193494696170092,,0.02193734608590603,2,18.62527824100107,1000.0
+2869,4406784,1077.2933351079998,0.010163053683936597,,0.022174587473273277,2,19.270843842532486,1000.0
+2870,4408320,1077.653878727,0.013900816378494104,,0.022275827825069427,0,,
+2871,4409856,1078.06126755,0.010405922339608272,,0.022375112399458885,1,16.409408825449646,1000.0
+2872,4411392,1078.467055073,0.006636107278366884,,0.02251563034951687,2,15.056159913365263,1000.0
+2873,4412928,1078.96481757,0.013564618149151405,,0.02263479307293892,1,29.652242829673924,1000.0
+2874,4414464,1079.418471887,0.014845003001391887,,0.022249609231948853,0,,
+2875,4416000,1079.814529287,0.009977040564020474,,0.022161370143294334,2,17.332298276596703,1000.0
+2876,4417536,1080.143821509,0.01148053507010142,,0.022555455565452576,1,30.715309165418148,1000.0
+2877,4419072,1080.629278596,0.0102255931434532,,0.022159412503242493,4,19.602679433388403,1000.0
+2878,4420608,1081.134375169,0.01653400876869758,,0.022591769695281982,0,,
+2879,4422144,1081.5807602799998,0.009091094601899385,,0.022073894739151,2,26.714669905602932,1000.0
+2880,4423680,1082.007696515,0.008241165118912855,,0.022284433245658875,1,23.68440347723663,1000.0
+2881,4425216,1082.455846697,0.01500708938886722,,0.021652696654200554,0,,
+2882,4426752,1082.9204787859999,0.015653313292811315,,0.02222280576825142,5,15.039092149271164,809.2
+2883,4428288,1083.311569342,0.006273165345191956,,0.022622033953666687,1,29.992798290681094,1000.0
+2884,4429824,1083.773819651,0.01753971024105946,,0.022443627938628197,1,25.318609523645137,1000.0
+2885,4431360,1084.1750321519999,0.014162764263649782,,0.02223200909793377,1,28.56598753691651,1000.0
+2886,4432896,1084.576040927,0.009001326685150465,,0.02236345410346985,1,21.28146332502365,1000.0
+2887,4434432,1085.060131423,0.010947935624668996,,0.022074278444051743,0,,
+2888,4435968,1085.4907114129999,0.018855494136611622,,0.022116651758551598,3,13.28376729413867,684.3333333333334
+2889,4437504,1085.955844028,0.014220114114383857,,0.022365015000104904,2,22.166210398077965,1000.0
+2890,4439040,1086.376227928,0.024783539958298205,,0.02281109057366848,3,17.2736553271922,1000.0
+2891,4440576,1086.7884715149999,0.012073915296544632,,0.022060420364141464,0,,
+2892,4442112,1087.219571594,0.006157205781588951,,0.022644057869911194,6,20.028085592125233,843.3333333333334
+2893,4443648,1087.573595218,0.012295819539576768,,0.02276410162448883,2,17.097284349554684,1000.0
+2894,4445184,1087.9485914319998,0.012753159180283547,,0.02285265550017357,2,24.29567287309328,1000.0
+2895,4446720,1088.3354622969998,0.021277259569615126,,0.023066362366080284,1,21.40787943918258,1000.0
+2896,4448256,1088.7353173279998,0.010310538113117218,,0.022823264822363853,2,23.9162815308664,1000.0
+2897,4449792,1089.225695314,0.011226586469759544,,0.02307868003845215,2,20.668573676375672,1000.0
+2898,4451328,1089.723045497,0.010653962877889474,,0.023092549294233322,1,25.442432450130582,1000.0
+2899,4452864,1090.2567561619999,0.026088328224917252,,0.02291841432452202,1,25.052344461902976,1000.0
+2900,4454400,1090.733382762,0.013028874682883421,,0.02271423116326332,2,18.5833147506346,1000.0
+2901,4455936,1091.2225395359999,0.01813312474017342,,0.022851673886179924,1,27.673755556344986,1000.0
+2902,4457472,1091.642691927,0.008767524951448042,,0.022505193948745728,3,20.849905752576888,747.6666666666666
+2903,4459008,1092.2195747399999,0.015500747909148535,,0.022234827280044556,3,12.875417881140796,683.3333333333334
+2904,4460544,1092.713005357,0.015116451277087132,,0.022241953760385513,2,16.252762495947536,766.5
+2905,4462080,1093.187179032,0.01881898585706949,,0.022822923958301544,1,23.361612881650217,1000.0
+2906,4463616,1093.6331741689999,0.008328719437122345,,0.02230394445359707,3,17.247430151328444,795.3333333333334
+2907,4465152,1094.175973445,0.011038790829479695,,0.02264336496591568,1,28.94681380316615,1000.0
+2908,4466688,1094.668990102,0.007714893203228712,,0.02160165272653103,3,22.869576247408986,1000.0
+2909,4468224,1095.1651113359999,0.01191431215653817,,0.02181791327893734,2,20.65185759635642,710.5
+2910,4469760,1095.5872825509998,0.015273196374376614,,0.02178303152322769,3,20.300709493846323,837.3333333333334
+2911,4471296,1096.012657862,0.006546554776529471,,0.021471191197633743,1,26.874935369938612,1000.0
+2912,4472832,1096.3781611519998,0.012439376829812923,,0.021656006574630737,0,,
+2913,4474368,1096.776712725,0.011541084510584672,,0.021741768345236778,2,19.49099705525441,1000.0
+2914,4475904,1097.2259784179998,0.008643846493214369,,0.022190116345882416,1,14.134481699671596,1000.0
+2915,4477440,1097.628386852,0.008832092117518186,,0.022038359194993973,1,16.289790543727577,1000.0
+2916,4478976,1098.036060986,0.011080588214099407,,0.02200145646929741,1,19.968278889544308,1000.0
+2917,4480512,1098.453245407,0.0023669305567940078,,0.022262226790189743,1,24.604139318689704,1000.0
+2918,4482048,1098.854022002,0.018828391035397848,,0.02220405451953411,4,21.032720786548452,1000.0
+2919,4483584,1099.24702102,0.010517437352488439,,0.022325344383716583,1,23.89623963087797,1000.0
+2920,4485120,1099.6218141079999,0.011788310327877602,,0.022149719297885895,0,,
+2921,4486656,1100.025878658,0.019954293438543876,,0.021741269156336784,2,23.92768751110998,1000.0
+2922,4488192,1100.378483775,0.030051473962763944,,0.021487325429916382,2,6.032441528979689,281.5
+2923,4489728,1100.7829017029999,0.012736720653871695,,0.021878531202673912,2,29.810744303744286,1000.0
+2924,4491264,1101.162851906,0.006232573712865511,,0.02156371995806694,2,22.412179626408033,1000.0
+2925,4492800,1101.5665718839998,0.01811757544055581,,0.0208992138504982,2,21.674927522079088,1000.0
+2926,4494336,1102.016707093,0.011497497310241063,,0.02134495973587036,0,,
+2927,4495872,1102.496151116,0.02070350417246421,,0.020691167563199997,1,20.67705714330077,1000.0
+2928,4497408,1102.895224535,0.010794323061903317,,0.021228140220046043,0,,
+2929,4498944,1103.32570956,0.02739960253238678,,0.02062983065843582,4,14.04289534149575,782.5
+2930,4500480,1103.794684319,0.011813800999273856,,0.02126595377922058,0,,
+2931,4502016,1104.199490233,0.00600124883155028,,0.020804397761821747,1,19.167184863996226,1000.0
+2932,4503552,1104.5613203369999,0.0086090838847061,,0.02115294337272644,1,13.929835859918967,1000.0
+2933,4505088,1104.98994064,0.015373524899284044,,0.021027423441410065,2,16.825361668888945,1000.0
+2934,4506624,1105.355272374,0.016393324236075084,,0.021370448172092438,3,21.85718466133888,1000.0
+2935,4508160,1105.781824551,0.01907051478823026,,0.021448809653520584,3,22.845765578056064,1000.0
+2936,4509696,1106.162347768,0.009666756882021824,,0.021382715553045273,0,,
+2937,4511232,1106.518977875,0.00790449297055602,,0.020931541919708252,1,31.073411175981164,1000.0
+2938,4512768,1106.992056496,0.0038702461247642835,,0.021059192717075348,3,25.442565250753734,1000.0
+2939,4514304,1107.4377561219999,0.019236520305275916,,0.021174948662519455,2,21.154458444274496,1000.0
+2940,4515840,1107.898719719,0.006781315679351489,,0.021268203854560852,1,25.931458981591277,1000.0
+2941,4517376,1108.438885545,0.005326779807607333,,0.020743772387504578,0,,
+2942,4518912,1108.839896468,0.008615495668103297,,0.02060207538306713,2,25.990860980004072,1000.0
+2943,4520448,1109.201851758,0.009941012226045131,,0.02070648781955242,1,20.423213576432317,1000.0
+2944,4521984,1109.623612334,0.01014344890912374,,0.02084812894463539,2,28.4803385627456,1000.0
+2945,4523520,1110.0095919409998,0.014047381902734439,,0.020612036809325218,2,21.844964586023707,1000.0
+2946,4525056,1110.4017438859998,0.011835542973130941,,0.02043784223496914,4,24.950214940239675,959.0
+2947,4526592,1110.772042162,0.004522957342366378,,0.020887456834316254,1,16.458008169196546,1000.0
+2948,4528128,1111.2140481899999,0.0022771854574481646,,0.02070869505405426,2,20.850191279954743,1000.0
+2949,4529664,1111.704731883,0.019301620374123255,,0.02028113231062889,5,10.751079321280121,632.6
+2950,4531200,1112.22243273,0.011628165654838086,,0.02135605737566948,1,18.00711359118577,1000.0
+2951,4532736,1112.682844024,0.014137523435056209,,0.021111037582159042,3,20.349292642126482,1000.0
+2952,4534272,1113.1003032659999,0.011756126148005327,,0.020988857373595238,2,17.317787751730066,1000.0
+2953,4535808,1113.590366253,0.013296692663182815,,0.02091800794005394,0,,
+2954,4537344,1114.092063007,0.03125607954959075,,0.02041187323629856,0,,
+2955,4538880,1114.547143608,0.009384020976722241,,0.02070869505405426,2,25.017291803378612,1000.0
+2956,4540416,1115.033006137,0.013408881643166145,,0.020955890417099,1,29.999552042922005,1000.0
+2957,4541952,1115.505167563,0.015550067524115245,,0.0205680038779974,1,21.481053278781474,1000.0
+2958,4543488,1115.989192117,0.016077577353765568,,0.020660553127527237,1,16.722787595703267,1000.0
+2959,4545024,1116.4964045739998,0.014657150302082301,,0.020784050226211548,1,15.24639172712341,1000.0
+2960,4546560,1116.958914241,0.008598009745279947,,0.0203036330640316,4,22.886051739915274,1000.0
+2961,4548096,1117.364758861,0.013911092032988867,,0.020388567820191383,1,11.83672136021778,398.0
+2962,4549632,1117.8049930119998,0.012636733365555604,,0.020496416836977005,0,,
+2963,4551168,1118.268290081,0.014626993332058191,,0.020399726927280426,4,18.209283044881886,989.25
+2964,4552704,1118.752680957,0.009238594335814317,,0.021052274852991104,1,13.741753702517599,1000.0
+2965,4554240,1119.137919912,0.012905348837375642,,0.021446343511343002,2,13.309842657181434,1000.0
+2966,4555776,1119.593029889,0.009840889057765404,,0.021617576479911804,0,,
+2967,4557312,1119.9835225909999,0.011619809394081434,,0.021040815860033035,2,14.77423845184967,1000.0
+2968,4558848,1120.364855951,0.01296924582372109,,0.02184203639626503,0,,
+2969,4560384,1120.761713384,0.017244770377874374,,0.021507948637008667,1,15.979057257529348,1000.0
+2970,4561920,1121.167279235,0.008876089161882797,,0.021559130400419235,1,23.613280648365617,1000.0
+2971,4563456,1121.552372874,0.017030546193321547,,0.02174905501306057,3,21.683200151426718,1000.0
+2972,4564992,1122.007269712,0.009381177959342797,,0.02156907320022583,1,8.78515941312071,408.0
+2973,4566528,1122.40219641,0.006010668476422628,,0.022017618641257286,1,13.645686362404376,1000.0
+2974,4568064,1122.758175024,0.019294091903915008,,0.022125165909528732,1,24.294627859722823,1000.0
+2975,4569600,1123.190706783,0.011991243157535792,,0.021784793585538864,3,25.06836531870067,1000.0
+2976,4571136,1123.5733907919998,0.005383993188540141,,0.02193714678287506,2,19.781144495907938,1000.0
+2977,4572672,1123.999930626,0.016360504366457463,,0.020653000101447105,4,23.943097834970104,984.75
+2978,4574208,1124.3797595689998,0.009270887263119221,,0.021262608468532562,1,14.363218716578558,1000.0
+2979,4575744,1124.770270687,0.005237018006543318,,0.02149033546447754,1,24.823574903421104,1000.0
+2980,4577280,1125.232856869,0.019200452199826638,,0.021410364657640457,1,21.79255382437259,1000.0
+2981,4578816,1125.7217539609999,0.012782265059649944,,0.021066179499030113,2,20.71950198034756,1000.0
+2982,4580352,1126.187616879,0.01012777875488003,,0.021124256774783134,1,15.35054942779243,1000.0
+2983,4581888,1126.582031207,0.016712193563580512,,0.02138037607073784,0,,
+2984,4583424,1126.979493615,0.015817665494978428,,0.02109881304204464,2,22.432952982431743,1000.0
+2985,4584960,1127.3809929289998,0.017868328156570593,,0.021122343838214874,1,16.951345349196345,1000.0
+2986,4586496,1127.857854371,0.017747034784406424,,0.021215707063674927,3,20.425524688248213,876.0
+2987,4588032,1128.336220623,0.008971454668790102,,0.02116798236966133,2,20.5217981285532,1000.0
+2988,4589568,1128.746343764,0.011881744302809239,,0.02102586440742016,1,23.46616454521427,1000.0
+2989,4591104,1129.168329634,0.025148129370063544,,0.02133110910654068,3,17.262758932852496,1000.0
+2990,4592640,1129.613984653,0.021378985357781252,,0.021328698843717575,2,20.746606628817972,732.0
+2991,4594176,1130.096104172,0.01616788553074002,,0.02114899270236492,5,20.499891519965605,1000.0
+2992,4595712,1130.5377557499999,0.012231937237083912,,0.021169859915971756,1,18.145169266383164,950.0
+2993,4597248,1130.947067595,0.007639867688218753,,0.021017666906118393,3,22.82617072908518,1000.0
+2994,4598784,1131.284948565,0.0219361520682772,,0.020798295736312866,1,20.309627095237374,1000.0
+2995,4600320,1131.6313525219998,0.008749723124007383,,0.02097674086689949,0,,
+2996,4601856,1132.0020567289998,0.007718581861505906,,0.021298322826623917,0,,
+2997,4603392,1132.418489506,0.005848295334726572,,0.02081860974431038,2,19.968004593916703,1000.0
+2998,4604928,1132.836404182,0.0036859224860866864,,0.020954720675945282,1,15.499054651590995,1000.0
+2999,4606464,1133.2436021649999,0.011731863083938757,,0.021292081102728844,0,,
+3000,4608000,1133.6835723489999,0.017177134690185388,,0.020334310829639435,3,22.138293247941572,962.0
diff --git a/results/rma/forward_v1/training_summary.json b/results/rma/forward_v1/training_summary.json
new file mode 100644
index 000000000..8178c5d9a
--- /dev/null
+++ b/results/rma/forward_v1/training_summary.json
@@ -0,0 +1,37 @@
+{
+ "iterations": 3000,
+ "total_transitions": 4608000,
+ "wall_seconds": 1133.6835723489999,
+ "reward_blocks": [
+ {
+ "first_iteration": 1,
+ "last_iteration": 500,
+ "mean_step_reward": 0.0209264800529927
+ },
+ {
+ "first_iteration": 501,
+ "last_iteration": 1000,
+ "mean_step_reward": 0.02189977381750941
+ },
+ {
+ "first_iteration": 1001,
+ "last_iteration": 1500,
+ "mean_step_reward": 0.02167243344336748
+ },
+ {
+ "first_iteration": 1501,
+ "last_iteration": 2000,
+ "mean_step_reward": 0.021493670616298914
+ },
+ {
+ "first_iteration": 2001,
+ "last_iteration": 2500,
+ "mean_step_reward": 0.021966765146702528
+ },
+ {
+ "first_iteration": 2501,
+ "last_iteration": 3000,
+ "mean_step_reward": 0.021465577770024537
+ }
+ ]
+}
diff --git a/results/rma/provenance.json b/results/rma/provenance.json
new file mode 100644
index 000000000..6ef5dfabb
--- /dev/null
+++ b/results/rma/provenance.json
@@ -0,0 +1,91 @@
+{
+ "captured_date": "2026-10-22",
+ "fork_base_commit": "c19b8810059e3c495dc5394a5652d3c82c00f70f",
+ "runtime_upstream_commit": null,
+ "runtime_upstream_commit_note": "Source-only copy has no Git history; provenance is not inferred from the fork.",
+ "python_version": "3.10.12",
+ "installed_distributions": {
+ "torch": "2.14.0+cu130",
+ "mujoco": "3.11.0",
+ "unilab": "1.3.3",
+ "unisim-core": "1.7.11",
+ "hydra-core": "1.3.2",
+ "numpy": "2.2.6",
+ "tensorboard": "2.21.0",
+ "matplotlib": "3.10.8"
+ },
+ "pasted_evaluation_source_sha256": "84c5a993f2a6a18f881e76c9b1486da67ad89c488bae4fde127f8dd382179239",
+ "original_run_config_sha256": "8fa159eab801ec3dc9762e932a6a720c5c9751def83ee8ca8d6e0d1985e7aa0f",
+ "training_csv_sha256": "70323752806b1fa8eb91d34ead7191ba5ef46d1d94935f59db85b84fd072bead",
+ "source_files": {
+ "deploy_cpp/CMakeLists.txt": "3fcf0e81fef555bb345342c3d924dbfd97fe0748a8e6197dcdc22372fb934520",
+ "deploy_cpp/include/DoubleBuffer.hpp": "4575b644ebc89f50ed0a797d1f418283b3f4776714025de8cd2ba63f841d3be5",
+ "deploy_cpp/include/TensorRTPolicy.hpp": "fb680179702c6bd22b38c8064b77b7d01e80d1c39d8666ec6628736bd4e1f85e",
+ "deploy_cpp/src/main_control_loop.cpp": "d77b818d82b7a6287959466ddbd47c98aac51471d1e5894d60624bbd77caff99",
+ "deploy_cpp/src/policy_worker.cpp": "15e9b2db30ae9ca5ced8c6205a935fb1d7617f7a9a42b374ad41be401311fc61",
+ "deploy_cpp/tests/test_double_buffer.cpp": "c1d03877210b98e9b7f4d3e3d504b80724045ccd34e8d12f542f30ba1d232314",
+ "legged_gym/go2_config.py": "0467cd077796f4a145dac705494499f123118a9a949175cc2007ab839b81323a",
+ "requirements-rma-export.txt": "aef2ad3cdb35f8b9bf3589c6c2b5ecd61a2bc73daf3ea8892c8acdb68fac80a4",
+ "rsl_rl/unilab_rma/__init__.py": "56669c007abd163bbce11c4d800a837fae984bb2b27b4b384f74c82dc9c7d448",
+ "rsl_rl/unilab_rma/actor_critic_rma.py": "f74d2bdf5d4a3d4a3be8141a907220560b1d72319f211578e7efe622dec74966",
+ "rsl_rl/unilab_rma/adaptation_module.py": "92765e6f59dd1b72c4c68cada421080ecc616451fbad93dd061f7ba89b93ae98",
+ "rsl_rl/unilab_rma/deployment.py": "e6d4fe648b4949b442949dcaa24efdb7fb5f5f435c5c1befde931a52be78093b",
+ "rsl_rl/unilab_rma/env_adapter.py": "3b29df75056b3303162020b64b037b100f45597de072339909cd3f72e1f831fc",
+ "rsl_rl/unilab_rma/evaluation_diagnostics.py": "c1feff8ab3324e8ba1383ebcab2eb2b040bade7b2b410e83d9eec9e9fa54e345",
+ "rsl_rl/unilab_rma/ppo.py": "c2590bbe9e36189d194abfafc0725b326affcfcc67079443cb22e8ed1c4eb2aa",
+ "rsl_rl/unilab_rma/rendering.py": "013e872caee921468038c924c513512d991a9a61f075217137684cd9c3f13f12",
+ "rsl_rl/unilab_rma/runner.py": "546fa942db91e09dd14cebea7380467086924cfa7de973df72c4bfe8068f5961",
+ "rsl_rl/unilab_rma/scene_contract.py": "754f2da4dffcf5458f4e7fb165d76f1559b428c81a830a339147323300b904ed",
+ "rsl_rl/unilab_rma/tensorrt_runtime.py": "42e62f60fa9f1769315569f36665761340fc584ca4d10594f6deb03e6af30309",
+ "rsl_rl/unilab_rma/training_log.py": "5888af17cda42d74c8382a0f96e916a6eb43300eca2fd5ae04a741fca776afd8",
+ "scripts/evaluate_rma.py": "b746723ecce0d502afbd5be91a168c25ed4be702d381fddd7d519b3bf773ab8f",
+ "scripts/export_onnx.py": "934f3c19c08f1e0c79495c628c2b38ff7cb7632ef2e7a322f89264a64e4b1ffa",
+ "scripts/train_rma.py": "655cfa468e37863c67134e3033d8e88b7faeee095be8144eccbcbaf2d977586f",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma.yaml": "f8fa2851e1ee6e0d4a078d5e027367244e245c5ec990d4d56b8da731143da3d1",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward.yaml": "ae040ad352f95f15e45fa100552a804e36dcf0ebd5e41fab4982dc385289450c",
+ "src/unilab/envs/mdp/rma.py": "0982d710cfb241f964d61caa02d067772aa9c7e07f90f5c04c1b36acf4c7f67f",
+ "tests/rma/test_core.py": "adb36921915fdb56dadb75e794a1e38c8ba1ce1cb12750b3f9694a193cdf8993",
+ "tests/rma/test_evaluation_diagnostics.py": "edf008b98d3e21876fb68a10bfe9e676e183ab5b2dc8edcc624c9fa6b574479a",
+ "tests/rma/test_rendering.py": "b5654caf76ed98b38b76b6b0776aa4e7af4e292a3ce64dc71db22ad99eb5c904",
+ "tests/rma/test_tensorrt_runtime.py": "fce1af68a21300bcbd4a6c1d4bd6058f0154c7e8edf847df30eea3d0dc527c0b",
+ "tests/rma/test_training_log.py": "58fa0815ad2584890b3a9e122be8c8d6352e59e68aa49798e036422c10f8f919"
+ },
+ "runtime_vs_fork_critical_files": [
+ {
+ "path": "src/unilab/base/config_adapter.py",
+ "runtime_sha256": "f4413d76698aaf482342a1702501da15be2da1b512c7b75751054e88110a0668",
+ "fork_sha256": "49e3f91bde6793d834f84d05f5181ceba2ef2eeb4648617ca5852513e56e349c",
+ "same_normalized_text": false
+ },
+ {
+ "path": "src/unilab/base/torch_env.py",
+ "runtime_sha256": "01ee0affc9c59639cf17b4964ca017f6923f0ddf0c3d84bbf8fa94242960bf69",
+ "fork_sha256": "d031525a2e249338e179090a912a644abb0d23df2e8f085b80bac99e5de859a7",
+ "same_normalized_text": false
+ },
+ {
+ "path": "src/unilab/envs/mdp/__init__.py",
+ "runtime_sha256": "cf55efd845258f22dabd7f89697ab05d959ea4f3cdf5d876d724d391fbd39350",
+ "fork_sha256": "10c56d6d249e3652d941ffd4d241323d52413aad03b77b67fcc8750fd2928024",
+ "same_normalized_text": true
+ },
+ {
+ "path": "src/unilab/conf/ppo/task/go2_joystick_flat/base.yaml",
+ "runtime_sha256": "1f91628cc0201affda56c1b7363469224100ad5d59c2421826d44cc58d399dce",
+ "fork_sha256": "a51b5058f74834c300f7e6418842bd0805609f8f9f9ce1aed225291e661541c6",
+ "same_normalized_text": false
+ },
+ {
+ "path": "src/unilab/conf/ppo/task/go2_joystick_flat/mujoco.yaml",
+ "runtime_sha256": "57d4fa8552601cdc151f5dc3e9dee48dbb0281e25f6e4138225414ec9450ddc9",
+ "fork_sha256": "883be3da09c95fcef79d9ce9354c86b946f8d14b9e16db59c6cee6be81c3cfba",
+ "same_normalized_text": true
+ },
+ {
+ "path": "src/unilab/tasks/locomotion/common/manager_terms.py",
+ "runtime_sha256": "477a4842f04263be08648051d266abeb011a73731a96e89537e3203dfb5b3db3",
+ "fork_sha256": "f0526f4c4f27ca4a91a5e2b5ff31424bb3ed7057f0649f2688f55d36c07eeda6",
+ "same_normalized_text": false
+ }
+ ]
+}
diff --git a/results/rma/sim2sim/EXP-006/README.md b/results/rma/sim2sim/EXP-006/README.md
new file mode 100644
index 000000000..e6f59704d
--- /dev/null
+++ b/results/rma/sim2sim/EXP-006/README.md
@@ -0,0 +1,38 @@
+# EXP-006:精选实验数据
+
+对应[实验报告](../../../../experiments/rma/EXP-006_sim2sim_nominal.md)。
+本目录保存一次冻结策略、名义条件、单种子评估的证据,不是跨场景鲁棒性结论。
+
+| 内容 | 用途 |
+| --- | --- |
+| `comparison.json` | 两端动作执行后 IMU 速度的统一统计口径 |
+| `plots/` | 速度、动作接近边界比例、Genesis 姿态与高度三图 |
+| `traces/mujoco.csv.gz`、`traces/genesis.csv.gz` | 两端各 1000 行逐步数据,可离线复查 |
+| `mujoco/run_config.json`、`mujoco/summary.json` | 原始评估元数据与原报告 |
+| `provenance.json` | 原始路径、模型/源文件 SHA256、数据行数与文件校验值 |
+| `analysis_snapshot/` | 本次离线分析脚本与名义评估约定的存档 |
+
+注意:原 MuJoCo summary 的速度口径是动作执行前;跨引擎比较以
+`comparison.json` 的动作执行后口径为准。MuJoCo 原日志生成时模式名称尚未改为 v2,
+但此次运行已使用 kd=0 和初始回合计数清零;保留原始元数据不回写。
+
+## 离线复查
+
+无需重新训练或启动仿真。将两份 gzip 分别解压为独立临时目录中的
+`mujoco/transitions.csv` 与 `genesis.csv`,再用 Python 3.10+ 和 Matplotlib 执行
+存档的 `compare_sim2sim_traces.py`,参数为:
+
+```text
+--mujoco-trace <临时目录>/mujoco
+--genesis-csv <临时目录>/genesis.csv
+--output-dir <新的输出目录>
+--command 0.5 0 0
+```
+
+运行时副本与 GitHub fork 的源码版本不同;本次仅归档结果,不把运行目录整体覆盖到 fork。
+运行时没有 Git 历史,不能用当前 fork 的 commit 冒充该实验的源码版本。
+源文件与模型哈希记录于 provenance;该存档不含模型、全部运行源码、资产及完整依赖,
+因此支持数据离线复算,不宣称仅克隆仓库即可重跑全部仿真。
+
+`.pt`、`.onnx`、`.engine`、完整训练日志与资产留在本地;此目录只保存精选证据。
+下一步先记录降速时的接触与控制信号,区分实际力矩与代数估计,再选择一个对照变量。
diff --git a/results/rma/sim2sim/EXP-006/analysis_snapshot/NOMINAL_COMPARISON.md b/results/rma/sim2sim/EXP-006/analysis_snapshot/NOMINAL_COMPARISON.md
new file mode 100644
index 000000000..da0048db6
--- /dev/null
+++ b/results/rma/sim2sim/EXP-006/analysis_snapshot/NOMINAL_COMPARISON.md
@@ -0,0 +1,48 @@
+# Go2 nominal cross-engine evaluation (v2)
+
+This is a frozen-policy comparison. Do not retrain or change rewards for this experiment.
+Use the same `student_mapping_v1_500.pt` and its matching ONNX export.
+
+Changes are opt-in through `--sim2sim-nominal`; ordinary training is unchanged.
+Both engines use home reset, zero initial velocities, zero observation noise,
+friction 1.0, added payload 0, actuator kp 35 and kd 0, and the original passive
+joint damping 0.5. Policy period is 0.02 s with two 0.01 s physics steps.
+MuJoCo initial timeout counters are explicitly cleared, so the first episode is
+1000 steps rather than a seed-dependent remaining training episode.
+
+Important sensor contract: the existing policy was trained on negative MJCF
+framezaxis (the site z-axis expressed in world coordinates), despite the name
+projected_gravity. Nominal Genesis now preserves that definition. Replacing it
+with conventional body-frame projected gravity would change this policy input.
+Do not alter the training definition for this frozen checkpoint.
+Genesis velocity diagnostics include the IMU offset via omega cross r.
+
+Run a fresh comparison from the project root, keeping previous results:
+
+```bash
+out="runs/rma/evaluations/nominal_$(date +%Y%m%d_%H%M%S)"
+mkdir -p "$out"
+set -o pipefail
+uv run --no-sync python scripts/evaluate_rma.py --policy student --checkpoint runs/rma/student_mapping_v1_500.pt --task go2_joystick_flat/rma_forward --num-envs 1 --steps 1000 --seed 123 --command 0.5 0 0 --diagnostics --sim2sim-nominal --trace-dir "$out/mujoco" 2>&1 | tee "$out/mujoco.log"
+scripts/run_genesis_go2.sh --steps 1000 --seed 123 --command 0.5 0 0 --sim2sim-nominal --output "$out/genesis.csv" 2>&1 | tee "$out/genesis.log"
+uv run --no-sync python scripts/compare_sim2sim_traces.py --mujoco-trace "$out/mujoco" --genesis-csv "$out/genesis.csv" --output-dir "$out/plots"
+```
+
+Plot meanings:
+- velocity_comparison.png: forward/lateral/yaw tracking against the command.
+- action_near_bounds.png: fraction with normalized action magnitude >= 0.95;
+ this is not a torque or joint-limit saturation metric.
+- genesis_stability.png: Genesis tilt and height over time.
+- comparison.json: both metrics computed from post-step velocity to avoid mixing
+ the MuJoCo evaluator pre-step summary with Genesis post-step samples.
+
+The original seed123 validation lives in
+`runs/rma/evaluations/sim2sim_nominal_v2_seed123`. Its MuJoCo raw log was
+captured before the mode label was renamed to v2; actual kd=0 and initial
+counter clearing were already active. Both traces end at step 1000, no falls.
+
+Limitations: matching settings does not make contact solvers or integrations
+identical; no universal acceptance threshold is claimed. With home reset and
+noise off, different seeds largely repeat the same condition. They are not a
+robustness test over varied initial states or physical parameters. Validate
+those separately after auditing the interfaces.
diff --git a/results/rma/sim2sim/EXP-006/analysis_snapshot/compare_sim2sim_traces.py b/results/rma/sim2sim/EXP-006/analysis_snapshot/compare_sim2sim_traces.py
new file mode 100644
index 000000000..7698e3ff9
--- /dev/null
+++ b/results/rma/sim2sim/EXP-006/analysis_snapshot/compare_sim2sim_traces.py
@@ -0,0 +1,107 @@
+"""Compare saved MuJoCo and Genesis runs; never loads or trains a policy."""
+
+import argparse
+import csv
+import json
+import math
+from pathlib import Path
+
+
+def load_rows(path):
+ with path.open(newline="", encoding="utf-8") as stream:
+ rows = list(csv.DictReader(stream))
+ if not rows:
+ raise ValueError(f"Empty trace: {path}")
+ return rows
+
+
+def series(rows, genesis=False):
+ names = ("vx_m_s", "vy_m_s", "yaw_rate_rad_s") if genesis else (
+ "after_vx_m_s", "after_vy_m_s", "after_wz_rad_s"
+ )
+ return [[float(row[name]) for row in rows] for name in names]
+
+
+def metrics(rows, command, genesis=False):
+ values = series(rows, genesis)
+ rmse = [math.sqrt(sum((x - target) ** 2 for x in axis) / len(axis))
+ for axis, target in zip(values, command, strict=True)]
+ falls = sum(row["reset_reason"] == "bad_orientation" for row in rows) if genesis else sum(
+ int(row["terminated"]) for row in rows
+ )
+ return dict(
+ samples=len(rows), mean_velocity=[sum(axis) / len(axis) for axis in values],
+ rmse_by_axis=rmse, planar_rmse_m_s=math.hypot(rmse[0], rmse[1]),
+ fall_or_termination_count=falls,
+ near_bound_fraction=[sum(abs(float(row[f"action_{i}"])) >= 0.95 for row in rows) / len(rows)
+ for i in range(12)],
+ )
+
+
+def main():
+ p = argparse.ArgumentParser(description=__doc__)
+ p.add_argument("--mujoco-trace", type=Path, required=True)
+ p.add_argument("--genesis-csv", type=Path, required=True)
+ p.add_argument("--output-dir", type=Path, required=True)
+ p.add_argument("--command", type=float, nargs=3, default=[0.5, 0.0, 0.0])
+ args = p.parse_args()
+ candidates = list(args.mujoco_trace.rglob("transitions.csv"))
+ if len(candidates) != 1:
+ p.error(f"Expected one MuJoCo trace, got {len(candidates)}; select its exact directory")
+ mj, gs = load_rows(candidates[0]), load_rows(args.genesis_csv)
+ if {row["env_id"] for row in mj} != {"0"}:
+ p.error("Use a single-environment MuJoCo trace")
+ args.output_dir.mkdir(parents=True, exist_ok=True)
+ summary = dict(
+ command=args.command, mujoco=metrics(mj, args.command), genesis=metrics(gs, args.command, True),
+ measurement="Both use post-action IMU-site velocity; yaw rate is rad/s",
+ limitation="Nominal interface-aligned comparison; contact solvers remain different. No universal pass threshold.",
+ sources=dict(mujoco=str(candidates[0].resolve()), genesis=str(args.genesis_csv.resolve())),
+ )
+ (args.output_dir / "comparison.json").write_text(json.dumps(summary, indent=2), encoding="utf-8")
+ import matplotlib
+ matplotlib.use("Agg")
+ import matplotlib.pyplot as plt
+
+ t_mj = [float(row["next_time_s"]) for row in mj]
+ t_gs = [float(row["sim_time_s"]) for row in gs]
+ fig, axes = plt.subplots(3, 1, figsize=(12, 8), sharex=True, constrained_layout=True)
+ for i, (ax, label) in enumerate(zip(axes, ("vx (m/s)", "vy (m/s)", "yaw rate (rad/s)"), strict=True)):
+ ax.plot(t_mj, series(mj)[i], label="MuJoCo", linewidth=1, alpha=0.8)
+ ax.plot(t_gs, series(gs, True)[i], label="Genesis", linewidth=1, alpha=0.8)
+ ax.axhline(args.command[i], linestyle="--", color="black", label="Command")
+ ax.set_ylabel(label)
+ ax.grid(alpha=0.2)
+ axes[0].legend(ncol=3)
+ axes[0].set_title("Frozen student, nominal evaluation; post-step IMU measurements")
+ axes[-1].set_xlabel("Simulation time (s)")
+ fig.savefig(args.output_dir / "velocity_comparison.png", dpi=160)
+ plt.close(fig)
+
+ fig, ax = plt.subplots(figsize=(12, 4), constrained_layout=True)
+ x = list(range(12))
+ ax.bar([i - 0.2 for i in x], summary["mujoco"]["near_bound_fraction"], width=0.4, label="MuJoCo")
+ ax.bar([i + 0.2 for i in x], summary["genesis"]["near_bound_fraction"], width=0.4, label="Genesis")
+ names = [f"{leg}_{joint}" for leg in ("FL", "FR", "RL", "RR") for joint in ("hip", "thigh", "calf")]
+ ax.set_xticks(x, names, rotation=35)
+ ax.set_ylabel("Fraction with |action| >= 0.95")
+ ax.set_title("Normalized action proximity to bounds; not joint-limit or torque saturation")
+ ax.legend()
+ fig.savefig(args.output_dir / "action_near_bounds.png", dpi=160)
+ plt.close(fig)
+
+ fig, axes = plt.subplots(2, 1, figsize=(12, 5), sharex=True, constrained_layout=True)
+ axes[0].plot(t_gs, [float(row["tilt_deg"]) for row in gs])
+ axes[0].set_ylabel("Tilt (deg)")
+ axes[1].plot(t_gs, [float(row["base_z_m"]) for row in gs])
+ axes[1].set_ylabel("Base height (m)")
+ axes[1].set_xlabel("Simulation time (s)")
+ axes[0].set_title("Genesis stability trace")
+ fig.savefig(args.output_dir / "genesis_stability.png", dpi=160)
+ plt.close(fig)
+ print(json.dumps(summary, indent=2))
+ print(f"Saved three plots in {args.output_dir.resolve()}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/results/rma/sim2sim/EXP-006/comparison.json b/results/rma/sim2sim/EXP-006/comparison.json
new file mode 100644
index 000000000..db0fe36b5
--- /dev/null
+++ b/results/rma/sim2sim/EXP-006/comparison.json
@@ -0,0 +1,71 @@
+{
+ "command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mujoco": {
+ "samples": 1000,
+ "mean_velocity": [
+ 0.5520572142675519,
+ 0.02310534722799457,
+ -0.08643446249634144
+ ],
+ "rmse_by_axis": [
+ 0.10183338166805582,
+ 0.04847269512295537,
+ 0.16515393788608937
+ ],
+ "planar_rmse_m_s": 0.11278138053080795,
+ "fall_or_termination_count": 0,
+ "near_bound_fraction": [
+ 0.016,
+ 0.124,
+ 0.118,
+ 0.003,
+ 0.013,
+ 0.258,
+ 0.03,
+ 0.014,
+ 0.044,
+ 0.122,
+ 0.155,
+ 0.417
+ ]
+ },
+ "genesis": {
+ "samples": 1000,
+ "mean_velocity": [
+ 0.4867710067454318,
+ 0.027043490791460498,
+ 0.03830585028952919
+ ],
+ "rmse_by_axis": [
+ 0.16554040927260974,
+ 0.05645601348660588,
+ 0.15112661729348884
+ ],
+ "planar_rmse_m_s": 0.17490256876599314,
+ "fall_or_termination_count": 0,
+ "near_bound_fraction": [
+ 0.002,
+ 0.096,
+ 0.116,
+ 0.0,
+ 0.01,
+ 0.261,
+ 0.011,
+ 0.005,
+ 0.032,
+ 0.125,
+ 0.12,
+ 0.449
+ ]
+ },
+ "measurement": "Both use post-action IMU-site velocity; yaw rate is rad/s",
+ "limitation": "Nominal interface-aligned comparison; contact solvers remain different. No universal pass threshold.",
+ "sources": {
+ "mujoco": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/mujoco/eval_3wq40pkr/transitions.csv",
+ "genesis": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/genesis.csv"
+ }
+}
\ No newline at end of file
diff --git a/results/rma/sim2sim/EXP-006/mujoco/summary.json b/results/rma/sim2sim/EXP-006/mujoco/summary.json
new file mode 100644
index 000000000..73b60c83c
--- /dev/null
+++ b/results/rma/sim2sim/EXP-006/mujoco/summary.json
@@ -0,0 +1,173 @@
+{
+ "policy": "student",
+ "seed": 123,
+ "completed_episodes": 1,
+ "mean_completed_episode_return": 41.99813461303711,
+ "mean_completed_episode_length_steps": 1000.0,
+ "mean_step_reward": 0.04199817029200494,
+ "planar_velocity_rmse_m_per_s": 0.11375569429588679,
+ "unfinished_episodes": 0,
+ "mean_unfinished_episode_return": null,
+ "student_latent_mse_vs_teacher": 0.009088981525565032,
+ "student_action_rmse_vs_teacher": 0.01922868809264916,
+ "terminations": 0,
+ "total_transitions": 1000,
+ "command_override": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "evaluation_mode": "sim2sim_nominal_home_zero_noise",
+ "task": "go2_joystick_flat/rma_forward",
+ "diagnostics": {
+ "velocity_axes": [
+ "vx_m_per_s",
+ "vy_m_per_s",
+ "yaw_rate_rad_per_s"
+ ],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_command": [
+ 0.5,
+ 0.0,
+ 0.0
+ ],
+ "mean_measured_velocity": [
+ 0.55138948494941,
+ 0.023139239531699787,
+ -0.0866801185098302
+ ],
+ "tracking_rmse_by_axis": [
+ 0.1029169786662413,
+ 0.04846084485677623,
+ 0.16497113784634895
+ ],
+ "mean_absolute_yaw_rate_rad_per_s": 0.13216670325931046,
+ "weighted_reward_terms_before_dt": {
+ "tracking_lin_vel": 1.9098223032951356,
+ "tracking_ang_vel": 0.1807469550538808,
+ "lin_vel_z": -0.011709675100798652,
+ "ang_vel_xy": -0.03375083813566289,
+ "base_height": -0.03783127726802195,
+ "action_rate": -0.006751242972022738,
+ "similar_to_default": -0.15488274090364576,
+ "contact": 0.18557999498769642,
+ "swing_feet_z": 0.06868506468459964
+ },
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards"
+ },
+ "trace": {
+ "directory": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/mujoco/eval_3wq40pkr",
+ "full": {
+ "transitions": 1000,
+ "mean_measured_velocity": [
+ 0.55138948494941,
+ 0.023139239531699787,
+ -0.0866801185098302
+ ],
+ "tracking_rmse_by_axis": [
+ 0.1029169786662413,
+ 0.04846084485677623,
+ 0.16497113784634895
+ ]
+ },
+ "after_startup_window": {
+ "transitions": 900,
+ "mean_measured_velocity": [
+ 0.556280231806967,
+ 0.021171637030127182,
+ -0.08470533217423104
+ ],
+ "tracking_rmse_by_axis": [
+ 0.09695333675688375,
+ 0.04586780016924982,
+ 0.16490015415929535
+ ]
+ },
+ "action_target_joint_order": [
+ "FL_hip_joint",
+ "FL_thigh_joint",
+ "FL_calf_joint",
+ "FR_hip_joint",
+ "FR_thigh_joint",
+ "FR_calf_joint",
+ "RL_hip_joint",
+ "RL_thigh_joint",
+ "RL_calf_joint",
+ "RR_hip_joint",
+ "RR_thigh_joint",
+ "RR_calf_joint"
+ ],
+ "normalized_action_min": [
+ -0.9902253746986389,
+ -0.9999876022338867,
+ -0.9998041391372681,
+ -0.8324918746948242,
+ -0.9374557137489319,
+ -0.9901061058044434,
+ -0.9884268641471863,
+ -0.9644988179206848,
+ -0.7830153107643127,
+ -0.9961377382278442,
+ -0.9996283054351807,
+ -0.9996256828308105
+ ],
+ "normalized_action_max": [
+ 0.9829237461090088,
+ 0.986842930316925,
+ 0.9712881445884705,
+ 0.9611890316009521,
+ 0.9720931053161621,
+ 0.9999984502792358,
+ 0.904410183429718,
+ 0.9691876173019409,
+ 0.9849426746368408,
+ 0.49857503175735474,
+ 0.9942507743835449,
+ 0.9998595118522644
+ ],
+ "normalized_action_rms": [
+ 0.7496004436854341,
+ 0.620985925763891,
+ 0.698776103261185,
+ 0.5772129133694048,
+ 0.5022383096920203,
+ 0.6929835285429926,
+ 0.5573535884985332,
+ 0.5070338913197341,
+ 0.6028693393574991,
+ 0.655578725800352,
+ 0.6217977881914584,
+ 0.867340289949644
+ ],
+ "normalized_action_near_bound_fraction": [
+ 0.016,
+ 0.124,
+ 0.118,
+ 0.003,
+ 0.013,
+ 0.258,
+ 0.03,
+ 0.014,
+ 0.044,
+ 0.122,
+ 0.155,
+ 0.417
+ ],
+ "mean_weighted_reward_rates_before_dt": {
+ "tracking_lin_vel": 1.9098223032951356,
+ "tracking_ang_vel": 0.1807469550538808,
+ "lin_vel_z": -0.011709675100798652,
+ "ang_vel_xy": -0.03375083813566289,
+ "base_height": -0.03783127726802195,
+ "action_rate": -0.006751242972022738,
+ "similar_to_default": -0.15488274090364576,
+ "contact": 0.18557999498769642,
+ "swing_feet_z": 0.06868506468459964
+ }
+ }
+}
diff --git a/results/rma/sim2sim/EXP-006/plots/action_near_bounds.png b/results/rma/sim2sim/EXP-006/plots/action_near_bounds.png
new file mode 100644
index 000000000..264e8dbb6
Binary files /dev/null and b/results/rma/sim2sim/EXP-006/plots/action_near_bounds.png differ
diff --git a/results/rma/sim2sim/EXP-006/plots/genesis_stability.png b/results/rma/sim2sim/EXP-006/plots/genesis_stability.png
new file mode 100644
index 000000000..c6db566c7
Binary files /dev/null and b/results/rma/sim2sim/EXP-006/plots/genesis_stability.png differ
diff --git a/results/rma/sim2sim/EXP-006/plots/velocity_comparison.png b/results/rma/sim2sim/EXP-006/plots/velocity_comparison.png
new file mode 100644
index 000000000..55bc60b47
Binary files /dev/null and b/results/rma/sim2sim/EXP-006/plots/velocity_comparison.png differ
diff --git a/results/rma/sim2sim/EXP-006/provenance.json b/results/rma/sim2sim/EXP-006/provenance.json
new file mode 100644
index 000000000..f2e841e0f
--- /dev/null
+++ b/results/rma/sim2sim/EXP-006/provenance.json
@@ -0,0 +1,78 @@
+{
+ "date": "2026-10-24",
+ "experiment": "EXP-006",
+ "source_runtime": "WSL UniLab source-only runtime; not the GitHub fork runtime",
+ "runtime_git_commit": null,
+ "source_directory": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123",
+ "scope": "single nominal initial condition, single environment, 1000 steps, seed 123; not a robustness study",
+ "copied_files": {
+ "comparison.json": {
+ "sha256": "a69d97bb857b25def179725e081584ad3f92ab5036a27c54d7608d4f0570a674",
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/plots/comparison.json"
+ },
+ "plots/velocity_comparison.png": {
+ "sha256": "94dadd3224174e703b939262f9eacfe0dc51adf384757b20272d67b6a5a2410d",
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/plots/velocity_comparison.png"
+ },
+ "plots/action_near_bounds.png": {
+ "sha256": "139465896411105d413684d272b7f1627c75f8bd06ef57aa39294e52ea421331",
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/plots/action_near_bounds.png"
+ },
+ "plots/genesis_stability.png": {
+ "sha256": "aaf8933006d13016fd2ac4ad53e6be30128e5de3266be2783d886501cbea552a",
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/plots/genesis_stability.png"
+ },
+ "mujoco/run_config.json": {
+ "sha256": "779c17c1bf1ac1cf576a85a4397aab4a0fc6232b9a084d584503845260f9563a",
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/mujoco/eval_3wq40pkr/run_config.json"
+ },
+ "mujoco/summary.json": {
+ "sha256": "1bceeb223d0c896526d4a332669f3a45bec05d1a11f5fad21f4d44daca9c9616",
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/mujoco/eval_3wq40pkr/summary.json"
+ },
+ "analysis_snapshot/compare_sim2sim_traces.py": {
+ "sha256": "622ff08d7908967063a4205315afd4954cfb2f8a74644932b9b33bf46fd6caae",
+ "source": "/home/abc/my_unilab/scripts/compare_sim2sim_traces.py"
+ },
+ "analysis_snapshot/NOMINAL_COMPARISON.md": {
+ "sha256": "6501a8e3c73eafdf1aa4d9a51a4b896619ae77c0081a4ed11f8f959fd21b6fb1",
+ "source": "/home/abc/my_unilab/scripts/tools/genesis_feasibility/NOMINAL_COMPARISON.md"
+ }
+ },
+ "raw_data": {
+ "mujoco": {
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/mujoco/eval_3wq40pkr/transitions.csv",
+ "file": "traces/mujoco.csv.gz",
+ "rows": 1000,
+ "uncompressed_sha256": "1db4bb6f3453c954072acce0f869ff4ae8e0840a32988de5b59ded04be2ed1fe",
+ "compressed_sha256": "c4131d016c5b6b4fd118ce9b7dc3237590dd57ee90ea01c237de28e5178e4449"
+ },
+ "genesis": {
+ "source": "/home/abc/my_unilab/runs/rma/evaluations/sim2sim_nominal_v2_seed123/genesis.csv",
+ "file": "traces/genesis.csv.gz",
+ "rows": 1000,
+ "uncompressed_sha256": "816205aff6e1557a4480d9d533bab1c819577aad448b26e4ff71410cba9cbe97",
+ "compressed_sha256": "3df965b79f2fd8b0ea3ca1278dbcd4cb662260a5db6fa14a77b7a0ef51e9dc6e"
+ }
+ },
+ "model_files": {
+ "student_mapping_v1_500.pt": {
+ "sha256": "33f62de2201d0dae7969ffca4aefe482239fd6ad02550749332cbd5b7a9f0218",
+ "bytes": 8356877,
+ "included_in_git": false
+ },
+ "student_mapping_v1_500.onnx": {
+ "sha256": "5dd0c739f3b2343551050b588bb94151898169311e161c5fe7ec73fb1d686f80",
+ "bytes": 2845225,
+ "included_in_git": false
+ }
+ },
+ "runtime_source_sha256": {
+ "scripts/train_rma.py": "a324025d073a5e726fdcc7133d620e67277f27bb2e0e919a22e6f5bdc4f89b7b",
+ "scripts/evaluate_rma.py": "80f42d5a9171d80e9a5f2684e9cf5f31236fd0ffddf8c11ef1e9d7ccc52ae431",
+ "scripts/sim2sim_genesis_go2.py": "89838e8d7b330863a816532a06a68962ee71812211ea15437baa987dc8a69c87",
+ "scripts/compare_sim2sim_traces.py": "622ff08d7908967063a4205315afd4954cfb2f8a74644932b9b33bf46fd6caae",
+ "scripts/run_genesis_go2.sh": "377f4c334e04657cd190da81d96428142b69abcbfe4bab5893567af5aa58896f",
+ "scripts/tools/genesis_feasibility/NOMINAL_COMPARISON.md": "6501a8e3c73eafdf1aa4d9a51a4b896619ae77c0081a4ed11f8f959fd21b6fb1"
+ }
+}
diff --git a/results/rma/sim2sim/EXP-006/traces/genesis.csv.gz b/results/rma/sim2sim/EXP-006/traces/genesis.csv.gz
new file mode 100644
index 000000000..01ed7a627
Binary files /dev/null and b/results/rma/sim2sim/EXP-006/traces/genesis.csv.gz differ
diff --git a/results/rma/sim2sim/EXP-006/traces/mujoco.csv.gz b/results/rma/sim2sim/EXP-006/traces/mujoco.csv.gz
new file mode 100644
index 000000000..166768719
Binary files /dev/null and b/results/rma/sim2sim/EXP-006/traces/mujoco.csv.gz differ
diff --git a/rsl_rl/unilab_rma/__init__.py b/rsl_rl/unilab_rma/__init__.py
new file mode 100644
index 000000000..912f2125b
--- /dev/null
+++ b/rsl_rl/unilab_rma/__init__.py
@@ -0,0 +1,4 @@
+"""Independent RMA extension; deliberately does not shadow the rsl_rl package."""
+
+from .actor_critic_rma import Actor, ActorCriticRMA, PrivilegedEncoder, RMAConfig
+from .adaptation_module import AdaptationModule, AdaptationTrainer, HistoryBuffer
diff --git a/rsl_rl/unilab_rma/actor_critic_rma.py b/rsl_rl/unilab_rma/actor_critic_rma.py
new file mode 100644
index 000000000..aa20c6a88
--- /dev/null
+++ b/rsl_rl/unilab_rma/actor_critic_rma.py
@@ -0,0 +1,81 @@
+from dataclasses import asdict, dataclass
+
+import torch
+from torch import nn
+from torch.distributions import Normal
+
+
+@dataclass
+class RMAConfig:
+ obs_dim: int = 49
+ critic_dim: int = 52
+ privileged_dim: int = 2 # sliding friction coefficient, added base mass (kg)
+ history_length: int = 50
+ latent_dim: int = 8
+ action_dim: int = 12
+ hidden: tuple = (256, 128)
+
+
+def mlp(widths, final=None):
+ layers = []
+ for i, (a, b) in enumerate(zip(widths, widths[1:])):
+ layers.append(nn.Linear(a, b))
+ if i < len(widths) - 2:
+ layers.append(nn.ELU())
+ if final is not None:
+ layers.append(final)
+ return nn.Sequential(*layers)
+
+
+class PrivilegedEncoder(nn.Module):
+ def __init__(self, cfg):
+ super().__init__()
+ # Fixed scales serialized in checkpoint. No unexported running statistics.
+ self.register_buffer("scale", torch.tensor([1.0, 5.0]))
+ if cfg.privileged_dim != 2:
+ raise ValueError("This contract requires friction and added base mass")
+ self.net = mlp([2, 64, 64, cfg.latent_dim], nn.Tanh())
+
+ def forward(self, privileged):
+ return self.net(privileged / self.scale)
+
+
+class Actor(nn.Module):
+ def __init__(self, cfg):
+ super().__init__()
+ self.net = mlp([cfg.obs_dim + cfg.latent_dim, *cfg.hidden, cfg.action_dim])
+
+ def forward(self, obs, z):
+ # Pre-tanh Gaussian mean; squashing is explicit in training and deployment.
+ return self.net(torch.cat((obs, z), -1))
+
+
+class ActorCriticRMA(nn.Module):
+ def __init__(self, cfg=RMAConfig()):
+ super().__init__()
+ self.cfg = cfg
+ self.encoder = PrivilegedEncoder(cfg)
+ self.actor = Actor(cfg)
+ self.critic = mlp([cfg.critic_dim + cfg.privileged_dim, *cfg.hidden, 1])
+ self.log_std = nn.Parameter(torch.full((cfg.action_dim,), -0.7))
+
+ def value(self, critic_obs, privileged):
+ return self.critic(torch.cat((critic_obs, privileged / self.encoder.scale), -1)).squeeze(-1)
+
+ def distribution(self, obs, privileged):
+ mean = self.actor(obs, self.encoder(privileged))
+ return Normal(mean, self.log_std.clamp(-5, 1).exp())
+
+ @staticmethod
+ def log_prob(dist, raw):
+ # Numerically stable log(1 - tanh(raw)^2).
+ correction = 2 * (0.6931471805599453 - raw - nn.functional.softplus(-2 * raw))
+ return (dist.log_prob(raw) - correction).sum(-1)
+
+ def sample(self, obs, privileged):
+ dist = self.distribution(obs, privileged)
+ raw = dist.sample()
+ return raw.tanh(), raw, self.log_prob(dist, raw)
+
+ def metadata(self):
+ return asdict(self.cfg)
diff --git a/rsl_rl/unilab_rma/adaptation_module.py b/rsl_rl/unilab_rma/adaptation_module.py
new file mode 100644
index 000000000..bd8148f6e
--- /dev/null
+++ b/rsl_rl/unilab_rma/adaptation_module.py
@@ -0,0 +1,77 @@
+import torch
+from torch import nn
+
+from .actor_critic_rma import mlp
+
+
+class AdaptationModule(nn.Module):
+ """Time-major history: oldest first, current observation last; zero padding."""
+
+ def __init__(self, cfg):
+ super().__init__()
+ self.cfg = cfg
+ self.net = mlp([cfg.history_length * cfg.obs_dim, 256, 128, cfg.latent_dim], nn.Tanh())
+
+ def forward(self, history):
+ return self.net(history.flatten(1))
+
+
+class HistoryBuffer:
+ def __init__(self, n, cfg, device="cpu"):
+ self.data = torch.zeros(n, cfg.history_length, cfg.obs_dim, device=device)
+
+ def push(self, obs, done=None):
+ if done is not None:
+ self.data[done.bool()] = 0
+ self.data[:, :-1] = self.data[:, 1:].clone()
+ self.data[:, -1] = obs
+ return self.data
+
+
+class AdaptationTrainer:
+ """DAgger-style latent labels on STUDENT-visited states, aggregated FIFO data.
+
+ Teacher and actor are fixed in phase 2; only adaptation parameters update.
+ """
+
+ def __init__(self, teacher, module, capacity=8192, lr=1e-4, seed=0):
+ self.teacher = teacher.eval().requires_grad_(False)
+ self.module = module
+ self.optimizer = torch.optim.Adam(module.parameters(), lr=lr)
+ cfg = module.cfg
+ self.capacity, self.size, self.cursor = capacity, 0, 0
+ self.histories = torch.empty(capacity, cfg.history_length, cfg.obs_dim)
+ self.labels = torch.empty(capacity, cfg.latent_dim)
+ self.generator = torch.Generator().manual_seed(seed)
+
+ @torch.no_grad()
+ def add(self, history, privileged):
+ labels = self.teacher.encoder(privileged)
+ h, z = history.detach().cpu(), labels.detach().cpu()
+ if len(h) > self.capacity:
+ h, z = h[-self.capacity :], z[-self.capacity :]
+ for start in range(0, len(h), self.capacity):
+ count = min(len(h) - start, self.capacity)
+ indices = (torch.arange(count) + self.cursor) % self.capacity
+ self.histories[indices] = h[start : start + count]
+ self.labels[indices] = z[start : start + count]
+ self.cursor = (self.cursor + count) % self.capacity
+ self.size = min(self.size + count, self.capacity)
+
+ def update(self, batch_size=256, updates=4):
+ if not self.size:
+ raise RuntimeError("Collect student rollouts first")
+ device = next(self.module.parameters()).device
+ losses = []
+ for _ in range(updates):
+ indices = torch.randint(
+ self.size, (min(batch_size, self.size),), generator=self.generator
+ )
+ prediction = self.module(self.histories[indices].to(device))
+ loss = nn.functional.mse_loss(prediction, self.labels[indices].to(device))
+ self.optimizer.zero_grad()
+ loss.backward()
+ nn.utils.clip_grad_norm_(self.module.parameters(), 1.0)
+ self.optimizer.step()
+ losses.append(loss.item())
+ return sum(losses) / len(losses)
diff --git a/rsl_rl/unilab_rma/control_diagnostics.py b/rsl_rl/unilab_rma/control_diagnostics.py
new file mode 100644
index 000000000..e0c6eb3eb
--- /dev/null
+++ b/rsl_rl/unilab_rma/control_diagnostics.py
@@ -0,0 +1,161 @@
+"""Evaluation-only reads of public position-control signals, for one world."""
+
+import csv
+import json
+from pathlib import Path
+
+import numpy as np
+import torch
+
+
+def array(value):
+ if isinstance(value, torch.Tensor):
+ value = value.detach().cpu().numpy()
+ return np.array(value, dtype=np.float64, copy=True)
+
+
+class ControlDiagnostics:
+ def __init__(self, raw, directory):
+ if raw.num_envs != 1:
+ raise ValueError("Control diagnostics require exactly one environment")
+ self.raw = raw
+ self.directory = Path(directory)
+ self.term = raw.action_manager.get_term("joint_pos")
+ self.robot = raw.scene[self.term.cfg.entity_name]
+ self.names = list(self.term.target_names)
+ joint_names = list(self.robot.joint_names)
+ self.joint_ids = [joint_names.index(name) for name in self.names]
+ actuator_names = list(raw.backend.get_actuator_names())
+ actuator_joints = list(raw.backend.get_actuator_joint_names())
+ self.actuator_ids = [actuator_joints.index(name) for name in self.names]
+ if list(self.robot.actuator_names) != actuator_names:
+ raise ValueError("Entity and backend actuator order differ; cannot interpret buffer")
+ if len(self.names) != 12 or len(set(self.actuator_ids)) != 12:
+ raise ValueError("Requires 12 distinct single-joint position actuators")
+ self.rows = []
+ self.step = self.episode = self.age = 0
+ self.metadata = {
+ "joint_names": self.names,
+ "actuator_names": actuator_names,
+ "action_to_actuator_indices": self.actuator_ids,
+ "control_period_s": float(raw.step_dt),
+ "alignment": "q_before/dq_before precede action; target is the authoritative control buffer after step; q_after precedes reset. No cross-reset rows.",
+ "mapping_residual": "written target - (processed_action - encoder_bias), in joint order",
+ "pd_demand_estimate": "kp*(written_target-q_before)-kd*dq_before; an algebraic estimate at the control boundary, NOT measured torque or a physics-substep sample.",
+ "torque_measurement": "unavailable through the current public backend API; no torque saturation claim",
+ "gains_scope": "public get_actuator_gains, refreshed each step; one environment only",
+ }
+ (self.directory / "control_metadata.json").write_text(
+ json.dumps(self.metadata, indent=2), encoding="utf-8"
+ )
+
+ def before(self):
+ return (
+ array(self.robot.data.joint_pos)[0, self.joint_ids],
+ array(self.robot.data.joint_vel)[0, self.joint_ids],
+ )
+
+ def record(self, before, action, terminated, truncated):
+ q, dq = before
+ after = array(self.robot.data.joint_pos)[0, self.joint_ids]
+ written = array(self.robot.data.control_buffer)[0, self.actuator_ids]
+ processed = array(self.term.processed_action)[0]
+ bias = array(self.robot.data.encoder_bias)[0, self.joint_ids]
+ kp, kd = self.raw.backend.get_actuator_gains()
+ kp, kd = array(kp).reshape(-1)[self.actuator_ids], array(kd).reshape(-1)[self.actuator_ids]
+ a = array(action)[0]
+ self.age += 1
+ for i, name in enumerate(self.names):
+ self.rows.append(
+ dict(
+ step=self.step,
+ episode=self.episode,
+ episode_step=self.age,
+ time_s=self.step * float(self.raw.step_dt),
+ joint=name,
+ action=a[i],
+ q_before_rad=q[i],
+ dq_before_rad_s=dq[i],
+ q_after_rad=after[i],
+ processed_target_rad=processed[i],
+ encoder_bias_rad=bias[i],
+ written_target_rad=written[i],
+ mapping_residual_rad=written[i] - (processed[i] - bias[i]),
+ kp=kp[i],
+ kd=kd[i],
+ pd_demand_estimate_nm=kp[i] * (written[i] - q[i]) - kd[i] * dq[i],
+ terminated=int(terminated),
+ truncated=int(truncated),
+ )
+ )
+ self.step += 1
+ if terminated or truncated:
+ self.episode += 1
+ self.age = 0
+
+ def finish(self):
+ if not self.rows:
+ raise ValueError("No control samples")
+ with (self.directory / "control_signals.csv").open(
+ "w", newline="", encoding="utf-8"
+ ) as stream:
+ writer = csv.DictWriter(stream, fieldnames=list(self.rows[0]))
+ writer.writeheader()
+ writer.writerows(self.rows)
+ report = {
+ "max_abs_mapping_residual_rad": max(abs(r["mapping_residual_rad"]) for r in self.rows),
+ "torque_measurement": self.metadata["torque_measurement"],
+ "samples": len(self.rows),
+ "joints_after_first_100_steps_per_episode": {},
+ }
+ for name in self.names:
+ rows = [r for r in self.rows if r["joint"] == name and r["episode_step"] > 100]
+ report["joints_after_first_100_steps_per_episode"][name] = {
+ "samples": len(rows),
+ "position_error_rmse_rad": float(
+ np.sqrt(
+ np.mean([(r["written_target_rad"] - r["q_after_rad"]) ** 2 for r in rows])
+ )
+ )
+ if rows
+ else None,
+ }
+ (self.directory / "control_summary.json").write_text(
+ json.dumps(report, indent=2), encoding="utf-8"
+ )
+ self.plot()
+ return report
+
+ def plot(self):
+ import matplotlib
+
+ matplotlib.use("Agg")
+ import matplotlib.pyplot as plt
+
+ fig, axes = plt.subplots(4, 3, figsize=(14, 11), constrained_layout=True)
+ for index, name in enumerate(self.names):
+ ax = axes.flat[index]
+ for ep in sorted({r["episode"] for r in self.rows}):
+ rows = [r for r in self.rows if r["joint"] == name and r["episode"] == ep]
+ t = [(r["step"] + 1) * float(self.raw.step_dt) for r in rows]
+ ax.plot(
+ t,
+ [r["written_target_rad"] for r in rows],
+ color="#1761A0",
+ label="Written target" if ep == 0 else None,
+ )
+ ax.plot(
+ t,
+ [r["q_after_rad"] for r in rows],
+ color="#D36C22",
+ label="Measured after step" if ep == 0 else None,
+ )
+ ax.set_title(name)
+ ax.set_ylabel("Angle (rad)")
+ ax.grid(alpha=0.25)
+ axes[0, 0].legend(fontsize=8)
+ for ax in axes[-1]:
+ ax.set_xlabel("Evaluation time (s)")
+ fig.suptitle("Authoritative actuator target vs measured angle; episodes plotted separately")
+ fig.savefig(self.directory / "control_tracking.png", dpi=140)
+ plt.close(fig)
diff --git a/rsl_rl/unilab_rma/deployment.py b/rsl_rl/unilab_rma/deployment.py
new file mode 100644
index 000000000..8daf37abd
--- /dev/null
+++ b/rsl_rl/unilab_rma/deployment.py
@@ -0,0 +1,30 @@
+from torch import nn
+
+from .actor_critic_rma import Actor
+from .adaptation_module import AdaptationModule
+
+
+def go2_control_layout():
+ """Current task contract, checked against runtime; not stored in old weights."""
+ return {
+ "action_joint_order": ["FL", "FR", "RL", "RR"],
+ "scene_actuator_order": ["FR", "FL", "RR", "RL"],
+ "action_to_actuator_indices": [3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8],
+ "control_layout_source": (
+ "Current Go2 YAML and Entity.find_joints_by_actuator_names natural joint order; "
+ "verified in the original 1.3.3 runtime. Historical checkpoints do not store "
+ "this layout; confirm against a trace from the matching scene before deployment."
+ ),
+ }
+
+
+class DeploymentPolicy(nn.Module):
+ """Only student adaptation and base actor. No teacher encoder or critic."""
+
+ def __init__(self, cfg):
+ super().__init__()
+ self.adaptation = AdaptationModule(cfg)
+ self.actor = Actor(cfg)
+
+ def forward(self, observation, history):
+ return self.actor(observation, self.adaptation(history)).tanh()
diff --git a/rsl_rl/unilab_rma/env_adapter.py b/rsl_rl/unilab_rma/env_adapter.py
new file mode 100644
index 000000000..25d76ec8c
--- /dev/null
+++ b/rsl_rl/unilab_rma/env_adapter.py
@@ -0,0 +1,57 @@
+"""UniLab manual-reset adapter: retain terminal obs before resetting histories."""
+
+import torch
+
+
+class UniLabRMAEnv:
+ def __init__(self, env, cfg, device="cpu"):
+ self.env, self.cfg, self.device = env, cfg, torch.device(device)
+ if env._autoreset:
+ raise ValueError("RMA adapter requires env.auto_reset=false")
+ self.num_envs = env.num_envs
+
+ def read(self, observations):
+ if not hasattr(self.env, "_rma_label_valid") or not self.env._rma_label_valid.all():
+ raise RuntimeError("RMA reset events must populate actual friction and payload labels")
+ # ManagerBasedRlEnv exports policy as 'obs' and drops other manager
+ # groups except the explicitly configured critic group.
+ policy_key = "obs" if "obs" in observations else "policy"
+ if policy_key not in observations or "critic" not in observations:
+ raise KeyError(
+ f"RMA requires public obs/critic tensors; got {list(observations)}. "
+ "Set critic_observation_group=critic in the RMA overlay."
+ )
+ if "privileged" in observations:
+ privileged = observations["privileged"]
+ else:
+ # These are the SAME reset samples written to the physics backend.
+ # Clone immediately: partial resets will overwrite these label rows.
+ privileged = self.env._rma_privileged
+ result = tuple(
+ torch.as_tensor(value, device=self.device, dtype=torch.float32).clone()
+ for value in (observations[policy_key], observations["critic"], privileged)
+ )
+ for tensor, width in zip(
+ result, (self.cfg.obs_dim, self.cfg.critic_dim, self.cfg.privileged_dim)
+ ):
+ if tensor.shape != (self.num_envs, width) or not torch.isfinite(tensor).all():
+ raise ValueError(
+ f"RMA observation mismatch: {tensor.shape}, expected width {width}"
+ )
+ return result
+
+ def reset(self):
+ obs, _ = self.env.reset()
+ return self.read(obs)
+
+ def step(self, action):
+ state = self.env.step(action.to(self.env.device))
+ terminal = self.read(state.obs)
+ reward = state.reward.to(self.device).clone()
+ terminated = state.terminated.to(self.device).bool().clone()
+ truncated = state.truncated.to(self.device).bool().clone()
+ done = terminated | truncated
+ if done.any():
+ self.env.reset(done.nonzero(as_tuple=False).flatten().to(self.env.device))
+ current = self.read(self.env.get_observations())
+ return current, reward, terminated, truncated, terminal
diff --git a/rsl_rl/unilab_rma/evaluation_diagnostics.py b/rsl_rl/unilab_rma/evaluation_diagnostics.py
new file mode 100644
index 000000000..d63b877d4
--- /dev/null
+++ b/rsl_rl/unilab_rma/evaluation_diagnostics.py
@@ -0,0 +1,85 @@
+"""Opt-in command control and evaluation-only locomotion diagnostics."""
+
+import math
+
+import torch
+
+DEFAULT_TASK = "go2_joystick_flat/rma"
+FORWARD_TASK = "go2_joystick_flat/rma_forward"
+NO_POSE_TASK = "go2_joystick_flat/rma_forward_no_pose"
+TIGHT_TRACKING_TASK = "go2_joystick_flat/rma_forward_tight_tracking"
+RMA_TASKS = (DEFAULT_TASK, FORWARD_TASK, NO_POSE_TASK, TIGHT_TRACKING_TASK)
+
+
+def command_overrides(command):
+ """Fix commands through their config owner, including after every reset."""
+ if len(command) != 3 or not all(math.isfinite(float(x)) for x in command):
+ raise ValueError("command must contain finite vx, vy, and yaw-rate values")
+ prefix = "env.commands.twist."
+ overrides = [
+ prefix + f"ranges.{name}=[{float(value)},{float(value)}]"
+ for name, value in zip(("lin_vel_x", "lin_vel_y", "ang_vel_z"), command)
+ ]
+ overrides += [prefix + "heading_command=false"]
+ overrides += [
+ prefix + name + "=0.0"
+ for name in ("rel_standing_envs", "rel_heading_envs", "rel_world_envs", "rel_forward_envs")
+ ]
+ return overrides
+
+
+class EvaluationDiagnostics:
+ """Accumulate clean critic velocities; never alter actions or observations."""
+
+ def __init__(self):
+ self.count = 0
+ self.command_sum = torch.zeros(3, dtype=torch.float64)
+ self.measured_sum = torch.zeros(3, dtype=torch.float64)
+ self.error_squared_sum = torch.zeros(3, dtype=torch.float64)
+ self.absolute_yaw_sum = 0.0
+ self.initial_command = None
+ self.reward_sum = {}
+ self.reward_steps = 0
+
+ def record_state(self, critic):
+ # critic[42:45] is command; [49:52] is clean local_linvel;
+ # critic[0:3] is clean gyro. Policy gyro includes training noise.
+ state = critic.detach().to(device="cpu", dtype=torch.float64)
+ if state.ndim != 2 or state.shape[1] != 52:
+ raise ValueError("Diagnostics require the current 52-dimensional Go2 critic contract")
+ command = state[:, 42:45]
+ measured = torch.cat((state[:, 49:51], state[:, 2:3]), dim=1)
+ if self.initial_command is None:
+ self.initial_command = command[0].tolist()
+ self.command_sum += command.sum(0)
+ self.measured_sum += measured.sum(0)
+ self.error_squared_sum += (command - measured).square().sum(0)
+ self.absolute_yaw_sum += measured[:, 2].abs().sum().item()
+ self.count += len(state)
+
+ def record_rewards(self, reward_manager):
+ # Public API: already weighted, but NOT multiplied by the control dt.
+ means = reward_manager.step_reward_means.detach().cpu().tolist()
+ for name, mean in zip(reward_manager.step_reward_names, means, strict=True):
+ self.reward_sum[name] = self.reward_sum.get(name, 0.0) + mean
+ self.reward_steps += 1
+
+ def report(self):
+ count = self.count
+ return {
+ "velocity_axes": ["vx_m_per_s", "vy_m_per_s", "yaw_rate_rad_per_s"],
+ "velocity_frame": "robot body; clean critic local_linvel xy and gyro z",
+ "initial_command_env0": self.initial_command,
+ "mean_command": (self.command_sum / count).tolist() if count else None,
+ "mean_measured_velocity": (self.measured_sum / count).tolist() if count else None,
+ "tracking_rmse_by_axis": (self.error_squared_sum / count).sqrt().tolist()
+ if count
+ else None,
+ "mean_absolute_yaw_rate_rad_per_s": self.absolute_yaw_sum / count if count else None,
+ "weighted_reward_terms_before_dt": {
+ name: total / self.reward_steps for name, total in self.reward_sum.items()
+ }
+ if self.reward_steps
+ else {},
+ "reward_terms_note": "weighted terms BEFORE control-dt scaling; not per-step rewards",
+ }
diff --git a/rsl_rl/unilab_rma/evaluation_trace.py b/rsl_rl/unilab_rma/evaluation_trace.py
new file mode 100644
index 000000000..eb50f8263
--- /dev/null
+++ b/rsl_rl/unilab_rma/evaluation_trace.py
@@ -0,0 +1,282 @@
+"""Evaluation-only transition recording; no simulator or policy mutation."""
+
+import csv
+import hashlib
+import json
+import math
+import subprocess
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import torch
+
+
+def _json_value(value):
+ if isinstance(value, torch.Tensor):
+ return value.detach().cpu().tolist()
+ return value
+
+
+def control_contract(raw):
+ """Read resolved public action metadata, never infer action order from obs."""
+ term = raw.action_manager.get_term("joint_pos")
+ robot = raw.scene[term.cfg.entity_name]
+ return {
+ "action_type": type(term).__name__,
+ "joint_observation_order": list(robot.joint_names),
+ "action_target_joint_order": list(term.target_names),
+ "action_target_joint_indices": [int(index) for index in term.target_ids],
+ "scale": _json_value(term.scale),
+ "offset_rad": _json_value(term.offset),
+ "clip_config": term.cfg.clip,
+ "note": (
+ "Resolved position-action affine mapping: target = offset + scale * action, "
+ "before configured clipping and encoder-bias compensation. This is configuration "
+ "evidence, not a measurement of actuator torque or proof of correct physical response."
+ ),
+ }
+
+
+class EvaluationTrace:
+ """One CSV row per environment transition, unique directory per invocation."""
+
+ def __init__(self, parent, raw, arguments, checkpoint, *, warmup_steps=100):
+ self.num_envs = int(arguments["num_envs"])
+ self.dt = float(raw.step_dt)
+ if not math.isfinite(self.dt) or self.dt <= 0 or warmup_steps < 0:
+ raise ValueError("Trace requires positive control dt and nonnegative warmup steps")
+ self.warmup_steps = warmup_steps
+ self.control = control_contract(raw)
+ if len(self.control["action_target_joint_order"]) != 12:
+ raise ValueError("Trace requires the 12-action Go2 contract")
+ self.names = tuple(raw.reward_manager.step_reward_names)
+ parent = Path(parent).resolve()
+ parent.mkdir(parents=True, exist_ok=True)
+ self.directory = Path(tempfile.mkdtemp(prefix="eval_", dir=parent))
+ self.episode_ids = [0] * self.num_envs
+ self.episode_steps = [0] * self.num_envs
+ self.rows = 0
+ self.steps = 0
+ self.action_min = torch.full((12,), torch.inf, dtype=torch.float64)
+ self.action_max = -self.action_min.clone()
+ self.action_squared_sum = torch.zeros(12, dtype=torch.float64)
+ self.action_near_bound = torch.zeros(12, dtype=torch.float64)
+ self.velocity_sum = torch.zeros(3, dtype=torch.float64)
+ self.error_squared_sum = torch.zeros(3, dtype=torch.float64)
+ self.window_velocity_sum = torch.zeros(3, dtype=torch.float64)
+ self.window_error_squared_sum = torch.zeros(3, dtype=torch.float64)
+ self.window_count = 0
+ self.reward_sums = {name: 0.0 for name in self.names}
+ self._stream = None
+ fields = ["step", "env_id", "episode_id", "episode_step", "time_s", "next_time_s"]
+ fields += [f"command_{axis}" for axis in ("vx_m_s", "vy_m_s", "wz_rad_s")]
+ fields += [f"next_command_{axis}" for axis in ("vx_m_s", "vy_m_s", "wz_rad_s")]
+ fields += [
+ f"{phase}_{axis}"
+ for phase in ("before", "after")
+ for axis in ("vx_m_s", "vy_m_s", "wz_rad_s")
+ ]
+ fields += ["reward", "terminated", "truncated", "after_startup_window"]
+ fields += [f"action_{i}" for i in range(12)]
+ fields += [f"joint_pos_rel_{i}_rad" for i in range(12)]
+ fields += [f"joint_vel_rel_{i}_rad_s" for i in range(12)]
+ fields += [f"reward_rate/{name}" for name in self.names]
+ root = Path(__file__).resolve().parents[2]
+ try:
+ revision = (
+ subprocess.run(
+ ["git", "-C", str(root), "rev-parse", "HEAD"],
+ capture_output=True,
+ text=True,
+ check=False,
+ ).stdout.strip()
+ or None
+ )
+ dirty = subprocess.run(
+ ["git", "-C", str(root), "status", "--porcelain"],
+ capture_output=True,
+ text=True,
+ check=False,
+ )
+ dirty = bool(dirty.stdout.strip()) if dirty.returncode == 0 else None
+ except OSError:
+ revision, dirty = None, None
+ metadata = {
+ "format": "unilab-rma-evaluation-trace-v1",
+ "created_at_utc": datetime.now(timezone.utc).isoformat(),
+ "arguments": arguments,
+ "git_commit": revision,
+ "git_dirty": dirty,
+ "checkpoint_sha256": hashlib.sha256(Path(checkpoint).read_bytes()).hexdigest(),
+ "control_period_s": self.dt,
+ "warmup_steps_per_episode": warmup_steps,
+ "velocity_frame": "body; clean critic [49:51] and gyro z [2]",
+ "transition_alignment": (
+ "before = s_t; action = a_t; after = terminal s_(t+1), before any reset. "
+ "Commands at both endpoints are retained; reward belongs to this transition. "
+ "Full/window summaries use before velocity and command, matching --diagnostics."
+ ),
+ "reward_terms": (
+ "Per-environment weighted rates from public get_active_iterable_terms(); "
+ "before control-dt scaling. reward is the actual returned scalar. "
+ "Do not compare rates directly with reward or across changed weights."
+ ),
+ "action_near_bound_definition": "abs(normalized policy action) >= 0.95; NOT torque saturation",
+ "control_contract": self.control,
+ }
+ source_paths = (
+ "scripts/evaluate_rma.py",
+ "rsl_rl/unilab_rma/evaluation_trace.py",
+ "rsl_rl/unilab_rma/env_adapter.py",
+ "src/unilab/envs/mdp/actions/actions.py",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/base.yaml",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/mujoco.yaml",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma.yaml",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward.yaml",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_no_pose.yaml",
+ "src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_tight_tracking.yaml",
+ )
+ metadata["runtime_source_sha256"] = {
+ name: hashlib.sha256((root / name).read_bytes()).hexdigest()
+ for name in source_paths
+ if (root / name).is_file()
+ }
+ config_dir = self.directory / "task_source_snapshot"
+ config_dir.mkdir()
+ for name in source_paths:
+ if name.endswith(".yaml") and (root / name).is_file():
+ (config_dir / Path(name).name).write_bytes((root / name).read_bytes())
+ (self.directory / "run_config.json").write_text(
+ json.dumps(metadata, indent=2, default=str) + "\n", encoding="utf-8"
+ )
+ self._stream = (self.directory / "transitions.csv").open("w", newline="", encoding="utf-8")
+ self._csv = csv.DictWriter(self._stream, fieldnames=fields)
+ self._csv.writeheader()
+ self._stream.flush()
+
+ def record(self, before, action, terminal, reward, terminated, truncated, reward_manager):
+ before = before.detach().to(device="cpu", dtype=torch.float64)
+ after = terminal.detach().to(device="cpu", dtype=torch.float64)
+ actions = action.detach().to(device="cpu", dtype=torch.float64)
+ if before.shape != (self.num_envs, 52) or after.shape != before.shape:
+ raise ValueError("Trace requires clean critic tensors of shape (num_envs, 52)")
+ if actions.shape != (self.num_envs, 12):
+ raise ValueError("Trace requires actions of shape (num_envs, 12)")
+ if tuple(reward_manager.step_reward_names) != self.names:
+ raise ValueError("Reward terms changed during trace")
+ measured = torch.cat((before[:, 49:51], before[:, 2:3]), dim=1)
+ next_measured = torch.cat((after[:, 49:51], after[:, 2:3]), dim=1)
+ errors = (before[:, 42:45] - measured).square()
+ rewards = reward.detach().cpu().tolist()
+ terms = terminated.detach().cpu().tolist()
+ truncs = truncated.detach().cpu().tolist()
+ for index in range(self.num_envs):
+ rates = dict(reward_manager.get_active_iterable_terms(index))
+ if set(rates) != set(self.names) or any(len(value) != 1 for value in rates.values()):
+ raise ValueError("Unexpected public reward-term shape")
+ self.episode_steps[index] += 1
+ age = self.episode_steps[index]
+ in_window = age > self.warmup_steps
+ row = dict(
+ step=self.steps,
+ env_id=index,
+ episode_id=self.episode_ids[index],
+ episode_step=age,
+ time_s=(age - 1) * self.dt,
+ next_time_s=age * self.dt,
+ reward=rewards[index],
+ terminated=int(terms[index]),
+ truncated=int(truncs[index]),
+ after_startup_window=int(in_window),
+ )
+ for prefix, values in (
+ ("command", before[index, 42:45]),
+ ("next_command", after[index, 42:45]),
+ ("before", measured[index]),
+ ("after", next_measured[index]),
+ ):
+ row.update(
+ zip(
+ (f"{prefix}_{axis}" for axis in ("vx_m_s", "vy_m_s", "wz_rad_s")),
+ values.tolist(),
+ strict=True,
+ )
+ )
+ row.update({f"action_{i}": value for i, value in enumerate(actions[index].tolist())})
+ row.update(
+ {
+ f"joint_pos_rel_{i}_rad": value
+ for i, value in enumerate(before[index, 6:18].tolist())
+ }
+ )
+ row.update(
+ {
+ f"joint_vel_rel_{i}_rad_s": value
+ for i, value in enumerate(before[index, 18:30].tolist())
+ }
+ )
+ for name in self.names:
+ row[f"reward_rate/{name}"] = rates[name][0]
+ self.reward_sums[name] += rates[name][0]
+ self._csv.writerow(row)
+ if in_window:
+ self.window_count += 1
+ self.window_velocity_sum += measured[index]
+ self.window_error_squared_sum += errors[index]
+ if terms[index] or truncs[index]:
+ self.episode_ids[index] += 1
+ self.episode_steps[index] = 0
+ self.action_min = torch.minimum(self.action_min, actions.amin(0))
+ self.action_max = torch.maximum(self.action_max, actions.amax(0))
+ self.action_squared_sum += actions.square().sum(0)
+ self.action_near_bound += (actions.abs() >= 0.95).sum(0)
+ self.velocity_sum += measured.sum(0)
+ self.error_squared_sum += errors.sum(0)
+ self.rows += self.num_envs
+ self.steps += 1
+ if self.steps % 50 == 0:
+ self._stream.flush()
+
+ def report(self):
+ def velocity_report(count, total, squared):
+ return {
+ "transitions": count,
+ "mean_measured_velocity": (total / count).tolist() if count else None,
+ "tracking_rmse_by_axis": (squared / count).sqrt().tolist() if count else None,
+ }
+
+ return {
+ "directory": str(self.directory),
+ "full": velocity_report(self.rows, self.velocity_sum, self.error_squared_sum),
+ "after_startup_window": velocity_report(
+ self.window_count, self.window_velocity_sum, self.window_error_squared_sum
+ ),
+ "action_target_joint_order": self.control["action_target_joint_order"],
+ "normalized_action_min": self.action_min.tolist() if self.rows else None,
+ "normalized_action_max": self.action_max.tolist() if self.rows else None,
+ "normalized_action_rms": (self.action_squared_sum / self.rows).sqrt().tolist()
+ if self.rows
+ else None,
+ "normalized_action_near_bound_fraction": (self.action_near_bound / self.rows).tolist()
+ if self.rows
+ else None,
+ "mean_weighted_reward_rates_before_dt": {
+ name: value / self.rows for name, value in self.reward_sums.items()
+ }
+ if self.rows
+ else {},
+ }
+
+ def finish(self, evaluation_report):
+ result = dict(evaluation_report, trace=self.report())
+ (self.directory / "summary.json").write_text(
+ json.dumps(result, indent=2) + "\n", encoding="utf-8"
+ )
+ self._stream.flush()
+ return result
+
+ def close(self):
+ if self._stream is not None:
+ self._stream.close()
+ self._stream = None
diff --git a/rsl_rl/unilab_rma/experiment_report.py b/rsl_rl/unilab_rma/experiment_report.py
new file mode 100644
index 000000000..394df59ac
--- /dev/null
+++ b/rsl_rl/unilab_rma/experiment_report.py
@@ -0,0 +1,118 @@
+"""Build a static, auditable report from selected RMA evaluation and CSV data."""
+
+import csv
+import json
+from pathlib import Path
+
+
+def load_evaluations(root):
+ """Read published reports; fail on mixed command or malformed comparisons."""
+ root = Path(root)
+ records = []
+ for label in ("baseline", "forward_v1"):
+ for seed in (123, 456, 789):
+ report = json.loads((root / label / f"seed{seed}.json").read_text())
+ diagnostics = report["diagnostics"]
+ if (
+ report["policy"] != "teacher"
+ or report["seed"] != seed
+ or diagnostics["mean_command"] != [0.5, 0.0, 0.0]
+ ):
+ raise ValueError(f"Unexpected evaluation protocol: {label}, seed {seed}")
+ if report["total_transitions"] != 8000:
+ raise ValueError("Comparison expects 8000 total transitions per evaluation")
+ records.append(
+ {
+ "model": label,
+ "seed": seed,
+ "target_vx_m_s": 0.5,
+ "mean_vx_m_s": diagnostics["mean_measured_velocity"][0],
+ "vx_rmse_m_s": diagnostics["tracking_rmse_by_axis"][0],
+ "planar_rmse_m_s": report["planar_velocity_rmse_m_per_s"],
+ "terminations": report["terminations"],
+ "total_transitions": report["total_transitions"],
+ }
+ )
+ return records
+
+
+def rolling_mean(values, window=100):
+ """Trailing mean over available numeric rows, retaining startup samples."""
+ output, total = [], 0.0
+ for index, value in enumerate(values):
+ total += value
+ if index >= window:
+ total -= values[index - window]
+ output.append(total / min(index + 1, window))
+ return output
+
+
+def build_report(root):
+ """Generate CSV/PNG outputs without importing or running the simulator."""
+ import matplotlib
+
+ matplotlib.use("Agg")
+ import matplotlib.pyplot as plt
+
+ root = Path(root)
+ records = load_evaluations(root)
+ with (root / "evaluation_summary.csv").open("w", newline="", encoding="utf-8") as stream:
+ writer = csv.DictWriter(stream, fieldnames=list(records[0]))
+ writer.writeheader()
+ writer.writerows(records)
+ figures = root / "figures"
+ figures.mkdir(parents=True, exist_ok=True)
+ fig, axes = plt.subplots(1, 2, figsize=(10, 4), constrained_layout=True)
+ colors = ("#5C6F91", "#E38B3B")
+ for index, label in enumerate(("baseline", "forward_v1")):
+ selected = [row for row in records if row["model"] == label]
+ for axis, field in zip(axes, ("mean_vx_m_s", "vx_rmse_m_s"), strict=True):
+ values = [row[field] for row in selected]
+ axis.bar(index, sum(values) / len(values), color=colors[index], alpha=0.65)
+ axis.scatter([index - 0.07, index, index + 0.07], values, color="#222222", zorder=3)
+ axes[0].axhline(0.5, color="#C53434", linestyle="--", label="Command: 0.5 m/s")
+ axes[0].set(
+ ylabel="Mean body-frame vx (m/s)", title="Measured forward speed", ylim=(-0.04, 0.56)
+ )
+ axes[0].legend(fontsize=8)
+ axes[1].set(ylabel="Forward tracking RMSE (m/s)", title="Forward speed error", ylim=(0, 0.56))
+ for axis in axes:
+ axis.set_xticks([0, 1], ["Original teacher", "Forward v1"])
+ axis.grid(axis="y", alpha=0.2)
+ fig.suptitle(
+ "Same checkpoint per group; dots are evaluation seeds, not training replicates", fontsize=10
+ )
+ fig.savefig(figures / "velocity_comparison.png", dpi=170)
+ plt.close(fig)
+
+ with (root / "forward_v1/training_metrics.csv").open() as stream:
+ rows = list(csv.DictReader(stream))
+ iterations = [int(row["iteration"]) for row in rows]
+ rewards = [float(row["mean_step_reward"]) for row in rows]
+ fig, axes = plt.subplots(2, 1, figsize=(10, 6), sharex=True, constrained_layout=True)
+ axes[0].plot(iterations, rewards, alpha=0.18, color="#4679A8", label="Per-update reward")
+ axes[0].plot(
+ iterations, rolling_mean(rewards), color="#1D4C79", label="Trailing 100-update mean"
+ )
+ axes[0].set(
+ ylabel="Mean step reward", title="Forward v1: 64 environments, rollout 24, training seed 42"
+ )
+ completed = [
+ (int(row["iteration"]), float(row["mean_episode_return"]))
+ for row in rows
+ if row["mean_episode_return"]
+ ]
+ axes[1].scatter(
+ [x for x, _ in completed], [y for _, y in completed], s=5, alpha=0.3, color="#E38B3B"
+ )
+ axes[1].set(
+ xlabel="Completed PPO updates",
+ ylabel="Mean completed episode return per update",
+ title="Only updates containing completed episodes are shown",
+ )
+ for axis in axes:
+ axis.grid(alpha=0.2)
+ axes[0].legend(fontsize=8)
+ fig.savefig(figures / "forward_v1_training.png", dpi=170)
+ plt.close(fig)
+ return {"evaluation_reports": len(records), "training_rows": len(rows), "figures": str(figures)}
diff --git a/rsl_rl/unilab_rma/ppo.py b/rsl_rl/unilab_rma/ppo.py
new file mode 100644
index 000000000..b27155c59
--- /dev/null
+++ b/rsl_rl/unilab_rma/ppo.py
@@ -0,0 +1,47 @@
+"""Small explicit PPO implementation, independent of external RSL-RL internals."""
+
+import torch
+
+
+def gae(rewards, values, next_values, terminated, truncated, gamma=0.99, lam=0.95):
+ advantage = torch.zeros_like(rewards)
+ carry = torch.zeros_like(rewards[0])
+ for t in reversed(range(len(rewards))):
+ # Timeout bootstraps from PRE-reset state, but never crosses episode boundary.
+ delta = rewards[t] + gamma * (~terminated[t]).float() * next_values[t] - values[t]
+ carry = delta + gamma * lam * (~(terminated[t] | truncated[t])).float() * carry
+ advantage[t] = carry
+ return advantage, advantage + values
+
+
+class PPO:
+ def __init__(self, model, lr=3e-4):
+ self.model = model
+ self.optimizer = torch.optim.Adam(model.parameters(), lr=lr)
+
+ def update(self, batch, epochs=5, minibatch=256, clip=0.2):
+ adv = batch["advantages"]
+ adv = (adv - adv.mean()) / (adv.std(unbiased=False) + 1e-8)
+ losses = []
+ for _ in range(epochs):
+ for ids in torch.randperm(len(adv), device=adv.device).split(minibatch):
+ dist = self.model.distribution(batch["obs"][ids], batch["priv"][ids])
+ logp = self.model.log_prob(dist, batch["raw"][ids])
+ ratio = (logp - batch["logp"][ids]).exp()
+ surrogate = torch.minimum(
+ ratio * adv[ids], ratio.clamp(1 - clip, 1 + clip) * adv[ids]
+ )
+ value = self.model.value(batch["critic"][ids], batch["priv"][ids])
+ value_loss = (value - batch["returns"][ids]).square().mean()
+ # Sample estimate of squashed-policy entropy; base Gaussian entropy is not used.
+ raw_entropy = dist.rsample()
+ entropy = -self.model.log_prob(dist, raw_entropy).mean()
+ loss = -surrogate.mean() + 0.5 * value_loss - 0.001 * entropy
+ if not torch.isfinite(loss):
+ raise FloatingPointError("Non-finite PPO loss")
+ self.optimizer.zero_grad()
+ loss.backward()
+ torch.nn.utils.clip_grad_norm_(self.model.parameters(), 1.0)
+ self.optimizer.step()
+ losses.append(loss.item())
+ return sum(losses) / len(losses)
diff --git a/rsl_rl/unilab_rma/rendering.py b/rsl_rl/unilab_rma/rendering.py
new file mode 100644
index 000000000..8dcf65811
--- /dev/null
+++ b/rsl_rl/unilab_rma/rendering.py
@@ -0,0 +1,110 @@
+"""Optional interactive evaluation; imported only when --render is requested.
+
+Keep policy inference, environment stepping, and metrics in the caller. This
+iterator only displays their state and paces playback using wall-clock waits.
+"""
+
+from __future__ import annotations
+
+import copy
+import math
+import sys
+import threading
+import time
+from collections.abc import Iterator
+from contextlib import contextmanager
+from typing import Any
+
+
+@contextmanager
+def _passive_viewer(mujoco: Any, model: Any, data: Any):
+ """Wait for MuJoCo's GUI thread before Python tears down native libraries."""
+ before = set(threading.enumerate())
+ viewer = mujoco.viewer.launch_passive(model, data)
+ # In MuJoCo 3.11 close() requests exit but does not join its daemon GUI
+ # thread. Capture that launch's new thread, without touching older workers.
+ viewer_threads = [
+ thread
+ for thread in threading.enumerate()
+ if thread not in before and "_launch_internal" in thread.name
+ ]
+ try:
+ with viewer:
+ yield viewer
+ finally:
+ for thread in viewer_threads:
+ thread.join(timeout=5.0)
+ if thread.is_alive():
+ raise RuntimeError("MuJoCo viewer did not finish shutting down within 5 seconds")
+
+
+def rendered_steps(env: Any, count: int, *, speed: float = 1.0) -> Iterator[int]:
+ """Render environment zero through UniLab's physics-snapshot contract.
+
+ The environment must already be reset. Its owner remains responsible for
+ calling close() in a finally block, including on renderer errors or Ctrl+C.
+ Rendering never changes ctrl_dt, the actions, or the simulation substeps.
+ """
+ if not math.isfinite(speed) or speed <= 0:
+ raise ValueError("Playback speed must be finite and positive")
+ period = float(env.step_dt) / speed
+ if not math.isfinite(period) or period <= 0:
+ raise ValueError("Interactive playback requires a finite, positive step_dt")
+ # MuJoCo's batch backend supports snapshots, NOT init_play_renderer().
+ # Use the same playback contract as UniLab's play_interactive entrypoint.
+ import glfw
+ import mujoco
+ import mujoco.viewer
+
+ from unilab.visualization.playback_state import (
+ PhysicsStateApplier,
+ assert_physics_state_playback_supported,
+ )
+
+ assert_physics_state_playback_supported(env, entrypoint="evaluate_rma --render")
+ if not glfw.init():
+ raise RuntimeError(
+ "Cannot open the MuJoCo viewer: no usable GLFW display. "
+ "In WSL, check WSLg/DISPLAY and OpenGL support. "
+ "Omit --render to continue normal headless evaluation."
+ )
+ glfw.terminate()
+ # Neither viewer.sync() nor mouse perturbations may write into the live
+ # physics model/data: both playback objects belong exclusively to the GUI.
+ source_model = env.get_playback_model(env_index=0)
+ if isinstance(source_model, str):
+ model = (
+ mujoco.MjModel.from_binary_path(source_model)
+ if source_model.lower().endswith(".mjb")
+ else mujoco.MjModel.from_xml_path(source_model)
+ )
+ else:
+ model = copy.deepcopy(source_model)
+ data = mujoco.MjData(model)
+ applier = PhysicsStateApplier(env, model, env_index=0)
+ applier.apply(env.get_physics_state_snapshot()[0], data)
+ print(
+ f"[render] Showing environment 0 at {speed:g}x speed; "
+ "close the window or press Ctrl+C to stop.",
+ file=sys.stderr,
+ )
+ with _passive_viewer(mujoco, model, data) as viewer:
+ with viewer.lock():
+ viewer.cam.distance = 2.5
+ viewer.cam.elevation = -20.0
+ base_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_BODY, "base")
+ if base_id >= 0:
+ viewer.cam.type = mujoco.mjtCamera.mjCAMERA_TRACKING
+ viewer.cam.trackbodyid = base_id
+ viewer.sync()
+ for index in range(count):
+ if not viewer.is_running():
+ break
+ started = time.perf_counter()
+ yield index
+ with viewer.lock():
+ applier.apply(env.get_physics_state_snapshot()[0], data)
+ viewer.sync()
+ remaining = period - (time.perf_counter() - started)
+ if remaining > 0:
+ time.sleep(remaining)
diff --git a/rsl_rl/unilab_rma/runner.py b/rsl_rl/unilab_rma/runner.py
new file mode 100644
index 000000000..5402ba91f
--- /dev/null
+++ b/rsl_rl/unilab_rma/runner.py
@@ -0,0 +1,146 @@
+from dataclasses import asdict
+from pathlib import Path
+
+import torch
+
+from .adaptation_module import AdaptationTrainer, HistoryBuffer
+from .ppo import PPO, gae
+
+
+def checkpoint(path, model, adaptation, iteration, optimizer=None, phase="teacher"):
+ Path(path).parent.mkdir(parents=True, exist_ok=True)
+ torch.save(
+ {
+ "format": "unilab-rma-v1",
+ "config": asdict(model.cfg),
+ "teacher": model.state_dict(),
+ "adaptation": adaptation.state_dict(),
+ "iteration": iteration,
+ "phase": phase,
+ "optimizer": None if optimizer is None else optimizer.state_dict(),
+ },
+ path,
+ )
+
+
+def train_teacher(env, model, adaptation, iterations, path, horizon=24, logger=None):
+ ppo = PPO(model)
+ obs, critic, priv = env.reset()
+ if logger is not None:
+ from .training_log import EpisodeLog
+
+ episodes = EpisodeLog(env.num_envs)
+ for iteration in range(iterations):
+ data = {
+ k: []
+ for k in (
+ "obs",
+ "critic",
+ "priv",
+ "raw",
+ "logp",
+ "values",
+ "rewards",
+ "next_values",
+ "terminated",
+ "truncated",
+ )
+ }
+ for _ in range(horizon):
+ with torch.no_grad():
+ action, raw, logp = model.sample(obs, priv)
+ value = model.value(critic, priv)
+ following, reward, term, trunc, terminal = env.step(action)
+ next_value = model.value(terminal[1], terminal[2])
+ entries = dict(
+ obs=obs,
+ critic=critic,
+ priv=priv,
+ raw=raw,
+ logp=logp,
+ values=value,
+ rewards=reward,
+ next_values=next_value,
+ terminated=term,
+ truncated=trunc,
+ )
+ for key, tensor in entries.items():
+ data[key].append(tensor.detach().clone())
+ obs, critic, priv = following
+ batch = {key: torch.stack(value) for key, value in data.items()}
+ batch["advantages"], batch["returns"] = gae(
+ batch["rewards"],
+ batch["values"],
+ batch["next_values"],
+ batch["terminated"],
+ batch["truncated"],
+ )
+ loss = ppo.update({k: v.flatten(0, 1) for k, v in batch.items()})
+ print(
+ f"teacher iteration={iteration} loss={loss:.5f} mean_step_reward={batch['rewards'].mean():.5f}",
+ flush=True,
+ )
+ if logger is not None:
+ logger.write(
+ iteration + 1,
+ (iteration + 1) * horizon * env.num_envs,
+ loss=loss,
+ mean_step_reward=batch["rewards"].mean().item(),
+ **episodes.consume(batch["rewards"], batch["terminated"] | batch["truncated"]),
+ )
+ if (iteration + 1) % 20 == 0 or iteration + 1 == iterations:
+ checkpoint(path, model, adaptation, iteration + 1, ppo.optimizer)
+
+
+def train_student(env, teacher, adaptation, iterations, path, horizon=24, logger=None):
+ trainer = AdaptationTrainer(teacher, adaptation)
+ obs, _, priv = env.reset()
+ history = HistoryBuffer(env.num_envs, teacher.cfg, obs.device)
+ history.push(obs)
+ episode_returns = torch.zeros(env.num_envs, device=obs.device)
+ episode_lengths = torch.zeros(env.num_envs, device=obs.device)
+ for iteration in range(iterations):
+ completed_returns, completed_lengths, rewards = [], [], []
+ for _ in range(horizon):
+ trainer.add(history.data, priv)
+ with torch.no_grad():
+ # Students collect their OWN state distribution, not teacher rollouts.
+ action = teacher.actor(obs, adaptation(history.data)).tanh()
+ (obs, _, priv), reward, term, trunc, _ = env.step(action)
+ done = term | trunc
+ episode_returns += reward
+ episode_lengths += 1
+ rewards.append(reward.mean().item())
+ completed_returns.extend(episode_returns[done].tolist())
+ completed_lengths.extend(episode_lengths[done].tolist())
+ episode_returns[done] = 0
+ episode_lengths[done] = 0
+ history.push(obs, done)
+ loss = trainer.update()
+ episodic = (
+ f" episode_return={sum(completed_returns) / len(completed_returns):.5f}"
+ f" episode_length={sum(completed_lengths) / len(completed_lengths):.1f}"
+ if completed_returns
+ else " completed_episodes=0"
+ )
+ print(
+ f"student iteration={iteration} latent_mse={loss:.6f}"
+ f" mean_step_reward={sum(rewards) / len(rewards):.5f}" + episodic,
+ flush=True,
+ )
+ if logger is not None:
+ logger.write(
+ iteration + 1,
+ (iteration + 1) * horizon * env.num_envs,
+ latent_mse=loss,
+ mean_step_reward=sum(rewards) / len(rewards),
+ completed_episodes=len(completed_returns),
+ mean_episode_return=(
+ sum(completed_returns) / len(completed_returns) if completed_returns else None
+ ),
+ mean_episode_length_steps=(
+ sum(completed_lengths) / len(completed_lengths) if completed_lengths else None
+ ),
+ )
+ if (iteration + 1) % 20 == 0 or iteration + 1 == iterations:
+ checkpoint(path, teacher, adaptation, iteration + 1, trainer.optimizer, phase="student")
diff --git a/rsl_rl/unilab_rma/scene_contract.py b/rsl_rl/unilab_rma/scene_contract.py
new file mode 100644
index 000000000..ae77cce0e
--- /dev/null
+++ b/rsl_rl/unilab_rma/scene_contract.py
@@ -0,0 +1,46 @@
+"""Cold-path XML discovery; never guess missing scene/home/geometry metadata."""
+
+import xml.etree.ElementTree as ET
+from pathlib import Path
+
+
+def expanded_xml(path, stack=()):
+ path = Path(path).resolve()
+ if path in stack:
+ raise ValueError(f"Cyclic XML include: {path}")
+ if not path.is_file():
+ raise FileNotFoundError(f"Restore original UniLab XML/mesh assets first: {path}")
+ root = ET.parse(path).getroot()
+
+ def expand(parent):
+ for child in list(parent):
+ if child.tag == "include":
+ included = expanded_xml(path.parent / child.attrib["file"], (*stack, path))
+ index = list(parent).index(child)
+ parent.remove(child)
+ for offset, element in enumerate(list(included)):
+ parent.insert(index + offset, element)
+ else:
+ expand(child)
+
+ expand(root)
+ return root
+
+
+def prepare_scene(override, root_dir):
+ scene = override["scene"]
+ path = Path(scene["model_file"])
+ if not path.is_absolute():
+ path = Path(root_dir) / path
+ tree = expanded_xml(path)
+ base = next((b for b in tree.iter("body") if b.get("name") == "base"), None)
+ if base is None:
+ raise ValueError("Expected the Go2 base body in restored scene")
+ names = [g.attrib["name"] for g in base.iter("geom") if g.get("name")]
+ if not names or len(names) != len(set(names)):
+ raise ValueError(
+ "RMA requires unique named robot geoms; inspect/name collision geoms in XML"
+ )
+ scene["model_file"] = str(path.resolve())
+ scene["entities"]["robot"]["geom_names"] = names
+ print(f"RMA friction geom selection from XML: {names}", flush=True)
diff --git a/rsl_rl/unilab_rma/tensorrt_runtime.py b/rsl_rl/unilab_rma/tensorrt_runtime.py
new file mode 100644
index 000000000..b3ecf928a
--- /dev/null
+++ b/rsl_rl/unilab_rma/tensorrt_runtime.py
@@ -0,0 +1,129 @@
+"""Optional C++ inference bridge; no TensorRT Python package is required.
+
+The worker persists for an evaluation run. Physics, observation/history assembly,
+episode resets and optional rendering continue to belong to the UniLab caller.
+"""
+
+from __future__ import annotations
+
+import os
+import select
+import struct
+import subprocess
+import time
+from pathlib import Path
+
+import numpy as np
+import torch
+
+
+class TensorRTWorker:
+ def __init__(self, worker: Path, engine: Path, cfg, *, timeout_s: float = 30.0):
+ if os.name != "posix":
+ raise RuntimeError("Run the TensorRT simulation bridge inside Linux/WSL")
+ if (cfg.obs_dim, cfg.history_length, cfg.action_dim) != (49, 50, 12):
+ raise ValueError("C++ worker requires observation=49, history=50, action=12")
+ if not np.isfinite(timeout_s) or timeout_s <= 0:
+ raise ValueError("Worker timeout must be finite and positive")
+ worker, engine = Path(worker).resolve(), Path(engine).resolve()
+ if not worker.is_file():
+ raise FileNotFoundError(f"Build with WITH_TENSORRT=ON first: {worker}")
+ if not engine.is_file():
+ raise FileNotFoundError(f"TensorRT engine not found: {engine}")
+ self.timeout_s = timeout_s
+ self._process = subprocess.Popen(
+ [str(worker), "--engine", str(engine)],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=None,
+ bufsize=0,
+ )
+ self._closed = False
+ try:
+ os.set_blocking(self._process.stdin.fileno(), False)
+ os.set_blocking(self._process.stdout.fileno(), False)
+ magic, obs, history, action = struct.unpack("<4sIII", self._read_exact(16))
+ if (magic, obs, history, action) != (b"RMA1", 49, 50, 12):
+ raise RuntimeError("TensorRT worker protocol/dimension mismatch")
+ except BaseException:
+ self.close()
+ raise
+
+ def _read_exact(self, size: int) -> bytes:
+ fd = self._process.stdout.fileno()
+ deadline = time.monotonic() + self.timeout_s
+ result = bytearray()
+ while len(result) < size:
+ remaining = deadline - time.monotonic()
+ if remaining <= 0 or not select.select([fd], [], [], remaining)[0]:
+ raise TimeoutError("TensorRT worker timed out while reading output")
+ try:
+ part = os.read(fd, size - len(result))
+ except BlockingIOError:
+ continue
+ if not part:
+ raise RuntimeError("TensorRT worker closed output; check its stderr message")
+ result.extend(part)
+ return bytes(result)
+
+ def _write_all(self, payload: bytes) -> None:
+ fd = self._process.stdin.fileno()
+ pending = memoryview(payload)
+ deadline = time.monotonic() + self.timeout_s
+ while pending:
+ remaining = deadline - time.monotonic()
+ if remaining <= 0 or not select.select([], [fd], [], remaining)[1]:
+ raise TimeoutError("TensorRT worker timed out while writing input")
+ try:
+ written = os.write(fd, pending)
+ except BlockingIOError:
+ continue
+ except BrokenPipeError as error:
+ raise RuntimeError(
+ "TensorRT worker closed input; check its stderr message"
+ ) from error
+ pending = pending[written:]
+
+ def infer(self, observation: torch.Tensor, history: torch.Tensor) -> torch.Tensor:
+ if self._closed:
+ raise RuntimeError("TensorRT worker is closed")
+ if observation.ndim != 2 or observation.shape[1] != 49:
+ raise ValueError("Expected observation shape [num_envs, 49]")
+ count = observation.shape[0]
+ if count < 1 or history.shape != (count, 50, 49):
+ raise ValueError("Expected history shape [num_envs, 50, 49]")
+ obs = observation.detach().to(device="cpu", dtype=torch.float32).contiguous().numpy()
+ hist = history.detach().to(device="cpu", dtype=torch.float32).contiguous().numpy()
+ if not np.isfinite(obs).all() or not np.isfinite(hist).all():
+ raise ValueError("TensorRT inputs must be finite")
+ actions = np.empty((count, 12), dtype=np.float32)
+ # Fixed-batch-one engine: process each environment independently. Read
+ # each reply before the next request so pipe capacity cannot deadlock.
+ for index in range(count):
+ payload = np.concatenate((obs[index], hist[index].reshape(-1))).astype(
+ " None:
+ if self._closed:
+ return
+ self._closed = True
+ process = self._process
+ try:
+ process.stdin.close()
+ try:
+ process.wait(timeout=1.0)
+ except subprocess.TimeoutExpired:
+ process.terminate()
+ try:
+ process.wait(timeout=1.0)
+ except subprocess.TimeoutExpired:
+ process.kill()
+ process.wait(timeout=1.0)
+ finally:
+ process.stdout.close()
diff --git a/rsl_rl/unilab_rma/training_log.py b/rsl_rl/unilab_rma/training_log.py
new file mode 100644
index 000000000..04630c06d
--- /dev/null
+++ b/rsl_rl/unilab_rma/training_log.py
@@ -0,0 +1,115 @@
+"""Per-iteration CSV and TensorBoard records, independent of policy updates."""
+
+import csv
+import json
+import tempfile
+import time
+from datetime import datetime
+from pathlib import Path
+
+
+class TrainingLog:
+ FIELDS = (
+ "iteration",
+ "total_transitions",
+ "wall_seconds",
+ "loss",
+ "latent_mse",
+ "mean_step_reward",
+ "completed_episodes",
+ "mean_episode_return",
+ "mean_episode_length_steps",
+ )
+
+ def __init__(self, output, phase, metadata, log_dir=None):
+ output = Path(output).resolve()
+ parent = Path(log_dir).resolve() if log_dir else output.parent / (output.stem + "_logs")
+ parent.mkdir(parents=True, exist_ok=True)
+ self.directory = Path(
+ tempfile.mkdtemp(prefix=datetime.now().strftime("%Y%m%d_%H%M%S_"), dir=parent)
+ )
+ self._writer = None
+ self._stream = None
+ self._started = time.monotonic()
+ self._phase = phase
+ try:
+ from torch.utils.tensorboard import SummaryWriter
+
+ self._writer = SummaryWriter(log_dir=str(self.directory / "tensorboard"), flush_secs=10)
+ self._stream = (self.directory / "metrics.csv").open("w", newline="", encoding="utf-8")
+ self._csv = csv.DictWriter(self._stream, fieldnames=self.FIELDS)
+ self._csv.writeheader()
+ self._stream.flush()
+ record = dict(
+ metadata,
+ output=str(output),
+ phase=phase,
+ log_directory=str(self.directory),
+ iteration_numbering="one-based completed updates",
+ )
+ (self.directory / "run_config.json").write_text(
+ json.dumps(record, indent=2, default=str) + "\n", encoding="utf-8"
+ )
+ except BaseException:
+ self.close()
+ raise
+
+ def write(self, iteration, total_transitions, **metrics):
+ row = dict(
+ iteration=iteration,
+ total_transitions=total_transitions,
+ wall_seconds=time.monotonic() - self._started,
+ **metrics,
+ )
+ self._csv.writerow(row)
+ self._stream.flush() # Keep completed iterations available after interruption.
+ for name, value in row.items():
+ if value is not None and name != "iteration":
+ self._writer.add_scalar(self._phase + "/" + name, value, iteration)
+
+ def close(self):
+ try:
+ if self._writer is not None:
+ self._writer.close()
+ self._writer = None
+ finally:
+ if self._stream is not None:
+ self._stream.close()
+ self._stream = None
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.close()
+
+
+class EpisodeLog:
+ """CPU-only bookkeeping; consumes detached rollout copies once per update."""
+
+ def __init__(self, count):
+ self.returns = [0.0] * count
+ self.lengths = [0] * count
+
+ def consume(self, rewards, done):
+ completed_returns, completed_lengths = [], []
+ for reward_row, done_row in zip(
+ rewards.detach().cpu().tolist(), done.detach().cpu().tolist()
+ ):
+ for index, (reward, finished) in enumerate(zip(reward_row, done_row)):
+ self.returns[index] += reward
+ self.lengths[index] += 1
+ if finished:
+ completed_returns.append(self.returns[index])
+ completed_lengths.append(self.lengths[index])
+ self.returns[index] = 0.0
+ self.lengths[index] = 0
+ return dict(
+ completed_episodes=len(completed_returns),
+ mean_episode_return=(
+ sum(completed_returns) / len(completed_returns) if completed_returns else None
+ ),
+ mean_episode_length_steps=(
+ sum(completed_lengths) / len(completed_lengths) if completed_lengths else None
+ ),
+ )
diff --git a/scripts/check_rma_mapping.py b/scripts/check_rma_mapping.py
new file mode 100644
index 000000000..97955f032
--- /dev/null
+++ b/scripts/check_rma_mapping.py
@@ -0,0 +1,58 @@
+"""Check nonzero joint targets against actual actuator storage without stepping physics."""
+
+import argparse
+import json
+
+import torch
+from train_rma import build_environment
+from unilab_rma import RMAConfig
+from unilab_rma.evaluation_diagnostics import FORWARD_TASK
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.parse_args()
+ raw, env = build_environment(2, RMAConfig(), "cpu", 123, task=FORWARD_TASK)
+ try:
+ env.reset()
+ robot = raw.scene["robot"]
+ joints = list(robot.joint_names)
+ actuator_joints = list(raw.backend.get_actuator_joint_names())
+ indices = [actuator_joints.index(name) for name in joints]
+ control = robot.data.control_buffer
+ if not isinstance(control, torch.Tensor) or len(joints) != 12:
+ raise ValueError("Expected the 12-joint Torch Go2 control plane")
+ errors, equivalence = [], []
+ for after_reset in (False, True):
+ if after_reset:
+ raw.reset(torch.tensor([0], device=raw.device))
+ saved = control.clone()
+ try:
+ for column in range(12):
+ target = torch.zeros((2, 12), dtype=control.dtype, device=control.device)
+ target[0, column] = 0.1
+ target[1, column] = -0.1
+ robot.set_full_width_joint_position_target(target)
+ actual = control.clone()
+ errors.append((actual[:, indices] - target).abs().max().item())
+ robot.set_joint_position_target(target)
+ equivalence.append((actual - control).abs().max().item())
+ finally:
+ control.copy_(saved)
+ report = dict(
+ cases=len(errors),
+ num_envs=2,
+ partial_reset_checked=True,
+ max_abs_mapping_error_rad=max(errors),
+ max_abs_fast_vs_ordinary_error_rad=max(equivalence),
+ physics_steps=0,
+ )
+ print(json.dumps(report, indent=2))
+ if max(errors + equivalence) > 1e-6:
+ parser.exit(1, "Mapping check FAILED; do not start a new training run.\n")
+ finally:
+ raw.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/diagnose_rma_control.py b/scripts/diagnose_rma_control.py
new file mode 100644
index 000000000..7759b1566
--- /dev/null
+++ b/scripts/diagnose_rma_control.py
@@ -0,0 +1,92 @@
+"""Short single-world teacher control diagnosis; never updates model weights."""
+
+import argparse
+import hashlib
+import json
+from pathlib import Path
+
+import torch
+from train_rma import build_environment
+from unilab_rma import ActorCriticRMA, AdaptationModule, RMAConfig
+from unilab_rma.control_diagnostics import ControlDiagnostics
+from unilab_rma.evaluation_diagnostics import RMA_TASKS, EvaluationDiagnostics
+from unilab_rma.evaluation_trace import EvaluationTrace
+
+
+def main():
+ p = argparse.ArgumentParser(description=__doc__)
+ p.add_argument("--checkpoint", type=Path, required=True)
+ p.add_argument("--task", choices=RMA_TASKS, required=True)
+ p.add_argument("--steps", type=int, default=500)
+ p.add_argument("--seed", type=int, default=123)
+ p.add_argument("--command", nargs=3, type=float, default=[0.5, 0.0, 0.0])
+ p.add_argument("--output-dir", type=Path, default=Path("runs/rma/control_diagnostics"))
+ args = p.parse_args()
+ if args.steps < 1 or args.steps > 5000:
+ p.error("steps must be between 1 and 5000 for this short diagnostic")
+ saved = torch.load(args.checkpoint, map_location="cpu", weights_only=True)
+ if saved.get("format") != "unilab-rma-v1" or saved.get("phase") != "teacher":
+ p.error("This diagnostic requires a teacher checkpoint")
+ torch.manual_seed(args.seed)
+ cfg = RMAConfig(**saved["config"])
+ model = ActorCriticRMA(cfg).eval()
+ # The reference evaluator initializes this even in teacher mode. Preserve
+ # its RNG consumption so environment observations have the same sequence.
+ AdaptationModule(cfg).eval()
+ model.load_state_dict(saved["teacher"])
+ raw, env = build_environment(1, cfg, "cpu", args.seed, task=args.task, command=args.command)
+ trace = None
+ try:
+ obs, critic, priv = env.reset()
+ trace = EvaluationTrace(args.output_dir, raw, dict(vars(args), num_envs=1), args.checkpoint)
+ recorder = ControlDiagnostics(raw, trace.directory)
+ diagnostics = EvaluationDiagnostics()
+ with torch.no_grad():
+ for _ in range(args.steps):
+ before = recorder.before()
+ diagnostics.record_state(critic)
+ action = model.actor(obs, model.encoder(priv)).tanh()
+ # Read final controls/physics BEFORE any explicit episode reset.
+ state = raw.step(action.to(raw.device))
+ terminal = env.read(state.obs)
+ term, trunc = bool(state.terminated[0]), bool(state.truncated[0])
+ recorder.record(before, action, term, trunc)
+ trace.record(
+ critic,
+ action,
+ terminal[1],
+ state.reward,
+ state.terminated,
+ state.truncated,
+ raw.reward_manager,
+ )
+ diagnostics.record_rewards(raw.reward_manager)
+ if term or trunc:
+ raw.reset(torch.tensor([0], device=raw.device))
+ # Match UniLabRMAEnv.step, including observation refresh/noise.
+ obs, critic, priv = env.read(raw.get_observations())
+ control = recorder.finish()
+ report = trace.finish(
+ dict(
+ policy="teacher",
+ seed=args.seed,
+ task=args.task,
+ total_transitions=args.steps,
+ diagnostics=diagnostics.report(),
+ control=control,
+ )
+ )
+ source = Path(__file__)
+ report["diagnostic_source_sha256"] = hashlib.sha256(source.read_bytes()).hexdigest()
+ (trace.directory / "diagnostic_summary.json").write_text(
+ json.dumps(report, indent=2), encoding="utf-8"
+ )
+ print(json.dumps(dict(directory=str(trace.directory), **control), indent=2))
+ finally:
+ if trace is not None:
+ trace.close()
+ raw.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/evaluate_rma.py b/scripts/evaluate_rma.py
new file mode 100644
index 000000000..1c6055d24
--- /dev/null
+++ b/scripts/evaluate_rma.py
@@ -0,0 +1,248 @@
+"""Evaluate RMA policies; opt into interactive playback with --render."""
+
+import argparse
+import json
+import math
+from pathlib import Path
+
+import torch
+from train_rma import build_environment
+from unilab_rma import ActorCriticRMA, AdaptationModule, HistoryBuffer, RMAConfig
+from unilab_rma.evaluation_diagnostics import DEFAULT_TASK, RMA_TASKS, EvaluationDiagnostics
+
+
+def main():
+ p = argparse.ArgumentParser()
+ p.add_argument("--checkpoint", type=Path, required=True)
+ p.add_argument("--policy", choices=["teacher", "student"], default="student")
+ p.add_argument("--steps", type=int, default=1000)
+ p.add_argument("--num-envs", type=int, default=8)
+ p.add_argument("--seed", type=int, default=123)
+ p.add_argument("--device", default="cpu")
+ p.add_argument("--task", choices=RMA_TASKS, default=DEFAULT_TASK)
+ p.add_argument(
+ "--command",
+ nargs=3,
+ type=float,
+ metavar=("VX", "VY", "WZ"),
+ help="Fix body-frame vx, vy (m/s), yaw rate (rad/s), including after reset",
+ )
+ p.add_argument(
+ "--diagnostics",
+ action="store_true",
+ help="Report commanded/actual velocity and weighted reward terms",
+ )
+ p.add_argument(
+ "--trace-dir",
+ type=Path,
+ help="Opt in to per-transition CSV and JSON in a unique subdirectory of this parent",
+ )
+ p.add_argument(
+ "--trace-warmup-steps",
+ type=int,
+ default=100,
+ help="Exclude this many initial steps per episode from the additional trace window summary",
+ )
+ p.add_argument(
+ "--backend",
+ choices=["pytorch", "tensorrt"],
+ default="pytorch",
+ help="Inference backend; TensorRT uses a persistent C++ worker",
+ )
+ p.add_argument(
+ "--engine", type=Path, help="TensorRT engine exported from this student checkpoint"
+ )
+ p.add_argument(
+ "--tensorrt-worker",
+ type=Path,
+ default=Path(__file__).resolve().parents[1] / "build/deploy_trt/policy_worker",
+ )
+ p.add_argument(
+ "--render",
+ action="store_true",
+ help="Show interactive playback; omitted by default for fast evaluation",
+ )
+ p.add_argument(
+ "--render-speed",
+ type=float,
+ default=1.0,
+ help="Playback speed with --render: 1.0 is real time, 0.5 is half speed",
+ )
+ args = p.parse_args()
+ if args.steps < 1 or args.num_envs < 1:
+ p.error("steps and num-envs must be positive")
+ if args.trace_warmup_steps < 0:
+ p.error("trace-warmup-steps must be nonnegative")
+ if not math.isfinite(args.render_speed) or args.render_speed <= 0:
+ p.error("render-speed must be finite and positive")
+ if args.command is not None and not all(math.isfinite(x) for x in args.command):
+ p.error("--command requires finite vx, vy, and yaw rate")
+ if args.backend == "tensorrt" and (args.engine is None or args.policy != "student"):
+ p.error("TensorRT requires --policy student and --engine matching the checkpoint")
+ if args.backend != "tensorrt" and args.engine is not None:
+ p.error("--engine requires --backend tensorrt")
+ saved = torch.load(args.checkpoint, map_location=args.device, weights_only=True)
+ if saved.get("format") != "unilab-rma-v1":
+ raise ValueError("Not an RMA checkpoint")
+ if args.policy == "student" and saved.get("phase") != "student":
+ raise ValueError("Student evaluation requires an adaptation-trained checkpoint")
+ torch.manual_seed(args.seed)
+ cfg = RMAConfig(**saved["config"])
+ model = ActorCriticRMA(cfg).to(args.device).eval()
+ adaptation = AdaptationModule(cfg).to(args.device).eval()
+ model.load_state_dict(saved["teacher"])
+ adaptation.load_state_dict(saved["adaptation"])
+ environment_options = {}
+ if args.task != DEFAULT_TASK:
+ environment_options["task"] = args.task
+ if args.command is not None:
+ environment_options["command"] = args.command
+ raw, env = build_environment(args.num_envs, cfg, args.device, args.seed, **environment_options)
+ returns = torch.zeros(args.num_envs, device=args.device)
+ completed, completed_lengths, tracking = [], [], []
+ partial_returns = torch.zeros(args.num_envs, device=args.device)
+ partial_lengths = torch.zeros(args.num_envs, device=args.device)
+ termination_count, step_rewards = 0, []
+ latent_errors, action_errors = [], []
+ steps = range(args.steps)
+ playback = None
+ runtime = None
+ trace = None
+ backend_action_errors, backend_max_abs_error = [], 0.0
+ diagnostics = EvaluationDiagnostics() if args.diagnostics else None
+ try:
+ if args.backend == "tensorrt":
+ from unilab_rma.tensorrt_runtime import TensorRTWorker
+
+ runtime = TensorRTWorker(args.tensorrt_worker, args.engine, cfg)
+ obs, critic, priv = env.reset()
+ if args.trace_dir is not None:
+ from unilab_rma.evaluation_trace import EvaluationTrace
+
+ trace = EvaluationTrace(
+ args.trace_dir,
+ raw,
+ vars(args),
+ args.checkpoint,
+ warmup_steps=args.trace_warmup_steps,
+ )
+ history = HistoryBuffer(args.num_envs, cfg, args.device)
+ history.push(obs)
+ # The default path retains the original range iterator: no renderer,
+ # rendering imports, per-step clocks, or playback sleeps.
+ if args.render:
+ from unilab_rma.rendering import rendered_steps
+
+ playback = rendered_steps(raw, args.steps, speed=args.render_speed)
+ steps = playback
+ with torch.no_grad():
+ for _ in steps:
+ if trace is not None:
+ trace_before = critic
+ if diagnostics is not None:
+ diagnostics.record_state(critic)
+ tracking.append((critic[:, 49:51] - obs[:, 42:44]).square().sum(-1).mean().item())
+ teacher_z = model.encoder(priv)
+ student_z = adaptation(history.data)
+ if args.policy == "student":
+ latent_errors.append((student_z - teacher_z).square().mean().item())
+ z = teacher_z if args.policy == "teacher" else student_z
+ teacher_action = model.actor(obs, teacher_z).tanh()
+ action = model.actor(obs, z).tanh()
+ if runtime is not None:
+ deployed_action = runtime.infer(obs, history.data)
+ difference = deployed_action - action
+ backend_action_errors.append(difference.square().mean().item())
+ backend_max_abs_error = max(
+ backend_max_abs_error, difference.abs().max().item()
+ )
+ action = deployed_action
+ if args.policy == "student":
+ action_errors.append((action - teacher_action).square().mean().item())
+ (obs, critic, priv), reward, term, trunc, terminal = env.step(action)
+ if trace is not None:
+ trace.record(
+ trace_before, action, terminal[1], reward, term, trunc, raw.reward_manager
+ )
+ if diagnostics is not None:
+ diagnostics.record_rewards(raw.reward_manager)
+ returns += reward
+ partial_returns += reward
+ partial_lengths += 1
+ done = term | trunc
+ completed.extend(returns[done].tolist())
+ completed_lengths.extend(partial_lengths[done].tolist())
+ returns[done] = 0
+ partial_returns[done] = 0
+ partial_lengths[done] = 0
+ termination_count += int(term.sum())
+ step_rewards.append(reward.mean().item())
+ history.push(obs, done)
+ report = {
+ "policy": args.policy,
+ "seed": args.seed,
+ "completed_episodes": len(completed),
+ "mean_completed_episode_return": sum(completed) / len(completed) if completed else None,
+ "mean_completed_episode_length_steps": sum(completed_lengths) / len(completed_lengths)
+ if completed_lengths
+ else None,
+ "mean_step_reward": sum(step_rewards) / len(step_rewards) if step_rewards else None,
+ "planar_velocity_rmse_m_per_s": (sum(tracking) / len(tracking)) ** 0.5
+ if tracking
+ else None,
+ "unfinished_episodes": int((partial_lengths > 0).sum()),
+ "mean_unfinished_episode_return": (
+ partial_returns[partial_lengths > 0].mean().item()
+ if (partial_lengths > 0).any()
+ else None
+ ),
+ "student_latent_mse_vs_teacher": (
+ sum(latent_errors) / len(latent_errors) if latent_errors else None
+ ),
+ "student_action_rmse_vs_teacher": (
+ (sum(action_errors) / len(action_errors)) ** 0.5 if action_errors else None
+ ),
+ "terminations": termination_count,
+ "total_transitions": len(step_rewards) * args.num_envs,
+ }
+ if args.command is not None:
+ report["command_override"] = args.command
+ if args.task != DEFAULT_TASK:
+ report["task"] = args.task
+ if diagnostics is not None:
+ report["diagnostics"] = diagnostics.report()
+ if runtime is not None:
+ report.update(
+ {
+ "inference_backend": "tensorrt_cpp",
+ "tensorrt_action_rmse_vs_pytorch": (
+ (sum(backend_action_errors) / len(backend_action_errors)) ** 0.5
+ if backend_action_errors
+ else None
+ ),
+ "tensorrt_action_max_abs_error_vs_pytorch": (
+ backend_max_abs_error if backend_action_errors else None
+ ),
+ }
+ )
+ if trace is not None:
+ report = trace.finish(report)
+ print(json.dumps(report, indent=2))
+ finally:
+ try:
+ if playback is not None:
+ playback.close() # Release the viewer even if policy inference fails.
+ finally:
+ try:
+ if runtime is not None:
+ runtime.close()
+ finally:
+ try:
+ if trace is not None:
+ trace.close()
+ finally:
+ raw.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/export_onnx.py b/scripts/export_onnx.py
new file mode 100644
index 000000000..1d9417e83
--- /dev/null
+++ b/scripts/export_onnx.py
@@ -0,0 +1,101 @@
+"""Export a STUDENT checkpoint, then require ONNX Runtime numerical validation."""
+
+import sys
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+import argparse
+import json
+
+import numpy as np
+import torch
+from unilab_rma import RMAConfig
+from unilab_rma.deployment import DeploymentPolicy, go2_control_layout
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--checkpoint", type=Path, required=True)
+ parser.add_argument("--output", type=Path, required=True)
+ args = parser.parse_args()
+ saved = torch.load(args.checkpoint, map_location="cpu", weights_only=True)
+ if saved.get("format") != "unilab-rma-v1" or saved.get("phase") != "student":
+ raise ValueError("Export requires an adaptation-trained student checkpoint")
+ cfg = RMAConfig(**saved["config"])
+ module = DeploymentPolicy(cfg).eval()
+ actor_state = {
+ k[len("actor.") :]: v for k, v in saved["teacher"].items() if k.startswith("actor.")
+ }
+ module.actor.load_state_dict(actor_state, strict=True)
+ module.adaptation.load_state_dict(saved["adaptation"], strict=True)
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ torch.manual_seed(123)
+ obs = torch.randn(1, cfg.obs_dim)
+ hist = torch.randn(1, cfg.history_length, cfg.obs_dim)
+ hist[:, -1] = obs
+ # Static batch=1; fixed history=50; FP32 IO, FP16 internal TensorRT build later.
+ torch.onnx.export(
+ module,
+ (obs, hist),
+ str(args.output),
+ opset_version=18,
+ input_names=["observation", "history"],
+ output_names=["action"],
+ dynamo=False,
+ )
+ import onnx
+ import onnxruntime as ort
+
+ graph = onnx.load(str(args.output))
+ onnx.checker.check_model(graph)
+ names = [initializer.name for initializer in graph.graph.initializer]
+ if any("critic" in name or "encoder" in name for name in names):
+ raise AssertionError("Privileged teacher leaked into deployment graph")
+ session = ort.InferenceSession(str(args.output), providers=["CPUExecutionProvider"])
+ maximum = 0.0
+ for i in range(12):
+ obs = torch.randn(1, cfg.obs_dim)
+ hist = torch.randn(1, cfg.history_length, cfg.obs_dim)
+ if i % 3 == 0:
+ hist.zero_() # episode-start padding
+ hist[:, -1] = obs
+ with torch.no_grad():
+ reference = module(obs, hist).numpy()
+ result = session.run(None, {"observation": obs.numpy(), "history": hist.numpy()})[0]
+ np.testing.assert_allclose(reference, result, rtol=1e-4, atol=1e-5)
+ maximum = max(maximum, float(np.max(np.abs(reference - result))))
+ metadata = {
+ "format": "unilab-rma-deployment-v1",
+ "obs_dim": cfg.obs_dim,
+ "history_length": cfg.history_length,
+ "history_order": "oldest_to_newest_including_current",
+ "history_reset": "zero_pad_then_append_reset_observation",
+ "action_dim": cfg.action_dim,
+ "latent_dim": cfg.latent_dim,
+ "policy_period_s": 0.02,
+ "action_scale": 0.25,
+ "normalization": "raw UniLab policy observations; no running normalization",
+ "observation_fields": [
+ ["gyro", 3],
+ ["projected_gravity", 3],
+ ["joint_pos_rel", 12],
+ ["joint_vel_rel", 12],
+ ["last_action", 12],
+ ["command", 3],
+ ["gait_phase", 4],
+ ],
+ "joint_order": ["FL", "FR", "RL", "RR"],
+ "action_actuator_order": ["FL", "FR", "RL", "RR"],
+ "action_actuator_order_note": "Legacy alias for action output order, NOT scene storage order",
+ **go2_control_layout(),
+ "per_leg_order": ["hip", "thigh", "calf"],
+ "onnx_max_abs_error": maximum,
+ "default_angles": "must read matching scene home keyframe in actuator order; not supplied by source-only copy",
+ }
+ args.output.with_suffix(".json").write_text(json.dumps(metadata, indent=2), encoding="utf-8")
+ print(f"ONNX verified: {args.output}; max_abs_error={maximum:.8g}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/inspect_rma_task.py b/scripts/inspect_rma_task.py
new file mode 100644
index 000000000..30e5ebd3d
--- /dev/null
+++ b/scripts/inspect_rma_task.py
@@ -0,0 +1,59 @@
+"""Show fully resolved task differences without building an environment."""
+
+import argparse
+import json
+
+from hydra import compose, initialize_config_dir
+from omegaconf import OmegaConf
+from train_rma import ROOT
+from unilab_rma.evaluation_diagnostics import FORWARD_TASK, RMA_TASKS
+
+
+def differences(before, after, prefix=""):
+ if isinstance(before, dict) and isinstance(after, dict):
+ result = []
+ for key in sorted(before.keys() | after.keys()):
+ path = f"{prefix}.{key}" if prefix else key
+ if key not in before or key not in after:
+ result.append(dict(path=path, before=before.get(key), after=after.get(key)))
+ else:
+ result.extend(differences(before[key], after[key], path))
+ return result
+ if before != after:
+ return [dict(path=prefix, before=before, after=after)]
+ return []
+
+
+def resolved(task):
+ with initialize_config_dir(config_dir=str(ROOT / "src/unilab/conf/ppo"), version_base=None):
+ config = compose(config_name="config", overrides=[f"task={task}"])
+ return OmegaConf.to_container(config, resolve=True)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--task", choices=RMA_TASKS, required=True)
+ parser.add_argument("--compare-with", choices=RMA_TASKS, default=FORWARD_TASK)
+ parser.add_argument("--expect-only", help="Fail unless exactly this resolved field changes")
+ args = parser.parse_args()
+ baseline, candidate = resolved(args.compare_with), resolved(args.task)
+ changes = differences(baseline, candidate)
+ print(
+ json.dumps(
+ dict(
+ root=str(ROOT),
+ baseline=args.compare_with,
+ candidate=args.task,
+ baseline_tracking=baseline["reward"]["tracking_lin_vel"],
+ candidate_tracking=candidate["reward"]["tracking_lin_vel"],
+ changes=changes,
+ ),
+ indent=2,
+ )
+ )
+ if args.expect_only and [row["path"] for row in changes] != [args.expect_only]:
+ parser.exit(1, "Single-variable check FAILED; inspect changes above.\n")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/plot_evaluation_trace.py b/scripts/plot_evaluation_trace.py
new file mode 100644
index 000000000..f2b955b9b
--- /dev/null
+++ b/scripts/plot_evaluation_trace.py
@@ -0,0 +1,123 @@
+"""Create quick-look plots from an opt-in RMA evaluation trace."""
+
+import argparse
+import csv
+import gzip
+import json
+from collections import defaultdict
+from pathlib import Path
+
+
+def plot_trace(trace_dir, output_dir=None):
+ import matplotlib
+
+ matplotlib.use("Agg")
+ import matplotlib.pyplot as plt
+
+ trace_dir = Path(trace_dir)
+ output_dir = Path(output_dir) if output_dir else trace_dir / "plots"
+ output_dir.mkdir(parents=True, exist_ok=True)
+ metadata_path = trace_dir / "run_config.json"
+ if not metadata_path.exists():
+ metadata_path = trace_dir / "run_configuration.json"
+ metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
+ csv_path = trace_dir / "transitions.csv"
+ if not csv_path.exists():
+ csv_path = trace_dir / "transitions.csv.gz"
+ opener = gzip.open if csv_path.suffix == ".gz" else open
+ with opener(csv_path, "rt", newline="", encoding="utf-8") as stream:
+ rows = list(csv.DictReader(stream))
+ if not rows:
+ raise ValueError(f"No transitions in {trace_dir / 'transitions.csv'}")
+ steps = sorted({int(row["step"]) for row in rows})
+ velocity_by_step = defaultdict(list)
+ command_by_step = defaultdict(list)
+ action_rows = []
+ reward_columns = [name for name in rows[0] if name.startswith("reward_rate/")]
+ reward_by_step = {name: defaultdict(list) for name in reward_columns}
+ for row in rows:
+ step = int(row["step"])
+ velocity_by_step[step].append(float(row["before_vx_m_s"]))
+ command_by_step[step].append(float(row["command_vx_m_s"]))
+ action_rows.append([float(row[f"action_{i}"]) for i in range(12)])
+ for name in reward_columns:
+ reward_by_step[name][step].append(float(row[name]))
+
+ dt = float(metadata["control_period_s"])
+ elapsed = [step * dt for step in steps]
+ velocity_mean = [sum(velocity_by_step[step]) / len(velocity_by_step[step]) for step in steps]
+ velocity_std = [
+ (sum((value - mean) ** 2 for value in velocity_by_step[step]) / len(velocity_by_step[step]))
+ ** 0.5
+ for step, mean in zip(steps, velocity_mean, strict=True)
+ ]
+ commands = [sum(command_by_step[step]) / len(command_by_step[step]) for step in steps]
+ fig, axis = plt.subplots(figsize=(10, 4), constrained_layout=True)
+ axis.plot(elapsed, commands, "--", color="#C53434", label="Command")
+ axis.plot(elapsed, velocity_mean, color="#1D4C79", label="Mean measured vx")
+ axis.fill_between(
+ elapsed,
+ [mean - std for mean, std in zip(velocity_mean, velocity_std, strict=True)],
+ [mean + std for mean, std in zip(velocity_mean, velocity_std, strict=True)],
+ color="#4679A8",
+ alpha=0.2,
+ label="Across-env standard deviation",
+ )
+ axis.set(
+ xlabel="Time since evaluation start (s)",
+ ylabel="Body-frame vx (m/s)",
+ title="Command tracking; each point averages active environments, resets included",
+ )
+ axis.grid(alpha=0.2)
+ axis.legend()
+ fig.savefig(output_dir / "velocity_tracking.png", dpi=160)
+ plt.close(fig)
+
+ joint_names = metadata["control_contract"]["action_target_joint_order"]
+ fig, axis = plt.subplots(figsize=(12, 4), constrained_layout=True)
+ axis.boxplot(
+ [[row[index] for row in action_rows] for index in range(12)],
+ showfliers=False,
+ )
+ axis.set_xticks(range(1, 13), joint_names)
+ axis.axhline(0.95, color="#C53434", linestyle="--", linewidth=1)
+ axis.axhline(-0.95, color="#C53434", linestyle="--", linewidth=1)
+ axis.set(
+ xlabel="Resolved joint target order",
+ ylabel="Normalized policy action",
+ title="Action distribution; dashed lines flag the |action| ≥ 0.95 indicator",
+ )
+ axis.tick_params(axis="x", rotation=35)
+ axis.grid(axis="y", alpha=0.2)
+ fig.savefig(output_dir / "action_distribution.png", dpi=160)
+ plt.close(fig)
+
+ if reward_columns:
+ fig, axis = plt.subplots(figsize=(11, 5), constrained_layout=True)
+ for name in reward_columns:
+ values = [
+ sum(reward_by_step[name][step]) / len(reward_by_step[name][step]) for step in steps
+ ]
+ axis.plot(elapsed, values, label=name.removeprefix("reward_rate/"))
+ axis.set(
+ xlabel="Time since evaluation start (s)",
+ ylabel="Weighted reward rate before control-dt scaling",
+ title="Reward components averaged across active environments",
+ )
+ axis.grid(alpha=0.2)
+ axis.legend(fontsize=8, ncol=2)
+ fig.savefig(output_dir / "reward_components.png", dpi=160)
+ plt.close(fig)
+ return sorted(str(path) for path in output_dir.glob("*.png"))
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("trace_dir", type=Path)
+ parser.add_argument("--output", type=Path)
+ args = parser.parse_args()
+ print(json.dumps(plot_trace(args.trace_dir, args.output), indent=2))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/report_rma.py b/scripts/report_rma.py
new file mode 100644
index 000000000..1a1f6e950
--- /dev/null
+++ b/scripts/report_rma.py
@@ -0,0 +1,22 @@
+"""Rebuild the checked-in RMA result tables and figures."""
+
+import argparse
+import json
+import sys
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+
+from unilab_rma.experiment_report import build_report
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--results", type=Path, default=ROOT / "results/rma")
+ args = parser.parse_args()
+ print(json.dumps(build_report(args.results), indent=2))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/train_rma.py b/scripts/train_rma.py
new file mode 100644
index 000000000..8514d153e
--- /dev/null
+++ b/scripts/train_rma.py
@@ -0,0 +1,106 @@
+"""Run from project root; requires the original UniLab runtime and robot assets."""
+
+import sys
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+sys.path.insert(0, str(ROOT / "src"))
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+import argparse
+
+import torch
+from unilab_rma import ActorCriticRMA, AdaptationModule, RMAConfig
+from unilab_rma.env_adapter import UniLabRMAEnv
+from unilab_rma.evaluation_diagnostics import DEFAULT_TASK, RMA_TASKS, command_overrides
+from unilab_rma.runner import train_student, train_teacher
+
+
+def build_environment(num_envs, cfg, device, seed=42, *, task=DEFAULT_TASK, command=None):
+ from hydra import compose, initialize_config_dir
+ from unilab_rma.scene_contract import prepare_scene
+
+ from unilab.base.config_adapter import BackendAdapter, create_env
+ from unilab.base.registry import ensure_registries
+
+ if task not in RMA_TASKS:
+ raise ValueError(f"Unsupported RMA task: {task}")
+ overrides = [f"task={task}"]
+ if command is not None:
+ overrides.extend(command_overrides(command))
+ with initialize_config_dir(config_dir=str(ROOT / "src/unilab/conf/ppo"), version_base=None):
+ composed = compose(config_name="config", overrides=overrides)
+ ensure_registries()
+ adapter = BackendAdapter(composed, root_dir=ROOT, algo_name="ppo")
+ override = adapter.build_task_env_cfg_override()
+ prepare_scene(override, ROOT)
+ override["auto_reset"] = False
+ override["seed"] = seed
+ raw = create_env(composed, num_envs=num_envs, env_cfg_override=override)
+ try:
+ return raw, UniLabRMAEnv(raw, cfg, device)
+ except Exception:
+ raw.close()
+ raise
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--phase", choices=["teacher", "student"], required=True)
+ parser.add_argument("--checkpoint", type=Path)
+ parser.add_argument("--output", type=Path, required=True)
+ parser.add_argument("--iterations", type=int, default=1000)
+ parser.add_argument("--num-envs", type=int, default=64)
+ parser.add_argument("--device", default="cpu")
+ parser.add_argument(
+ "--task",
+ choices=RMA_TASKS,
+ default=DEFAULT_TASK,
+ help="Original RMA task or an isolated forward-walking experiment",
+ )
+ parser.add_argument(
+ "--log-dir",
+ type=Path,
+ help="Parent for unique CSV/TensorBoard runs; default: _logs",
+ )
+ args = parser.parse_args()
+ if args.iterations < 1 or args.num_envs < 1:
+ parser.error("iterations and num-envs must be positive")
+ if args.phase == "student" and args.checkpoint is None:
+ parser.error("Student training requires a trained teacher checkpoint")
+ if args.output.exists():
+ parser.error(f"Output already exists: {args.output}. Choose a new --output to keep it.")
+ torch.manual_seed(42)
+ cfg = RMAConfig()
+ model, adaptation = ActorCriticRMA(cfg).to(args.device), AdaptationModule(cfg).to(args.device)
+ if args.checkpoint:
+ saved = torch.load(args.checkpoint, map_location=args.device, weights_only=True)
+ if saved.get("format") != "unilab-rma-v1":
+ raise ValueError("Not an RMA checkpoint")
+ if saved["config"] != model.metadata():
+ raise ValueError("Checkpoint dimension/config mismatch")
+ model.load_state_dict(saved["teacher"], strict=True)
+ adaptation.load_state_dict(saved["adaptation"], strict=True)
+ raw, env = build_environment(args.num_envs, cfg, args.device, task=args.task)
+ try:
+ fn = train_teacher if args.phase == "teacher" else train_student
+ from unilab_rma.training_log import TrainingLog
+
+ metadata = dict(
+ arguments=vars(args),
+ model_config=model.metadata(),
+ horizon=24,
+ seed=42,
+ torch_version=torch.__version__,
+ requested_policy_device=args.device,
+ environment_device=str(raw.device),
+ sim_backend="mujoco",
+ )
+ with TrainingLog(args.output, args.phase, metadata, args.log_dir) as logger:
+ print(f"Training logs: {logger.directory}", flush=True)
+ fn(env, model, adaptation, args.iterations, args.output, logger=logger)
+ finally:
+ raw.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/unilab/conf/ppo/task/go2_joystick_flat/rma.yaml b/src/unilab/conf/ppo/task/go2_joystick_flat/rma.yaml
new file mode 100644
index 000000000..24bc7c893
--- /dev/null
+++ b/src/unilab/conf/ppo/task/go2_joystick_flat/rma.yaml
@@ -0,0 +1,60 @@
+# @package _global_
+defaults:
+ - /task/go2_joystick_flat/mujoco
+ - _self_
+
+# Existing non-RMA configs remain unchanged. train_rma.py composes this overlay.
+env:
+ policy_observation_group: policy
+ critic_observation_group: critic
+ scene:
+ entities:
+ robot:
+ body_names: [FL_calf, base]
+ # train_rma.py fills exact named robot geoms from the restored XML assets.
+ geom_names: []
+ observations:
+ privileged:
+ terms:
+ parameters:
+ func: unilab.envs.mdp.rma.privileged_parameters
+ events:
+ randomize_leg_mass: null
+ rma_base_load:
+ func: unilab.envs.mdp.rma.RMABaseMass
+ mode: reset
+ params:
+ asset_cfg:
+ _target_: unilab.managers.SceneEntityCfg
+ name: robot
+ body_names: [base]
+ operation: add
+ distribution: uniform
+ mass_distribution_params: [0.0, 5.0]
+ recompute_inertia: false
+ rma_friction:
+ func: unilab.envs.mdp.rma.RMAFriction
+ mode: reset
+ params:
+ asset_cfg:
+ _target_: unilab.managers.SceneEntityCfg
+ name: robot
+ geom_names: ['.*']
+ ranges: [0.4, 1.25]
+ axes: [0]
+ shared_random: true
+ operation: abs
+ auto_reset: false
+
+algo:
+ obs_groups:
+ actor: [policy]
+ critic: [critic]
+
+rma:
+ obs_dim: 49
+ critic_dim: 52
+ privileged_dim: 2
+ history_length: 50
+ latent_dim: 8
+ action_dim: 12
diff --git a/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward.yaml b/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward.yaml
new file mode 100644
index 000000000..26f3e85d4
--- /dev/null
+++ b/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward.yaml
@@ -0,0 +1,20 @@
+# @package _global_
+# Experimental forward-walking curriculum. Original rma task is unchanged.
+# Same policy I/O, dynamics, action scale and randomization as the RMA baseline.
+defaults:
+ - /task/go2_joystick_flat/rma
+ - _self_
+
+env:
+ commands:
+ twist:
+ ranges:
+ lin_vel_x: [0.3, 0.6]
+ lin_vel_y: [0.0, 0.0]
+ ang_vel_z: [0.0, 0.0]
+
+reward:
+ tracking_lin_vel:
+ weight: 2.0
+ swing_feet_z:
+ weight: 0.25
diff --git a/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_no_pose.yaml b/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_no_pose.yaml
new file mode 100644
index 000000000..4072efc5d
--- /dev/null
+++ b/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_no_pose.yaml
@@ -0,0 +1,9 @@
+# @package _global_
+# EXP-003: disable only the default-pose deviation penalty.
+defaults:
+ - /task/go2_joystick_flat/rma_forward
+ - _self_
+
+reward:
+ similar_to_default:
+ weight: 0.0
diff --git a/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_tight_tracking.yaml b/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_tight_tracking.yaml
new file mode 100644
index 000000000..753025011
--- /dev/null
+++ b/src/unilab/conf/ppo/task/go2_joystick_flat/rma_forward_tight_tracking.yaml
@@ -0,0 +1,12 @@
+# @package _global_
+# Native 1.3.4 profile: denominator is tracking_sigma, NOT std squared.
+# Effective width 0.35 m/s corresponds to 0.35**2 = 0.1225.
+# The 1.3.3 experiment profile is in experiments/rma/runtime_1_3_3/.
+defaults:
+ - /task/go2_joystick_flat/rma_forward
+ - _self_
+
+reward:
+ tracking_lin_vel:
+ params:
+ tracking_sigma: 0.1225
diff --git a/src/unilab/envs/mdp/rma.py b/src/unilab/envs/mdp/rma.py
new file mode 100644
index 000000000..bd225bf19
--- /dev/null
+++ b/src/unilab/envs/mdp/rma.py
@@ -0,0 +1,54 @@
+"""RMA reset labels recorded from the SAME samples written to simulation.
+
+Only manager reset-transaction backends are supported; no guessed fallback labels.
+Friction is the selected robot geoms' sliding coefficient, not an effective
+robot/terrain contact coefficient (contact mixing remains backend-specific).
+"""
+
+import numpy as np
+import torch
+
+from unilab.envs.mdp.events import GeomFriction, RandomizeRigidBodyMass, resolve_env_ids
+
+
+def _labels(env):
+ if not hasattr(env, "_rma_privileged"):
+ # Initialization defaults only, overwritten by the reset events.
+ env._rma_privileged = np.tile(np.array([1.0, 0.0]), (env.num_envs, 1))
+ env._rma_label_valid = np.zeros((env.num_envs, 2), dtype=bool)
+ return env._rma_privileged
+
+
+def privileged_parameters(env):
+ return torch.as_tensor(_labels(env), device=env.device, dtype=torch.float32)
+
+
+class RMAFriction(GeomFriction):
+ def _write(self, values, env_ids):
+ coefficients = values[..., 0]
+ if not np.allclose(coefficients, coefficients[:, :1]):
+ raise ValueError(
+ "RMA scalar friction requires shared_random=true across selected geoms"
+ )
+ super()._write(values, env_ids)
+ _labels(self._env)[env_ids, 0] = coefficients[:, 0]
+ self._env._rma_label_valid[env_ids, 0] = True
+
+
+class RMABaseMass(RandomizeRigidBodyMass):
+ def __call__(self, env, env_ids, **kwargs):
+ if self._operation != "add" or self._distribution != "uniform" or len(self._body_ids) != 1:
+ raise ValueError("RMA load requires one base body, uniform additive mass")
+ ids = resolve_env_ids(env, env_ids)
+ samples = env.rng.uniform(*self._distribution_params, size=(ids.size, 1))
+ defaults = self._default_mass
+ if defaults.ndim == 2:
+ defaults = defaults[ids]
+ values = defaults + samples
+ if np.any(values < self._min_mass):
+ raise ValueError("Invalid randomized base mass")
+ self._entity.write_body_mass_to_sim(
+ values, body_ids=self._body_ids, env_ids=ids, term_name="randomize_rigid_body_mass"
+ )
+ _labels(env)[ids, 1] = samples[:, 0]
+ env._rma_label_valid[ids, 1] = True
diff --git a/tests/rma/test_ablation_config.py b/tests/rma/test_ablation_config.py
new file mode 100644
index 000000000..419225c9c
--- /dev/null
+++ b/tests/rma/test_ablation_config.py
@@ -0,0 +1,98 @@
+"""Protect the single-variable experiment and existing checkpoints."""
+
+import contextlib
+import io
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from unittest.mock import patch
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "scripts"))
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+import train_rma
+from inspect_rma_task import differences, resolved
+from unilab_rma.evaluation_diagnostics import (
+ FORWARD_TASK,
+ NO_POSE_TASK,
+ RMA_TASKS,
+ TIGHT_TRACKING_TASK,
+)
+
+
+class AblationConfigTests(unittest.TestCase):
+ def test_legacy_133_overlay_changes_only_std(self):
+ import yaml
+
+ path = ROOT / "experiments/rma/runtime_1_3_3/rma_forward_tight_tracking.yaml"
+ overlay = yaml.safe_load(path.read_text(encoding="utf-8"))
+ self.assertEqual(overlay["defaults"], ["/task/go2_joystick_flat/rma_forward", "_self_"])
+ self.assertEqual(overlay["reward"]["tracking_lin_vel"], {"params": {"std": 0.35}})
+
+ def test_native_tight_tracking_changes_only_denominator(self):
+ baseline, experiment = resolved(FORWARD_TASK), resolved(TIGHT_TRACKING_TASK)
+ self.assertIn(TIGHT_TRACKING_TASK, RMA_TASKS)
+ self.assertEqual(
+ differences(baseline, experiment),
+ [dict(path="reward.tracking_lin_vel.params.tracking_sigma", before=0.5, after=0.1225)],
+ )
+ self.assertNotIn("std", experiment["reward"]["tracking_lin_vel"]["params"])
+ self.assertEqual(experiment["reward"]["similar_to_default"]["weight"], -0.1)
+
+ def test_inspector_catches_extra_changes_and_is_read_only(self):
+ before = {"reward": {"width": 0.5, "weight": 2}, "other": [1, 2]}
+ after = {"reward": {"width": 0.35, "weight": 3}, "other": [1, 2]}
+ changes = differences(before, after)
+ self.assertEqual([row["path"] for row in changes], ["reward.weight", "reward.width"])
+ self.assertEqual(before["reward"], {"width": 0.5, "weight": 2})
+
+ def test_composed_experiment_changes_exactly_one_weight(self):
+ from hydra import compose, initialize_config_dir
+ from omegaconf import OmegaConf
+
+ configs = []
+ for task in (FORWARD_TASK, NO_POSE_TASK):
+ with initialize_config_dir(
+ config_dir=str(ROOT / "src/unilab/conf/ppo"), version_base=None
+ ):
+ config = compose(config_name="config", overrides=[f"task={task}"])
+ configs.append(OmegaConf.to_container(config, resolve=True))
+ baseline, experiment = configs
+ self.assertIn(NO_POSE_TASK, RMA_TASKS)
+ self.assertEqual(baseline["reward"]["similar_to_default"]["weight"], -0.1)
+ self.assertEqual(experiment["reward"]["similar_to_default"]["weight"], 0.0)
+ experiment["reward"]["similar_to_default"]["weight"] = -0.1
+ self.assertEqual(experiment, baseline)
+
+ def test_existing_output_is_rejected_before_model_or_environment_creation(self):
+ with tempfile.TemporaryDirectory() as directory:
+ output = Path(directory) / "existing.pt"
+ output.write_bytes(b"existing checkpoint must be preserved")
+ argv = [
+ "train_rma.py",
+ "--phase",
+ "teacher",
+ "--task",
+ NO_POSE_TASK,
+ "--output",
+ str(output),
+ ]
+ stderr = io.StringIO()
+ with (
+ patch.object(sys, "argv", argv),
+ patch.object(train_rma, "ActorCriticRMA") as model,
+ patch.object(train_rma, "build_environment") as build,
+ contextlib.redirect_stderr(stderr),
+ self.assertRaises(SystemExit) as error,
+ ):
+ train_rma.main()
+ self.assertEqual(error.exception.code, 2)
+ self.assertIn("Output already exists", stderr.getvalue())
+ self.assertEqual(output.read_bytes(), b"existing checkpoint must be preserved")
+ model.assert_not_called()
+ build.assert_not_called()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/rma/test_control_diagnostics.py b/tests/rma/test_control_diagnostics.py
new file mode 100644
index 000000000..c8e76db03
--- /dev/null
+++ b/tests/rma/test_control_diagnostics.py
@@ -0,0 +1,97 @@
+"""Position-control telemetry must resolve storage order and reset boundaries."""
+
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from types import SimpleNamespace
+
+import numpy as np
+import torch
+
+sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "rsl_rl"))
+from unilab_rma.control_diagnostics import ControlDiagnostics
+
+
+def fixture():
+ names = [
+ f"{leg}_{joint}_joint"
+ for leg in ("FL", "FR", "RL", "RR")
+ for joint in ("hip", "thigh", "calf")
+ ]
+ permutation = np.array([3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8])
+ target = torch.arange(12, dtype=torch.float32).reshape(1, 12) / 10
+ bias = np.full((1, 12), 0.02)
+ buffer = np.zeros((1, 12))
+ buffer[:, permutation] = target.numpy() - bias
+ actuators = [f"motor_{i}" for i in range(12)]
+ data = SimpleNamespace(
+ joint_pos=np.zeros((1, 12)),
+ joint_vel=np.ones((1, 12)),
+ encoder_bias=bias,
+ control_buffer=buffer,
+ )
+ term = SimpleNamespace(
+ cfg=SimpleNamespace(entity_name="robot"), target_names=names, processed_action=target
+ )
+ robot = SimpleNamespace(joint_names=names, actuator_names=actuators, data=data)
+ backend = SimpleNamespace(
+ get_actuator_names=lambda: actuators,
+ get_actuator_joint_names=lambda: [names[i] for i in permutation],
+ get_actuator_gains=lambda: (np.full(12, 35), np.full(12, 0.5)),
+ )
+ raw = SimpleNamespace(
+ num_envs=1,
+ step_dt=0.02,
+ scene={"robot": robot},
+ action_manager=SimpleNamespace(get_term=lambda _: term),
+ backend=backend,
+ )
+ return raw, target, permutation
+
+
+class ControlDiagnosticsTests(unittest.TestCase):
+ def test_permuted_targets_bias_and_before_snapshot(self):
+ raw, action, _ = fixture()
+ with tempfile.TemporaryDirectory() as directory:
+ recorder = ControlDiagnostics(raw, directory)
+ before = recorder.before()
+ raw.scene["robot"].data.joint_pos[:] = 0.2
+ recorder.record(before, action, False, False)
+ np.testing.assert_array_equal(before[0], np.zeros(12))
+ self.assertLess(max(abs(row["mapping_residual_rad"]) for row in recorder.rows), 1e-7)
+ self.assertAlmostEqual(recorder.rows[0]["pd_demand_estimate_nm"], -1.2)
+ self.assertAlmostEqual(recorder.rows[0]["q_after_rad"], 0.2)
+ torch.testing.assert_close(
+ raw.action_manager.get_term("joint_pos").processed_action, action
+ )
+
+ def test_direct_copy_bug_is_detected(self):
+ raw, action, _ = fixture()
+ raw.scene["robot"].data.control_buffer[:] = action.numpy() - 0.02
+ with tempfile.TemporaryDirectory() as directory:
+ recorder = ControlDiagnostics(raw, directory)
+ recorder.record(recorder.before(), action, False, False)
+ self.assertGreater(max(abs(row["mapping_residual_rad"]) for row in recorder.rows), 0.2)
+
+ def test_reset_boundary_has_new_episode_and_copied_terminal_state(self):
+ raw, action, _ = fixture()
+ with tempfile.TemporaryDirectory() as directory:
+ recorder = ControlDiagnostics(raw, directory)
+ recorder.record(recorder.before(), action, True, False)
+ raw.scene["robot"].data.joint_pos[:] = 9
+ recorder.record(recorder.before(), action, False, False)
+ self.assertEqual(recorder.rows[0]["q_after_rad"], 0)
+ self.assertEqual(recorder.rows[12]["episode"], 1)
+ self.assertEqual(recorder.rows[12]["episode_step"], 1)
+ self.assertEqual(recorder.rows[12]["q_before_rad"], 9)
+
+ def test_multiple_worlds_rejected(self):
+ raw, _, _ = fixture()
+ raw.num_envs = 2
+ with tempfile.TemporaryDirectory() as directory, self.assertRaises(ValueError):
+ ControlDiagnostics(raw, directory)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/rma/test_core.py b/tests/rma/test_core.py
new file mode 100644
index 000000000..f869cf864
--- /dev/null
+++ b/tests/rma/test_core.py
@@ -0,0 +1,207 @@
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from types import SimpleNamespace
+
+import numpy as np
+import torch
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+from unilab_rma import ActorCriticRMA, AdaptationModule, AdaptationTrainer, HistoryBuffer, RMAConfig
+from unilab_rma.deployment import DeploymentPolicy, go2_control_layout
+from unilab_rma.env_adapter import UniLabRMAEnv
+from unilab_rma.ppo import gae
+from unilab_rma.runner import train_student, train_teacher
+from unilab_rma.scene_contract import expanded_xml, prepare_scene
+
+torch.set_num_threads(1)
+
+
+class SyntheticEnv:
+ """Synthetic tensors ONLY, not a Go2 simulation or performance benchmark."""
+
+ num_envs = 2
+
+ def reset(self):
+ self.t = 0
+ return self.obs()
+
+ def obs(self):
+ return (
+ torch.randn(2, 49) * 0.1,
+ torch.randn(2, 52) * 0.1,
+ torch.tensor([[0.5, 1.0], [1.0, 2.0]]),
+ )
+
+ def step(self, action):
+ self.t += 1
+ terminal = self.obs()
+ done = torch.tensor([self.t % 3 == 0, self.t % 4 == 0])
+ return (
+ self.obs(),
+ -action.square().mean(-1),
+ done,
+ torch.zeros(2, dtype=torch.bool),
+ terminal,
+ )
+
+
+class CoreTests(unittest.TestCase):
+ def setUp(self):
+ torch.manual_seed(4)
+ self.cfg = RMAConfig()
+
+ def test_shapes_and_log_probability(self):
+ m = ActorCriticRMA(self.cfg)
+ a, raw, logp = m.sample(torch.zeros(3, 49), torch.ones(3, 2))
+ self.assertEqual(a.shape, (3, 12))
+ self.assertTrue(torch.isfinite(logp).all())
+ self.assertTrue((a.abs() <= 1).all())
+ self.assertTrue(
+ torch.isfinite(
+ m.log_prob(
+ m.distribution(torch.zeros(3, 49), torch.ones(3, 2)),
+ torch.full_like(raw, 100.0),
+ )
+ ).all()
+ )
+
+ def test_history_reset(self):
+ h = HistoryBuffer(2, self.cfg)
+ h.push(torch.ones(2, 49))
+ h.push(torch.full((2, 49), 2.0), torch.tensor([True, False]))
+ self.assertEqual(h.data[0, :-1].abs().sum().item(), 0)
+ self.assertTrue((h.data[1, -2] == 1).all())
+ self.assertTrue((h.data[:, -1] == 2).all())
+
+ def test_timeout_and_termination(self):
+ r = torch.tensor([[1.0, 1.0], [100.0, 100.0]])
+ v = torch.zeros_like(r)
+ nxt = torch.full_like(r, 10.0)
+ term = torch.tensor([[True, False], [False, False]])
+ trunc = torch.tensor([[False, True], [False, False]])
+ a, _ = gae(r, v, nxt, term, trunc)
+ self.assertAlmostEqual(a[0, 0].item(), 1.0)
+ self.assertAlmostEqual(a[0, 1].item(), 10.9, places=5)
+
+ def test_supervision_freezes_teacher(self):
+ teacher, student = ActorCriticRMA(self.cfg), AdaptationModule(self.cfg)
+ saved = {k: v.clone() for k, v in teacher.state_dict().items()}
+ trainer = AdaptationTrainer(teacher, student, capacity=8)
+ history = torch.randn(2, 50, 49)
+ trainer.add(history, torch.ones(2, 2))
+ with torch.no_grad():
+ initial = (student(history) - teacher.encoder(torch.ones(2, 2))).square().mean().item()
+ for _ in range(50):
+ trainer.update(batch_size=2, updates=2)
+ with torch.no_grad():
+ final = (student(history) - teacher.encoder(torch.ones(2, 2))).square().mean().item()
+ self.assertLess(final, initial)
+ for key, value in teacher.state_dict().items():
+ self.assertTrue(torch.equal(value, saved[key]))
+ self.assertTrue(all(p.grad is None for p in teacher.parameters()))
+
+ def test_rollout_update_and_checkpoint(self):
+ teacher, student = ActorCriticRMA(self.cfg), AdaptationModule(self.cfg)
+ before = teacher.actor.net[0].weight.detach().clone()
+ with tempfile.TemporaryDirectory() as d:
+ p = Path(d) / "teacher.pt"
+ train_teacher(SyntheticEnv(), teacher, student, 1, p, horizon=4)
+ self.assertFalse(torch.equal(before, teacher.actor.net[0].weight))
+ train_student(SyntheticEnv(), teacher, student, 1, Path(d) / "student.pt", horizon=4)
+ saved = torch.load(Path(d) / "student.pt", weights_only=True)
+ self.assertEqual(saved["phase"], "student")
+ deploy = DeploymentPolicy(self.cfg)
+ deploy.actor.load_state_dict(teacher.actor.state_dict())
+ deploy.adaptation.load_state_dict(student.state_dict())
+ obs, h = torch.randn(2, 49), torch.randn(2, 50, 49)
+ torch.testing.assert_close(deploy(obs, h), teacher.actor(obs, student(h)).tanh())
+ self.assertFalse(any("encoder" in k or "critic" in k for k in deploy.state_dict()))
+
+ def test_scene_names_from_xml_includes(self):
+ with tempfile.TemporaryDirectory() as d:
+ p = Path(d)
+ (p / "robot.xml").write_text(
+ ''
+ )
+ (p / "scene.xml").write_text(
+ ''
+ )
+ override = {"scene": {"model_file": "scene.xml", "entities": {"robot": {}}}}
+ prepare_scene(override, p)
+ self.assertEqual(override["scene"]["entities"]["robot"]["geom_names"], ["foot"])
+
+ def test_export_control_layout_matches_current_task_names(self):
+ from hydra import compose, initialize_config_dir
+
+ with initialize_config_dir(config_dir=str(ROOT / "src/unilab/conf/ppo"), version_base=None):
+ config = compose(config_name="config", overrides=["task=go2_joystick_flat/rma"])
+ robot = config.env.scene.entities.robot
+ layout = go2_control_layout()
+ joint_names = list(robot.joint_names)
+ actuators = list(robot.actuator_names)
+ self.assertEqual(
+ layout["action_to_actuator_indices"],
+ [actuators.index(name.removesuffix("_joint")) for name in joint_names],
+ )
+ self.assertEqual(layout["action_joint_order"], ["FL", "FR", "RL", "RR"])
+ self.assertEqual(layout["scene_actuator_order"], ["FR", "FL", "RR", "RL"])
+
+ def test_adapter_preserves_pre_reset_state(self):
+ class Raw:
+ _autoreset = False
+ num_envs = 2
+ device = "cpu"
+ _rma_label_valid = np.ones((2, 2), dtype=bool)
+
+ def __init__(self):
+ self.data = {
+ k: torch.zeros(2, n)
+ for k, n in [("policy", 49), ("critic", 52), ("privileged", 2)]
+ }
+
+ def step(self, action):
+ for x in self.data.values():
+ x.fill_(7.0)
+ return SimpleNamespace(
+ obs=self.data,
+ reward=torch.ones(2),
+ terminated=torch.tensor([False, False]),
+ truncated=torch.tensor([True, False]),
+ )
+
+ def reset(self, ids):
+ for x in self.data.values():
+ x[ids] = 0
+ return self.data, {}
+
+ def get_observations(self):
+ return self.data
+
+ env = UniLabRMAEnv(Raw(), self.cfg)
+ current, _, term, trunc, terminal = env.step(torch.zeros(2, 12))
+ self.assertEqual(terminal[0][0, 0].item(), 7.0)
+ self.assertEqual(current[0][0, 0].item(), 0.0)
+ self.assertEqual(current[0][1, 0].item(), 7.0)
+
+ def test_adapter_public_mapping_and_label_snapshot(self):
+ raw = SimpleNamespace(
+ _autoreset=False,
+ num_envs=2,
+ _rma_label_valid=np.ones((2, 2), dtype=bool),
+ _rma_privileged=np.array([[0.5, 1.0], [1.0, 2.0]]),
+ )
+ env = UniLabRMAEnv(raw, self.cfg)
+ obs, critic, priv = env.read({"obs": torch.zeros(2, 49), "critic": torch.ones(2, 52)})
+ self.assertEqual(obs.shape, (2, 49))
+ self.assertEqual(critic.shape, (2, 52))
+ raw._rma_privileged[0] = 0
+ self.assertEqual(priv[0, 1].item(), 1.0)
+ with self.assertRaisesRegex(KeyError, "critic_observation_group"):
+ env.read({"obs": torch.zeros(2, 49)})
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/tests/rma/test_evaluation_diagnostics.py b/tests/rma/test_evaluation_diagnostics.py
new file mode 100644
index 000000000..1031ddff3
--- /dev/null
+++ b/tests/rma/test_evaluation_diagnostics.py
@@ -0,0 +1,94 @@
+"""Command/reset contract and diagnostic arithmetic, independent of assets."""
+
+import sys
+import unittest
+from pathlib import Path
+from types import SimpleNamespace
+
+import torch
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+from unilab_rma.evaluation_diagnostics import (
+ DEFAULT_TASK,
+ FORWARD_TASK,
+ EvaluationDiagnostics,
+ command_overrides,
+)
+
+
+class EvaluationDiagnosticTests(unittest.TestCase):
+ def test_fixed_command_is_a_config_override_not_a_one_time_tensor_patch(self):
+ overrides = command_overrides((0.5, 0, 0))
+ self.assertIn("env.commands.twist.ranges.lin_vel_x=[0.5,0.5]", overrides)
+ self.assertIn("env.commands.twist.ranges.ang_vel_z=[0.0,0.0]", overrides)
+ self.assertIn("env.commands.twist.rel_standing_envs=0.0", overrides)
+ with self.assertRaises(ValueError):
+ command_overrides((float("nan"), 0, 0))
+ with self.assertRaises(ValueError):
+ command_overrides((0, 0))
+
+ def test_clean_body_velocity_and_reward_units(self):
+ diagnostics = EvaluationDiagnostics()
+ critic = torch.zeros(2, 52)
+ critic[:, 42] = 0.5
+ critic[:, 49] = 0.1
+ critic[:, 2] = 0.2
+ original = critic.clone()
+ diagnostics.record_state(critic)
+ manager = SimpleNamespace(
+ step_reward_names=("tracking_lin_vel", "base_height"),
+ step_reward_means=torch.tensor([0.4, -0.1]),
+ )
+ diagnostics.record_rewards(manager)
+ manager.step_reward_means = torch.tensor([0.6, -0.3])
+ diagnostics.record_rewards(manager)
+ report = diagnostics.report()
+ self.assertEqual(report["mean_command"], [0.5, 0, 0])
+ self.assertAlmostEqual(report["mean_measured_velocity"][0], 0.1, places=6)
+ self.assertAlmostEqual(report["mean_measured_velocity"][2], 0.2, places=6)
+ self.assertAlmostEqual(report["tracking_rmse_by_axis"][0], 0.4, places=6)
+ self.assertAlmostEqual(report["tracking_rmse_by_axis"][2], 0.2, places=6)
+ terms = report["weighted_reward_terms_before_dt"]
+ self.assertAlmostEqual(terms["tracking_lin_vel"], 0.5, places=6)
+ self.assertAlmostEqual(terms["base_height"], -0.2, places=6)
+ self.assertTrue(torch.equal(critic, original))
+
+ def test_empty_report_and_invalid_contract(self):
+ diagnostics = EvaluationDiagnostics()
+ self.assertIsNone(diagnostics.report()["mean_command"])
+ with self.assertRaises(ValueError):
+ diagnostics.record_state(torch.zeros(1, 49))
+
+ def test_forward_task_keeps_policy_contract_and_changes_only_experiment_drivers(self):
+ from hydra import compose, initialize_config_dir
+ from omegaconf import OmegaConf
+
+ configs = []
+ for task in (DEFAULT_TASK, FORWARD_TASK):
+ with initialize_config_dir(
+ config_dir=str(ROOT / "src/unilab/conf/ppo"), version_base=None
+ ):
+ configs.append(compose(config_name="config", overrides=[f"task={task}"]))
+ original, forward = configs
+ self.assertEqual(
+ OmegaConf.to_container(original.env.observations),
+ OmegaConf.to_container(forward.env.observations),
+ )
+ self.assertEqual(
+ OmegaConf.to_container(original.env.actions),
+ OmegaConf.to_container(forward.env.actions),
+ )
+ self.assertEqual(
+ OmegaConf.to_container(original.env.events), OmegaConf.to_container(forward.env.events)
+ )
+ self.assertEqual(list(forward.env.commands.twist.ranges.lin_vel_x), [0.3, 0.6])
+ self.assertEqual(list(forward.env.commands.twist.ranges.ang_vel_z), [0.0, 0.0])
+ self.assertEqual(original.reward.tracking_lin_vel.weight, 1.0)
+ self.assertEqual(forward.reward.tracking_lin_vel.weight, 2.0)
+ self.assertEqual(original.reward.swing_feet_z.weight, 4.0)
+ self.assertEqual(forward.reward.swing_feet_z.weight, 0.25)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/rma/test_evaluation_trace.py b/tests/rma/test_evaluation_trace.py
new file mode 100644
index 000000000..b9061caa1
--- /dev/null
+++ b/tests/rma/test_evaluation_trace.py
@@ -0,0 +1,117 @@
+"""Trace alignment, reset boundaries and disabled-path behavior."""
+
+import csv
+import json
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from types import SimpleNamespace
+
+import torch
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+from unilab_rma.evaluation_trace import EvaluationTrace
+
+
+def trace_raw(num_envs=2):
+ joint_names = [
+ f"{leg}_{joint}_joint"
+ for leg in ("FL", "FR", "RL", "RR")
+ for joint in ("hip", "thigh", "calf")
+ ]
+ ids = [3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8]
+ action = SimpleNamespace(
+ cfg=SimpleNamespace(entity_name="robot", clip=None),
+ target_names=[joint_names[i] for i in ids],
+ target_ids=ids,
+ scale=0.25,
+ offset=torch.zeros(num_envs, 12),
+ )
+ rewards = SimpleNamespace(
+ step_reward_names=("tracking_lin_vel", "penalty"),
+ get_active_iterable_terms=lambda i: [
+ ("tracking_lin_vel", [float(i + 1)]),
+ ("penalty", [-0.2]),
+ ],
+ )
+ return SimpleNamespace(
+ step_dt=0.02,
+ reward_manager=rewards,
+ action_manager=SimpleNamespace(get_term=lambda name: action),
+ scene={"robot": SimpleNamespace(joint_names=joint_names)},
+ )
+
+
+class EvaluationTraceTests(unittest.TestCase):
+ def test_terminal_state_reset_ids_and_units_are_not_mixed(self):
+ with tempfile.TemporaryDirectory() as directory:
+ checkpoint = Path(directory) / "weights.pt"
+ checkpoint.write_bytes(b"test checkpoint")
+ raw = trace_raw()
+ trace = EvaluationTrace(directory, raw, {"num_envs": 2}, checkpoint, warmup_steps=1)
+ before = torch.zeros(2, 52)
+ before[:, 42] = 0.5
+ before[:, 49] = 0.1
+ after = before.clone()
+ after[:, 49] = 0.25
+ action = torch.zeros(2, 12)
+ action[:, 0] = 0.96
+ original = before.clone(), after.clone(), action.clone()
+ trace.record(
+ before,
+ action,
+ after,
+ torch.tensor([0.016, 0.036]),
+ torch.tensor([True, False]),
+ torch.zeros(2, dtype=torch.bool),
+ raw.reward_manager,
+ )
+ trace.record(
+ before,
+ action,
+ after,
+ torch.tensor([0.016, 0.036]),
+ torch.zeros(2, dtype=torch.bool),
+ torch.zeros(2, dtype=torch.bool),
+ raw.reward_manager,
+ )
+ report = trace.finish({"total_transitions": 4})
+ trace.close()
+ with (trace.directory / "transitions.csv").open() as stream:
+ rows = list(csv.DictReader(stream))
+ metadata = json.loads((trace.directory / "run_config.json").read_text())
+ self.assertEqual(len(rows), 4)
+ self.assertAlmostEqual(float(rows[0]["before_vx_m_s"]), 0.1)
+ self.assertAlmostEqual(float(rows[0]["after_vx_m_s"]), 0.25)
+ self.assertEqual(rows[2]["episode_id"], "1")
+ self.assertEqual(rows[2]["episode_step"], "1")
+ self.assertEqual(rows[3]["episode_id"], "0")
+ self.assertEqual(rows[3]["episode_step"], "2")
+ self.assertAlmostEqual(float(rows[1]["reward_rate/tracking_lin_vel"]), 2)
+ self.assertEqual(report["trace"]["full"]["transitions"], 4)
+ self.assertEqual(report["trace"]["after_startup_window"]["transitions"], 1)
+ self.assertEqual(report["trace"]["normalized_action_near_bound_fraction"][0], 1)
+ self.assertEqual(
+ metadata["control_contract"]["action_target_joint_order"][0], "FR_hip_joint"
+ )
+ self.assertEqual(
+ metadata["control_contract"]["joint_observation_order"][0], "FL_hip_joint"
+ )
+ for left, right in zip(original, (before, after, action), strict=True):
+ self.assertTrue(torch.equal(left, right))
+
+ def test_repeated_invocations_do_not_overwrite_and_empty_window_is_null(self):
+ with tempfile.TemporaryDirectory() as directory:
+ checkpoint = Path(directory) / "weights.pt"
+ checkpoint.write_bytes(b"checkpoint")
+ first = EvaluationTrace(directory, trace_raw(), {"num_envs": 2}, checkpoint)
+ second = EvaluationTrace(directory, trace_raw(), {"num_envs": 2}, checkpoint)
+ try:
+ self.assertNotEqual(first.directory, second.directory)
+ self.assertIsNone(first.report()["after_startup_window"]["tracking_rmse_by_axis"])
+ self.assertIsNone(first.report()["normalized_action_min"])
+ finally:
+ first.close()
+ second.close()
diff --git a/tests/rma/test_experiment_report.py b/tests/rma/test_experiment_report.py
new file mode 100644
index 000000000..7548d8b12
--- /dev/null
+++ b/tests/rma/test_experiment_report.py
@@ -0,0 +1,36 @@
+import json
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+
+from unilab_rma.experiment_report import load_evaluations, rolling_mean
+
+
+class ExperimentReportTests(unittest.TestCase):
+ def test_published_reports_have_same_protocol(self):
+ rows = load_evaluations(ROOT / "results/rma")
+ self.assertEqual(len(rows), 6)
+ self.assertEqual({row["seed"] for row in rows}, {123, 456, 789})
+ self.assertTrue(all(row["total_transitions"] == 8000 for row in rows))
+ self.assertTrue(all(row["vx_rmse_m_s"] > 0.48 for row in rows))
+
+ def test_trailing_mean_retains_startup(self):
+ self.assertEqual(rolling_mean([1.0, 3.0, 5.0], window=2), [1.0, 2.0, 4.0])
+
+ def test_rejects_student_report_in_teacher_comparison(self):
+ report = json.loads((ROOT / "results/rma/baseline/seed123.json").read_text())
+ report["policy"] = "student"
+ with tempfile.TemporaryDirectory() as directory:
+ root = Path(directory)
+ (root / "baseline").mkdir()
+ (root / "baseline/seed123.json").write_text(json.dumps(report))
+ with self.assertRaisesRegex(ValueError, "Unexpected evaluation protocol"):
+ load_evaluations(root)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/rma/test_plot_evaluation_trace.py b/tests/rma/test_plot_evaluation_trace.py
new file mode 100644
index 000000000..8b78fb10b
--- /dev/null
+++ b/tests/rma/test_plot_evaluation_trace.py
@@ -0,0 +1,49 @@
+import csv
+import json
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "scripts"))
+from plot_evaluation_trace import plot_trace
+
+
+class PlotEvaluationTraceTests(unittest.TestCase):
+ def test_generates_command_action_and_reward_figures(self):
+ with tempfile.TemporaryDirectory() as directory:
+ trace = Path(directory) / "eval_sample"
+ trace.mkdir()
+ (trace / "run_config.json").write_text(
+ json.dumps(
+ {
+ "control_period_s": 0.02,
+ "control_contract": {
+ "action_target_joint_order": [f"joint_{i}" for i in range(12)]
+ },
+ }
+ )
+ )
+ fields = ["step", "before_vx_m_s", "command_vx_m_s", "reward_rate/track"]
+ fields += [f"action_{i}" for i in range(12)]
+ with (trace / "transitions.csv").open("w", newline="") as stream:
+ writer = csv.DictWriter(stream, fieldnames=fields)
+ writer.writeheader()
+ for step in range(2):
+ writer.writerow(
+ {
+ "step": step,
+ "before_vx_m_s": 0.1 * step,
+ "command_vx_m_s": 0.5,
+ "reward_rate/track": 1.0,
+ **{f"action_{i}": 0.01 * i for i in range(12)},
+ }
+ )
+ output = plot_trace(trace)
+ self.assertEqual(len(output), 3)
+ self.assertTrue(all(Path(path).stat().st_size > 1000 for path in output))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/rma/test_rendering.py b/tests/rma/test_rendering.py
new file mode 100644
index 000000000..ff41ad69a
--- /dev/null
+++ b/tests/rma/test_rendering.py
@@ -0,0 +1,349 @@
+"""Rendering isolation/cleanup regressions; synthetic states, not Go2 benchmarks."""
+
+import contextlib
+import io
+import json
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from types import SimpleNamespace
+from unittest.mock import patch
+
+import torch
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "scripts"))
+import evaluate_rma
+from unilab_rma import ActorCriticRMA, AdaptationModule, RMAConfig
+
+try:
+ import mujoco
+except ImportError:
+ mujoco = None
+
+
+class SyntheticEnv:
+ def __init__(self):
+ self.actions = []
+
+ def observations(self):
+ return torch.randn(1, 49), torch.randn(1, 52), torch.ones(1, 2)
+
+ def reset(self):
+ return self.observations()
+
+ def step(self, action):
+ self.actions.append(action.clone())
+ obs = self.observations()
+ done = torch.zeros(1, dtype=torch.bool)
+ return obs, -action.square().mean(-1), done, done, obs
+
+
+class PlaybackEnv:
+ step_dt = 0.02
+ play_capabilities = SimpleNamespace(supports_physics_state_playback=True)
+
+ def __init__(self):
+ self.closed = False
+ if mujoco is not None:
+ self.model = mujoco.MjModel.from_xml_string(
+ ''
+ ''
+ )
+
+ def close(self):
+ self.closed = True
+
+ def get_playback_model(self, env_index=0):
+ return self.model
+
+ def get_physics_state_layout(self):
+ return SimpleNamespace(
+ nq=1,
+ nv=1,
+ nmocap=0,
+ split_state=lambda state: SimpleNamespace(
+ time=state[0], qpos=state[1:2], qvel=state[2:3]
+ ),
+ )
+
+ def get_physics_state_snapshot(self):
+ import numpy as np
+
+ return np.array([[0.0, 0.2, 0.1]])
+
+
+class FakeViewer:
+ def __init__(self, open_checks=None):
+ self.cam = SimpleNamespace()
+ self.open_checks = open_checks
+ self.closed = False
+ self.frames = 0
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.closed = True
+
+ def lock(self):
+ return contextlib.nullcontext()
+
+ def is_running(self):
+ if self.open_checks is None:
+ return True
+ result = self.open_checks > 0
+ self.open_checks -= 1
+ return result
+
+ def sync(self):
+ self.frames += 1
+
+
+class EvaluationRenderingTests(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ torch.set_num_threads(1)
+ cls.directory = tempfile.TemporaryDirectory()
+ cls.checkpoint = Path(cls.directory.name) / "student.pt"
+ cfg = RMAConfig()
+ teacher, adaptation = ActorCriticRMA(cfg), AdaptationModule(cfg)
+ torch.save(
+ {
+ "format": "unilab-rma-v1",
+ "phase": "student",
+ "config": teacher.metadata(),
+ "teacher": teacher.state_dict(),
+ "adaptation": adaptation.state_dict(),
+ },
+ cls.checkpoint,
+ )
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.directory.cleanup()
+
+ def evaluate(self, raw, env, *extra):
+ output = io.StringIO()
+ argv = [
+ "evaluate_rma.py",
+ "--checkpoint",
+ str(self.checkpoint),
+ "--num-envs",
+ "1",
+ "--steps",
+ "3",
+ *extra,
+ ]
+ with (
+ patch.object(sys, "argv", argv),
+ patch.object(evaluate_rma, "build_environment", return_value=(raw, env)),
+ contextlib.redirect_stdout(output),
+ ):
+ evaluate_rma.main()
+ return json.loads(output.getvalue())
+
+ def test_default_does_not_import_rendering_and_keeps_transition_count(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ with patch.dict(
+ sys.modules,
+ {
+ "unilab_rma.rendering": None,
+ "unilab_rma.tensorrt_runtime": None,
+ "unilab_rma.evaluation_trace": None,
+ },
+ ):
+ metrics = self.evaluate(raw, env)
+ self.assertEqual(metrics["total_transitions"], 3)
+ self.assertTrue(raw.closed)
+
+ def test_diagnostics_preserve_default_metrics_and_actions(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ expected = self.evaluate(raw, env)
+ raw2, env2 = PlaybackEnv(), SyntheticEnv()
+ raw2.reward_manager = SimpleNamespace(
+ step_reward_names=("tracking_lin_vel",), step_reward_means=torch.tensor([0.5])
+ )
+ actual = self.evaluate(raw2, env2, "--diagnostics")
+ diagnostics = actual.pop("diagnostics")
+ self.assertEqual(actual, expected)
+ self.assertAlmostEqual(
+ diagnostics["weighted_reward_terms_before_dt"]["tracking_lin_vel"], 0.5
+ )
+ for left, right in zip(env.actions, env2.actions):
+ self.assertTrue(torch.equal(left, right))
+
+ def test_fixed_command_and_task_are_forwarded_to_environment_builder(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ argv = [
+ "evaluate_rma.py",
+ "--checkpoint",
+ str(self.checkpoint),
+ "--num-envs",
+ "1",
+ "--steps",
+ "3",
+ "--command",
+ "0.5",
+ "0",
+ "0",
+ "--task",
+ "go2_joystick_flat/rma_forward",
+ ]
+ with (
+ patch.object(sys, "argv", argv),
+ patch.object(evaluate_rma, "build_environment", return_value=(raw, env)) as build,
+ contextlib.redirect_stdout(io.StringIO()),
+ ):
+ evaluate_rma.main()
+ self.assertEqual(
+ build.call_args.kwargs,
+ {"task": "go2_joystick_flat/rma_forward", "command": [0.5, 0.0, 0.0]},
+ )
+
+ def test_trace_preserves_actions_and_metrics_and_writes_separate_json(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ expected = self.evaluate(raw, env)
+ raw2, env2 = PlaybackEnv(), SyntheticEnv()
+ names = [f"joint_{i}" for i in range(12)]
+ term = SimpleNamespace(
+ cfg=SimpleNamespace(entity_name="robot", clip=None),
+ target_names=names,
+ target_ids=list(range(12)),
+ scale=0.25,
+ offset=torch.zeros(1, 12),
+ )
+ raw2.action_manager = SimpleNamespace(get_term=lambda name: term)
+ raw2.scene = {"robot": SimpleNamespace(joint_names=names)}
+ raw2.reward_manager = SimpleNamespace(
+ step_reward_names=("tracking_lin_vel",),
+ get_active_iterable_terms=lambda index: [("tracking_lin_vel", [0.5])],
+ )
+ with tempfile.TemporaryDirectory() as directory:
+ actual = self.evaluate(raw2, env2, "--trace-dir", directory)
+ trace = actual.pop("trace")
+ self.assertEqual(actual, expected)
+ self.assertEqual(trace["full"]["transitions"], 3)
+ saved = json.loads((Path(trace["directory"]) / "summary.json").read_text())
+ self.assertEqual(saved["total_transitions"], 3)
+ self.assertTrue(raw2.closed)
+ for left, right in zip(env.actions, env2.actions, strict=True):
+ self.assertTrue(torch.equal(left, right))
+
+ def test_reset_failure_still_closes_environment(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ with patch.object(env, "reset", side_effect=RuntimeError("reset failed")):
+ with self.assertRaisesRegex(RuntimeError, "reset failed"):
+ self.evaluate(raw, env, "--render")
+ self.assertTrue(raw.closed)
+
+ def test_tensorrt_actions_drive_environment_and_runtime_is_closed(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+
+ class Runtime:
+ closed = False
+
+ def infer(self, obs, history):
+ self.history_matches_current = torch.equal(history[:, -1, :], obs)
+ return torch.full((1, 12), 0.125)
+
+ def close(self):
+ self.closed = True
+
+ runtime = Runtime()
+ module = SimpleNamespace(TensorRTWorker=lambda *args: runtime)
+ with patch.dict(sys.modules, {"unilab_rma.tensorrt_runtime": module}):
+ metrics = self.evaluate(raw, env, "--backend", "tensorrt", "--engine", "unused.engine")
+ self.assertTrue(runtime.closed and raw.closed and runtime.history_matches_current)
+ self.assertEqual(metrics["inference_backend"], "tensorrt_cpp")
+ self.assertEqual(metrics["total_transitions"], 3)
+ self.assertTrue(
+ all(torch.equal(action, torch.full((1, 12), 0.125)) for action in env.actions)
+ )
+
+ def test_tensorrt_failure_closes_runtime_and_environment(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ closed = []
+
+ def fail(*args):
+ raise RuntimeError("worker failed")
+
+ runtime = SimpleNamespace(infer=fail, close=lambda: closed.append(True))
+ module = SimpleNamespace(TensorRTWorker=lambda *args: runtime)
+ with patch.dict(sys.modules, {"unilab_rma.tensorrt_runtime": module}):
+ with self.assertRaisesRegex(RuntimeError, "worker failed"):
+ self.evaluate(raw, env, "--backend", "tensorrt", "--engine", "unused.engine")
+ self.assertEqual(closed, [True])
+ self.assertTrue(raw.closed)
+
+ @unittest.skipIf(mujoco is None, "MuJoCo is required for playback contract tests")
+ def test_render_keeps_actions_and_metrics_and_uses_separate_model(self):
+ import mujoco.viewer
+
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ expected = self.evaluate(raw, env)
+ raw2, env2, viewer = PlaybackEnv(), SyntheticEnv(), FakeViewer()
+
+ def launch(model, data):
+ self.assertIsNot(model, raw2.model)
+ model.opt.gravity[:] = 0 # A viewer edit must not change physics.
+ return viewer
+
+ with (
+ patch("glfw.init", return_value=True),
+ patch("glfw.terminate"),
+ patch("mujoco.viewer.launch_passive", side_effect=launch),
+ patch("unilab_rma.rendering.time.perf_counter", return_value=0),
+ patch("unilab_rma.rendering.time.sleep") as sleep,
+ ):
+ actual = self.evaluate(raw2, env2, "--render", "--render-speed", "0.5")
+ self.assertEqual(actual, expected)
+ for a, b in zip(env.actions, env2.actions):
+ self.assertTrue(torch.equal(a, b))
+ self.assertNotEqual(float(raw2.model.opt.gravity[2]), 0)
+ self.assertEqual(viewer.frames, 4)
+ self.assertTrue(viewer.closed and raw2.closed)
+ self.assertEqual(sleep.call_count, 3)
+ self.assertAlmostEqual(sleep.call_args.args[0], 0.04)
+
+ @unittest.skipIf(mujoco is None, "MuJoCo is required for playback contract tests")
+ def test_window_close_reports_actual_transition_count(self):
+ import mujoco.viewer
+
+ raw, env, viewer = PlaybackEnv(), SyntheticEnv(), FakeViewer(open_checks=1)
+ with (
+ patch("glfw.init", return_value=True),
+ patch("glfw.terminate"),
+ patch("mujoco.viewer.launch_passive", return_value=viewer),
+ ):
+ metrics = self.evaluate(raw, env, "--render")
+ self.assertEqual(metrics["total_transitions"], 1)
+ self.assertTrue(viewer.closed and raw.closed)
+
+ @unittest.skipIf(mujoco is None, "MuJoCo is required for playback contract tests")
+ def test_inference_failure_closes_viewer(self):
+ import mujoco.viewer
+
+ raw, env, viewer = PlaybackEnv(), SyntheticEnv(), FakeViewer()
+ with (
+ patch("glfw.init", return_value=True),
+ patch("glfw.terminate"),
+ patch("mujoco.viewer.launch_passive", return_value=viewer),
+ patch.object(env, "step", side_effect=RuntimeError("step failed")),
+ ):
+ with self.assertRaisesRegex(RuntimeError, "step failed"):
+ self.evaluate(raw, env, "--render")
+ self.assertTrue(viewer.closed and raw.closed)
+
+ @unittest.skipIf(mujoco is None, "MuJoCo is required for playback contract tests")
+ def test_unavailable_display_fails_cleanly(self):
+ raw, env = PlaybackEnv(), SyntheticEnv()
+ with patch("glfw.init", return_value=False):
+ with self.assertRaisesRegex(RuntimeError, "no usable GLFW display"):
+ self.evaluate(raw, env, "--render")
+ self.assertTrue(raw.closed)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/rma/test_tensorrt_runtime.py b/tests/rma/test_tensorrt_runtime.py
new file mode 100644
index 000000000..02c033b14
--- /dev/null
+++ b/tests/rma/test_tensorrt_runtime.py
@@ -0,0 +1,120 @@
+"""Bridge protocol and cleanup tests using an engine-independent subprocess."""
+
+import os
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from types import SimpleNamespace
+
+import torch
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+from unilab_rma.tensorrt_runtime import TensorRTWorker
+
+FAKE_WORKER = """
+from pathlib import Path
+import struct, sys, time
+mode = Path(sys.argv[2]).read_text()
+if mode == 'startup_failure':
+ raise SystemExit(2)
+magic = b'BAD!' if mode == 'bad_header' else b'RMA1'
+sys.stdout.buffer.write(struct.pack('<4sIII',magic,49,50,12))
+sys.stdout.buffer.flush()
+if mode == 'bad_header':
+ raise SystemExit(0)
+while True:
+ frame = sys.stdin.buffer.read((49+2450)*4)
+ if not frame:
+ break
+ if len(frame) != (49+2450)*4:
+ raise SystemExit(3)
+ values = struct.unpack('<2499f',frame)
+ action = [values[i]+values[49+2450-49+i] for i in range(12)]
+ if mode == 'stall':
+ time.sleep(60)
+ if mode == 'nan':
+ action[0] = float('nan')
+ encoded = struct.pack('<12f',*action)
+ if mode == 'short_output':
+ sys.stdout.buffer.write(encoded[:4])
+ sys.stdout.buffer.flush()
+ break
+ sys.stdout.buffer.write(encoded)
+ sys.stdout.buffer.flush()
+"""
+
+
+@unittest.skipUnless(os.name == "posix", "The C++ bridge targets Linux/WSL pipes")
+class TensorRTWorkerTests(unittest.TestCase):
+ def setUp(self):
+ self.directory = tempfile.TemporaryDirectory()
+ self.addCleanup(self.directory.cleanup)
+ self.folder = Path(self.directory.name)
+ self.worker = self.folder / "fake_worker"
+ self.worker.write_text("#!" + sys.executable + "\n" + FAKE_WORKER)
+ self.worker.chmod(0o755)
+ self.engine = self.folder / "fake.engine"
+ self.cfg = SimpleNamespace(obs_dim=49, history_length=50, action_dim=12)
+
+ def start(self, mode="echo", **kwargs):
+ self.engine.write_text(mode)
+ runtime = TensorRTWorker(self.worker, self.engine, self.cfg, **kwargs)
+ self.addCleanup(runtime.close)
+ return runtime
+
+ def test_multiple_environments_preserve_observation_and_history_order(self):
+ runtime = self.start()
+ process = runtime._process
+ obs = torch.arange(98, dtype=torch.float32).reshape(2, 49)
+ history = torch.zeros(2, 50, 49)
+ history[:, -1, :] = -3 * obs
+ actual = runtime.infer(obs, history)
+ self.assertTrue(torch.equal(actual, -2 * obs[:, :12]))
+ history[:, -1, :] = obs + 1
+ self.assertTrue(torch.equal(runtime.infer(obs, history), 2 * obs[:, :12] + 1))
+ self.assertIs(runtime._process, process)
+ runtime.close()
+ self.assertIsNotNone(process.poll())
+ self.assertTrue(process.stdout.closed and process.stdin.closed)
+ runtime.close() # Repeated cleanup is safe.
+ with self.assertRaisesRegex(RuntimeError, "closed"):
+ runtime.infer(obs, history)
+
+ def test_bad_handshake_and_startup_failure_are_reported(self):
+ for mode, message in [("bad_header", "protocol"), ("startup_failure", "closed output")]:
+ with self.subTest(mode=mode):
+ self.engine.write_text(mode)
+ with self.assertRaisesRegex(RuntimeError, message):
+ TensorRTWorker(self.worker, self.engine, self.cfg)
+
+ def test_truncated_action_does_not_hang(self):
+ runtime = self.start("short_output")
+ with self.assertRaisesRegex(RuntimeError, "closed output"):
+ runtime.infer(torch.zeros(1, 49), torch.zeros(1, 50, 49))
+
+ def test_nonfinite_output_is_rejected(self):
+ runtime = self.start("nan")
+ with self.assertRaisesRegex(RuntimeError, "non-finite"):
+ runtime.infer(torch.zeros(1, 49), torch.zeros(1, 50, 49))
+
+ def test_stalled_worker_times_out_and_can_be_stopped(self):
+ runtime = self.start("stall", timeout_s=0.5)
+ with self.assertRaises(TimeoutError):
+ runtime.infer(torch.zeros(1, 49), torch.zeros(1, 50, 49))
+ runtime.close()
+ self.assertIsNotNone(runtime._process.poll())
+
+ def test_invalid_inputs_are_rejected_before_send(self):
+ runtime = self.start()
+ with self.assertRaisesRegex(ValueError, "observation shape"):
+ runtime.infer(torch.zeros(1, 48), torch.zeros(1, 50, 49))
+ with self.assertRaisesRegex(ValueError, "history shape"):
+ runtime.infer(torch.zeros(2, 49), torch.zeros(1, 50, 49))
+ with self.assertRaisesRegex(ValueError, "finite"):
+ runtime.infer(torch.full((1, 49), float("nan")), torch.zeros(1, 50, 49))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/rma/test_training_log.py b/tests/rma/test_training_log.py
new file mode 100644
index 000000000..5138dc29f
--- /dev/null
+++ b/tests/rma/test_training_log.py
@@ -0,0 +1,98 @@
+import contextlib
+import csv
+import io
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+
+import torch
+from tensorboard.backend.event_processing.event_accumulator import EventAccumulator
+
+ROOT = Path(__file__).resolve().parents[2]
+sys.path.insert(0, str(ROOT / "rsl_rl"))
+from unilab_rma import ActorCriticRMA, AdaptationModule, RMAConfig
+from unilab_rma.runner import train_teacher
+from unilab_rma.training_log import EpisodeLog, TrainingLog
+
+
+class LoggingTests(unittest.TestCase):
+ def test_csv_events_and_unique_runs(self):
+ with tempfile.TemporaryDirectory() as folder:
+ output = Path(folder) / "teacher.pt"
+ with TrainingLog(output, "teacher", {"seed": 42}) as log:
+ directory = log.directory
+ log.write(
+ 1,
+ 48,
+ loss=0.5,
+ mean_step_reward=0.1,
+ completed_episodes=0,
+ mean_episode_return=None,
+ mean_episode_length_steps=None,
+ )
+ self.assertEqual(
+ len(list(csv.DictReader((directory / "metrics.csv").read_text().splitlines()))),
+ 1,
+ )
+ log.write(
+ 2,
+ 96,
+ loss=0.4,
+ mean_step_reward=0.2,
+ completed_episodes=2,
+ mean_episode_return=1.5,
+ mean_episode_length_steps=7,
+ )
+ rows = list(csv.DictReader((directory / "metrics.csv").read_text().splitlines()))
+ self.assertEqual(rows[0]["mean_episode_return"], "")
+ self.assertEqual(rows[1]["total_transitions"], "96")
+ events = EventAccumulator(str(directory / "tensorboard")).Reload()
+ self.assertEqual([event.step for event in events.Scalars("teacher/loss")], [1, 2])
+ self.assertEqual(len(events.Scalars("teacher/mean_episode_return")), 1)
+ with TrainingLog(output, "teacher", {}) as second:
+ self.assertNotEqual(second.directory, directory)
+
+ def test_episode_accumulators_cross_rollouts_and_reset_individually(self):
+ episodes = EpisodeLog(2)
+ first = episodes.consume(
+ torch.tensor([[1.0, 2.0], [3.0, 4.0]]), torch.tensor([[False, True], [False, False]])
+ )
+ self.assertEqual(first["mean_episode_return"], 2.0)
+ second = episodes.consume(torch.tensor([[5.0, 6.0]]), torch.tensor([[True, True]]))
+ self.assertEqual(second["completed_episodes"], 2)
+ self.assertEqual(second["mean_episode_return"], 9.5)
+ self.assertEqual(second["mean_episode_length_steps"], 2.5)
+
+ def test_logging_does_not_change_policy_updates_or_rng(self):
+ class Env:
+ num_envs = 2
+
+ def reset(self):
+ return self.obs()
+
+ def obs(self):
+ return torch.randn(2, 49), torch.randn(2, 52), torch.ones(2, 2)
+
+ def step(self, action):
+ done = torch.zeros(2, dtype=torch.bool)
+ return self.obs(), -action.square().mean(-1), done, done, self.obs()
+
+ def run(output, logging):
+ torch.manual_seed(123)
+ teacher, adaptation = ActorCriticRMA(RMAConfig()), AdaptationModule(RMAConfig())
+ scope = TrainingLog(output, "teacher", {}) if logging else contextlib.nullcontext(None)
+ with contextlib.redirect_stdout(io.StringIO()), scope as logger:
+ train_teacher(Env(), teacher, adaptation, 2, output, horizon=3, logger=logger)
+ return teacher.state_dict(), torch.get_rng_state()
+
+ with tempfile.TemporaryDirectory() as folder:
+ expected, rng1 = run(Path(folder) / "off.pt", False)
+ actual, rng2 = run(Path(folder) / "on.pt", True)
+ self.assertTrue(torch.equal(rng1, rng2))
+ self.assertTrue(all(torch.equal(expected[name], actual[name]) for name in expected))
+
+
+if __name__ == "__main__":
+ torch.set_num_threads(1)
+ unittest.main()