1use super::mj_model::{MjModel, MjtSameFrame, MjtObj, MjtStage};
2use super::mj_statistic::{MjWarningStat, MjTimerStat};
3use super::mj_auxiliary::MjContact;
4use super::mj_primitive::*;
5use crate::mujoco_c::*;
6
7use std::io::{self, Error, ErrorKind};
8use std::ffi::CString;
9use std::ptr;
10
11use crate::{mj_view_indices, mj_model_nx_to_mapping, mj_model_nx_to_nitem};
12use crate::{view_creator, info_method, info_with_view};
13
14pub type MjtState = mjtState;
19
20pub type MjtConstraint = mjtConstraint;
23
24pub type MjtConstraintState = mjtConstraintState;
26
27pub type MjtWarning = mjtWarning;
30
31pub type MjtTimer = mjtTimer;
35pub struct MjData<'a> {
45 data: *mut mjData,
46 model: &'a MjModel
47}
48
49unsafe impl Send for MjData<'_> {}
52unsafe impl Sync for MjData<'_> {}
53
54
55impl<'a> MjData<'a> {
56 pub fn new(model: &'a MjModel) -> Self {
58 unsafe {
59 Self {
60 data: mj_makeData(model.ffi()),
61 model: model,
62 }
63 }
64 }
65
66 pub fn ffi(&self) -> &mjData {
68 unsafe { self.data.as_ref().unwrap() }
69 }
70
71 pub unsafe fn ffi_mut(&mut self) -> &mut mjData {
73 unsafe { self.data.as_mut().unwrap() }
74 }
75
76 pub(crate) fn model(&self) -> &MjModel {
80 self.model
81 }
82
83 pub fn contacts(&self) -> &[MjContact] {
86 unsafe {
87 std::slice::from_raw_parts((*self.data).contact, (*self.data).ncon as usize)
88 }
89 }
90
91 info_method! { Data, model.ffi(), body, [
92 xfrc_applied: 6, xpos: 3, xquat: 4, xmat: 9, xipos: 3, ximat: 9, subtree_com: 3, cinert: 10,
93 crb: 10, cvel: 6, subtree_linvel: 3, subtree_angmom: 3, cacc: 6, cfrc_int: 6, cfrc_ext: 6
94 ], [], []}
95 info_method! { Data, model.ffi(), camera, [xpos: 3, xmat: 9], [], []}
96 info_method! { Data, model.ffi(), geom, [xpos: 3, xmat: 9], [], []}
97 info_method! { Data, model.ffi(), site, [xpos: 3, xmat: 9], [], []}
98 info_method! { Data, model.ffi(), light, [xpos: 3, xdir: 3], [], []}
99
100 pub fn actuator(&self, name: &str) -> Option<MjActuatorDataInfo> {
106 let c_name = CString::new(name).unwrap();
107 let id = unsafe { mj_name2id(self.model.ffi(), MjtObj::mjOBJ_ACTUATOR as i32, c_name.as_ptr())};
108 if id == -1 { return None;
110 }
111
112 let ctrl;
113 let act;
114 let model_ffi = self.model.ffi();
115 unsafe {
116 ctrl = (id as usize, 1);
117 act = mj_view_indices!(id as usize, model_ffi.actuator_actadr, model_ffi.nu as usize, model_ffi.na as usize);
118 }
119
120 Some(MjActuatorDataInfo { name: name.to_string(), id: id as usize, ctrl, act})
121 }
122
123 pub fn joint(&self, name: &str) -> Option<MjJointDataInfo> {
129 let c_name = CString::new(name).unwrap();
130 let id = unsafe { mj_name2id(self.model.ffi(), MjtObj::mjOBJ_JOINT as i32, c_name.as_ptr())};
131 if id == -1 { return None;
133 }
134 let model_ffi = self.model.ffi();
135 let id = id as usize;
136 unsafe {
137 let nq_range = mj_view_indices!(id, mj_model_nx_to_mapping!(model_ffi, nq), mj_model_nx_to_nitem!(model_ffi, nq), model_ffi.nq);
138 let nv_range = mj_view_indices!(id, mj_model_nx_to_mapping!(model_ffi, nv), mj_model_nx_to_nitem!(model_ffi, nv), model_ffi.nv);
139
140 let qpos = nq_range;
142 let qvel = nv_range;
143 let qacc_warmstart = nv_range;
144 let qfrc_applied = nv_range;
145 let qacc = nv_range;
146 let xanchor = (id * 3, 3);
147 let xaxis = (id * 3, 3);
148 #[allow(non_snake_case)]
149 let qLDiagInv = nv_range;
150 let qfrc_bias = nv_range;
151 let qfrc_passive = nv_range;
152 let qfrc_actuator = nv_range;
153 let qfrc_smooth = nv_range;
154 let qacc_smooth = nv_range;
155 let qfrc_constraint = nv_range;
156 let qfrc_inverse = nv_range;
157
158 let qfrc_spring = nv_range;
159 let qfrc_damper = nv_range;
160 let qfrc_gravcomp = nv_range;
161 let qfrc_fluid = nv_range;
162 Some(MjJointDataInfo {name: name.to_string(), id: id as usize,
167 qpos, qvel, qacc_warmstart, qfrc_applied, qacc, xanchor, xaxis, qLDiagInv, qfrc_bias,
168 qfrc_spring, qfrc_damper, qfrc_gravcomp, qfrc_fluid, qfrc_passive,
169 qfrc_actuator, qfrc_smooth, qacc_smooth, qfrc_constraint, qfrc_inverse
170 })
171 }
172 }
173
174 pub fn sensor(&self, name: &str) -> Option<MjSensorDataInfo> {
180 let c_name = CString::new(name).unwrap();
181 let id = unsafe { mj_name2id(self.model.ffi(), MjtObj::mjOBJ_SENSOR as i32, c_name.as_ptr())};
182 if id == -1 { return None;
184 }
185 let model_ffi = self.model.ffi();
186 let id = id as usize;
187
188 unsafe {
189 let data = mj_view_indices!(id, mj_model_nx_to_mapping!(model_ffi, nsensordata), mj_model_nx_to_nitem!(model_ffi, nsensordata), model_ffi.nsensordata);
190 Some(MjSensorDataInfo { id, name: name.to_string(), data })
191 }
192 }
193
194
195 #[allow(non_snake_case)]
201 pub fn tendon(&self, name: &str) -> Option<MjTendonDataInfo> {
202 let c_name = CString::new(name).unwrap();
203 let id = unsafe { mj_name2id(self.model.ffi(), MjtObj::mjOBJ_TENDON as i32, c_name.as_ptr())};
204 if id == -1 { return None;
206 }
207
208 let model_ffi = self.model.ffi();
209 let id = id as usize;
210 let nv = model_ffi.nv as usize;
211 let wrapadr = (id, 1);
212 let wrapnum = (id, 1);
213 let J_rownnz = (id, 1);
214 let J_rowadr = (id, 1);
215 let J_colind = (id * nv, nv);
216 let length = (id, 1);
217 let J = (id * nv, nv);
218 let velocity = (id, 1);
219
220 Some(MjTendonDataInfo { id, name: name.to_string(), wrapadr, wrapnum, J_rownnz, J_rowadr, J_colind, length, J, velocity })
221 }
222
223 pub fn step(&mut self) {
225 unsafe {
226 mj_step(self.model.ffi(), self.ffi_mut());
227 }
228 }
229
230 pub fn step1(&mut self) {
232 unsafe {
233 mj_step1(self.model.ffi(), self.ffi_mut());
234 }
235 }
236
237 pub fn step2(&mut self) {
240 unsafe {
241 mj_step2(self.model.ffi(), self.ffi_mut());
242 }
243 }
244
245 pub fn forward(&mut self) {
248 unsafe {
249 mj_forward(self.model.ffi(), self.ffi_mut());
250 }
251 }
252
253 pub fn forward_skip(&mut self, skipstage: MjtStage, skipsensor: bool) {
256 unsafe {
257 mj_forwardSkip(self.model.ffi(), self.ffi_mut(), skipstage as i32, skipsensor as i32);
258 }
259 }
260
261 pub fn inverse(&mut self) {
264 unsafe {
265 mj_inverse(self.model.ffi(), self.ffi_mut());
266 }
267 }
268
269 pub fn inverse_skip(&mut self, skipstage: MjtStage, skipsensor: bool) {
272 unsafe {
273 mj_inverseSkip(self.model.ffi(), self.ffi_mut(), skipstage as i32, skipsensor as i32);
274 }
275 }
276
277 pub fn contact_force(&self, contact_id: usize) -> [MjtNum; 6] {
282 let mut force = [0.0; 6];
283 unsafe {
284 mj_contactForce(
285 self.model.ffi(), self.data,
286 contact_id as i32, force.as_mut_ptr()
287 );
288 }
289 force
290 }
291
292 pub fn reset(&mut self) {
296 unsafe { mj_resetData(self.model.ffi(), self.ffi_mut()) }
297 }
298
299 pub fn reset_debug(&mut self, debug_value: u8) {
301 unsafe { mj_resetDataDebug(self.model.ffi(), self.ffi_mut(), debug_value) }
302 }
303
304 pub fn reset_keyframe(&mut self, key: i32) {
306 unsafe { mj_resetDataKeyframe(self.model.ffi(), self.ffi_mut(), key) }
307 }
308
309 pub fn print_formatted(&self, filename: &str, float_format: &str) {
314 let c_filename = CString::new(filename).unwrap();
315 let c_float_format = CString::new(float_format).unwrap();
316 unsafe { mj_printFormattedData(self.model.ffi(), self.ffi(), c_filename.as_ptr(), c_float_format.as_ptr()) }
317 }
318
319 pub fn print(&self, filename: &str) {
323 let c_filename = CString::new(filename).unwrap();
324 unsafe { mj_printData(self.model.ffi(), self.ffi(), c_filename.as_ptr()) }
325 }
326
327 pub fn fwd_position(&mut self) {
329 unsafe { mj_fwdPosition(self.model.ffi(), self.ffi_mut()) }
330 }
331
332 pub fn fwd_velocity(&mut self) {
334 unsafe { mj_fwdVelocity(self.model.ffi(), self.ffi_mut()) }
335 }
336
337 pub fn fwd_actuation(&mut self) {
339 unsafe { mj_fwdActuation(self.model.ffi(), self.ffi_mut()) }
340 }
341
342 pub fn fwd_acceleration(&mut self) {
344 unsafe { mj_fwdAcceleration(self.model.ffi(), self.ffi_mut()) }
345 }
346
347 pub fn fwd_constraint(&mut self) {
349 unsafe { mj_fwdConstraint(self.model.ffi(), self.ffi_mut()) }
350 }
351
352 pub fn euler(&mut self) {
354 unsafe { mj_Euler(self.model.ffi(), self.ffi_mut()) }
355 }
356
357 pub fn runge_kutta(&mut self, n: i32) {
359 unsafe { mj_RungeKutta(self.model.ffi(), self.ffi_mut(), n) }
360 }
361
362 pub fn implicit(&mut self) {
364 unsafe { mj_implicit(self.model.ffi(), self.ffi_mut()) }
365 }
366
367 pub fn inv_position(&mut self) {
369 unsafe { mj_invPosition(self.model.ffi(), self.ffi_mut()) }
370 }
371
372 pub fn inv_velocity(&mut self) {
374 unsafe { mj_invVelocity(self.model.ffi(), self.ffi_mut()) }
375 }
376
377 pub fn inv_constraint(&mut self) {
379 unsafe { mj_invConstraint(self.model.ffi(), self.ffi_mut()) }
380 }
381
382 pub fn compare_fwd_inv(&mut self) {
384 unsafe { mj_compareFwdInv(self.model.ffi(), self.ffi_mut()) }
385 }
386
387 pub fn sensor_pos(&mut self) {
389 unsafe { mj_sensorPos(self.model.ffi(), self.ffi_mut()) }
390 }
391
392 pub fn sensor_vel(&mut self) {
394 unsafe { mj_sensorVel(self.model.ffi(), self.ffi_mut()) }
395 }
396
397 pub fn sensor_acc(&mut self) {
399 unsafe { mj_sensorAcc(self.model.ffi(), self.ffi_mut()) }
400 }
401
402 pub fn energy_pos(&mut self) {
404 unsafe { mj_energyPos(self.model.ffi(), self.ffi_mut()) }
405 }
406
407 pub fn energy_vel(&mut self) {
409 unsafe { mj_energyVel(self.model.ffi(), self.ffi_mut()) }
410 }
411
412 pub fn check_pos(&mut self) {
414 unsafe { mj_checkPos(self.model.ffi(), self.ffi_mut()) }
415 }
416
417 pub fn check_vel(&mut self) {
419 unsafe { mj_checkVel(self.model.ffi(), self.ffi_mut()) }
420 }
421
422 pub fn check_acc(&mut self) {
424 unsafe { mj_checkAcc(self.model.ffi(), self.ffi_mut()) }
425 }
426
427 pub fn kinematics(&mut self) {
429 unsafe { mj_kinematics(self.model.ffi(), self.ffi_mut()) }
430 }
431
432 pub fn com_pos(&mut self) {
434 unsafe { mj_comPos(self.model.ffi(), self.ffi_mut()) }
435 }
436
437 pub fn camlight(&mut self) {
439 unsafe { mj_camlight(self.model.ffi(), self.ffi_mut()) }
440 }
441
442 pub fn flex_comp(&mut self) {
444 unsafe { mj_flex(self.model.ffi(), self.ffi_mut()) }
445 }
446
447 pub fn tendon_comp(&mut self) {
449 unsafe { mj_tendon(self.model.ffi(), self.ffi_mut()) }
450 }
451
452 pub fn transmission(&mut self) {
454 unsafe { mj_transmission(self.model.ffi(), self.ffi_mut()) }
455 }
456
457 pub fn crb(&mut self) {
459 unsafe { mj_crb(self.model.ffi(), self.ffi_mut()) }
460 }
461
462 pub fn make_m(&mut self) {
464 unsafe { mj_makeM(self.model.ffi(), self.ffi_mut()) }
465 }
466
467 pub fn factor_m(&mut self) {
469 unsafe { mj_factorM(self.model.ffi(), self.ffi_mut()) }
470 }
471
472 pub fn com_vel(&mut self) {
474 unsafe { mj_comVel(self.model.ffi(), self.ffi_mut()) }
475 }
476
477 pub fn passive(&mut self) {
479 unsafe { mj_passive(self.model.ffi(), self.ffi_mut()) }
480 }
481
482 pub fn subtree_vel(&mut self) {
484 unsafe { mj_subtreeVel(self.model.ffi(), self.ffi_mut()) }
485 }
486
487 pub fn rne(&mut self, flg_acc: bool) -> Vec<MjtNum> {
489 let mut out = vec![0.0; self.model.ffi().nv as usize];
490 unsafe { mj_rne(self.model.ffi(), self.ffi_mut(), flg_acc as i32, out.as_mut_ptr()) };
491 out
492 }
493
494 pub fn rne_post_constraint(&mut self) {
496 unsafe { mj_rnePostConstraint(self.model.ffi(), self.ffi_mut()) }
497 }
498
499 pub fn collision(&mut self) {
501 unsafe { mj_collision(self.model.ffi(), self.ffi_mut()) }
502 }
503
504 pub fn make_constraint(&mut self) {
506 unsafe { mj_makeConstraint(self.model.ffi(), self.ffi_mut()) }
507 }
508
509 pub fn island(&mut self) {
511 unsafe { mj_island(self.model.ffi(), self.ffi_mut()) }
512 }
513
514 pub fn project_constraint(&mut self) {
516 unsafe { mj_projectConstraint(self.model.ffi(), self.ffi_mut()) }
517 }
518
519 pub fn reference_constraint(&mut self) {
521 unsafe { mj_referenceConstraint(self.model.ffi(), self.ffi_mut()) }
522 }
523
524 pub fn constraint_update(&mut self, jar: &[MjtNum], cost: Option<&mut MjtNum>, flg_cone_hessian: bool) {
528 unsafe { mj_constraintUpdate(
529 self.model.ffi(), self.ffi_mut(),
530 jar.as_ptr(), cost.map_or(ptr::null_mut(), |x| x as *mut MjtNum),
531 flg_cone_hessian as i32
532 ) }
533 }
534
535 pub fn add_contact(&mut self, con: &MjContact) -> io::Result<()> {
537 match unsafe { mj_addContact(self.model.ffi(), self.ffi_mut(), con) } {
538 0 => Ok(()),
539 1 => Err(Error::new(ErrorKind::StorageFull, "buffer full")),
540 _ => Err(Error::new(ErrorKind::Other, "unknown error"))
541 }
542 }
543
544 pub fn jac(&self, jacp: bool, jacr: bool, point: &[MjtNum; 3], body_id: i32) -> (Vec<MjtNum>, Vec<MjtNum>) {
549 let required_len = 3 * self.model.ffi().nv as usize;
550 let mut jacp_vec = if jacp { vec![0 as MjtNum; required_len] } else { vec![] };
551 let mut jacr_vec = if jacr { vec![0 as MjtNum; required_len] } else { vec![] };
552
553 unsafe {
554 mj_jac(
555 self.model.ffi(),
556 self.ffi(),
557 if jacp { jacp_vec.as_mut_ptr() } else { ptr::null_mut() },
558 if jacr { jacr_vec.as_mut_ptr() } else { ptr::null_mut() },
559 point.as_ptr(),
560 body_id,
561 )
562 };
563
564 (jacp_vec, jacr_vec)
565 }
566
567 pub fn jac_body(&self, jacp: bool, jacr: bool, body_id: i32) -> (Vec<MjtNum>, Vec<MjtNum>) {
571 let required_len = 3 * self.model.ffi().nv as usize;
572 let mut jacp_vec = if jacp { vec![0 as MjtNum; required_len] } else { vec![] };
573 let mut jacr_vec = if jacr { vec![0 as MjtNum; required_len] } else { vec![] };
574
575 unsafe {
576 mj_jacBody(
577 self.model.ffi(),
578 self.ffi(),
579 if jacp { jacp_vec.as_mut_ptr() } else { ptr::null_mut() },
580 if jacr { jacr_vec.as_mut_ptr() } else { ptr::null_mut() },
581 body_id,
582 )
583 };
584
585 (jacp_vec, jacr_vec)
586 }
587
588 pub fn jac_body_com(&self, jacp: bool, jacr: bool, body_id: i32) -> (Vec<MjtNum>, Vec<MjtNum>) {
592 let required_len = 3 * self.model.ffi().nv as usize;
593 let mut jacp_vec = if jacp { vec![0 as MjtNum; required_len] } else { vec![] };
594 let mut jacr_vec = if jacr { vec![0 as MjtNum; required_len] } else { vec![] };
595
596 unsafe {
597 mj_jacBodyCom(
598 self.model.ffi(),
599 self.ffi(),
600 if jacp { jacp_vec.as_mut_ptr() } else { ptr::null_mut() },
601 if jacr { jacr_vec.as_mut_ptr() } else { ptr::null_mut() },
602 body_id,
603 )
604 };
605
606 (jacp_vec, jacr_vec)
607 }
608
609 pub fn jac_subtree_com(&mut self, jacp: bool, body_id: i32) -> Vec<MjtNum> {
613 let required_len = 3 * self.model.ffi().nv as usize;
614 let mut jacp_vec = if jacp { vec![0 as MjtNum; required_len] } else { vec![] };
615
616 unsafe {
617 mj_jacSubtreeCom(
618 self.model.ffi(),
619 self.ffi_mut(),
620 if jacp { jacp_vec.as_mut_ptr() } else { ptr::null_mut() },
621 body_id,
622 )
623 };
624
625 jacp_vec
626 }
627
628 pub fn jac_geom(&self, jacp: bool, jacr: bool, geom_id: i32) -> (Vec<MjtNum>, Vec<MjtNum>) {
632 let required_len = 3 * self.model.ffi().nv as usize;
633 let mut jacp_vec = if jacp { vec![0 as MjtNum; required_len] } else { vec![] };
634 let mut jacr_vec = if jacr { vec![0 as MjtNum; required_len] } else { vec![] };
635
636 unsafe {
637 mj_jacGeom(
638 self.model.ffi(),
639 self.ffi(),
640 if jacp { jacp_vec.as_mut_ptr() } else { ptr::null_mut() },
641 if jacr { jacr_vec.as_mut_ptr() } else { ptr::null_mut() },
642 geom_id,
643 )
644 };
645
646 (jacp_vec, jacr_vec)
647 }
648
649 pub fn jac_site(&self, jacp: bool, jacr: bool, site_id: i32) -> (Vec<MjtNum>, Vec<MjtNum>) {
653 let required_len = 3 * self.model.ffi().nv as usize;
654 let mut jacp_vec = if jacp { vec![0 as MjtNum; required_len] } else { vec![] };
655 let mut jacr_vec = if jacr { vec![0 as MjtNum; required_len] } else { vec![] };
656
657 unsafe {
658 mj_jacSite(
659 self.model.ffi(),
660 self.ffi(),
661 if jacp { jacp_vec.as_mut_ptr() } else { ptr::null_mut() },
662 if jacr { jacr_vec.as_mut_ptr() } else { ptr::null_mut() },
663 site_id,
664 )
665 };
666
667 (jacp_vec, jacr_vec)
668 }
669
670 pub fn angmom_mat(&mut self, body_id: i32) -> Vec<MjtNum> {
672 let mut mat = vec![0.0; 3 * self.model.ffi().nv as usize];
673 unsafe { mj_angmomMat(self.model.ffi(), self.ffi_mut(), mat.as_mut_ptr(), body_id) };
674 mat
675 }
676
677 pub fn object_velocity(&self, obj_type: MjtObj, obj_id: i32, flg_local: bool) -> [MjtNum; 6] {
679 let mut result: [MjtNum; 6] = [0.0; 6];
680 unsafe { mj_objectVelocity(
681 self.model.ffi(), self.ffi(),
682 obj_type as i32, obj_id,
683 result.as_mut_ptr(), flg_local as i32
684 ) };
685 result
686 }
687
688 pub fn object_acceleration(&self, obj_type: MjtObj, obj_id: i32, flg_local: bool) -> [MjtNum; 6] {
690 let mut result: [MjtNum; 6] = [0.0; 6];
691 unsafe { mj_objectAcceleration(
692 self.model.ffi(), self.ffi(),
693 obj_type as i32, obj_id,
694 result.as_mut_ptr(), flg_local as i32
695 ) };
696 result
697 }
698
699 pub fn geom_distance(&self, geom1_id: i32, geom2_id: i32, dist_max: MjtNum, fromto: Option<&mut [MjtNum; 6]>) -> MjtNum {
701 unsafe { mj_geomDistance(
702 self.model.ffi(), self.ffi(),
703 geom1_id, geom2_id, dist_max,
704 fromto.map_or(ptr::null_mut(), |x| x.as_mut_ptr())
705 ) }
706 }
707
708 pub fn local_to_global(&mut self, pos: &[MjtNum; 3], quat: &[MjtNum; 4], body_id: i32, sameframe: MjtSameFrame) -> ([MjtNum; 3], [MjtNum; 9]) {
712 let mut xpos: [MjtNum; 3] = [0.0; 3];
714 let mut xmat: [MjtNum; 9] = [0.0; 9];
715 unsafe { mj_local2Global(self.ffi_mut(), xpos.as_mut_ptr(), xmat.as_mut_ptr(), pos.as_ptr(), quat.as_ptr(), body_id, sameframe as MjtByte) };
716 (xpos, xmat)
717 }
718
719 pub fn multi_ray(
723 &mut self, pnt: &[MjtNum; 3], vec: &[[MjtNum; 3]], geomgroup: Option<&[MjtByte; mjNGROUP as usize]>,
724 flg_static: bool, bodyexclude: i32, cutoff: MjtNum
725 ) -> (Vec<i32>, Vec<MjtNum>) {
726 let nray = vec.len();
727 let mut geom_id = vec![0; nray];
728 let mut distance = vec![0.0; nray];
729
730 unsafe { mj_multiRay(
731 self.model.ffi(), self.ffi_mut(), pnt.as_ptr(),
732 vec.as_ptr() as *const MjtNum, geomgroup.map_or(ptr::null(), |x| x.as_ptr()),
733 flg_static as u8, bodyexclude, geom_id.as_mut_ptr(),
734 distance.as_mut_ptr(), nray as i32, cutoff
735 ) };
736
737 (geom_id, distance)
738 }
739
740 pub fn ray(
744 &self, pnt: &[MjtNum; 3], vec: &[MjtNum; 3],
745 geomgroup: Option<&[MjtByte; mjNGROUP as usize]>, flg_static: bool, bodyexclude: i32
746 ) -> (i32, MjtNum) {
747 let mut geom_id = -1;
748 let dist = unsafe { mj_ray(
749 self.model.ffi(), self.ffi(),
750 pnt.as_ptr(), vec.as_ptr(),
751 geomgroup.map_or(ptr::null(), |x| x.as_ptr()),
752 flg_static as MjtByte, bodyexclude, &mut geom_id
753 ) };
754 (geom_id, dist)
755 }
756
757 pub(crate) unsafe fn __raw(&self) -> *mut mjData {
762 self.data
763 }
764
765}
766
767
768impl MjData<'_> {
770 pub fn maxuse_stack(&self) -> MjtSize {
772 self.ffi().maxuse_stack
773 }
774
775 pub fn maxuse_threadstack(&self) -> &[MjtSize] {
777 &self.ffi().maxuse_threadstack
778 }
779
780 pub fn warning_stats(&self) -> &[MjWarningStat] {
782 &self.ffi().warning
783 }
784
785 pub fn timer_stats(&self) -> &[MjTimerStat] {
787 &self.ffi().timer
788 }
789
790 pub fn time(&self) -> MjtNum {
792 self.ffi().time
793 }
794
795 pub fn energy(&self) -> &[MjtNum] {
797 &self.ffi().energy
798 }
799}
800
801impl Drop for MjData<'_> {
802 fn drop(&mut self) {
803 unsafe {
804 mj_deleteData(self.data);
805 }
806 }
807}
808
809
810info_with_view!(
814 Data,
815 joint,
816 [
817 qpos: MjtNum, qvel: MjtNum, qacc_warmstart: MjtNum, qfrc_applied: MjtNum, qacc: MjtNum, xanchor: MjtNum, xaxis: MjtNum, qLDiagInv: MjtNum,
818 qfrc_bias: MjtNum, qfrc_spring: MjtNum, qfrc_damper: MjtNum, qfrc_gravcomp: MjtNum, qfrc_fluid: MjtNum, qfrc_passive: MjtNum,
819 qfrc_actuator: MjtNum, qfrc_smooth: MjtNum, qacc_smooth: MjtNum, qfrc_constraint: MjtNum, qfrc_inverse: MjtNum
820 ],
821 []
822);
823
824#[deprecated]
826pub type MjJointInfo = MjJointDataInfo;
827
828
829impl MjJointDataViewMut<'_> {
831 #[deprecated]
833 pub fn reset(&mut self) {
834 self.zero();
835 }
836}
837
838#[deprecated]
840pub type MjJointView<'d> = MjJointDataView<'d>;
841
842#[deprecated]
844pub type MjJointViewMut<'d> = MjJointDataViewMut<'d>;
845
846info_with_view!(Data, sensor, sensor, [data: MjtNum], []);
850
851info_with_view!(Data, geom, geom_, [xpos: MjtNum, xmat: MjtNum], []);
855
856#[deprecated]
858pub type MjGeomInfo = MjGeomDataInfo;
859
860#[deprecated]
862pub type MjGeomView<'d> = MjGeomDataView<'d>;
863
864#[deprecated]
866pub type MjGeomViewMut<'d> = MjGeomDataViewMut<'d>;
867
868info_with_view!(Data, actuator, [ctrl: MjtNum], [act: MjtNum]);
872
873#[deprecated]
875pub type MjActuatorInfo = MjActuatorDataInfo;
876
877#[deprecated]
879pub type MjActuatorView<'d> = MjActuatorDataView<'d>;
880
881#[deprecated]
883pub type MjActuatorViewMut<'d> = MjActuatorDataViewMut<'d>;
884
885info_with_view!(
889 Data, body, [
890 xfrc_applied: MjtNum, xpos: MjtNum, xquat: MjtNum, xmat: MjtNum, xipos: MjtNum, ximat: MjtNum,
891 subtree_com: MjtNum, cinert: MjtNum, crb: MjtNum, cvel: MjtNum, subtree_linvel: MjtNum,
892 subtree_angmom: MjtNum, cacc: MjtNum, cfrc_int: MjtNum, cfrc_ext: MjtNum
893 ], []
894);
895
896info_with_view!(Data, camera, cam_, [xpos: MjtNum, xmat: MjtNum], []);
900
901info_with_view!(Data, site, site_, [xpos: MjtNum, xmat: MjtNum], []);
905
906info_with_view!(Data, tendon, ten_, [wrapadr: i32, wrapnum: i32, J_rownnz: i32, J_rowadr: i32, J_colind: i32, length: MjtNum, J: MjtNum, velocity: MjtNum], []);
910
911info_with_view!(Data, light, light_, [xpos: MjtNum, xdir: MjtNum], []);
915
916#[cfg(test)]
921mod test {
922 use crate::assert_relative_eq;
923 use crate::prelude::*;
924 use super::*;
925
926 const MODEL: &str = "
927<mujoco>
928 <worldbody>
929 <light ambient=\"0.2 0.2 0.2\"/>
930 <body name=\"ball\" pos=\".2 .2 .1\">
931 <geom name=\"green_sphere\" size=\".1\" rgba=\"0 1 0 1\" solref=\"0.004 1.0\"/>
932 <joint name=\"ball\" type=\"free\"/>
933 </body>
934
935 <body name=\"ball2\" pos=\".7 .2 .1\">
936 <geom name=\"green_sphere2\" size=\".1\" rgba=\"0 1 0 1\" solref=\"0.004 1.0\"/>
937 <joint name=\"ball2\" type=\"free\"/>
938 </body>
939
940 <geom name=\"floor1\" type=\"plane\" size=\"10 10 1\" solref=\"0.004 1.0\"/>
941 </worldbody>
942</mujoco>";
943
944
945 #[test]
946 fn test_joint_view() {
947 let model = MjModel::from_xml_string(MODEL).unwrap();
948 let mut data = model.make_data();
949 let joint_info = data.joint("ball").unwrap();
950 let body_info = data.body("ball").unwrap();
951
952 for _ in 0..10 {
953 data.step();
954 }
955
956 let mut joint_view = joint_info.view(&data);
958 assert_relative_eq!(joint_view.qvel[0], 0.0, epsilon=1e-9); assert_relative_eq!(joint_view.qvel[1], 0.0, epsilon=1e-9); assert_relative_eq!(joint_view.qvel[3], 0.0, epsilon=1e-9); assert_relative_eq!(joint_view.qvel[4], 0.0, epsilon=1e-9); assert_relative_eq!(joint_view.qvel[5], 0.0, epsilon=1e-9); let mut joint_view_mut = joint_info.view_mut(&mut data);
967 joint_view_mut.qvel[0] = 0.5; joint_view_mut.qvel[4] = 0.5 / 0.1; let initial_qpos: [MjtNum; 3] = joint_view_mut.qpos[..3].try_into().unwrap(); data.step();
972
973 joint_view = joint_info.view(&data);
975 assert_relative_eq!(joint_view.qvel[0], 0.5, epsilon=1e-3); assert_relative_eq!(joint_view.qvel[4], 0.5 / 0.1, epsilon=1e-3); let timestep = model.opt().timestep;
980 assert_relative_eq!(joint_view.qpos[0], initial_qpos[0] + timestep * joint_view.qvel[0], epsilon=1e-9); assert_relative_eq!(joint_view.qpos[1], initial_qpos[1] + timestep * joint_view.qvel[1], epsilon=1e-9);
982 assert_relative_eq!(joint_view.qpos[2], initial_qpos[2] + timestep * joint_view.qvel[2], epsilon=1e-9);
983
984 data.step1(); joint_view = joint_info.view(&data);
989 let body_view = body_info.view(&data);
990 assert_relative_eq!(joint_view.qpos[0], body_view.xpos[0], epsilon=1e-9); assert_relative_eq!(joint_view.qpos[1], body_view.xpos[1], epsilon=1e-9);
993 assert_relative_eq!(joint_view.qpos[2], body_view.xpos[2], epsilon=1e-9);
994
995 assert_relative_eq!(joint_view.qpos[3], body_view.xquat[0], epsilon=1e-9); assert_relative_eq!(joint_view.qpos[4], body_view.xquat[1], epsilon=1e-9);
997 assert_relative_eq!(joint_view.qpos[5], body_view.xquat[2], epsilon=1e-9);
998 assert_relative_eq!(joint_view.qpos[6], body_view.xquat[3], epsilon=1e-9);
999
1000 assert_relative_eq!(joint_view.qvel[0], body_view.cvel[3], epsilon=1e-9); assert_relative_eq!(joint_view.qvel[1], body_view.cvel[4], epsilon=1e-9);
1003 assert_relative_eq!(joint_view.qvel[2], body_view.cvel[5], epsilon=1e-9);
1004
1005 assert_relative_eq!(joint_view.qvel[3], body_view.cvel[0], epsilon=1e-9); assert_relative_eq!(joint_view.qvel[4], body_view.cvel[1], epsilon=1e-9);
1007 assert_relative_eq!(joint_view.qvel[5], body_view.cvel[2], epsilon=1e-9);
1008 }
1009
1010 #[test]
1011 fn test_body_view() {
1012 let model = MjModel::from_xml_string(MODEL).unwrap();
1013 let mut data = model.make_data();
1014 let body_info = data.body("ball2").unwrap();
1015 let mut cvel;
1016
1017 data.step1();
1018
1019 for _ in 0..10 {
1020 data.step2();
1021 data.step1(); }
1023
1024 cvel = body_info.view(&data).cvel;
1026 assert_relative_eq!(cvel[0], 0.0, epsilon=1e-9);
1027 assert_relative_eq!(cvel[1], 0.0, epsilon=1e-9);
1028 assert_relative_eq!(cvel[2], 0.0, epsilon=1e-9);
1029 assert_relative_eq!(cvel[3], 0.0, epsilon=1e-9);
1030 assert_relative_eq!(cvel[4], 0.0, epsilon=1e-9);
1031 body_info.view_mut(&mut data).xfrc_applied[0] = 5.0;
1035 data.step2();
1036 data.step1();
1037
1038 let view = body_info.view(&data);
1039 cvel = view.cvel;
1040 println!("{:?}", cvel);
1041 assert_relative_eq!(cvel[0], 0.0, epsilon=1e-9);
1042 assert!(cvel[1] > 0.0); assert_relative_eq!(cvel[2], 0.0, epsilon=1e-9);
1044 assert!(cvel[3] > 0.0); assert_relative_eq!(cvel[4], 0.0, epsilon=1e-9); assert_relative_eq!(view.xfrc_applied[0], 5.0, epsilon=1e-9); data.step2();
1051 data.step1();
1052 }
1053
1054 #[test]
1055 fn test_copy_reset_variants() {
1056 let model = MjModel::from_xml_string(MODEL).unwrap();
1057 let mut data = model.make_data();
1058
1059 data.reset();
1061 data.reset_debug(7);
1062 data.reset_keyframe(0);
1063 }
1064
1065 #[test]
1066 fn test_dynamics_and_sensors() {
1067 let model = MjModel::from_xml_string(MODEL).unwrap();
1068 let mut data = model.make_data();
1069
1070 data.fwd_position();
1072 data.fwd_velocity();
1073 data.fwd_actuation();
1074 data.fwd_acceleration();
1075 data.fwd_constraint();
1076
1077 data.euler();
1078 data.runge_kutta(4);
1079 data.inv_position();
1082 data.inv_velocity();
1083 data.inv_constraint();
1084 data.compare_fwd_inv();
1085
1086 data.sensor_pos();
1088 data.sensor_vel();
1089 data.sensor_acc();
1090
1091 data.energy_pos();
1092 data.energy_vel();
1093
1094 data.check_pos();
1095 data.check_vel();
1096 data.check_acc();
1097
1098 data.kinematics();
1099 data.com_pos();
1100 data.camlight();
1101 data.flex_comp();
1102 data.tendon_comp();
1103 data.transmission();
1104 data.crb();
1105 data.make_m();
1106 data.factor_m();
1107 data.com_vel();
1108 data.passive();
1109 data.subtree_vel();
1110 }
1111
1112
1113 #[test]
1114 fn test_rne_and_collision_pipeline() {
1115 let model = MjModel::from_xml_string(MODEL).unwrap();
1116 let mut data = model.make_data();
1117 data.step();
1118
1119 data.rne(true);
1121
1122 data.rne_post_constraint();
1123
1124 data.collision();
1126 data.make_constraint();
1127 data.island();
1128 data.project_constraint();
1129 data.reference_constraint();
1130
1131 let jar = vec![0.0; (data.model.ffi().nv) as usize];
1132 let mut cost = 0.0;
1133 data.constraint_update(&jar, None, false);
1134 data.constraint_update(&jar, Some(&mut cost), true);
1135 }
1136
1137 #[test]
1138 fn test_add_contact() {
1139 let model = MjModel::from_xml_string(MODEL).unwrap();
1140 let mut data = model.make_data();
1141
1142 let dummy_contact = unsafe { std::mem::zeroed() };
1144 data.add_contact(&dummy_contact).unwrap();
1145 }
1146
1147 #[test]
1148 fn test_jacobian() {
1149 let model = MjModel::from_xml_string(MODEL).unwrap();
1150 let mut data = model.make_data();
1151
1152 let nv = data.model.ffi().nv as usize;
1153 let expected_len = 3 * nv;
1154
1155 let point = [0.1, 0.0, 0.0];
1157
1158 let ball_body_id = model.body("ball").unwrap().id as i32;
1159
1160 let (jacp, jacr) = data.jac(true, true, &point, ball_body_id);
1162 assert_eq!(jacp.len(), expected_len);
1163 assert_eq!(jacr.len(), expected_len);
1164
1165 let (jacp_body, jacr_body) = data.jac_body(true, true, ball_body_id);
1167 assert_eq!(jacp_body.len(), expected_len);
1168 assert_eq!(jacr_body.len(), expected_len);
1169
1170 let (jacp_com, jacr_com) = data.jac_body_com(true, true, ball_body_id);
1172 assert_eq!(jacp_com.len(), expected_len);
1173 assert_eq!(jacr_com.len(), expected_len);
1174
1175 let jac_subtree = data.jac_subtree_com(true, 0);
1177 assert_eq!(jac_subtree.len(), expected_len);
1178
1179 let (jacp_geom, jacr_geom) = data.jac_geom(true, true, ball_body_id);
1181 assert_eq!(jacp_geom.len(), expected_len);
1182 assert_eq!(jacr_geom.len(), expected_len);
1183
1184 let (jacp_site, jacr_site) = data.jac_site(true, true, ball_body_id);
1186 assert_eq!(jacp_site.len(), expected_len);
1187 assert_eq!(jacr_site.len(), expected_len);
1188
1189 let (jacp_none, jacr_none) = data.jac(false, false, &[0.0; 3], ball_body_id);
1191 assert!(jacp_none.is_empty());
1192 assert!(jacr_none.is_empty());
1193 }
1194
1195 #[test]
1196 fn test_angmom_and_object_dynamics() {
1197 let model = MjModel::from_xml_string(MODEL).unwrap();
1198 let mut data = model.make_data();
1199
1200 let mat = data.angmom_mat(0);
1201 assert_eq!(mat.len(), (3 * data.model.ffi().nv as usize));
1202
1203 let vel = data.object_velocity(MjtObj::mjOBJ_BODY, 0, true);
1204 assert_eq!(vel, vel); let acc = data.object_acceleration(MjtObj::mjOBJ_BODY, 0, false);
1207 assert_eq!(acc, acc);
1208 }
1209
1210 #[test]
1211 fn test_geom_distance_and_transforms() {
1212 let model = MjModel::from_xml_string(MODEL).unwrap();
1213 let mut data = model.make_data();
1214 data.step();
1215
1216 let mut ft = [0.0; 6];
1217 let dist = data.geom_distance(0, 0, 1.0, Some(&mut ft));
1218 assert_eq!(ft, [0.0; 6]);
1219 assert_eq!(dist, 1.0);
1220
1221 let pos = [0.0; 3];
1222 let quat = [1.0, 0.0, 0.0, 0.0];
1223 let (xpos, xmat) = data.local_to_global(&pos, &quat, 0, MjtSameFrame::mjSAMEFRAME_NONE);
1224 assert_eq!(xpos.len(), 3);
1225 assert_eq!(xmat.len(), 9);
1226
1227 let ray_vecs = [[1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 0.0, 0.0]];
1228 let rays = data.multi_ray(&pos, &ray_vecs, None, false, -1, 10.0);
1229 assert_eq!(rays.0.len(), 3);
1230 assert_eq!(rays.1.len(), 3);
1231
1232 let (geomid, dist) = data.ray(&pos, &[1.0, 0.0, 0.0], None, true, -1);
1233 assert!(dist.is_finite());
1234 assert!(geomid >= -1);
1235 }
1236}