Browse Source

make dora-rustypot pip installable

tags/v0.3.12-rc0
haixuantao 11 months ago
parent
commit
86a54a77de
6 changed files with 149 additions and 78 deletions
  1. +1
    -0
      Cargo.lock
  2. +1
    -0
      examples/so100-remote/no_torque.yml
  3. +16
    -0
      node-hub/dora-rustypot/Cargo.toml
  4. +28
    -0
      node-hub/dora-rustypot/pyproject.toml
  5. +101
    -0
      node-hub/dora-rustypot/src/lib.rs
  6. +2
    -78
      node-hub/dora-rustypot/src/main.rs

+ 1
- 0
Cargo.lock View File

@@ -3393,6 +3393,7 @@ version = "0.1.0"
dependencies = [
"dora-node-api",
"eyre",
"pyo3",
"rustypot",
"serialport",
]


+ 1
- 0
examples/so100-remote/no_torque.yml View File

@@ -1,6 +1,7 @@
nodes:
- id: so100
path: dora-rustypot
build: pip install -e ../../node-hub/dora-rustypot
inputs:
tick: dora/timer/millis/33
#pose: pytorch-kinematics/action


+ 16
- 0
node-hub/dora-rustypot/Cargo.toml View File

@@ -10,3 +10,19 @@ dora-node-api = { workspace = true }
eyre = "0.6.12"
rustypot = { version = "1.0" }
serialport = { version = "4.7.1", default-features = false }
pyo3 = { workspace = true, features = [
"extension-module",
"abi3",
"eyre",
"generate-import-lib",
], optional = true }


[features]
default = []
python = ["pyo3"]

[lib]
name = "dora_rustypot"
path = "src/lib.rs"
crate-type = ["lib", "cdylib"]

+ 28
- 0
node-hub/dora-rustypot/pyproject.toml View File

@@ -0,0 +1,28 @@
[build-system]
requires = ["maturin>=0.13.2"]
build-backend = "maturin"

[project]
name = "dora-rustypot"
dynamic = ["version"]
license = { text = "MIT" }
requires-python = ">=3.10"

dependencies = []

scripts = { "dora-rustypot" = "dora_rustypot:py_main" }

[tool.maturin]
features = ["python", "pyo3/extension-module"]

[tool.ruff.lint]
extend-select = [
"D", # pydocstyle
"UP", # Ruff's UP rule
"PERF", # Ruff's PERF rule
"RET", # Ruff's RET rule
"RSE", # Ruff's RSE rule
"NPY", # Ruff's NPY rule
"N", # Ruff's N rule
"I", # Ruff's I rule
]

+ 101
- 0
node-hub/dora-rustypot/src/lib.rs View File

@@ -0,0 +1,101 @@
use dora_node_api::dora_core::config::DataId;
use dora_node_api::{into_vec, DoraNode, Event, IntoArrow, Parameter};
use eyre::{Context, Result};
use rustypot::servo::feetech::sts3215::Sts3215Controller;
use std::collections::BTreeMap;
use std::time::Duration;

pub fn lib_main() -> Result<()> {
let (mut node, mut events) = DoraNode::init_from_env()?;
let serialportname: String = std::env::var("PORT").context("Serial port name not provided")?;
let baudrate: u32 = std::env::var("BAUDRATE")
.unwrap_or_else(|_| "1000000".to_string())
.parse()
.context("Invalid baudrate")?;
let ids = std::env::var("IDS")
.unwrap_or_else(|_| "1,2,3,4,5,6".to_string())
.split(&[',', ' '][..])
.map(|s| s.parse::<u8>().unwrap())
.collect::<Vec<u8>>();

let serial_port = serialport::new(serialportname, baudrate)
.timeout(Duration::from_millis(1000))
.open()?;

let mut c = Sts3215Controller::new()
.with_protocol_v1()
.with_serial_port(serial_port);

if let Ok(torque) = std::env::var("TORQUE") {
let truthies = vec![true; ids.len()];

c.write_torque_enable(&ids, &truthies)
.expect("could not enable torque");

if let Ok(torque_limit) = torque.parse::<u16>() {
let limits = vec![torque_limit; ids.len()];
c.write_torque_limit(&ids, &limits)
.expect("could not enable torque");
}
} else {
let falsies = vec![false; ids.len()];
c.write_torque_enable(&ids, &falsies)
.expect("could not enable torque");
}

while let Some(event) = events.recv() {
match event {
Event::Input {
id,
metadata: _,
data,
} => match id.as_str() {
"tick" => {
if let Ok(joints) = c.read_present_position(&ids) {
let mut parameter = BTreeMap::new();
parameter.insert(
"encoding".to_string(),
Parameter::String("jointstate".to_string()),
);
node.send_output(
DataId::from("pose".to_string()),
parameter,
joints.into_arrow(),
)
.unwrap();
};
}
"pose" => {
let data: Vec<f64> = into_vec(&data).expect("could not cast values");
c.write_goal_position(&ids, &data).unwrap();
}
other => eprintln!("Received input `{other}`"),
},
_ => {}
}
}

Ok(())
}

#[cfg(feature = "python")]
use pyo3::{
pyfunction, pymodule,
types::{PyModule, PyModuleMethods},
wrap_pyfunction, Bound, PyResult, Python,
};

#[cfg(feature = "python")]
#[pyfunction]
fn py_main(_py: Python) -> eyre::Result<()> {
lib_main()
}

/// A Python module implemented in Rust.
#[cfg(feature = "python")]
#[pymodule]
fn dora_rustypot(_py: Python, m: Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(py_main, &m)?)?;
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
Ok(())
}

+ 2
- 78
node-hub/dora-rustypot/src/main.rs View File

@@ -1,79 +1,3 @@
use dora_node_api::dora_core::config::DataId;
use dora_node_api::{into_vec, DoraNode, Event, IntoArrow, Parameter};
use eyre::{Context, Result};
use rustypot::servo::feetech::sts3215::Sts3215Controller;
use std::collections::BTreeMap;
use std::time::Duration;

fn main() -> Result<()> {
let (mut node, mut events) = DoraNode::init_from_env()?;
let serialportname: String = std::env::var("PORT").context("Serial port name not provided")?;
let baudrate: u32 = std::env::var("BAUDRATE")
.unwrap_or_else(|_| "1000000".to_string())
.parse()
.context("Invalid baudrate")?;
let ids = std::env::var("IDS")
.unwrap_or_else(|_| "1,2,3,4,5,6".to_string())
.split(&[',', ' '][..])
.map(|s| s.parse::<u8>().unwrap())
.collect::<Vec<u8>>();

let serial_port = serialport::new(serialportname, baudrate)
.timeout(Duration::from_millis(1000))
.open()?;

let mut c = Sts3215Controller::new()
.with_protocol_v1()
.with_serial_port(serial_port);

if let Ok(torque) = std::env::var("TORQUE") {
let truthies = vec![true; ids.len()];

c.write_torque_enable(&ids, &truthies)
.expect("could not enable torque");

if let Ok(torque_limit) = torque.parse::<u16>() {
let limits = vec![torque_limit; ids.len()];
c.write_torque_limit(&ids, &limits)
.expect("could not enable torque");
}
} else {
let falsies = vec![false; ids.len()];
c.write_torque_enable(&ids, &falsies)
.expect("could not enable torque");
}

while let Some(event) = events.recv() {
match event {
Event::Input {
id,
metadata: _,
data,
} => match id.as_str() {
"tick" => {
if let Ok(joints) = c.read_present_position(&ids) {
let mut parameter = BTreeMap::new();
parameter.insert(
"encoding".to_string(),
Parameter::String("jointstate".to_string()),
);
node.send_output(
DataId::from("pose".to_string()),
parameter,
joints.into_arrow(),
)
.unwrap();
};
}
"pose" => {
let data: Vec<f64> = into_vec(&data).expect("could not cast values");
c.write_goal_position(&ids, &data).unwrap();
}
other => eprintln!("Received input `{other}`"),
},
_ => {}
}
}

Ok(())
fn main() -> Result<(), eyre::Error> {
dora_rustypot::lib_main()
}

Loading…
Cancel
Save